Repository: petercorke/bdsim
Branch: master
Commit: 9603af34d51d
Files: 191
Total size: 5.2 MB
Directory structure:
gitextract_lbrlybs_/
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── 0bdsim-bug-report.md
│ │ └── 1bdedit-bug-report.md
│ └── workflows/
│ ├── master.yml
│ └── publish.yml
├── .gitignore
├── CONTRIBUTING.md
├── Icons.qrc
├── LICENSE
├── Makefile
├── README.md
├── bdsim/
│ ├── __init__.py
│ ├── bdedit/
│ │ ├── Icons.py
│ │ ├── Icons.qrc
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── TechReport.md
│ │ ├── __init__.py
│ │ ├── bdedit.py
│ │ ├── block.py
│ │ ├── block_connector_block.py
│ │ ├── block_graphics_block.py
│ │ ├── block_graphics_socket.py
│ │ ├── block_graphics_wire.py
│ │ ├── block_importer.py
│ │ ├── block_main_block.py
│ │ ├── block_param_window.py
│ │ ├── block_socket.py
│ │ ├── block_wire.py
│ │ ├── docs/
│ │ │ ├── .buildinfo
│ │ │ ├── _sources/
│ │ │ │ ├── bdedit.rst.txt
│ │ │ │ ├── index.rst.txt
│ │ │ │ └── modules.rst.txt
│ │ │ ├── _static/
│ │ │ │ ├── alabaster.css
│ │ │ │ ├── basic.css
│ │ │ │ ├── css/
│ │ │ │ │ ├── badge_only.css
│ │ │ │ │ └── theme.css
│ │ │ │ ├── custom.css
│ │ │ │ ├── doctools.js
│ │ │ │ ├── documentation_options.js
│ │ │ │ ├── jquery-3.5.1.js
│ │ │ │ ├── jquery.js
│ │ │ │ ├── js/
│ │ │ │ │ ├── badge_only.js
│ │ │ │ │ └── theme.js
│ │ │ │ ├── language_data.js
│ │ │ │ ├── pygments.css
│ │ │ │ ├── searchtools.js
│ │ │ │ ├── underscore-1.13.1.js
│ │ │ │ └── underscore.js
│ │ │ ├── bdedit.html
│ │ │ ├── genindex.html
│ │ │ ├── index.html
│ │ │ ├── modules.html
│ │ │ ├── objects.inv
│ │ │ ├── py-modindex.html
│ │ │ ├── search.html
│ │ │ └── searchindex.js
│ │ ├── docstring.md
│ │ ├── floating_label.py
│ │ ├── floating_label_graphics.py
│ │ ├── grouping_box.py
│ │ ├── grouping_box_graphics.py
│ │ ├── interface.py
│ │ ├── interface_graphics_scene.py
│ │ ├── interface_graphics_view.py
│ │ ├── interface_manager.py
│ │ ├── interface_scene.py
│ │ ├── interface_scene_history.py
│ │ └── interface_serialize.py
│ ├── bdrun.py
│ ├── bin/
│ │ └── stubgen.py
│ ├── blockdiagram.py
│ ├── blockdiagram.pyi
│ ├── blocks/
│ │ ├── IO/
│ │ │ ├── Firmata.py
│ │ │ └── README.md
│ │ ├── Icons/
│ │ │ ├── README.md
│ │ │ └── icons.sh
│ │ ├── README.md
│ │ ├── __init__.py
│ │ ├── connections.py
│ │ ├── discrete.py
│ │ ├── displays.py
│ │ ├── functions.py
│ │ ├── linalg.py
│ │ ├── sinks.py
│ │ ├── sources.py
│ │ ├── spatial.py
│ │ ├── transfers.py
│ │ └── vision.py
│ ├── components.py
│ ├── graphics.py
│ ├── run_realtime.py
│ ├── run_sim.py
│ └── tk_editor/
│ ├── bdeditor.py
│ ├── edit.py
│ ├── editor.py
│ └── editor2.py
├── docs/
│ ├── Makefile
│ ├── make.bat
│ └── source/
│ ├── bdsim.blocks.rst
│ ├── bdsim.rst
│ ├── conf.py
│ ├── exts/
│ │ └── blockname.py
│ ├── index.rst
│ ├── internals.rst
│ └── modules.rst
├── docs-aside/
│ ├── .buildinfo
│ ├── .nojekyll
│ ├── _modules/
│ │ ├── bdsim/
│ │ │ ├── bdsim.html
│ │ │ ├── blockdiagram.html
│ │ │ ├── blocks/
│ │ │ │ ├── connections.html
│ │ │ │ ├── discrete.html
│ │ │ │ ├── functions.html
│ │ │ │ ├── linalg.html
│ │ │ │ ├── robots.html
│ │ │ │ ├── sinks.html
│ │ │ │ ├── sources.html
│ │ │ │ └── transfers.html
│ │ │ ├── components.html
│ │ │ └── graphics.html
│ │ ├── index.html
│ │ └── roboticstoolbox/
│ │ └── blocks/
│ │ ├── arm.html
│ │ ├── mobile.html
│ │ └── uav.html
│ ├── _sources/
│ │ ├── bdsim.blocks.rst.txt
│ │ ├── bdsim.rst.txt
│ │ ├── index.rst.txt
│ │ ├── internals.rst.txt
│ │ └── modules.rst.txt
│ ├── _static/
│ │ ├── alabaster.css
│ │ ├── basic.css
│ │ ├── css/
│ │ │ ├── badge_only.css
│ │ │ └── theme.css
│ │ ├── custom.css
│ │ ├── doctools.js
│ │ ├── documentation_options.js
│ │ ├── fonts/
│ │ │ └── FontAwesome.otf
│ │ ├── graphviz.css
│ │ ├── jquery-3.4.1.js
│ │ ├── jquery-3.5.1.js
│ │ ├── jquery.js
│ │ ├── js/
│ │ │ ├── badge_only.js
│ │ │ └── theme.js
│ │ ├── language_data.js
│ │ ├── pygments.css
│ │ ├── searchtools.js
│ │ ├── underscore-1.3.1.js
│ │ └── underscore.js
│ ├── bdsim.blocks.html
│ ├── bdsim.html
│ ├── genindex.html
│ ├── index.html
│ ├── internals.html
│ ├── modules.html
│ ├── objects.inv
│ ├── py-modindex.html
│ ├── search.html
│ └── searchindex.js
├── examples/
│ ├── README.md
│ ├── RVC2/
│ │ ├── README.md
│ │ ├── rvc4_11.py
│ │ ├── rvc4_2.py
│ │ ├── rvc4_4.py
│ │ ├── rvc4_6.py
│ │ └── rvc4_8.py
│ ├── deriv.py
│ ├── eg1.bd
│ ├── eg1.py
│ ├── eg1_zoh.py
│ ├── pid.py
│ ├── rt_step.py
│ ├── sine+sampler.py
│ ├── sine+sampler2.py
│ ├── subsys.py
│ ├── vanderpol.py
│ ├── viewsim.py
│ └── waveform.py
├── figs/
│ ├── data_structures.ezdraw
│ └── plugs_and_wires.ezdraw
├── pyproject.toml
└── tests/
├── __init__.py
├── test_bdsim.py
├── test_blockdiagram.py
├── test_components.py
├── test_connections.py
├── test_discrete.py
├── test_functions.py
├── test_linalg.py
├── test_sinks.py
├── test_sources.py
├── test_spatial.py
└── test_transfers.py
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/ISSUE_TEMPLATE/0bdsim-bug-report.md
================================================
---
name: bdsim bug report
about: Create a report to help us improve bdsim, the Python based block diagram simulator
title: "[bdsim BUG]"
labels: ''
assignees: ''
---
For bugs with the graphical tool `bdedit` please use the `bdedit` bug report template.
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Please provide a complete minimal stand-alone Python example.
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, for instance a problem with a SCOPE block, please add screenshots to help explain your problem.
**Operating environment (please complete the following information):**
- OS: [e.g. MacOS]
- Version [e.g. Ventura]
**Additional context**
Add any other context about the problem here.
================================================
FILE: .github/ISSUE_TEMPLATE/1bdedit-bug-report.md
================================================
---
name: bdedit bug report
about: Create a report to help us improve bdedit, the graphical editor for block diagrams.
title: "[bdedit BUG]"
labels: ''
assignees: petercorke
---
**`bdedit` is an experimental editor for block diagrams that can be used in conjunction with `bdsim`. It is not a drop-in replacement for Simulink, if you want something reliable and supported buy it from The MathWorks.**
**Before you post a bug please check that PyQt5 is properly installed on your computer, see the notes on the [wiki](https://github.com/petercorke/bdsim/wiki/Getting-going-with-PyQt5). If you cannot run the PyQt5 test example then you need to resolve that yourself, please don't post it here.**
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Operating environment (please complete the following information):**
- OS: [e.g. MacOS]
- Version [e.g. Ventura]
**Your version of PyQT
- please include the output of running `pip list | grep -I qt`
**Additional context**
Add any other context about the problem here.
================================================
FILE: .github/workflows/master.yml
================================================
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
name: build
on:
push:
branches: [ master, future ]
# pull_request:
# branches: [ master ]
jobs:
# Run tests on different versions of python
unittest:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [windows-latest, ubuntu-latest, macos-13]
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install .[dev]
- name: Test with pytest
env:
MPLBACKEND: TkAgg
run: |
pytest --capture=no --ignore=W605 --timeout=50 --timeout_method=thread
codecov:
# If all tests pass:
# Run coverage and upload to codecov
needs: unittest
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
- name: Run coverage
run: |
pip install .[dev]
coverage run --omit='tests/*.py' -m pytest
coverage report
coverage xml
- name: upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
file: ./coverage.xml
sphinx:
# If the above worked:
# Build docs and upload to GH Pages
needs: unittest
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install .[dev,docs]
pip install git+https://github.com/petercorke/sphinx-autorun.git
pip install sympy
sudo apt-get install graphviz
- name: Build docs
run: |
cd docs
make html
# Tell GitHub not to use jekyll to compile the docs
touch build/html/.nojekyll
cd ../
- name: Commit documentation changes
run: |
git clone https://github.com/petercorke/bdsim.git --branch gh-pages --single-branch gh-pages
cp -r docs/build/html/* gh-pages/
cd gh-pages
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git add .
git commit -m "Update documentation" -a || true
# The above command will fail if no changes were present, so we ignore
# that.
- name: Push changes
uses: ad-m/github-push-action@master
with:
branch: gh-pages
directory: gh-pages
github_token: ${{ secrets.GITHUB_TOKEN }}
================================================
FILE: .github/workflows/publish.yml
================================================
# This workflows will upload a Python Package using Twine when a release is created
# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries
# name: Upload Python Package
on:
release:
types: [created]
workflow_dispatch:
jobs:
deploy:
runs-on: ${{ matrix.os }}
strategy:
max-parallel: 2
matrix:
os: [ubuntu-latest]
python-version: ['3.10']
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -U setuptools wheel twine
- name: Build and publish
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD_BDSIM }}
run: |
python setup.py sdist bdist_wheel
ls ./dist/*.whl
twine upload dist/*.gz
twine upload dist/*.whl
================================================
FILE: .gitignore
================================================
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
untitled*.py
# docs
*.pdf
*.dot
# MATLAB
*.m
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
*.json
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
.python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
.idea/
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing
This is a small-scale private project with a team size of about 0.01. I'd be delighted if you'd like to use and apply the tool, or even to contribute.
## Communicating
GitHub Issues is a convenient means to discuss bugs or possible contributions.
## Bug notifications
If you're using bdsim and encounter errors with the latest version from GitHub then please report it through GitHib Issues. Be sure to include:
* a description of what the issue is, and the stack trace you get
* the version of Python and numpy that you are using
* a runnable code example that demonstrates the issue
## Specific contributions needed
* The numerical integrator from SciPy has some limitations. It cannot handle:
* hybrid continuous-discrete systems,
* events associated with strong non-linearities or discontinuous inputs,
* allow the state vector to be updated (ie. as would be required to renormalize a unit-quaternion state).
* Extend to support bond graphs, or a hybrid of bond graphs and block diagrams.
* There are many more blocks that could be created but of immediate interest are:
* real-time blocks that interface to ADCs, DACs and PWM channels for use on a RaspberryPi
* vision blocks that interface to cameras, displays and OpenCV operators
## Other contributions
These are welcome but it'd be great to discuss through GitHub Issues before you start. You will be acknowledged as the author, but by contributing you are agreeing to your work being shared under the MIT Licence. Contributions should have unit tests and good quality documentation.
## Feature requests
These are unlikely to be implemented by me, it's a time thing...
## Any contributions you make will be under the MIT Software License
In short, when you submit code changes, your submissions are understood to be under the same [MIT License](http://choosealicense.com/licenses/mit/) that covers the project.
## Code of conduct
So far there isn't one, but if there were it would embed principles from the [Contributor Covenant Code Of Conduct](https://www.contributor-covenant.org/version/1/4/code-of-conduct).
================================================
FILE: Icons.qrc
================================================
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2020 Peter Corke
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: Makefile
================================================
.FORCE:
BLUE=\033[0;34m
BLACK=\033[0;30m
help:
@echo "$(BLUE) make test - run all unit tests"
@echo " make coverage - run unit tests and coverage report"
@echo " make docs - build Sphinx documentation"
@echo " make docupdate - upload Sphinx documentation to GitHub pages"
@echo " make dist - build dist files"
@echo " make upload - upload to PyPI"
@echo " make clean - remove dist and docs build files"
@echo " make help - this message$(BLACK)"
test:
pytest
coverage:
coverage run --source='bdsim' -m pytest
coverage report
coverage html
open htmlcov/index.html
docs: .FORCE
(cd docs; make html)
view:
open docs/build/html/index.html
dist: .FORCE
#$(MAKE) test
python -m build
upload: .FORCE
twine upload dist/*
install:
pip install -e .
clean: .FORCE
# (cd docsrc; make clean)
-rm -r *.egg-info
-rm -r dist build
================================================
FILE: README.md
================================================
[](https://github.com/petercorke/robotics-toolbox-python)
[](https://qcr.github.io)
[](https://badge.fury.io/py/bdsim)

[](https://opensource.org/licenses/MIT)
[](https://github.com/petercorke/bdsim/actions?query=workflow%3Abuild)
[](https://codecov.io/gh/petercorke/bdsim)
[](https://pypistats.org/packages/bdsim)
[](https://GitHub.com/petercorke/bdsim/stargazers/)
Dependencies: numpy, scipy, matplotlib, ansitable, ffmpeg (if rendering animations as a movie)
`bdsim` is Python 3 package that enables modelling and simulation of continuous-time, discrete-time or hybrid dynamic systems. Systems are conceptualized in block diagram form, but represented in terms of Python objects.
# define the blocks
demand = bd.STEP(T=1, name='demand')
sum = bd.SUM('+-')
gain = bd.GAIN(10)
plant = bd.LTI_SISO(0.5, [2, 1])
scope = bd.SCOPE(styles=['k', 'r--'])
# connect the blocks
bd.connect(demand, sum[0], scope[1])
bd.connect(plant, sum[1])
bd.connect(sum, gain)
bd.connect(gain, plant)
bd.connect(plant, scope[0])
Key features include:
* The block diagram can be created easily using Python code, rather than drawing boxes and wires. This enables use of your favourite IDE, standard version control tools and development workflows.
* Wires can communicate *any* Python type such as scalars, lists, dicts, NumPy arrays, objects, and functions. For robotics and vision applications using the [Spatial Maths Toolbox for Python](https://github.com/petercorke/spatialmath-python) wires could send values such as `SE3`, `UnitQuaternion` or `Twist3` objects.
* Over 70 blocks for linear, nonlinear functions, display blocks, as well as continuous- and discrete-time dynamics
* Easy to add your own block, it's simply a class
* Subsystems are supported, and a subsystem can be independently instantiated multiple times in a system. Subsystems can also be nested.
* Blocks from other toolboxes are automatically discovered and included. There are blocks for some functions in the [Robotics Toolbox for Python](https://github.com/petercorke/robotics-toolbox-python) (such as arm, ground and aerial robots) and [Machine Vision Toolbox for Python](https://github.com/petercorke/machinevision-toolbox-python) (such as cameras). These are defined in the `blocks` folder of those toolboxes.
* The diagram can be executed in a headless configuration, particularly useful on an embedded computer like a RaspberryPi.
* A [python-based graphical editor](bdedit-the-graphical-editing-tool)
* allows graphical creation of block diagrams
* the diagram is stored in a human readable/editable JSON file with extension `.bd`
* creates good-quality graphics for inclusion in publications
* can launch `bdsim` to import and execute the model
* automatically discovers all bsdim and toolbbox blocks and adds them to the block library menu
* icons can be easily created using any image creation tool or a LaTeX expression
# Getting started
We first sketch the dynamic system we want to simulate as a block diagram, for example this simple first-order system

which we can express concisely with `bdsim` as (see [`bdsim/examples/eg1.py`](https://github.com/petercorke/bdsim/blob/master/examples/eg1.py))
```python
1 #!/usr/bin/env python3
2 import bdsim
4 sim = bdsim.BDSim() # create simulator
5 bd = sim.blockdiagram() # create an empty block diagram
6
7 # define the blocks
8 demand = bd.STEP(T=1, name='demand')
9 sum = bd.SUM('+-')
10 gain = bd.GAIN(10)
11 plant = bd.LTI_SISO(0.5, [2, 1], name='plant')
12 scope = bd.SCOPE(styles=['k', 'r--'])
13
14 # connect the blocks
15 bd.connect(demand, sum[0], scope[1])
17 bd.connect(sum, gain)
18 bd.connect(gain, plant)
19 bd.connect(plant, sum[1], scope[0])
20
21 bd.compile() # check the diagram
22
23 sim.report(bd) # list the system
24 out = sim.run(bd, 5) # simulate for 5s
```
which is just 15 lines of executable code.
The red block annotations on the hand-drawn diagram are used as the names of the variables holding references to the block instance. The blocks can also have user-assigned names, see lines 8 and 11, which are used in diagnostics and as labels in plots.
After the blocks are created their input and output ports need to be connected. In `bdsim` all wires are point to point, a *one-to-many* connection is implemented by *many* wires,
for example
```
bd.connect(source, dest1, dest2, ...)
```
creates individual wires from `source` -> `dest1`, `source` -> `dest2` and so on.
Ports are designated using Python indexing notation, for example `block[2]` is port 2 (the third port) of `block`. Whether it is an input or output port depends on context.
In the example above an index on the first argument refers to an output port, while on the second (or subsequent) arguments it refers to an input port. If a block has only a single input or output port then no index is required, 0 is assumed.
A group of ports can be denoted using slice notation, for example
```
bd.connect(source[2:5], dest[3:6)
```
will connect `source[2]` -> `dest[3]`, `source[3]` -> `dest[4]`, `source[4]` -> `dest[5]`.
The number of wires in each slice must be consistent. You could even do a cross over by connecting `source[2:5]` to `dest[6:3:-1]`.
Line 21 assembles all the blocks and wires, instantiates subsystems, checks connectivity to create a flat wire list, and then builds the dataflow execution plan.
Line 23 generates a report, in tabular form, showing a summary of the block diagram:
```
┌────────┬──────────┬────────┬────────┬─────────────┐
│ block │ type │ inport │ source │ source type │
├────────┼──────────┼────────┼────────┼─────────────┤
│demand@ │ step │ │ │ │
├────────┼──────────┼────────┼────────┼─────────────┤
│gain.0 │ gain │ 0 │ sum.0 │ float64 │
├────────┼──────────┼────────┼────────┼─────────────┤
│plant │ lti_siso │ 0 │ gain.0 │ float64 │
├────────┼──────────┼────────┼────────┼─────────────┤
│scope.0 │ scope │ 0 │ plant │ float64 │
│ │ │ 1 │ demand │ int │
├────────┼──────────┼────────┼────────┼─────────────┤
│sum.0 │ sum │ 0 │ demand │ int │
│ │ │ 1 │ plant │ float64 │
└────────┴──────────┴────────┴────────┴─────────────┘
```
Line 24 runs the simulation for 5 seconds
using the default variable-step RK45 solver and saves output values at least every 0.05s. It
causes the following output
```
>>> Start simulation: T = 5.00, dt = 0.050
Continuous state variables: 1
x0 = [0.]
Discrete state variables: 0
no graphics backend specified: Qt5Agg found, using instead of MacOSX
bdsim ◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉ 100.0% - 0s
<<< Simulation complete
block diagram evaluations: 784
block diagram exec time: 0.075 ms
time steps: 123
integration intervals: 2
```
This provides a summary of the number of states for the complete system: the number of continuous states, the number
of discrete states, and the initial value of the state vectors.
During execution a progress bar is updated and scope blocks pops up a graphical window

The simulation results are in a container object (`BDStruct`)
```
>>> out
t = ndarray:float64 (123,)
x = ndarray:float64 (123, 1)
xnames = ['plantx0'] (list)
ynames = [] (list)
```
which contains an array of time values, an array of state values, and a list of the
names of the state variables.
By default the `.run()` method at line 24 blocks blocks the script until all figure
windows are closed (by pressing the operating system close button or typing "q"), or the
script is killed with SIGINT. If you want to continue the script with the figures still
active then the `hold=False` option should be set.
If we wished to also record additional outputs, we can add them as _watched_ signals
```
out = sim.run(bd, watch=[demand, sum]) # simulate for 5s
```
and now the output is
```
>>> out
t = ndarray:float64 (123,)
x = ndarray:float64 (123, 1)
xnames = ['plantx0'] (list)
y0 = ndarray:float64 (123,)
y1 = ndarray:int64 (123,)
ynames = ['plant[0]', 'demand[0]'] (list)
```
where
- `t` the time vector: ndarray, shape=(M,)
- `x` is the state vector: ndarray, shape=(M,N), one row per timestep
- `xnames` is a list of the names of the states corresponding to columns of `x`, eg. "plant.x0"
The `watch` argument is a list of outputs to log, in this case `plant` defaults
to output port 0. This information is saved in additional variables `y0`, `y1`
etc. `ynames` is a list of the names of the watched variables.
An alternative system report, created by `sim.report(bd, type="lists")` is more detailed
```
Blocks::
┌───┬─────────┬─────┬──────┬────────┬─────────┬───────┐
│id │ name │ nin │ nout │ nstate │ ndstate │ type │
├───┼─────────┼─────┼──────┼────────┼─────────┼───────┤
│ 0 │ demand │ 0 │ 1 │ 0 │ 0 │ step │
│ 1 │ sum.0 │ 2 │ 1 │ 0 │ 0 │ sum │
│ 2 │ gain.0 │ 1 │ 1 │ 0 │ 0 │ gain │
│ 3 │ plant │ 1 │ 1 │ 1 │ 0 │ LTI │
│ 4 │ scope.0 │ 2 │ 0 │ 0 │ 0 │ scope │
└───┴─────────┴─────┴──────┴────────┴─────────┴───────┘
Wires::
┌───┬──────┬──────┬──────────────────────────┬─────────┐
│id │ from │ to │ description │ type │
├───┼──────┼──────┼──────────────────────────┼─────────┤
│ 0 │ 0[0] │ 1[0] │ demand[0] --> sum.0[0] │ int │
│ 1 │ 0[0] │ 4[1] │ demand[0] --> scope.0[1] │ int │
│ 2 │ 3[0] │ 1[1] │ plant[0] --> sum.0[1] │ float64 │
│ 3 │ 1[0] │ 2[0] │ sum.0[0] --> gain.0[0] │ float64 │
│ 4 │ 2[0] │ 3[0] │ gain.0[0] --> plant[0] │ float64 │
│ 5 │ 3[0] │ 4[0] │ plant[0] --> scope.0[0] │ float64 │
└───┴──────┴──────┴──────────────────────────┴─────────┘
```
In the first table we can see key information about each block, its `id` (used internally), name, the number of input and output ports, the number of
continuous- and discrete-time states, and the type which is the block class. Note that the name is auto-generated based on the type, except if it has
been set explicitly as for the blocks `demand` and `plant`.
The second table shows all wires in point-to-point form, showing the start and end block and port (the block is represented here by its `id`) and the type of the object sent along the wire.
To save figures we need to make two modifications, changing line 4 to
```
4 sim = bdsim.BDSim(hold=False) # create simulator
```
which prevents `.run()` from blocking and then deleting all the figures.
Then, after the `.run()` we add
```
25 scope.savefig() # save scope figure
```
If the filename is not given it defaults to the block name, in this case `scope.0.pdf`.
The output can be pickled and written to a file
```[shell]
examples/eg1.py -o
python -mpickle bd.out
t = ndarray:float64 (123,)
x = ndarray:float64 (123, 1)
xnames = ['plantx0'] (list)
y0 = ndarray:float64 (123,)
y1 = ndarray:int64 (123,)
ynames = ['plant[0]', 'demand[0]'] (list)
```
by default the results are written to `bd.out`, use the option `--out FILE` to set it
to a specific value.
The block parameters can also be overridden from the command line without having to
edit the code. To increase the loop gain we could write:
```[shell]
examples/eg1.py --set gain.0:K=20
```
More details on this Wiki about:
- [Adding blocks](https://github.com/petercorke/bdsim/wiki/Adding-blocks)
- [Connecting blocks](https://github.com/petercorke/bdsim/wiki/Connecting-blocks)
- [Running the simulation](https://github.com/petercorke/bdsim/wiki/Running)
- [Command line options](https://github.com/petercorke/bdsim/wiki/Runtime-options)
## Other examples
In the folder `bdsim/examples` you can find a few other runnable examples:
- [`eg1.py`](https://github.com/petercorke/bdsim/blob/master/examples/eg1.py) the example given above
- [`waveform.py`](https://github.com/petercorke/bdsim/blob/master/examples/waveform.py) two signal generators connected to two scopes
Examples from Chapter four of _Robotics, Vision & Control 2e (2017)_:
- [`rvc4_2.py`](https://github.com/petercorke/bdsim/blob/master/examples/rvc4_2.py) Fig 4.2 - a car-like vehicle with bicycle kinematics driven by a rectangular pulse steering signal
- [`rvc4_4.py`](https://github.com/petercorke/bdsim/blob/master/examples/rvc4_4.py) Fig 4.4 - a car-like vehicle driving to a point

- [`rvc4_6.py`](https://github.com/petercorke/bdsim/blob/master/examples/rvc4_6.py) Fig 4.6 - a car-like vehicle driving to/along a line

- [`rvc4_8.py`](https://github.com/petercorke/bdsim/blob/master/examples/rvc4_8.py) Fig 4.8 - a car-like vehicle using pure-pursuit trajectory following

- [`rvc4_11.py`](https://github.com/petercorke/bdsim/blob/master/examples/rvc4_11.py) Fig 4.11 a car-like vehicle driving to a pose

Figs 4.8 (pure pursuit) and Fig 4.21 (quadrotor control) are yet to be done.
# A more concise way
Wiring, and some simple arithmetic blocks like `GAIN`, `SUM` and `PROD` can be implicitly generated by overloaded Python operators. This strikes a nice balance between block diagram coding and Pythonic programming.
```
1 #!/usr/bin/env python3
2
3 import bdsim
4
5 sim = bdsim.BDSim() # create simulator
6 bd = sim.blockdiagram() # create an empty block diagram
7
8 # define the blocks
9 demand = bd.STEP(T=1, name='demand')
10 plant = bd.LTI_SISO(0.5, [2, 1], name='plant')
11 scope = bd.SCOPE(styles=['k', 'r--'], movie='eg1.mp4')
12
13 # connect the blocks using Python syntax
14 scope[0] = plant
15 scope[1] = demand
16 plant[0] = 10 * (demand - plant)
17
18 bd.compile() # check the diagram
19 bd.report() # list all blocks and wires
20
22 out = sim.run(bd, 5, watch=[plant,]) # simulate for 5s
```
This requires fewer lines of code and the code is more readable. Importantly, it results in in *exactly the same* block diagram in terms of blocks and wires
```
Wires::
┌───┬──────┬──────┬──────────────────────────────┬─────────┐
│id │ from │ to │ description │ type │
├───┼──────┼──────┼──────────────────────────────┼─────────┤
│ 0 │ 1[0] │ 2[0] │ plant[0] --> scope.0[0] │ float64 │
│ 1 │ 0[0] │ 2[1] │ demand[0] --> scope.0[1] │ int │
│ 2 │ 0[0] │ 3[0] │ demand[0] --> _sum.0[0] │ int │
│ 3 │ 1[0] │ 3[1] │ plant[0] --> _sum.0[1] │ float64 │
│ 4 │ 3[0] │ 4[0] │ _sum.0[0] --> _gain.0(10)[0] │ float64 │
│ 5 │ 4[0] │ 1[0] │ _gain.0(10)[0] --> plant[0] │ float64 │
└───┴──────┴──────┴──────────────────────────────┴─────────┘
```
The implicitly created blocks have names prefixed with an underscore.
# bdedit: the graphical editing tool

`bdedit` is a multi-platform PyQt5-based graphical tool to create, edit, render and execute block diagram models.
From the examples folder
```
% bdedit eg1.bd
```
will create a display like that shown above. Pushing the run button, top left (triangle in circle) will spawn `bdrun` as a subprocess which will:
* parse the JSON file
* instantiate all blocks and wires
* compile and run the diagram
Screencast showing bdedit usage.
# Article
I published [this article on LinkedIn](https://www.linkedin.com/pulse/journey-toward-open-source-block-diagram-simulation-peter-corke/?trackingId=wrJYinHUgAHDq63Nv65PnA%3D%3D), which describes the thought process behind bdsim.
# Limitations
There are lots! The biggest is that `bdsim` is based on a very standard variable-step integrator from the scipy library. For discontinuous inputs (step, square wave, triangle wave, piecewise constant) the transitions get missed. This also makes it inaccurate to simulate hybrid discrete-continuous time systems. We really need a better integrator, perhaps [`odedc`](https://help.scilab.org/docs/6.1.0/en_US/odedc.html) from SciLab could be integrated.
================================================
FILE: bdsim/__init__.py
================================================
# from bdsim.bdsim import *
# from bdsim.blockdiagram import *
# from bdsim.components import *
# from bdsim.graphics import GraphicsBlock
# from bdsim.bdrun import bdrun, bdload
from .run_sim import *
from .run_realtime import *
from .blockdiagram import *
from .components import *
from .graphics import GraphicsBlock
from .bdrun import bdrun, bdload
try:
import importlib.metadata
__version__ = importlib.metadata.version("bdsim")
except:
pass
================================================
FILE: bdsim/bdedit/Icons.py
================================================
# -*- coding: utf-8 -*-
# Resource object code
#
# Created by: The Resource Compiler for PyQt5 (Qt v5.15.2)
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore
qt_resource_data = b"\
\x00\x00\x0e\xc4\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x64\x00\x00\x00\x64\x08\x06\x00\x00\x00\x70\xe2\x95\x54\
\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\x00\x00\x00\
\x09\x70\x48\x59\x73\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7\x6f\
\xa8\x64\x00\x00\x0e\x59\x49\x44\x41\x54\x78\x5e\xed\xdd\x05\x8c\
\x34\x49\x19\x06\xe0\x1f\x77\x77\x77\x77\x77\x38\xdc\xdd\xed\x70\
\x08\x12\x24\x40\xb0\x40\xd0\x10\x0e\x77\x77\x87\x10\x3c\x38\x07\
\x1c\x76\x38\x1c\xee\xee\xee\x0e\xef\xc3\x6d\x91\x61\xd2\x5d\xd3\
\x3d\xdb\xdd\xd3\xcb\xcd\x9b\xbc\xd9\xbd\xbd\xdd\x7f\xaa\xeb\xab\
\xfa\xbc\xaa\xf7\x6d\xb1\xc5\x16\x5b\x6c\xb1\xc5\x16\x5b\x6c\x31\
\x02\x0e\xb7\xf3\x75\x2f\xe0\x24\xe1\xe9\x76\x78\xa2\xf0\x98\x0b\
\x3c\x52\xf8\xb7\xf0\xf7\xe1\xef\x76\xbe\xfe\x2c\xfc\xd6\x0e\x7f\
\x1a\xee\x09\xcc\x51\x20\x87\x0f\x8f\x1b\x9e\x3f\xbc\x50\x78\xc1\
\xf0\x0c\xe1\xb1\xc3\x23\x87\x26\xff\x08\xa1\xdf\x43\xcf\x80\xff\
\xda\xe1\x3f\x77\xf8\x8f\x90\x90\xfe\x12\xfe\x26\xfc\x5a\xf8\x89\
\xf0\xe3\xe1\xa7\xc3\xdf\x86\x7e\x7f\x56\x98\x8b\x40\x8e\x18\x9e\
\x2a\xbc\x5c\x78\xd9\xf0\xec\x21\x01\x94\x1d\x70\xd4\xb0\x4c\x7e\
\x5f\x14\x21\xfd\x29\xfc\x43\x68\xf7\xfc\x3a\xfc\x7c\xf8\x9e\xf0\
\xc0\xf0\x47\x21\x01\x6e\x1c\x9b\x16\xc8\x89\xc3\x8b\x87\x97\x0f\
\xed\x88\x93\x85\x27\x08\x09\x81\x00\xc6\x02\x01\x51\x6d\x3f\x0f\
\x09\xe3\x93\xe1\xbb\xc2\x8f\x86\xbf\x08\x37\x86\x4d\x09\xe4\xa4\
\xa1\x9d\x70\xd5\xf0\xbc\xe1\xc9\xc3\xe3\x85\x63\x0a\xa1\x0d\x76\
\xc6\xaf\xc2\xef\x87\x87\x84\x04\xf3\xbe\xf0\x7b\xe1\xe4\x98\x5a\
\x20\xa7\x08\xaf\x1c\xee\x17\x9e\x27\x64\xa0\x8f\x15\xce\x05\x76\
\xcd\x77\xc2\xcf\x84\xef\x08\xdf\x1d\xfe\x38\x9c\x0c\x53\x09\x84\
\x0d\xb8\x54\x78\xed\x90\x30\x4e\x1f\x1e\x2d\x9c\x2b\xd8\x9a\xaf\
\x87\xef\x0f\xdf\x1a\x1e\x14\xb2\x41\xa3\x83\xb7\x32\x36\xce\x11\
\xde\x32\xbc\x55\x78\x95\xf0\x94\x21\x4f\x69\xce\xe0\xcd\x71\xb3\
\xcf\x1a\x5a\x3c\xd4\xe9\x2f\xc3\xd1\xed\xcb\x98\x3b\xc4\xa4\xb3\
\x13\x37\x0e\xaf\x16\x8a\x1d\x86\x58\x00\xc5\x20\xff\x39\xe4\xd2\
\xfe\x75\xe7\x67\xec\x8f\x89\xb4\x1b\xed\xbe\x63\xec\xfc\x6c\xb7\
\x60\x63\x18\xfe\xb7\x84\xaf\x09\xed\x96\xbf\x87\xa3\x60\x0c\x81\
\xf8\x37\xad\xa8\xab\x87\xb7\x0d\x2f\x1a\x9a\xa4\xbe\x28\xee\x2a\
\x4f\xe8\x87\xe1\x4f\x42\xc6\x97\xcb\x6a\xa5\x52\x2b\xd4\x08\xa1\
\x98\x34\xc2\xf6\x39\xc8\x4b\xe3\xad\x89\x67\x8c\xc5\x6a\xe7\x38\
\x9c\x30\x34\xbe\x75\x9e\xdb\xe7\x7d\x28\x7c\x61\xf8\xf6\xd0\x38\
\x06\xc7\xd0\x02\xb1\x22\x19\x6e\xbb\xe2\x6e\x21\xf5\xd4\x67\x57\
\x10\x82\x15\xcf\x90\x7e\x3b\xe4\xe9\xd0\xe5\x5f\x09\xbf\x11\x5a\
\xa9\x22\x70\x42\x58\x05\x82\xb1\x2b\x09\x42\x60\x79\x96\xf0\x8c\
\xa1\x78\xe7\xb4\x21\x4f\x4f\xfc\xd3\x67\x0e\xec\x8c\x6f\x86\x4f\
\x0f\x5f\x1d\xca\x00\x0c\x1a\x5c\x0e\x29\x10\x0f\xe7\x41\x6f\x11\
\xde\x27\x3c\x7a\xd8\xf5\xdf\xb7\x13\x44\xce\x84\x20\xa2\x16\x4d\
\x7f\x30\xe4\xed\x0c\x69\x4c\x8d\xe9\x02\xe1\x25\x43\x59\x00\x82\
\x32\xe6\x3e\x71\x0f\x01\x88\xfc\x0f\x08\x5f\x11\x72\x97\x67\x11\
\x54\x2e\x82\xbd\x38\x5b\xf8\xd8\xd0\xea\x35\xe8\x2e\xf4\x20\x8c\
\xe5\xa7\xc2\xe7\x84\xd7\x0c\x8f\x13\x4e\x01\xaa\xec\x7a\xe1\x8b\
\x42\x82\xa7\x0e\x8d\xa7\x69\x9c\xcb\xb4\x80\x3c\xe7\x23\x43\xbb\
\xce\x62\x9c\x0d\x0c\x86\x37\x62\x1b\xdb\xd2\x4d\x0f\xd0\x44\x3a\
\x99\x2a\x7a\x76\xc8\xf8\xaf\x63\x67\x86\x00\x07\xe0\x4a\x21\xdb\
\x60\x77\x1a\x97\x09\x6f\x1a\xf3\x32\x3d\xef\x13\x42\x3b\x6d\x0a\
\x8f\x75\x25\x0c\xc2\x60\x1e\x1d\x76\x15\x86\xdf\x63\x94\x19\xc6\
\x1b\x86\xbc\xa1\x39\x80\xda\x62\xfb\x8c\xcb\xae\xed\xf3\x3c\x8f\
\x08\x4f\x1d\x6e\x22\xd3\xf0\x5f\xb0\x0f\x8c\xf6\x43\xc2\xae\x6a\
\x8a\xc1\x96\x0e\xbf\x7f\xc8\xf8\xcf\x11\xa7\x09\x1f\x16\x8a\xd8\
\x65\x8b\x9b\x9e\x63\x99\x5c\x70\x76\x93\xa3\x30\xb4\xa3\xd4\x19\
\xc7\x0f\xef\x19\xca\x9e\x36\x0d\x72\x99\x56\xd2\x87\x43\xee\xf0\
\x51\xc2\x39\x83\x1a\xbb\x41\xc8\xb9\xe8\xba\x53\xc4\x46\x77\x08\
\xa7\xb2\x81\xff\x03\x76\xe3\x26\xa1\x55\xd4\x55\xdf\xbe\x24\x94\
\x56\xdf\xd8\x0a\xea\x09\xea\x47\x06\x5a\x30\xd8\xf4\x3c\xcb\x34\
\x0f\x5c\xe2\x6b\x84\x93\xdb\x13\x46\x58\x2d\xa1\x8b\x57\x62\xa0\
\x0c\xfe\x99\xc2\x8d\xea\xd8\x35\x60\x62\x79\x8f\xcf\x08\xbb\x3c\
\xab\xdd\x24\xf7\x75\xb1\x70\x32\xf0\xa8\x78\x46\xe2\x83\xa6\x41\
\x2d\xd2\x43\x30\x78\xb2\xba\xb3\xf0\x42\x76\x01\x71\x47\x17\xa1\
\xfc\x31\x7c\x62\xc8\xd9\x19\x1d\x5c\xd3\x7b\x84\x3f\x08\x9b\x06\
\xb3\xcc\xa7\x86\xff\x0f\xc2\x80\x33\x87\x4f\x0b\x9b\x9e\x73\x99\
\x82\xc5\x3b\x85\xa3\xbb\xf2\x57\x0c\x15\x70\x56\x19\x3a\x2b\x89\
\xcd\xf0\x10\x5d\x85\x21\xc5\x71\xa3\x9d\xaf\x73\x85\xcc\xb5\x94\
\x49\xd3\x33\x2f\xd2\xfc\x48\x46\x2a\x39\x8c\x06\xe5\x55\x5b\x51\
\x52\xad\x69\x10\x85\x5c\xc5\x83\xc3\x73\x86\x7d\x76\x06\x61\xf8\
\x7b\xb5\x6e\x0e\xc3\x1c\x05\x23\x23\x21\xe5\xf2\xb1\x70\x95\x33\
\x23\x96\x11\xc9\x2b\x53\x8f\x02\x39\xaa\xcf\x86\xb5\x81\x58\x19\
\xdf\x0d\xb9\xb6\x7d\x0d\x78\x11\x48\xe1\x2b\xc3\x39\x0a\x45\x8a\
\xff\x3a\xa1\xc4\x62\xcd\xa6\x98\x27\x82\x93\x9e\x19\x1c\x02\xc0\
\xe7\x87\xd2\x0a\x4d\x1f\x8e\x06\x20\x1f\xf4\xc0\x70\x9d\x38\x63\
\x59\x20\xc8\x71\xb8\x57\x38\x37\xc1\x88\xea\x05\x8f\x0c\x78\x6d\
\x81\x8a\x4d\x9e\x12\x0a\x18\x07\xc5\xcd\x42\x09\xb8\xa6\x0f\x2d\
\x34\xb8\xb7\x85\xeb\x46\xe0\x4d\x02\x29\x94\x72\xbf\x75\x38\x17\
\xc1\x88\xa5\xa4\x4a\x94\x78\x45\xe9\x4d\x63\x2e\xa4\xbe\xaf\x1b\
\x0e\x06\x35\x05\xbb\xa3\x34\x96\x35\xd1\xd6\x55\xaf\xb8\x7e\xb8\
\x2e\x6a\x02\x29\xd4\xe8\xe6\xf7\xe6\x22\x18\x0b\x95\xc7\x59\x53\
\x5d\x6c\xee\x93\x43\x05\xb3\x41\x20\xf2\x94\x42\x68\xfa\xb0\x42\
\xaa\xea\x05\xe1\x6e\x12\x85\x5d\x04\x52\x28\x65\x3e\x07\xa1\xe8\
\x98\x79\x55\x48\x35\x35\x8d\xb3\x50\xd9\xf7\x0a\xe1\x4a\xac\x32\
\xbc\x52\x24\xba\x44\x24\xdc\xda\x40\x87\xf2\xbb\x5f\x1e\xb2\x31\
\xab\x30\x44\x4c\xa2\x61\x42\xea\x5e\x55\x72\x93\x82\x21\x08\x8b\
\x43\x79\xd9\x3c\xb4\x41\x90\xa8\x28\xb6\xeb\x67\x27\x88\x55\x71\
\x87\xea\xd9\x8b\xc3\xae\x6d\x3d\x6d\x6e\x60\x9f\x1d\xb2\x48\x55\
\x46\x1e\xe0\xa6\x04\x23\xf8\x7b\x6d\x58\xdb\x25\xe6\xef\x0d\xe1\
\x4a\xfb\xba\x6a\x87\x08\x6c\xd4\xa0\xdb\x24\xeb\xc3\xd4\xbd\x5f\
\x1f\x76\x2d\xb5\x6a\x3c\x18\x12\x16\xcd\x4b\x43\x8b\x62\x13\xf6\
\x85\x51\x27\x10\xbb\xc4\x7c\x34\xc1\xfc\x29\x15\x6b\x9b\x5d\x1b\
\x3c\x09\x65\x55\xf6\x61\x51\xda\x8b\x54\x07\x79\x63\x38\xc4\x24\
\xaf\xbb\x43\x96\x29\xcf\x36\xb5\x50\x94\x22\x24\x5b\xd5\x7b\x9a\
\xc6\x84\xba\x67\x04\xd6\xd5\x6c\x77\x6d\x87\xe8\x3e\x97\x48\xf4\
\xb5\x0d\x82\x23\xc1\xcf\x28\x2d\x31\x6b\xe2\x8e\xe1\x17\x42\xb9\
\xa4\xa9\x04\x23\x2a\xe7\xde\xd6\x1a\xe9\xd4\xf0\x57\xcd\x67\x55\
\x20\xe7\x0b\x49\xbe\xed\x77\x48\x9d\xba\xe2\x8b\x8f\x0d\xab\x8b\
\xa7\xd7\x15\x76\xec\xb3\x42\xf6\xef\xa6\xe1\x14\x82\xb1\x43\xb4\
\x2f\x99\x97\x26\x98\x47\x7d\x61\x6a\x42\xad\x58\x25\x90\x5a\xf5\
\xcb\x07\xf3\xc1\x75\x8c\x8c\x0d\x3b\x51\xba\x82\x77\xa5\x28\xd6\
\x15\x1e\x5e\xab\xce\x73\xc3\xb1\xed\x8b\x1d\x52\x13\x08\x58\xe0\
\xba\xfd\x5b\x51\x13\x88\x6a\x59\x4d\x20\xb6\xa7\x2e\x0d\x11\xfa\
\x14\xd0\xbd\x28\x83\xcc\x30\xea\xf4\xe8\x03\xad\xac\xb2\xb4\xf7\
\x0b\xc7\x12\x8a\x52\xb6\xf9\xa8\xa9\x6f\x6a\xeb\xdc\x87\x7e\xdb\
\x8c\x9a\x40\x78\x05\x35\x57\xd6\x6a\xf8\xd2\xa1\xdf\x4e\x0a\x82\
\x79\x7c\xa8\x43\x84\x2b\xd9\x07\x77\x0f\xa5\x80\x6e\x13\x8e\x21\
\x18\x99\x6a\xea\xb5\x0d\x72\x60\xe6\xb5\x15\x6d\x02\x11\x2b\xd0\
\xc3\xb5\x40\x46\x7e\xc9\x8a\xd8\x04\x08\x45\xad\xfb\xae\x21\x1b\
\xe1\x04\x54\x57\x48\x05\xc9\x2a\xbc\x33\x1c\x3a\xcd\xff\xe5\xb0\
\x66\xd8\x05\xda\xe6\xb5\x35\x8d\xd2\x26\x10\xbe\xbd\x80\xa7\xe6\
\xa2\x09\x08\x4d\xcc\x26\xe1\xf3\xa5\x2e\xae\x15\xde\x3e\xac\xad\
\xce\x65\x28\x36\x49\xf1\xab\x97\x0f\x25\x14\x19\x0b\x01\x62\x1b\
\xcc\x27\xad\x23\xb6\x6b\x44\x4d\x20\xf2\xfe\x6d\x90\x26\x20\x90\
\xb9\x1c\x37\x26\x18\x09\x50\xa7\xb2\x4c\x70\x1f\x38\x44\xa4\x5b\
\x44\x5f\xd5\x6e\x05\xa3\x19\x9c\x40\x6a\x69\x14\x02\x91\x29\x6e\
\x44\x9b\x40\xb8\x67\xb5\x43\x35\x72\x56\x56\xa3\x28\x75\x4e\x20\
\x98\x47\x85\xa5\x03\xb1\x2b\xd4\x6f\xf4\x25\x8b\xa9\x78\x72\xeb\
\x0a\xc6\x7c\x98\x97\x5a\xd6\xc2\xbc\xf2\xb6\x1a\xd1\x26\x90\x55\
\xdd\xe0\x3e\xb0\xb6\x35\x37\x89\x62\x5f\x6e\x17\x4a\x8f\x0b\x12\
\xbb\x42\xae\x49\xb2\xf0\x4d\xe1\x3a\x6e\x32\x97\xd7\xbc\xd4\x8e\
\x4b\xb0\x23\xe6\xb7\x11\x6d\x93\x2e\x8d\x5e\x33\xe8\x52\x04\x73\
\xdb\x1d\xcb\x20\x18\x36\x42\x23\xb5\xa8\xbd\x8f\x7d\x71\x64\x81\
\x9b\xfc\xb8\xb0\xaf\x50\x2c\x56\x7d\x05\x6d\x30\xaf\x8e\x45\x34\
\xa2\x4d\x20\xfe\xa0\xb6\x43\xca\x0d\x09\x7b\x01\x04\x23\x27\xc7\
\xbe\xe8\x70\xef\x03\x1e\xdc\x47\xc2\xd6\x15\xdd\x80\x55\x02\x31\
\xaf\xbd\x05\x42\xcf\xd5\x3c\x2c\x46\x4b\x95\x6c\xaf\xc0\x2a\xbf\
\x74\x78\xe1\xff\xfc\x57\x3f\x94\x23\x0a\x5d\x21\xd5\x5e\x9b\x1b\
\x73\xde\x6a\x9f\xdb\x04\x52\xba\xbe\xdb\xe0\xef\x6a\x2a\x6d\x2e\
\x20\x08\xb6\x40\xc3\x1e\xf5\xc5\xd5\xed\x0a\x2a\xce\x19\xc9\xfd\
\xc3\xda\x5c\x2c\x83\x8d\xa8\xcd\x8d\xc5\xdc\xba\x83\xda\x04\x52\
\xba\x29\xda\x40\xc2\x73\xef\x60\x27\x8c\xfb\x86\x6c\x41\xdf\x56\
\x1c\xae\x73\x51\x71\x54\x5e\x1f\x70\x6b\x6b\x1e\xaa\x79\x6d\x4d\
\x37\xb5\x09\xc4\x16\xad\x6d\x3b\x31\x4a\xd7\x0a\xe1\xd4\x20\x08\
\xa9\x11\x29\x12\xc7\x25\xfa\x40\x6d\x87\xcb\xcc\x75\xee\x2b\x88\
\x82\x55\x02\x31\xaf\xbd\x05\x22\x51\xb6\x2a\xb8\x99\xd3\x95\x18\
\x50\xd4\x13\x97\x57\x6a\x44\x8a\xa4\x2b\xd8\x09\x2e\xf2\x5d\x42\
\x7f\xbf\xae\x30\xd8\x5d\xf5\x8e\x9a\xf6\x60\x63\x5a\x6d\x52\x9b\
\x40\xe8\xcf\x9a\xa7\xc0\x2d\x96\x8f\xd9\xd4\xb9\xc0\x65\x10\x86\
\x6a\x1c\xf5\x74\x09\x3f\xe8\x08\x0b\x8f\x10\x34\x72\xb0\x31\xeb\
\x0a\xa2\xc0\x7c\x98\x97\x9a\xf6\x30\xaf\xad\xf9\xae\x36\x81\x68\
\x1c\xa8\xb9\xb5\xfe\x4e\x6a\x7e\xb4\xbe\xd5\x8e\x20\x08\x29\x0f\
\xa9\x0f\xbb\xa3\x0f\x14\xb0\x9c\x5d\x7f\x66\xb8\x5b\x41\x14\xe8\
\x7f\xa6\x39\xda\xe6\x15\xb8\xc5\xad\x35\x9d\xb6\x3f\xf4\x07\xe5\
\xdc\x60\x1b\x08\x64\x53\xe7\x04\x09\x82\xf7\xe3\x88\x9c\x94\x47\
\x1f\x07\xe3\x03\x21\x3b\xe1\xdc\xca\x50\x82\x28\xd0\x72\x5b\x53\
\xe5\xe6\x93\x40\x24\x21\x1b\xd1\x26\x10\xa9\x75\xc9\xc3\x9a\x61\
\xa7\xa3\x9d\xd1\x9e\x12\x8b\x76\x42\x97\x49\xad\x5f\x6c\x19\x6e\
\x84\xb8\x79\x28\xd8\xdb\x8d\x9d\xa8\x41\xcd\xbc\xd6\xa1\xc8\x7e\
\x28\x60\xf5\x56\x59\x40\x0d\xd4\xaa\x81\x1a\x88\xab\xf5\xe1\x81\
\x41\x18\xda\xfb\xfb\xda\x09\x29\x1e\x0d\xdb\x97\x09\x95\x73\xc7\
\x10\x44\x81\x23\x18\x35\x67\x82\xcd\x62\x0e\x5a\x51\x13\x48\xb9\
\x28\xb2\x0d\x32\x96\xce\x0d\xb6\xa6\x01\x06\x84\x74\xb5\x4e\x45\
\xee\x6c\x1f\xd8\x45\xba\x06\x9f\x14\x8e\x29\x08\xa0\xaa\x1c\x50\
\xaa\x95\xbd\x75\xa7\x38\xd2\xd1\x8a\x9a\x40\x34\x2f\x50\x5b\x6d\
\xf0\xb7\x56\xad\x44\xdc\xd8\x90\x4b\xea\x93\x4f\x72\x4f\x0a\x3b\
\xe1\x68\xc4\xd8\x82\x28\xb8\x48\xe8\xd6\xa1\x5a\xca\x49\x8f\xdb\
\xda\x02\xf1\x87\x74\x5d\x5b\x3c\xe2\x83\x55\xbe\xe4\x88\xe6\x02\
\xee\xba\x5d\x44\x18\x63\xd9\x89\x36\xb8\xc8\x93\x97\xd5\x26\x10\
\xf6\x98\x6d\xae\x96\x03\x6a\x02\xb1\x3b\xd4\x88\x6b\x6a\x8b\xdb\
\x6b\x65\xe8\xa6\xd8\x24\xd8\x89\x7b\x87\xd2\x1d\xea\x19\x53\x0a\
\x02\xa8\x6f\xf3\xd0\x5a\x78\x0a\xec\x0e\xf3\x59\xad\x23\xd5\x04\
\xc2\x45\x3b\x28\xd4\xb3\xda\x06\x29\x02\x57\xe0\x09\xac\xba\x82\
\x9e\x1d\x12\x6a\xea\xec\x84\xd6\xa0\xa9\x05\x51\xa0\xe6\xc2\xce\
\x49\x2c\xb6\x41\x0f\x1b\x37\xbd\x9a\xa8\xac\x09\x04\x74\x25\x3a\
\x33\xd8\xe6\xfe\x16\xb5\xe5\x84\x50\xd7\xdc\x56\xcd\x2e\xf5\x81\
\x4e\x13\xaa\xc9\xce\xd8\x94\x20\x40\x74\xee\xa0\x52\xcd\x7e\x98\
\x3f\x77\xbc\xa8\xad\x54\xb1\x4a\x20\x1e\x94\x2d\xe1\x1d\xb4\x81\
\xb1\xd5\xe5\xd8\xd5\x15\xed\x53\xb9\x6b\x82\x1d\x2b\x2d\xae\xd3\
\x64\x6a\x3b\xd1\x04\xb7\x5a\x78\xfe\x9a\xb7\xa9\x19\xc4\x3c\x0e\
\x72\xe5\xac\x13\xb5\xab\x4e\x50\x09\x76\xa4\xaa\xfb\x78\x42\xcb\
\x10\xf0\x35\xfd\xdb\x8b\x74\x45\x07\xcf\x6e\x2e\xe0\xea\x8a\x8b\
\x56\x5d\xc0\x23\x3b\xd0\xe9\x04\x55\x17\x08\x74\x9e\x17\x76\x39\
\x63\xe8\x06\x9d\x75\x51\x13\x88\x43\xf8\xfe\xff\x9c\x84\x01\x32\
\xc4\x76\xa8\xe7\x6f\x1a\x37\x0e\x7e\xc6\x10\xba\x9e\xc2\xd5\x7a\
\x23\x9f\xb3\x0e\x9a\x04\x32\xd7\x4b\x04\xd8\x0a\x46\x9c\xd3\x53\
\x72\x7e\x6d\x74\x9f\xfc\xa0\xa7\x70\x41\x12\xb1\xeb\x39\xf5\x07\
\x85\xeb\xa4\xe5\x17\x05\xc2\x35\xbc\x73\x38\x37\x41\x14\x50\xcd\
\x0f\x0f\x2d\xc2\xc5\x39\x58\xa6\xe7\x18\xe5\x9c\x3a\x48\xcc\xd9\
\x25\x26\xbe\xe9\xc3\x51\xf2\xac\xdc\xe4\xd0\xb7\xe6\x6e\xf2\x79\
\x4e\x0f\xdd\xf9\x7e\xae\x90\x59\x56\x12\x16\xe4\xd5\x54\x95\x79\
\x72\x44\x61\x94\x9b\x1c\x40\x14\xca\xd7\xa7\x13\x9b\x06\x50\xa8\
\x00\x63\x20\xe7\x0a\xf7\x42\x23\x44\x57\x58\x24\xe2\x2e\x9d\x2b\
\xd2\x4a\xb5\x85\x89\xb2\x1c\x52\xfc\xa3\xd6\x8c\x78\x0a\x5d\x6f\
\x03\x7a\x59\xd8\xe7\x36\xa0\xb9\x43\xd0\xa7\x6b\x85\xab\xdd\xf4\
\xcc\x8b\x34\x3f\x6f\x0e\x47\xbd\x0d\x08\xd8\x86\xc3\xe2\x7d\x59\
\xc6\x6f\x71\x71\xbb\x9b\x9e\x73\x99\x8e\xfa\x39\xeb\x38\x49\x89\
\x5b\x11\x46\xf9\x53\xe5\xab\x69\x30\x8b\xb4\x53\xf6\xfa\x8d\x72\
\xc6\xad\xcc\xd0\xe7\x46\xb9\x72\x97\xef\x64\xf0\xae\x28\x2f\x3b\
\x59\xa5\xba\x90\xae\xd5\xe7\x74\x58\xba\x73\xd1\x0b\x08\x26\x05\
\x7d\x2a\x8f\xa4\xfa\xb5\xca\xb8\x15\x3a\xdc\xbf\x97\x6e\x25\x35\
\x4e\xb5\x1e\x97\x02\x34\x3d\xcf\x32\xcd\x83\xe0\x78\x1d\x0f\x73\
\x10\x48\x35\x3b\xb3\xc7\xd7\x6e\x1a\xe0\x32\x79\x5f\x92\x6b\x2e\
\xb3\x99\x44\xb7\xee\x02\x12\xa5\xb2\x0e\x6e\x1f\xea\xa2\x05\x50\
\x26\xc3\x29\xae\x5a\xc5\x70\x54\x58\x41\x02\xc6\x07\x87\xab\xa2\
\xd5\xc2\x72\xb3\xf5\x03\xc2\x75\x23\xfa\xb1\xe1\x50\xa6\xa0\x4f\
\xe7\x4d\xed\x66\x86\x45\x96\x7a\xcc\xaa\x8a\xe1\xe8\x60\x13\xd4\
\x43\xd6\xb9\xfb\x9d\xfb\x2c\xd8\xac\xde\x6c\x30\x21\x24\x0a\xa9\
\xe1\x3d\x7b\xf7\x7b\x01\x7b\xc2\xf3\x72\x85\x6a\xd7\x87\x40\xde\
\xc8\x57\x43\x67\x37\x38\x09\x9b\x52\x63\xd4\x93\x37\xc7\xa9\x34\
\x96\xa3\x07\x5d\xed\xa2\xe7\x9d\xd5\xdb\x11\x0a\x44\xb0\x43\xbd\
\x3f\x64\xe8\xdb\x82\xda\xb0\xf8\xfe\x10\xb5\x0a\x19\x88\x2e\x9e\
\x14\x12\x18\x35\x35\xf8\xfb\x43\x86\xd4\x77\x06\x45\xff\x0e\xf1\
\x86\x1d\xc6\xd4\xfb\x9e\xe4\xce\xfa\x1c\x96\x59\x05\x3d\xc9\xe5\
\x0d\x3b\xbe\x9a\x4c\x63\x96\x2c\xec\xaa\x6e\xca\x58\x1f\x13\xea\
\x07\x1e\xf4\x0d\x3b\x43\x1b\x20\x0f\x25\xe7\x43\x17\xbb\xed\xad\
\x76\xd7\x56\x13\xac\x3e\xde\x98\xe3\xc5\x84\x23\xe2\xe5\x4a\x2e\
\xbf\x83\x6a\xd5\xf9\x46\xcf\x45\x05\xca\x23\xc9\xc1\x51\x29\xfa\
\x78\x7d\x35\x26\x42\x58\xf7\x1d\x54\xc6\x21\x2e\x51\x98\x52\x09\
\x34\xe6\xc1\x30\xb4\x40\xc0\xbf\x49\x1d\xf0\xc7\xdd\x24\xea\x62\
\xfa\xae\xf5\xf6\x45\x14\xd5\xc0\x01\x90\xaa\x59\x7c\x4b\x1b\x35\
\xa7\x4a\x27\x5b\x40\x45\x5a\xa1\x04\x2f\x13\xeb\xb3\x18\x68\x6e\
\x39\xf5\x67\x2c\x26\xdf\x42\x71\xdc\x1b\xd6\x79\x6e\x3b\x55\xfd\
\x83\x8a\xf3\x16\x50\xe3\x18\x1c\x63\x08\xa4\xc0\xea\x5b\x7c\x8f\
\xa1\xd5\x3a\x84\xe1\x23\x24\x93\x43\x18\x76\x0a\xd7\xd4\xcf\xec\
\x4e\x02\x41\xea\x12\x87\xf0\x7a\x08\x5b\x55\x50\x04\x2e\xb1\xa8\
\x1c\x3b\x98\x8a\x5a\xc6\x98\x02\x29\x10\x9d\xdb\x2d\xee\x8d\xf7\
\x6e\x74\xab\x76\x8a\xcf\xdd\x2d\xec\x50\x1d\x32\x1c\x0e\xc2\x50\
\x46\xe6\x15\x8e\x8a\x29\x5c\x35\x3a\xdf\x43\x95\x40\x8b\x61\x65\
\x44\x6b\xc7\xbe\x36\x0d\x3b\xf0\x8b\xa1\x0b\x04\x34\x6f\xbc\x2e\
\xac\xf5\xa7\x0d\x86\xa9\x7c\x67\xc6\x50\x84\xce\xbd\x64\x08\x8b\
\x51\xa6\xef\xe7\x94\x46\x61\x97\x78\x79\xef\x0d\xdd\xcd\x85\x9f\
\x0b\x8d\x7f\x12\x6c\x4a\x75\x30\xb2\x7a\x82\xbd\x4f\x9d\xfb\xc9\
\xe0\xae\xba\x0e\x6a\x2c\xb0\x07\x9c\x05\x8e\x83\xc9\x97\xc5\x3e\
\x30\xe4\xe1\x4d\x8e\x4d\xeb\x72\x2d\x46\xbc\x30\xf6\x45\xb3\x19\
\x17\x95\x27\xd4\x27\x2e\x58\x07\x9c\x00\x49\x51\x4d\x7b\x5c\x69\
\x71\x8f\x54\xce\xaa\x8b\x2c\x47\xc7\x5c\x8c\xab\x9d\x21\x3e\xd0\
\x23\x2c\x8d\xa2\x54\x6a\xc7\x14\x7b\x43\xad\x11\xd0\x3a\xe3\x65\
\x9c\xed\x02\x6a\x92\x6d\xa0\x96\xb8\xac\x87\x84\x2e\xae\xb4\x1b\
\x74\x14\x8e\xe6\x39\xf5\xc1\x1c\xbd\x1d\x63\x22\x0c\x3b\xc6\xcb\
\x53\xca\x3b\x6b\xfd\x8c\x23\x80\x04\x48\x40\x85\x05\x56\x7e\xa1\
\x09\x16\x64\x72\x24\xa8\xa4\x92\x01\x70\x05\x93\xc3\x48\xa5\xdb\
\x70\x56\x98\xa3\x40\xda\x20\x8e\x51\x0a\x96\x5d\x2e\x6a\x4d\x00\
\x58\x3c\x36\x13\x6f\x92\xa9\x22\xe4\xdd\x71\x24\x44\xfc\xbe\xdf\
\x62\x8b\x2d\xb6\xd8\x62\x8b\x2d\xb6\x98\x0a\xfb\xf6\xfd\x1b\x7a\
\x3c\x86\x67\xee\xbb\xee\x69\x00\x00\x00\x00\x49\x45\x4e\x44\xae\
\x42\x60\x82\
\x00\x00\x25\x17\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\xb2\x00\x00\x00\xb2\x08\x02\x00\x00\x00\x69\xe8\x02\x3f\
\x00\x00\x01\x35\x69\x43\x43\x50\x49\x43\x43\x20\x50\x72\x6f\x66\
\x69\x6c\x65\x00\x00\x78\x9c\x63\x60\x60\x32\x61\x80\x82\xdc\xbc\
\x92\xa2\x20\x77\x27\x85\x88\xc8\x28\x05\xf6\x7b\x0c\x6c\x0c\x2c\
\x0c\x82\x0c\xda\x0c\x16\x89\xc9\xc5\x05\x0c\x98\x80\x11\xc1\xfc\
\x76\x0d\xc2\xbb\xac\x8b\x45\x1d\x21\xc0\x95\x92\x5a\x9c\x0c\xa4\
\xff\x00\x71\x65\x52\x76\x41\x09\xd0\xe8\x0a\x20\x5b\xa4\xbc\x04\
\xcc\xee\x01\xb1\x93\x0b\x8a\x40\xec\x05\x40\xb6\x68\x11\xd0\x81\
\x40\xf6\x0e\x90\x78\x3a\x84\x7d\x06\xc4\x4e\x82\xb0\x1f\x80\xd8\
\x45\x21\x41\xce\x40\xf6\x17\x20\xdb\x21\x1d\x89\x9d\x84\xc4\x86\
\xda\x0b\x02\xf2\xc5\x20\x8f\x7b\xba\x3a\x9b\x19\x5a\x9a\x99\xe9\
\x1a\xe9\x1a\x2a\x24\xe5\x24\x26\x67\x2b\x14\x27\x27\xe6\xa4\xa6\
\x90\xe1\x2b\x02\x00\x14\xc6\x10\x16\xb3\x18\x10\x1b\x33\x30\x30\
\x2d\x41\x88\x21\xc2\xb3\x24\xb5\xa2\x04\xc4\x72\x29\xca\x2f\x48\
\xca\xaf\xd0\x51\xf0\xcc\x4b\xd6\x43\xd1\x9f\xbf\x88\x81\xc1\xe2\
\x2b\xd0\x8c\x09\x08\xb1\xa4\x99\x0c\x0c\xdb\x5b\x19\x18\x24\x6e\
\x21\xc4\x54\x80\x61\xc7\xdf\xc2\xc0\xb0\xed\x7c\x72\x69\x51\x19\
\xd4\x19\x52\x40\x7c\x94\xf1\x0c\x73\x12\xeb\x64\x8e\x6c\xee\x6f\
\x02\x0e\xa2\x81\xd2\x26\x8a\x1f\x35\x27\x18\x49\x58\x4f\x72\x63\
\x0d\x2c\x8b\x7d\x9b\x5d\x50\xc5\xda\xb9\x69\x56\xcd\x9a\xcc\xfd\
\x75\x97\x0f\xbe\x34\xff\xff\x1f\x00\x81\x49\x5c\xa9\xc6\xc2\x24\
\x8e\x00\x00\x23\x9d\x49\x44\x41\x54\x78\x9c\xed\x7d\x79\x74\x14\
\x55\xfe\xef\xf7\xde\xaa\x5e\x92\x74\x56\x02\x21\x40\x82\x09\x09\
\x24\x20\x61\x40\xa2\x6c\x13\xe1\x08\x8e\x22\x22\xb8\xa0\x1c\x1d\
\x67\x64\x66\xde\x19\xfc\xe9\x1c\x70\x3c\x8a\x8c\x0a\xe8\x30\xa8\
\x38\xa3\x8e\x07\x75\x5c\xdf\x3c\xdc\x1f\x8c\x4f\x07\x65\x11\xd1\
\x04\x09\x61\x58\x4d\x24\x0c\x10\xc8\x4a\x42\xf6\x90\xa4\xf7\xaa\
\xfa\xbe\x3f\xbe\xe9\xb2\x49\x3a\x49\x27\xe9\x2d\xa1\x3e\x27\xc7\
\x23\xdd\xd5\x55\x75\xef\xfd\xd4\xe7\xbb\xd4\xf7\xde\xcb\x10\x11\
\x86\x0a\x14\x45\x41\x44\x44\x64\x8c\x09\x82\xd0\xf5\xdb\xf6\xf6\
\xf6\xe6\xe6\xe6\xba\xba\xba\xc6\xc6\xc6\x96\x96\x96\xd6\xd6\xd6\
\x4b\x97\x2e\x59\xad\x56\x87\xc3\x61\xb7\xdb\x19\x63\x00\x60\x34\
\x1a\x0d\x06\x83\xc9\x64\x8a\x8c\x8c\x8c\x89\x89\x89\x8d\x8d\x1d\
\x36\x6c\xd8\xf0\xe1\xc3\xa3\xa3\xa3\xc3\xc3\xc3\xbb\x5e\x54\x92\
\x24\x00\x60\x8c\x71\xce\xe9\x0c\x43\x00\x6c\xb0\xd3\x02\x11\x15\
\x45\x01\x80\x4e\x3c\xb0\xd9\x6c\x17\x2e\x5c\x38\x7d\xfa\x74\x69\
\x69\x69\x71\x71\x71\x59\x59\xd9\xc5\x8b\x17\x6b\x6b\x6b\x5b\x5b\
\x5b\xad\x56\x2b\x8d\xa5\x97\x30\x18\x0c\x61\x61\x61\xc3\x86\x0d\
\x4b\x4c\x4c\x4c\x4c\x4c\x4c\x4f\x4f\x4f\x4f\x4f\x4f\x4b\x4b\x4b\
\x4b\x4b\x1b\x39\x72\xa4\xfb\x91\x8a\xa2\x28\x8a\x42\xfc\x18\xd4\
\x14\x19\xac\xb4\x40\x44\x59\x96\x3b\xa9\xc2\x85\x0b\x17\x8e\x1f\
\x3f\x7e\xf8\xf0\xe1\xa3\x47\x8f\x16\x17\x17\x57\x55\x55\x39\x9d\
\x4e\x8f\x3f\x67\x2e\xf4\x7a\x15\xe2\x9c\x47\x98\x4c\xa6\xf1\xe3\
\xc7\x4f\x9c\x38\xf1\xda\x6b\xaf\x9d\x3e\x7d\xfa\xa4\x49\x93\xa2\
\xa2\xa2\xd4\x6f\x65\x59\x06\x80\x41\x2a\x21\x83\x8c\x16\xc4\x06\
\xce\x39\xe7\x9c\x3e\x69\x6e\x6e\x2e\x28\x28\xf8\xf6\xdb\x6f\xf3\
\xf2\xf2\x4e\x9e\x3c\xd9\xde\xde\xee\x7e\xbc\x7a\x24\xba\xa0\x9e\
\xc7\xfb\x8b\xd2\xb8\xaa\x34\xa2\xff\xca\xb2\xdc\xe9\x24\xa3\x46\
\x8d\xba\xe6\x9a\x6b\xe6\xce\x9d\x3b\x77\xee\xdc\xc9\x93\x27\xeb\
\x74\x3a\xfa\x7c\x30\xf2\x63\xd0\xd0\x82\x3a\x57\xd5\x86\x0b\x17\
\x2e\xec\xdd\xbb\xf7\x8b\x2f\xbe\xc8\xcf\xcf\xbf\x78\xf1\xa2\x7a\
\x18\xf1\x00\xdd\xe0\xbf\x5b\x22\xa2\x10\xed\x3a\x59\xa5\x89\x13\
\x27\xce\x9b\x37\x6f\xf1\xe2\xc5\xb3\x67\xcf\x8e\x88\x88\x50\x9b\
\xa0\x1e\x1f\xe2\x08\x75\x5a\x90\x8c\xab\x6c\x68\x68\x68\xd8\xb9\
\x73\xe7\xf6\xed\xdb\x73\x73\x73\x5b\x5a\x5a\xe8\x43\x95\x0a\xe4\
\x72\x06\xeb\x56\x55\xaf\xd3\x9d\x22\x29\x29\x29\x37\xdf\x7c\xf3\
\xd2\xa5\x4b\xe7\xce\x9d\x2b\x8a\x22\x74\xe1\x77\x88\x02\x43\x15\
\x8a\xa2\x48\x92\xa4\xfe\x73\xef\xde\xbd\x2b\x56\xac\x48\x48\x48\
\x50\xef\x5c\x10\x04\x41\x10\x42\x50\x99\x89\x1f\xa2\x28\xba\x0b\
\xc3\xa4\x49\x93\x9e\x7d\xf6\xd9\x92\x92\x12\xb5\x45\x92\x24\xa9\
\xa1\x53\xa8\x21\x14\x69\x21\xcb\xb2\x4a\x88\x96\x96\x96\x2d\x5b\
\xb6\x64\x67\x67\xab\xfd\x1b\xb2\x6c\xf0\x88\x4e\xfc\x30\x99\x4c\
\xcb\x97\x2f\xdf\xb3\x67\x8f\xda\xd8\xd0\x24\x47\x68\xd1\xc2\x5d\
\x21\x2a\x2a\x2a\x1e\x7f\xfc\xf1\x31\x63\xc6\x50\x87\x32\xc6\x44\
\x51\x1c\x2c\x6c\xe8\x0a\xce\xb9\xbb\xe1\x98\x39\x73\xe6\x07\x1f\
\x7c\x60\xb1\x58\xa8\xb1\xa1\x46\x8e\x50\xa1\x85\x3b\x21\xce\x9e\
\x3d\xfb\xf0\xc3\x0f\xc7\xc6\xc6\x52\x0f\x0a\x82\x30\x28\xdc\x34\
\x6f\x40\x11\xb5\xda\x9c\x8c\x8c\x8c\xd7\x5e\x7b\xad\xbd\xbd\x9d\
\x1a\xee\x6e\x34\x83\x8b\x90\xa0\x85\xbb\x42\xac\x5e\xbd\xda\x64\
\x32\x51\xaf\x0d\x22\x63\xd1\x57\xb8\x8b\xc7\xf8\xf1\xe3\xdf\x7c\
\xf3\x4d\xea\x04\x59\x96\x29\xf4\x0d\x2e\x82\x4c\x0b\x59\x96\x49\
\x3c\x9b\x9b\x9b\xd7\xaf\x5f\xef\xae\x10\x43\x95\x10\xee\x70\x27\
\x47\x76\x76\xf6\xe7\x9f\x7f\x4e\xdd\x12\x74\x9b\x12\x34\x5a\xb8\
\x5b\x8d\xad\x5b\xb7\x8e\x1b\x37\x8e\x7a\xe7\x0a\x21\x84\x3b\xdc\
\xc9\x71\xcb\x2d\xb7\x1c\x3b\x76\x8c\xba\x25\x88\x36\x25\x38\xb4\
\x50\x1b\x7c\xf4\xe8\xd1\x05\x0b\x16\x50\x8f\x5c\x81\x84\x70\x87\
\x9a\x90\xd5\xeb\xf5\x8f\x3d\xf6\xd8\xa5\x4b\x97\x30\x78\xb2\x11\
\x68\x5a\xa8\x22\x61\xb5\x5a\xd7\xae\x5d\xab\xd7\xeb\x61\x68\x39\
\x95\x03\x84\x2a\x1b\x13\x26\x4c\xf8\xf2\xcb\x2f\xa9\xd3\x02\x2f\
\x1b\x01\xa5\x85\xea\x49\xec\xdf\xbf\x7f\xea\xd4\xa9\x9d\x3a\x42\
\x03\x81\x42\x71\xfa\xff\x95\x2b\x57\x36\x37\x37\x63\xc0\x65\x23\
\x70\xb4\x70\x3a\x9d\x88\x28\x49\xd2\x53\x4f\x3d\x45\x54\x18\xd4\
\x79\x08\x7f\x43\xb5\x29\x69\x69\x69\x3b\x77\xee\x44\x44\x45\x51\
\x02\x16\xa4\x04\x82\x16\x8a\xa2\x10\x27\xce\x9e\x3d\x3b\x6f\xde\
\x3c\x70\xa5\x87\x83\xdd\xf3\x83\x00\xaa\x6c\x3c\xf9\xe4\x93\xea\
\x73\x15\x80\x21\xf3\x3b\x2d\x54\x8e\x6f\xdf\xbe\x3d\x3e\x3e\x1e\
\x34\x91\xe8\x23\x54\xd9\x98\x3f\x7f\x7e\x59\x59\x19\xba\x74\xd7\
\xaf\xf0\x2f\x2d\x54\xd1\x5b\xbb\x76\x2d\x35\x52\xf3\x24\xfa\x07\
\x92\x8d\xc4\xc4\xc4\xaf\xbf\xfe\x1a\xfd\xef\x6a\xf8\x91\x16\x24\
\x77\xcd\xcd\xcd\xb7\xde\x7a\x2b\x68\xe1\xc6\x80\x41\x4f\x94\x20\
\x08\xaf\xbc\xf2\x0a\x22\x52\x81\xa0\x9f\xc6\xce\x5f\xb4\x20\xa1\
\x3b\x73\xe6\x4c\x56\x56\x16\xb8\xd9\x48\x0d\x03\x81\x5a\xe2\xf5\
\x87\x3f\xfc\x81\xfa\xd9\x4f\x4e\xa8\x5f\x68\x41\x9c\xc8\xcd\xcd\
\xa5\x0a\x58\x8d\x13\x3e\x84\x1a\xbe\xde\x76\xdb\x6d\x6a\xca\xcb\
\xe7\x23\xe8\x7b\x5a\x10\x27\x3e\xfb\xec\x33\x2a\x9f\xd7\x9c\x09\
\x7f\x80\x0a\x45\x67\xcd\x9a\x55\x57\x57\x87\x7e\x60\x86\x8f\x69\
\x41\x9c\xf8\xe7\x3f\xff\x49\x5a\xa7\x39\x13\xfe\x03\x69\x46\x66\
\x66\xe6\xf9\xf3\xe7\xd1\xd7\xcc\xf0\x25\x2d\x88\x13\x6f\xbf\xfd\
\x36\xb8\x85\x55\x1a\xfc\x07\x62\x46\x6a\x6a\xea\xb9\x73\xe7\xd0\
\xa7\x81\xab\xcf\x68\x41\xf7\xf4\xc6\x1b\x6f\xc0\x60\x2b\x7e\x1f\
\xd4\x20\x1b\xad\x32\xc3\x57\x9a\xe1\x1b\x5a\x10\x27\xde\x7b\xef\
\x3d\xd0\x38\x11\x70\xf8\x83\x19\x3e\xa0\x85\xea\x4f\xc0\x15\xff\
\x72\x3c\x58\x20\x6b\x32\x6e\xdc\xb8\xea\xea\x6a\xf4\x45\xd4\x3a\
\x50\x5a\x10\x27\xf6\xec\xd9\xc3\x5d\x08\x76\x17\x5d\xa1\x20\x66\
\x64\x67\x67\x37\x37\x37\x0f\x3c\xd3\x35\x20\x5a\x90\x5e\x15\x14\
\x14\x98\x4c\x26\xed\xed\x57\xd0\x41\xcc\x98\x3f\x7f\xbe\xd3\xe9\
\x54\x6b\x18\x02\x4d\x0b\x52\xaa\xb2\xb2\xb2\xd1\xa3\x47\x83\x16\
\x8b\x86\x06\x88\x19\xf7\xdf\x7f\x3f\x0e\x2c\x30\xe9\x27\x2d\xe8\
\xbd\x68\x5b\x5b\xdb\xf4\xe9\xd3\x41\xcb\x59\x85\x12\x88\x19\xcf\
\x3c\xf3\xcc\x40\x98\xd1\x4f\x5a\xd0\xf5\xee\xb9\xe7\x1e\xd0\x72\
\xdb\x21\x06\x35\x3b\xbe\x7d\xfb\xf6\x7e\x33\xa3\x3f\xb4\xa0\x2b\
\x3d\xf7\xdc\x73\xe0\xca\xc2\x6a\x08\x29\x50\x8e\x20\x32\x32\xb2\
\xb8\xb8\x18\xfb\x15\x98\xf4\x99\x16\xe4\x66\x7e\xfd\xf5\xd7\x34\
\x41\x4a\x0b\x47\x43\x13\x64\xd6\xb3\xb2\xb2\x2c\x16\x4b\x3f\x8a\
\x33\xfa\x46\x0b\xf2\x6f\x6b\x6a\x6a\x46\x8f\x1e\xad\x85\x1e\x21\
\x0e\x32\x25\xbf\xfd\xed\x6f\xb1\xef\xa6\xa4\x6f\xb4\x20\xa9\x58\
\xb4\x68\x11\x68\x6e\xe6\x60\x00\x31\xe3\xa3\x8f\x3e\xc2\x3e\x66\
\x3f\xfb\x40\x0b\x3a\xef\x96\x2d\x5b\x40\x73\x33\x07\x09\x48\xd1\
\xe3\xe2\xe2\xca\xcb\xcb\xb1\x2f\x4e\x86\xb7\xb4\x20\x4e\x9c\x3c\
\x79\x32\x3c\x3c\x5c\x73\x29\x06\x11\x48\xd4\x6f\xbc\xf1\xc6\x4e\
\xcb\xc8\xf8\x80\x16\x74\x46\x45\x51\xe6\xcc\x99\x03\x9a\xf9\x18\
\x6c\x20\x69\x7f\xfd\xf5\xd7\xd1\x6b\x27\xc3\x2b\x5a\x10\xcb\x5e\
\x7b\xed\x35\xd0\x38\x31\x08\x41\xef\xaa\xe2\xe2\xe2\x2a\x2a\x2a\
\xbc\x9c\x83\xd4\x3b\x2d\x28\xfa\xa8\xac\xac\x8c\x8e\x8e\xd6\x5e\
\x9a\x0f\x52\xd0\xc3\x7c\xe7\x9d\x77\xa2\x77\xbe\x67\xef\xb4\xa0\
\xb3\x2c\x5b\xb6\x0c\x34\xa9\x18\xcc\xa0\xb1\xa3\xe9\xce\xbd\x32\
\xa3\x17\x5a\xd0\xef\xf7\xed\xdb\x07\xda\xcb\xb0\x41\x0e\x1a\xbe\
\xcc\xcc\x4c\xab\xd5\xda\xeb\xfb\xd5\x5e\x68\x21\xcb\xb2\xc3\xe1\
\x98\x36\x6d\x1a\x68\xb4\x18\xfc\x20\xc1\x78\xf1\xc5\x17\xb1\x37\
\xdf\xb3\x27\x5a\x90\x54\x50\x29\x9e\x66\x3e\x86\x00\xc8\x35\x1c\
\x3e\x7c\x78\x5d\x5d\x5d\xcf\xa5\x3a\xdd\xd2\x82\x7e\xd6\xd6\xd6\
\x36\x76\xec\x58\x2d\xcf\x3d\x64\x40\x8f\xf7\x23\x8f\x3c\x82\x3d\
\x7a\x18\xdd\xd2\x82\x44\xe6\xa5\x97\x5e\x02\x4d\x2a\x86\x10\x68\
\x9d\xf2\xc8\xc8\xc8\xca\xca\xca\x1e\x82\x55\xcf\xb4\x50\xa5\x22\
\x29\x29\x49\x93\x8a\x21\x06\xca\x6e\xad\x5a\xb5\xaa\x07\xc1\xf0\
\x4c\x0b\x92\x8a\xbf\xfd\xed\x6f\xa0\x49\xc5\x90\x03\x79\x18\x26\
\x93\xa9\xbc\xbc\xbc\x3b\xc1\xf0\x40\x0b\x92\x0a\xb3\xd9\x9c\x9c\
\x9c\xac\x49\xc5\x90\x04\x09\xc6\xea\xd5\xab\xbb\x13\x0c\x0f\xb4\
\xa0\xe3\xd4\x79\x1f\xc1\x6e\x82\x06\xdf\x83\x3c\x8c\xf8\xf8\xf8\
\x86\x86\x06\x8f\x21\x89\x67\xb5\x90\x24\x89\x72\x15\x1a\x2d\x86\
\x2a\x68\x64\xff\xfa\xd7\xbf\xa2\xa7\x1c\x46\x67\x5a\x68\x69\xcd\
\x2b\x04\x6a\xd2\xd3\x6e\xb7\xf7\xae\x16\x44\x8b\xbb\xee\xba\x0b\
\xb4\x5a\x9b\xa1\x0e\x62\xc6\x8e\x1d\x3b\xba\x96\x62\x5c\x46\x0b\
\x72\x4a\xcb\xcb\xcb\x69\x7b\x2d\xed\x65\xe9\xd0\x06\xd9\x91\x25\
\x4b\x96\x60\x97\xc2\xad\xcb\x68\x41\x36\xe6\x85\x17\x5e\x00\x4d\
\x2a\xae\x00\xd0\x63\x1f\x11\x11\x41\xeb\x3a\xba\x33\xe3\x27\x5a\
\x90\x47\x2a\x49\x12\x2d\xbb\xac\x39\x9b\x57\x02\xe8\xe1\xef\xfa\
\xf2\xec\x27\x5a\x10\x59\x8e\x1c\x39\xa2\xd5\xda\x5c\x39\xa0\x87\
\x7f\xda\xb4\x69\x9d\x5e\xb5\xff\x14\x6b\xd0\xf6\xc0\xff\xfa\xd7\
\xbf\xdc\x37\x98\xd4\x30\xb4\xa1\x28\x0a\x63\xec\xc4\x89\x13\x45\
\x45\x45\x8c\x31\x75\x8b\xe8\x0e\x5a\x20\xa2\x20\x08\xb2\x2c\x7f\
\xf1\xc5\x17\xe0\xa2\x88\x86\x21\x0f\x1a\x77\x45\x51\x3e\xff\xfc\
\x73\x70\x1f\xf7\x4e\x16\xc4\xcb\xcd\xc7\x35\x0c\x19\x90\x65\xc8\
\xce\xce\x76\x4f\x77\x76\x84\x1b\x8a\xa2\x70\xce\x69\x83\x02\x51\
\x14\x3b\x6d\x0d\x1d\x9a\x08\xf1\xf7\x35\xc1\xdd\xc2\xd9\x7b\x90\
\x1d\xf9\xe1\x87\x1f\xce\x9e\x3d\x3b\x7e\xfc\x78\x62\x02\xa8\x61\
\x08\x22\x6a\xd3\x40\xae\x4c\x50\x3c\xb2\x65\xcb\x16\x35\x1e\x61\
\xc4\x09\xce\xf9\x85\x0b\x17\x26\x4c\x98\x60\x36\x9b\x19\x0b\xf5\
\x8d\xd7\xe9\x0e\x23\x23\x23\xe7\xcc\x99\x43\xdb\x5a\x85\x8e\xd5\
\x53\x1f\xb3\xa3\x47\x8f\xd6\xd4\xd4\x84\x7e\x67\x02\x00\xb9\x95\
\x4b\x97\x2e\xa5\x80\x83\x73\x2e\x82\xcb\x82\xe4\xe7\xe7\x9b\xcd\
\x66\x3a\x22\xd8\xf7\xd9\x0b\x38\xe7\xb2\x2c\x67\x67\x67\xaf\x5e\
\xbd\x7a\xe7\xce\x9d\xa2\x28\x86\x8e\x8f\xcc\x39\x77\x3a\x9d\x33\
\x67\xce\x4c\x49\x49\x79\xf5\xd5\x57\x05\x41\x08\x7d\x8b\x4c\xc4\
\x2d\x28\x28\x68\x6f\x6f\x37\x99\x4c\x3f\xf9\x16\x00\x90\x9b\x9b\
\x0b\xa1\xf4\xd8\xf5\x0a\x83\xc1\xf0\xd5\x57\x5f\xbd\xfc\xf2\xcb\
\xc1\xbe\x11\x0f\x38\x7d\xfa\x74\x7a\x7a\x3a\xb8\x7a\x3c\xc4\x41\
\xee\x45\x4d\x4d\x4d\x61\x61\xe1\xac\x59\xb3\x14\x45\x11\x01\x40\
\x10\x04\x44\x2c\x28\x28\x00\xff\x84\xa6\x9c\xf3\x8e\xdc\x99\x4f\
\x81\x88\x26\x93\x49\x10\x04\x0a\xb1\x7c\x7b\xf2\x7e\x83\x94\x2c\
\x3a\x3a\x7a\xe0\xa7\x52\x95\x3b\x00\x12\x4e\xaa\x76\xf0\xe0\xc1\
\x59\xb3\x66\x21\xa2\x48\x16\xa4\xaa\xaa\xaa\xb8\xb8\x18\xfc\xc3\
\x6e\x1a\x33\x7f\x58\x59\xaa\x39\x03\x80\xd0\x31\x7c\x34\x84\x3e\
\xa1\xa9\x2c\xcb\x46\xa3\x51\xa7\xd3\xb5\xb5\xb5\x0d\xfc\x6c\xde\
\xe0\xe0\xc1\x83\x40\xab\x6f\xd1\x50\xfd\xf8\xe3\x8f\x56\xab\x95\
\x73\xee\xdb\xc7\x8e\x96\xf7\x5a\xb8\x70\xe1\xb2\x65\xcb\xf6\xef\
\xdf\xff\xc6\x1b\x6f\x0c\x0a\xdf\x25\xe8\xa0\x81\x58\xbe\x7c\x79\
\x66\x66\x66\x6c\x6c\x6c\x43\x43\xc3\xb3\xcf\x3e\x0b\xfe\x4c\x33\
\xd2\x99\x7f\xf8\xe1\x07\x87\xc3\xa1\xd7\xeb\x39\xd1\xe2\xf8\xf1\
\xe3\xe0\x87\xba\x1b\x44\xe4\x9c\x9f\x3c\x79\xb2\xb6\xb6\x36\x25\
\x25\x05\x06\x95\xef\x12\x44\x50\xbf\x2d\x5b\xb6\xec\xbd\xf7\xde\
\x7b\xf8\xe1\x87\xef\xbf\xff\xfe\x29\x53\xa6\x74\x64\x14\xfc\x76\
\x45\x00\x28\x2d\x2d\x2d\x2f\x2f\x07\x35\xf9\x4d\xb4\xf0\x07\x24\
\x49\x2a\x29\x29\xa9\xae\xae\x0e\x80\x43\xee\x3d\xe7\xbc\xcc\xe4\
\x06\x6b\x7f\x35\x0a\x71\xef\xbc\xf3\xce\x8b\x17\x2f\x4e\x9e\x3c\
\x39\x37\x37\xb7\xba\xba\xda\xaf\xb1\x2e\x11\x51\x96\xe5\xff\xfe\
\xf7\xbf\x00\xc0\x29\xba\xa3\x7f\xf8\x43\xa3\x68\x00\xf4\x7a\x7d\
\x00\x74\xc2\xfb\x5e\xf3\xd2\x05\xf6\x95\x97\xd0\x0f\x10\x1d\xaf\
\xbb\xee\xba\xe7\x9e\x7b\xae\xaa\xaa\xaa\xae\xae\x0e\xfc\x1c\xd7\
\xd0\x15\x4f\x9e\x3c\x09\xa4\x16\x4d\x4d\x4d\x24\x1d\xfe\xbb\x2a\
\x65\x51\xbd\x65\x06\xf3\xf4\xd7\x3d\x28\x2d\xfb\xc0\x03\x0f\xe4\
\xe6\xe6\xd2\x3a\xa1\xbd\x5e\xe8\x93\x4f\x3e\x79\xe6\x99\x67\xa0\
\x7b\xbb\x49\x67\xb8\xee\xba\xeb\xae\xbe\xfa\x6a\x6f\x4e\xe8\x73\
\x90\x37\x9d\x9b\x9b\x7b\xcb\x2d\xb7\x64\x64\x64\xfc\xe6\x37\xbf\
\xa1\xf7\x12\xfe\xbe\xee\xa9\x53\xa7\x80\x68\x51\x56\x56\xd6\xda\
\xda\x0a\x3d\xd2\x82\x31\x60\x9c\xf5\xf9\x8f\x01\xe3\x0c\x11\x75\
\x7a\x9d\x4e\x27\x22\xa2\xfa\x61\x37\xc7\x33\xc6\x19\x20\x74\xfd\
\x63\x9c\x75\x47\x0e\x1a\xb3\xd4\xd4\xd4\x9c\x9c\x1c\x8a\x57\x45\
\x51\xec\x9a\xc2\xe7\x9c\x8b\xa2\x48\x9b\xf3\xce\x9e\x3d\x7b\xca\
\x94\x29\xea\x6f\xc9\x35\xa6\x5f\xa9\xf6\x45\x10\x84\xbd\x7b\xf7\
\xbe\xf5\xd6\x5b\xe0\x5a\x50\x86\xbe\x55\x8f\xa4\x1f\x76\x77\x39\
\x2f\xd1\xd1\x64\x76\xd9\x27\x00\x10\x19\x19\xf9\xfc\xf3\xcf\x13\
\xcb\x23\x22\x22\x6c\x36\x5b\xcf\x03\x04\x00\xc0\x80\x09\xac\xf3\
\x1f\xf7\x96\xd0\x74\x72\xda\xe2\x4a\x04\x00\x92\x8a\x9e\x62\x04\
\x06\x88\x00\xfd\xd2\x12\xa7\xc3\x79\xfd\x9c\xb9\x29\x63\x52\x19\
\x67\xf3\xe7\x2e\xd8\xfb\xdd\xd7\x74\x0b\xdd\xdf\x1d\x30\xce\x0c\
\x91\x3a\x44\x84\x8e\xee\x62\xb2\x43\x71\x5a\x7b\x71\x4d\x6c\x36\
\x9b\xc3\xe1\x90\x5d\x80\xcb\x43\x62\xf2\xed\x55\x8b\x60\x36\x9b\
\x2d\x16\x4b\x47\xe3\x18\x43\x44\x77\xd7\x87\x3e\x91\x65\x79\xc6\
\x8c\x19\x74\x98\xfb\x7b\x2f\xf5\x48\xea\x31\xb5\xd3\x3c\xda\x7e\
\xc6\x19\x07\xd6\x6d\x6b\x15\x40\x44\x40\x00\x00\x26\x74\x8c\x1f\
\x3d\x35\x4e\xd9\x69\x8a\x32\xad\x5b\xff\xb4\x53\x92\x0e\x1c\x3c\
\xf0\xe1\xc7\x1f\x72\x91\x23\x2a\xea\x61\x1e\x7a\x4e\x46\x94\xfb\
\xaf\xf7\xd4\x39\xe5\xe5\xe5\x66\xb3\x59\x04\x80\xb2\xb2\x32\xe8\
\x59\x27\x11\x22\x13\xc3\xb8\x9e\x43\x5f\x2f\xca\x00\x10\xce\x34\
\x9e\x7c\xe2\xc5\x47\x11\x50\x14\xc5\xa8\xe4\x70\xc6\x98\xe7\xf3\
\x70\x40\x19\x13\x26\xc7\x4e\xf9\x55\x9a\x31\x46\x87\x0a\x00\x03\
\x05\x99\xc0\x50\x91\xf1\xdc\xee\xea\x23\x6f\x9c\x56\x9c\x08\x88\
\x02\x78\x38\x01\x25\xb5\x8c\x46\xe3\xbd\xf7\xde\x3b\x72\xe4\xc8\
\xbc\xbc\xbc\xfc\xfc\x7c\x1a\x2a\x2a\x30\x49\x4b\x4b\x5b\xb4\x68\
\x11\x22\x7e\xf2\xc9\x27\x4e\xa7\x93\x04\x99\x0e\x88\x8e\x8e\x5e\
\xba\x74\x69\x52\x52\x52\x71\x71\xf1\x17\x5f\x7c\xe1\x74\x3a\xe9\
\x73\xbd\x5e\x6f\xb7\xdb\x01\x00\x11\xb3\xb2\xb2\x8c\x46\xe3\xe9\
\xd3\xa7\xef\xbe\xfb\xee\x98\x98\x98\x03\x07\x0e\x1c\x38\x70\x20\
\x22\x22\x62\xf9\xf2\xe5\xf1\xf1\xf1\x87\x0e\x1d\xfa\xf6\xdb\x6f\
\x3b\x79\xb2\x8c\x81\xe4\xec\x85\xcd\x91\xa3\xc2\x74\xe1\xba\x96\
\xd2\x36\xc5\x35\xa2\x44\x13\x59\xb2\xfd\xcf\xca\xff\x89\x32\xc4\
\xc8\xb2\x6c\x96\xbc\xca\x5b\xe8\x22\xc4\xd1\xd9\xf1\x86\x28\x1d\
\x43\x04\x06\x0a\x02\x63\xac\xad\xda\x52\x7d\xa4\x91\xc6\x82\x61\
\xef\x03\xd8\xd4\xd4\x54\x57\x57\x27\x02\x40\x45\x45\x45\xb7\x47\
\x31\x10\x74\xfc\xfa\x0d\x53\x52\xe7\x8f\x54\x24\xec\x9f\x85\x95\
\x29\x9d\x05\x80\x80\x02\xef\x5e\x6c\x19\x28\x12\x88\x06\x81\x31\
\xa6\x38\x15\x04\xc6\x00\x0d\x82\x62\x91\x04\x81\xe1\xb5\x0f\x67\
\xc8\x76\xf9\xd8\x3f\xce\x80\xc0\x1c\x1d\x87\x5f\x06\xca\xe0\xe6\
\xe6\xe6\x1a\x8d\x46\x51\x14\x37\x6d\xda\xb4\x71\xe3\xc6\x27\x9f\
\x7c\x92\xea\x04\x96\x2c\x59\xb2\x6d\xdb\xb6\xa6\xa6\xa6\xda\xda\
\xda\x07\x1f\x7c\x70\xe4\xc8\x91\xc7\x8e\x1d\xa3\x5f\xa5\xa7\xa7\
\xef\xda\xb5\x2b\x26\x26\xe6\xf4\xe9\xd3\xeb\xd7\xaf\x3f\x72\xe4\
\xc8\xa2\x45\x8b\x1a\x1a\x1a\x00\xe0\xcb\x2f\xbf\xcc\xcf\xcf\xbf\
\xf3\xce\x3b\x01\x60\xd5\xaa\x55\xcb\x97\x2f\x2f\x2e\x2e\xd6\xeb\
\xf5\xb1\xb1\xb1\xcf\x3f\xff\xfc\xfa\xf5\xeb\x17\x2e\x5c\x18\x15\
\x15\x05\x00\x9b\x36\x6d\xda\xb4\x69\xd3\xda\xb5\x6b\x55\x67\x85\
\x31\x40\x84\x31\xd7\x8e\x88\xba\x2a\x0c\x65\xec\x7c\xbb\x0c\x50\
\x86\x51\x53\x87\x25\xe7\x24\x08\x3a\xde\x54\xd2\x5a\xb2\xfb\x82\
\xd3\x26\xbb\xf7\xb0\xc0\x05\x9b\xcd\xc6\x18\x33\x18\xe3\x7b\x4d\
\xf6\x70\x91\x67\x2c\x4e\x1a\x31\x39\x16\x14\xb4\x2b\x82\x02\xcc\
\xc8\x25\x62\x41\xe9\x37\x35\xfb\x9e\x3c\x8e\x36\xb9\x67\x86\x92\
\xd4\x59\x2c\x96\xca\xca\x4a\x11\x00\xaa\xaa\xaa\x3c\x0f\x13\x67\
\xa8\xe0\xe8\x19\xf1\x93\x96\x8d\xb5\x36\xd9\x05\x7d\x3f\x43\x35\
\x0e\xde\xfd\x90\x01\x20\x4a\x16\x19\x18\x70\x0e\x16\x59\x5c\x31\
\xa6\x64\xce\xf0\x9a\x0d\xff\x9d\x56\x69\x09\xe7\xcd\xf6\xe4\x1b\
\x12\x8f\xbc\x53\x02\x92\x72\x8f\x00\x46\x80\x52\xb8\xec\xbc\x4e\
\xa7\xd3\x60\x30\xbc\xfe\xfa\xeb\xe4\x0d\x3c\xfd\xf4\xd3\x1b\x36\
\x6c\xf8\xf4\xd3\x4f\x0b\x0b\x0b\xa3\xa3\xa3\xdf\x7d\xf7\xdd\xdd\
\xbb\x77\xdf\x7e\xfb\xed\x76\xbb\x3d\x27\x27\x67\xef\xde\xbd\xa4\
\x99\x8a\xa2\xac\x5b\xb7\xce\x64\x32\x0d\x1f\x3e\x5c\x51\x94\xc9\
\x93\x27\x17\x16\x16\xae\x5c\xb9\x92\x1c\xd2\xd6\xd6\x56\xb3\xd9\
\x4c\xe7\x6f\x6b\x6b\x13\x45\x71\xed\xda\xb5\xbb\x77\xef\x16\x04\
\x61\xdb\xb6\x6d\xeb\xd7\xaf\x5f\xb3\x66\xcd\xf3\xcf\x3f\x0f\x00\
\xaf\xbe\xfa\xea\x9a\x35\x6b\x36\x6f\xde\xdc\xd2\xd2\x42\x5d\xe7\
\x30\xcb\x23\xe6\x44\xde\xfe\xcf\x39\x8a\x2c\x63\x17\x12\x23\x80\
\xe2\x44\xc5\x81\x92\x4d\x46\x05\x87\x4f\x8c\x19\x39\x35\x8e\x77\
\x0d\xd7\x18\x73\xc9\x47\x4f\x40\x00\x74\xa2\xd3\x22\xdb\x5a\x1c\
\x92\xc2\xd2\x23\x9a\x22\x44\xa9\xb0\x25\x0e\x38\x0a\x51\x7a\x8b\
\x55\x76\x02\x00\xb0\x11\x80\x97\x00\xec\xdd\x9f\x87\x4c\xed\xc5\
\x8b\x17\x45\x00\xa0\x27\xa3\x3b\x77\xc6\xd1\x26\x29\x4e\x45\x17\
\x2e\x42\xd7\xc6\xf9\x02\x1c\x40\x01\xe0\x00\xc8\x40\x16\xd0\x29\
\xcb\x28\x23\x20\x30\x84\x36\x49\x57\x6f\x0b\x73\x28\x82\x80\xe8\
\x60\x7c\xac\xa4\xfc\x19\x31\x1b\xc0\x0e\xf0\x2b\x80\x6b\x2f\x37\
\x25\x7a\xbd\x5e\x92\x24\xe2\x04\x00\xbc\xf0\xc2\x0b\x4f\x3c\xf1\
\xc4\xed\xb7\xdf\x5e\x58\x58\x98\x93\x93\x13\x1b\x1b\xfb\xc4\x13\
\x4f\xd8\xed\x76\x51\x14\xf3\xf2\xf2\x4a\x4b\x4b\x69\xf7\x5e\x70\
\xe5\x98\xc7\x8d\x1b\x77\xf6\xec\xd9\xa2\xa2\xa2\xb1\x63\xc7\x92\
\x5b\x4a\xa1\xbc\xfa\xf4\x47\x44\x44\xd4\xd5\xd5\xed\xde\xbd\x5b\
\xa7\xd3\x39\x9d\xce\xbc\xbc\xbc\x85\x0b\x17\xbe\xf2\xca\x2b\xf4\
\xed\xae\x5d\xbb\x1e\x7a\xe8\xa1\x84\x84\x84\xe6\xe6\xe6\x8e\x1b\
\x42\x1c\xb7\x68\x24\x2a\x68\xae\xb5\x31\xb1\x4b\xc7\x21\x28\x4e\
\x72\xc0\x19\x30\x70\x5a\x25\x87\x19\x98\x00\x4c\xf4\x64\x20\xbd\
\x80\x6c\x47\x2e\x30\xce\x19\x03\xfe\xbf\x52\x4a\x12\xc2\xdb\xfe\
\x50\x38\xcb\x29\x1b\xce\xff\xf5\xc7\x1f\xff\xcf\xf9\x04\x80\x45\
\x0c\xb2\x01\xfe\x04\xe0\xe8\xb8\xbe\x07\x10\x2b\x6b\x6a\x6a\x44\
\x49\x92\x9a\x9a\x9a\xc0\x13\x2d\x50\x41\x60\x70\xf1\x78\x53\xde\
\x33\x85\xe3\x17\x27\xc9\x4e\xc5\x1f\x61\x5a\x3b\x40\x24\x80\x15\
\x80\x33\xd0\x29\x10\x93\x64\x32\xc6\x19\x64\xbb\x1c\x01\xf8\xef\
\x96\x94\xaf\x2e\x5d\xa5\x30\x08\x33\x21\x37\xe9\x0e\xfd\xbb\xca\
\x22\xe3\x51\xce\x16\x03\xcc\x03\x68\xf4\xc4\xd2\xb0\xb0\x30\xab\
\xd5\xca\x18\xb3\xdb\xed\xf5\xf5\xf5\xe3\xc6\x8d\x03\x80\xd4\xd4\
\x54\x45\x51\x6a\x6b\x6b\xc9\xc9\xa0\xd2\x76\x6a\x2f\xe7\xfc\xa9\
\xa7\x9e\x4a\x49\x49\x39\x75\xea\xd4\x99\x33\x67\xf2\xf2\xf2\x36\
\x6f\xde\x7c\xee\xdc\x39\x7a\xbd\x77\x59\x6f\x20\x52\x3d\x18\xfd\
\x8f\x5e\xaf\xe7\x9c\x1b\x8d\x46\x8a\x11\xa8\xec\xe3\xa7\x9f\x30\
\x00\x80\xca\xbc\xfa\x19\xf7\x0a\xe1\x23\x0c\x1e\xc2\x01\x04\x7b\
\x8b\x24\xd9\xe5\x0e\xa7\x9a\x33\xc6\xc0\x38\x4c\xc7\x75\xdd\x38\
\x5e\xbd\x41\x76\xa0\xb3\x4d\x92\x1d\xb2\x82\xec\xe3\xca\xb1\xc3\
\x04\x7b\x2b\x37\x4c\xfa\x73\x61\xc6\xbf\x2b\x6f\x15\x58\x9c\x8c\
\x3f\x47\xb8\xcd\xd5\x69\x3d\x5f\xa1\xa6\xa6\x46\xb4\xd9\x6c\x14\
\x9d\x7a\x06\x02\x00\x14\x7d\x58\x56\xf4\x61\x59\x7f\x6e\xd6\x0b\
\xcc\x02\xf8\x1a\x20\x03\xc0\x02\x50\x01\x90\x90\x15\x3b\x75\x45\
\xba\x29\x31\x0c\x5c\x0d\x60\x0c\x1c\x66\xe9\xec\x8e\xaa\xe2\xed\
\xe5\xc0\xe0\x84\x82\x7b\x05\x48\x02\x18\xed\xa9\x79\xf4\x88\xd3\
\xf0\xab\xd5\x87\x4e\xa7\x13\xdc\xc6\xd5\x3d\xac\xe0\x9c\x57\x54\
\x54\xe4\xe4\xe4\xcc\x98\x31\xe3\x86\x1b\x6e\xb8\xfb\xee\xbb\x8b\
\x8b\x8b\x6f\xbd\xf5\xd6\x3d\x7b\xf6\x78\xbc\x5b\x62\x95\x9a\x0d\
\x53\xcf\xd3\x99\x43\x32\xea\x22\xc4\xaa\xaf\x5a\xbe\x5a\x79\x28\
\x26\x2d\x42\x76\x5e\xee\x96\x31\x00\x05\x92\x66\x8d\x18\x9e\x19\
\xe3\x30\x3b\x29\x38\x57\x24\xe5\xd8\x5b\x25\xb2\x43\xea\x9f\x26\
\x73\x81\xa5\xfd\x62\x74\x74\xb2\xc9\xa8\xe0\x0f\xca\x68\xd9\x09\
\xa6\x30\xe5\xe4\x43\x19\xdf\xb5\x39\x2b\x72\x6b\x19\x67\x33\x15\
\x7c\x10\xe0\x29\x80\xda\xde\x98\x51\x5f\x5f\x2f\x5a\xad\xd6\xf6\
\xf6\xf6\xae\x0d\x73\x07\x39\x19\xfd\xb8\xd7\x9e\x21\x00\xc8\x00\
\xb7\x00\x4c\x07\x98\x0a\xf0\x67\x00\x00\xa8\x2d\x6c\xde\xb5\xea\
\x3f\x6e\xd1\x1a\x00\x80\xea\xa5\x73\x04\x06\xd0\x0e\x50\x0c\x30\
\xf6\xf2\xb6\x91\xaf\x40\xcf\x2e\x00\x24\x24\x24\x24\x26\x26\x16\
\x16\x16\x02\x40\x61\x61\x21\xe7\xfc\xea\xab\xaf\xde\xb7\x6f\x1f\
\x1d\x46\xb5\x04\x00\xc0\x18\x7b\xee\xb9\xe7\xf6\xec\xd9\xb3\x6f\
\xdf\xbe\x82\x82\x82\x8d\x1b\x37\x96\x97\x97\xaf\x5a\xb5\x8a\x68\
\xe1\x9e\x0c\xed\x94\x18\xed\x9a\x27\xf5\xd0\x81\x0c\x4e\xef\xa8\
\xec\xae\xf9\xa7\x3f\xaf\xbc\xf5\xcd\x99\x61\xb1\x06\xd9\xa9\x88\
\x46\xe1\xf0\x96\xff\x16\xbe\x7f\xde\xeb\xce\xf3\x80\x93\x9f\x94\
\xa7\xde\x30\x52\x17\xa1\x63\xa8\x30\x60\x92\x02\x7a\x93\x4e\xd4\
\x73\x04\x44\x84\x03\x00\x07\x00\x3c\x06\x71\x9d\xd0\xd4\xd4\x24\
\xb6\xb7\xb7\x3b\x1c\x8e\x9e\x8f\xf3\x07\x27\x00\x40\x61\xc0\x39\
\x7b\x16\xe0\x04\xc0\x5f\x11\xce\x29\x28\x00\x28\x9c\x01\x00\xfe\
\x14\xad\x75\x80\x09\x0c\x65\xa4\xb4\x83\x08\x20\x77\x69\x9e\x2c\
\xcb\xa2\x28\xbe\xff\xfe\xfb\xeb\xd6\xad\x03\x80\x37\xde\x78\xc3\
\x6c\x36\x7f\xfa\xe9\xa7\x8c\xb1\x83\x07\x0f\x16\x16\x16\xbe\xf7\
\xde\x7b\xb7\xdd\x76\x5b\x7d\x7d\xfd\x8a\x15\x2b\xc6\x8d\x1b\xf7\
\xfd\xf7\xdf\x03\x80\x24\x49\xf3\xe6\xcd\x7b\xf0\xc1\x07\x17\x2c\
\x58\x50\x56\x56\x96\x99\x99\x39\x6a\xd4\xa8\x0f\x3f\xfc\x90\xce\
\xa9\xd3\xe9\xd4\xc4\xa2\x28\x8a\xee\x5b\x2d\x09\x82\xe0\xfe\x4f\
\xcf\x15\xf3\x08\xa2\x5e\x54\xba\x04\x11\x24\x81\xad\x55\x96\x96\
\x8a\xf6\xa8\xe4\x70\x6c\x47\x45\x51\xca\xbf\xaf\x65\x02\xe3\xfd\
\x7d\x02\x11\xa0\xfd\xa2\xb5\xf0\x83\xd2\xee\x0e\xa0\x87\xb0\xe7\
\x78\x86\x98\xdd\xd6\xd6\x26\x5a\xad\xd6\x60\x55\x95\x21\x00\xca\
\x68\x03\xd8\x01\x90\xef\x8a\xe8\x3c\x74\x0a\x39\xe3\x6e\x89\x1a\
\xf4\x44\x79\x7a\xb3\x83\x88\x87\x0e\x1d\x8a\x89\x89\x69\x6e\x6e\
\x5e\xbe\x7c\xf9\x85\x0b\x17\xc8\x94\xdc\x75\xd7\x5d\xdb\xb6\x6d\
\x3b\x7e\xfc\x78\x5b\x5b\xdb\xf7\xdf\x7f\x9f\x9f\x9f\x4f\x96\x85\
\x31\xb6\x70\xe1\xc2\xf7\xdf\x7f\x7f\xdf\xbe\x7d\x56\xab\x35\x22\
\x22\xe2\xb3\xcf\x3e\xdb\xb4\x69\x13\xd9\x9a\x86\x86\x86\x4b\x97\
\x2e\xd1\xf9\x2f\x5d\xba\x54\x5f\x5f\xaf\x5e\xce\x6c\x36\xd7\xd5\
\xd5\xa9\x0a\x61\xb7\xdb\x9b\x9a\x9a\xba\xf6\x24\xca\xa8\x78\x4a\
\x31\x21\x03\xc6\x80\xeb\x18\xe3\xc0\x04\x60\x1c\x74\x61\x22\xca\
\xa8\x78\xec\x01\xef\x40\xe9\xe3\xce\x17\x72\x9d\xd0\xfb\x6a\x06\
\xab\xd5\x2a\xda\xed\xf6\xe0\x14\x40\x30\x00\x84\xa4\xeb\xe2\x47\
\xcf\x1d\xd9\x6c\x97\xd9\x8e\x2a\x2c\x69\xf3\x6c\xf4\x7a\xeb\x25\
\x1a\x8c\x2d\x5b\xb6\xbc\xf5\xd6\x5b\xcd\xcd\xcd\x29\x29\x29\xc3\
\x87\x0f\x2f\x2e\x2e\x6e\x6f\x6f\x67\x8c\x49\x92\xc4\x18\x3b\x73\
\xe6\x4c\x56\x56\xd6\xcf\x7e\xf6\x33\x59\x96\x8b\x8a\x8a\xc2\xc3\
\xc3\x55\x27\xb1\xb1\xb1\xf1\xe6\x9b\x6f\x4e\x4d\x4d\x4d\x48\x48\
\xa8\xae\xae\xa6\x9c\x2f\x3d\xf7\x37\xdf\x7c\x33\xb1\x07\x00\x9e\
\x7e\xfa\xe9\x8d\x1b\x37\xaa\x97\x7b\xe7\x9d\x77\x3e\xf9\xe4\x13\
\xb2\xbf\x00\xf0\xcd\x37\xdf\x64\x66\x66\x36\x36\x36\x7a\x5f\xb3\
\x82\x97\xb3\x7b\xe0\x92\x8c\x97\x3f\x3c\xfd\xc6\x65\xb4\x08\x64\
\xd5\x21\x39\x2b\x13\x16\x27\xcd\x7b\x76\x2a\x63\x78\x81\xb1\x69\
\x77\x5e\x55\xff\x50\x41\xed\x89\xe6\x7e\xfb\x31\x66\xb3\xd9\x6c\
\x36\x73\xce\x4b\x4b\x4b\x4b\x4b\x4b\xc1\x15\x85\x83\xcb\x0f\x55\
\x14\xe5\xc4\x89\x13\x00\xc0\x18\xb3\x58\x2c\x94\xd5\x56\x5f\xe0\
\x9d\x3f\x7f\xfe\xfc\xf9\xf3\x70\x79\x89\x61\x63\x63\xa3\x7a\xfe\
\xb6\xb6\x36\xf7\x2a\x29\xf5\x0c\x04\xbb\xdd\x4e\x2f\x39\x87\xc0\
\x74\x0a\x59\x96\x83\x31\xfd\x86\x01\x2a\x28\x1a\x85\xa9\xbf\x4d\
\x57\x1c\x72\x7b\x93\x04\xf5\x76\x53\x94\xee\x67\xbf\x4a\x1b\xd0\
\x59\x19\x53\xe3\x4f\x7a\xa7\xe5\xfe\xd4\x52\x0e\x94\xf2\x10\x44\
\x05\xd5\x0f\xe8\x98\x8c\xcb\x39\x55\x57\xb8\xc7\x29\xee\x87\x75\
\x49\x6c\x77\xf6\x24\x86\x52\x85\x91\x18\xf8\xd2\x64\x32\x14\xc6\
\x18\xbd\x3e\x42\x74\x38\x20\xda\x20\x39\x14\x66\xb7\x2b\x61\xc3\
\xf4\x30\x00\x2d\x55\x1b\xd2\x9d\x86\x77\x0a\x2b\x3a\x7d\xeb\xf1\
\x57\x9d\x42\x8f\xee\xbe\xea\xee\x93\xc1\x0b\x4e\x19\x3d\x08\x38\
\xd9\x19\x03\x19\x59\xa4\xce\xf9\x5c\xe6\xd1\x55\x29\xc5\xc8\x18\
\xf8\xc2\x2e\x6a\xf0\x09\xb8\xc1\x60\x08\x8a\x39\x44\x04\x0e\xe0\
\x50\xf8\x79\x8b\xe9\x82\x2d\x1c\x29\x68\xd3\x10\x02\x30\x18\x0c\
\xa2\x5e\xaf\x0f\x96\x97\xc4\x18\x3a\x40\x7c\xb1\x22\x0b\x15\x34\
\x1a\xfa\xa9\xc1\xa1\x36\xc5\xde\xcb\x9b\x21\x4b\x2a\xdb\x15\x60\
\x0c\x10\x98\xc0\x04\x7d\xa8\xf8\xaa\x46\xa3\x51\x8c\x88\x88\xd0\
\xe9\x74\x56\xab\x35\xc0\xd7\xa6\x57\x44\x3a\x3d\xe8\x50\x41\x40\
\xa1\xef\xe5\x68\xe8\x5a\x7f\x21\xa4\x66\xf3\xd1\xcd\xd0\x8d\xf5\
\x7a\xb0\xfb\x21\xa1\x40\x6c\x22\x74\x78\x78\xb8\x18\x11\x11\x61\
\x30\x18\x02\x79\x6d\xea\x0a\x7b\x9b\x53\x71\x2a\x4c\x64\x8a\x03\
\x11\x81\xeb\x99\x6c\xa3\x92\x2a\x6f\xab\xc0\x04\x41\x88\x8e\x8e\
\xa6\x89\x65\xa1\x33\xf7\x84\xa6\x67\xc5\xc4\xc4\x50\x5e\xa4\x67\
\xb8\x53\x27\x14\x68\x41\x88\x8e\x8e\x16\x8d\x46\x63\x64\x64\x64\
\x7d\x7d\x7d\xe0\xe6\x56\x23\x30\xce\x1c\xed\xce\xd3\x5f\x54\x66\
\x3f\x34\x41\xb6\xc9\x8c\x33\xc9\x26\x9f\xfc\xbf\x65\x00\x5e\xf1\
\x82\xee\xb3\xaa\xaa\x6a\xd2\xa4\x49\x2f\xbe\xf8\xa2\xfa\x82\x23\
\x14\x40\x09\xb4\x84\x84\x84\xad\x5b\xb7\xf6\x7c\x1c\x20\xca\x0e\
\x85\x71\x40\x04\x2e\x30\xde\xdf\x72\x16\x9f\x23\x2e\x2e\x4e\x34\
\x1a\x8d\xb1\xb1\xb1\x41\xb9\xfc\xd9\x1d\x55\x53\x7e\x9d\x0a\x9c\
\x89\x61\x42\xcd\xd1\xa6\xd2\x7d\x17\xc1\xbb\x00\x95\x82\xc9\xc2\
\xc2\xc2\xdb\x6e\xbb\xcd\xfd\xc5\x44\xe8\x40\x9d\x49\x10\x3a\x32\
\xe6\x3d\x12\x12\x12\x44\xda\x21\x13\x82\x91\x8d\x61\x22\x53\x4b\
\x7b\xa8\xa0\xb7\x1f\xa5\x06\x6a\x72\x7a\x30\x42\xb6\xcb\x24\x1b\
\x4c\x60\x22\xb9\x9c\x21\x60\x4a\x12\x13\x13\x39\x00\x24\x24\x24\
\x40\x50\x92\x74\xd8\xe3\x3f\xaf\x04\xb8\x37\x39\x04\x6c\x08\x29\
\xdc\xe8\xd1\xa3\x39\x00\x8c\x19\x33\x26\xd8\xf7\x13\x64\xb8\x17\
\xe7\x05\x08\x0c\x00\x80\x0a\xde\x10\x81\x73\xd6\xef\x52\x59\x1f\
\x02\x11\x05\x41\x48\x48\x48\xe0\x00\x40\x93\x86\xaf\x4c\x90\x46\
\xd2\x14\x92\xc0\x4f\x37\xf5\x53\x21\x4b\xff\xa0\x4e\x5b\x4a\x4a\
\x4a\xe2\x00\x90\x94\x94\x04\x57\xea\x5a\x9c\x14\xc2\x64\x67\x67\
\x67\x64\x64\x5c\x99\x3d\xa0\x82\x68\x91\x98\x98\x38\x6c\xd8\x30\
\x0e\x00\xa9\xa9\xa9\xf4\xe6\x30\x70\xee\x05\x02\x00\xc8\x12\xa2\
\x8c\xa4\xa2\x82\x8e\x07\xd8\xb7\xa1\x74\x64\x62\x62\xe2\x47\x1f\
\x7d\x34\x75\xea\xd4\x0d\x1b\x36\x3c\xfe\xf8\xe3\x70\x05\xef\xa2\
\x42\xa3\x9f\x9c\x9c\xac\xd7\xeb\x39\x00\x8c\x1e\x3d\x7a\xc4\x88\
\x11\x81\xbf\x0f\x45\x42\xc5\xa5\xa2\x5c\xc7\x03\xec\x84\x53\x9e\
\x26\x21\x21\xa1\xbd\xbd\xfd\xcd\x37\xdf\x7c\xf4\xd1\x47\x7f\xff\
\xfb\xdf\x87\x85\x85\x05\xf2\xf1\xe0\xae\x92\x55\x04\xc0\x60\x4b\
\x15\xb5\x9a\x6a\xe5\x39\xad\x40\x95\x96\x96\x06\x01\x7d\x50\x10\
\x00\x24\xab\xa4\x48\xc8\x38\x43\x19\x75\xe1\x22\x17\x03\x1a\xa1\
\x91\xc9\x38\x71\xe2\xc4\xef\x7e\xf7\x3b\x92\x8d\x92\x92\x12\x87\
\xc3\x11\xa0\xb4\x1e\x02\x00\x08\x7a\x01\x69\xf6\x9c\x8c\xb2\x3d\
\x24\x32\x1c\x34\x43\x9f\x53\xbe\x25\x33\x33\x13\x02\x18\xa3\x52\
\xaf\x3b\x2d\x92\xd3\x22\x51\x39\x96\xde\x24\xea\x22\x04\x08\x78\
\xdc\x4e\xaf\x09\xc3\xc2\xc2\x1e\x7f\xfc\xf1\xf5\xeb\xd7\xcb\xb2\
\x1c\xa0\x4e\x40\x04\x00\x7d\x94\x0e\x65\x04\xce\x14\xa7\xe2\xb4\
\xca\x00\xc1\x8c\xd2\x89\x09\x93\x26\x4d\x02\x35\x58\xbe\xe6\x9a\
\x6b\x02\x7a\x0b\xe4\x5b\xd8\x15\x4b\xbd\x8d\xeb\x98\x22\x29\x86\
\x28\x5d\x64\x62\x18\x63\x01\x7d\x37\xc0\x18\x93\x65\x39\x3c\x3c\
\xfc\x4f\x7f\xfa\xd3\xe6\xcd\x9b\x0f\x1c\x38\x40\x46\x24\x00\x97\
\x46\x04\xc6\x98\x29\xc1\x88\x32\x72\xce\x64\x87\x62\x6d\xec\x61\
\x16\xa0\xdf\xc1\x5c\x2b\xe0\x66\x64\x64\x00\x40\xc7\xd6\x21\xb4\
\xd8\x43\x20\x33\xb5\x34\x13\xa4\xa5\xdc\xcc\x45\xae\x48\xa8\x37\
\x89\x23\xb2\x62\x10\x81\x8b\x7d\x5f\x45\xa3\x5f\x7f\x5c\xe0\x8c\
\xb3\x09\x19\x13\x76\x7c\xb9\xc3\x66\xb7\x01\x83\xbf\xff\xfd\x95\
\xe9\xd9\xd3\x19\x67\x82\x28\xf8\xf7\xd2\x22\x63\x9c\x45\x8c\x34\
\x46\x8d\x09\x97\xec\x32\xd7\x31\x6b\xb3\xdd\xd2\xe0\xc5\x0a\x16\
\xfe\x1b\x0e\xc6\x00\x60\xfc\xf8\xf1\xc3\x87\x0f\xef\x98\x65\x09\
\x00\x13\x27\x4e\x4c\x48\x48\xa0\x7f\x07\xf2\x6e\x6a\x0e\x37\x02\
\x4d\xf8\xb7\xc9\x93\xef\x4b\x0d\x8f\x37\xc8\x0e\x05\x15\x0c\xc0\
\x9f\x22\x2b\x8a\xac\x24\xc4\x8d\x3c\x53\x7c\x36\x32\x2c\xea\xd7\
\xf7\x3d\xa0\x63\x86\x92\x53\xe7\x50\x41\x59\x92\xfd\x7b\x69\x09\
\x51\xc1\x89\x77\x8d\x35\xc6\xea\x65\xa7\x22\x18\x84\xc6\x33\x6d\
\x4e\x8b\xcc\x78\xd0\x8c\x08\x8d\xfb\xb4\x69\xd3\x48\x41\x45\x2a\
\x85\x8d\x8a\x8a\x9a\x32\x65\xca\x9e\x3d\x7b\x02\xe7\x5e\x28\x08\
\x00\x15\xdf\xd7\x99\x2f\x5a\xf5\x51\x3a\xa7\x55\x8e\xb9\xca\xb4\
\x64\xeb\xec\xd3\xff\xaf\xb2\xb6\xa8\xc5\x5a\x6f\x93\x1c\x8a\x5f\
\xfb\x88\x0a\x7d\xff\x73\xee\x40\xde\x9a\xdc\x8e\xf9\xd1\x00\xa6\
\x28\x43\x74\x72\x84\x1f\xaf\x0a\x20\x86\x09\x51\xa3\xc3\x93\xaf\
\x4f\x98\xb0\x78\x8c\xa3\x5d\x62\x0c\xb8\xc0\x4a\xbf\xb9\x08\xe0\
\x9a\x9f\x1e\x0c\x90\x4a\xcd\x9e\x3d\xbb\xe3\x26\xc1\x35\xaf\x72\
\xf6\xec\xd9\x81\xa4\x05\x95\x24\x59\x9b\x1c\x27\xde\x3b\x97\xb3\
\x2e\xcb\x5c\x6b\x73\x5a\xa4\xc8\xd1\xe1\x33\x1f\x9d\x28\x3b\x14\
\xfa\x0b\x40\x1f\x51\x35\xb8\xfa\x4f\x45\x96\xbd\x58\x1a\x64\x40\
\x17\x14\x0d\x5c\x30\x08\x8c\x83\xa3\x5d\x52\x9c\x8a\x21\x4a\x5f\
\x7f\xb2\xe5\xdc\xae\x6a\x2a\x88\xf7\xe7\xa5\xbb\xbf\x27\x52\x08\
\x51\x9c\x31\x63\x06\xd0\x6a\x52\xe0\xb2\x2b\x39\x39\x39\x10\xd8\
\x5c\x27\x2a\xc8\x38\x3b\xf1\xbf\xcf\x45\x8f\x8d\x98\x72\x7f\xaa\
\xbd\xcd\x29\x59\x65\xa7\x59\x62\x1c\x18\x63\x5c\xe8\x6d\x29\x35\
\x5f\xdd\x06\xfc\xd4\x64\x26\xb0\x6e\x97\xe8\xf2\x11\x64\x87\x22\
\xd9\x64\xf2\xa2\x8c\x31\x7a\x5b\x8b\xe3\xbb\xa7\x7e\x90\x6c\x32\
\xe3\x41\x4b\x5d\x90\xbf\x39\x61\xc2\x84\x8e\xa4\x05\xd1\x82\x1e\
\x97\x6b\xae\xb9\x66\xc4\x88\x11\x75\x75\x75\x3e\x5f\xcb\xb7\x5b\
\x60\x87\x76\xe5\xae\x2f\x6c\x3e\xd7\x96\xf5\xab\x71\x51\x63\xc2\
\xb9\xc0\x50\x46\xcf\xb3\x0e\x87\x04\x18\x67\x8c\x03\xe3\x4c\xb6\
\xcb\x95\x07\xeb\xbf\xdf\xf8\x63\x53\x49\x9b\x9f\x26\x7f\x7b\x09\
\x9a\x3b\xf3\xf3\x9f\xff\x5c\x14\x45\x59\x96\x05\x41\xe8\x50\x0b\
\x59\x96\x23\x23\x23\x73\x72\x72\xb6\x6f\xdf\x1e\x38\x5a\xa8\x60\
\x50\xb8\xb5\xf4\xd4\xbf\x2a\xc7\xcc\x88\x1f\x31\x39\x26\x7a\xac\
\xc9\x18\xad\x13\xf4\x81\xce\x7b\x06\x02\x08\xb2\x5d\xb1\x34\xda\
\x9b\xcf\xb5\x55\x1f\x69\xac\x39\xda\x04\x7e\x5b\x10\xc0\x7b\xd0\
\x8c\xa9\x5f\xfc\xe2\x17\x3f\x7d\x44\x93\x6a\x68\xcf\x99\x77\xde\
\x79\x07\x82\x34\x5d\xce\xfb\x75\x02\x87\x18\x82\xde\x70\x72\x21\
\xe2\xe2\xe2\xea\xeb\xeb\xd1\xb5\x0f\xd5\x65\x9b\x52\x55\x54\x54\
\xd0\xd2\x41\xc1\xa9\xaf\x57\x97\x95\x1c\xd2\xfb\xb0\xd2\x42\x9c\
\xbc\x2f\x2b\x66\xfa\x15\x34\x31\x73\xf1\xe2\xc5\xe8\xb6\x71\xb2\
\xba\x2c\x1c\x53\x14\x25\x29\x29\x69\xd6\xac\x59\x2c\x58\x5b\xc3\
\x61\xc7\xca\x92\x38\x38\xf6\x7e\xeb\x27\x10\x29\x6b\x82\xa1\xe3\
\x3c\x21\xe2\x92\x25\x4b\xa0\xeb\x86\x97\xaa\x1d\xf9\xc7\x3f\xfe\
\x01\x43\x62\xda\xb5\x06\x6f\xa0\x96\xde\x54\x57\x57\xab\x46\xe3\
\x27\x23\xa2\x0a\x48\x55\x55\x55\x44\x44\x04\x04\xcb\x8e\x68\x08\
\x2c\x68\xad\x9f\x3b\xee\xb8\x83\x66\x61\xa9\x64\xf8\x89\x16\x2a\
\x33\x96\x2c\x59\xc2\x18\xd3\x04\xe3\x4a\x00\x8d\xf2\xb6\x6d\xdb\
\x54\x73\xe1\x81\x16\xf4\xc5\xf6\xed\xdb\xe1\x0a\x2e\x52\xba\x72\
\x40\x43\x3c\x66\xcc\x98\xf6\xf6\x76\x77\x0b\xd2\x99\x16\x54\xe9\
\x6a\x36\x9b\xc7\x8e\x1d\x0b\x1a\x33\x86\x3a\xc8\x82\xac\x5a\xb5\
\xaa\x93\x54\x74\xa6\x85\xfa\xf5\xda\xb5\x6b\xd5\x9f\x69\x18\xaa\
\x60\x8c\xe9\x74\xba\xa2\xa2\x22\xf7\xd0\xd4\x33\x2d\xe8\xeb\x92\
\x92\x12\xa3\xd1\x18\x52\x0b\x04\x68\xf0\x2d\xc8\xab\xb8\xf1\xc6\
\x1b\xbb\x72\xc2\x03\x2d\xd0\xe5\x91\xde\x7d\xf7\xdd\xa0\x45\xaa\
\x43\x17\xe4\x21\xec\xd8\xb1\x03\x2f\x8f\x41\x7a\xa1\x05\xad\x66\
\xaa\xb9\x17\x43\x12\x94\xd9\x9c\x3c\x79\xb2\xd3\xe9\x74\xf7\x34\
\x7b\xa2\x05\xa9\x8a\xa2\x28\xf3\xe7\xcf\x07\xcd\xc3\x18\x8a\x20\
\x23\xf0\xfe\xfb\xef\x7b\x94\x8a\x6e\x69\x41\x87\x7e\xf7\xdd\x77\
\xa0\x09\xc6\x90\x03\x49\x45\x7a\x7a\xba\xcd\x66\xa3\xd8\xd3\x5b\
\x5a\xa0\xcb\x0d\x21\xc1\xd0\x3c\x8c\xa1\x04\x1a\xcd\x37\xdf\x7c\
\xb3\x3b\xa9\xe8\x89\x16\xf4\x83\xdc\xdc\x5c\xd0\x04\x63\x08\x81\
\xa4\x22\x33\x33\xd3\x62\xb1\x90\xab\xd0\x37\x5a\xa8\x82\xb1\x60\
\xc1\x02\xd0\x04\x63\xa8\x80\xc6\xf1\xc3\x0f\x3f\xec\x41\x2a\x7a\
\xa1\x05\xfd\xec\xe8\xd1\xa3\xa2\x28\xd2\xde\x2d\xc1\x6e\x94\x86\
\x01\x81\x38\x91\x9d\x9d\x4d\x3b\x83\xf6\x30\xf4\x3d\xd1\x42\x65\
\xc6\x03\x0f\x3c\x00\x9a\x60\x0c\x7e\x90\x33\xb0\x6f\xdf\xbe\x9e\
\xa5\xa2\x77\x5a\x90\xf9\xa9\xac\xac\x8c\x89\x89\xd1\x04\x63\x50\
\x83\x9e\xea\xbb\xee\xba\xab\x57\x4e\xf4\x4e\x0b\xf5\x14\x2f\xbd\
\xf4\x12\x68\x82\x31\x68\x41\x15\x77\x91\x91\x91\x65\x65\x65\xb4\
\x7b\xfb\x40\x69\xa1\x28\x8a\x24\x49\x0e\x87\x63\xfa\xf4\xe9\xa0\
\x31\x63\x70\x82\x46\x6d\xf3\xe6\xcd\xde\x48\x85\x57\xb4\x50\x4f\
\x74\xe8\xd0\x21\xda\x74\x23\xd8\x6d\xd4\xd0\x37\xa8\x9e\xa6\x24\
\x49\x92\x24\x75\x17\x94\xf6\x99\x16\x2a\x33\x1e\x7d\xf4\x51\xd0\
\xd2\xe1\x83\x0a\x54\x68\x27\x8a\xe2\xe1\xc3\x87\xd1\x3b\xa9\xe8\
\x03\x2d\xc8\x20\x59\x2c\x96\x8e\x65\x31\xb4\x04\xd7\x20\x01\x3d\
\xc3\xeb\xd6\xad\xf3\x9e\x13\x7d\xa0\x05\xba\xb2\x5b\x47\x8e\x1c\
\xd1\xe9\x74\x94\x2c\x0b\x76\x93\x35\xf4\x02\x32\x1f\xb3\x67\xcf\
\xf6\xde\x7c\xf4\x99\x16\xe8\xaa\xdd\x7a\xe1\x85\x17\x40\x33\x25\
\x21\x0f\x5a\x83\x36\x32\x32\xf2\xf4\xe9\xd3\xe8\xa9\xd6\xc6\x67\
\xb4\x40\x97\x10\xdd\x72\xcb\x2d\xa0\x45\x25\x21\x0c\xc6\x18\x3d\
\xb7\x5b\xb7\x6e\xc5\xbe\x98\x8f\x7e\xd2\x82\x5e\xc5\xd6\xd7\xd7\
\x6b\x65\xc0\xa1\x0c\xe2\xc4\xca\x95\x2b\xb1\x4b\xf9\xae\x5f\x68\
\x81\x2e\xea\x1d\x38\x70\x80\x36\xb4\xd2\x9c\x8c\x50\x03\xa9\xf8\
\xcc\x99\x33\x1d\x0e\x47\x9f\x5c\x8a\x01\xd1\x02\x5d\x04\x7c\xeb\
\xad\xb7\x40\x73\x32\x42\x0c\xa4\xdf\xa3\x46\x8d\xaa\xa8\xa8\xc0\
\x3e\xba\x14\x03\xa5\x85\xca\x8c\x3f\xfe\xf1\x8f\xa0\x31\x23\x64\
\x40\x49\xee\xb0\xb0\xb0\xfd\xfb\xf7\x63\xdf\x5d\x0a\x1f\xd0\x82\
\x92\xe2\x88\xb8\x74\xe9\x52\xd0\x98\x11\x02\x50\xa7\x88\x7e\xf0\
\xc1\x07\xd8\x2f\x97\xc2\x07\xb4\x40\x57\x8e\xcb\x6c\x36\xd3\x0a\
\x6d\x5a\x60\x12\x5c\xd0\xfe\x5c\x9b\x36\x6d\x1a\x20\x27\x06\x4a\
\x0b\x74\x99\xae\x86\x86\x86\x89\x13\x27\x82\xa6\x19\xc1\x03\xf5\
\xfc\x9a\x35\x6b\x10\xd1\xe1\x70\x0c\x70\x58\x07\x4a\x0b\x74\x19\
\xb0\xf3\xe7\xcf\x5f\x75\xd5\x55\xa0\x69\x46\x30\x40\x3a\xb1\x62\
\xc5\x0a\x1a\x8e\x7e\x84\x1e\xbe\xa7\x05\xba\x98\x71\xe6\xcc\x19\
\x8d\x19\x81\x07\xe9\xc4\xbd\xf7\xde\x8b\x3e\xe2\x04\xfa\x8a\x16\
\xe8\x32\x66\x2a\x33\x34\x6b\x12\x18\x50\x3f\xdf\x77\xdf\x7d\xe8\
\x2a\xa5\xf3\xc9\x68\xfa\x8c\x16\xe8\xa6\x19\xb4\xf9\x99\xc6\x0c\
\x7f\x83\x7a\xf8\xd7\xbf\xfe\x35\xf9\xfe\xfd\x4b\x51\x78\x84\x2f\
\x69\x81\x6e\x7e\x46\x56\x56\x16\x68\xcc\xf0\x1b\xd4\x58\xf4\x91\
\x47\x1e\x41\x9f\xea\x04\xc1\xc7\xb4\x40\x17\x33\x9a\x9a\x9a\xe6\
\xcc\x99\x03\x1a\x33\xfc\x00\x75\x7b\xce\x0d\x1b\x36\xa0\xef\xfc\
\x09\x77\xf8\x9e\x16\xe8\x62\x46\x7b\x7b\xfb\x3d\xf7\xdc\x03\xae\
\x99\x4c\xc1\xee\xcc\x21\x02\x12\x09\x41\x10\xde\x7e\xfb\x6d\x44\
\xec\x6e\xca\xf9\x00\xe1\x17\x5a\xa0\x5b\x2a\x7e\xcd\x9a\x35\xd4\
\x1e\xed\x5d\xeb\xc0\x41\xd2\x1b\x1f\x1f\xbf\x7b\xf7\x6e\x1c\x70\
\xce\xaa\x07\xf8\x8b\x16\xe8\xca\x81\x22\xe2\x3b\xef\xbc\x13\x16\
\x16\x06\x9a\x41\x19\x00\x54\x67\x62\xda\xb4\x69\xa7\x4e\x9d\x42\
\x7f\x72\x02\xfd\x4a\x0b\x74\x7b\x6f\x92\x9f\x9f\x9f\x9e\x9e\x0e\
\x9a\x41\xe9\x17\x54\xa1\xfd\xe5\x2f\x7f\xd9\xda\xda\x8a\x7e\xe6\
\x04\xfa\x9b\x16\x04\x6a\x43\x43\x43\xc3\x1d\x77\xdc\x41\xcd\xd3\
\xf2\x5d\xde\x83\x24\xd6\x68\x34\xfe\xfd\xef\x7f\xa7\xfe\xf4\x61\
\x20\xda\x1d\x02\x41\x0b\x74\x7b\xc3\xfb\xf2\xcb\x2f\xd3\x6a\xf3\
\xa2\x28\x6a\xb2\xd1\x33\xd4\x88\x23\x2b\x2b\xab\xa0\xa0\x00\xfd\
\x13\x74\x78\x44\x80\x68\x81\x6e\xae\xc6\xe1\xc3\x87\xaf\xbd\xf6\
\x5a\x6a\xb9\x26\x1b\xdd\x41\xf5\xc3\x1e\x7a\xe8\xa1\xb6\xb6\x36\
\x1c\x40\xf1\x44\x3f\x10\x38\x5a\x10\xc8\xa0\xd8\xed\xf6\x75\xeb\
\xd6\xd1\x0b\x1e\x4d\x36\x3a\x41\x7d\x54\x32\x32\x32\x28\xe2\xc0\
\xc0\x72\x02\x03\x4f\x0b\x74\x33\x8d\x05\x05\x05\xd7\x5f\x7f\x3d\
\x75\x81\x46\x0e\x00\x50\xe7\x72\x0a\x82\xb0\x7a\xf5\xea\x4b\x97\
\x2e\x61\x00\x0d\x87\x3b\x82\x40\x0b\x44\x54\x14\x85\x64\x43\x51\
\x94\x2d\x5b\xb6\x8c\x1c\x39\x92\xfa\xe5\x8a\xb5\x29\xee\x6b\xef\
\x5f\x7f\xfd\xf5\xf9\xf9\xf9\xd4\x51\x01\x16\x09\x15\xc1\xa1\x05\
\x41\xcd\xe4\xd7\xd4\xd4\x3c\xfc\xf0\xc3\x06\x83\xa1\x53\x07\x5d\
\x09\x70\x6f\xef\xb8\x71\xe3\xde\x7d\xf7\x5d\xea\x9c\xa0\x88\x84\
\x8a\x60\xd2\x82\xa0\x3e\x10\xc7\x8e\x1d\x5b\xb6\x6c\x99\x7b\x67\
\x0d\x6d\xb3\xe2\x4e\x88\xb8\xb8\xb8\x8d\x1b\x37\x36\x37\x37\xa3\
\x9b\x6f\x1e\x44\x04\x9f\x16\xe8\x96\xf5\x42\xc4\xdc\xdc\x5c\x5a\
\xc4\x8d\x30\x24\x7d\x0e\xf7\xf5\x20\x62\x63\x63\x1f\x7b\xec\x31\
\x2a\xde\xc7\xe0\x59\x8d\x4e\x08\x09\x5a\x10\x64\x59\x56\x3b\x65\
\xef\xde\xbd\x4b\x97\x2e\x55\xb3\x7b\x82\x20\x0c\x81\x57\x2a\x24\
\x0f\x2a\x21\x12\x12\x12\x3a\x11\x22\x88\x56\xa3\x13\x42\x88\x16\
\x04\xf7\xde\xf9\xcf\x7f\xfe\xb3\x62\xc5\x8a\x98\x98\x18\xea\x47\
\x7a\xc8\x06\xa3\x78\x70\xce\xdd\xdf\x07\x65\x64\x64\x6c\xde\xbc\
\x99\x36\x98\xc4\x10\x23\x04\x21\xe4\x68\x41\x90\x24\x49\xb5\xaf\
\x15\x15\x15\x7f\xf9\xcb\x5f\xa8\xb2\x9c\x40\xcf\x5c\xe8\xf3\x83\
\xd8\xa0\xde\xa7\xc1\x60\x58\xb4\x68\xd1\xf6\xed\xdb\x6d\x36\x9b\
\xda\xcc\x50\x23\x04\x81\x61\x08\xef\x2d\x49\x5d\x46\xaa\xeb\x70\
\x38\xbe\xf9\xe6\x9b\x8f\x3f\xfe\x78\xe7\xce\x9d\xf5\xf5\xf5\x74\
\x00\x7d\x85\x88\x81\xde\xe6\xb9\x7b\xd0\xbc\x2e\xda\x88\x5a\xed\
\xdb\xcc\xcc\xcc\x3b\xee\xb8\xe3\x9e\x7b\xee\xa1\x45\x63\x00\x40\
\x96\xe5\x50\x5e\xb9\x30\xa4\x69\x41\x70\x27\x07\x00\xd4\xd7\xd7\
\xef\xdc\xb9\xf3\xb3\xcf\x3e\xcb\xcd\xcd\x6d\x6e\x6e\x56\x0f\x13\
\x45\xd1\x9d\xef\x81\xbc\x43\xda\x8f\x87\x76\x2a\x97\x65\x59\xfd\
\x3c\x2d\x2d\xed\xa6\x9b\x6e\x5a\xb2\x64\x49\x4e\x4e\x0e\xa5\x74\
\xa9\x2d\xa1\x4c\x08\xc2\x20\xa0\x05\x41\x95\x04\x95\x1f\xb5\xb5\
\xb5\x79\x79\x79\xbb\x76\xed\xca\xcb\xcb\x2b\x29\x29\x71\x3f\x98\
\x4c\x8c\x9f\x58\x42\x23\xca\x5c\xa0\x95\x1d\xd4\x6f\x0d\x06\x43\
\x56\x56\xd6\x82\x05\x0b\x6e\xba\xe9\xa6\xe9\xd3\xa7\x53\xa1\x09\
\x00\xc8\xb2\x1c\xb4\x7d\x87\xfb\x8e\x41\x43\x0b\x15\xf4\x44\xaa\
\x6f\x17\x01\xc0\x6a\xb5\x16\x15\x15\xed\xdf\xbf\xff\xc0\x81\x03\
\x27\x4e\x9c\x28\x2b\x2b\xeb\xd4\x28\xf7\x0c\x01\x7d\xe5\x25\x57\
\xdc\x19\xe0\x7e\xf5\x4e\x87\x85\x85\x85\x65\x64\x64\x64\x67\x67\
\xcf\x9d\x3b\x77\xc6\x8c\x19\x54\xf8\x4e\xa0\x83\x43\x5f\x1e\x3a\
\x61\xf0\xd1\x42\x45\x57\xfd\x00\x00\x8b\xc5\x72\xee\xdc\xb9\x13\
\x27\x4e\x1c\x3f\x7e\xbc\xa8\xa8\xa8\xa4\xa4\xa4\xba\xba\xda\xe1\
\x70\xf8\xf6\xd2\xd1\xd1\xd1\x29\x29\x29\x69\x69\x69\xd3\xa6\x4d\
\xcb\xca\xca\x9a\x3c\x79\x72\x72\x72\xb2\xfb\x01\x92\x24\xa9\x4e\
\x86\x6f\x2f\x1d\x18\x0c\x62\x5a\xa8\xa0\x47\x5f\x51\x94\xae\x89\
\x73\xab\xd5\x5a\x57\x57\x57\x5a\x5a\x5a\x55\x55\x55\x56\x56\x56\
\x5e\x5e\x5e\x5b\x5b\xdb\xd8\xd8\xd8\xd2\xd2\xd2\xda\xda\x6a\x36\
\x9b\x69\xad\x31\x77\x01\xa0\xe5\x85\x04\x41\xd0\xeb\xf5\x51\x51\
\x51\x51\x51\x51\x71\x71\x71\xf1\xf1\xf1\xa3\x46\x8d\xba\xea\xaa\
\xab\x92\x93\x93\xc7\x8e\x1d\x9b\x9c\x9c\x1c\x1f\x1f\xdf\xe9\x36\
\xc8\xc7\x74\x97\xb1\xc1\x8b\xa1\x40\x0b\x77\xa8\x14\x01\xb7\x32\
\x96\xae\x70\x38\x1c\x36\x9b\xcd\xe1\x70\x98\xcd\x66\x9b\xcd\x46\
\x11\x23\xb9\x23\xa2\x28\x1a\x8d\xc6\xb0\xb0\xb0\xb0\xb0\x30\xa3\
\xd1\x68\x30\x18\xba\x7b\x47\x43\x3c\x60\x6e\xf0\x63\xc3\x02\x8b\
\xff\x0f\x81\x99\x66\x42\x17\xac\xab\x60\x00\x00\x00\x00\x49\x45\
\x4e\x44\xae\x42\x60\x82\
\x00\x00\x06\x3d\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x64\x00\x00\x00\x64\x08\x06\x00\x00\x00\x70\xe2\x95\x54\
\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\x00\x00\x00\
\x09\x70\x48\x59\x73\x00\x00\x0e\xc1\x00\x00\x0e\xc1\x01\xb8\x91\
\x6b\xed\x00\x00\x05\xd2\x49\x44\x41\x54\x78\x5e\xed\x9c\xd7\xaa\
\x2c\x45\x14\x86\xb7\x39\x1c\x0c\x18\x41\x0c\x88\x01\x44\x14\x11\
\x11\xc1\x7c\x21\xde\x0b\x5e\x8b\x5e\xf9\x04\x3e\x84\x4f\xe1\x03\
\x28\x82\x07\x3c\xc7\x9c\x15\x45\xcc\x01\x73\x02\x73\xce\xf9\xf8\
\x7f\x38\x05\x65\x33\xf6\xee\xde\xd3\x55\xf3\x77\xcd\xfa\xe1\x63\
\xce\xde\x67\x76\xf7\xaa\xfa\x6b\xad\xaa\xee\xa9\x9e\xad\x01\xda\
\x37\x13\xfe\x10\x37\x88\xe6\xb5\xac\xf1\xae\xfc\x2d\x6e\x16\x4d\
\x6b\x59\xc3\x9d\x69\xde\x94\x65\x8d\x76\xa7\x69\x53\xba\x8d\x75\
\x53\x37\xbe\x44\xb3\xa6\x74\x1b\xea\xa6\x6e\x7c\x39\x4d\x9a\xd2\
\x6d\xa4\x9b\xba\xf1\xfd\xb5\xe4\xe7\x9b\x44\x33\xca\x1b\x07\x6e\
\xea\xc6\x77\xa3\xe8\x9a\xd2\x54\xa6\xe4\x0d\x03\x37\x2d\x8b\xaf\
\x69\x53\xf2\x46\x81\x9b\xfe\x2f\xbe\x66\x4d\xc9\x1b\x04\x6e\xea\
\x8b\xaf\x49\x53\xf2\xc6\x80\x9b\xb6\x8b\xaf\x39\x53\xf2\x86\x80\
\x9b\x86\xc4\xd7\x94\x29\x79\x23\xc0\x4d\x43\xe3\x6b\xc6\x94\xbc\
\x01\xe0\xa6\x31\xf1\x35\x61\x4a\x1e\x3c\xb8\x69\x6c\x7c\xb3\x37\
\x25\x0f\x1c\xdc\xb4\x93\xf8\x66\x6d\x4a\x1e\x34\xb8\x69\xa7\xf1\
\xcd\xd6\x94\x3c\x60\x70\xd3\x2a\xf1\xcd\xd2\x94\x3c\x58\x70\xd3\
\xaa\xf1\xcd\xce\x94\x3c\x50\x70\xd3\x14\xf1\xcd\xca\x94\x3c\x48\
\x70\xd3\x54\xf1\xcd\xc6\x94\x3c\x40\x70\xd3\x94\xf1\xcd\xc2\x94\
\x3c\x38\x70\xd3\xd4\xf1\xd9\x9b\x92\x07\x06\x6e\x2a\x11\x9f\xb5\
\x29\x79\x50\xe0\xa6\x52\xf1\xd9\x9a\x92\x07\x04\x6e\x2a\x19\x9f\
\xa5\x29\x79\x30\xe0\xa6\xd2\xf1\xd9\x99\x92\x07\x02\x6e\xea\xc6\
\x57\x0b\x4c\x9a\x7c\x2f\xf1\x7e\x8b\xd7\x3e\x71\xf2\x5c\x43\xfe\
\xa6\xa6\xba\xf1\xd5\xd4\x9f\xe2\xa0\x7f\xff\x39\x8d\xc2\x90\xd5\
\x35\x69\x7f\xec\xbf\x78\x0d\x99\xa8\x85\x0c\xa9\xad\xa2\xfd\x11\
\x19\x62\xa6\x30\xc4\x4c\x8e\x25\x8b\xe3\x1f\x2a\x76\x2d\x5e\xfb\
\xc4\x63\x6c\x3f\x8a\x5f\x04\xd7\x06\x35\x54\xb4\x3f\x1c\x0d\x61\
\x19\x79\xa2\x38\x4d\x9c\xc0\x2f\x7a\xf4\xbd\x78\x47\x7c\x22\x7e\
\x17\xdd\x58\x4b\x68\xe3\x0c\x21\x33\xce\x13\x97\x2d\x5e\xfb\xf4\
\x91\xb8\x5f\x3c\x2f\x7e\x12\x5c\x17\x94\xd6\xc6\x19\x72\xb4\xb8\
\x52\x5c\x2f\xae\xe0\x17\x3d\x7a\x43\xdc\x26\xee\x15\xdf\x09\xb2\
\xa4\xb4\x8a\xf6\x87\xe3\xa4\x4e\x4c\x87\x8b\xe3\xc4\x29\xdb\x40\
\x69\x23\xa3\x0e\x10\xa5\x07\x4a\x15\xc5\x2a\xcb\x4c\x61\x88\x99\
\xc2\x10\x33\x85\x21\x66\x0a\x43\xcc\x14\x86\x98\x29\x0c\x31\x53\
\x18\x62\xa6\x30\xc4\x4c\x61\x88\x99\xc2\x10\x33\x85\x21\x66\x0a\
\x43\xcc\x14\x86\x98\x29\x0c\x31\x53\x18\x62\xa6\x30\xc4\x4c\x61\
\x88\x99\xc2\x10\x33\x85\x21\x66\x0a\x43\xcc\x14\x86\x98\x29\x0c\
\x31\x53\x89\x8d\x72\xec\x91\x3a\x4c\x9c\x2a\xd8\x79\x78\xac\x18\
\x63\x3c\xfb\xac\xce\x11\x17\x2f\x5e\xfb\xf4\xb1\x78\x54\xbc\x22\
\xc6\xec\x5c\x64\x1f\x30\x8f\xa4\xb1\xe3\xf1\x7d\xf1\x8d\x60\x9f\
\xf0\x10\xcd\x6e\xe7\x22\x86\xd0\xa9\x67\x89\xcb\xc5\xb9\x82\x0d\
\x6d\x07\x8b\x21\xe2\x7d\x98\x78\x92\x60\xb3\x5c\x9f\x7e\x10\x6c\
\x27\xfd\x42\xd0\xa1\x74\xf2\x76\xe2\x7d\xec\x72\xfc\x40\x3c\x28\
\x5e\x17\xe9\xef\x87\x68\x76\x86\xf0\xff\x74\xea\xc9\xe2\x12\x71\
\x95\xb8\x48\xd0\xb9\xe9\x79\xbc\xbe\x63\xa4\xbf\x67\xe7\xfb\x21\
\xfc\xa2\x47\x64\x04\x3b\xdf\x7f\x13\x7d\xbb\xdf\x53\x1b\x78\xff\
\xb7\xe2\x2d\xc1\x9e\xe0\xa7\xc4\x7b\x02\x83\x86\xee\x9e\x9f\x9d\
\x21\x49\x47\x88\x33\x05\x86\x5c\x2b\xce\x17\x98\x42\x06\xd5\x9c\
\xbb\x52\xfc\xbc\x7e\x2d\x30\xe3\x09\x71\xbb\xc0\x8c\x31\xe5\x0a\
\x15\x35\xa4\x64\xc7\x50\xd3\xdf\x16\x0f\x88\xbb\xc4\x6b\x82\x12\
\x93\x3f\xf3\x5d\x5a\xb9\x19\xbf\x8a\x14\xcf\x6e\xc1\xbc\x83\x41\
\x63\xcc\x28\xae\x92\x86\x50\x02\x7e\x16\xd4\xf8\x67\xc4\xdd\x82\
\x91\xf9\xa9\xa8\xf5\x70\x0d\xe2\x5c\x94\xb4\xe7\x04\x66\x3c\x2e\
\xde\x14\x94\xba\x1a\x8f\x2f\x8c\x52\xe9\xd2\x41\x36\xf0\x50\xcd\
\xbb\x82\xd5\x10\x93\xe8\xcb\xe2\x33\xc1\xc8\xa4\xb3\x4a\x65\x0a\
\xc7\xe5\x1c\xcc\x19\x18\xc0\xf9\x1f\x13\x64\xea\x57\xa2\xe6\xa0\
\x18\xac\x1a\xb5\x1c\x53\x98\x34\xe9\x14\x46\xe7\x7d\x82\xd1\x4a\
\x09\x29\x59\xb6\x38\x36\x59\xc0\x13\x56\x94\x28\x06\x03\x65\xea\
\x73\x61\x55\xa6\x72\xd5\x9a\x5c\x53\xa6\x24\x53\x1e\x16\x2f\x89\
\x2f\x05\x9d\x33\x95\x31\x1c\x07\x18\xfd\x9c\x8f\x09\xfc\x49\xb1\
\x57\x90\x99\x98\x41\xf9\xb2\x55\x2d\x43\x92\x98\x53\xb8\x10\xc3\
\x94\x3b\x04\xa6\x50\x3e\xd2\xf3\x81\xab\x18\x93\xfe\x16\x33\x38\
\x0f\xe6\x33\x67\xf0\x74\x15\x4f\x5a\x51\xba\xec\xe6\x8c\xae\x6a\
\x1b\x42\x87\xb0\xcc\xa4\xb3\x1e\x11\x0f\x89\x94\x29\x53\xd4\x74\
\x8e\xc1\xea\x8e\x8b\x3d\x4c\x67\xce\x78\x41\xb0\x9a\xaa\xf5\x50\
\xe8\x4a\xaa\x6d\x08\x4a\xe5\x8b\x25\x28\xf3\x09\x17\x68\x4c\xb4\
\xe9\xe2\x6c\x27\x99\xc2\xfb\x39\x6e\x5a\xd5\x31\x5f\xdc\x23\x5e\
\x14\x5c\x85\x4f\x61\x76\x15\xad\xc3\x10\x44\xe7\x31\x92\x99\x70\
\xa9\xf1\x98\xc2\xd2\x38\xad\xbc\xc6\x0a\x43\x98\xc0\x29\x4d\x7b\
\x04\x99\x87\xc9\x64\x9e\x7d\x99\xca\xb5\x2e\x43\x10\x1d\x9f\x32\
\x05\x53\xe8\x44\xca\x0b\x23\x9a\x89\x77\x48\x96\xf0\x9e\x74\x1c\
\xcc\xe0\x3a\x87\x79\xe3\x55\x91\x8e\x33\x2b\x95\xbc\x75\x32\x54\
\xdc\xb7\x3a\x46\x9c\x21\x2e\x15\xd7\x08\xee\xf2\x72\x9b\x25\xbf\
\x21\x99\x9f\x37\xc5\x44\xa6\x91\x19\xac\xa6\x30\x94\x6b\x0d\xee\
\xe0\x8e\x31\x75\xac\x8a\xf6\xc7\x3a\x33\x24\x89\xc9\x96\xd2\x42\
\x89\xa1\xdc\x30\x11\x33\xda\x99\xfc\xfb\xca\x17\x1d\x43\xd9\xe3\
\xa2\xf3\x69\xc1\x52\xfa\x59\xc1\xb7\x3a\x94\xbe\xc6\x59\xab\x68\
\x58\x4e\x29\x31\xd2\x0e\x14\x17\x88\x5b\x04\xc6\x30\xca\x31\x05\
\xf2\x18\xf8\x99\xf9\x06\xe3\x6e\x15\xdc\xc0\xe4\x6b\x38\x6a\x0c\
\xb0\x3c\x0e\x98\x54\x0e\x19\x92\x44\xe3\x98\x80\x3f\x14\x8c\x78\
\x2e\xe6\x30\x85\x2f\x97\xa1\x34\xa5\x0e\xc0\x0c\xca\x14\x2b\x28\
\x32\x8a\xe5\x33\xcb\xe8\x31\xb7\xd0\x6d\xe5\x64\x48\x12\x77\x84\
\xd3\x2d\xf2\x74\xef\x2b\xcd\x09\x69\xc9\x9c\x5f\xf1\x33\x81\x73\
\x71\x69\x7b\x3b\x64\x8c\x1c\x26\xf5\x65\x4a\x9f\x1a\xf2\xa9\x23\
\xdf\x7b\x72\xb5\x38\x5b\xf0\xd1\x30\xd7\x19\x64\x05\x66\xb0\x2a\
\x4b\x73\x46\x2d\x15\xed\x0f\x57\x43\x10\x1f\x64\x1d\x25\x4e\x17\
\xd7\x89\x0b\x05\x1f\x0d\x93\x1d\x77\x0a\x4a\x16\xf7\xa6\x6a\x7c\
\xe1\x4c\xae\x8d\x35\x04\x51\x52\xc9\x0a\x3e\x6d\xe4\xcb\x66\xc8\
\x1c\x6e\xdd\x53\xc6\xd2\x87\x4b\xdd\xf8\x4a\x6b\xa3\x0d\x41\x98\
\x72\xbc\x38\x52\x90\x35\x2c\x75\x53\x66\xd4\x36\x03\x6d\xbc\x21\
\x88\xcc\xc0\x0c\xce\xcd\xc4\xbe\xce\x1b\x85\x61\x88\x99\x8a\xf6\
\x87\xe3\xb2\x77\xa3\x15\x86\x98\x29\x0c\x31\x53\x18\x62\xa6\x9d\
\x4c\xea\xa1\xff\x2a\x26\xf5\x96\x15\x86\x98\x29\x0c\x09\x85\x42\
\xa1\x50\xa8\x09\x6d\x6d\xfd\x03\x55\x05\x7f\xb7\x68\xfd\x50\x93\
\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
\x00\x00\x10\x3b\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x64\x00\x00\x00\x64\x08\x06\x00\x00\x00\x70\xe2\x95\x54\
\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\x00\x00\x00\
\x09\x70\x48\x59\x73\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7\x6f\
\xa8\x64\x00\x00\x0f\xd0\x49\x44\x41\x54\x78\x5e\xed\xdd\x05\xac\
\x2c\x49\x19\x05\xe0\xc5\xdd\xdd\xdd\xdd\x25\xb8\x6b\xf0\xe0\x41\
\x82\xbb\x26\x10\x02\xc1\x02\x81\xc5\xdd\x5d\x17\x97\x45\x82\x2c\
\xb0\xb8\x5b\x70\x77\x77\xf7\xf3\x91\x5b\x64\x18\xba\x7b\xaa\x7b\
\xba\x7b\xe6\xb2\x73\x92\x93\xf7\xee\xbd\x33\xdd\x55\xf5\xd7\xaf\
\x55\xd5\x7d\xc0\x0e\x3b\xec\xb0\xc3\x0e\x3b\xec\xb0\xc3\x0e\x13\
\xe0\x70\x7b\xff\xee\x07\x9c\x24\x3c\xdd\x1e\x4f\x14\x1e\x73\x81\
\x47\x0a\xff\x1a\xfe\x2e\xfc\xed\xde\xbf\x3f\x0d\xbf\xb9\xc7\x9f\
\x84\xfb\x02\xdb\x28\x90\xc3\x87\xc7\x0d\xcf\x1f\x5e\x28\xbc\x60\
\x78\x86\xf0\xd8\xe1\x91\x43\x83\x7f\x84\xd0\xe7\x50\x1f\xf0\x9f\
\x7b\xfc\xc7\x1e\xff\x1e\x12\xd2\x9f\xc3\x5f\x87\x5f\x0d\x3f\x1e\
\x7e\x2c\xfc\x54\xf8\x9b\xd0\xe7\xb7\x0a\xdb\x22\x90\x23\x86\xa7\
\x0a\x2f\x17\x5e\x36\x3c\x7b\x48\x00\x45\x03\x8e\x1a\x96\xc1\xef\
\x8b\x22\xa4\x3f\x86\xbf\x0f\x69\xcf\xaf\xc2\xcf\x87\xef\x0a\x0f\
\x09\x7f\x18\x12\xe0\xc6\xb1\x69\x81\x9c\x38\xbc\x78\x78\xf9\x90\
\x46\x9c\x2c\x3c\x41\x48\x08\x04\x30\x15\x08\x88\x69\xfb\x59\x48\
\x18\x9f\x08\xdf\x11\x7e\x38\xfc\x79\xb8\x31\x6c\x4a\x20\x27\x0d\
\x69\xc2\x55\xc3\xf3\x86\x27\x0f\x8f\x17\x4e\x29\x84\x36\xd0\x8c\
\x5f\x86\xdf\x0b\x3f\x17\x12\xcc\x7b\xc2\xef\x86\xb3\x63\x6e\x81\
\x9c\x22\xbc\x72\x78\x99\xf0\x3c\x21\x07\x7d\xac\x70\x5b\x40\x6b\
\xbe\x1d\x7e\x3a\x7c\x7b\xf8\xce\xf0\x47\xe1\x6c\x98\x4b\x20\x7c\
\xc0\x25\xc3\x6b\x85\x84\x71\xfa\xf0\x68\xe1\xb6\x82\xaf\xf9\x5a\
\xf8\xde\xf0\xe0\xf0\xd0\x90\x0f\x9a\x1c\xa2\x95\xa9\x71\x8e\xf0\
\xe6\xe1\x2d\xc2\xab\x84\xa7\x0c\x45\x4a\xdb\x0c\xd1\x9c\x30\xfb\
\xac\xa1\xc9\xc3\x9c\xfe\x22\x9c\xdc\xbf\x4c\xa9\x21\x06\x9d\x9f\
\xb8\x61\x78\xb5\x50\xee\x30\xc6\x04\x28\x0e\xf9\x4f\xa1\x90\xf6\
\x2f\x7b\xbf\xe3\x7f\x0c\x24\x6d\xa4\x7d\xc7\xd8\xfb\xdd\xba\xe0\
\x63\x38\xfe\x37\x87\x07\x85\xb4\xe5\x6f\xe1\x24\x98\x42\x20\xae\
\x69\x46\x5d\x3d\xbc\x75\x78\xd1\xd0\x20\xf5\x45\x09\x57\x45\x42\
\x3f\x08\x7f\x1c\x72\xbe\x42\x56\x33\x95\x59\x61\x46\x08\xc5\xa0\
\x11\xb6\xfb\xa0\x28\x4d\xb4\x26\x9f\xd1\x16\xb3\x5d\xe0\x70\xc2\
\x50\xfb\x86\xf4\xdb\xfd\x3e\x10\x3e\x3f\x7c\x5b\xa8\x1d\xa3\x63\
\x6c\x81\x98\x91\x1c\x37\xad\xb8\x4b\xc8\x3c\xf5\xd1\x0a\x42\x30\
\xe3\x39\xd2\x6f\x85\x22\x1d\xb6\xfc\xcb\xe1\xd7\x43\x33\x55\x06\
\x4e\x08\xab\x40\x30\xb4\x92\x20\x24\x96\x67\x09\xcf\x18\xca\x77\
\x4e\x1b\x8a\xf4\xe4\x3f\x7d\xc6\x80\x66\x7c\x23\x7c\x6a\xf8\xca\
\x50\x05\x60\xd4\xe4\x72\x4c\x81\xe8\x9c\x8e\xde\x2c\xbc\x4f\x78\
\xf4\xb0\xf6\xfa\x34\x41\xe6\x4c\x08\x32\x6a\xd9\xf4\xfb\x43\xd1\
\xce\x98\xce\x54\x9b\x2e\x10\x5e\x22\x54\x05\x20\x28\x6d\xee\x93\
\xf7\x10\x80\xcc\xff\xd1\xe1\xcb\x42\xe1\xf2\x56\x24\x95\x8b\xe0\
\x2f\xce\x16\x1e\x18\x9a\xbd\x1a\x5d\x43\x1d\xe1\x2c\x3f\x19\x3e\
\x2b\xbc\x66\x78\x9c\x70\x0e\x30\x65\xd7\x0d\x5f\x10\x12\x3c\x73\
\xa8\x3d\x4d\xed\x5c\xa6\x09\xa4\x9f\x0f\x0f\x69\x9d\xc9\xb8\x35\
\xd0\x18\xd1\x08\x35\xa6\xd2\x4d\x1d\x68\x22\x9b\xcc\x14\x3d\x33\
\xe4\xfc\x87\xf8\x99\x31\x20\x00\xb8\x52\xc8\x37\xd0\x4e\xed\x32\
\xe0\x4d\x6d\x5e\xa6\xfe\x3e\x2e\xa4\x69\x73\x44\xac\x2b\xa1\x11\
\x1a\xf3\xc8\xb0\x56\x18\x3e\xc7\x29\x73\x8c\x37\x08\x45\x43\xdb\
\x00\x66\x8b\xef\xd3\x2e\x5a\xdb\xa7\x3f\x0f\x0b\x4f\x1d\x6e\xa2\
\xd2\xf0\x1f\xf0\x0f\x9c\xf6\x83\xc2\x5a\x33\xc5\x61\x2b\x87\xdf\
\x2f\xe4\xfc\xb7\x11\xa7\x09\x1f\x12\xca\xd8\x55\x8b\x9b\xfa\xb1\
\x4c\x21\x38\xbf\x29\x50\x18\x3b\x50\xaa\xc6\xf1\xc3\x7b\x84\xaa\
\xa7\x4d\x8d\x5c\xa6\x99\xf4\xc1\x50\x38\x7c\x94\x70\x9b\xc1\x8c\
\x5d\x3f\x14\x5c\xd4\x6a\x8a\xdc\xe8\xb6\xe1\x5c\x3e\xf0\xbf\xc0\
\x6f\xdc\x28\x34\x8b\x6a\xed\xed\x8b\x42\x65\xf5\x8d\xcd\xa0\x9e\
\x60\x7e\x54\xa0\x25\x83\x4d\xfd\x59\xa6\x71\x10\x12\x5f\x23\x9c\
\xdd\x9f\x70\xc2\xd6\x12\x6a\xa2\x12\x0d\xe5\xf0\xcf\x14\x6e\xd4\
\xc6\x0e\x80\x81\x15\x3d\x3e\x2d\xac\xe9\x2b\x6d\x52\xfb\xba\x58\
\x38\x1b\x44\x54\x22\x23\xf9\x41\x53\xa3\x16\xa9\x13\x1c\x9e\xaa\
\xee\x56\x44\x21\x03\xa0\xdd\x26\x93\xbc\xa3\x46\x28\x7f\x08\x1f\
\x1f\x0a\x76\x26\x87\xd0\xf4\xee\xe1\xf7\xc3\xa6\xc6\x2c\xf3\xc9\
\xe1\x7e\x16\x46\x81\xf6\x9f\x39\x7c\x4a\xd8\xd4\xcf\x65\x4a\x16\
\x6f\x1f\x4e\x1e\xca\x5f\x31\xb4\x80\xb3\xca\xd1\x99\x49\x7c\x86\
\x4e\xec\x77\x61\x14\xf0\x9b\x2a\xd7\x4a\x26\x4d\x7d\x5e\xa4\xf1\
\x51\x8c\xb4\xe4\x30\x19\x2c\xaf\x52\x45\x45\xb5\xa6\x46\x14\x0a\
\x15\x3f\x12\x9e\x33\xfc\x7f\x11\x46\x81\x8a\x84\x92\xcb\x47\xc3\
\x55\xc1\x8c\x5c\x46\x26\x6f\x99\x7a\x12\xa8\x51\x7d\x26\xec\x6a\
\x88\x99\xf1\x9d\x50\x68\xdb\xc7\x81\x13\x9c\x8a\x2c\x8d\x9a\x13\
\x1c\xb6\x02\x64\x9f\xb6\x2a\xf1\x5f\x3b\x54\x58\xec\xf2\x29\xc6\
\x89\xe0\x94\x67\xaa\x51\x3b\x83\x25\x80\xb7\x0a\x2f\x15\x6a\x50\
\x13\x34\x42\x81\xf0\x49\xe1\x4b\x43\xc2\xa9\x81\x36\x58\x57\xbf\
\x73\xa8\xe8\xc7\xfe\x2a\xb5\x4f\x0d\x21\xad\x3c\x4a\xb1\x51\x15\
\x59\x99\x5f\x1f\x56\x81\x10\xb4\xd1\x38\x5c\x24\x64\xca\x9a\x42\
\x79\xbf\x93\x93\xb0\x28\xb6\x1d\xc9\xd7\x46\xc3\x4d\x42\x05\xb8\
\xc5\x19\xb0\x4c\xd1\xc5\x5b\xc3\x3e\x19\x38\x61\x30\x01\xcf\x0d\
\x95\x53\x94\xd6\xfd\x9f\x80\xa6\x84\xf5\x7c\x3e\x4e\x41\x91\x20\
\x44\x8d\xe7\x0b\x6b\x8b\x84\x06\x5b\xa9\xc4\x12\xaf\x2c\xbd\x69\
\x3c\x0a\x99\xef\xeb\x84\xa3\x81\x4a\x1b\xa4\xb2\xb1\xac\x89\x66\
\x8d\xf5\x8a\xeb\x85\xb5\x28\xc2\x78\x4e\x48\x18\xae\x43\xcd\xd9\
\x5e\xf7\xe3\x83\xa6\xc0\xb9\x43\x15\x5e\x33\xb7\x98\x5f\xf7\x7f\
\x46\x48\x28\xb5\x56\x03\x4c\x54\x11\x67\x97\xe9\x72\x9f\x27\x86\
\x16\xcc\x46\x81\xcc\x53\x09\xa1\xe9\x66\x85\x66\xda\xf3\xc2\xda\
\x42\xe1\xa2\x30\x8a\xa9\x28\x34\x48\x3a\xa1\x1c\xcf\xc6\x8f\x05\
\xb3\x5a\x94\x44\x18\xcc\xc7\xb2\x2f\xa4\x9d\x12\x58\xda\x59\x2b\
\x14\x3b\x66\x5e\x11\x2a\x9b\x2c\x5e\x6b\x99\x96\x7d\xaf\x10\xae\
\x0d\x2a\xfc\x98\xb0\xac\x8c\x35\xd1\xec\xb0\x9f\xc9\x66\xb7\x1a\
\xe8\x2c\xbb\x4d\x0b\x96\x85\x51\x68\xb0\x0c\x9a\x59\x2b\x11\x5d\
\xb7\xdc\xe2\x9e\xca\x36\x26\x0d\x13\xb3\x2c\x8c\x42\x42\x79\x7a\
\xd8\x47\x53\x6c\xdc\xb0\xaa\xd9\xa5\x25\x96\xa0\x1f\x1c\xd6\x5e\
\xb3\x15\x2a\x9f\xab\xf2\x0e\xab\x67\x2f\x0c\x6b\xb7\xf5\x08\x03\
\xad\x21\x14\x33\xd5\x46\x83\xa6\x8a\xcc\xbe\xcb\x94\x87\x76\xa6\
\xe4\x0f\xae\x63\xd0\xda\x84\x51\x68\x92\x58\x4e\xa8\x0d\x57\x25\
\x7f\xaf\x0a\xbb\xb4\xc4\xf8\xbd\x3e\x5c\xe9\x5f\x57\x85\x7b\x12\
\x1b\x6b\xd0\x6d\x83\xe1\x66\xd6\xbd\x5f\x17\xd6\x2e\xb5\xda\x78\
\xa0\x13\x65\x60\xda\x40\x2b\xc4\xfd\x2a\xa8\x77\x0d\x6d\xc7\xe9\
\x2b\x14\xdf\xb7\x96\xee\xfb\xae\xe3\x9a\x5d\xda\xa6\x3d\x84\xa6\
\x7d\xb5\x1b\xf8\x68\x1c\x81\x88\x0c\xdb\xfa\xa3\xdd\x96\x8a\x6d\
\x9b\x1d\x0c\x0d\x67\xc7\xf9\x07\x37\x6a\xa2\x19\xfc\x86\xd0\x20\
\xf7\x81\x28\xe7\xd9\x21\x2d\x59\x35\x63\xd1\x67\x9e\x10\x1a\xdc\
\xda\x48\x88\x30\x68\x86\xc2\x60\xed\x3d\x68\x07\x3f\xc2\xbc\xf5\
\x81\xa5\x08\xc5\x56\xeb\x3d\x4d\xd7\x46\xd7\x96\x58\x0f\x36\xbf\
\x62\xe8\xf7\x85\x5d\xb6\x91\x76\x3c\x20\x1c\x02\x51\x14\x33\xb2\
\x18\xed\x74\xd1\x67\xd4\xc6\x6a\x84\xe2\xef\x06\xd5\xe0\x76\xb5\
\xbf\xd0\xb5\xb5\x83\xff\x20\xc4\x21\x78\x44\x28\x9f\x69\xba\x3e\
\x6a\x87\xb4\x60\xf0\x7a\x89\x2d\x9f\xb6\xec\x37\x5d\x1c\x75\xc2\
\x82\x93\x64\x6e\x28\x0c\x1a\xc7\xdd\x14\xf5\x34\xd1\x67\x14\xf8\
\xba\x6a\x64\x7e\xef\xba\xb5\x25\x73\xd7\x74\x7f\xc2\x5b\x27\xaa\
\x13\xd4\x48\x00\xbb\xfa\x21\x5a\x1d\x5c\x9a\xbf\x67\x48\x03\x9a\
\x2e\x8c\x3a\xcb\x76\xda\x5a\xb3\x0e\x0c\x02\x4d\x61\xfe\x6a\x85\
\x22\xae\xb7\xdb\x63\x59\xfd\xfd\x5c\xae\x57\x7b\x2d\xf7\x55\x5d\
\x70\xbd\x75\x60\x4d\x9e\x06\x74\x4d\x02\xb9\xda\x1d\xc3\x41\x78\
\x71\xd8\x95\x0c\x0a\x85\xa9\xe9\x18\x30\xe3\xfb\xd8\x7a\x9d\xa6\
\x29\xcb\x83\x48\x33\xe4\x36\xfe\x5e\x7b\x2d\x76\xdd\x12\xc1\x18\
\x20\xd8\xae\xe8\x51\xd2\xcb\x2c\x0e\x82\x64\xa6\x6b\x91\xff\xb3\
\xa1\x4d\xd4\x63\x40\xb4\x47\x28\x3a\x54\x6b\x66\x44\x37\x34\xa1\
\x38\x60\x3e\x89\x30\x44\x7b\xb5\xc2\xa0\x69\x16\x92\x06\x3b\xda\
\x25\xdc\x2e\xb4\xb5\xa9\xe9\x7e\xc8\xe9\xd3\xa2\xde\x10\x83\x4b\
\xf6\xba\x3a\x26\xaa\xb0\x6f\x77\x2c\xb0\xfd\x1c\x36\xc7\x5d\x3b\
\xa0\x62\x7f\x33\xee\xc6\xa1\xa4\xcf\xcf\xb5\xdf\x95\xf0\x8e\xbd\
\x9f\x4a\xf1\x95\x5f\x6d\xba\x27\xba\xef\x87\xc2\xde\x65\x14\x65\
\x0d\x9b\xc6\x9a\x2e\x5a\xf8\xda\x50\x81\x6d\x4c\x88\x8e\x64\xe6\
\x7d\x84\x22\x2c\x57\x7d\xed\x13\xad\x3d\x36\x9c\x62\x73\x9b\x5c\
\xc9\x41\x9f\xa6\xfb\x16\x2a\xd2\xb6\x16\x4f\xdb\x12\x43\x19\x7a\
\x5b\x99\x1d\x74\x4a\x86\x3e\xf6\x71\x63\x19\xad\x32\x84\x88\x87\
\x4f\xd1\x81\x2e\x30\x35\xc2\x48\x1b\xaa\x1d\x12\xed\x32\x3d\x65\
\x40\xf8\x0c\xd7\xb6\x8f\x98\x79\x1c\x13\xc2\xde\xa2\xa5\x6d\x50\
\xd1\x68\x9d\xc8\x6d\x02\xb1\x6d\x5f\x62\xd5\x06\xdb\x2d\x25\x3a\
\xec\xf8\xd8\x28\x42\xe1\xb4\x99\xa3\x32\x90\x6d\x20\x84\xc2\x36\
\xf8\x3e\x7f\xc8\x47\x11\xf6\x14\xc2\x00\xe3\x61\x5c\xba\xaa\x16\
\xc6\x55\x22\xd9\x88\x36\x81\xac\xda\x0d\xee\x86\x66\xc2\x54\x20\
\x14\x26\xd3\x00\xca\x53\x4a\x06\x3c\x04\xbe\x67\xad\x46\x31\xd3\
\xf5\xec\x9c\x9c\x42\x18\xe0\x5e\xc6\x45\x28\xdd\x06\x66\xd9\xf8\
\x36\xa2\x6d\xd0\x95\xd1\xbb\xec\xab\x01\x9a\x42\x3b\x16\x61\xd0\
\xbe\x12\x2a\x99\x28\x99\x1b\xd4\xbe\x42\xf1\x79\xa1\xfb\x4b\x42\
\x11\x95\x8d\x6c\x43\x05\x5b\x0b\x93\x95\x36\xb6\xc1\xb8\xb6\xe6\
\x6e\x6d\x02\xf1\x85\x2e\x0d\x71\xc3\xae\x59\x30\x16\x0c\x1e\xa1\
\x18\x4c\x67\x31\x4a\x5e\x54\x03\x9f\xe3\xf0\xed\x12\xa1\x19\xc2\
\xd1\x39\xb0\x4a\x20\xc6\xb5\xb7\x40\xd8\xb9\x2e\x9b\xcc\x69\x4d\
\xa5\xf6\x4d\xf8\x62\xf8\xee\x90\xef\xea\x03\x02\xb4\xcc\xfa\x85\
\x7f\xff\x34\x0f\x98\xdb\xae\xb1\x31\xe6\xad\xfe\xb9\x4d\x20\x25\
\x21\x6c\x83\xef\x8d\x1d\x32\x76\x41\x39\xc4\x63\x37\xfa\x1e\x5d\
\x10\x79\xc9\x0d\x4a\xf2\x38\x07\xf8\x88\xae\xb1\x31\x99\x5b\x35\
\xa8\x4d\x20\xec\x75\x57\xe8\x46\xc2\x73\xec\x60\xa7\xa5\x32\x78\
\xbb\x25\xad\x5f\xaf\x0a\x6d\x17\xe1\x73\x4e\x49\xd9\x14\x6e\x3d\
\x44\xd2\x39\x07\x84\xb5\x5d\x11\xaa\x71\x35\xbe\x8d\x68\x13\x08\
\xd3\xd0\xa5\x76\x72\x94\xda\x15\xc2\xa1\x30\xcb\x08\xc3\x56\x9d\
\x5b\x86\xec\x6e\xad\x30\x0a\x7c\x9e\x10\x95\x78\xee\x16\xaa\x59\
\xf5\xbd\x46\x5f\xac\x12\x88\x71\xed\x2d\x90\x52\x0e\x6f\x83\x9b\
\x4e\xf9\x48\x0c\x6a\x6f\xd9\xd6\x20\xde\x21\x34\x01\x86\x0e\xa4\
\xef\x11\xe6\x6d\xc2\x22\x94\xa9\xcc\x6d\x99\x00\x5d\xd6\x83\x8f\
\x69\xf5\x85\x6d\x02\x91\xdc\x74\x45\x0a\x6c\xb9\x7a\xcc\x14\x9b\
\x89\x09\x43\x15\xd7\xc6\x39\xa5\x6a\x9d\xec\x12\x06\x5f\x57\xd8\
\x06\xdf\x37\x6b\x99\x3e\xd7\x55\x89\x98\x42\x28\xc6\xc3\xb8\x74\
\x59\x0f\xe3\xaa\x22\xdc\x88\x36\x81\xc8\x64\xbb\xc2\x5a\xdf\x53\
\xb2\x18\x7b\xdf\x6a\x11\xc6\x9d\x42\x03\xd7\x25\x08\x20\x04\x25\
\x1c\xbb\x3a\x24\x64\xab\x84\x82\xd6\x79\x5c\x7f\x0a\xa1\xd8\xff\
\xcc\x72\xb4\x8d\x2b\x08\x8b\x1d\x74\x6a\x44\xdb\x17\x7d\x81\x40\
\xba\x3a\x48\x20\x63\x9e\x13\x34\x38\x0a\x7e\x06\xcb\x43\x07\x6a\
\x84\x41\xf5\xe5\x19\xf7\x0d\x15\x3b\x6b\x92\x47\xd7\xbd\x57\x58\
\x84\xd2\x35\x78\x7d\x61\xcb\x6d\x97\x29\xd7\x36\x02\x51\x0c\xed\
\x0d\x07\xf7\x4b\xf8\xdb\xc4\x31\xd7\x43\x0c\xd2\xba\xeb\x21\xd6\
\xc2\xad\x87\xf8\xbd\xbf\x37\x7d\x6f\x91\x3e\xa3\x0a\xb0\x2f\xd6\
\x43\xc0\xde\x57\xe6\xa0\xe9\xc2\xa8\xd2\x6b\xff\xd2\x18\xe0\xc0\
\x6b\x57\x0c\xd1\xe7\x14\x09\xdb\x56\x0c\xfb\x5c\xc7\x1e\xb1\x31\
\x57\x0c\xad\x0a\x36\xdd\x0b\xd7\x5a\x31\x5c\xb5\xa6\x2e\x5a\x78\
\x75\xd8\x5a\x06\xa8\x84\xa4\x4f\x01\x91\x89\xac\x19\x48\x9f\xd1\
\x71\x42\x5c\x9e\xd9\x7e\x26\x94\x3e\x6b\xea\x34\xaa\xac\xd1\xaf\
\x03\xa6\xca\x19\xf7\x2e\x0d\x57\xc5\x16\x35\x0e\xc2\xa5\xc3\x9a\
\x5d\x27\xeb\x9c\x12\x32\x78\x7d\x77\x9d\xd0\x0c\x49\x5e\x9b\x43\
\xf6\x7b\xd7\xf5\xb9\x5a\xf3\x27\x20\xf0\xf9\x75\x76\x9d\xd8\xbb\
\x3b\xe9\xae\x13\x9b\xdf\xd4\x81\xba\x3a\x35\xc6\xbe\x2c\x05\xc0\
\x5a\x61\x58\x23\xb1\xa2\x28\x1a\xeb\x82\xbf\xf7\x15\x8a\x76\x30\
\x9b\x43\xf7\x65\x31\xdf\x9e\x62\xd4\x74\x7d\x64\x51\xde\x12\xca\
\x53\x06\x81\xfa\x97\x01\x6b\xba\x01\x32\x33\x6f\x0c\x95\x28\xfa\
\xc0\x91\x80\xbe\x3b\x17\x99\x95\x21\x3b\x17\xd9\xec\xda\x7b\xc8\
\xbf\x08\x9d\x30\xfb\xc0\x82\x93\xe2\x67\xd7\xce\x45\x1b\xb9\xf9\
\xab\xb5\x02\x08\xc7\xd8\xbe\x14\x36\xdd\x00\x75\x82\x59\xeb\x73\
\x20\xa5\x6c\xf9\xd1\xc0\x55\x03\xe5\xef\x68\x8d\xdd\xf7\xfa\xe6\
\x0d\x84\x42\x13\x99\xc5\x72\xad\xa6\xfb\x14\xfa\xbb\x3d\xba\xe5\
\x81\x32\xb5\x50\x2f\xe3\x1f\xba\xae\x6f\x2d\xdd\xd3\x21\x3a\xb1\
\x2a\x06\x67\xb2\x9c\x19\xa4\xf6\x4d\x20\x6d\x9b\xb1\x09\xa4\xb6\
\xb6\x25\x72\xe3\x48\xdd\xbb\x6b\xb6\xe8\x84\xb0\x9b\x26\x11\x88\
\x4d\x66\x6d\xed\x68\x83\xef\x9b\x50\xbe\xef\x3a\x65\x70\xda\xa0\
\x3d\x84\x6e\xa6\xd7\xae\x88\xca\xce\x1d\x54\x72\x46\xb2\xad\x3f\
\xda\x6d\xa5\xd2\x8e\x93\xb5\xa0\x71\x9e\x81\x55\x73\x3e\xa4\xf6\
\x40\x8a\x6b\xd6\x9e\x0f\x61\x32\xb7\xfd\x7c\x88\x67\x0f\xcf\x76\
\x3e\x04\x9c\xa8\x5d\x75\x82\xca\x16\x1c\xcf\x9b\x6a\x5d\x2b\x5e\
\x82\x86\x6d\xe2\x04\x15\xf3\xe5\x2c\x4b\x53\x54\x47\x18\x4c\x69\
\x1f\x61\x08\x75\x55\x0a\x5c\x6f\xf1\x5a\xcb\xb4\x69\x7d\x94\x13\
\x54\xe0\x8c\xa1\x81\xab\x39\x63\xb8\xd2\x46\x2e\x40\xa7\x2f\x1c\
\xd2\x94\xb2\xfd\xd2\x20\x49\x9e\xcc\x64\x83\x37\x05\xca\x19\x43\
\xa6\xb3\x08\xc5\xfd\x69\xe3\x90\x33\x86\x66\x7f\x97\x76\x98\x5c\
\x02\x92\xd1\xce\x18\x42\xed\x29\x5c\x89\x91\x7a\x4e\x2d\x8a\x50\
\x08\xc0\xa0\x98\xa5\x04\x34\xf7\x29\x5c\xda\xe8\x98\x74\x6d\x04\
\x47\xdb\xec\xad\x3a\x34\x2c\x35\xbf\x36\x7a\x9e\x7c\x75\xd0\x53\
\x3b\x1b\xcc\x5a\xb6\x5c\xd8\xd9\xb6\xf8\xa2\x33\xf6\x73\x11\x4c\
\x79\xce\xd4\x2a\x68\xb0\xd8\xbd\x14\xdb\x6c\x68\x90\x3b\x78\x40\
\xc1\x94\x10\x49\x29\xa0\xca\x09\x0c\x18\x87\xcf\x0f\x9a\xe9\x35\
\x60\x9a\xad\x42\xb2\x08\x5d\x4b\x10\x4c\xd9\xc1\xe1\xcb\xf7\xfe\
\x3f\x2a\x6e\x1a\xd2\x92\x36\x87\x88\x84\x50\x9e\xe4\xd0\x47\xf5\
\x7d\x76\x93\x4f\x72\xe8\xd3\x56\x8b\x4f\x9e\xce\x40\x9b\xbb\x4c\
\x95\x71\x72\x46\xbd\xd7\x93\x1c\xfa\x40\xad\x5f\x7c\xce\x26\x36\
\x35\xa0\x50\xa8\xa9\x21\xe7\x0a\xfb\x74\x74\x3f\x80\x75\x60\x62\
\x3d\x45\xb5\x6b\x62\x22\x13\xec\xd1\x54\x93\x3d\xeb\x04\x44\x0a\
\xb5\x4f\x03\xb2\x39\x6d\x48\x32\xb7\xad\x60\x92\x65\xfe\x07\x85\
\x4d\x7d\x5e\xa4\xf1\x79\x53\x38\xe9\xd3\x80\x80\xbd\x3c\x2c\x3f\
\x2f\x8b\x7f\x6b\xea\xe7\x32\xd5\xf8\xac\x8d\x4c\xb1\xc4\xfd\x3f\
\xe0\xdc\x95\x22\xac\x7c\x35\x35\x66\x91\x34\xe5\xb0\xf8\x44\xb9\
\xbe\xa5\x97\xb5\x61\xd3\x9a\x97\x9d\xac\x32\x5d\xc8\xd6\x4a\xb8\
\x74\x6a\xcc\xe5\xd2\x39\x40\x18\x1c\xbf\xf6\xd7\x08\xc3\x78\x88\
\xaa\xc6\x3c\xc8\x54\x05\xf6\xd4\x43\x87\x6d\x86\x58\xe5\xdc\x0a\
\x9d\x59\x54\xbe\x58\xb7\x0c\x32\x17\xb4\x53\x89\xc7\xc1\xd6\xa6\
\xfe\x2c\xd3\x38\x48\x8e\xfb\x46\x98\xa3\x41\xc9\xd9\x3e\xa7\xb2\
\xdb\x63\x15\x45\x5f\x8a\x6b\x1e\x66\x33\x8b\x6d\x5d\x03\x0a\xa5\
\x72\x0c\xaf\xd9\xab\xb1\x02\xa8\x92\x61\xef\xd7\xe0\x73\xe8\xeb\
\xc2\x0c\xb2\xeb\xe4\x81\xe1\xaa\x6c\xb5\x50\x15\x55\xd5\xf3\xfe\
\x61\x9f\x8c\x7e\x4e\x78\x04\xc6\x43\x43\x89\x63\xd7\xfa\xc6\x22\
\x15\x2c\xef\x1d\x76\x55\x7c\x67\x01\x9f\xe0\x5c\xdd\x90\x67\xbf\
\x0b\x9f\x25\x9b\x83\x57\xd0\x46\x86\x42\xe1\xbe\x7e\xf6\x7b\x01\
\x7f\x22\xf2\xb2\xd2\x56\xdb\x09\x14\x8d\x28\x95\xa8\x23\x09\x12\
\x36\x65\xc6\x98\x27\x6f\x8e\x53\x70\xdc\xf7\x6f\x47\x28\x90\xc1\
\x8a\x46\xc6\x78\x7f\x48\xdf\x07\xd9\x0c\xc5\xe2\xfb\x43\xd4\xce\
\x54\x20\x6a\x22\x29\x24\x30\x66\x6a\xf4\xf7\x87\x8c\x69\xef\x34\
\x6a\xac\x37\xec\x70\xa6\xde\xf7\xa4\x76\xd6\xf7\x90\x4e\x17\xec\
\x49\x2e\x6f\xd8\xf1\xaf\xc1\xec\xfb\x86\x9d\xd2\xd6\x47\x85\x8a\
\x86\x0a\xa3\x04\x39\x0a\xc6\x76\x40\x3a\xe5\x88\x72\x79\x07\x55\
\xd7\xb3\xb6\x9a\x60\xf6\x89\xc6\x1c\x2f\x26\x1c\x19\xaf\x50\x72\
\xf9\x1d\x54\x66\x67\x17\xf4\x8b\x09\x54\x47\x52\x83\x63\x52\x54\
\xaa\xfd\xbb\xee\x3b\xa8\xb4\x43\x5e\xb2\xf5\xef\xa0\x2a\x70\x4d\
\xe6\x40\x3c\xee\x5c\x87\x7d\x48\xb5\xeb\xed\x8b\x28\xa6\x41\x00\
\xa0\x54\xb3\xf8\x96\x36\x66\x4e\x39\x5b\xb5\x80\x89\x34\x43\x09\
\x5e\x25\xd6\xbd\x38\x68\x61\x79\x79\x4b\x9b\xc1\x37\x51\x2c\x0f\
\xc0\x90\x7e\xd3\x54\xeb\x1f\x4c\x9c\x87\x03\x68\xc7\xe8\x98\x42\
\x20\x05\x66\xdf\xe2\x7b\x0c\xcd\xd6\x31\x1c\x1f\x21\x19\x1c\xc2\
\xa0\x29\x42\x53\xbf\xa3\x9d\x04\x82\xcc\x25\x8e\x11\xf5\x10\xb6\
\x55\x41\x19\xb8\xc2\x62\x79\x86\xd8\x24\x98\x52\x20\x05\xb2\x73\
\xda\xe2\xb9\xf1\xde\x8d\x6e\xd6\xce\x71\xdf\x75\x41\x43\x2d\xf3\
\x0a\x38\x08\xc3\xb3\xdc\x45\x85\x93\x62\x8e\x50\x8d\xcd\xd7\xa9\
\x92\x68\x71\xac\x9c\x68\xdb\xca\xe3\x36\x80\x06\x3a\xb9\x6b\x13\
\xa0\xcd\x1b\xaf\x09\xe7\x78\xda\xf6\x6c\xb1\x33\x67\x28\x43\x17\
\x5e\x72\x84\xc5\x29\xb3\xf7\xdb\x54\x46\xe1\x97\x44\x79\x76\x21\
\x5a\x73\x47\xc7\x2e\xb4\x7f\x16\x6c\xca\x74\x70\xb2\x8e\x2b\xdb\
\xd3\x24\xfc\xe4\x70\x99\xb2\xb9\x26\xc8\x22\xf8\x03\xc1\x82\xc0\
\xc1\xe0\xab\x62\x1f\x12\x8a\xf0\x66\xc7\xa6\x6d\xb9\xf5\x6c\x51\
\x18\xff\x62\x0b\x8e\x10\x55\x24\xd4\x27\x2f\x18\x02\x41\x80\xa2\
\xa8\x1d\x27\x42\x69\x79\x8f\x52\x8e\xa5\x67\x51\xdd\xc6\xb0\x2d\
\xce\x95\x66\xc8\x0f\x3c\x78\x53\x19\xc5\x52\x29\x8d\x29\xfe\x86\
\x59\x23\xa0\x21\xed\xe5\x9c\x69\x01\x33\xc9\x37\x30\x4b\x42\x56\
\xbb\x4c\x3c\x84\x8d\x36\xd8\xf9\x32\x59\xe4\xd4\x07\xdb\x18\xed\
\x68\x13\x61\xd0\x18\xbb\x1b\x51\x42\xe7\x77\x02\x01\x24\x40\x02\
\x2a\x2c\x30\xf3\x0b\x0d\xb0\x24\x53\x20\xc1\x24\x95\x0a\x80\x77\
\x7a\x94\xd7\x47\x8c\x9a\xd4\x8d\x81\x6d\x14\x48\x1b\xe4\x31\x96\
\x82\x55\x97\x8b\x59\x93\x00\x96\x88\xcd\xc0\x1b\x64\xa6\x08\x45\
\x77\x02\x09\x19\xbf\xff\xef\xb0\xc3\x0e\x3b\xec\xb0\xc3\x0e\x3b\
\xcc\x85\x03\x0e\xf8\x17\x13\x38\xc8\x5d\x25\x6a\x17\x2b\x00\x00\
\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
\x00\x00\x03\x0d\
\x3c\
\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
\x30\x22\x20\x73\x74\x61\x6e\x64\x61\x6c\x6f\x6e\x65\x3d\x22\x6e\
\x6f\x22\x3f\x3e\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\x20\x73\
\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\x57\x33\
\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x32\x30\x30\x31\x30\
\x39\x30\x34\x2f\x2f\x45\x4e\x22\x0a\x20\x22\x68\x74\x74\x70\x3a\
\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x54\x52\x2f\
\x32\x30\x30\x31\x2f\x52\x45\x43\x2d\x53\x56\x47\x2d\x32\x30\x30\
\x31\x30\x39\x30\x34\x2f\x44\x54\x44\x2f\x73\x76\x67\x31\x30\x2e\
\x64\x74\x64\x22\x3e\x0a\x3c\x73\x76\x67\x20\x76\x65\x72\x73\x69\
\x6f\x6e\x3d\x22\x31\x2e\x30\x22\x20\x78\x6d\x6c\x6e\x73\x3d\x22\
\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\
\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x0a\x20\x77\x69\x64\
\x74\x68\x3d\x22\x32\x35\x30\x2e\x30\x30\x30\x30\x30\x30\x70\x74\
\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x32\x35\x30\x2e\x30\x30\
\x30\x30\x30\x30\x70\x74\x22\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\
\x22\x30\x20\x30\x20\x32\x35\x30\x2e\x30\x30\x30\x30\x30\x30\x20\
\x32\x35\x30\x2e\x30\x30\x30\x30\x30\x30\x22\x0a\x20\x70\x72\x65\
\x73\x65\x72\x76\x65\x41\x73\x70\x65\x63\x74\x52\x61\x74\x69\x6f\
\x3d\x22\x78\x4d\x69\x64\x59\x4d\x69\x64\x20\x6d\x65\x65\x74\x22\
\x3e\x0a\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\
\x22\x74\x72\x61\x6e\x73\x6c\x61\x74\x65\x28\x30\x2e\x30\x30\x30\
\x30\x30\x30\x2c\x32\x35\x30\x2e\x30\x30\x30\x30\x30\x30\x29\x20\
\x73\x63\x61\x6c\x65\x28\x30\x2e\x31\x30\x30\x30\x30\x30\x2c\x2d\
\x30\x2e\x31\x30\x30\x30\x30\x30\x29\x22\x0a\x66\x69\x6c\x6c\x3d\
\x22\x23\x30\x30\x30\x30\x30\x30\x22\x20\x73\x74\x72\x6f\x6b\x65\
\x3d\x22\x6e\x6f\x6e\x65\x22\x3e\x0a\x3c\x70\x61\x74\x68\x20\x64\
\x3d\x22\x4d\x36\x38\x32\x20\x32\x32\x35\x33\x20\x6c\x33\x20\x2d\
\x32\x34\x37\x20\x36\x30\x20\x2d\x32\x31\x20\x63\x32\x34\x38\x20\
\x2d\x38\x36\x20\x34\x32\x34\x20\x2d\x32\x36\x30\x20\x35\x30\x37\
\x20\x2d\x35\x30\x31\x20\x33\x36\x20\x2d\x31\x30\x35\x20\x34\x38\
\x0a\x2d\x32\x35\x30\x20\x32\x39\x20\x2d\x33\x35\x39\x20\x2d\x33\
\x37\x20\x2d\x32\x30\x39\x20\x2d\x31\x37\x31\x20\x2d\x34\x31\x31\
\x20\x2d\x33\x34\x36\x20\x2d\x35\x32\x30\x20\x2d\x36\x30\x20\x2d\
\x33\x38\x20\x2d\x39\x37\x20\x2d\x35\x34\x20\x2d\x32\x33\x32\x20\
\x2d\x31\x30\x36\x20\x2d\x32\x33\x20\x2d\x39\x0a\x2d\x32\x33\x20\
\x2d\x39\x20\x2d\x32\x33\x20\x2d\x32\x35\x34\x20\x6c\x30\x20\x2d\
\x32\x34\x35\x20\x33\x37\x39\x20\x30\x20\x33\x38\x30\x20\x30\x20\
\x35\x38\x20\x34\x38\x20\x63\x31\x30\x32\x20\x38\x36\x20\x32\x34\
\x39\x20\x32\x34\x37\x20\x33\x31\x37\x20\x33\x34\x39\x20\x31\x30\
\x33\x20\x31\x35\x36\x0a\x31\x37\x37\x20\x33\x33\x30\x20\x32\x32\
\x32\x20\x35\x32\x34\x20\x32\x32\x20\x31\x30\x30\x20\x33\x31\x20\
\x34\x35\x31\x20\x31\x34\x20\x35\x36\x39\x20\x2d\x33\x30\x20\x32\
\x30\x36\x20\x2d\x31\x31\x38\x20\x34\x33\x36\x20\x2d\x32\x33\x34\
\x20\x36\x30\x39\x20\x2d\x37\x30\x20\x31\x30\x36\x20\x2d\x32\x33\
\x39\x0a\x32\x39\x30\x20\x2d\x33\x32\x39\x20\x33\x36\x30\x20\x6c\
\x2d\x35\x34\x20\x34\x31\x20\x2d\x33\x37\x37\x20\x30\x20\x2d\x33\
\x37\x36\x20\x30\x20\x32\x20\x2d\x32\x34\x37\x7a\x22\x2f\x3e\x0a\
\x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\x0a\
\x00\x00\x00\xc9\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xff\x61\
\x00\x00\x00\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\
\xa7\x93\x00\x00\x00\x7e\x49\x44\x41\x54\x38\x8d\xcd\xd1\x31\x0e\
\x82\x50\x10\x84\xe1\x4f\x0b\x12\x0e\x03\xa1\x90\x8a\xd6\x86\x44\
\xce\x44\x38\x8a\x67\xe0\x0c\x9e\xc0\x52\x7b\x3c\x84\x09\x16\x58\
\x18\x83\x8f\xe4\x51\xe0\x24\x5b\xec\x6e\xe6\xcf\x66\x96\x7f\x54\
\x85\x73\xac\xb9\xc0\x03\x75\x8c\x39\xc3\x80\x26\xc6\xbc\xc3\x15\
\xe3\x4c\x3d\x71\x47\x87\x34\x04\xc9\xdf\x17\x9c\xbe\xe6\x09\x4a\
\xf4\xb8\x2c\x41\x0e\xa6\x0c\x8e\x3f\xf6\x3d\xda\x10\x80\xf0\x17\
\x4a\xdc\x96\x00\x21\x25\xa6\x4c\x56\x69\xfc\x6c\xf6\x6b\x69\xdb\
\x03\xb6\xd7\x0b\x26\xa7\x15\x72\xfb\xba\xe1\x95\x00\x00\x00\x00\
\x49\x45\x4e\x44\xae\x42\x60\x82\
\x00\x00\x01\xf4\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x20\x00\x00\x00\x20\x08\x06\x00\x00\x00\x73\x7a\x7a\xf4\
\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\x00\x00\x00\
\x09\x70\x48\x59\x73\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7\x6f\
\xa8\x64\x00\x00\x01\x89\x49\x44\x41\x54\x58\x47\xe5\x95\xbd\x4a\
\xc5\x40\x10\x85\x57\x5b\x41\xc1\x42\x51\x41\xb1\x12\x5b\x3b\x5f\
\xc0\x4e\x9f\x42\xf0\x31\xc4\x77\xf0\x07\xdf\xe1\x22\xd6\x3e\x80\
\x8d\xad\x95\x88\xa0\xa0\x9d\x88\x62\x61\xa7\xe7\x64\x66\x2f\x43\
\x88\x9b\x9d\xbd\x89\x08\xf9\xe0\x30\x93\x6c\x7e\x76\xe7\x64\x36\
\x61\xf0\x4c\x69\xf4\xb2\x0a\xed\x48\x3a\xe6\x0a\x7a\x92\xb4\x7f\
\xf6\xa1\xef\x9a\x78\xee\x4f\xe0\xea\x2f\xa1\xfa\x04\x58\x01\x8e\
\xf5\x4e\xd3\xea\xa3\xdc\x55\x98\xd6\x58\xca\x1d\x74\x2b\x69\x19\
\x25\x13\xd8\xd4\x48\xce\xa0\x73\x49\x2b\x76\x21\x97\x0d\xde\x09\
\xf0\xe1\x07\x92\x56\x7c\x42\x5f\x92\x56\xec\x41\xf5\xee\x48\xe2\
\x9d\x00\x1f\x3e\x23\x69\x78\x84\xf8\xe1\x51\xf7\x3c\x51\x82\x77\
\x02\x6b\x1a\xc9\x31\xc4\xbe\xa7\x4e\x78\x42\xd9\xd0\xd8\x39\x2c\
\xff\x1b\xd4\xf4\xc5\xdb\xce\xf8\x80\x7a\x69\x47\xfb\x92\x67\xc8\
\xbe\x84\x39\x2b\x11\xc7\xb3\xdb\xd1\x63\xc1\x92\x46\x72\x0a\xd9\
\x6d\x97\x39\x2d\x89\x58\xab\x92\xe4\xfe\x0b\xb8\xc2\x1b\x68\xa1\
\x3a\x0a\xe1\x10\x7a\x91\x74\xcc\x32\x74\x24\x69\x78\x85\xb6\x20\
\x3b\xc9\x89\xb0\xe5\xcf\x55\x96\x0d\xb9\x16\xcc\x6b\xf4\xb0\xa8\
\x31\x49\x8e\x05\x2c\xff\x35\xb4\x52\x1d\x35\x97\x3f\x62\x6d\xe0\
\x35\xdb\xd0\xc4\x36\xd8\xf2\xbf\x43\xa9\x16\xe3\x18\xaf\xc9\xb6\
\x21\xc7\x82\x59\x8d\x84\xfb\x7e\x6a\x45\x1c\x63\x87\x44\xe6\x34\
\x16\xc3\x15\x3d\x40\xd9\x2b\x02\xb6\x62\xbc\x37\x55\xb1\xd6\x0a\
\x70\xef\x5f\x97\xb4\x08\xde\x9b\xfc\x39\x79\x36\xa2\x0b\x88\x3f\
\x9e\x36\x78\xcd\x48\xd2\x76\xda\xba\x80\xe5\x8b\x2b\xe0\x83\x73\
\xbf\xe8\xd2\xfb\x06\xc8\x6f\x16\xd8\x12\x76\x85\xcb\x0a\xdb\x4a\
\x5d\xa9\xb1\x85\x3d\x5d\xd0\x0b\xff\xd6\x82\xa1\x10\xc2\x0f\x6f\
\x35\x79\x22\x70\x77\xe8\xe3\x00\x00\x00\x00\x49\x45\x4e\x44\xae\
\x42\x60\x82\
\x00\x00\x00\xaf\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xff\x61\
\x00\x00\x00\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\
\xa7\x93\x00\x00\x00\x64\x49\x44\x41\x54\x38\x8d\xed\x92\x31\x0a\
\x80\x30\x0c\x45\x1f\x1e\xa1\xe7\x71\x10\xaf\xa6\x78\x57\x77\x97\
\x74\x89\x83\x16\x44\xd3\x92\x16\x04\x07\x1f\x64\x09\xc9\x23\x81\
\x0f\x5f\x63\x01\x04\xd0\x5b\x6d\xc0\xe0\x11\x08\x10\x8c\xbe\x02\
\xab\x47\xa2\x85\x7e\x7f\x4a\xc6\x56\xc1\xf5\x9d\x6a\x41\x76\xa6\
\x73\x2c\x14\xf9\x05\x4f\x41\xc4\x0e\x52\x22\x70\x84\x2d\xcb\x8c\
\x1d\xe5\x54\x02\x4c\x8d\xc7\xbe\xc4\x0e\x62\x40\x1f\x4c\x3d\x90\
\xe3\x21\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
\x00\x00\x1c\x03\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x01\xd5\x00\x00\x00\x9a\x08\x06\x00\x00\x00\xff\xc0\xd2\xfa\
\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\x00\x00\x00\
\x09\x70\x48\x59\x73\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7\x6f\
\xa8\x64\x00\x00\x1b\x98\x49\x44\x41\x54\x78\x5e\xed\xdd\x6d\x6c\
\x1c\x67\x81\x07\xf0\xe7\x99\xb1\x9d\x36\x29\xd4\xb9\x96\x70\xa0\
\x56\x75\x10\x25\x95\x40\xba\xa4\xe9\x11\xb5\xa1\x57\x9b\xa3\x92\
\x1d\x54\x70\x3e\x51\xa9\x1f\xba\x4e\x48\xae\xa7\x4a\x4d\x2d\x71\
\x2f\x48\x85\x24\x27\xa4\x7e\x38\x74\x49\xf8\x84\x92\x4b\xbc\xfd\
\x80\xc4\xdd\xe9\x52\x97\x4a\x89\x05\x3d\xec\xa3\x6f\x0a\xd0\xd8\
\x48\x45\x70\x07\x22\xae\x82\xca\xd1\x2b\xad\x8b\x2e\x6f\xb6\x77\
\x9e\x7b\xfe\xeb\x79\x9c\xf1\x74\x76\x77\x9e\xdd\xd9\xd9\x99\xd9\
\xff\x4f\x79\xb2\x6f\xde\x9d\xdd\x9d\xdd\xf9\xef\xf3\x32\xcf\x08\
\x22\x22\x22\x22\x22\x22\x22\x22\x22\x22\x2a\x22\xe9\x9f\x12\xa5\
\x66\x74\x74\x74\xc0\x3f\x4b\x94\xba\xc9\xc9\xc9\x79\xff\x2c\x51\
\xe2\x18\xaa\x94\x2a\x04\xaa\x52\xea\x82\x7f\x91\x28\x75\xae\xeb\
\x0e\x9c\x3e\x7d\xfa\x0d\xff\x22\x51\xa2\x18\xaa\x94\xaa\x60\xa8\
\x6e\xda\xb4\xa9\x7a\x1d\x51\x1a\xde\x7a\xeb\xad\xea\x29\x43\x95\
\xda\x89\xa1\x4a\xa9\x32\xa1\x8a\x40\x3d\x7e\xfc\xb8\x7f\x2d\x51\
\xfb\xed\xdf\xbf\xbf\x1a\xac\x0c\x55\x6a\x27\xc7\x3f\x25\x22\x22\
\xa2\x16\x31\x54\x89\x88\x88\x12\xc2\x50\x25\x22\x22\x4a\x08\x43\
\x95\x88\x88\x28\x21\x0c\x55\x22\x22\xa2\x84\x30\x54\x89\x88\x88\
\x12\xc2\x50\x25\x22\x22\x4a\x08\x43\x95\x88\x88\x28\x21\x0c\x55\
\x22\x22\xa2\x84\x30\x54\x89\x88\x88\x12\xc2\x50\xad\x6d\x50\x97\
\x23\xba\x60\x9e\xda\x09\x5c\x41\x44\x54\x40\xfd\xba\x1c\xd4\x65\
\x5a\x17\x6c\xef\x94\x7f\x8a\xcb\x25\x5d\xc8\x02\x43\xf5\x3a\x7c\
\xb0\xf0\x01\x42\x80\xbe\xab\x0b\x3e\x50\x4f\xea\xc2\xc3\x94\x11\
\x51\x51\x1d\xd0\x05\x01\x7a\xa8\x7a\x49\x88\x19\x5d\x26\x57\xce\
\x56\x2b\x16\xd8\x1e\xe2\x76\x6e\x07\x63\x62\xa8\x5e\x77\x54\x17\
\x7c\x80\xf0\x41\xc2\x07\xeb\x98\x2e\x44\x44\x45\x85\x4a\x04\xb6\
\x7b\xa8\x50\x0c\xf9\x65\x4c\x97\xdd\xba\x6c\xd6\xe5\xb0\x2e\x80\
\x40\x65\x6b\x5d\x4c\x0c\xd5\xeb\xf0\x4b\x6d\xa3\x2e\xf8\x30\xe1\
\x43\x85\x5a\x2a\x11\x51\x51\x3d\xea\x9f\x02\x2a\x12\x61\xd8\x26\
\x9a\xeb\x51\xd9\xd8\xba\x72\x96\xea\x61\xa8\x5e\x37\xaf\xcb\xc2\
\xca\x59\x22\x22\xd2\x9e\xf3\x4f\x81\xa1\x1a\x03\x43\x95\x88\xa8\
\x3b\xa1\xa9\x17\xdd\x5c\xa6\x99\x37\x0a\x2a\x1b\x64\x81\xa1\x4a\
\x44\xd4\x9d\x10\x98\xe8\xe6\x32\x83\x94\xa2\x04\x07\x28\xcd\xf9\
\xa7\x54\x07\x43\x95\x88\x88\x6a\xc1\xe8\x60\x28\xeb\xc2\x50\x8d\
\x81\xa1\x4a\x44\x44\x61\x18\x11\xfc\xac\x2e\xa8\xa9\x62\xb0\xd2\
\xb8\x2e\x14\x03\x43\x95\x88\x88\xc0\xec\xa7\x3f\xab\x0b\xf6\xd5\
\x47\xb0\xa2\xdf\x15\xbb\xda\x70\x10\x67\x4c\x0c\x55\x22\x22\x02\
\xec\x36\x83\x60\x35\xa3\x7c\x71\x19\xcd\xbf\x9c\x55\xc9\x02\x43\
\x95\x88\x88\x00\xe1\x29\xfd\x82\xfd\xf5\xd1\xe4\x6b\x26\x7e\xc0\
\xac\x4a\xa8\xb9\x52\x03\x0c\x55\xca\x8d\x73\xe7\xce\x89\x1f\xfe\
\xf0\x87\xab\xe5\xf5\xd7\x5f\xf7\x6f\xc9\xa6\x4b\x97\x2e\xad\x79\
\xbe\x28\xb8\x8e\x28\x07\x30\x32\x18\xb3\x2d\x61\x22\x1c\xe0\xac\
\x4a\x31\x31\x54\x29\x37\x9e\x7f\xfe\x79\xf1\xad\x6f\x7d\x6b\xb5\
\x20\xa4\xb2\x0c\x01\x1a\x7c\xbe\x28\x17\x2e\xe0\x07\x3f\x51\x6e\
\x60\x90\x92\x99\x55\x69\x54\x17\xd6\x56\x1b\x60\xa8\x12\x75\xa9\
\xb7\xde\x7a\x4b\x3c\xf5\xd4\x53\xe2\x91\x47\x1e\x11\xe3\xe3\xe3\
\xd5\x96\x00\xa2\x08\x6f\xf8\xa7\x10\xdc\x6f\x95\x22\x30\x54\x89\
\xba\xd4\x77\xbf\xfb\xdd\x6a\x13\x3a\x6a\xd4\xa8\x41\xa3\x26\xcd\
\xe6\x69\x8a\x70\xb3\x7f\x4a\x31\x30\x54\x89\xba\x54\xb8\x4f\xda\
\x84\x2b\x75\x05\x34\xe3\xe2\xf0\x96\xd8\x75\x06\xcd\xba\xf5\x98\
\xd1\xc0\xe8\x67\xe5\x04\x10\x0d\x30\x54\x89\xba\xd4\xa6\x4d\x9b\
\xfc\x73\xd7\x45\x5d\x47\x85\x84\xdd\x65\x50\x10\xae\x66\xd6\xa4\
\x28\xb8\xcd\x34\xf9\x3e\xe3\x9f\x52\x1d\x0c\xd5\xda\x82\x7d\x07\
\xec\x9c\xa7\xc2\x79\xe2\x89\x27\xc4\xe6\xcd\xd8\x73\x42\x88\x0d\
\x1b\x36\x88\xbd\x7b\xf7\x32\x54\xbb\x07\x06\x1f\x99\x09\x1d\x10\
\xae\x51\x7d\xa5\x08\x54\x8c\x00\x06\xfc\x7d\xbd\x39\x82\xc9\xc7\
\x50\x5d\xeb\x88\x2e\x98\x4d\x04\x6d\x60\x38\x35\xd0\x3c\x82\xeb\
\xd0\x5c\x82\xc2\x43\x20\x51\xee\x21\x40\x8f\x1c\x39\x22\x26\x27\
\x27\xc5\x77\xbe\xf3\x1d\xf1\xd0\x43\x0f\xf9\xb7\x50\x17\x40\xa0\
\x62\xa6\x24\x73\x14\x1a\x6c\xdf\x30\x2d\x21\x82\xd3\xec\x97\x6a\
\x02\x15\x47\xb2\xc1\xdf\x52\x0c\x0c\xd5\xb5\x7e\xa6\x0b\x8e\x1f\
\x88\x66\x0e\x73\x48\x24\x53\x70\xdd\x7f\xfa\x85\x53\x76\x11\x51\
\xde\xa1\x7f\x14\x4d\x15\x98\x8a\x70\x52\x17\xd4\x56\x71\xe0\x72\
\xd4\x5c\x71\x1b\xb6\x7b\x1b\x75\xc1\x91\x6c\x28\x26\xcc\x9c\x41\
\x05\x53\x7a\xf9\xc1\xad\xa2\xd2\xa3\xbf\x20\xaa\xc9\x66\x6b\xb9\
\x20\xa4\x5a\x28\xdf\x3f\x65\xf6\x4f\x4b\xcc\xe8\xe8\xe8\x80\x52\
\xea\x02\x6a\x49\xc7\x8f\x1f\xf7\xaf\x8d\x07\xbb\x7f\x04\x07\xd7\
\x7c\xf6\xb3\x9f\xad\x36\x61\x66\x15\x76\x59\xd9\xbf\x7f\xbf\x7f\
\x69\xc5\x37\xbe\xf1\x0d\xf1\xa9\x4f\x7d\xca\xbf\x44\x69\xc2\xba\
\xc0\x3a\x71\x5d\x77\xe0\xf4\xe9\xd3\xc1\xdd\x44\x88\x12\xc3\x9a\
\x6a\x41\x94\xa6\x87\x07\xf6\xbc\x32\x72\x64\xcf\x4b\x23\xef\x3a\
\xa2\x67\xd6\x71\xc5\xb3\x8e\x2b\x27\x9a\x2b\xfa\xbe\x8e\x9c\xc6\
\x63\xed\x79\x79\xd7\x04\x1e\xdb\x5f\x4c\x2e\x60\xc3\x69\x4a\x3b\
\x77\x11\x49\x6b\x39\x41\x9d\x58\x66\x33\xf0\xdc\x82\xcf\xd5\x46\
\xf8\xbe\x59\x7e\x9d\x44\x61\xac\xa9\x16\xc0\xde\x57\x76\x1d\x50\
\x9e\x3a\xa4\xd7\x66\xfb\x06\x54\x39\xf2\xd0\xa9\x7b\xcf\xa0\x39\
\xa8\x25\xed\xaa\xa9\xe2\x7a\xcc\xb0\x84\x09\x0c\xc2\x1b\x61\x0c\
\xc6\x41\xed\x10\x7d\x86\xad\x0e\xc4\xc1\x46\x1e\x33\x3b\x45\x4d\
\x39\x88\xc7\xc6\x72\x1e\x7e\xf8\xe1\xea\x79\xfc\x6d\xab\x35\x55\
\x2c\xc3\xbc\x2e\xec\xee\x12\x5e\x26\x06\x18\xe1\xf5\xe1\xbd\x40\
\xb1\x81\xc7\x0d\xce\x4a\x85\xc7\xfa\xea\x57\xbf\xea\x5f\x8a\x16\
\xbe\xcf\x8e\x1d\x3b\x56\xfb\x62\xcd\x7b\x83\xe7\x8a\xf3\x41\x78\
\x6c\xb3\x0e\xa2\x5e\x7f\xf0\x75\x86\x77\xf5\x01\xbc\x46\x2c\x0b\
\xaf\xb1\xd9\x75\x98\x87\x9a\x6a\x69\x7a\xb0\x5f\xf4\xf5\x0e\x88\
\x8a\xbb\x32\x6e\x43\x8a\x79\xb1\x7c\x75\xae\x3c\x34\xc3\x2e\xa7\
\x06\xde\xf7\xde\x35\x45\x2e\x08\x77\x79\xbe\xbc\xf3\x07\x4d\xef\
\x3a\x14\x19\xaa\x5f\xfe\xc9\xf0\xa0\xbe\x49\x3f\x31\xc9\x51\xaf\
\x19\xe7\x2d\x8b\x3b\x84\xa7\xd2\x39\x8a\x44\x02\xc1\x9a\x74\xa8\
\x62\xc4\x2a\x26\x2d\x88\x33\x1b\x10\x96\x89\xc0\xb3\x0d\x1f\x03\
\x81\x71\xf2\xe4\x49\xff\x52\x7d\x66\x39\xad\x84\x2a\x5e\x93\xcd\
\x84\x0c\x78\x7d\xf8\x91\x11\xf7\xf1\x31\xf9\x03\x8a\x11\x67\x9d\
\x84\xef\x83\xd7\x88\x65\xe2\x7d\xc1\xfb\x13\x07\x82\x15\xeb\xcd\
\xc0\x3a\xc5\xeb\x0c\x07\x71\x14\x3c\x47\xdc\x17\x01\x6b\x2b\xcb\
\xa1\x5a\x7a\x71\x78\xd0\x75\xe5\x41\xa5\xaa\xfd\x99\xef\x23\xa5\
\x98\xa9\x2c\x8b\x63\xe5\xbf\x38\x8b\xbe\x4f\x0a\x68\xf4\xde\x35\
\x69\x5e\xbf\xeb\x33\xde\xa2\x77\xb8\x3c\x34\x65\x06\x73\xc5\xb2\
\x26\x54\x11\xa6\xd2\x75\x8e\x08\xc5\xd1\xad\x79\xa0\x2a\x4a\x78\
\x4b\xfe\x85\xb4\x48\x31\x7e\xea\xbe\xb3\x66\x54\xa0\xb5\x24\x43\
\x15\x1b\x56\x6c\x24\x6d\x27\x2c\x40\xe0\xa1\xd8\x08\x87\x49\x1c\
\x08\x9c\x60\xad\x0e\xe2\x86\x6a\x33\xcb\x33\x10\x72\x58\x76\x23\
\xe1\x65\x34\x1b\xaa\x58\x07\x51\xb5\xcb\x7a\x4c\xb0\xda\xfc\x50\
\x09\x6a\xa6\x6f\x3a\x8b\xa1\x8a\xae\x15\x77\x9d\x9c\x88\x1f\x08\
\xb2\xdc\xcc\x86\xbe\x88\x50\x33\x75\xd6\xdd\x78\x50\xe7\x55\x3b\
\x07\x52\xcd\x7b\x15\x31\x6e\xf3\x63\x66\x35\x54\xf7\xff\x74\x64\
\x54\x49\x89\x21\xd5\x94\x13\x95\x6b\x4a\x27\xab\x7f\x21\x3d\x0b\
\xde\xe2\x95\xcd\xcd\x36\x47\x25\x19\xaa\x61\x78\x4c\x6c\x68\x71\
\x0a\x08\xdb\x5a\x35\x58\x9b\x8d\x72\x38\x48\x0c\x34\x69\x22\xd8\
\x83\xcb\x43\xa9\x57\xe3\x8a\xb3\x5c\x04\x31\x6a\x6e\x61\xb8\x9f\
\x79\x7d\xa8\xbd\x62\x59\x78\x3f\xa2\x96\x17\x67\x39\xe1\xd7\x15\
\x67\x9d\x84\xef\x83\xf7\x20\x58\x93\xc6\x32\xd1\x54\x8b\xeb\xa1\
\xde\x3a\x40\xb0\x86\x6b\xb7\xc1\xfb\x07\x5f\x63\x58\x9c\xe7\x1a\
\x16\x27\x54\xf7\xfd\xf8\xc1\xad\x15\xb7\x95\xe6\x43\x0b\x8b\xba\
\x78\xf2\xa0\xfe\xdf\x76\xcc\xc2\xbc\xe8\x55\x87\x85\xeb\x5f\xea\
\x52\xf2\xaa\x3c\xa0\x37\x7f\xe9\xac\x2b\x8b\xca\x44\x35\x54\x4b\
\xb3\xc3\x03\xbd\x9e\x83\xfd\x2f\x73\x35\x20\xa5\x9b\xb5\x5a\x4b\
\x5d\xef\x2e\x8b\x4f\xdc\xf4\x47\x71\xb9\xd2\x23\xfe\xfb\xff\x3e\
\xe8\x5f\x1b\x93\xd2\x1f\xb0\xcf\x34\x57\x5b\x6d\x47\xa8\xe2\xb1\
\x6a\x35\x7b\x62\x23\x8a\x10\x08\xd7\x18\xe3\x2e\x1f\xf7\x0f\x37\
\xe1\x02\x6a\xba\x08\x05\x13\x1e\x41\x08\x0a\x2c\x33\xaa\xd9\x36\
\x4e\xd8\x99\x8d\xbf\x51\xef\xf5\x41\x38\xe8\x00\xc1\x84\x7d\x50\
\xeb\x09\xdf\x2f\xce\x7b\x12\xb5\x2c\xc0\xf2\xd0\x1f\x8b\xc7\x08\
\xc3\x6b\x41\x6d\xb4\x5e\x13\x3d\x5e\x1b\x5e\x63\xad\xfb\x63\xdd\
\x07\xdf\x13\xb0\xad\xad\xd6\x0b\xd5\x7d\xb3\x18\x97\x20\x0f\xc9\
\xa6\x47\xcc\x5b\xd2\x69\x50\x59\x6c\xe1\x47\xb1\xde\x72\xbb\x7d\
\xfa\xbf\x35\x6d\x8d\xdd\x43\x2d\xeb\xed\xdf\xb2\x7f\x21\x25\x9e\
\xa3\x36\x97\xef\x6d\xdc\x42\x50\x1d\xfd\xdb\xb3\x2c\x31\xb9\x01\
\x03\x35\x47\x54\xc5\x3f\xd3\x84\x2d\x1b\xde\x13\x4f\xdf\x75\x5e\
\x3c\x7e\xc7\x2f\xc5\xdf\x7c\xec\x75\xf1\xf5\x3b\xe7\xaa\x21\x1b\
\x97\x72\xc4\x17\xfd\xb3\x0d\xe9\x6d\x46\x5b\xfb\x7b\xb1\x11\xae\
\xb7\x71\x35\x81\x84\x00\x0c\xc2\xc6\x35\x4e\x1f\x60\x54\x80\xa0\
\xd9\x12\xa1\x1a\x15\xa8\x80\x65\xe1\x39\xd5\xba\xbd\x9e\xa8\x9a\
\x67\xbd\x40\x05\x13\xf0\x41\xb5\x6a\x78\xed\x60\x02\x3c\x2a\x10\
\x01\xd7\x23\x70\xf1\x77\x51\x50\xdb\xc7\xfb\x55\xef\xfe\x51\xef\
\x67\xf8\x87\x52\xb3\xf6\xcf\x7e\xfe\x88\xf0\xc4\xd1\xd4\x02\x55\
\xf3\x74\x28\xb4\xd4\xca\xa4\xef\xeb\xe9\x1f\xd6\x5d\x09\xaf\x3d\
\xcd\x40\x55\x98\x97\x40\x8d\xc5\x09\x54\xa8\x86\xaa\x74\xe3\x6f\
\x24\x29\x1b\x54\x0b\xdf\xa7\xd2\xed\xbf\x5e\x13\xa2\xb7\xdf\x78\
\x59\xfc\xe5\xad\xbf\xf3\x2f\x35\x26\x63\xf4\xb9\xeb\xa7\x37\xa8\
\x0b\x5a\x3f\x26\xf4\x69\xdb\xa6\x37\xab\xb7\x31\x0e\x42\xf0\x84\
\xff\xae\xd1\xe0\x26\x84\x5b\x78\xc3\x8d\x3e\xc4\x70\x80\x45\x41\
\x80\xd8\xf6\xdb\x02\xc2\x30\x08\x41\x12\xa7\x36\x16\x15\xf2\xe1\
\xc7\x6a\x97\x46\x23\x86\x8d\x5a\xef\x5b\x70\xd0\x52\x2d\x58\x77\
\xe1\xc1\x49\x49\xfc\x68\xd8\xf7\xda\xae\x92\xf2\x54\xba\x93\x1b\
\xe8\x2f\x44\x2b\x3f\x8a\x0d\x85\xaf\x70\x0b\xdb\x81\xbc\xaa\xfe\
\x20\xb1\x64\x5a\xe6\xb6\xde\xfc\x8e\x55\x05\x42\x9b\xf7\xa4\x1c\
\x3a\xb5\x73\xaa\xec\x5f\x6e\x68\x65\x3f\x55\x25\x59\x4b\xcd\x9b\
\x26\xbf\x4c\xb7\xf4\x5d\x13\xb7\xea\x12\xb6\x65\xc3\x1f\xfd\x73\
\xb1\xd4\xfc\x45\xaf\x9f\x56\xbf\x2e\x68\x77\x44\xa0\x62\xf0\x05\
\xfa\x5e\xdb\x32\xa8\x22\xd8\x9f\xd9\x08\x02\x27\x3c\x78\x07\x1b\
\xe5\x7a\x23\x6b\xa3\x36\xda\x36\x41\x19\x0e\x81\x38\xc2\xcf\x27\
\x6e\x6d\x17\x7f\x87\xe5\x21\x80\x4d\x89\x7b\xdf\x56\x60\x39\x71\
\xd7\x41\xd4\xfb\x61\xb3\x0e\xc3\x35\xdd\x7a\xeb\xce\x02\xfa\x34\
\x53\x95\x64\x0d\xb3\x1b\x6b\xab\xca\xf3\xcf\xc4\x84\x6d\xde\xd7\
\xee\xfc\x59\xb5\x55\x0e\xad\x73\x5f\xd7\xe7\x6f\xbf\xa1\xf1\x67\
\x47\x57\x1e\x66\xbc\xf5\x57\xb6\x95\x77\x9e\x69\xb8\x7b\x8d\xbf\
\xdd\xab\xb6\xca\xad\x84\xaa\x54\x5d\x3f\x92\x2c\x77\x9a\xec\x4b\
\xb9\x52\x89\x1e\xdd\x70\xd9\x6b\x7d\xd4\x83\xfe\x50\x61\x02\x6e\
\x54\x8f\xcc\x2f\x7f\xec\x7e\xb3\x59\x3f\xd5\xd8\xbf\xf2\x6c\xd8\
\x86\x46\x54\x4d\xa9\x5e\x6d\x35\x5c\x4b\xb5\x09\x90\x66\x85\x1f\
\x1f\xb5\xe5\xb8\x35\x32\x34\x13\xa3\xe6\x6e\x4a\xf8\x47\x44\xa7\
\x45\xad\x2f\xbc\xa7\x71\x85\xef\xdf\x6a\xa8\xae\xec\x3a\xd8\x81\
\x6e\x2f\xcb\x50\xa8\x2b\xc9\xc7\xca\x03\xfc\x86\xb0\xfc\x1d\xf1\
\x85\x4d\x17\xd7\x54\x24\x10\xb2\x5f\xfa\x68\xfd\x56\x1c\xbd\x88\
\x63\x27\x3f\x73\x76\xa8\xbc\xad\xf1\x80\x4c\xfd\xb7\xe8\x3e\xc5\
\x5c\xf1\x68\x95\x1b\xac\x86\xaa\xaa\x48\xcc\x67\x4b\x79\xd2\x64\
\xa8\x62\x60\xd2\xf3\xbf\xbf\xdd\xbf\xb4\x02\xd7\xfd\xeb\x9b\xf1\
\xb7\x2d\xb7\xbe\x79\x79\x41\x7f\x78\xa6\x43\x05\xc7\x65\xc4\xe0\
\x25\xd4\x62\x31\xbd\x21\xc2\xf4\x90\x2e\x99\xd9\x69\x1d\x1b\xe5\
\x70\x68\xd5\x6b\x22\x0d\xdf\x56\xab\x4f\x30\x49\x51\xb5\x39\x8c\
\x04\x4e\xaa\xff\x30\x6b\xd2\xa8\x4d\x67\x4d\x2b\x5d\x37\x61\x49\
\x3e\x56\x1e\x34\xf3\x7a\x3f\x71\xd3\x7b\xfe\xb9\xeb\xb6\xdc\x54\
\xa3\x65\xce\xef\x3f\x9d\xd8\x79\xb6\x61\x97\x80\x7e\x2a\x5b\x75\
\x41\x8b\x1c\xf6\x9a\xc1\x06\xb4\x7a\xe4\x9f\x6a\xa8\x2e\xf7\xf4\
\xe9\x8d\xa1\xcc\xcc\xc6\x8f\x1a\x93\x2b\x6d\x0c\x4d\xf9\x9e\x0e\
\xd5\x89\x8b\x1f\x17\xaf\xbc\xb3\x49\xbc\xf0\xf6\x47\xc4\x37\x7f\
\xf3\x49\xf1\xf6\xe2\x0d\xfe\xad\x8d\x6d\x99\x7b\x07\xc1\x89\x5f\
\xf9\xc1\x62\x9a\x84\xf1\x39\x1a\xd3\x61\x9a\xc9\xd6\x0f\x9b\x26\
\xc4\xf0\x6d\x69\x84\x2a\x42\x26\x5c\xa3\x46\x6d\x15\xc1\x8a\xd1\
\xab\x18\x45\x9b\xd6\x00\xa4\xa2\x93\xca\xe9\xcc\x36\x2f\xc9\x20\
\xec\xb2\x50\x95\x4d\x54\x26\xfe\xb0\xb8\xce\x3f\x77\x5d\xd4\x75\
\x5a\xac\xfe\x53\xfd\x96\x9b\x2e\x2e\xd4\x4e\xb1\xed\xc3\xe7\x68\
\x5c\x3f\xb5\x21\x5d\xe6\xaa\x9b\xe6\xf2\xb6\x49\x7d\x65\x65\x1c\
\xe7\x29\x1f\x1c\xb7\x89\x4f\x57\xc0\x2b\xef\x6e\x12\x13\xbf\xfd\
\xb8\xf8\x97\x37\x37\x8b\x8b\x57\xec\x6a\x0b\x1f\xfb\xf9\xc2\x6e\
\x7d\x82\x43\x41\x05\x0b\x8e\x74\x81\x20\x45\xb8\x5e\xd0\x1f\x3a\
\x34\x85\x64\xae\xaf\x3e\x5c\x33\x0a\x8f\xb4\x35\xa2\xae\x6f\x77\
\xd3\xaf\x81\x81\x3b\x51\x4d\xd5\x78\x4e\x18\xb1\x8c\xdd\x4b\x46\
\x47\x47\xab\xa7\x08\xd9\xb4\x06\x24\x15\xcd\x52\x6f\x9f\xfe\xbc\
\xe6\xbc\x32\xd1\xda\x66\x20\x7f\xf0\x7a\x2d\x5f\x73\xb8\x65\x0e\
\x5e\x78\xfb\xa3\xfe\xb9\x15\x5b\xce\xbf\x23\x8e\x7d\xfe\x85\x85\
\x89\x9d\x67\x8e\xe8\xed\x56\xb8\x15\x6e\x4d\xd1\x7f\x1e\xec\xe2\
\xc2\xd1\xcc\xd0\x2a\xb7\xba\x8b\xe1\x6a\x7d\xe7\xc4\xf6\xa9\xb2\
\xa7\xd4\x6e\x29\xd8\xbf\x9a\x0b\x7a\x2d\xca\x1e\xff\x7c\xaa\x54\
\x79\x68\xf2\xe2\xa4\x5e\xfc\x4c\xa8\xe0\xd7\xdd\x36\x5d\xcc\x34\
\x86\xe8\xb4\xc7\x87\x30\xf5\x81\x20\x45\x80\x60\xad\xb5\xdf\xa6\
\x81\x1a\x2b\x42\x76\x7c\x7c\xbc\x5a\x8b\x2d\x6a\x13\x71\xbb\xa0\
\x32\xa1\x3c\x85\x8d\x62\xba\xf4\x97\x25\x31\x49\x3e\x56\x4e\xd8\
\xd6\x56\xff\xeb\xd2\xcd\xe2\xef\x7f\xb9\xbd\xda\x2a\x87\xd6\x39\
\xb4\xcc\xe1\x7c\xd0\x8e\x17\xde\x5c\xb8\x69\x61\x09\x7b\x35\x84\
\x5b\xe0\xa2\x8a\x69\x95\xc3\x2c\x4b\x47\xf5\xd3\x59\xf3\xc3\x2c\
\xf2\xe9\xed\xfd\xe9\xc8\xa8\x54\x98\xfb\x97\xb2\xae\xb2\xa8\xbe\
\xa8\x57\x62\x5a\xeb\x6a\xbe\x3a\x1a\xae\x41\xe7\xbd\x0e\x52\xd4\
\x50\xb1\x1b\x0d\x8e\xcd\x08\xcf\xe9\xe7\x88\xce\xfc\xc4\xe7\xfe\
\x45\xf0\xd8\x08\xf7\x4f\x62\xa0\x0c\x06\xf5\x84\xa1\x56\x18\x9e\
\xf4\x01\x7f\x67\x33\xb0\x26\x89\xc7\x00\x3c\x5f\x94\x38\xcd\xbe\
\x78\x5f\xeb\xed\x13\x1a\x94\xc4\xe4\x0f\xb5\xde\xbf\x5a\x50\xc3\
\x0e\xc2\xfa\x8b\x3b\xa0\x0a\xef\x41\x78\xa6\x29\x1c\x60\x3d\xae\
\xa8\xc9\x1f\x4a\xb3\xa3\xfd\x7d\xde\xb5\x59\x25\xd2\xdb\x03\x02\
\xbb\x84\x54\x77\x87\x49\x80\x74\x75\xcd\xa8\xd7\x32\x65\x72\x0e\
\xa3\x7f\x3d\x4c\x9c\x91\xb0\x7b\xa6\xff\x67\xe6\xaf\x9f\x9a\x8d\
\x33\xb7\x39\xb6\xb7\x18\x94\x69\x3e\x33\xd8\xd6\x3d\xa3\xd7\x42\
\xb5\x42\xda\x5d\x6b\xa3\x80\x4a\xaf\x0e\x0f\x48\x4f\x3e\xdb\xee\
\x60\xd5\x8f\x3f\x57\x71\xd4\xee\xb8\x3b\x40\x83\xfe\xd8\x63\x0b\
\x8a\xbe\x07\xf4\x35\x54\xef\xc7\x50\xb5\x0f\x55\x03\x7d\xbc\x68\
\xea\xc5\x7b\x60\x4a\x2d\x08\xd6\x46\xbb\xf4\x30\x54\x57\x3c\x36\
\x3b\x3c\x50\xf1\x1c\x7c\x4e\xd7\x3e\xb9\x36\x49\x32\x14\xaa\xb3\
\x2a\xb5\x30\xbe\x22\xaf\xf0\xfe\xd9\xee\x5a\x13\x8b\x14\x93\xde\
\x35\x35\xde\x68\x6e\xe5\x88\x8a\x03\xfe\xfe\xb0\x5e\x1b\x65\x5d\
\x28\x0b\xf4\x4a\xea\xd7\x2b\x23\xb2\x06\x88\x15\x68\x42\xa9\x96\
\x3d\x2f\x0e\x1f\x12\x8e\xc4\x0a\x4e\xf6\x17\x37\x46\xc3\x29\x75\
\xec\xd4\xfd\x53\x89\x4c\xe0\xd0\xe9\x50\xb5\x79\x8c\x56\x02\x00\
\x92\x0e\xd5\x30\x84\x2c\x76\x09\x42\xc8\x61\x59\x41\xe8\x3b\xc6\
\xfb\x5b\x6f\x74\x2d\x43\x75\xad\x95\x5d\x6c\x9c\x41\xe9\x88\x3b\
\xfc\xab\xda\xa6\x72\x4d\x0d\xea\xef\x56\x4b\xdf\x55\x29\xc5\x9c\
\xb3\x4e\x36\x7d\x88\xb2\x5c\xab\xe8\x7f\x4b\xfa\x3d\x4c\x7a\x7b\
\xb7\x62\x5e\x87\xf6\x50\x9c\x83\x16\xf8\xe1\x8a\xd1\xbf\xa6\x52\
\x83\x01\x4b\xd4\x69\x7a\xc5\xa0\x29\x01\xa1\xb5\x5b\xaf\x10\x0c\
\xcb\x5e\xa5\x6f\x43\x9f\x24\xfa\x27\xb1\xb2\x1a\x6e\x41\x4a\x3f\
\x1a\x19\x95\x2e\xf6\x95\x92\x37\xfb\x57\x35\xc5\x13\xea\x3d\x55\
\xd1\xcf\xe5\x03\x57\x66\xe2\xec\xab\x15\x57\xa7\x43\xf5\x91\x47\
\x1e\x59\x33\xaa\x17\x93\x39\xd4\x9a\xd0\xc1\x6c\x84\x0d\x0c\x1e\
\x8a\x33\xfb\x8f\xd1\xee\x50\x0d\x0a\x87\x1d\xd4\x7b\x6d\x10\xbe\
\x4f\xb7\x87\x6a\x9a\xd0\xc2\xe4\x78\x12\xa3\x47\x4d\xff\x9c\x1d\
\xfd\x63\xd7\x73\xd5\x36\x9b\x96\xa3\xa2\xf1\xdf\xc3\x76\xcd\x59\
\xbf\xe0\x55\xc4\x58\xdc\xa3\xd3\xe8\xed\x34\xb6\xd1\xa8\xd4\xec\
\xee\xc2\x86\x83\x4c\xda\xa8\x0b\xbe\x5c\x6b\x66\x40\xf7\x7f\x05\
\x21\x6c\x71\x1a\xeb\x17\x29\x3e\x04\xd8\xc7\xea\xe4\xce\x33\x63\
\xad\x14\x3c\x06\x1e\x2b\xc9\x40\xed\x34\x6c\x50\x6d\x76\x93\x09\
\x87\x5f\xbb\x47\xd9\xe2\xb9\xe1\x39\x06\x4b\x5c\x08\xcf\xb4\x9f\
\x2f\x35\x0f\x61\xa8\x7f\xb8\x36\xbd\xc7\x85\xae\x4d\xc7\x9e\x8b\
\xb6\xa8\xaa\xef\xe1\xe2\xba\x6d\xca\xab\x8e\xc0\x4d\x5a\xbf\xe3\
\x8a\x23\x38\x34\x9f\x7f\xb9\x2e\x5d\xe1\x41\xb3\x2f\xba\xb9\x56\
\xf6\x53\xa5\x8e\xc3\x70\x6c\x7c\x41\xb0\x33\x71\x70\xa7\x63\x33\
\x72\x16\x2b\xac\xab\xbf\x40\x51\xc2\x01\xd9\x48\xb0\x2f\xd5\xa8\
\x17\xaa\xe1\xdb\x50\x4b\xb6\x09\x3a\x5b\x68\xca\x45\x6d\x2a\x58\
\x6c\x5e\x63\xf8\xf9\xda\xbe\x3f\x94\xae\xf2\xce\xa9\xb2\xe7\xa9\
\x21\xab\x91\x2d\xfa\x6f\x3d\x21\xb7\x9d\xbc\x8f\x07\x2b\x87\xf2\
\xd0\xe4\xc2\xc4\xfd\x67\x9f\xf4\xd6\x5f\xd9\xa8\x6b\x96\xbb\xf5\
\xf6\xf3\x98\x14\x52\x6f\x2f\x9b\x2f\xba\x36\x33\x8e\xf5\x72\x6a\
\xe7\xd9\xcd\xcd\x1c\xb7\x96\xa1\x9a\x01\xf8\x75\xa3\x4f\xb0\x9f\
\x27\x1c\xd4\x1f\x0c\xec\x5c\x8c\x76\x32\x34\x29\xe0\xb6\x38\x23\
\xd2\xba\x0e\x42\xa8\xde\x60\x9d\x20\x84\x61\x38\x54\x51\xb3\x43\
\x93\x67\x2d\x68\x96\x0c\xf7\x49\xda\x1c\x50\x3b\x2a\xc4\xeb\x89\
\x0a\x78\x9b\xda\x26\x43\x34\x7f\xca\xf7\x4f\xcd\x60\xb0\x11\x46\
\xf1\xd6\xa5\x37\x12\xb2\x47\x56\x07\x26\xc5\x99\x8b\xb6\xdb\xa0\
\x45\x2d\xa9\x56\x3a\x1c\xd6\x12\xeb\xc5\x7f\x68\x6b\x0c\xd5\x8c\
\xd0\xdf\x19\xac\x44\x14\x34\x03\xa3\x86\x6a\x9a\x82\xf5\x2f\x2f\
\xd6\x52\x6b\x41\x1f\x5b\x9c\xda\x23\xc2\x30\xfc\x77\x8d\xfa\xf2\
\x10\xa8\xe1\x11\xb4\x66\x60\x50\x23\x08\xd4\x38\x7f\x17\x84\x50\
\x0d\x07\x2b\x5e\x5f\x9c\xb0\xc4\x6b\x0b\xff\xc0\x88\x0a\x69\xca\
\x20\xfd\x05\xc7\x6e\x31\xee\x3a\x29\x1c\x04\x2c\xf6\x3f\x47\xc8\
\xea\x52\xdd\x65\x46\x5f\x87\x30\x75\x70\xbd\xfe\x5b\xca\x36\x86\
\x6a\xb6\x98\xda\x2a\x9a\x80\xd1\x96\x3f\xaf\xbf\x43\x89\x8c\xba\
\x2d\x2a\x84\x09\x06\x30\xd5\xaa\x15\x9a\xdb\xc3\x13\xe7\xa3\x86\
\x1a\x67\x80\x0c\xfa\x2a\xc3\xb5\x55\x33\x58\x27\x2a\xcc\x11\x80\
\xb8\x2d\x3c\xa0\x26\xae\xa8\x29\x0a\x31\xb9\x43\xd4\xb2\x0c\xdc\
\xf6\xf4\xd3\x4f\xbf\xef\x6f\xa2\x66\x65\xa2\x0c\xd3\x5f\x76\x4c\
\x3f\xea\xa0\x46\x8a\x90\xd5\x05\x61\x5b\x9d\x92\x94\x61\x9a\x1b\
\x0c\xd5\x0c\xd1\xdf\x1b\xd4\x48\x83\x9d\xee\x6c\xf6\x8d\x01\x61\
\x82\x10\x43\x1f\x24\xc2\x05\xe7\x51\x10\xa6\xb8\x2e\xaa\x89\x38\
\xee\x88\x55\x84\x6f\xd4\x08\x5a\x04\x27\xc2\x2e\x6a\x79\xb6\x35\
\xd4\x20\x04\x7d\xb8\x76\x8c\xd7\x87\xc7\xc5\xe3\xa3\xc6\x8d\x59\
\x94\x50\x70\xde\x2c\x33\xdc\x4c\x8c\x40\xad\xd7\xb4\x4d\x44\xed\
\xc1\x50\xcd\x1e\x33\x87\x24\x6a\xa9\x6d\x39\x64\x5a\x51\x20\xec\
\x82\x4d\x9c\x08\x1f\xd4\x48\x51\x6b\x45\xa9\xd5\xdf\x8a\xdd\x38\
\x6c\x02\x07\x01\x15\x15\xac\xa8\x95\x86\x97\x17\x6c\xaa\xc5\x7d\
\x9a\x09\x36\x3c\xbf\xa8\x89\x1b\xf0\xf8\x26\x4c\x4d\xb8\x46\xbd\
\x46\xf4\x15\xdb\xec\xfa\x43\x44\xc9\x61\xa8\x52\x6e\x21\xb0\x50\
\xe3\x8c\xdb\xcc\x69\xfe\x1e\xb5\x41\x5b\x08\x48\x04\x55\x9c\x90\
\x44\x73\x31\xfe\x16\xf7\xa9\x37\xf9\x42\x2d\xb8\x0f\x66\x44\x8a\
\xbb\x3c\xc3\x2c\xd7\x66\xbf\x51\x22\x4a\x56\xa3\x31\x67\x94\xb2\
\x43\x2b\x03\x95\xd0\xa7\xba\x70\x78\x6d\x53\x70\x21\xdc\x75\xd7\
\x5d\xd5\xd7\x87\x00\xb0\xed\xf3\x43\x2d\x70\xe3\xc6\x8d\xab\x03\
\x7a\x50\x9b\x43\xe8\xdc\x7d\xf7\xdd\xd5\xa0\x34\xb5\xc4\x85\x85\
\xb5\xbb\xd6\xa2\xe6\x86\xdb\x51\x03\xbc\xed\xb6\xdb\xfc\x6b\xed\
\x6d\xd9\xb2\x65\xb5\x06\xb9\xb4\xb4\xf4\xbe\xe5\xe0\x39\x0d\x0f\
\x0f\x8b\xaf\x7c\xe5\x2b\xab\xfb\x8c\xe2\xef\x82\xcf\x19\xd7\xe3\
\x72\x1c\x58\x1e\x9e\xb7\x79\xce\x58\x1e\x1e\x2f\x08\xef\x23\xfe\
\x0e\xef\x25\x5e\x9f\x59\x6e\x1c\x78\xbf\xfa\xfa\xfa\x56\x9f\x1b\
\x0a\xde\xcb\x7a\xa2\xee\x63\xb3\x4c\xb4\x26\x84\xef\x1b\xf7\x87\
\x83\x59\xbf\xc1\xfb\x47\xd5\xe8\x6b\x41\xcd\x1e\x8f\xe1\x38\xce\
\xd1\x5f\xfc\xe2\x17\xef\x3f\xc8\x66\x87\x6c\xff\xab\x3b\xad\xc6\
\x4d\x9c\x3f\xfe\x2b\x76\x0b\x65\x18\xbb\xbf\x33\xc6\x9f\xf0\x01\
\x1d\x64\x68\xfe\x2d\xdc\xf0\xcd\x56\x66\x54\xb2\x61\x06\xed\xd8\
\xd4\xf4\x9a\x91\xd6\x72\x82\xcc\x32\x11\xa8\x28\x14\x0f\xfa\x9e\
\xf1\xde\x65\x61\x46\xa5\xa0\x7d\xaf\xed\xd2\x5f\xfb\xf8\x4e\x6c\
\x3f\xc3\xed\x76\x86\xb1\xf9\x37\x03\x4a\x2f\x3f\xb8\xb5\xf4\xa3\
\xe1\x12\xca\x3f\xfd\xe3\x3d\xa3\x7f\xf8\xd3\x1b\xfd\x5b\xa8\x59\
\x08\xb9\x34\x82\x2e\xad\xe5\x04\x99\x65\x32\x50\x89\xb2\x87\xa1\
\xda\x21\xa5\xe9\xc1\xfe\x3d\xaf\xee\x3a\xb8\xe7\xa5\x91\x77\x1d\
\xd1\x33\xeb\xb8\x72\x02\xe5\xe7\xf7\x7d\xe8\xc8\xdf\xfe\xfb\xa0\
\xf8\xbb\x7f\x7b\xa0\x7f\xcf\xcb\xc3\x98\xfc\x81\x88\x88\x72\x82\
\xa1\xda\x01\x7b\x5f\x19\x19\x75\x7a\x6f\xbc\x20\x3c\x75\x48\xc8\
\xe8\x09\xb5\xdf\xfe\xe8\x7a\x7d\xbd\x9c\x18\x7b\x65\x64\x3a\xee\
\xfc\x93\x44\x44\xd4\x59\x0c\xd5\x94\xed\x7d\xf5\xf3\x8f\x2a\x25\
\x9e\xad\x15\xa6\x61\x52\x89\x41\xa7\x4f\xea\x60\x1d\x8c\xf5\xf7\
\x44\x44\xd4\x39\x0c\xd5\x14\xa1\xc6\xa9\x2a\x9e\xd9\x0f\xd5\xc6\
\x80\x5c\x77\x23\x8e\xd9\x47\x44\x44\x19\xc6\x50\x4d\x91\xd3\xe7\
\x1c\x8c\x5b\x43\x0d\x43\x8d\xb5\xf4\x22\x0e\xa2\x4c\x44\x44\x59\
\xc5\x50\x4d\xc9\x4a\xbf\xa8\x6a\x69\xe0\x91\x74\xa5\x39\x14\x1c\
\x11\x11\x65\x10\x43\x35\x25\x4e\xaf\xc4\xa1\xdc\x5a\x52\xad\xad\
\xb2\x6f\x95\x88\x28\xb3\x18\xaa\x29\x51\x42\x6d\xf5\xcf\xb6\xa6\
\xaf\x97\x23\x81\x89\x88\x32\x8a\xa1\x9a\x12\x47\xc8\x3b\xfc\xb3\
\xad\xf1\x5c\xd6\x54\x89\x88\x32\x8a\xa1\x4a\x44\x44\x94\x10\x86\
\x6a\x06\xac\x77\x97\xc5\x43\x1f\xbe\x28\xc6\x6e\xfb\x95\xb8\x6f\
\x63\xed\x83\x51\x13\x11\x51\xb6\x31\x54\x3b\xec\x96\xbe\x6b\xe2\
\x6b\x77\xfe\x4c\x7c\x41\x87\xea\x7d\x7f\xf2\xbf\x62\xec\xf6\x5f\
\x8b\x2f\x7d\x64\xed\x01\xa7\x89\x88\x28\x1f\x18\xaa\x1d\xf6\xb9\
\x5b\xdf\x14\xb7\xea\x60\x0d\xfa\xdc\x87\x7e\xa7\xaf\xbb\xea\x5f\
\x22\x22\xa2\xbc\x60\xa8\x76\xd8\x2d\xbd\x6b\x03\xd5\x40\x0d\x96\
\x88\x88\xf2\x85\xa1\xda\x61\x17\xaf\x46\x1f\xbe\xeb\x0f\x8b\xeb\
\xfc\x73\x44\x54\x70\xf3\xfe\x69\x2c\x8f\x9f\xdf\x95\xcc\x9e\x04\
\xd4\x16\x0c\xd5\x0e\xfb\x8f\xb7\x3f\x22\x2e\x5e\x59\xef\x5f\x5a\
\xf1\xfc\xef\x6f\x17\x6f\x2f\xde\xe0\x5f\x22\x22\xa2\xbc\x60\xa8\
\x76\xd8\xe5\x4a\x8f\xf8\x87\x5f\x6d\x15\xdf\xfc\xcd\x27\xc5\xc4\
\x6f\x3f\x2e\x0e\xfc\xfc\xd3\xe2\x7b\x3a\x54\x89\x88\x28\x7f\x18\
\xaa\x1d\x26\x5d\x29\x9c\x3e\x29\x7e\xbd\xdc\x2f\xce\x5d\xfe\xb0\
\xb8\xd6\xd3\x8b\x29\x0d\xf5\x0d\xfe\x1f\x10\x11\x51\x6e\x30\x54\
\x3b\x45\x87\x26\xc2\xd4\xe9\xd5\x67\x83\x6b\x01\x79\xea\x0a\xe1\
\xea\xdb\xd6\x5c\x4f\x44\x44\x99\xc7\xcd\x76\x87\x38\x3d\x0d\x42\
\xd3\x0f\x5d\xd6\x58\x89\x88\xf2\x83\xa1\xda\x01\x08\x53\xd4\x46\
\xe3\xa8\x36\x05\x13\x11\x51\x2e\x30\x54\x3b\x00\xfd\xa8\x71\x55\
\x6b\xb3\xcc\x55\x22\xa2\x5c\x60\xa8\x76\x02\x43\x92\x88\xa8\x90\
\x18\xaa\x29\xf1\x84\x7a\xc3\x3f\x6b\x4d\x32\x84\x89\x8a\x4b\xc9\
\x05\xff\x5c\x2c\x8b\xcb\x4b\x1b\xfd\xb3\x94\x41\x0c\xd5\x94\x48\
\x65\x37\x6b\x4a\x4d\xcb\x57\xe7\xfc\x73\x44\x54\x04\x8e\x67\x15\
\xaa\x4a\xf2\x98\xca\x59\xc6\x3a\x50\x4a\x4a\x2f\x0e\x0f\x3a\x8e\
\x9c\xc6\x79\x8c\xea\xb5\xd9\x5d\xc6\x5b\x54\x42\x79\xd5\x95\x35\
\x77\x72\xe7\xd9\x6d\xfe\xd5\xb9\x34\x3a\x3a\x3a\xa0\x94\xba\xb0\
\x61\xc3\x06\xb1\x63\xc7\x0e\xff\x5a\xa2\xf6\x3b\x77\xee\x9c\xb8\
\x74\xe9\x92\x70\x5d\x77\xe0\xf4\xe9\xd3\x4d\xb7\x1c\x25\x6d\xdf\
\xf9\x91\x69\x9d\x94\x83\xfe\xc5\x86\x94\xe7\x0d\xfd\xf3\x9f\x4f\
\xcd\xf8\x17\x29\x63\x18\xaa\x29\x1a\x7b\x69\x64\x5a\x4a\x31\xe8\
\xae\xd3\x6f\xbb\xc5\x3b\x5f\xb9\xa6\xf4\x37\x09\xe7\xd4\xd8\xa9\
\x9d\x53\xe5\xea\x95\x39\x65\x42\xd5\xbf\x48\x94\x3a\x86\x2a\xb5\
\x13\x43\x35\x45\xa6\xb6\xda\x64\xa8\xce\x9f\xda\x79\x76\xb3\x7f\
\x55\x6e\xe9\x50\xed\xaf\x54\x2a\xa3\xfe\x45\xa2\xd4\xe9\x50\x9d\
\xd4\xac\x9a\x5c\xdb\x89\xa1\x5a\x2c\x0c\xd5\x94\xed\x79\x71\xf8\
\x90\x7b\xa3\x73\xd0\x32\x54\xe7\x3d\xa9\x86\xca\xf7\x4e\x25\xd3\
\x2f\x4b\x44\x99\xc1\x50\x2d\x16\x0e\x54\x4a\xd9\xa9\xfb\xa7\x0e\
\xe9\x40\xb5\x0a\x47\xb7\x67\x79\x37\x03\x95\x88\x28\xfb\x18\xaa\
\x39\xd0\xd7\xd3\xfb\xae\x7f\x96\x88\x0a\x46\x79\xc2\xaa\x7f\xd7\
\x53\xce\x80\x7f\x96\x32\x88\xa1\x4a\x44\x44\x94\x10\x86\x2a\x11\
\x11\x51\x42\x18\xaa\x44\x44\x44\x09\x61\xa8\x12\x11\x11\x25\x84\
\xa1\x4a\x44\x44\x94\x10\x86\x2a\x11\x51\x07\x29\x61\x37\xa1\xbe\
\x23\x15\xe7\xfe\xcd\x30\x86\x2a\x11\x51\x07\x49\x25\x2c\x67\x77\
\x92\x0c\xd5\x0c\x63\xa8\x12\x11\x11\x25\x84\xa1\x4a\x44\x44\x94\
\x10\x86\x2a\x11\x11\x51\x42\x18\xaa\x44\x44\x44\x09\x61\xa8\x12\
\x11\x11\x25\x84\xa1\x4a\x44\x44\x94\x10\x86\x2a\x11\x11\x51\x42\
\x18\xaa\x44\x44\x44\x09\x61\xa8\x76\x82\xb2\x9b\x41\x65\x71\x79\
\x69\xa3\x7f\x96\xba\xc3\xa0\x2e\x13\xba\x5c\xd0\x45\xf9\x05\xc7\
\xd4\x9d\xd6\xa5\xa4\x0b\x11\x65\x14\x43\xb5\x13\x1c\xcf\x2a\x54\
\x95\x74\x39\x83\x4a\xf7\x38\xa2\x0b\xc2\x73\x54\x97\x19\x5d\x0e\
\xeb\x72\x4c\x17\x7c\x66\x4c\xd8\xe2\x76\x7e\x26\x88\x32\x88\xa1\
\x4a\x94\x1d\x07\x75\x79\x52\x17\x04\xe8\x66\x5d\xc6\x74\x39\xe4\
\x5f\x87\xcb\xcf\xe8\x02\x08\x57\xfc\x2d\x11\x65\x0c\x43\x95\x28\
\x1b\x50\xf3\x44\x80\x02\x42\x35\xaa\x35\xc3\x04\x2e\xe0\xfc\x1d\
\x2b\x67\x89\x28\x2b\x18\xaa\x9d\x60\xd9\xa7\xaa\xa4\xc7\xa6\x3e\
\x02\x7c\x6e\x4c\x6d\x15\x86\xfc\x53\x22\xca\x08\x86\x6a\x07\x28\
\xa5\xde\xf3\xcf\xc6\xa2\xbc\x1e\x86\x6a\xf1\x21\x30\xd1\x7f\x3a\
\xe7\x97\x5a\xe6\xfd\x53\x18\xf0\x4f\x89\x28\x23\x18\xaa\x44\xd9\
\x81\xe6\xdf\x6d\xba\xec\xae\x5e\x6a\xcc\xaa\xc5\x83\x32\x4a\x2a\
\xcb\x1f\x47\x8a\xeb\x3d\xc3\x18\xaa\x1d\x60\x7f\x50\x62\xd6\x48\
\x68\xd5\x9f\xf9\xa7\x80\xd1\xc1\xd4\x65\x3c\xcb\xee\x23\x4a\x17\
\x43\xb5\x03\x6c\x0f\x4a\x2c\x79\xa4\x7f\xba\x0e\x23\x7f\x01\x81\
\x5a\xaf\x99\x98\x72\x42\x4a\x79\xb3\x7f\x96\x0a\x80\xa1\xda\x01\
\x9e\xb3\xa6\x5f\xac\x31\x7e\xe9\x68\xc5\x01\x5d\x4c\xab\x05\x76\
\xb7\xa1\x22\xb0\xfc\xd1\xec\x48\xcf\x6e\xfb\x41\xa9\x62\xa8\xe6\
\x81\xf2\x38\xa3\x12\x21\x4c\xcd\x2e\x37\x18\xd0\xc4\x0d\x6b\x51\
\x78\x0e\x5b\xa2\x0a\x84\xa1\xda\x01\x6e\xc5\xb2\xd9\x4e\x3a\xc1\
\x7e\x34\xea\x3e\x08\x54\x33\x8b\x12\x66\x57\x32\xe1\x4a\x45\x60\
\x39\x66\x62\x9d\xeb\x60\xfa\x4a\xca\x28\x86\x6a\x07\xb8\xbd\x76\
\xd3\x14\x6a\xfc\x25\xdb\xbd\xb0\xee\x9f\xd5\x05\x1b\x5e\xec\xa3\
\x8a\x49\x1f\xa8\x50\xec\x9a\x7f\x2f\xc9\xcb\x56\xbb\xe4\x51\xba\
\x18\xaa\x1d\xf0\xed\x6d\x53\xb6\x4d\x77\xfd\x8f\x9f\xdf\xc5\xd9\
\x73\xba\x8f\xa9\xa1\x6e\xd5\x05\x35\x54\x4e\xa6\x5f\x30\xfb\x7e\
\xbc\x0b\xeb\xd6\xc6\x42\x79\xdb\x0c\x47\xff\x66\x18\x43\xb5\x73\
\xac\x82\xf5\xca\x32\x67\xcf\xe9\x32\xc1\x40\x45\x1f\x2a\x6b\xa8\
\x05\xe4\x39\x96\xfb\xa8\x4a\xc5\xbe\xf4\x8c\x63\xa8\x76\x8e\x55\
\xbf\xaa\xeb\x28\xdb\x5f\xb4\x94\x5f\x58\xd7\x08\x54\x6c\x70\xc7\
\x75\x89\xea\x43\xc5\x6d\xb8\x9e\x5d\x03\x39\x26\x95\xb4\xfb\x5e\
\x7b\xea\x0d\xff\x1c\x65\x14\x43\xb5\x43\x3c\x25\xec\xbe\x1c\x8e\
\x78\xc0\x3f\x47\xc5\x86\x43\xbe\x99\x41\x49\x68\x9d\x38\xaa\x4b\
\x14\x73\xa4\x1a\xee\x6e\x95\x63\xd2\x55\x56\xdf\x6b\xa5\x1c\xee\
\x9b\x9c\x71\x0c\xd5\x8e\x51\x76\xb3\xe1\xe8\x5f\xb4\xfb\x7e\xfc\
\x20\x6b\xab\xc5\x86\x90\xc4\xa0\x24\xf4\x99\x61\xba\xc2\x7a\x9f\
\x11\xfe\xc8\xca\xb9\xd2\xec\x68\xbf\xfe\x5e\x9b\xc9\x3c\x62\x51\
\x72\x99\xa1\x9a\x71\x0c\xd5\x0e\xa9\xb8\xeb\xac\xa7\x98\x93\xb2\
\x17\xb5\x18\x2a\x26\x04\xaa\x69\xe6\x45\x2d\x15\xb5\x55\xec\x3a\
\x51\xab\xf0\xb3\x90\x73\xbd\xde\xa2\xf5\x3a\xec\x5d\x62\x4d\x35\
\xeb\x18\xaa\x1d\x52\xde\x36\xb9\x20\xa4\x5d\x6d\x55\x39\xe2\x40\
\xe9\xd5\x61\xbb\x81\x0d\x94\x17\xc1\x1a\x0b\x42\x15\xeb\xb9\x5e\
\x61\x5f\x6a\xde\x49\xf5\xa8\x7f\x2e\x16\x29\xd4\xfc\xb7\xef\xb5\
\xde\x73\x80\x52\x26\xfd\x53\xea\x80\x2f\xff\x64\xd7\x21\xe9\x54\
\x6b\x28\xf1\xe9\x20\x3e\x71\xf7\x59\x8e\x04\x2e\x1e\xec\x2e\x83\
\xb0\xb4\x85\x3e\x57\xee\x62\x91\x33\xfb\x5e\xdb\x85\xf5\x3d\xb1\
\x72\x29\xb6\xf2\x89\xed\x67\x38\x3d\x65\xc6\x31\x54\x3b\xa8\xba\
\x8f\x9a\x2b\x66\xfd\x8b\xb1\xe9\x5f\xac\x93\x8b\xce\x95\x31\xee\
\xaf\x46\x94\x3f\x25\xfd\xbd\xef\x71\xe5\xb4\xfe\x1e\x5b\xb5\x36\
\x78\x6a\x79\xf7\xc9\x7b\xbe\x3f\xe9\x5f\xa4\x8c\x62\xa8\x76\xd8\
\xbe\xf3\x23\xd3\xb6\x83\x15\x7c\x68\x06\x3a\xac\x7f\xb9\x96\x57\
\x2e\x12\x51\x96\x95\x66\x07\xfb\xfb\xc4\xfa\x03\x9e\x27\x9f\xb4\
\x0d\x54\x34\xfd\x1e\xdf\x7e\x76\xb3\x7f\x91\x32\x8c\xa1\xda\x61\
\xfb\x5e\x1b\x2e\x09\xe1\xd8\x36\x03\xad\xc2\xb1\x59\x1d\xe1\xcd\
\xe8\xd3\xe7\x44\x65\x69\xee\xc4\xa7\x7f\xc0\x81\x0c\x44\x19\xf1\
\xd8\xab\xc3\x03\x4b\xbd\x72\xab\xeb\x8a\x07\x3c\xcf\x29\xd9\x86\
\x69\x00\x9b\x7e\x73\x82\xa1\x9a\x01\xfb\x5f\x1b\xb9\xa0\x43\xb1\
\x99\xfe\xb4\x1a\xd4\xbc\x5e\xb3\xd5\x01\x0d\x8e\x92\xab\x03\x1b\
\x2a\x9e\xe5\xbe\xb1\x44\x14\x8b\xeb\x88\xd5\x69\x44\x95\x0e\x4e\
\x25\xe5\x80\x52\x72\xa0\x85\x10\x5d\xc3\x5d\xf4\x36\x73\x90\x52\
\x3e\x30\x54\x33\x60\xef\x4f\x47\x46\x1d\x29\xb1\x7f\x22\x11\x51\
\x18\x6b\xa9\x39\xc2\x5d\x6a\x32\xe0\xe4\x3d\x67\x27\x6d\x77\xaf\
\x21\xa2\xae\xb0\xa0\x6b\xa9\x98\xfb\x99\x72\x82\xa1\x9a\x11\xae\
\x54\x63\x18\x8c\xe0\x5f\x24\x22\x12\xca\x53\x87\xd9\xec\x9b\x2f\
\x6c\xfe\xcd\x90\x66\x77\xb1\x21\xa2\x42\x62\xb3\x6f\x0e\xb1\xa6\
\x9a\x21\x27\x3e\x7d\x66\x4e\x08\x8f\x5f\x22\xa2\x2e\x27\xa5\x98\
\xdb\xe0\x5c\xc6\x11\x8a\x28\x67\x18\xaa\x19\x73\x62\xfb\x54\xd9\
\x53\x6a\xb7\xfe\x5a\x71\x62\x07\xa2\x2e\x84\x40\x5d\x2f\x2f\x0f\
\x1d\xe5\xe4\x2e\xb9\xc4\xe6\xdf\x8c\x7a\x6c\x76\x78\xc0\xf3\xe4\
\x74\xb2\xbb\xda\x10\x51\xa6\x29\x75\xec\xc4\x3d\x67\x79\x40\xfa\
\x1c\x63\xa8\x66\x1c\xe6\x07\x76\x1c\xf5\x28\xc3\x95\xa8\xb8\xaa\
\x83\x14\x95\x18\x3f\x8e\x3d\x01\x28\xd7\x18\xaa\x39\x80\x5a\xeb\
\xf2\xb2\x53\x62\xb8\x12\x15\xce\x82\xf2\xc4\xb1\x9b\x7a\x2e\x1f\
\x65\x73\x6f\x31\x30\x54\x73\xa6\x3a\xad\xa1\x72\xbe\xa8\xd7\x1c\
\xe6\x0b\xe6\xe1\xbf\x88\x72\x48\x29\x35\xe3\x49\xf5\xcc\x07\x9d\
\xab\x93\x0c\xd3\x62\x61\xa8\xe6\xd8\x97\x7f\x32\xac\x83\x55\x6e\
\x95\x52\x3e\xa0\x84\x18\x90\x92\xc7\xd9\x24\xca\x1e\x34\xed\xca\
\x39\x21\xd5\x1b\x9e\x12\x33\x1f\x70\xaf\xcc\x30\x48\x8b\x8b\xa1\
\x5a\x30\x4f\xce\x0e\xf6\x5f\x5a\x5a\x3f\xa0\xa4\x87\xf9\x47\x75\
\xb9\x3e\xf7\xa8\xe3\x39\x6c\x3a\x26\x6a\x0b\xb5\xe0\x39\x6a\x35\
\x28\x1d\x4f\xcc\xf7\x2c\x8b\xf9\x1b\x6e\xb8\xba\xc0\x00\x25\x22\
\x22\x22\x22\x22\x22\x22\x22\x22\x22\xca\x39\x21\xfe\x1f\xf5\x3f\
\xad\x40\x47\xc3\xfd\x1e\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\
\x60\x82\
\x00\x00\x00\xd1\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xff\x61\
\x00\x00\x00\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\
\xa7\x93\x00\x00\x00\x86\x49\x44\x41\x54\x38\x8d\xd5\xd1\x3d\x0a\
\xc2\x50\x10\x04\xe0\xcf\x84\x74\x5e\x44\x09\x08\x82\x57\xb0\xb0\
\x92\x1c\xca\xc2\x83\xa4\x91\x5c\x44\x3c\x83\x95\x7f\x67\x10\x82\
\x29\xb4\x90\xe0\x7b\x42\x52\x84\x0c\x2c\x2c\xcc\xec\xec\xb0\xcb\
\x98\x50\x62\xd5\xc7\x60\x8d\x07\x96\x7d\x4c\xb6\xb8\x61\x1e\x13\
\x4d\xb1\xc3\x19\x35\x5e\x3f\xea\x88\x49\x68\xf8\x84\xea\x13\x35\
\x6b\xf1\x05\xae\x98\x85\xb6\xef\x71\x08\x70\x1b\xdc\xb1\x88\xc5\
\xbf\x20\x0f\x70\x7f\xbf\x90\xe1\x89\x34\x26\x6a\x23\xf9\xea\x53\
\xef\xa3\xd5\x5d\x0d\x3a\x61\x78\x83\xe1\xd1\x00\x11\x26\x16\x72\
\x44\x98\x03\xe0\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
\
\x00\x00\x01\x1a\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x20\x00\x00\x00\x20\x08\x06\x00\x00\x00\x73\x7a\x7a\xf4\
\x00\x00\x00\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\
\xa7\x93\x00\x00\x00\xcf\x49\x44\x41\x54\x58\x85\xed\x96\x41\x0a\
\xc2\x30\x10\x45\x9f\x42\x77\xc5\x73\x68\xdd\xa8\x3b\xcf\xa2\x47\
\x52\x51\xd0\xc3\xe8\x35\xbc\x41\xd1\x0b\xd8\x8d\x52\x21\x2e\x66\
\x0a\x6e\xda\x26\x25\x45\x90\xf9\x10\x7e\x20\x93\xfc\x97\xb4\x25\
\x05\x93\xa9\x5d\x4e\x5b\x2f\xf3\x86\x1d\x16\x8e\x2a\x03\x30\x00\
\x03\x30\x00\x03\xf0\x01\x28\xd4\xd3\x80\x75\x47\xea\x8f\x18\x00\
\xb9\xfa\x34\x00\xa0\xaa\xcd\x1b\xab\x3c\x01\x2e\xea\xab\x00\x80\
\xb5\xfa\x39\x60\x4e\xad\x32\xe0\x0d\x3c\x81\x99\x47\xfd\x02\x78\
\x01\x25\x30\x8e\x01\x00\x70\x40\xee\xf6\x1b\x30\x6f\x09\xbf\x6b\
\xed\x2e\x56\x38\x40\x82\x3c\x0a\x87\xec\xee\x08\x2c\x91\x17\x33\
\xd5\xfe\x49\xc7\x1c\x72\xf4\x49\x4c\x80\x0a\x62\x8f\x1c\xad\xab\
\x69\x25\xb2\xf3\xe8\xe1\xdf\xca\x80\x2d\x70\x45\x3e\xd1\x42\xfb\
\x1b\x60\xd2\x67\xf0\x7f\x6a\xd0\x30\xd6\xe5\x4f\x38\x38\xeb\xe7\
\x77\x81\xc9\xf4\x01\x03\x59\x2a\x74\x94\x02\x88\x2a\x00\x00\x00\
\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
\x00\x00\x00\x85\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x20\x00\x00\x00\x20\x08\x06\x00\x00\x00\x73\x7a\x7a\xf4\
\x00\x00\x00\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\
\xa7\x93\x00\x00\x00\x3a\x49\x44\x41\x54\x58\x85\xed\xd4\x21\x0e\
\x00\x20\x0c\x03\xc0\xc1\xff\xff\x0c\x9e\x2c\x20\x08\x20\xb8\x93\
\x35\x35\x4d\x23\xe0\x77\x25\xc9\xda\xcd\xce\x7a\xb8\x8c\xa5\x6c\
\x03\xa3\xdd\x4d\x4c\x3b\x6c\xe0\x39\x3f\x80\x1f\xc0\x0f\x00\x74\
\x6a\x27\x05\x10\x5a\x70\x8c\x42\x00\x00\x00\x00\x49\x45\x4e\x44\
\xae\x42\x60\x82\
\x00\x00\x0d\x3b\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x64\x00\x00\x00\x64\x08\x06\x00\x00\x00\x70\xe2\x95\x54\
\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\x00\x00\x00\
\x09\x70\x48\x59\x73\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7\x6f\
\xa8\x64\x00\x00\x0c\xd0\x49\x44\x41\x54\x78\x5e\xed\xdd\x65\x8c\
\x34\x49\x1d\x06\xf0\xc3\xdd\xdd\xdd\xdd\xdd\xdd\x3d\x10\x24\x10\
\x82\x7c\x21\x40\x80\x0f\x90\x00\xc1\x12\x2c\x81\x0f\x38\x81\xe0\
\x10\x20\x84\x04\x09\x10\x9c\xc3\x1d\x0e\x77\x77\x77\x87\xe7\xf7\
\xee\xf6\xbd\xc3\xa4\xab\xba\x67\xae\xbb\x67\x76\xa7\x9f\xe4\xc9\
\xde\xee\xed\xbb\x53\x5d\xff\xaa\xbf\x57\xf5\x31\x33\x66\xcc\x98\
\x31\x63\xc6\x8c\x19\x33\x46\xc0\x89\xf6\xbf\x1e\x04\x9c\x23\xbc\
\xd0\x3e\xcf\x16\x9e\x76\x81\x27\x0b\xff\x19\xfe\x29\xfc\xe3\xfe\
\xd7\x5f\x86\xdf\xdd\xe7\x2f\xc2\x03\x81\x6d\x14\xc8\x89\xc3\x33\
\x86\x57\x0e\xaf\x16\x5e\x35\xbc\x48\x78\xfa\xf0\xe4\xa1\xc9\x3f\
\x49\xe8\xf7\xd0\x33\xe0\x7f\xf7\xf9\x9f\x7d\xfe\x3b\x24\xa4\xbf\
\x87\xbf\x0f\xbf\x19\x7e\x3a\xfc\x54\xf8\xb9\xf0\x0f\xa1\xdf\xdf\
\x2a\x6c\x8b\x40\x4e\x1a\x9e\x2f\xbc\x71\x78\xa3\xf0\xd2\x21\x01\
\x34\x3b\xe0\x94\x61\x33\xf9\xab\xa2\x11\xd2\x5f\xc3\x3f\x87\x76\
\xcf\xef\xc2\x2f\x85\xef\x0d\xdf\x1f\xfe\x34\x24\xc0\x8d\x63\xd3\
\x02\x39\x7b\x78\xed\xf0\x26\xa1\x1d\x71\xae\xf0\x2c\x21\x21\x10\
\xc0\x58\x20\x20\xaa\xed\x57\x21\x61\x7c\x26\x7c\x77\xf8\xf1\xf0\
\xd7\xe1\xc6\xb0\x29\x81\x9c\x33\xb4\x13\x6e\x15\x5e\x31\x3c\x77\
\x78\xa6\x70\x4c\x21\x94\x60\x67\xfc\x36\xfc\x51\x78\x5c\x48\x30\
\x1f\x08\x7f\x18\x4e\x8e\xa9\x05\x72\x9e\xf0\x16\xe1\x0d\xc3\x2b\
\x84\x0c\xf4\xe9\xc2\x6d\x81\x5d\xf3\xfd\xf0\xf3\xe1\xbb\xc2\xf7\
\x84\x3f\x0b\x27\xc3\x54\x02\x61\x03\xae\x17\xde\x21\x24\x8c\x0b\
\x87\xa7\x0a\xb7\x15\x6c\xcd\xb7\xc2\x0f\x86\x6f\x0f\x8f\x0d\xd9\
\xa0\xd1\xc1\x5b\x19\x1b\x97\x09\xef\x13\xde\x37\xbc\x65\x78\xde\
\x90\xa7\xb4\xcd\xe0\xcd\x71\xb3\x2f\x19\x5a\x3c\xd4\xe9\x6f\xc2\
\xd1\xed\xcb\x98\x3b\xc4\xa4\xb3\x13\x77\x0f\x6f\x1d\x8a\x1d\x86\
\x58\x00\x8d\x41\xfe\x5b\xc8\xa5\xfd\xc7\xfe\xcf\xd8\x1f\x13\x69\
\x37\xda\x7d\xa7\xd9\xff\xd9\x09\x05\x1b\xc3\xf0\xbf\x2d\x7c\x43\
\x68\xb7\xfc\x2b\x1c\x05\x63\x08\xc4\xdf\xb4\xa2\x6e\x13\xde\x3f\
\xbc\x66\x68\x92\x56\x45\xe3\xae\xf2\x84\x7e\x12\xfe\x3c\x64\x7c\
\xb9\xac\x56\x2a\xb5\x42\x8d\x10\x8a\x49\x23\x6c\x9f\x83\xbc\x34\
\xde\x9a\x78\xc6\x58\xac\x76\x8e\xc3\x59\x43\xe3\x5b\xe7\xb9\x7d\
\xde\x47\xc2\x97\x85\xef\x0c\x8d\x63\x70\x0c\x2d\x10\x2b\x92\xe1\
\xb6\x2b\x1e\x12\x52\x4f\xab\xec\x0a\x42\xb0\xe2\x19\xd2\xef\x85\
\x3c\x1d\xba\xfc\xeb\xe1\xb7\x43\x2b\x55\x04\x4e\x08\x5d\x20\x18\
\xbb\x92\x20\x04\x96\x97\x08\x2f\x1a\x8a\x77\x2e\x18\xf2\xf4\xc4\
\x3f\xab\xcc\x81\x9d\xf1\x9d\xf0\x79\xe1\xeb\x43\x19\x80\x41\x83\
\xcb\x21\x05\xe2\xe1\x3c\xe8\xbd\xc3\x47\x85\xa7\x0e\xfb\xfe\x7d\
\x3b\x41\xe4\x4c\x08\x22\x6a\xd1\xf4\x87\x43\xde\xce\x90\xc6\xd4\
\x98\xae\x12\x5e\x37\x94\x05\x20\x28\x63\x5e\x25\xee\x21\x00\x91\
\xff\x33\xc2\xd7\x86\xdc\xe5\xad\x08\x2a\x17\xc1\x5e\x5c\x2a\x7c\
\x66\x68\xf5\x1a\x74\x1f\x7a\x10\xc6\xf2\xb3\xe1\x8b\xc3\xdb\x85\
\x67\x08\xa7\x00\x55\x76\xe7\xf0\xe5\x21\xc1\x53\x87\xc6\xd3\x36\
\xce\x65\x5a\x40\x9e\xf3\x29\xa1\x5d\x67\x31\x6e\x0d\x0c\x86\x37\
\x62\x1b\xdb\xd2\x6d\x0f\xd0\x46\x3a\x99\x2a\x7a\x51\xc8\xf8\xaf\
\x63\x67\x86\x00\x07\xe0\xe6\x21\xdb\x60\x77\x1a\x97\x09\x6f\x1b\
\xf3\x32\x3d\xef\xb3\x42\x3b\x6d\x0a\x8f\xb5\x13\x06\x61\x30\x4f\
\x0d\xfb\x0a\xc3\xef\x31\xca\x0c\xe3\xdd\x42\xde\xd0\x36\x80\xda\
\x62\xfb\x8c\xcb\xae\x5d\xe5\x79\x9e\x1c\x9e\x3f\xdc\x44\xa6\xe1\
\x78\xb0\x0f\x8c\xf6\xe3\xc3\xbe\x6a\x8a\xc1\x96\x0e\x7f\x74\xc8\
\xf8\x6f\x23\x2e\x10\x3e\x31\x14\xb1\xcb\x16\xb7\x3d\xc7\x32\xb9\
\xe0\xec\x26\x47\x61\x68\x47\xa9\x37\xce\x1c\x3e\x3c\x94\x3d\x6d\
\x1b\xe4\x32\xad\xa4\x8f\x86\xdc\xe1\x53\x84\xdb\x0c\x6a\xec\xae\
\x21\xe7\xa2\xef\x4e\x11\x1b\x3d\x30\x9c\xca\x06\xfe\x1f\xd8\x8d\
\x7b\x84\x56\x51\x5f\x7d\xfb\xca\x50\x5a\x7d\xe8\x15\xc4\x8d\xc5\
\xa1\x41\xfd\xc8\x40\x0b\x06\xdb\x9e\x67\x99\xe6\x81\x4b\x7c\xdb\
\x70\x72\x7b\xc2\x08\xab\x25\xf4\xf1\x4a\x0c\x94\xc1\xbf\x58\x38\
\xa4\x8e\xbd\x63\x28\x36\x69\x3e\x47\xbc\x72\xfb\x70\x48\x98\x58\
\xde\xe3\xf3\xc3\x3e\xcf\x6a\x37\xc9\x7d\x5d\x2b\x9c\x0c\x3c\x2a\
\x9e\x91\xf8\xa0\x6d\x50\x8b\xf4\x10\x0c\x9e\xac\xee\x90\xab\x86\
\x30\xda\x76\xa6\xcf\x1b\x5a\x28\x0d\xc4\x1d\x7d\x84\xf2\x97\xf0\
\xd9\x21\x67\x67\x74\x70\x4d\x1f\x16\xfe\x38\x6c\x1b\xcc\x32\x9f\
\x13\x0e\x2d\x0c\x2a\x6f\x71\x67\x2c\x93\xeb\x3a\x06\x2e\x1e\x3e\
\x37\x6c\xfb\xcc\x65\x0a\x16\x1f\x1c\x8e\xee\xca\xdf\x2c\x54\xc0\
\xe9\x32\x74\x56\x12\x9b\xe1\x21\x86\xd6\xa7\xdc\xcb\xb6\xcf\x5c\
\xe4\x18\x36\x05\x64\xae\xa5\x4c\xda\x3e\x73\x91\xe6\x47\x32\x52\
\xc9\x61\x34\x28\xaf\xda\x8a\x92\x6a\x6d\x83\x68\xc8\x55\xfc\x44\
\x78\xd9\x70\x0c\xe3\x66\x52\xda\x3e\x77\x91\x7e\x67\x0c\xc8\x48\
\x48\xb9\x7c\x32\xec\x72\x66\xc4\x32\x22\x79\x65\xea\x51\x20\x47\
\xf5\x85\xb0\x36\x10\x2b\xe3\x07\x21\xd7\x76\xac\x20\x69\x93\x02\
\x01\x29\x7e\x36\x4c\x62\xb1\x66\x53\xcc\x13\xc1\x49\xcf\xf4\x46\
\xdf\x49\x13\x00\xf2\xac\xe4\x6d\x4a\x6e\xab\x41\xf0\xc5\x5f\x18\
\x2a\x7d\x1a\xd0\x61\x84\xe0\xd6\xf3\xbd\x20\x6c\x02\xe2\x36\x98\
\x27\x1e\x9a\x0a\xa9\x80\xb1\x17\xfa\x0a\xe4\xfa\xa1\x2c\xa9\x6c\
\x69\x09\xa2\x55\x5d\x1b\xaf\x08\xfb\xa4\xc7\x0f\x32\xe4\xbb\x5e\
\x1a\x0a\x1c\x09\xa8\x04\xe9\x98\x6b\x84\xbd\xdd\xe0\x3e\x02\x51\
\x53\xd0\xa6\xa3\x94\x59\x82\xdd\xa0\x56\xf1\x92\x90\x07\x76\xd8\
\x61\x57\x50\xcd\xdc\x7f\x79\xb9\x9a\x36\x50\x87\xb1\x4b\x14\xcc\
\x3a\xd1\x47\x20\x24\x7c\xf9\xb0\xd6\x1d\xa2\x96\xa1\x21\x40\x62\
\x6e\x97\xf0\xd6\x50\x49\x57\xec\x51\x82\x54\x8a\x88\xff\x4a\x47\
\xbe\xeb\x40\x97\x40\xa4\x48\x48\x57\xc2\xad\x04\xab\x83\xdf\xfd\
\x9a\xd0\x56\xde\x25\xb0\x99\xea\x29\xca\xcb\xb5\x5d\x22\x48\x54\
\x14\xeb\xf4\x3a\xbb\x04\x22\x23\xab\x7f\x4a\x22\xb1\x04\xc9\x45\
\x05\x26\x89\xc3\x5d\x84\xa6\x3a\xbd\xc2\xb5\x5d\xc2\xf5\xd5\x10\
\xd8\x69\xdc\xbb\x04\x22\xb0\x11\x64\x95\x24\x4b\x97\xaa\x7b\xbf\
\x39\x9c\xa4\x6f\x69\x0b\xc1\x99\x79\x63\x68\x97\x94\x3c\x2e\xf3\
\xa7\x54\xac\x6d\xb6\x8a\x9a\x40\xb8\x6d\xbc\x2b\x1d\x1b\x25\x08\
\x02\xa5\x31\xac\x92\x5d\x06\x37\x58\xe6\x5b\x1c\x56\x82\xd0\x81\
\x40\xaa\xd9\xee\x9a\x40\x74\x9f\x4b\x24\xfa\x5a\x82\xe0\x48\xf0\
\x33\x4a\x4b\xcc\x01\x82\xa8\x5c\x76\xa2\xd6\x48\xa7\x86\xdf\x35\
\x9f\x55\x81\xf0\x0a\xd8\x8e\xd2\xef\x34\xea\x8a\x77\x35\x63\xaf\
\x1c\xa1\x7d\xa9\xa4\xb6\xcc\xa3\xbe\x30\x35\xa1\x22\xba\x04\x52\
\xab\x7e\xf9\x60\x31\x07\x83\x3e\x63\x6f\x87\xd4\x04\x02\x16\x38\
\xe3\x5e\x44\x4d\x20\x7c\xe7\x9a\x40\x6c\x4f\xa9\xee\x9a\x77\xb1\
\x4b\xe0\x6d\x9a\x8f\x9a\xfa\xa6\xb6\xc4\x74\x45\xd4\x04\xc2\x2b\
\xa8\x75\xa8\x5b\x0d\x5f\xdd\xfb\xcf\x19\xfb\x70\x2a\x4b\xeb\x6b\
\x09\x52\x29\xe6\xb5\x88\x92\x40\xf8\xcd\xfa\x62\x6b\x81\x8c\x96\
\xce\xb1\x8a\x41\x07\x15\x5f\x0b\x6b\x86\x5d\xa0\x6d\x5e\x8b\x69\
\x94\x92\x40\x44\xe6\xaa\x5d\x35\x17\x4d\x3b\xa5\x26\xe8\x19\x47\
\x21\x63\x21\x7a\x2f\xc1\x7c\xd2\x3a\xc5\x02\x5a\x4d\x20\xf2\xfe\
\x25\x48\x13\x10\xc8\x81\x39\x6e\x3c\x11\x24\x58\x09\xa4\x96\x46\
\x21\x10\x55\xcf\x56\x94\x04\xc2\x3d\xab\x1d\xaa\x91\xb3\xa2\x2b\
\x45\xa9\x33\x8e\xc2\x7c\x98\x97\x5a\xd6\xc2\xbc\x16\x53\x51\x25\
\x81\x74\x75\x83\xfb\xc0\xda\xd6\xdc\x55\x70\x79\xcd\x4b\xad\x1e\
\xc4\x8e\x98\xdf\x56\x94\x26\x5d\xbf\x6d\xcd\xa0\x2b\xca\x6c\xf3\
\xee\x10\x7c\x29\xa8\xad\x4b\xb1\x42\x2d\x65\x54\x83\xc5\x2a\xa5\
\x54\x82\x79\xad\x15\xfa\x5a\xf1\xf4\x90\xb7\x40\xe2\x6d\xd4\xa1\
\xa7\x1d\x68\x13\xe8\x53\x53\x1f\x8a\xd2\x42\x9a\x1a\x56\xc1\x63\
\x42\x19\x8c\xb6\xbf\x87\xec\xcc\x13\xc2\x56\x94\x76\x08\x3d\x57\
\xf3\xb0\x18\x2d\x05\xfe\xc3\x0e\xc2\x70\xd3\xc3\xe5\x8e\x7c\xd7\
\x0f\x12\x8c\xb5\xb9\x31\xe7\x45\xfb\x5c\x12\x48\xd3\xf5\x5d\x82\
\x7f\x57\x53\x69\x87\x09\xd4\xb7\xee\xcb\xbe\x60\x23\x6a\x73\x63\
\x31\x17\x55\x5a\x49\x20\xd2\x21\x35\xd7\x8d\x84\xb7\xbd\x83\x7d\
\x48\xe8\xb8\xe9\x0b\x6e\x6d\xcd\x43\x35\xaf\xc5\x74\x53\x49\x20\
\xdc\xda\xda\xb6\x13\xa3\xd4\xd2\x2a\x63\x62\xdb\xbd\xbb\x2e\x81\
\x98\xd7\x95\x05\x22\x51\xd6\x15\xdc\x6c\xea\x4a\x0c\xdd\x1e\x8a\
\x62\x53\xe2\x7d\xfb\x5f\xbb\xc0\xee\xaa\x77\xd4\xb4\x07\x1b\x53\
\xec\x3d\x28\x09\x44\x70\x53\x73\xdd\xe8\x55\xf9\x98\x4d\x9d\x0b\
\x7c\x44\x58\x5b\x30\x43\xc2\xe4\x3d\x76\xef\x3f\x3b\x61\x3e\xcc\
\x4b\x4d\x7b\x98\xd7\x62\xbe\xab\x24\x10\xc7\x93\x6b\xc1\x8d\x7f\
\x27\x35\x3f\x5a\xdf\x6a\x07\xde\x12\xde\x29\x74\x26\x64\x4c\xa8\
\x71\xdc\x20\xfc\xf2\x91\xef\xba\xa1\xff\x99\xe6\x28\xcd\x2b\x88\
\x53\x94\x7b\x5b\x51\x72\x6d\x35\xc7\xd9\xa6\x7c\xfe\xd2\xef\xf8\
\xff\x56\xce\xc7\x8e\x7c\xb7\x39\xa8\x55\xaf\x1b\xc4\x95\x40\xcf\
\x4b\x9c\xae\x9a\xab\xd3\x83\xf0\xb4\xb0\xd4\xa9\xc8\x73\x25\x64\
\xa7\xac\x6a\x59\xe1\x56\x38\xb8\xdf\xb8\xbf\x6d\xfc\x62\xe8\x52\
\x99\x19\x47\xf1\xa0\xd0\x51\xef\xb6\xf9\x42\x19\x8e\x77\x84\x45\
\xd4\xb6\x96\x68\xbc\x56\x0d\xd4\x63\x54\xad\x0f\xef\x20\x1c\xc1\
\xa0\x5d\x4a\xe0\x2c\x31\x07\x45\xd4\x04\xd2\x5c\x14\x59\x82\x8c\
\xa5\x73\x83\x2b\xe7\x65\x0e\x29\xd8\x0e\x07\x94\x6a\x65\x6f\xdd\
\x29\x8e\x74\x14\x51\x13\x88\xe6\x05\x35\x8f\x12\xfc\x5b\x17\xbb\
\x48\xc6\xcd\xd8\xeb\x81\x66\xcb\x6a\x29\x27\xd7\x77\xac\x2d\x10\
\xff\x90\xe1\x29\xb9\x97\x3e\x58\xe5\x8b\x21\x9b\xb1\x77\x42\x80\
\x97\x55\x12\x08\x47\x41\xd9\xbb\xea\xb1\xd5\x04\x62\x77\xa8\x11\
\xd7\xd4\x16\xb7\xd7\xca\xd0\x4d\xb1\xcb\xa0\xbe\xcd\x43\xb1\xf0\
\x14\xd8\x1d\xe6\xb3\x9a\x69\xa8\x09\x84\x57\x70\x6c\xa8\x67\xb5\
\x04\x29\x02\xe7\x46\x74\xc8\xef\x32\x5c\x5e\xa3\x2c\x2b\xb1\x58\
\x82\x1e\x36\x0d\xe9\xe6\xb5\x88\x9a\x40\x40\x57\xa2\x54\x45\x29\
\xaf\xd5\xa8\x2d\x41\xda\xa6\x72\x5b\x9b\x86\xe8\xfc\x2e\x61\xcd\
\x7e\x98\x3f\x77\xbc\x74\xc6\x6c\x5d\x02\x11\x1c\xb1\x25\xbc\x83\
\x12\x94\x23\x75\x39\x5e\xe7\xc8\x77\xbb\x07\x99\x60\xcf\x5f\xf3\
\x36\x05\x98\xe6\xb1\xf3\xca\xd9\x2e\x81\x90\xac\xce\xf6\x62\xa8\
\x1f\xf8\x1b\x76\xc9\xbd\xc2\x62\xad\xf8\x90\x82\xab\x7b\xbf\x50\
\x4c\x56\x9b\x4b\x29\x1e\x81\x76\x49\xd3\x1c\x8f\x2e\x81\x80\x32\
\x26\xe9\xd6\x8c\x91\x81\xf1\xb6\x5c\x03\xbb\x4b\x70\x03\x9e\x33\
\x34\x35\x75\xcd\x39\x12\xd3\xe1\x60\xb8\x67\xe8\x1a\xbc\xc5\x34\
\xc0\x32\x45\xf5\xce\x18\xca\x2d\x1d\x76\xb0\x15\x8c\x38\xa7\xa7\
\xeb\xae\x30\x27\x93\xd9\xd8\x5e\xe8\xb3\x43\x80\x71\x77\x61\x7d\
\x2d\x95\xc2\xb8\x71\xfd\x5c\x98\xbc\xa9\xb4\xfc\x54\x50\x7e\x78\
\x40\x28\x28\xae\x35\x14\x4a\x95\xd0\x30\xa3\x24\x60\xd9\x08\xbb\
\x44\xa0\xd8\xb6\x12\x70\xf1\x26\x87\xc3\x5a\x73\x57\x7c\x72\x3b\
\x83\x20\x8f\x4d\x68\x9b\x07\x34\x4f\x32\xbb\x2b\xdd\xe4\xb0\x0a\
\x44\xa1\x2e\x7c\xec\x7b\xd7\x89\x4e\x8d\xc3\x24\x14\x69\x22\x71\
\xd7\xd5\x43\x69\xa5\xda\xc2\x44\x59\x0e\xcd\x11\xa3\xd6\x8c\x6e\
\x1a\xf6\xbd\x0d\xe8\xd5\xe1\x18\xb7\x01\x6d\x0a\x82\x3e\xf5\xa1\
\x3e\x37\xcc\x99\x1f\x67\xd8\x47\xbd\x0d\x08\xd8\x86\x4d\xdf\x97\
\xb5\x09\x18\xbf\xc5\xe5\x66\xbc\xb6\xe7\x5c\xa6\x46\x39\xb5\x91\
\x49\x6c\xa9\x83\x8b\x2e\x98\x51\x8a\x6c\x1b\xcc\x22\xed\x94\x31\
\x6e\x94\x9b\x12\xc6\xad\xcc\xb0\xca\x8d\x72\xcd\x5d\xbe\x93\xc1\
\xbb\xa2\x1c\x05\xee\x52\x5d\x48\xd7\xba\xb3\x70\xe8\x3b\x17\xa7\
\x00\x61\xac\x73\xe7\xa2\x17\x10\x4c\x0a\xfa\xd4\xa5\xc3\xaa\x5f\
\x5d\xc6\xad\xe1\xab\xc2\x31\x6e\x25\x1d\x0b\xc6\xc9\xad\x75\x29\
\x40\xdb\xf3\x2c\xd3\x3c\x68\x4f\xda\x98\x87\x29\xd5\xfc\xd0\x50\
\x04\xdf\x36\xc0\x65\xf2\xbe\xf8\xe3\x0a\xfc\xdb\x1e\xa7\x88\xbc\
\xdd\xdb\xeb\x35\x7b\x7d\xb4\x00\x2a\x53\x88\x4d\x6a\x15\xc3\x51\
\x61\x05\xb9\x0b\xe5\x71\x61\x57\xb4\xda\xb0\xb9\xd9\x5a\x87\xf8\
\xb6\x46\xf4\x0e\x65\x3e\x29\x94\xbf\x33\xde\xb6\xe7\x58\xa6\xa3\
\x19\x8f\x0c\xbb\x2a\x86\xa3\x83\x4d\x50\x0f\x59\xe7\xee\x77\xee\
\xb3\x60\xb3\x7a\xb3\xc1\x84\x90\x8f\x3b\xd0\x77\xbf\x37\x60\x4f\
\x78\x5e\xae\x50\xed\xfb\x10\xc8\x1b\xf9\x46\xe8\x35\x15\x9c\x84\
\x4d\xa9\x31\xea\xc9\x9b\xe3\x5c\xb3\x74\xe0\xdf\x8e\xd0\x40\x04\
\x3b\xd4\xfb\x43\x1c\x1b\x9e\x02\x8b\xef\x0f\x91\xcd\x96\x81\xe8\
\xe3\x49\x21\x81\x51\x53\x83\xbf\x3f\x64\x48\x7d\x67\x50\xf4\xef\
\x10\x6f\xd8\x61\x4c\xbd\xef\x49\xee\xac\xd8\x98\xbc\x06\x24\x05\
\x79\x4e\x2e\x13\xf3\xd5\x64\x1a\x73\xd7\x99\xca\x45\x34\x63\x75\
\xca\xec\x75\xe1\xa0\x6f\xd8\x19\xda\x00\x79\x28\x39\x9f\xe6\x1d\
\x54\xb5\xbb\xb6\xda\x60\xf5\xf1\xc6\x1c\xfb\x22\x1c\x11\x2f\x57\
\x72\xf9\x1d\x54\x5d\xe7\x1b\x3d\x17\x15\x28\x8f\x24\x07\x47\xa5\
\xb8\xfb\xd0\x57\x63\x22\x04\x45\x25\x8b\x68\x95\x39\xa0\xa2\x8c\
\x43\x5c\xb2\xf5\xef\xa0\x6a\xe0\x6f\x52\x07\xfc\x71\xd5\x34\x7d\
\xae\xeb\xd4\xdb\x1b\xd5\xc0\x01\x90\xaa\x59\x7c\x4b\x1b\x35\x27\
\xb5\x2d\x5b\x40\x45\x5a\xa1\x04\x2f\x13\xeb\xb3\x18\x68\x6e\x79\
\xf3\x96\x36\x93\x6f\xa1\x38\xee\x0d\xeb\x3c\xb7\x9d\xaa\xfe\x41\
\xc5\x79\x0b\xe8\x28\x57\x52\x8d\x21\x90\x06\x56\x9f\x7a\xb3\xdd\
\xe2\x3d\x86\x56\xeb\x10\x86\x8f\x90\x4c\x0e\x61\xd8\x29\x5c\x53\
\x3f\xb3\x3b\x09\x04\xa9\x4b\x1c\xc2\xeb\x21\x6c\xbd\x05\x22\x70\
\x89\xc5\x0f\xed\xff\x6c\x14\x8c\x29\x90\x06\xa2\x73\xbb\xc5\xbd\
\xf1\xde\x8d\x6e\xd5\x4e\xf1\xb9\x27\x14\x76\xa8\xf2\x2b\x87\x83\
\x30\xdc\xe5\xce\x2b\x1c\x15\x53\xb8\x6a\x74\xbe\x87\x6a\x02\x2d\
\x86\x95\x11\xad\x1d\xfb\xda\x34\xec\xc0\xaf\x84\xce\xa1\x78\x59\
\xd8\x9b\xc2\x5a\x7f\xda\x60\x98\xca\x77\x66\x0c\x45\xe8\xdc\x4b\
\x86\xb0\x31\xca\xf4\xfd\x36\xa5\x51\x9a\x3b\xaf\x9c\x7d\xf1\x76\
\x07\x74\xec\xc2\xf8\x27\xc1\xa6\x54\x07\x23\xab\x4b\xc5\xfb\xd4\
\xb9\x9f\x0c\x6e\xd7\x75\x50\x63\x81\x3d\xe0\x2c\x70\x1c\x4c\xbe\
\x2c\xb6\xb3\xe9\x3c\xbc\xc9\xb1\x69\x5d\xee\x2c\x05\x2f\x8c\x7d\
\xd1\x6c\xc6\x45\xe5\x09\xad\x12\x17\xac\x03\x4e\x80\xa4\xa8\xb3\
\x94\x5c\x69\x71\x8f\x54\x8e\xd2\xf3\xca\x27\x9b\x86\xc4\xb6\x18\
\x57\x3b\x43\x7c\xa0\x47\x58\x1a\x45\xa9\xd4\x8e\x69\xec\x0d\xb5\
\x46\x40\xeb\x8c\x97\x71\xb6\x0b\xa8\x49\xb6\x81\x5a\xe2\xb2\x1e\
\x17\xba\xb8\xd2\x6e\xd0\x51\x38\x9a\xe7\xb4\x0a\xb6\xd1\xdb\x31\
\x26\xc2\xb0\x63\x5c\x6d\xd1\xbc\xb3\xd6\xcf\x38\x02\x48\x80\x04\
\xd4\xb0\x81\x95\xdf\xd0\x04\x0b\x32\x39\x12\x54\x52\x93\x01\xd0\
\x96\xa3\x69\x8d\x60\x06\x0d\xea\x86\xc0\x36\x0a\xa4\x04\x71\x8c\
\x52\xb0\xec\x72\xa3\xd6\x04\x80\x8d\xc7\x66\xe2\x4d\x32\x55\x84\
\xbc\x3b\x8e\x84\x88\xdf\x7f\xcf\x98\x31\x63\xc6\x8c\x19\x33\x66\
\x4c\x85\x63\x8e\xf9\x1f\x14\xbe\xad\xda\x96\xb0\xa6\xcd\x00\x00\
\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
\x00\x00\x00\x84\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x20\x00\x00\x00\x20\x08\x06\x00\x00\x00\x73\x7a\x7a\xf4\
\x00\x00\x00\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\
\xa7\x93\x00\x00\x00\x39\x49\x44\x41\x54\x58\x85\xed\xd4\x31\x0a\
\x00\x20\x0c\x03\xc0\xea\xff\xff\xac\x1f\x28\x74\x28\x8a\xe0\xdd\
\x98\x25\x4b\x48\x04\xfc\x6e\x24\xd9\xba\xd9\x39\x0f\x97\x51\xca\
\x36\x50\xe9\x6e\xc4\x06\xde\xe2\x07\xf0\x03\xf8\x01\x80\x0d\x4a\
\x27\x05\x10\x7b\xf4\xd9\x97\x00\x00\x00\x00\x49\x45\x4e\x44\xae\
\x42\x60\x82\
\x00\x00\x0e\xae\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\xfa\x00\x00\x00\xfa\x08\x06\x00\x00\x00\x88\xec\x5a\x3d\
\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\x00\x00\x00\
\x09\x70\x48\x59\x73\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7\x6f\
\xa8\x64\x00\x00\x0e\x43\x49\x44\x41\x54\x78\x5e\xed\xdd\x05\x90\
\x23\x69\x19\x87\xf1\xc3\xdd\xdd\xdd\x39\xdc\xdd\x5d\x0e\x77\x77\
\x28\x5c\x0e\x87\x82\xc3\xe5\x28\xdc\xdd\x0b\x28\xdc\xfd\x70\x77\
\x2d\xec\x90\xc2\xdd\xfd\x7d\x36\xe9\xb9\x9e\xec\xdb\x92\xb4\xce\
\xec\xf3\xab\xfa\xd7\x64\x67\x93\x74\xa6\xd3\x5f\xcb\x67\xbd\x9f\
\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\
\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\
\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\
\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\
\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\
\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\
\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\
\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\
\x92\x24\x49\x92\x24\x0d\xe3\x28\xcb\x9f\x43\x39\xfe\xf2\xe7\x46\
\x0e\xb7\xfc\xa9\xf9\x3b\x68\xf9\xb3\xca\xdf\x22\x8f\x59\x3c\xd4\
\x48\x4e\x18\x61\x9d\xdf\x3c\x72\xf4\xc8\x37\x22\x77\x8b\x7c\x38\
\xd2\x97\x87\x46\xee\x1d\xa1\xa0\xff\x28\xf2\xa4\xc8\xb3\x22\xda\
\x85\x8e\x11\xf9\x5f\x43\xfa\xdc\xb8\xd4\x8c\x82\xfd\xa5\x48\xf6\
\x5d\x5c\x3a\xd2\x87\xa7\x45\xb2\xf7\xbf\x6f\x44\xbb\x90\x05\x7d\
\x7e\x9e\x13\xc9\xbe\x07\xf2\x9e\x48\x57\xa7\x8b\x64\xef\x5d\xe4\
\x22\x11\xed\x32\x16\xf4\x79\x39\x20\x92\x7d\x07\x45\x0e\x8d\x74\
\x75\xb5\x48\xf6\xde\x45\x3e\x12\xd1\x2e\x63\x41\x9f\x97\x6f\x45\
\xb2\xef\xa0\xc8\x9b\x23\x5d\x9d\x22\x92\xbd\x77\x39\xf7\x88\x68\
\x17\xb1\xa0\xcf\xc7\x81\x91\x6c\xfd\x97\x73\xcd\x48\x1f\x5e\x1f\
\xc9\xde\xbf\xc8\x5f\x22\xa7\x8a\x68\x97\xb0\xa0\xcf\xc3\xb1\x23\
\x7f\x88\x64\xeb\xbf\xc8\x07\x23\x7d\xb9\x58\x24\x5b\x46\x39\xaf\
\x88\x68\x97\xb0\xa0\xcf\xc3\xa3\x22\xd9\xba\x2f\xe7\xb2\x91\x3e\
\xbd\x2c\x92\x2d\xa7\x9c\xfd\x23\xb5\x6c\x47\xdf\x39\x68\x4b\xad\
\xf3\x9f\xc8\xd3\x17\x0f\x35\x80\x13\x44\x7e\x1c\x39\xda\x9e\x7f\
\xe5\x5e\x19\xb9\xc5\xe2\x61\x6f\xce\x1a\xf9\xe6\xe2\x61\xa5\x97\
\x44\x6e\xbb\x78\x28\xa9\x8b\xc7\x45\xb2\xa3\x69\x39\x67\x8e\x0c\
\xe1\xe0\x48\xb6\xbc\x72\xd8\x21\x48\xea\xe0\xa4\x91\x7f\x45\xb2\
\x02\x56\xe4\xf1\x91\xa1\x9c\x38\xf2\xd7\x48\xb6\xdc\x22\xcf\x8b\
\x48\xea\xe0\xc9\x91\xac\x70\x15\xf9\x65\x84\x7a\x94\x21\x3d\x2c\
\x92\x2d\xbb\x9c\x33\x46\x24\x6d\x88\x82\x9c\x15\xac\x22\x0f\x89\
\x0c\x8d\xba\x01\x9a\xd3\xb2\xe5\x17\x61\x87\x94\xea\xa3\x32\xee\
\x88\x91\x73\x2f\xc3\x29\xce\xb7\x23\x87\x44\x58\x39\x75\x8e\x1a\
\xb9\x5c\xe4\xd4\x11\x5e\xc7\x80\x80\x22\xff\x8d\x0c\x8d\xbf\x9d\
\xe5\x16\x39\xd9\xf2\xe7\x6f\x23\xbf\x59\xe6\x7b\x11\x06\x12\xa8\
\x3b\xd6\xf7\xc5\x23\x27\x59\x86\x23\xe0\xaf\x23\xac\xe7\x5f\x44\
\x3e\x1d\x99\xa3\x9b\x44\x5e\xbd\x78\x58\x89\xee\xaa\x3f\x5c\x3c\
\x1c\x14\x83\x59\xee\xba\x78\x98\xfa\x55\x84\xd3\xfc\xbd\xac\x16\
\xf4\x6b\x44\x4e\xb9\x0c\x9d\xf6\x8f\x1c\x39\xd2\xf2\xe7\xe1\x23\
\xa0\x20\x50\x03\xcc\x97\x45\x05\xc5\x6d\x22\x19\x7a\x07\xd1\x73\
\x87\x9a\xca\x32\x3a\xfc\xdf\x2b\x42\xa7\x82\x23\xf0\x8b\xc4\xeb\
\x22\x8f\x8d\x7c\x65\xcf\xbf\xba\xe3\xf3\x9f\x6f\x25\xe7\x8d\xb4\
\x41\xbb\xe9\xd7\x22\xaf\x8a\xd0\xd4\xc1\xb5\xd2\x50\x58\xd7\x74\
\x7d\x3c\x79\x84\x1d\x0f\xeb\xa7\x08\xeb\x7f\xf5\xdf\xab\x28\x38\
\x8c\x76\x1a\xca\x15\x23\x6c\x1b\x74\xd2\x60\x58\x66\x79\xfb\x28\
\xb0\xc1\x3f\x71\xf1\x70\x8f\x3b\x47\x6e\x18\xb9\x44\x84\xe7\x56\
\xe1\xb3\x7f\x20\xc2\x7a\x7e\x1b\xbf\x98\x89\x77\x46\xae\xba\x78\
\x98\x7a\x7b\xa4\xaf\x0e\x32\x4d\x2e\x14\x69\xda\x21\xde\x2c\x52\
\xb9\x63\x3a\x5b\x84\x86\xfe\xec\x74\x60\x35\x5f\x88\xf0\x85\xf3\
\xc5\x64\xff\x5f\xce\xef\x22\xd7\x8d\xe0\xb4\x11\x0a\x7f\xf6\xbc\
\xaa\x3c\x3b\x52\xb7\x71\x34\xb9\x63\xe4\xfd\x91\xec\xbd\x37\x49\
\x31\x14\x94\x82\xd6\x37\x86\x37\x72\x74\xcb\x96\xdb\x36\x7d\x0c\
\xa6\xc8\xf0\x7d\x7f\x35\x92\x2d\x73\x35\x6f\x89\xe0\xd6\x91\xef\
\x44\xb2\xe7\x34\x85\xf7\x60\xa3\x9e\xda\x99\x22\xd9\xe7\x2b\xe7\
\xc6\x91\x31\x1d\x12\xc9\x3e\x47\x91\x77\x47\x2a\x7d\x2a\x92\xbd\
\x28\xcb\xef\x93\xdf\x35\xe5\x35\xc9\xef\xda\xe6\xad\x91\x75\x5d\
\x30\xf2\xd3\x48\xf6\x7e\x7d\x84\xa3\xd6\xb5\x22\x7d\x39\x7b\x84\
\xcb\x95\x6c\x59\xeb\x64\xa8\x82\xce\xe5\x58\xb6\xbc\x2c\x1f\x8f\
\xbc\x77\xe5\x77\x9b\xe6\x76\x91\x29\x35\x75\x90\xe1\x54\x79\x6c\
\xac\x93\xec\xb3\x94\x93\x36\xb5\x71\x8d\x9c\x3d\x79\x4e\x59\xb7\
\xe9\xa0\x69\xd0\x41\x5f\xe1\x34\xa9\x0f\xb7\x8c\x64\xef\xbf\x6e\
\x86\x28\xe8\x5c\xe2\x64\xcb\x1a\x2b\x5c\xc2\x4d\x85\x11\x62\xd9\
\x67\x2a\xc2\x78\xf1\xb1\x71\x36\xd9\xd4\x0d\x77\xaf\xeb\x78\xae\
\xf3\x86\x6e\x16\xe8\x03\xa7\xe0\x17\x5d\x3c\x6c\x74\xbc\xc8\x59\
\x16\x0f\x07\x47\x4f\xa8\xc6\xee\x87\x2d\x1c\x73\xf9\x73\x8e\xe8\
\xdf\x3d\xa5\x07\x45\xaa\xea\x81\x86\x44\x1d\xc4\xa5\x16\x0f\x2b\
\xbd\x6b\xf9\x73\x4c\xf4\x80\xe4\x8c\xa9\x0e\x7d\xe4\xb7\xa1\xa0\
\xd3\xbd\x8e\x6a\xfb\xb9\xbb\xcb\xf2\x67\x13\x3a\x36\x8c\x89\xf6\
\xcd\xae\x68\x69\x98\xab\x39\x7c\xb6\x17\x47\x98\xb6\x69\x4c\x4d\
\x85\x1c\x5c\xa6\x4c\xa1\x69\xb9\xb4\x6e\xa4\x6e\x15\xc9\x4e\x01\
\xda\x86\x1d\xc5\xcf\x56\x7e\xb7\x4e\xbe\x9e\xfc\x6e\x35\x54\x84\
\x95\x6b\x77\xeb\x7c\x22\x92\xbd\x47\x5d\xfe\x19\xa1\x29\xed\xe7\
\xcb\xc7\xd9\x73\xaa\x72\x8e\x48\x57\x5c\x9e\x64\xef\xbd\x4e\x86\
\xba\x46\xa7\xe6\x3c\x5b\xde\x26\xa1\x2e\xe2\x27\x11\x5a\x6f\xb2\
\xff\xaf\xca\xfd\x23\x63\x7a\x74\x24\xfb\x1c\x45\xa6\x6c\x0e\xbc\
\x40\x24\xfb\x4c\xe5\xd0\xe4\x97\x62\x63\x65\x50\x04\xa7\x05\x6d\
\x6a\xd4\xc9\x47\x23\x57\x8f\x14\x6e\x10\x59\xa7\xc0\x3f\x32\x42\
\xfb\x3b\xd8\x0b\xd1\x6e\x9d\x3d\xaf\xc8\x85\x23\x6d\x30\x82\xe8\
\x4f\x91\xec\x3d\xf8\x3d\x23\xbd\xe8\x5c\x40\x1b\x29\xcb\x3f\x51\
\x64\xd5\xb1\x22\xbc\xcf\x6b\x23\xd9\xfb\x94\xc3\xdf\xd1\x87\x6b\
\x47\x5e\x1a\xe1\x3b\xa0\x69\x91\x50\x11\x56\xec\x80\x68\xc5\xa8\
\xeb\x0a\x39\x54\x41\xc7\x79\x22\x1c\x59\xa9\xb8\x5d\x77\x47\xf8\
\xd9\xc8\x03\x22\xab\x1b\xdf\x71\x22\x5c\xfa\x3c\x21\x92\xbd\xae\
\x1c\x0e\x06\x63\x6a\xba\x3e\x7f\x4a\x64\x4a\x4d\xd7\xe9\xad\xea\
\x8f\xf8\x62\xb2\x17\x97\x43\x13\x48\xd6\xf4\xc5\x75\x6b\xf6\xfc\
\x72\x38\x03\xc8\x6a\xad\xe9\x40\x93\x3d\xbf\xc8\x95\x22\x6d\xd1\
\xde\x4b\x93\xd5\x53\x23\xf7\x8b\x5c\x27\x72\xce\xc8\x26\x18\x91\
\x94\x7d\x9e\x22\x1f\x8a\x8c\xa5\xee\xec\x67\xc8\x82\x5e\x46\xdf\
\x88\x6c\xf9\x59\x38\x32\xb6\x41\xa5\x30\x3b\xb6\xec\x3d\x8a\x9c\
\x21\x32\x06\xae\xcf\xb3\xe5\x97\x53\x34\x1b\x4f\x85\xf6\xfd\xec\
\x73\x15\xa1\x69\xba\x51\x53\x41\xaf\x1b\xfb\x7c\xfd\x48\xf6\x9a\
\x72\xaa\x9a\xa6\x38\x8a\x66\xcf\x2f\x42\x61\x9d\x4a\x5d\x13\x21\
\xb5\xfc\x63\xd9\x29\x05\x9d\x33\x8f\xba\x8e\x26\x99\xa6\x89\x16\
\xee\x14\x19\x03\xfd\x4a\xb2\xe5\x97\x93\xf6\x40\x1b\x51\x53\x13\
\xe6\xb6\x83\x4f\xd6\xbb\xaa\x09\xa7\xd7\xf4\x74\xaa\xf2\xf7\xe5\
\xcf\x2a\x7c\x59\x55\x6d\xe3\x4d\xaf\xdd\xe4\xf3\xf6\xa5\xae\x02\
\x84\x5e\x6c\x3a\xcc\x1f\x23\x57\x89\xac\x5b\x2b\x4d\xdd\x0a\x97\
\x56\x55\x38\xd5\x1f\x43\x53\xc5\x1f\x35\xdf\x4d\x5d\xbc\x87\xc6\
\x34\x53\x75\xb6\xfd\x0d\x9b\x14\x1c\x7a\xc6\x75\xf9\x23\xe9\xe2\
\xb8\xa9\x3e\x0b\x3a\x5d\x7c\xe9\xa8\xc2\x51\x84\x6e\xa7\x37\x8d\
\x30\x11\xff\xf5\x96\xff\xe6\xfa\xfc\xf4\x91\x42\x5d\xd7\xd7\x21\
\x7a\xca\xed\x54\xf4\xee\xbb\x42\x84\xfa\x9b\x4d\xd4\xf5\x19\x1f\
\xab\x19\xb2\xa9\xa0\x4f\x5d\xc8\xd1\xf4\x19\xb6\xd5\x3b\x6d\x52\
\x70\xa6\x9c\x95\xa6\x4b\x41\xa7\x60\xd3\x44\xf7\xa2\xc8\x97\x23\
\xd4\x13\x70\x1a\xcc\x91\xfa\x1d\x11\x76\x40\xcc\xbf\xf5\x86\xe5\
\xbf\xe9\x12\x5c\x54\x0e\x52\x39\x49\x2f\xa9\x2a\x16\xf4\xc3\x30\
\x4e\x81\x4b\xbf\x4d\xfd\x63\xf9\x33\xc3\x40\xa8\x31\xec\x86\x82\
\xde\xf9\x88\xde\xe7\x51\x75\x5d\x9b\x2c\x9b\x9e\x5d\xcf\x8c\x50\
\x58\xa9\xa0\x60\xca\x9d\x73\x45\xd6\xc1\x34\x42\x4c\xbf\x5b\x65\
\xca\x75\x32\x37\x43\xae\x8b\xb1\xd6\xf3\x6e\x28\xe8\x1c\x7c\xb6\
\xee\xd7\xb6\xc9\x8a\xdb\x49\x47\xf4\x47\x44\xb8\xd4\xa0\xf6\xbd\
\x6e\xae\xaf\xae\x2c\xe8\x87\xb1\xa0\x8f\xa3\xcd\x67\xd8\x3a\x7d\
\xdf\x64\xc5\x4d\xb9\x51\xb7\xdd\xc9\xd0\x05\x96\x8a\x9d\xbe\xda\
\xb7\x9b\xec\x6b\xa7\xee\x75\xdf\x43\xd7\xed\xa3\x6e\x5d\x8e\xb5\
\xed\x35\x8d\x98\xa4\x1f\xc1\xd4\xda\x7c\x86\xad\xbf\x63\xa7\x15\
\xf4\x36\x28\xe4\x5c\x63\xb7\xed\x1b\xdf\x87\x29\xcf\x72\xe6\xa6\
\xeb\xf6\x51\xf7\xfa\xb1\x76\xa8\x4d\xa3\xd2\xa6\x6e\x5a\x43\x9b\
\xcf\x40\xc5\xe8\x1e\x9b\x7c\x29\x73\xde\xa8\x19\xf3\x4e\x21\x1f\
\xab\x63\x85\xf6\xd6\x75\xfb\x98\xc3\x11\x9d\xfa\x9c\x3a\x59\x4f\
\xca\xb1\xb5\xf9\x0c\x5b\x7f\xc7\x26\x2b\x6e\xac\x95\xbd\x89\x67\
\x44\x2c\xe4\xd3\xea\xba\x7d\xd4\xbd\x7e\x2e\x05\x7d\x27\x1c\xd1\
\xe9\x22\xbb\x35\xc0\x6b\x93\x15\x37\xd7\x23\x3a\x7d\xa9\x99\x0a\
\xab\x0d\x06\x55\xd0\xbf\xfa\x0e\x11\xda\xcb\x99\x1a\x89\xbf\x8b\
\x6b\x1a\xf6\x94\xcc\xcf\x4d\xfb\x3a\xe3\xc4\xe9\xc2\xc9\xd4\x46\
\xab\x53\x62\x29\xd7\xb5\x30\xd6\x1d\xd1\xe7\x72\xea\xbe\x13\x8e\
\xe8\xdb\x76\x56\x9b\x7c\x29\x63\xed\x55\xd7\x75\x9f\xe5\xcf\x3a\
\x4c\x87\x44\xcf\x3c\x0a\xf6\x03\x23\x2f\x8c\xd0\x9d\x97\x82\x8f\
\x7f\x47\x58\x41\xdf\x8d\x7c\x32\x42\xbb\xfa\xc3\x23\x74\xd9\xa5\
\xcf\xbc\x16\xea\x76\xf6\x5d\xb7\x8f\xba\xd7\x8f\xb5\xed\x35\x1d\
\xd1\x99\xc3\x61\xea\x39\x04\x9a\x8e\xe8\x5b\xd7\xe7\xd8\x2d\x05\
\x9d\x89\x29\x98\xac\xb2\x0e\xe3\xc6\x69\x3f\x7f\xfe\x9e\x7f\xad\
\x8f\x8e\x33\x6a\x36\xe4\x35\xfa\x58\x8a\x1d\x7f\x1d\x46\xf3\x4d\
\xa9\xa9\x2f\xc8\xb6\xe6\xb7\x21\x0a\xed\x14\x05\xa2\x72\xa0\xfd\
\xd2\x3d\x23\x07\x2d\x1e\x6e\x8c\xa3\xbd\x86\x37\x87\x03\x09\xf3\
\x22\x7e\x71\xf1\xb0\x12\xb3\xda\x4e\xa9\x69\x9b\x67\x98\xed\x96\
\x39\x1e\x9d\x37\xc1\xf4\xc8\x55\x18\xc3\xdd\xf5\xe6\x83\x77\x8f\
\x4c\x39\x77\xd9\xbe\x64\x0e\x47\x74\x6c\x3c\x8b\xcb\x08\x18\xd2\
\xdb\x74\x57\x16\x66\x8b\xdd\xb2\x5b\x0a\x7a\x5d\xaf\xb7\x2e\x53\
\x4b\x31\xe6\x98\x99\x44\xd8\x51\x4c\x3d\x77\xda\xbe\x62\x2e\xdb\
\x24\x1d\xae\xea\x4c\x59\xd0\x9b\x96\x4d\x8d\xfb\xb6\x19\x70\x56\
\xf7\x9e\xd4\x36\xd3\xd1\xe4\x32\x91\xaa\xa3\xe4\xf7\x23\xcc\x22\
\xc3\x1d\x5a\x98\x0e\x68\x15\xef\xc1\x48\xb0\x2a\xdc\x0c\x81\xda\
\x6d\x66\x4c\x59\xc5\xe7\xa9\x9b\x83\x8d\x4a\x12\x2a\x19\x28\xbc\
\xe5\x79\xee\xf8\xbc\xc5\x4c\x35\xab\xa8\x38\x61\x78\x23\x5f\x5c\
\x9b\xde\x44\x5c\xfb\x70\x83\x0a\x66\x7a\xb9\x7d\xa4\xae\x8f\x7b\
\x19\x7f\x17\x33\xa8\xb0\x3c\x86\x31\xae\x73\xa3\x07\x26\xc9\x60\
\x86\x1f\xd6\x3d\x7f\x07\xfd\xf3\xcf\xbf\xcc\xea\x8d\x27\x78\x4e\
\x55\x8d\x2b\xc3\x7c\xff\x1c\xe1\xbd\x98\xf2\x97\x9f\xab\x61\xac\
\x35\xeb\x83\x6b\x69\x86\x93\xb6\xc5\x7a\x60\x86\x1f\x3e\x13\x43\
\x50\x99\x3b\x20\xc3\xf7\x42\x0b\x05\x95\x45\x6c\x70\x6d\x7b\x91\
\xb1\xee\x98\xa6\x9b\xd1\x83\x55\x15\x5d\xfc\x6d\xcc\x71\xc8\x74\
\x54\x3c\x1e\x12\xeb\xa6\xee\x56\xd5\x1c\x5c\x18\x6e\x9d\x6d\xc7\
\x43\x63\x70\x16\xeb\xaa\xca\xfb\x22\xcc\x9f\xb0\x17\xbe\xb4\x17\
\x44\x8a\x41\xeb\x6d\x43\xc5\xd6\x6a\xe5\x0b\x4d\x5c\xd9\x73\x57\
\xc3\x6c\x22\x57\x8e\x94\xb1\x03\xc8\x9e\xbb\x1a\x36\x68\xee\x02\
\x53\xe0\x66\x01\xd9\xf3\xca\x61\x83\x7b\x6e\x84\x41\x2d\x34\xa9\
\x9d\x26\x42\xa1\x66\x48\x25\x33\xc8\x50\xb0\x0f\x8d\x64\xaf\xdd\
\x24\xb4\xe9\x37\xe1\xae\x35\x74\xf0\xc9\x5e\x3f\x46\x98\x25\xa8\
\xcd\x00\x1f\x36\xe8\xec\xf5\x6d\xd2\x34\xe5\x12\x3b\x36\x3e\x47\
\xf6\xda\xba\xbc\x3c\x72\xdc\xc8\x90\x9a\xa6\x36\x2b\x6f\x83\x63\
\x62\xf4\x65\xf6\x79\x8a\x54\xce\xaf\xc7\xd0\xcc\xec\x05\x6d\x42\
\x01\x29\xa3\x29\x2a\x7b\x5e\x16\xf6\x9a\xe5\x7b\x4a\xb7\x2d\xe8\
\x45\x98\xd4\xb2\xd0\x65\x72\xca\xa1\x52\x79\xd3\xbb\xc0\x29\x2a\
\x33\xac\x66\xaf\x1b\x33\x4d\xe3\xc6\xb9\xc9\x7e\xf6\xba\x75\x52\
\xb7\x1e\x3e\x16\xc9\x5e\xd3\x26\x8c\x4a\x1c\x12\xdb\x76\xb6\xdc\
\x22\x53\x4c\x10\xc9\xd9\x6b\xf6\x59\xca\x49\xef\x72\x43\xb3\x54\
\xf6\xe4\x75\x52\x1e\x27\x7c\x40\x24\x7b\x4e\x55\xa8\xe8\x2a\xac\
\x5b\xd0\xb9\xef\x55\xa1\xeb\x4c\xb6\x43\xa4\xae\xe3\x05\xb7\x39\
\xca\x5e\x33\x45\xea\xe6\xd2\xe3\x72\x29\x7b\xcd\x3a\xa9\x9a\xd8\
\x91\x26\xaa\xec\xf9\x6d\x33\xe4\x7d\xf0\xc0\xd9\x5e\xb6\xdc\x72\
\xc6\xbe\x75\x54\xd3\xce\x27\x9d\x9e\x9b\xa3\x4a\x5d\x8d\x75\x5b\
\xe5\xf7\x58\xb7\x32\xa5\xed\x35\x70\xa6\xbc\x5c\x6e\x80\xc8\xc4\
\x94\x73\xc2\x70\xc7\xaa\x1b\x64\x70\x5d\x3e\x17\x74\x20\xca\x30\
\xc3\x0e\x63\xf1\xbb\x62\x26\x9f\xac\xc2\xb4\xeb\x3a\xe0\x3d\x87\
\xbc\x59\x07\xf7\xed\xa3\x4e\xa0\x4e\x5f\x77\xeb\x69\x83\xef\xa2\
\x7c\x16\x9b\xa1\x93\x57\x8a\xb9\xd2\xb3\x3d\x43\xdb\x30\xdf\x7a\
\x59\x9b\xc9\x21\xcb\xa1\x9b\x69\x61\xdd\x23\x7a\x56\xb0\xf9\x43\
\xb3\xe7\x4e\x11\x2a\x2e\xab\x50\xb1\x95\xbd\x66\x8a\xd0\x5c\x53\
\xa5\x6e\x7a\xe9\xb6\x39\x24\x92\x61\x47\x92\x3d\xbf\x6d\xa8\x53\
\x19\x1a\xf7\x3e\xcf\x96\x5d\xa4\xa9\x17\x5d\x9f\xe8\xfd\x99\x7d\
\x86\x72\x6a\x77\x9e\x0f\x8e\x64\x2f\x6a\x93\xd5\x0a\x09\x26\x8e\
\xcc\x9e\x97\x65\x75\x03\x58\xa7\xa0\x53\xb3\x4d\x0d\x72\x86\x6e\
\xab\xd9\x6b\x36\x0d\xa7\x43\x4d\xd3\xeb\x66\x29\xef\xc4\x32\x4c\
\x5f\x95\xbd\x6e\xcc\x34\xf5\x31\xa0\xe6\x39\x7b\xdd\x3a\xe1\x14\
\xb8\x0a\xf7\xfc\xce\x5e\xd3\x26\x4d\xeb\xb7\x0f\x54\xda\x66\xcb\
\x2e\x87\xfb\x03\x8c\xa1\x69\x3a\xec\x37\x46\x1a\x51\x89\xc6\x74\
\xc1\x9c\xaa\x30\x13\x27\x35\xdb\x59\x68\x32\x61\x7a\x63\xe6\x54\
\xcb\xee\x0b\xcd\x6d\x64\xb3\x0f\x41\x98\x0f\x8c\xbd\x30\x37\x01\
\x60\x4f\xb9\x3a\x07\x58\x5d\x41\xa7\xd6\x9c\x1b\xe6\xd3\x63\x89\
\x16\x82\xf4\x8e\x91\x25\x97\x8c\x74\xa9\x64\xe4\x68\x4c\x21\xe0\
\xae\x18\x38\x30\x92\x3d\xaf\x1c\xd6\x0f\xaf\xe3\x3e\xdf\x6d\xa7\
\x3a\xa6\xa9\x84\xf5\x41\xb7\xcb\xec\x3d\xfb\x0e\x3b\x48\x9a\xbf\
\xa8\x48\x62\x50\x4f\x1b\xd4\xbb\x30\xbd\xf0\x0f\x22\x34\x6d\x66\
\xef\x5b\x0e\x4d\x6c\x8c\x17\x78\x53\xa4\x4d\x7b\x33\x2d\x21\x8c\
\x2d\x68\x9a\x46\xba\x58\xbf\x9c\x52\xaf\x3b\x95\x74\x17\xcc\xb8\
\x9a\x7d\x9e\x22\x34\x67\x0d\xad\x4d\xdd\x17\xcf\xd9\x67\x31\x6c\
\x95\x42\x4a\x13\x51\x55\xc5\x12\x6d\xb2\x9f\x8f\x70\x03\x79\xa6\
\x9f\xaa\x6a\xa3\xa4\xfe\xa1\x2e\x5d\xd1\x54\x39\x74\xfa\x90\xfd\
\xed\xe5\x74\x91\xbd\x5f\x91\xa9\xd0\x77\x21\xdb\x6e\xca\xa9\xeb\
\x3b\xd2\x07\x76\xcc\xd9\x72\x8b\x74\x99\x90\x73\x57\xa2\xb3\x08\
\x37\xb8\xe7\x48\x43\xd3\xde\x58\x73\x85\x6b\x67\xe3\xec\x24\x2b\
\x60\x45\x86\xbc\x19\x25\x67\x3c\xd9\x32\xcb\xb9\x51\x44\x52\x47\
\xdc\x5d\x35\x2b\x60\xe5\x70\xeb\xaf\x21\x70\x19\x94\x2d\xaf\x48\
\x53\x77\x5d\x49\x6b\x60\x02\x92\xac\xa0\x15\xa1\xfe\xaa\x8f\xe6\
\xc8\x32\x76\x1e\xd9\xb2\xca\x99\xfa\x3e\x70\xd2\xae\x72\xf9\x48\
\x56\xd0\xca\x39\x38\xd2\x17\xba\xa6\x33\xb6\x23\x5b\x4e\x91\x6d\
\xc3\x51\x25\xf5\xa3\xe9\x5a\x9d\x94\xbb\x75\x77\xd1\x74\x8f\x76\
\xd2\x76\xfa\x34\x49\x6b\x60\x64\x61\x56\xe0\xca\xe9\xe3\xa8\xce\
\xe8\xd0\xa6\xa3\x79\xab\x76\x73\x49\x9b\xe1\x3e\x7c\x59\xc1\x2b\
\xc2\x90\xe5\xae\xda\x54\xfe\x55\x0d\xcd\x96\xd4\x13\x46\xfd\x65\
\x85\x8f\xf4\x31\xaa\xad\x69\xc0\x0f\xb3\x1e\x4b\x1a\x58\x5d\x41\
\xa4\x4b\x79\x1f\x3e\x17\xc9\xde\x9f\x9e\x97\x92\x46\x42\x1f\x77\
\x26\x92\x2c\x17\xc2\x3e\xa7\x05\xdf\x3f\xf2\x99\x48\xf9\xfd\x99\
\xa8\x64\xed\x1b\x48\xf4\xd5\x25\x52\xda\x57\x31\xcb\x0d\x33\x25\
\x31\xa7\x20\xbd\xe3\x9a\x26\x95\xdc\x04\xe3\x50\x18\xe9\xc7\xa0\
\x16\xc6\x98\x48\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\
\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\
\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\
\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\
\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\
\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\
\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\
\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\
\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\x49\x92\x24\
\x49\x92\x24\xf5\x67\xbf\xfd\xfe\x0f\x9b\xbc\x15\xda\x67\xbe\x80\
\x39\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
\x00\x00\x00\xe7\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xff\x61\
\x00\x00\x00\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\
\xa7\x93\x00\x00\x00\x9c\x49\x44\x41\x54\x38\x8d\xcd\xd2\x3d\x0a\
\xc2\x40\x10\x86\xe1\x87\xa0\x76\x2a\xa4\xf5\x50\x76\x36\x7a\x1b\
\x83\x07\xf1\x08\x82\xad\x78\x24\x2d\x04\xb7\xf0\xa7\x48\xfc\x4b\
\xd4\x6c\xd4\xc2\x0f\x3e\xd8\x19\x76\x5f\x66\x76\x86\x7f\xd1\x0c\
\x01\x27\x1c\xb1\x46\xb7\x09\x20\x20\x2d\xce\x09\xe6\x05\x34\x5a\
\xa7\x52\x3c\xc0\xae\xc8\x3f\x73\x40\xf6\x0e\x50\xa7\x14\xfb\x6f\
\x00\xd7\x37\x49\x29\xd9\xc1\x12\x07\xaf\xcb\xbf\x18\xb4\x4a\x80\
\x51\x01\x6d\xcb\xa7\x51\x5b\x41\x39\x58\x60\x1c\xd7\x41\x15\xd0\
\xc3\x06\xfd\x26\x80\xfb\x3f\x18\xca\x17\x68\x1b\x09\x78\x50\xc0\
\x0a\x93\xc8\xfb\x95\x31\x66\x6e\xab\x1c\xe3\x80\xe9\x27\x95\xfe\
\x5e\x67\xca\x4f\x38\x40\x1e\xdb\x25\xdb\x00\x00\x00\x00\x49\x45\
\x4e\x44\xae\x42\x60\x82\
\x00\x00\x03\x0e\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x19\x00\x00\x00\x19\x08\x06\x00\x00\x00\xc4\xe9\x85\x63\
\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\x00\x00\x00\
\x09\x70\x48\x59\x73\x00\x00\x0e\xc2\x00\x00\x0e\xc2\x01\x15\x28\
\x4a\x80\x00\x00\x02\xa3\x49\x44\x41\x54\x48\x4b\xad\x96\x4d\x4f\
\x13\x51\x14\x86\xcf\x4c\xb1\x45\x34\x8d\x48\x5b\xc4\x44\xe2\x17\
\xea\xc6\x85\x74\x67\x4c\x8c\x0b\xd1\x0a\x3f\x80\x98\xd4\x85\xd1\
\xea\xca\x98\x74\x83\x0b\x83\x1f\x0b\xdd\x90\xb8\xe9\xa6\x76\x25\
\xd1\xf8\x03\xd4\xfa\xf1\x1b\x8a\x1a\x0d\x12\x15\xdd\x89\xa0\xc4\
\x68\x43\xcc\x14\xe8\xf8\x9e\x7b\xef\x4c\xa7\xcc\x6d\xe9\x50\x1f\
\x52\x72\xce\x99\xce\xbc\x3d\xf7\x9e\x7b\xce\x18\xd4\x84\x4c\xe9\
\x54\x9f\x4d\xe6\x59\x98\x23\xf8\x0c\x12\x19\x51\x71\x41\x60\xff\
\xc1\xbf\x29\x7c\x9e\x18\x54\x7d\x94\x4f\xbe\x98\x13\x61\x0d\x5a\
\x91\x4c\xe9\x74\x8f\x4d\xc6\x4d\x5c\xbe\x00\x37\x22\xa3\x4d\xb1\
\x20\x5a\x30\xc8\x1e\xcf\x27\x9f\x2f\xaa\x98\x8b\x4f\x24\x53\x4a\
\x9d\x84\xc0\x03\x98\x3b\x64\x24\x10\xdf\x21\x74\x2e\x9f\x2c\xbe\
\x52\xbe\xa0\x4e\xe4\x62\x29\x35\x8a\xd0\x24\xcc\x0e\x19\xd9\x10\
\x2b\xc8\x2a\x7d\x3f\x59\x7c\xac\xfc\x9a\x88\xca\xe0\x19\xcc\x76\
\x04\x1c\x56\x90\xd1\x19\x27\x23\x21\x22\xf7\xc0\x7c\x0f\x73\x23\
\x4b\xd4\x88\x79\x83\x56\x0f\xa3\x20\x7e\x98\xec\xc9\x4d\x6e\x4f\
\xe0\x78\x2c\x45\x7b\xb7\x1c\x52\x9e\xa0\x17\x3f\x7c\x9c\x0d\x43\
\x96\x69\xe8\x2b\xec\x56\xaa\x48\xcb\x89\xf8\x08\x8d\xee\xba\x4c\
\xd6\xea\x5f\xba\xf7\xf9\x3a\x7d\x59\x9a\x51\x57\xc8\x42\x36\x7b\
\x4c\x75\x0e\xda\x16\x30\xf0\xd7\x19\xea\xa2\xab\xfb\x6f\x7b\x33\
\xc2\x73\xcd\x34\x2f\x17\x1f\x34\x1f\x5b\x3b\xa2\xe2\xc6\x66\x78\
\x05\x1c\x4c\x23\x44\x11\xb3\x53\x79\xbc\x15\x94\x62\x11\x9c\xe4\
\x7a\xba\x37\xc5\x68\xec\xe0\x04\xa5\xfb\xaf\x34\x14\xd2\x09\x54\
\xaa\x16\xe5\x66\x6f\xd1\x87\xf2\x1b\x15\x11\x0c\x42\xc4\xdb\x2a\
\xa4\x40\xf6\xc0\x1d\x4a\x44\x76\xd2\xb1\xd8\x90\x56\x28\x80\x00\
\x30\xa2\xa2\xba\xbc\x9c\xdf\x9d\x15\x02\x0e\x6b\x85\x82\x09\x48\
\x42\xc9\x4b\x03\x37\x94\x2d\x98\x5d\x9a\xa6\x23\xdb\x8e\xd2\x66\
\x6c\xa2\x43\x7f\xd7\x3e\x91\x61\x4f\x38\x11\x58\x80\x31\xd0\x4a\
\x7e\xaf\x5d\xb2\x44\xa4\x8f\xb2\x03\x77\xa9\x3b\x1c\x53\x11\x3d\
\xad\x08\x70\xb7\xe6\xe5\xe2\x76\x5d\xc7\x82\x35\x47\x13\x9f\xc6\
\xe8\x57\xe5\xa7\x8a\xf8\x69\x4d\x40\x30\xc5\x22\x4f\xa5\x5d\x8f\
\x2b\xb4\xec\x17\x5a\xae\x56\x5a\x15\xe0\x85\x2d\x9a\x18\x38\x0f\
\x61\x63\x1e\xf8\x11\x42\x1f\xaf\x41\xa8\x36\x22\x82\x08\x00\x3c\
\xb7\x3a\x69\xca\x89\x66\x17\x54\xd0\xc7\x82\xf5\x0d\x42\x9c\xd1\
\xa2\x2b\x30\x5d\x7e\xad\xae\xae\x87\x5d\xe0\xe7\x8b\x32\x41\xff\
\x8a\xa3\x7f\xbd\x83\xd9\xcb\xbe\x0e\x2e\xeb\xed\xe1\x38\xcd\x94\
\xdf\xaa\xc8\xba\xb8\x5d\xd8\xad\x45\x54\xd9\x10\x56\x90\xf7\xe7\
\xbf\xcc\x13\x64\x31\x8c\xc1\xf5\x92\x1d\xf7\x30\xca\x80\x9d\x86\
\x89\x2f\xb4\x85\x33\x19\x85\x00\x53\x77\xe2\xe5\xc8\xb4\x87\x61\
\xce\xcb\x48\x60\x70\x9f\xc8\xc0\x1d\xbd\x8c\xaf\xad\xf0\x2f\xe0\
\xb5\xc4\x97\x73\x70\xb5\x55\xa7\x81\xdf\x56\x72\x7c\x9f\x37\x03\
\x87\x5a\x7f\xd0\xc0\x03\x8d\xe7\x01\xb7\x6b\xb8\xda\xf7\x2e\x3e\
\x07\x5c\xa6\x8d\xdf\xbb\x88\xfe\x01\x2d\xca\x14\x85\x20\xa6\xbe\
\xe2\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
\x00\x00\x09\x1b\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x64\x00\x00\x00\x64\x08\x06\x00\x00\x00\x70\xe2\x95\x54\
\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\x00\x00\x00\
\x09\x70\x48\x59\x73\x00\x00\x0e\xc2\x00\x00\x0e\xc2\x01\x15\x28\
\x4a\x80\x00\x00\x08\xb0\x49\x44\x41\x54\x78\x5e\xed\x9c\x57\xc8\
\x24\x45\x14\x85\xd7\x9c\xc5\x9c\xd7\x2c\x98\x33\x6b\x0e\xb8\x66\
\x45\x14\x0c\x0f\x0a\xa2\xbe\x88\x22\x98\x31\xe7\x9c\xb3\x20\x62\
\x06\xc5\x27\x31\xa0\xb8\x2a\x06\x54\x74\x4d\x88\x98\xf3\x9a\xb3\
\xae\x39\x9f\xef\x9f\xe9\xb5\xf6\xda\xdd\xd3\xa9\x7a\x6a\x7a\xeb\
\xc0\xc7\xf4\x1f\xa6\xfa\x76\x9f\xae\x74\xab\x66\xc6\x15\xd0\x3f\
\x23\xc2\x1f\x62\x7f\xd1\x79\xa5\x5d\x7c\xa8\xfc\x2d\x0e\x16\x9d\
\x56\xda\x85\x87\x4c\xe7\x4d\x49\xbb\xe8\xd0\xe9\xb4\x29\xf6\x62\
\x43\x93\x8d\x2f\xa1\xb3\xa6\xd8\x0b\x0d\x4d\x36\x3e\x97\x4e\x9a\
\x62\x2f\x32\x34\xd9\xf8\xfe\x4a\xf9\xf9\x40\xd1\x19\xb9\x17\x07\
\xa1\xc9\xc6\x77\x80\xb0\xa6\x74\xaa\xa6\xb8\x17\x06\xa1\x29\x2d\
\xbe\x4e\x9b\xe2\x5e\x14\x84\xa6\xac\xf8\x3a\x6b\x8a\x7b\x41\x10\
\x9a\xf2\xe2\xeb\xa4\x29\xee\xc5\x40\x68\x1a\x14\x5f\xe7\x4c\x71\
\x2f\x04\x42\x53\x91\xf8\x3a\x65\x8a\x7b\x11\x10\x9a\x8a\xc6\xd7\
\x19\x53\xdc\x0b\x80\xd0\x54\x26\xbe\x4e\x98\xe2\x06\x0f\xa1\xa9\
\x6c\x7c\x23\x6f\x8a\x1b\x38\x84\xa6\x2a\xf1\x8d\xb4\x29\x6e\xd0\
\x10\x9a\xaa\xc6\x37\xb2\xa6\xb8\x01\x43\x68\xaa\x13\xdf\x48\x9a\
\xe2\x06\x0b\xa1\xa9\x6e\x7c\x23\x67\x8a\x1b\x28\x84\xa6\x26\xe2\
\x1b\x29\x53\xdc\x20\x21\x34\x35\x15\xdf\xc8\x98\xe2\x06\x08\xa1\
\xa9\xc9\xf8\x46\xc2\x14\x37\x38\x08\x4d\x4d\xc7\x17\xbc\x29\x6e\
\x60\x10\x9a\x7c\xc4\x17\xb4\x29\x6e\x50\x10\x9a\x7c\xc5\x17\xac\
\x29\x6e\x40\x10\x9a\x7c\xc6\x17\xa4\x29\x6e\x30\x10\x9a\x7c\xc7\
\x17\x9c\x29\x6e\x20\x10\x9a\x6c\x7c\x6d\x81\x49\x8d\xef\x25\x9e\
\xa9\xff\x9a\x27\x4e\xee\xaa\xc8\x7b\xda\x94\x8d\xaf\x4d\xfd\x29\
\x66\xeb\x1d\x36\xa3\x68\x48\x7d\x35\x7a\x3f\x66\xee\xbf\x46\x05\
\xa2\x2e\xd4\x90\xb6\xe5\xf5\x7e\xc4\x1a\x12\x98\xa2\x21\x81\x29\
\xc4\x26\x8b\xf2\xe7\x14\xf3\xf4\x5f\xf3\xc4\xc7\xd8\x7e\x14\xbf\
\x08\xe6\x06\x6d\xc8\xeb\xfd\x08\xd1\x10\x86\x91\x8b\x8b\xe5\xc4\
\x62\xfc\x22\x47\x3f\x88\x77\xc4\xa7\xe2\x77\x61\x63\xf5\xa1\x19\
\xce\x10\x6a\xc6\x5a\x62\xf3\xfe\x6b\x9e\xa6\x88\x87\xc4\x8b\xe2\
\x27\xc1\xbc\xc0\xb7\x66\x38\x43\x16\x10\x5b\x89\xbd\xc4\x96\xfc\
\x22\x47\x6f\x88\x9b\xc4\x83\xe2\x7b\x41\x2d\xf1\x2d\xaf\xf7\x23\
\xc4\x4e\x9d\x98\xe6\x16\x8b\x88\xf1\x03\xa0\x69\xa3\x46\xcd\x22\
\x7c\x3f\x28\xad\x28\x8e\xb2\x02\x53\x34\x24\x30\x45\x43\x02\x53\
\x34\x24\x30\x45\x43\x02\x53\x34\x24\x30\x45\x43\x02\x53\x34\x24\
\x30\x45\x43\x02\x53\x34\xa4\x3d\x2d\x28\x56\x13\x24\x4d\xe7\xe0\
\x17\x69\x8a\x86\xf8\xd5\x7c\xe2\x44\xf1\x8a\xf8\x46\xbc\x2a\xde\
\x17\xdf\x89\xfb\xc5\x2e\x62\x3a\x45\x43\xfc\x89\xc4\xe8\x5b\xe2\
\x2c\xb1\x06\xbf\x70\xc4\x3a\xcf\x8e\xe2\x5e\x71\x9f\x20\xa1\x3a\
\xa6\x68\x88\x1f\xed\x2e\x58\x16\x20\xf9\x39\x48\x3b\x8b\xc7\x05\
\xb5\x29\x1a\xe2\x41\x5b\x88\x3b\x44\x99\xfd\x5a\xac\xfb\x5c\xc7\
\x41\x34\xa4\xbc\xde\xeb\xbf\x22\xf7\x18\xad\x2f\xee\x12\x99\x9d\
\x76\x8e\xf6\x11\x13\xa2\x21\xe5\x75\xa8\xf8\xb8\x0f\xc7\x89\x30\
\x63\x92\x58\x68\xec\xa7\xf2\x62\x3d\xe7\xa0\x68\x48\x79\x31\x3a\
\x5a\xa6\x0f\xc7\x28\xcb\x8c\xc7\xfa\xaf\x45\x35\x31\x1a\x52\x5f\
\x59\x66\x9c\x2e\xb6\xee\xbf\x16\xd5\xf8\x68\x48\x3d\xe5\x99\x71\
\x5a\xef\x70\xec\xb5\xb0\x29\xd1\x90\xea\xca\x32\xe3\x0c\x91\x98\
\x91\xa8\xa8\x29\x53\xa2\x21\xd5\xb4\xae\x60\xa7\x8b\x35\xe3\x7c\
\x71\x6a\xef\xf0\x7f\xc2\x94\xe3\x7a\x87\x99\x9a\x14\x0d\x29\x2f\
\x6a\xc6\xc3\x62\xe1\xb1\x9f\xfe\xd3\x99\x62\xd0\x0d\xc7\xb0\xac\
\x9a\xc2\xf6\xa2\x1b\xa2\x21\xe5\x94\xd5\x4c\x61\xc6\x29\xbd\xc3\
\x81\xa2\xa6\x3c\xda\x3b\x9c\x4e\xb7\x8b\xc9\x3e\x36\xca\xb1\x47\
\x6a\x2e\xb1\xac\x60\x06\xca\x93\x54\xc6\x78\xf6\x59\x91\x15\x9d\
\xd0\x7f\xcd\xd3\x27\x82\xb4\x03\xc9\xbb\x32\x3b\x17\xd9\x07\xcc\
\x47\xd2\xd8\xf1\x48\xb2\xef\x5b\xc1\x3e\xe1\x3c\x65\x99\x41\xae\
\xea\xe4\xde\x61\x21\x51\x43\xac\x79\x2f\x0b\x76\x6a\x4e\xf5\x65\
\x08\x37\x75\x15\x41\x1a\x81\xc4\x1a\x39\x9d\xd9\x45\x11\xf1\x7f\
\x98\xb8\x94\x60\xb3\x5c\x9e\xa6\x0a\xb6\x93\x7e\x29\xb8\xa1\xdc\
\xe4\x41\xe2\xff\xd8\xe5\xf8\x81\x78\x44\xbc\x26\x92\xf7\x67\xa9\
\x29\x33\xa8\x49\x27\xf5\x0e\xa7\xe9\x2b\xb1\x8e\xe0\xe1\x2a\xb4\
\xdb\xaf\xac\x21\xfc\x9d\x9b\xca\xc4\x69\x63\xc1\x58\x7c\x43\xc1\
\xcd\x4d\xf2\x3b\x79\x65\x24\xef\x27\x23\x3a\x28\x05\x41\x8d\x60\
\xe7\xfb\x6f\x22\x6f\xf7\x7b\x72\x0d\xfc\x3f\xa9\x6f\xb2\xb0\x24\
\xff\x9e\x16\xa4\x3f\x30\x28\xeb\xfd\x74\xe0\xfc\xaf\xed\x33\x2e\
\x14\xc7\xf6\x0e\x0b\x89\xd1\x97\x35\x8f\x58\xb6\x17\x93\xc7\x7e\
\x2a\x28\x2e\xc6\xa5\xa8\xc8\x5e\xae\x27\x8e\x10\x0f\x08\x9e\x00\
\xf6\xde\xda\x8f\x18\xfb\x86\x1b\x9d\x34\x51\xd4\x84\xa7\x04\x37\
\x73\x23\xc1\xee\xfa\xbc\x24\x20\x66\xf0\x04\xdb\x32\x2f\x10\x65\
\x44\xcd\xb0\x65\xb0\x3e\xc2\x83\x5a\x5a\xb6\xa0\xa2\xa2\xdf\xc0\
\x94\xb5\xc5\x21\x82\xa7\xec\x6b\x81\x29\xc9\x4d\xb2\x65\x37\x8d\
\x6b\x06\x7d\x0c\x35\x82\x9b\xc3\x5a\x05\xcd\xea\xac\x22\x4b\xbe\
\xcd\xd8\x40\x54\x92\x2d\xac\x8c\xe8\x4f\x58\xba\xe4\x49\x38\x52\
\xdc\x2d\x3e\x14\x34\x1d\x6d\x19\xc2\xb9\x7e\x16\x4f\x08\xda\xfc\
\x1d\xc4\x12\x22\x6f\xa0\x91\x65\x06\x35\xab\x8c\x38\x9f\x2d\xe3\
\x0b\x31\xe8\x63\x16\xb9\xb2\x05\x96\x15\xa6\xd0\x19\x62\xca\xe1\
\x82\x15\x32\x32\xa5\xb4\xfb\x3c\xb9\xbe\x8c\xa1\x5c\xce\xc1\x8d\
\x7d\x49\x9c\x2d\x30\x83\x5d\xf3\x55\x9a\xa9\xb2\x66\x70\x3e\x5b\
\xc6\xe7\xa2\x96\x19\xc8\x16\x5a\x45\x98\x32\xbf\x48\x4c\xb9\x47\
\xd0\x91\xfa\xac\x29\x98\x4d\xa7\xf9\x8c\xa0\xd9\x98\x28\x96\x16\
\x79\x03\x85\xa6\xcc\x38\x47\xd8\x32\x30\x63\x4d\x51\x5b\xb6\xe0\
\x3a\x4a\x4c\x39\x4a\xd0\x84\x7c\x26\x92\x11\x92\x3d\x4f\x15\x28\
\x07\x30\x83\xb9\x05\xa3\x97\x4b\xc5\x66\xa2\x6a\x07\x1e\x94\x19\
\xc8\x16\x5e\x47\x74\xa2\x0c\x7f\x19\xe1\x50\x53\xc8\x07\x31\xfa\
\xfa\x55\x24\x37\xd3\x9e\xaf\x28\xc9\xfb\xa9\x75\xcc\x4f\xa8\x19\
\xe7\x89\x9d\x04\xe7\x64\x28\x9d\x35\xdc\xce\x32\xe3\x22\x51\x46\
\xe7\x0a\x5b\x06\x0f\x9d\xdd\xe4\x50\x4b\xf6\x04\x75\x95\x74\xf4\
\x0c\x89\x8f\x17\x0c\x89\x3f\x12\x75\x9b\xaf\xc4\x0c\x9a\xc2\x67\
\xc5\xc5\x82\x6d\x36\x4b\x8a\x2a\x1d\x78\x19\x33\x30\xfa\x32\x61\
\xcb\xc0\x8c\xd5\x45\xa3\xb2\x27\x69\x42\x98\xc2\x90\x98\xe6\xeb\
\x68\x41\x4d\x61\x48\x9c\x98\x52\xd6\x18\xfe\x9f\x99\x36\x9f\xca\
\x25\x8d\x42\xcd\x60\xc2\xc5\xe4\xb4\xca\xd0\xb6\xac\x19\x97\x0b\
\x5b\x06\x9f\x0c\x6e\xdc\x0c\x64\x4f\xd4\x94\x78\x6a\xa9\x29\x9b\
\x0a\x66\xbc\x2c\x87\x32\xeb\xae\x52\x53\xe8\x33\x30\x83\x3e\x83\
\x36\x9f\xd1\x14\x66\xe4\x7d\xce\xbd\x29\x33\xae\x10\xb6\x0c\xcc\
\x18\x94\x87\xab\x2c\x7b\xb2\x26\x45\x4d\xa1\xb3\x25\xb1\x86\x29\
\x4c\xdc\xb8\x98\xe4\x8b\x00\xec\xb9\x2d\xfc\x8f\xdb\x81\xd3\x6c\
\xb0\x01\x0d\x33\x18\x4d\x95\xed\x33\x68\xe6\x8a\x2a\xcb\x0c\x72\
\x6b\x2b\x0b\x6f\xb2\x27\x6c\x5a\x74\xb6\x4c\xd4\x18\x09\x61\x0a\
\x49\x3c\xfa\x14\xb7\xa3\xb7\xe6\x24\xbf\x4b\x9a\xa9\xe7\x05\x4f\
\xf6\x6e\x82\x79\x06\x35\xc3\xb7\x19\x57\x0a\x5b\x06\x93\x5e\xaf\
\x66\x20\x7b\x52\x1f\xa2\x9d\xa7\xf9\x62\xd2\x44\x6a\x9a\x05\x20\
\x6a\x4a\x56\x9f\xc2\xcf\xc9\x3c\x83\x49\xdf\x35\x62\x57\x41\x86\
\xb8\x4a\x9f\x51\xd6\x8c\xab\x84\x2d\x03\x33\x56\x12\xde\x65\x4f\
\xec\x4b\x5c\x28\x37\x93\x9b\x46\x4d\x61\x9e\x92\xcc\x51\xd2\x0c\
\xa1\x76\xf0\xc5\x01\xe4\x96\xc8\x28\xd3\xf4\x55\x19\x4d\x95\x35\
\xe3\x6a\x61\xcb\x20\x95\xdf\x8a\x19\xc8\x9e\xdc\xb7\x48\xb3\xf0\
\x4d\x0e\xec\x1a\x27\x21\x49\x93\xc4\xcd\x4f\x8c\xa1\x66\x90\x28\
\x7c\x4e\xd0\x67\x30\xb4\xa5\x66\x0c\x4a\xd5\xa7\x99\x71\x89\x28\
\xaa\x3c\x33\x56\x14\xad\xc9\x06\xe0\x5b\xcc\xa6\xb9\xc1\x3c\xf5\
\x27\x88\x27\x05\x93\x47\x3a\x7a\x8c\xa1\x03\x67\xa5\x0f\x33\xd8\
\xd4\xbc\xbc\xc0\x8c\xac\xda\x91\x55\x33\xca\x9a\x41\xb3\x68\xcb\
\x60\xb5\x71\x05\xd1\xaa\x6c\x10\x6d\x88\x8e\x9e\x09\x1d\x69\x72\
\x16\x75\x58\xd9\xa3\xa3\x67\xae\x42\x9f\xc1\xb8\x7f\x0f\xc1\xcd\
\xa8\x32\xb4\x2d\x6b\xc6\xb5\xc2\x96\x31\x14\x33\x90\x0d\xa4\x2d\
\x25\x59\x62\xd6\x0d\xc8\x9c\x32\x4f\x61\xfd\xfc\x7a\x41\x33\xc5\
\xd0\x16\xe3\xb2\xe4\xd3\x0c\x56\x19\xa9\x99\x43\x91\x0d\xa6\x4d\
\xd1\x0c\xb1\x90\xb4\x89\xd8\x5b\xec\x27\xb6\x13\x0c\x93\xf3\x72\
\x53\x4c\xca\xa8\x4d\x36\xf6\x32\x66\x70\x6e\xbe\x69\xc8\x96\xc1\
\xf2\x2f\x0f\xc3\xd0\x64\x03\x6a\x5b\xdc\x18\x36\x49\xb0\x69\x62\
\x55\xc1\x3c\x23\x6f\xd2\x87\x98\xcb\xd8\xb8\xcb\x98\x41\xed\xbc\
\x59\xd8\x32\xde\x14\xa4\xf0\x87\x2a\x1b\xd4\x30\x44\x6d\x60\x6b\
\x11\x5f\xdb\x34\xc8\x0c\x3e\x1e\x46\xe7\xef\xc6\x4c\x0a\xbe\xa8\
\xb2\xcc\x60\x88\x3d\x74\x33\x90\x0d\x2c\x74\xed\x29\xdc\x78\x19\
\x26\x93\xc4\x2c\x22\xcc\xb8\x4d\xb8\xef\x07\xb6\x0a\x31\xc8\x08\
\x42\x36\xb8\xd0\x45\xa7\x6f\x63\x66\x46\x4f\x12\x33\x4f\x98\x71\
\x8b\xb0\xef\x7d\x5d\x30\x0c\x0f\x46\x36\xc0\xd0\x45\x0a\xc3\xc6\
\x0c\x7c\x7b\x29\xcb\xb8\x69\xc2\x8c\x5b\x85\x7d\x4f\x70\x66\x20\
\x1b\x64\xc8\x22\x17\x66\xe3\x75\x61\x86\xcf\x3a\x89\xab\x2c\x33\
\x82\x6a\xa6\x5c\xd9\x40\x43\xd6\x31\xc2\xc6\x6b\x21\x3f\xc6\x0c\
\x1f\x8d\x44\x9f\x61\x65\x83\x1d\x16\xef\x0a\xd6\xc7\xf3\x44\xee\
\x2b\xed\xbd\x16\x4c\x61\x5e\x73\xa7\xf3\xbb\x04\x36\x3e\x2f\x2a\
\x82\x95\x0d\x78\x98\x90\x3e\xc9\x12\x13\x48\xd6\x50\xd2\xde\x57\
\x14\xd2\x32\x83\x36\x78\x7b\x55\x5e\xba\x7a\xd4\xb4\x8d\x18\x94\
\xf1\xcd\x13\x66\x6c\x2b\x48\xb7\x04\xad\xb4\x27\x69\x18\x0c\x6a\
\xb2\xd2\x16\x8d\x8a\xf2\x82\xb0\xbb\xdb\xa3\x6a\xea\x6d\x91\x76\
\xb3\xf3\x60\xad\x85\x79\xcb\xb4\x2f\x7f\x89\x6a\x46\xcc\x15\xd2\
\x6e\xb8\x85\x9d\xf7\xac\x44\xf2\xc1\x4c\xd6\xf0\xf3\x96\x7b\xa3\
\x6a\x88\xe4\xa3\xcd\x5f\x01\x2b\x8c\x8c\x9a\xc8\x65\x91\xb2\x9f\
\x57\x44\xb5\xa4\xc3\x04\x7b\x68\x59\xab\xb8\x51\xec\x2b\x48\xd3\
\x8f\x90\xc6\x8d\xfb\x17\xa6\x87\x61\x1e\x5b\xff\x9d\x6e\x00\x00\
\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
\x00\x00\x00\x83\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x20\x00\x00\x00\x20\x08\x06\x00\x00\x00\x73\x7a\x7a\xf4\
\x00\x00\x00\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\
\xa7\x93\x00\x00\x00\x38\x49\x44\x41\x54\x58\x85\xed\xd4\xb1\x11\
\x00\x20\x08\x03\x40\x74\xff\x9d\x75\x01\x3c\x2a\xb4\xf0\xbf\xa4\
\x20\x4d\x2e\x11\xf0\xbb\x91\xdc\xd6\xcd\xcc\xd9\x1c\x46\xa9\xa3\
\x03\xd9\xcf\x23\x1d\x78\xce\x0e\x60\x07\xb0\x03\x00\x1b\x8a\x27\
\x05\x10\xf6\xe3\x4e\x43\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\
\x60\x82\
\x00\x00\x1a\xb9\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\xb2\x00\x00\x00\xb2\x08\x02\x00\x00\x00\x69\xe8\x02\x3f\
\x00\x00\x01\x35\x69\x43\x43\x50\x49\x43\x43\x20\x50\x72\x6f\x66\
\x69\x6c\x65\x00\x00\x78\x9c\x63\x60\x60\x32\x61\x80\x82\xdc\xbc\
\x92\xa2\x20\x77\x27\x85\x88\xc8\x28\x05\xf6\x7b\x0c\x6c\x0c\x2c\
\x0c\x82\x0c\xda\x0c\x16\x89\xc9\xc5\x05\x0c\x98\x80\x11\xc1\xfc\
\x76\x0d\xc2\xbb\xac\x8b\x45\x1d\x21\xc0\x95\x92\x5a\x9c\x0c\xa4\
\xff\x00\x71\x65\x52\x76\x41\x09\xd0\xe8\x0a\x20\x5b\xa4\xbc\x04\
\xcc\xee\x01\xb1\x93\x0b\x8a\x40\xec\x05\x40\xb6\x68\x11\xd0\x81\
\x40\xf6\x0e\x90\x78\x3a\x84\x7d\x06\xc4\x4e\x82\xb0\x1f\x80\xd8\
\x45\x21\x41\xce\x40\xf6\x17\x20\xdb\x21\x1d\x89\x9d\x84\xc4\x86\
\xda\x0b\x02\xf2\xc5\x20\x8f\x7b\xba\x3a\x9b\x19\x5a\x9a\x99\xe9\
\x1a\xe9\x1a\x2a\x24\xe5\x24\x26\x67\x2b\x14\x27\x27\xe6\xa4\xa6\
\x90\xe1\x2b\x02\x00\x14\xc6\x10\x16\xb3\x18\x10\x1b\x33\x30\x30\
\x2d\x41\x88\x21\xc2\xb3\x24\xb5\xa2\x04\xc4\x72\x29\xca\x2f\x48\
\xca\xaf\xd0\x51\xf0\xcc\x4b\xd6\x43\xd1\x9f\xbf\x88\x81\xc1\xe2\
\x2b\xd0\x8c\x09\x08\xb1\xa4\x99\x0c\x0c\xdb\x5b\x19\x18\x24\x6e\
\x21\xc4\x54\x80\x61\xc7\xdf\xc2\xc0\xb0\xed\x7c\x72\x69\x51\x19\
\xd4\x19\x52\x40\x7c\x94\xf1\x0c\x73\x12\xeb\x64\x8e\x6c\xee\x6f\
\x02\x0e\xa2\x81\xd2\x26\x8a\x1f\x35\x27\x18\x49\x58\x4f\x72\x63\
\x0d\x2c\x8b\x7d\x9b\x5d\x50\xc5\xda\xb9\x69\x56\xcd\x9a\xcc\xfd\
\x75\x97\x0f\xbe\x34\xff\xff\x1f\x00\x81\x49\x5c\xa9\xc6\xc2\x24\
\x8e\x00\x00\x19\x3f\x49\x44\x41\x54\x78\x9c\xed\x9d\x7b\x74\x94\
\xc5\xdd\xc7\x7f\xf3\x3c\xcf\xee\x3e\x7b\xcb\x6d\xb3\xe6\x46\x08\
\x9b\x40\x48\xc8\x05\xc1\x80\x16\x4d\x41\x0e\x58\x24\x3d\xa5\xa0\
\x20\xc7\xa2\xb6\x88\x58\x7b\xb4\xbe\x5a\xad\x9e\xf2\x9e\x1e\xa8\
\x6f\x5b\x34\x54\x4f\x2d\xb6\xc8\x91\x42\x78\x9b\x16\xb1\x05\x4f\
\xad\x1c\x0d\xbc\x90\x22\xe5\x7e\x4f\x20\xb7\x4d\x08\x21\x09\x24\
\x61\x73\x21\xc9\xee\xe6\xb9\xcd\xfb\xc7\x98\x75\x4d\x26\xc9\x86\
\x5c\x71\xe7\x73\xf2\x47\xb2\x99\x9d\x99\xe7\x99\xef\x33\xf3\x9b\
\xdf\xfc\xe6\x19\x84\x31\x06\x06\xe3\xeb\x70\x63\x5d\x01\xc6\x78\
\x84\xc9\x82\x41\x81\xc9\x82\x41\x81\xc9\x82\x41\x81\xc9\x82\x41\
\x81\xc9\x82\x41\x81\xc9\x82\x41\x81\xc9\x82\x41\x81\xc9\x82\x41\
\x81\xc9\x82\x41\x81\xc9\x82\x41\x81\xc9\x82\x41\x81\xc9\x82\x41\
\x81\xc9\x82\x41\x81\xc9\x82\x41\x81\xc9\x82\x41\x81\xc9\x82\x41\
\x81\xc9\x82\x41\x81\xc9\x82\x41\x81\xc9\x82\x41\x81\xc9\x82\x41\
\x81\xc9\x82\x41\x41\x18\x7a\x16\x6c\x4b\xc1\x9d\x02\x42\x28\xd0\
\x94\xac\x51\x19\xbd\x19\x6a\x6f\xa1\x28\xca\x17\x5f\x7c\x21\x49\
\x12\xcf\xf3\x30\x18\x3d\x32\x46\x07\x8c\x31\x42\x48\x96\x65\xa3\
\xd1\x38\x77\xee\x5c\xf2\xe7\x80\xdf\x1a\xaa\x2c\xdc\x6e\xf7\xdb\
\x6f\xbf\xed\x72\xb9\x38\x8e\x63\x1d\xcf\xf8\x04\x21\x84\x31\x8e\
\x89\x89\x19\x3d\x59\x70\x1c\x17\x1a\x1a\x3a\x61\xc2\x84\xc7\x1f\
\x7f\x5c\xd3\x34\xd6\x5b\x8c\x37\x30\xc6\x1c\xc7\xfd\xe9\x4f\x7f\
\x12\x45\x31\xf0\x6f\x0d\x83\xc9\x29\x49\x52\x58\x58\x58\x76\x76\
\xf6\xd0\xb3\x62\x8c\x10\x5b\xb7\x6e\x95\x24\x29\xf0\xf4\xc3\x20\
\x0b\x00\x90\x65\x59\x55\x55\x4d\xd3\x38\x8e\xcd\x78\xc7\x17\xa4\
\x51\x06\x3b\xbe\x0f\x8f\x2c\x10\x42\x3c\xcf\x23\x84\x98\x2c\xc6\
\x1b\xb7\xd7\x28\xac\x15\x19\x14\x98\x2c\x18\x14\x98\x2c\x18\x14\
\x98\x2c\x18\x14\x98\x2c\x18\x14\x98\x2c\x18\x14\x98\x2c\x18\x14\
\x98\x2c\x18\x14\x98\x2c\x18\x14\x98\x2c\x18\x14\x98\x2c\x18\x14\
\x98\x2c\x18\x14\x98\x2c\x18\x14\x98\x2c\x18\x14\x98\x2c\x18\x14\
\x98\x2c\x18\x14\x86\x27\x0c\x67\x40\x34\x4d\xf3\x05\x08\x71\x1c\
\x37\x6a\x21\x9f\xfe\xe5\x92\xd8\xf4\x11\x02\x63\xac\x69\x1a\xdc\
\x6e\xd8\xcb\x78\x63\xc4\x65\x41\x82\xc6\x9c\x4e\xe7\xe1\xc3\x87\
\x31\xc6\x18\xe3\x59\xb3\x66\xcd\x98\x31\x63\xa4\xcb\x25\x21\xce\
\xfb\xf7\xef\x77\x3a\x9d\x7a\xbd\x5e\xa7\xd3\x2d\x5d\xba\x34\x34\
\x34\x74\x84\x8a\x23\xf1\x69\x23\x94\xf9\xe8\x33\xe2\xb2\x20\x0f\
\x6b\x5d\x5d\xdd\x9e\x3d\x7b\x54\x55\x55\x55\xd5\x6c\x36\x8f\xb4\
\x2c\x88\xfe\x10\x42\xc7\x8e\x1d\x2b\x28\x28\xb0\x5a\xad\x06\x83\
\x21\x3b\x3b\x3b\x34\x34\x34\xc0\x88\xf8\xc1\x22\xcb\xf2\xd9\xb3\
\x67\xdd\x6e\x77\x62\x62\x62\x42\x42\xc2\xb0\xe7\x3f\xca\x8c\xd2\
\x20\x22\x08\x82\xc5\x62\x21\x61\xc0\x7a\xbd\x7e\x74\x0a\x05\x00\
\x51\x14\xad\x56\xab\xc5\x62\x31\x18\x0c\x23\xf7\x34\xab\xaa\xba\
\x6b\xd7\xae\x0f\x3f\xfc\x50\x92\xa4\x84\x84\x84\x57\x5e\x79\x65\
\xea\xd4\xa9\x77\x74\xc0\xf3\x28\xd5\x1b\x63\xac\x76\x33\x9a\xbb\
\x8c\x34\x4d\x1b\x85\x72\x65\x59\xfe\xfc\xf3\xcf\x05\x41\x88\x88\
\x88\x28\x2f\x2f\xbf\x70\xe1\x02\xdc\xe1\x1b\xec\xee\x54\x39\x8f\
\x2b\x10\x42\x56\xab\x55\x51\x14\xd2\x1d\x0e\x6a\xa3\xce\xf8\x84\
\xc9\x62\x18\xd0\xeb\xf5\xcf\x3e\xfb\xac\xcd\x66\xf3\x7a\xbd\x0b\
\x16\x2c\xb8\xff\xfe\xfb\xc7\xba\x46\x43\xe5\x4b\xdb\x02\xc3\x97\
\x36\x1a\x82\x3b\xb8\xeb\x1b\x2b\x10\x42\x77\xdf\x7d\xf7\xb6\x6d\
\xdb\x30\xc6\x82\x20\x90\xe1\xe3\x8e\x1e\x44\x04\x15\xab\x3c\xe2\
\x11\x20\x72\x19\x1a\xd6\x38\x34\x4a\x5d\x08\x71\x2a\x20\x84\xc8\
\xde\x59\x32\xf6\x0f\xd6\xab\xe1\x73\x18\x90\xbd\x53\x3e\x03\xe2\
\x36\x5a\xc5\xdf\xf7\xe0\xfb\x04\x02\x73\x45\x68\x9a\x46\x4c\x5a\
\xdf\x57\xfa\xca\x1c\xfc\xae\x91\x5a\x22\xb5\x38\xdf\xbd\xf2\xfd\
\x49\x92\x8d\x90\xf8\x84\x5d\xd5\x5b\xad\xba\xb0\x70\xbd\x2d\xc6\
\x38\xc1\x61\x99\xca\x23\x7e\x14\x94\x41\x6e\x87\xff\xd4\xc0\xff\
\xf2\x02\xb7\xe1\x55\x55\xe5\x79\xde\x97\x8f\x7f\x26\xb2\x2c\x0f\
\xea\x96\xf5\xc8\xaa\xf7\x7f\xfb\x6f\x03\x5f\x85\xfb\x4a\xd3\xdb\
\xb1\x41\x2e\x93\x5a\xa2\x7f\x71\x44\xeb\x3d\x6e\x88\xef\xcf\x11\
\x9a\xef\x08\x9f\xd6\x7e\xa8\x61\x55\x03\x2d\x42\x1f\x79\x8f\xed\
\x81\x05\x31\x4b\x1c\x96\x64\x0c\x78\xe4\x46\x13\xf2\x7c\xf0\x3c\
\x7f\xfd\xfa\xf5\xd2\xd2\xd2\xe6\xe6\x66\x8f\xc7\xc3\x71\x9c\x28\
\x8a\xf1\xf1\xf1\xa9\xa9\xa9\x16\x8b\xa5\xaf\x67\xae\x47\x3e\x3c\
\xcf\xbb\xdd\xee\xa2\xa2\xa2\x9a\x9a\x1a\x49\x92\x10\x42\xa2\x28\
\x46\x47\x47\xc7\xc7\xc7\xc7\xc7\xc7\xfb\x3f\xa0\x03\x56\x89\xe7\
\x79\x49\x92\xca\xca\xca\x1a\x1a\x1a\x9a\x9a\x9a\xc8\xed\x36\x99\
\x4c\x36\x9b\x6d\xe2\xc4\x89\x13\x27\x4e\x84\xbe\xdb\x00\x63\x7c\
\xe5\xca\x15\x97\xcb\x45\xda\x7e\xf2\xe4\xc9\x56\xab\xd5\xf7\x70\
\x93\x5f\x6e\xdd\xba\x75\xe5\xca\x15\x52\xc9\xd8\xd8\xd8\xe8\xe8\
\x68\x8e\xe3\x5a\x5b\x5b\x4b\x4a\x4a\x6e\xdc\xb8\xe1\xf5\x7a\x49\
\x1d\xec\x76\x7b\x46\x46\xc6\x5d\x77\xdd\x05\x7e\x82\x40\x08\x55\
\x56\x56\x5e\xbb\x76\xed\xfa\xf5\xeb\xe4\x43\x8b\xc5\x62\xb7\xdb\
\x33\x33\x33\x2d\x16\x0b\xe9\x39\x86\xb7\xdb\x10\x2c\x82\x15\x00\
\x21\x00\x15\xab\x05\x75\x7b\x4b\xda\xce\xaf\x9e\xfc\x72\x7a\xd8\
\x3d\xc3\x58\x86\x3f\x18\x63\xbd\x5e\x8f\x10\xda\xbd\x7b\xf7\xd1\
\xa3\x47\x2b\x2a\x2a\xbc\x5e\x2f\x74\xcf\x60\xef\xba\xeb\xae\xd4\
\xd4\xd4\x85\x0b\x17\x66\x67\x67\xfb\x5c\x52\xd4\x7c\x48\x0b\x1d\
\x3a\x74\xe8\xe0\xc1\x83\xa5\xa5\xa5\x8d\x8d\x8d\x82\x20\x90\x7c\
\xc2\xc2\xc2\x62\x63\x63\x1f\x7a\xe8\xa1\x9c\x9c\x1c\x83\xc1\xd0\
\xbf\x32\x7c\x23\xd7\xe1\xc3\x87\x0f\x1f\x3e\x5c\x5e\x5e\xde\xd0\
\xd0\xa0\x28\x0a\x74\x77\x69\x21\x21\x21\x13\x27\x4e\xcc\xc8\xc8\
\x78\xe2\x89\x27\x4c\x26\x13\xb5\x4a\x9a\xa6\xed\xd9\xb3\xe7\xe8\
\xd1\xa3\x82\x20\x18\x8d\xc6\xd7\x5f\x7f\x3d\x35\x35\xd5\x97\x92\
\xb4\x77\x65\x65\xe5\x1f\xfe\xf0\x87\xd6\xd6\x56\x9e\xe7\x7f\xf8\
\xc3\x1f\xe6\xe4\xe4\xec\xdb\xb7\xaf\xb0\xb0\xb0\xaa\xaa\xea\xe6\
\xcd\x9b\x3c\xcf\x93\xe2\x44\x51\x9c\x3a\x75\xea\xfc\xf9\xf3\x17\
\x2f\x5e\xcc\xf3\x3c\xc7\x71\x2e\x97\x6b\xf7\xee\xdd\xe7\xcf\x9f\
\xaf\xaf\xaf\x6f\x6f\x6f\x27\x29\x65\x59\x8e\x8c\x8c\x9c\x36\x6d\
\xda\xdc\xb9\x73\x1f\x7a\xe8\xa1\x1e\x23\xd1\x20\x9a\x03\xe8\x93\
\x76\x41\xc5\x2a\xf9\x0d\x01\x8a\x30\xd8\x9b\xbc\x37\x3e\xa8\xd8\
\xf4\xdf\x19\xef\x44\x8a\xd1\x83\x2d\x63\xe0\x4a\x60\xcc\xf3\x7c\
\x4b\x4b\x4b\x6e\x6e\xee\xc1\x83\x07\x01\x40\xaf\xd7\x9b\xcd\x66\
\x62\xa9\xe9\x74\x3a\x49\x92\x4e\x9e\x3c\x59\x54\x54\xd4\xd8\xd8\
\xb8\x74\xe9\x52\x62\x73\x50\xaf\x96\xe3\xb8\x8f\x3f\xfe\x78\xe7\
\xce\x9d\xb7\x6e\xdd\xb2\x5a\xad\x51\x51\x51\xb2\x2c\x2b\x8a\x82\
\x10\x52\x14\xa5\xaa\xaa\x6a\xcb\x96\x2d\x4d\x4d\x4d\x2d\x2d\x2d\
\x82\x20\xf4\xe5\xb1\xf0\x7d\xfe\xd1\x47\x1f\xe5\xe7\xe7\xbb\xdd\
\x6e\xa3\xd1\x68\x32\x99\x14\x45\x21\xb2\x23\xf6\xe3\x95\x2b\x57\
\x4a\x4b\x4b\xcb\xcb\xcb\xd7\xac\x59\x93\x9a\x9a\x4a\xcd\xaa\xab\
\xab\x4b\x92\x24\xd2\xf9\x53\x85\x28\xcb\xb2\xd7\xeb\x95\x24\x49\
\x10\x84\x6b\xd7\xae\x6d\xde\xbc\xf9\xe0\xc1\x83\x1d\x1d\x1d\x06\
\x83\x21\x24\x24\x04\x00\x78\x9e\xd7\xe9\x74\x9a\xa6\x95\x95\x95\
\x95\x96\x96\xba\x5c\xae\xd5\xab\x57\x97\x95\x95\xbd\xff\xfe\xfb\
\x45\x45\x45\x7a\xbd\x9e\xe7\x79\xff\x94\xb2\x2c\x9f\x3a\x75\xea\
\xf2\xe5\xcb\x5e\xaf\xf7\x7b\xdf\xfb\x1e\x74\x77\x4b\x83\x68\x0d\
\x80\xbe\xc6\x84\xaf\xbc\x9c\x18\xb0\x82\x65\x91\x37\xba\xba\x1a\
\xff\xb7\xea\xbd\x97\x52\xdf\x18\xf6\x61\x84\xf4\x75\x07\x0e\x1c\
\xb8\x75\xeb\x16\xcf\xf3\x06\x83\x21\x25\x25\x25\x2a\x2a\x8a\x3c\
\x4c\x25\x25\x25\x3a\x9d\xce\x62\xb1\x48\x92\xb4\x75\xeb\x56\x9b\
\xcd\x36\x6f\xde\x3c\xda\xd5\x60\x84\x50\x61\x61\x61\x5e\x5e\x9e\
\xaa\xaa\x61\x61\x61\x92\x24\x49\x92\x94\x9a\x9a\x3a\x69\xd2\x24\
\x8c\xf1\xd5\xab\x57\x6b\x6b\x6b\xdb\xda\xda\xfe\xf5\xaf\x7f\xf1\
\x3c\x6f\x34\x1a\xfb\xea\x30\xc8\x4d\xfc\xec\xb3\xcf\xf2\xf2\xf2\
\xc8\x4d\xef\xec\xec\x9c\x30\x61\xc2\xec\xd9\xb3\x2d\x16\x4b\x5b\
\x5b\x9b\xd3\xe9\xac\xac\xac\x24\x7d\xc0\x85\x0b\x17\x36\x6f\xde\
\xfc\xc6\x1b\x6f\x44\x44\x44\xf4\xce\x8a\xf3\xa3\xaf\xb2\x7c\x09\
\x0a\x0b\x0b\x3b\x3a\x3a\x64\x59\xb6\xd9\x6c\x29\x29\x29\xe1\xe1\
\xe1\xb2\x2c\xd7\xd4\xd4\x94\x97\x97\x93\x3b\xa0\x28\xca\x47\x1f\
\x7d\xa4\xd3\xe9\xce\x9c\x39\x53\x5c\x5c\x6c\x32\x99\xcc\x66\xb3\
\xc3\xe1\x20\x83\x4b\x7d\x7d\xfd\xe5\xcb\x97\xc9\x0b\x67\xdc\x6e\
\xf7\x5f\xff\xfa\x57\x87\xc3\x91\x91\x91\xd1\xc3\x5c\x1b\xb8\x35\
\x00\xea\xbd\x35\x2d\x72\x13\xf4\x6a\xe9\x9e\xce\x6f\x0d\x6b\x3a\
\xa4\x2f\x69\xbb\x50\xd2\x76\x3e\x35\xec\xee\x9e\x46\x86\xa6\xc1\
\x90\x0d\x9c\x8e\x8e\x0e\x84\x50\x56\x56\xd6\xd3\x4f\x3f\x6d\xb7\
\xdb\xc9\x13\x29\x49\xd2\xd5\xab\x57\xb7\x6f\xdf\x5e\x5c\x5c\x6c\
\x34\x1a\x55\x55\xcd\xcf\xcf\x4f\x4f\x4f\x8f\x8c\x8c\xec\xfd\x10\
\xb4\xb7\xb7\x6f\xdb\xb6\x4d\x92\x24\x51\x14\xdb\xdb\xdb\xa7\x4f\
\x9f\xfe\xdc\x73\xcf\x45\x47\x47\xeb\x74\x3a\x00\x90\x65\xb9\xb9\
\xb9\x79\xcb\x96\x2d\xa7\x4e\x9d\x12\x45\xb1\xaf\xc7\xd7\x57\x99\
\xfc\xfc\x7c\xd2\x31\xa8\xaa\xfa\xe2\x8b\x2f\x66\x67\x67\x8b\xa2\
\xc8\xf3\xbc\xa2\x28\xb2\x2c\x97\x96\x96\x6e\xde\xbc\xb9\xa1\xa1\
\x21\x34\x34\xb4\xba\xba\x3a\x3f\x3f\xff\x85\x17\x5e\xe8\x6d\x64\
\x60\x3f\xfa\x2a\xcb\x97\xa0\xa3\xa3\x43\xa7\xd3\x2d\x59\xb2\x64\
\xf9\xf2\xe5\x46\xa3\x91\xb4\xa5\x24\x49\x4e\xa7\xf3\xf7\xbf\xff\
\x7d\x63\x63\xa3\x4e\xa7\xd3\xe9\x74\xff\xf8\xc7\x3f\x54\x55\x35\
\x99\x4c\x0b\x16\x2c\x78\xea\xa9\xa7\xc8\x82\x1f\x00\x28\x8a\xd2\
\xd0\xd0\xb0\x71\xe3\xc6\x6b\xd7\xae\x99\x4c\xa6\x9b\x37\x6f\x16\
\x16\x16\xa6\xa5\xa5\x91\xf1\x65\xc0\x0e\x83\xa4\xb9\xd8\x76\xf2\
\xe3\xfa\xbc\x9b\x5d\x37\x34\xda\x38\x42\x69\x63\x84\x40\xc1\xd2\
\xb9\xd6\xe3\x00\x80\x71\xf7\x0d\xd5\xb4\xaf\x34\x71\xf6\x2c\x1c\
\x38\x00\x8a\x02\xb7\xe5\x4e\x56\x55\xf5\x81\x07\x1e\x58\xbf\x7e\
\x7d\x7c\x7c\xbc\x28\x8a\x82\x20\x90\x67\x3a\x25\x25\x65\xdd\xba\
\x75\x33\x66\xcc\xe8\xec\xec\x34\x9b\xcd\x57\xae\x5c\x39\x7a\xf4\
\x68\x8f\xeb\x54\x55\x15\x21\xf4\xe7\x3f\xff\xb9\xb9\xb9\x59\x14\
\x45\x8f\xc7\x93\x99\x99\xf9\xf3\x9f\xff\xdc\xe1\x70\x18\x8d\x46\
\x41\x10\xc8\x93\x1d\x17\x17\xf7\xda\x6b\xaf\xcd\x9d\x3b\xb7\xab\
\xab\xab\xff\xdb\x74\xe2\xc4\x89\x9b\x37\x6f\x1a\x0c\x86\x96\x96\
\x96\x15\x2b\x56\x2c\x5a\xb4\xc8\x6c\x36\x93\x76\x22\x59\xcd\x98\
\x31\xe3\xc5\x17\x5f\xb4\xd9\x6c\x5d\x5d\x5d\x00\x70\xe6\xcc\x19\
\xb7\xdb\x3d\x94\x17\x85\x11\xeb\x6a\xe5\xca\x95\xcf\x3c\xf3\x4c\
\x58\x58\x98\xc1\x60\x20\xd5\x36\x99\x4c\x99\x99\x99\xaf\xbd\xf6\
\x1a\xe9\xde\x7c\x63\x5f\x4e\x4e\xce\x4f\x7f\xfa\xd3\xd0\xd0\x50\
\xdf\x05\x8a\xa2\x98\x90\x90\xf0\xf2\xcb\x2f\x73\x1c\xa7\xaa\xaa\
\xc1\x60\x28\x2b\x2b\xab\xaf\xaf\x87\x00\x5e\x86\xa9\x61\x0d\x03\
\x3e\xde\xfc\x7f\x5b\xaf\x6c\xbc\xd2\x59\xe6\x56\x3b\xbd\xaa\xbb\
\xf7\x0f\x47\xcb\x86\x53\x34\xf9\x7a\x7b\x35\xc8\x0a\x56\x14\x50\
\x14\x90\x65\xe0\x38\xe0\x38\xa8\xab\x83\xff\xf9\x1f\xb8\xe7\x1e\
\xf8\xc9\x4f\xa0\xb6\x16\x10\x02\x55\x1d\xd4\x4d\x51\x55\x35\x2e\
\x2e\xee\x67\x3f\xfb\x19\xa5\xc6\x9a\x16\x12\x12\xb2\x62\xc5\x0a\
\xbd\x5e\xaf\x28\x8a\xc5\x62\xd9\xbb\x77\x6f\x67\x67\xa7\xff\x0d\
\x25\xd6\xfb\xc5\x8b\x17\xa1\xfb\xe5\x4c\xab\x56\xad\x8a\x8c\x8c\
\x54\xbf\x5e\x0d\x4d\xd3\x2c\x16\xcb\xea\xd5\xab\x93\x93\x93\xc9\
\x34\xa7\xaf\xfa\x54\x57\x57\xf3\x3c\x2f\xcb\x72\x58\x58\x98\xc3\
\xe1\xd0\x34\x8d\xd8\x9b\xfe\x15\xce\xcc\xcc\x4c\x4a\x4a\xf2\x7a\
\xbd\x3c\xcf\x7b\xbd\xde\xb2\xb2\x32\xb8\xdd\xb7\x91\x22\x84\x34\
\x4d\x4b\x4e\x4e\x5e\xb6\x6c\x59\x8f\x7f\x91\x0c\x1d\x0e\xc7\xdc\
\xb9\x73\xdd\x6e\x37\x51\x73\x74\x74\xf4\xa3\x8f\x3e\x4a\xcd\x2a\
\x31\x31\x31\x23\x23\x43\x96\x65\xbd\x5e\xdf\xd0\xd0\xd0\xd2\xd2\
\x12\x48\x05\x04\x5e\xb8\xea\xae\xf8\x7b\xdd\xf6\x4e\xa5\xdd\xc0\
\x1b\x39\xc4\x53\x7f\x04\x0c\x08\x7d\xbd\x1b\x41\x64\x5e\xa0\xe7\
\x41\x27\x7c\x35\xca\xb8\x5c\xf0\xcf\x7f\xc2\x9b\x6f\x42\x59\x19\
\xcc\x98\x01\x6b\xd7\x82\xcd\x06\x00\xb7\x31\xa6\x64\x67\x67\x93\
\xce\xb0\x07\xe4\x46\x4c\x99\x32\xe5\xbe\xfb\xee\x3b\x74\xe8\x50\
\x68\x68\x68\x7d\x7d\x7d\x43\x43\x83\xc5\x62\x21\x09\xc8\xd8\x79\
\xe4\xc8\x91\xd6\xd6\x56\x41\x10\x24\x49\x9a\x32\x65\xca\xf4\xe9\
\xd3\x7b\x8f\xa9\xe4\xee\x47\x45\x45\xc5\xc4\xc4\x14\x17\x17\x1b\
\x0c\x86\x7e\xea\x43\x46\x7d\x8f\xc7\x23\x49\x12\xc7\x71\xc4\xe1\
\xe1\x73\x1b\x10\xb3\x77\xd1\xa2\x45\x53\xa7\x4e\x25\x63\x8d\xcd\
\x66\x83\xdb\x75\x62\x92\xce\x2f\x22\x22\x42\xa7\xd3\xf5\xe8\x08\
\x49\x41\x3a\x9d\x2e\x29\x29\x89\xbc\xd0\xd2\xe3\xf1\x4c\x9f\x3e\
\x9d\x6a\xca\x00\x00\xc7\x71\xc9\xc9\xc9\x67\xcf\x9e\x35\x18\x0c\
\x6e\xb7\x9b\x74\x66\x81\x88\xb5\xac\xe3\xe2\x0d\x6f\xad\x55\x08\
\x55\xb1\xd2\x57\x1a\xa1\x77\xab\x62\xc0\x48\xd0\x59\x1a\x3a\xe0\
\xf2\x27\x20\xa8\xc0\xe9\xa0\xb1\x11\xfe\xfe\x77\xd8\xb7\x0f\xc2\
\xc3\x61\xfd\x7a\x58\xb3\x06\xe2\xe2\x7c\x57\x33\x60\x3d\x7a\x60\
\x34\x1a\xa9\x9f\x23\x84\x54\x55\x35\x1a\x8d\xc9\xc9\xc9\xfb\xf7\
\xef\x07\x00\x41\x10\x2a\x2b\x2b\x93\x92\x92\xbe\xac\x18\xc6\x00\
\x50\x5f\x5f\xef\xf5\x7a\x49\xaf\x9b\x95\x95\xe5\x1f\x7f\xd5\xf3\
\x42\x30\x26\x83\x4e\x3f\x95\x89\x8d\x8d\xed\xea\xea\x22\xfd\x76\
\x41\x41\x41\x52\x52\x52\x5c\xf7\xa5\x91\x79\x0d\xd1\xc7\xec\xd9\
\xb3\x67\xcf\x9e\xdd\xa3\xb6\x83\xbc\xee\xaf\x50\xfb\xe8\x62\x89\
\xbe\x45\x51\x24\xae\x08\x4d\xd3\x62\x62\x62\xfa\xf1\x8f\x99\xcd\
\x66\xdf\xef\x03\x9b\x14\x80\x01\xa0\x4b\xf5\xd6\xb8\x2b\x07\x1c\
\xfd\x05\xe8\x65\x71\x60\x84\x0c\x2a\x9f\xf8\xce\x87\xf0\xf1\xbb\
\x5f\x13\x4d\x78\x38\x14\x14\x40\x56\x16\x00\x80\x24\xc1\xed\x86\
\x4d\xf4\x63\x00\x12\x8b\xcc\x6e\xb7\x8b\xa2\x48\x5a\xb4\xae\xae\
\xae\x47\x9a\x86\x86\x06\xf2\x30\x19\x8d\xc6\xb4\xb4\xb4\x7e\x86\
\xf9\x40\x6e\xd6\xcc\x99\x33\x13\x13\x13\x6b\x6b\x6b\x43\x42\x42\
\xce\x9c\x39\xf3\xe6\x9b\x6f\x66\x65\x65\xa5\xa4\xa4\x64\x64\x64\
\xf8\xe4\xab\x69\x9a\x7f\x9d\xc9\x5b\xc2\x02\xba\xd4\x3e\xe8\xff\
\xeb\xfe\x5d\x69\x8f\x11\xad\x07\x01\x3a\xeb\xfc\x91\xd4\x2e\x49\
\xf5\x08\x88\xd2\xee\xfe\x50\xc2\x70\x34\x50\x75\x18\x65\x2d\xfa\
\x2f\xc8\x52\x11\xb9\xe3\xb2\x0c\x3b\x77\x42\x75\x35\x6c\xd8\x00\
\x3f\xf8\x01\xac\x5c\x09\x7a\x3d\x60\x7c\x1b\x5d\x05\xf4\x7b\x53\
\x48\x43\x5a\xad\x56\x32\xf5\x42\x08\xb5\xb5\xb5\x91\x7f\x11\x9f\
\x87\xaa\xaa\x9d\x9d\x9d\xa4\xbf\x15\x04\x61\x88\x41\x78\x18\xe3\
\xa8\xa8\xa8\xb5\x6b\xd7\xe6\xe6\xe6\xb6\xb6\xb6\x9a\x4c\xa6\x8a\
\x8a\x8a\xd2\xd2\x52\xbb\xdd\x1e\x15\x15\x65\xb7\xdb\x89\x3e\x26\
\x4f\x9e\x4c\xc4\x37\x3a\xab\x5f\xfe\x2a\xef\xbf\xc4\x41\xd5\x87\
\xcc\x28\x4d\x3a\xcb\x5d\xe2\x04\x8f\xe6\x31\x81\xa5\x9f\xc4\x34\
\x59\xa8\xea\x83\x13\x1e\x8d\xcc\x7e\x16\xfb\xcf\x67\x1f\x7d\x14\
\x7e\xf7\x3b\xc8\xcb\x83\x82\x02\x28\x28\x80\x0d\x1b\x20\x3e\x1e\
\x06\xaf\xd6\x01\xaa\x8e\x10\x00\x18\x8d\x46\xa3\xd1\xd8\xd1\xd1\
\x01\x5f\x7f\x20\x10\x42\x3e\x0b\x80\x98\x9f\x7d\x8d\x47\x81\x17\
\xa7\x69\xda\xcc\x99\x33\x7f\xf3\x9b\xdf\xe4\xe7\xe7\x9f\x38\x71\
\x42\xa7\xd3\xe9\xf5\xfa\xd6\xd6\xd6\xa6\xa6\x26\x8c\xf1\xe9\xd3\
\xa7\x2d\x16\x4b\x78\x78\xf8\x82\x05\x0b\xbe\xfb\xdd\xef\x0e\xf1\
\xea\xc6\x03\x3c\xe2\x93\xad\x99\x61\x7a\x9b\x8c\x65\x1e\x78\x0d\
\xe8\x2d\xc8\x21\x40\xe4\x87\x43\x1c\xc6\x58\xd2\xba\x1c\xd6\xe4\
\x47\x13\x56\x43\x0f\x1f\x47\x46\x06\x6c\xdb\x06\xa7\x4f\xc3\xac\
\x59\xb0\x7d\x3b\x2c\x5e\x0c\xc5\xc5\xc0\x71\x83\x9d\x89\x0c\x91\
\x1e\xe3\xc5\xd0\xe3\xf0\xc8\x24\xc5\xe1\x70\xbc\xfe\xfa\xeb\xb9\
\xb9\xb9\x0f\x3e\xf8\xa0\xc5\x62\x11\x45\xd1\x6c\x36\x1b\x8d\x46\
\xb7\xdb\xdd\xd4\xd4\x54\x5e\x5e\xfe\xc1\x07\x1f\xfc\xf8\xc7\x3f\
\xae\xae\xae\xee\x5d\x87\x3b\x0b\x55\x53\x33\x43\x66\x2d\xb0\x2f\
\x91\x34\x49\xd2\xba\xc8\x7c\xb5\xf7\xcf\x97\xce\x6f\x0d\x54\x45\
\x55\x44\x5e\xcc\x0c\x9b\xbd\x66\xca\xab\x02\xd7\x6b\xa6\x80\x31\
\xf0\x3c\xdc\x73\x0f\x1c\x39\x02\xaf\xbc\x02\x7a\x3d\xa4\xa5\x01\
\xc6\x43\xf7\x6e\x7d\xbd\x10\x0c\x00\x1d\x1d\x1d\x1d\x1d\x1d\x64\
\xc8\xe8\xb1\xb2\x6a\xb5\x5a\x89\x79\x48\xc6\x11\x45\x51\xfa\x9f\
\x65\x04\x5e\xa8\x20\x08\x29\x29\x29\x29\x29\x29\x8a\xa2\x94\x96\
\x96\x5e\xba\x74\xc9\xe9\x74\x3a\x9d\xce\x5b\xb7\x6e\x79\x3c\x1e\
\x8c\xf1\xb5\x6b\xd7\x7e\xf1\x8b\x5f\xfc\xf2\x97\xbf\x4c\x49\x49\
\x19\x62\x89\x63\x08\x79\xfe\x97\x4f\x58\xa3\x81\x76\xcc\x75\x50\
\xd6\xbc\xbe\xd5\x0f\x7f\x04\x91\x37\x02\x80\x89\x37\x87\x1a\xc2\
\x67\xd9\xb2\x1f\x8e\x5b\x01\x64\x32\xd2\xc3\x21\xea\x3f\x8c\x6d\
\xda\x44\xff\x7c\xc8\x10\x93\xd3\xe3\xf1\x74\x76\x76\x1a\x0c\x06\
\x45\x51\xac\x56\x6b\x77\x39\x88\x0c\x28\x7a\xbd\x9e\x0c\xf3\x92\
\x24\xd5\xd5\xd5\x25\x27\x27\x0f\xa5\xc4\x1e\x83\x14\x00\x08\x82\
\x90\x9e\x9e\x9e\x9e\x9e\x0e\x00\x1e\x8f\xa7\xa0\xa0\x60\xff\xfe\
\xfd\xb5\xb5\xb5\x7a\xbd\xbe\xad\xad\xed\xdd\x77\xdf\xcd\xcd\xcd\
\x35\x99\x4c\x77\x74\x94\x0d\x06\xfc\xd8\x84\xb5\x8b\xa2\x97\x17\
\xb5\x9d\x72\x2b\x1d\xbd\x57\x46\x84\xa7\x92\x5e\xc0\x00\x91\x86\
\xa8\x29\x21\x69\xd0\x2d\x88\x01\x56\xd5\xc9\xad\xbc\xdd\x7e\xa2\
\x9f\xa5\x51\x62\x72\x36\x34\x34\xb4\xb7\xb7\x9b\xcd\x66\x49\x92\
\x62\x62\x62\xfc\xbf\x08\x00\x91\x91\x91\xfe\xfe\xf2\xc9\x93\x27\
\x43\x1f\xc6\x57\x20\xbd\x7d\x5f\x0b\xe5\xe4\xbb\x06\x83\x61\xc9\
\x92\x25\x73\xe6\xcc\x59\xbf\x7e\x7d\x55\x55\x95\x5e\xaf\x6f\x6a\
\x6a\x3a\x79\xf2\xe4\x83\x0f\x3e\x48\xe2\x33\x02\xbe\xe8\xf1\x05\
\x02\xa4\x61\x2d\x54\x08\x7f\xc0\xf6\x10\x35\x81\x70\x9f\x7d\x3e\
\xf9\x0d\x83\x86\x31\xe6\x50\x00\x97\x3a\xb4\x81\xa3\xaf\x09\x1e\
\x99\xb5\x77\x74\x74\x94\x94\x94\x98\x4c\x26\x4d\xd3\x24\x49\xf2\
\x39\x2d\xa0\xbb\xed\x27\x4e\x9c\x48\x16\x39\x3b\x3b\x3b\x2f\x5e\
\xbc\xb8\x70\xe1\x42\x45\x51\xa8\xad\x3b\xe0\x03\x5d\x51\x51\x51\
\x58\x58\x88\x10\xf2\x7a\xbd\xdf\xfa\xd6\xb7\x66\xce\x9c\x49\xea\
\xe0\x3f\xb3\xed\xea\xea\xb2\xdb\xed\x73\xe6\xcc\xa9\xa9\xa9\x01\
\x00\x59\x96\x89\x9b\xf9\x4e\x87\x43\x1c\x89\xd4\xa4\xce\x54\x39\
\x15\xab\x2a\x56\x35\xac\x01\xa0\x80\x34\x31\x64\x8e\x1d\x3b\x26\
\xcb\x72\x5f\xab\x4a\x4e\xa7\xf3\xc4\x89\x13\xa4\xe1\x63\x63\x63\
\x7d\xce\x25\xe8\x0e\xcb\xbb\xff\xfe\xfb\xc3\xc3\xc3\x89\xaf\xa9\
\xa2\xa2\xa2\xb6\xb6\x96\x58\x21\xfe\x99\x90\xa5\xac\x1b\x37\x6e\
\xd4\xd7\xd7\x93\x41\xa7\x47\x29\xe4\x13\x97\xcb\xf5\xb7\xbf\xfd\
\x6d\xd7\xae\x5d\x3b\x76\xec\xf8\xf7\xbf\xff\xed\x8b\x9a\xf1\x4f\
\x49\x96\xd0\x22\x22\x22\x0c\x06\x03\x09\x89\x90\x65\x79\xb8\x6e\
\xc5\xd8\x42\xec\x0c\xba\xff\x9b\x47\x3c\x8f\x78\x0e\x71\xa3\x13\
\xdc\xcb\x71\xdc\xe5\xcb\x97\x3f\xf8\xe0\x03\x5f\x08\x27\xf9\x9c\
\x4c\x38\xdd\x6e\x77\x5e\x5e\x9e\xaf\xdb\x58\xb4\x68\x91\xcf\xf3\
\x0d\xdd\xe6\x45\x44\x44\x84\xc3\xe1\xc0\x18\x1b\x0c\x86\x9a\x9a\
\x9a\x1d\x3b\x76\x90\xd5\x0a\x9f\x95\x40\x3c\x1c\x5d\x5d\x5d\xf9\
\xf9\xf9\x55\x55\x55\xc4\x69\xd8\xf3\x8e\x20\x04\x00\x77\xdf\x7d\
\x77\x4c\x4c\x4c\x58\x58\xd8\xc4\x89\x13\xcf\x9d\x3b\x57\x54\x54\
\x44\x16\x21\x7d\xc9\xc8\x60\xc7\xf3\x7c\x49\x49\x89\xdb\xed\x06\
\x00\x51\x14\x1d\x0e\x07\x0c\xcd\xcb\x39\xfe\x19\xed\x0d\x01\x08\
\x21\x9d\x4e\xf7\xd9\x67\x9f\x6d\xda\xb4\xe9\xfa\xf5\xeb\xbe\x9b\
\x4b\xa2\x5d\x36\x6c\xd8\x50\x5e\x5e\x6e\x32\x99\x3c\x1e\xcf\xa4\
\x49\x93\xe6\xcd\x9b\xe7\x2f\x1d\x00\x20\xcd\x46\x56\xe4\x65\x59\
\x36\x18\x0c\xc7\x8e\x1d\x7b\xeb\xad\xb7\xc8\xf1\x47\xbe\xac\x1a\
\x1b\x1b\xdf\x7e\xfb\xed\x83\x07\x0f\x92\xa5\x87\xbe\x2a\x23\x8a\
\x62\x76\x76\x36\xf1\x8f\xb5\xb5\xb5\xbd\xf3\xce\x3b\xe7\xce\x9d\
\xf3\x1f\x8f\x10\x42\xb2\x2c\xe7\xe5\xe5\x1d\x39\x72\x44\xaf\xd7\
\x13\xdf\x7c\x56\x56\x16\x7c\xd3\x65\x31\x4a\x9b\x0d\xa1\xdb\x9c\
\x44\x08\xe9\xf5\x7a\x8f\xc7\x53\x58\x58\x78\xfe\xfc\x79\x87\xc3\
\x61\xb7\xdb\x79\x9e\xbf\x79\xf3\x66\x71\x71\xb1\xd7\xeb\x25\x13\
\x10\x4d\xd3\x1e\x7f\xfc\xf1\xe8\xe8\x68\xaa\x71\x1a\x1d\x1d\xbd\
\x72\xe5\xca\x2d\x5b\xb6\x90\xad\x8b\xa7\x4f\x9f\x7e\xfe\xf9\xe7\
\x93\x93\x93\x23\x23\x23\x01\xe0\xc6\x8d\x1b\x35\x35\x35\xcd\xcd\
\xcd\xbe\x28\x8a\xbe\xbc\xe0\x18\xe3\x27\x9f\x7c\xb2\xbc\xbc\xfc\
\xf2\xe5\xcb\xa2\x28\xba\x5c\xae\x5f\xfd\xea\x57\xc9\xc9\xc9\x99\
\x99\x99\x56\xab\x55\x96\xe5\x1b\x37\x6e\x5c\xba\x74\xa9\xa6\xa6\
\x46\xa7\xd3\xa9\xaa\x2a\x08\xc2\x63\x8f\x3d\x46\xc2\xc9\x7a\x64\
\x88\xfc\x18\xf0\x0e\x0c\x28\xa9\x00\x93\x0d\x2a\xe5\xa0\x18\x25\
\x59\x10\x1f\x03\x69\xa1\xb5\x6b\xd7\x1e\x3e\x7c\xb8\xa4\xa4\xa4\
\xa9\xa9\xa9\xad\xad\xcd\x3f\xa2\x9a\xe3\x38\xb2\x0c\xf6\xdc\x73\
\xcf\xcd\x9f\x3f\x1f\x68\x0f\x25\xf9\xe4\xe1\x87\x1f\xf6\x78\x3c\
\x3b\x76\xec\xf0\x78\x3c\x24\xf0\x82\x6c\xf1\x03\x00\x45\x51\x14\
\x45\x91\x24\x69\xc5\x8a\x15\x2d\x2d\x2d\x85\x85\x85\xa4\x51\xa9\
\x15\x33\x99\x4c\xaf\xbe\xfa\x6a\x6e\x6e\x6e\x55\x55\x95\x2c\xcb\
\x1c\xc7\x95\x96\x96\x96\x95\x95\xe1\xee\x18\x63\x32\x00\xb9\xdd\
\x6e\x8b\xc5\xb2\x6c\xd9\xb2\xc5\x8b\x17\x53\x6b\x45\xf6\x33\x42\
\xdf\xcb\x60\xb8\x7b\xbb\xa5\x2f\xcf\x01\xef\xd5\x80\x1b\x24\xf1\
\x88\x6d\xe1\x1c\x25\x59\x90\x58\x34\x62\x69\x3a\x1c\x8e\x79\xf3\
\xe6\xed\xde\xbd\xfb\x3f\xff\xf9\x8f\xcb\xe5\x6a\x6f\x6f\x27\x69\
\x48\x14\x5a\x5c\x5c\xdc\xd2\xa5\x4b\x17\x2e\x5c\x08\x03\x05\x27\
\x2e\x5b\xb6\x4c\x10\x84\x7d\xfb\xf6\x35\x36\x36\xb6\xb7\xb7\xfb\
\xee\x78\x78\x78\x78\x6c\x6c\xec\xac\x59\xb3\x9e\x7e\xfa\xe9\xbd\
\x7b\xf7\x9e\x3c\x79\x52\xaf\xd7\x53\x37\x00\xa2\xee\xb3\xdd\x36\
\x6e\xdc\xb8\x67\xcf\x9e\x33\x67\xce\xd4\xd4\xd4\xb4\xb4\xb4\x10\
\x7b\x96\x54\xc0\x68\x34\xda\x6c\xb6\xd8\xd8\xd8\x9c\x9c\x9c\x7e\
\x0e\xde\x32\x1a\x8d\x24\x7e\xc7\x60\x30\x50\xeb\x4c\x96\x7c\x89\
\x68\xa8\x71\x05\xfe\x29\x2d\x16\x0b\x31\xba\x49\xdc\x72\x3f\x29\
\xcd\x66\xb3\xc9\x64\xea\x6b\x63\xc1\x6d\x33\xd4\x73\x50\x3b\x3a\
\x3a\x56\xaf\x5e\x9d\x90\x90\x90\x9b\x9b\x4b\x8d\x97\x27\x4d\xdb\
\xdc\xdc\x5c\x5e\x5e\x4e\xd6\x03\xa7\x4e\x9d\x6a\xb7\xdb\x01\xa0\
\xba\xba\xfa\xe2\xc5\x8b\x75\x75\x75\x24\x8c\xcf\x66\xb3\xc5\xc5\
\xc5\xcd\x9c\x39\x33\x32\x32\x32\x90\xed\x0f\x24\x67\x97\xcb\x75\
\xfc\xf8\xf1\xc6\xc6\xc6\xe6\xe6\x66\x12\x7d\x33\x69\xd2\xa4\x8c\
\x8c\x8c\x09\x13\x26\x60\x8c\x6b\x6b\x6b\xaf\x5e\xbd\x0a\x00\x3c\
\xcf\xa7\xa5\xa5\x85\x84\x84\xf4\x96\x9a\xef\x93\xf6\xf6\xf6\x73\
\xe7\xce\x55\x55\x55\xdd\xba\x75\x8b\x84\x75\x91\xed\x05\x89\x89\
\x89\xd3\xa7\x4f\x27\x56\x6d\x5f\x7e\x8e\xb2\xb2\xb2\xa6\xa6\x26\
\xf2\xdf\xb4\xb4\xb4\xb0\xb0\x30\xfc\xf5\x0d\x01\xad\xad\xad\x65\
\x65\x65\xe4\xc0\xb0\xf0\xf0\xf0\xf4\xf4\xf4\xbe\x6a\xd2\xd4\xd4\
\x54\x5c\x5c\x2c\x8a\xa2\x2c\xcb\x09\x09\x09\xfd\xbc\x16\xa1\xa6\
\xa6\xa6\xba\xba\x5a\x10\x04\x45\x51\xd2\xd3\xd3\x23\x22\x22\x7a\
\xe7\x49\xea\xbc\x6a\xd5\x2a\x00\xf8\xcb\x5f\xfe\x12\xe0\xbe\x92\
\x11\x97\x05\x15\xdc\x6b\xfb\x90\x3f\x81\x7b\x8a\xfa\x49\x39\x28\
\x77\x13\x99\x2d\xf7\x53\xf9\x01\x13\x8c\x5b\x6e\x4f\x16\xa3\x67\
\x5b\xf4\xd8\x6a\x47\x1e\x3e\xdf\x3e\x41\xf0\xdb\x40\x17\x78\x73\
\xfa\xb6\x57\xe0\xee\x4d\x8b\x64\x28\xf1\x65\xd2\xbb\x5c\x6a\x3e\
\xbe\xd9\xb2\x2f\xa8\xc7\x57\x25\xf0\x0b\xda\xee\xa7\x26\x03\xbe\
\x05\xca\xbf\x26\xa8\xdf\xdd\x8b\x81\xa7\x1c\xb9\x57\x4f\x8d\x92\
\x2c\x10\xed\x1d\x42\xfe\xf7\x9a\xc4\x4f\x0c\x31\x67\x12\xf4\x36\
\x60\xb9\x01\x66\xd5\x7f\x93\xf4\x60\xc0\x94\x81\xd7\x24\xf0\x94\
\x23\xd7\x7b\x8d\x97\x5e\x71\x58\x94\x3e\x8c\x8f\xcb\x37\xdb\x2d\
\x31\x20\xe3\x45\x16\x8c\x71\x05\x93\x05\x83\x02\x93\x05\x83\x02\
\x93\x05\x83\x02\x93\x05\x83\x02\x93\x05\x83\x02\x93\x05\x83\x02\
\x93\x05\x83\x02\x93\x05\x83\x02\x93\x05\x83\x02\x93\x05\x83\x02\
\x93\x05\x83\x02\x93\x05\x83\x02\x93\x05\x83\x02\x93\x05\x83\x02\
\x93\x05\x83\x02\x93\x05\x83\xc2\xf0\x04\xed\x91\x0d\x0b\xfd\xbc\
\xdd\x8c\x31\x56\xdc\x5e\xa3\x0c\x8f\x2c\xf8\x6e\x86\x25\x37\xc6\
\x30\x42\x1a\xa5\xc7\x9e\xcd\x01\x19\x06\x59\x08\x82\xe0\xf1\x78\
\x2e\x5d\xba\xe4\xdb\x75\xc3\x18\x3f\x90\xd8\x69\x55\x55\x07\x75\
\xa0\xe4\x50\x65\x81\x31\x26\x2f\xb6\xdd\xb0\x61\xc3\x6d\xbc\x0f\
\x90\x31\x0a\x90\x2d\xbe\x64\xcb\x56\x80\x0c\x55\x16\x82\x20\x3c\
\xf2\xc8\x23\x1e\x8f\x67\x88\xf9\x30\x46\x1a\xf2\xba\xa9\x00\xbb\
\xf3\xa1\xee\x2a\xf3\xbd\xbd\x84\x0d\x1f\xe3\x19\xff\x3d\x51\x81\
\x30\x54\x59\x30\xbe\x91\x30\xbf\x05\x83\x02\x93\x05\x83\x02\x93\
\x05\x83\x02\x93\x05\x83\x02\x93\x05\x83\x02\x93\x05\x83\x02\x93\
\x05\x83\x02\x93\x05\x83\x02\x93\x05\x83\x02\x93\x05\x83\x02\x93\
\x05\x83\x02\x93\x05\x83\xc2\xe8\xbd\xf3\x7b\xdc\x42\x16\x0b\x7d\
\x4b\x86\xa8\xfb\x54\xdc\xb1\xac\xd3\x58\xc3\x56\x50\x19\x14\x82\
\x7d\x10\x51\x55\x75\xcf\x9e\x3d\xdf\xff\xfe\xf7\x13\x13\x13\xed\
\x76\x7b\x4c\x4c\xcc\xfc\xf9\xf3\xf3\xf2\xf2\xc6\xba\x5e\x63\x4c\
\x50\xf7\x16\x1e\x8f\x67\xd5\xaa\x55\x9f\x7e\xfa\xe9\x9c\x39\x73\
\x16\x2d\x5a\xd4\xde\xde\x7e\xfc\xf8\xf1\x03\x07\x0e\x00\xc0\x4b\
\x2f\xbd\xf4\xdb\xdf\xfe\x56\x10\x84\x20\x8d\x5b\xc6\x41\x09\x39\
\x69\xe1\x99\x67\x9e\x01\x80\xa5\x4b\x97\xfa\xff\xeb\xad\xb7\xde\
\x22\x52\x58\xb7\x6e\x1d\xc6\xd8\x77\x7e\x56\x50\x11\xa4\xb2\xc0\
\x18\x77\x75\x75\x99\xcd\x66\x41\x10\xbe\xf3\x9d\xef\x28\x8a\xe2\
\xf5\x7a\x55\x55\x25\x22\xf8\xf6\xb7\xbf\x8d\x10\x4a\x4a\x4a\x6a\
\x6e\x6e\x26\x67\xde\x8c\x75\x65\x47\x9b\x60\xb4\x2d\xc8\x95\x6b\
\x9a\x36\x63\xc6\x0c\x45\x51\x1c\x0e\x07\xd9\xe4\x42\x5e\x20\xaf\
\xaa\xea\xfc\xf9\xf3\x31\xc6\x1e\x8f\xa7\xa2\xa2\xc2\xff\x14\xb4\
\xe0\x21\x18\x27\xa8\x64\x2f\x8d\x28\x8a\x5b\xb7\x6e\x2d\x2a\x2a\
\xba\xf7\xde\x7b\xc1\xef\x5c\x6e\x9e\xe7\x43\x42\x42\xa0\xfb\x60\
\x18\x08\xca\xc9\x6a\x30\xca\x02\xba\x5b\x3a\x35\x35\x35\x35\x35\
\xd5\xff\x13\x02\x39\x99\x46\xa7\xd3\x91\x23\x14\x83\x50\x16\xc1\
\x38\x88\xf8\x50\x55\x95\x98\x0e\xe4\x4f\x8c\x31\x00\x74\x76\x76\
\x7e\xfe\xf9\xe7\x00\xb0\x7c\xf9\x72\xb3\xd9\xdc\xe3\x9c\xf7\x20\
\x21\xa8\x27\xa8\x3d\x90\x65\x59\xa7\xd3\xed\xd8\xb1\xe3\x47\x3f\
\xfa\x51\x64\x64\xa4\xd3\xe9\x0c\x0d\x0d\x65\xbd\x45\x50\xa3\xaa\
\xaa\x4e\xa7\x73\xb9\x5c\xeb\xd6\xad\x13\x45\x71\xd3\xa6\x4d\x41\
\xab\x09\x60\xb2\x20\x28\x8a\xc2\xf3\x7c\x43\x43\x43\x4e\x4e\x4e\
\x5b\x5b\xdb\xfb\xef\xbf\xff\xd4\x53\x4f\x41\x50\x1a\x9b\x04\x26\
\x0b\x20\xe7\x4a\xd6\xd7\xd7\x3f\xf2\xc8\x23\x45\x45\x45\x7f\xfc\
\xe3\x1f\x9f\x7c\xf2\x49\x72\x8e\x5a\x5f\x87\x9a\x7e\xf3\x19\x13\
\x6f\xc9\xf8\x41\x51\x14\x8c\x71\x7d\x7d\xfd\xbd\xf7\xde\xab\xd7\
\xeb\x77\xee\xdc\x89\x31\x96\x65\x39\x08\x5d\x58\xfe\x04\x75\x6f\
\x41\x0e\xdd\x74\x3a\x9d\x0f\x3f\xfc\xb0\xd3\xe9\xdc\xb5\x6b\xd7\
\x13\x4f\x3c\x41\x06\x14\x84\x50\x4d\x4d\xcd\xc9\x93\x27\xc7\xba\
\x8e\x63\x43\x90\xfa\x2d\x08\x1c\xc7\x15\x14\x14\xac\x59\xb3\xc6\
\x6a\xb5\x1e\x3e\x7c\x78\xda\xb4\x69\x9a\xa6\x91\x03\x16\x31\xc6\
\xbf\xfe\xf5\xaf\xeb\xeb\xeb\x3f\xf9\xe4\x13\x55\x55\x87\xf7\x38\
\xc9\xf1\x4f\x90\xf6\x16\x18\x63\x00\xd8\xbe\x7d\xfb\xf2\xe5\xcb\
\x1d\x0e\xc7\x17\x5f\x7c\x31\x6d\xda\x34\xf0\xdb\xea\x2f\x49\xd2\
\xa1\x43\x87\x7c\x07\x7d\x07\x1b\xc1\xd8\x5b\x90\x03\x95\xdf\x7b\
\xef\xbd\xe7\x9f\x7f\x1e\x00\x6a\x6b\x6b\xe7\xcc\x99\xd3\xd5\xd5\
\xe5\xff\xfa\x07\x8e\xe3\x9c\x4e\x67\x3f\x07\x59\x7f\xb3\x09\x46\
\x59\x90\xae\xc2\xe9\x74\x9a\xcd\x66\x32\x2f\xed\xed\xca\x24\xa7\
\xda\x93\x37\xc8\x04\x21\xc1\xe8\xe5\xc4\x18\x23\x84\x2e\x5c\xb8\
\x50\x59\x59\xd9\x97\xc5\xc0\x71\x9c\xd7\xeb\x8d\x8f\x8f\x9f\x33\
\x67\x0e\x0e\x3e\xa7\x16\x52\xb5\x20\x9d\x9a\x73\x28\x20\xbb\x4a\
\xc3\x64\xc5\x04\x03\x04\x91\x32\x82\xb1\xb7\xf8\x8a\xfe\x2f\x1d\
\x07\xad\x45\x0e\x42\x51\xdb\xa9\xb1\xae\x03\x63\xdc\x81\x5e\x3c\
\xbf\x62\xac\xeb\xc0\x18\x77\x08\xed\x4a\xeb\x58\xd7\x81\x31\xee\
\x10\x04\xa4\x1b\xeb\x3a\x30\xc6\x1d\x02\x1e\xc0\xee\x62\x04\x23\
\xc1\x6a\x6a\x33\xfa\x85\xc9\x82\x41\x81\xc9\x82\x41\x81\xc9\x82\
\x41\x81\x99\x9c\x0c\x0a\x02\x0a\x26\x57\x3f\x23\x40\xd0\xfe\x86\
\xbd\x63\x5d\x07\xc6\xb8\x23\xb8\x97\xca\x18\x7d\xc0\x6c\x0b\x06\
\x05\x66\x5b\x30\x28\xb0\x09\x2a\x83\x02\x93\x05\x83\x02\x93\x05\
\x83\x02\x93\x05\x83\x02\x93\x05\x83\x02\x93\x05\x83\x02\x93\x05\
\x83\x02\x93\x05\x83\x02\x93\x05\x83\x02\x93\x05\x83\x02\x93\x05\
\x83\x02\x93\x05\x83\x02\x93\x05\x83\x02\x93\x05\x83\x02\x93\x05\
\x83\x02\x93\x05\x83\x02\x93\x05\x83\x02\x93\x05\x83\x02\x93\x05\
\x83\xc2\xff\x03\x78\xf8\xa2\x0e\x16\xe4\x5d\x96\x00\x00\x00\x00\
\x49\x45\x4e\x44\xae\x42\x60\x82\
\x00\x00\x01\x93\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x20\x00\x00\x00\x20\x08\x06\x00\x00\x00\x73\x7a\x7a\xf4\
\x00\x00\x00\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\
\xa7\x93\x00\x00\x01\x48\x49\x44\x41\x54\x58\x85\xed\xd6\x4f\x4a\
\x03\x31\x1c\xc5\xf1\xcf\x5a\x71\x67\x15\xa1\xe0\x42\xef\xa4\x6e\
\xb4\x8b\xe2\xba\x22\x88\xa2\x47\xb2\x47\x10\x14\x3c\x81\xd6\xba\
\x14\xea\x5e\x3d\x80\x65\x5c\x4c\x86\x46\xd1\xb6\x99\x3f\x15\xc4\
\x07\xd9\x84\xbc\x7c\x5f\x92\x5f\x32\xc3\xbf\xea\xd1\x0e\x86\x78\
\x41\x1f\xed\x45\xc2\x8f\x91\x7d\x69\xcf\xd8\x5e\x04\xfc\x24\x00\
\xc7\xe8\xa2\x85\xeb\xd0\x37\xc2\x56\x93\xf0\x62\xe5\x63\x1c\x44\
\xfd\x4b\xb8\xd2\xf0\x4e\xfc\x04\x5f\x48\x88\x59\xf0\x46\x43\xc4\
\x67\x3e\x0d\x5e\x68\xd9\xe7\x9a\xa8\x74\x3b\x62\x78\x27\xc1\x17\
\x87\xe8\x57\x85\x67\x38\x2a\xe1\x6f\x05\xef\x6b\x55\x78\x86\x7b\
\xac\x25\xce\xd1\x0d\xde\x61\x59\xf8\x58\xbe\xf2\xfb\x12\x21\xf6\
\x83\x3f\xc3\x5e\x0a\xfc\xbb\x6a\x6f\xe1\x2e\xf4\x3f\x62\x63\xc6\
\x1c\xbb\x78\x0f\xe3\x2f\xaa\xc2\x0b\xcd\x1b\xa2\x11\xf8\xbc\x21\
\x1a\x85\xcf\x0a\x51\x1a\xbe\x13\xc1\xf7\xe7\xf4\xac\x63\x10\x7c\
\x03\xf4\x4c\x0a\xee\x2c\x05\x0e\x0f\xc1\xd8\x4d\xf4\xc5\x21\x8a\
\x96\x0c\x27\xff\x99\xc8\xb0\x5a\xc2\xdb\xab\x0a\x27\x7f\x26\x33\
\xf9\xb3\xb9\x9c\xe0\x8b\xef\xf9\x69\x59\x38\xf9\x87\x62\x94\x18\
\xe2\xa0\x2e\x78\xa1\x4d\x3c\x85\x09\x6f\xb1\x32\x65\x6c\xe9\x6a\
\xaf\x23\x44\x0c\x3f\xaf\x13\x3e\x4f\x88\x8e\xc9\xb6\x37\x02\x2f\
\xb4\x65\x52\x13\x37\xf2\x8f\xcf\xa1\x9a\xcf\x7c\x96\xe2\x9d\xa8\
\xab\x25\xab\x8d\x4b\xbc\xfd\x56\x80\x7f\xfd\x6d\x7d\x00\xd1\x84\
\xbb\x35\x03\xbe\x08\xdc\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\
\x60\x82\
\x00\x00\x01\x63\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xff\x61\
\x00\x00\x00\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\
\xa7\x93\x00\x00\x01\x18\x49\x44\x41\x54\x38\x8d\xa5\xd3\xbf\x2e\
\x44\x41\x14\x06\xf0\x9f\x3f\x8d\x15\xbb\x15\xd1\xe8\x90\xb5\x05\
\x7a\xd9\xc2\x13\x68\x14\x1e\x44\x21\xda\x6d\xfd\xcd\xe5\x01\x88\
\x6c\xa5\x10\x85\x42\x34\xe2\x05\x58\xc5\x8a\x55\xe2\x01\x88\x56\
\x14\x77\x6e\x4c\x26\xf7\x36\x7c\xc9\x49\x66\xce\xf9\x66\xce\x77\
\xce\x9c\xe1\x9f\x18\xaa\xf0\xb7\xb0\x86\xf9\xb0\x7f\xc6\x05\xfa\
\x29\x71\x38\xd9\x37\xd0\xc5\x35\x26\x71\x1b\x6c\x0a\x37\x38\x43\
\xbd\x4a\x4d\x03\x3d\x1c\x62\xac\x24\x5e\x43\x86\x87\xaa\x4b\xba\
\xe1\x70\x81\x69\xec\x63\x2f\xac\x0b\x64\x38\x4d\x0f\xb7\xf0\x9a\
\x64\xbe\xc3\x0e\x76\x43\x19\xb1\x92\x37\x34\xe3\x0b\xb6\x43\xa6\
\x18\xf7\x18\x09\x72\xbf\x92\xd8\x01\xb6\xf8\x6d\xe2\x2c\x1e\x13\
\xd2\x32\xbe\xd1\xc1\x55\x12\xeb\x61\x0e\x46\xd3\x5a\x12\x6c\x60\
\x05\xab\x55\x84\x42\xc1\x0b\x16\x4b\xe2\xef\xd8\xc4\x67\xe2\x5f\
\xc2\x20\x76\x2c\xc8\x9b\x58\x4b\x88\x33\xc1\x62\x8c\x2b\x69\x22\
\xf9\x90\x64\x89\xaf\x13\x2c\xc6\x11\x4e\x4a\xd4\xaa\xcb\x87\x24\
\x2b\x51\x52\x64\x3e\x96\xbf\xce\x44\xe1\x8c\x9b\xf8\x81\x76\xc8\
\x30\xc0\x79\x20\x93\xbf\xc8\xba\x7c\x9c\xdb\xa2\x9e\x54\x7d\xa6\
\xa6\xfc\x33\x15\x75\xf6\x71\x89\xa7\x0a\xfe\xdf\xf1\x03\x27\xfd\
\x32\xe4\xdd\x25\x00\xc7\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\
\x60\x82\
\x00\x00\x00\xae\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xff\x61\
\x00\x00\x00\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\
\xa7\x93\x00\x00\x00\x63\x49\x44\x41\x54\x38\x8d\xcd\x92\x41\x0a\
\xc0\x20\x0c\x04\x87\xbe\xab\x60\xe8\x33\x7d\x61\xed\x2b\xbc\x44\
\x28\xd4\x98\x88\x07\xbb\xd7\x9d\x5d\xd8\x10\xf8\x93\x32\x90\x02\
\x9c\x28\xfb\x51\x02\x8a\x53\x22\xca\x88\x05\x9c\xc0\x0d\x5c\x86\
\x57\x0c\xcf\x05\xc3\xe1\x5e\x60\x3a\xdc\xd4\xf6\x0e\x37\x1f\xb3\
\xad\x51\x2d\x4d\x58\x3a\xe2\x08\x74\x4b\xdc\x27\x51\xef\xb1\x98\
\xec\x84\xdf\x25\xdd\x57\xde\xa3\x0a\x64\xe5\x1c\x32\x38\xcd\xe4\
\x26\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
\x00\x00\x01\xd7\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x20\x00\x00\x00\x20\x08\x06\x00\x00\x00\x73\x7a\x7a\xf4\
\x00\x00\x00\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\
\xa7\x93\x00\x00\x01\x8c\x49\x44\x41\x54\x58\x85\xed\xd6\xcf\x4b\
\x15\x51\x18\xc6\xf1\x4f\xb7\x16\xc1\x05\x85\x28\x25\x84\x10\xdb\
\x28\x44\x24\xa8\x18\x41\x11\xad\xec\xef\x10\x5a\xb4\x6e\xa1\x0b\
\x71\xd5\xa2\x16\x41\x2b\xfd\x33\x5c\x0a\x6d\xfd\xb1\x11\xac\x96\
\xd1\xc6\x54\x68\x53\x54\x46\x68\xa5\x2d\xce\xbd\x70\x19\xce\x19\
\xee\xdc\x3b\x77\xee\x22\x1f\x38\x30\xbc\xef\xbc\xe7\xfd\x32\xf3\
\xce\x33\x87\xff\x5d\x17\x12\xf1\x3a\x66\x73\xf2\x31\x7d\xc7\x11\
\x3e\xe2\xb8\x4b\x2e\x0b\x38\xeb\x70\xfd\xc1\x0e\x16\x31\xd0\x29\
\xc0\x72\x17\x00\xad\xeb\x33\xee\xe5\x35\xaa\x75\x4a\xd8\xa6\x86\
\xb0\x8e\x9b\xfd\x02\x20\xcc\xd3\x8b\x54\xf2\x52\xc1\xcd\xde\x63\
\x2b\x12\xbf\x8a\x29\xdc\x48\xd4\x3d\x6e\x80\xfc\x6c\xb7\x51\x6a\
\x06\x5e\xe5\xd4\xd4\xf0\x24\x51\x77\x86\x5b\xa9\xa2\xb2\x74\x8a\
\x55\x6c\x26\xf2\x57\x7a\x0d\xd0\xd4\xa7\x44\xfc\xb0\x2a\x80\x89\
\x48\xec\x2b\xf6\x62\x37\x17\x1d\xc2\x3c\x5d\xc4\x53\xdc\x8e\xe4\
\x56\x71\x52\x06\xc0\xa3\xc6\x66\x59\x5d\xc3\x24\x46\x23\xb9\xb7\
\x78\x5e\xb0\x4f\x69\x4e\x78\x24\xc7\x84\xe8\xbd\x11\xd5\x05\xdf\
\x78\xd0\x2f\x00\xc2\xeb\x59\xc3\x78\x19\x00\x2b\xc2\xf7\x9c\x5d\
\xc3\x98\xc6\x92\x30\xf1\x59\x0d\xe2\x65\x91\x46\x9d\x38\x61\x53\
\x77\xf0\x3b\x52\xfb\x17\xd7\xb3\x37\xf7\xe2\x15\xec\x8a\xbb\x61\
\x4d\x38\xe4\xf4\x1c\x80\xb4\x1b\x56\xf2\x04\xa2\x8d\x1a\xfa\x55\
\x05\xc0\x14\xee\x27\x72\xfb\xd9\x40\x51\x27\x1c\xc4\x58\x24\x7e\
\x19\x23\x98\xc3\x7c\x62\xdf\x1f\xd8\x68\xb7\x51\x59\x4e\xd8\xba\
\x5e\xc7\x1a\x55\x61\x44\xf0\x41\x38\x25\xf7\x05\xe0\x1d\x1e\x0a\
\xff\x85\x4a\x01\x0e\xf0\x0c\x33\x8d\xeb\xa8\x52\x43\xf8\x06\x77\
\x15\x03\xfc\x86\x2f\xc2\xe3\xde\x16\x06\xee\xb4\x40\xfd\xb9\xfa\
\xa3\x7f\xde\xd4\x90\xf2\xea\x8a\xc9\x88\x00\x00\x00\x00\x49\x45\
\x4e\x44\xae\x42\x60\x82\
\x00\x00\x00\xa7\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xff\x61\
\x00\x00\x00\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\
\xa7\x93\x00\x00\x00\x5c\x49\x44\x41\x54\x38\x8d\xed\x93\x41\x0a\
\x80\x30\x0c\x04\x47\x9f\xd0\x2f\x5b\x7c\xb3\x39\xd5\x4b\xc5\xba\
\x52\xdb\x4a\xbc\x39\x10\xb2\x90\x65\xc9\x21\x81\x8f\x58\x01\x03\
\x52\xee\x71\x34\xc0\x80\x90\x75\x00\xb6\x9a\x71\x2a\x74\x7a\x39\
\xbb\xa0\xc6\xe6\x7c\x6e\x18\xb5\xdf\xa8\x05\x74\xf3\x07\x38\x04\
\x28\xe5\x05\x2a\x8f\x17\x79\x10\x39\x7f\x40\xcb\x80\xc5\x65\x4d\
\x57\x76\x10\x96\x17\x24\xc4\x1a\x99\x16\x00\x00\x00\x00\x49\x45\
\x4e\x44\xae\x42\x60\x82\
\x00\x00\x03\x43\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x19\x00\x00\x00\x19\x08\x06\x00\x00\x00\xc4\xe9\x85\x63\
\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\x00\x00\x00\
\x09\x70\x48\x59\x73\x00\x00\x0e\xc2\x00\x00\x0e\xc2\x01\x15\x28\
\x4a\x80\x00\x00\x02\xd8\x49\x44\x41\x54\x48\x4b\xad\x96\x3f\x4c\
\x54\x41\x10\xc6\xbf\x7d\xf7\x10\x4a\x8d\x05\x58\x91\x50\x90\x78\
\x9c\x12\xb5\xa2\x34\x1a\x51\x08\xd4\x72\x91\x02\x0c\xa1\xa2\x27\
\x34\xc4\x86\x02\x48\x28\x08\xe5\x41\x21\x01\x0b\x28\x48\x20\x67\
\x34\x6a\x49\xa5\xe6\x34\x9e\x1d\x96\x1e\x09\x9c\x16\x14\x87\xf7\
\xee\xad\x33\xfb\xf6\xdd\xfb\xff\x0e\x89\xbf\xe2\xb2\x33\x7b\xb7\
\xdf\xee\xce\xcc\xce\x09\xa4\x70\x7e\xf7\x66\x57\x5b\xdd\xc8\x43\
\xe2\x09\x04\xee\x09\x1b\xd7\xf4\x14\xa4\x81\x5f\xe4\xff\x48\xfe\
\x62\xbd\xcd\xde\x6a\xff\xf4\xbd\xa2\xa7\x22\xc4\x8a\xd4\xfb\xb3\
\xd7\x33\xb6\x78\x41\x8b\x3e\x27\xb3\xc3\xf1\xa6\x52\x23\xd1\x42\
\xc3\x90\xf3\x6d\xa5\xf2\xa9\xf6\x35\x89\x88\x58\xb7\xb3\xf7\x49\
\x60\x8b\x76\xd9\xa5\x5d\x17\x47\xa0\x42\x42\x79\xf3\x4b\xf9\x83\
\xf6\x28\x02\x22\xf6\xad\xbe\xa7\xb4\xfb\x97\x34\x34\x1d\xcf\xa5\
\xb0\xe8\x54\xe3\xc6\xd7\x6f\xaf\xb4\xed\x89\xa8\x13\x34\xc4\x1b\
\x1a\x7a\x02\x1d\x74\x53\xb5\x9a\x36\x52\x88\x7e\xcf\x6a\x64\xe4\
\x23\xf7\x44\x06\x7f\xe8\x18\x6c\xd1\xd0\x13\xe8\xec\x04\x76\x77\
\x81\xb1\x31\xed\x48\x60\x70\x10\x38\x38\x00\x7a\x7a\xb4\x43\x61\
\xf2\x7a\xbc\x2e\x1b\x4a\x84\x83\x1c\x88\x01\x0b\x6c\x6c\x00\xdd\
\xdd\xc0\xdc\x5c\xb2\x10\x0b\x2c\x2e\x3a\xdf\x5f\x5f\x0f\x0a\xd1\
\x7a\x6a\x5d\x42\x70\x9a\x5e\x39\x37\x7e\xd0\xd8\xc9\x22\x83\x74\
\x77\x76\x80\xde\x5e\x65\x2a\xa4\x04\x16\x16\x80\xed\x6d\xed\x20\
\x5c\x81\x4c\x46\x3b\x88\xe3\x63\x60\x78\xd8\x7f\x75\xb5\x3f\xed\
\x76\x8f\xa1\xea\xc0\x9f\xa6\xb6\x0d\x2c\x2d\x05\xef\x58\x50\xe8\
\xfc\x27\x8a\x13\x68\x34\x80\xe5\xe5\x70\x6c\x3a\xcc\xba\xc8\x0b\
\x3b\xd7\xf7\x56\x48\x3c\xd4\x4e\x8f\x81\x01\x60\x75\xd5\x09\xaa\
\x0b\x9f\x68\x6f\x0f\x18\x19\x89\x0a\xcc\xce\x02\xc5\xa2\x76\x78\
\x48\x81\xf7\x82\xd2\xb6\xea\xaf\xe4\x00\x71\x42\x61\x52\x04\x18\
\x4a\xe7\xdf\x46\xa2\x00\x73\x78\x08\xcc\xcc\x84\xaf\xc0\xa3\x85\
\x00\x43\xeb\x5f\x55\xd9\x95\x0a\x0b\x6d\x6e\x6a\x23\xc4\xfe\x7e\
\xaa\x80\x4b\x6b\x11\x0e\xf2\xc4\x84\x36\x42\x8c\x8e\xb6\xae\x23\
\xc2\x50\xaf\x69\x12\x71\x59\xe4\x27\x9c\x75\x31\xa8\x98\xa8\xe7\
\x3a\x8e\xa4\x34\x2d\x14\xd2\xd3\x3b\x8c\xc4\x67\x43\x0a\xf9\x5a\
\x9b\x1e\x49\x02\x1c\xe4\x95\x95\x68\x32\xa4\x08\x49\x43\x16\xa3\
\x15\xcf\xe9\xca\x6f\x11\x3f\x15\x2e\x71\x59\x14\x97\xde\x67\x67\
\xc0\xd0\x10\x50\xad\x6a\x87\xae\x78\xee\x68\xdc\x70\xb4\xd3\xd9\
\xe1\xd4\x14\x70\x72\xe2\xd8\x49\x69\x1a\x4e\x6f\x16\x98\x9e\xf6\
\x0b\x70\x3c\x0a\xb4\xfe\x4f\x95\x5d\xdc\xd1\xb8\xe1\xa8\x19\xe6\
\xe8\x08\x98\x9c\x74\xde\xa2\xb4\x3a\x70\x85\x4e\xa9\x19\xb2\x40\
\xa9\xa4\x27\x14\x15\x6a\xcb\xf3\x3c\xf0\xfa\x49\x7f\xf6\x41\xc6\
\x12\x1c\x9f\xff\xd3\x4f\x4c\xf9\xd8\x2c\x95\xdf\xb1\xd1\xac\x13\
\x76\xd0\xf1\xc6\x69\x68\x39\x1e\xe2\x22\x02\x4c\x48\x80\xd7\x71\
\x05\x98\x40\x31\x72\xcb\xe4\x1d\x04\xae\xee\xdf\xa8\xf0\xef\xfd\
\xad\x97\x89\x54\x3c\xef\xc0\xca\xc8\x1c\xed\x66\x8d\xcc\x0b\x1e\
\x45\xfd\x5b\x59\xa3\x4c\xca\xf9\x4f\xe0\xd2\x8c\x49\x1c\x94\xde\
\x37\x4c\x4b\x3c\x13\xb6\xe0\xff\x5d\x77\xf8\xb1\xd3\x53\xaa\x92\
\xb9\xd0\xb8\x0e\x2c\x53\x6e\x72\x16\xe9\xa9\x10\xc0\x5f\xd7\x77\
\x48\xe8\xe8\xc2\xdf\x4d\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\
\x60\x82\
\x00\x00\x03\x4d\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x64\x00\x00\x00\x64\x08\x06\x00\x00\x00\x70\xe2\x95\x54\
\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\x00\x00\x00\
\x09\x70\x48\x59\x73\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7\x6f\
\xa8\x64\x00\x00\x02\xe2\x49\x44\x41\x54\x78\x5e\xed\xdd\xbd\x8a\
\x15\x31\x1c\x05\xf0\xeb\x07\x8a\x2f\xa0\x8d\x95\xa2\x2c\x8a\xa0\
\x20\x82\xbd\xa8\xcd\x62\xa3\x0b\xea\x53\x58\x69\xa7\x76\x5a\xf9\
\x1e\x8a\xa8\xfb\x12\x36\x56\xa2\xd8\xe8\x0a\xb2\x8d\x36\x2a\xf8\
\x81\x36\x7a\xfe\x24\x45\x18\x32\x33\x77\x32\xc9\xdc\x33\xd9\xf3\
\x83\x43\xc2\x2d\x96\xc9\x3d\xbb\xe1\x86\x3b\xec\x2c\x44\x44\x44\
\x44\x44\x44\x26\xb6\xcb\x8f\x39\x1c\x43\xd6\x91\x23\xc8\x41\x7b\
\x81\xc0\x17\x64\x0b\xd9\x44\xde\xdb\x0b\x3b\xc1\x71\xc4\x16\xfc\
\x8f\x3c\x2f\x10\xfb\xa5\xa9\xda\x65\xe4\x3b\x12\x7b\x03\x18\xf3\
\x0d\xb9\x84\x54\xe9\x0c\xf2\x13\x89\x2d\x9c\x39\xbf\x90\x73\x48\
\x55\xf6\x20\x6f\x91\xd8\x82\xe7\x90\x77\xc8\x5e\xa4\x1a\x37\x90\
\xd8\x42\xe7\x94\xeb\x08\x9d\xdd\x7e\x1c\xea\x9a\x1f\xe7\xec\xaa\
\x1f\xa9\xa4\x16\x72\xd6\x8f\x73\x46\xb9\x86\xd4\x73\xc8\x1f\x64\
\x9f\x9b\x46\xbd\x44\xb6\xdd\x74\x65\x0e\x23\xe7\xdd\x34\xea\x2f\
\xb2\xdf\x4d\xe7\x2f\xb6\x27\x87\x61\xd8\xd2\xec\x1a\x62\xd7\x16\
\x86\x4e\xea\x96\x25\x85\xa8\x10\x32\x2a\x84\x8c\x0a\x21\xa3\x42\
\xc8\xa8\x10\x32\x2a\x84\x8c\x0a\x21\xa3\x42\xc8\xa8\x10\x32\x2a\
\x84\x8c\x0a\x21\xa3\x42\xc8\xa8\x10\x32\x2a\x84\x8c\x0a\xe9\xd6\
\xf5\x05\x57\x11\x2a\xa4\xdb\x2d\xe4\x81\x9b\x4e\x43\x85\xf4\xbb\
\x8d\x4c\x56\x8a\x0a\x59\xce\x64\xa5\xa4\xde\xe4\xd0\xf7\x7d\xf4\
\x06\xf2\xc4\x4d\x57\xe6\x14\x72\xd3\x4d\x5b\xdd\xf1\x63\x9b\xc7\
\x48\x78\x7f\xc0\x7d\xe4\x9e\x9b\x72\x69\xde\x2c\xd0\x4c\x0d\xf7\
\x6d\x19\x2b\xa4\xb9\xb6\xa2\x7f\x29\xda\xb2\x86\x2b\xba\x7d\xa9\
\x90\x34\xc5\x4a\x51\x21\xe9\x8a\x94\xa2\x42\xc6\xc9\x5e\x8a\x0a\
\x19\x2f\x6b\x29\x2a\x24\x8f\x6c\xa5\xb0\x9c\x43\x0e\x20\x27\xdc\
\x94\x8a\xbd\xc9\x17\xdc\x74\x29\x2b\x3b\xa7\x34\x3f\x9b\x37\x33\
\xf4\x1c\x72\x12\x89\xfd\x9c\x39\x66\xd4\x5f\x8a\xb6\xac\xfc\x46\
\x6d\x5f\x2a\xa4\x8c\xe4\x52\x54\x48\x39\x49\xa5\xa8\x90\xb2\x7e\
\xfb\x71\x69\x2a\xa4\x1c\xfb\xb4\x65\x9f\xba\x06\x51\x21\x65\x24\
\x95\x61\x54\x48\x7e\xc9\x65\x18\x1d\x0c\xbb\xed\xd8\x83\x21\xab\
\xd8\x17\x54\x6d\xb9\x8b\x8c\xa6\x2d\x2b\x8f\x51\xdb\x54\x48\x85\
\x8c\x97\xad\x0c\xa3\x42\xc6\xc9\x5a\x86\x51\x21\xe9\xb2\x97\x61\
\x54\x48\x9a\x22\x65\x18\x15\x32\x5c\xb1\x32\x4c\xcd\x37\xca\xad\
\x21\x57\xdc\xb4\xd5\x43\x3f\xb6\xd1\x8d\x72\x19\xd9\x35\xc4\xae\
\x2d\x4c\x9f\xf0\x1c\x92\xe5\x9c\xd1\x47\x5b\xd6\x72\x8a\x6e\x53\
\x21\x15\xd2\x6f\xb2\x32\x8c\x0a\xe9\xf6\x08\x99\xac\x0c\xa3\x42\
\xba\xd9\xbf\x2a\x9c\x94\x0a\x21\xa3\x42\xc8\xa8\x10\x32\x2a\x84\
\x8c\x0a\x21\xa3\x42\xc8\xa8\x10\x32\x2a\x84\x8c\x0a\x21\xa3\x42\
\xc8\xa8\x10\x32\x2a\x84\x8c\x0a\x21\xa3\x42\xc8\xa8\x10\x32\x7a\
\xe4\x51\x25\x3e\x21\xe1\xcd\x02\x73\xcc\x47\x84\x4e\xea\x96\xf5\
\xca\x8f\x73\x46\xb9\x86\xd4\x42\x56\x7d\xcf\x55\x0e\x4f\xfd\x58\
\x05\x7b\xf4\xea\x1b\x24\xb6\x15\xcc\x21\xaf\x11\x5b\x43\x55\x4e\
\x23\x3f\x90\xd8\x82\x99\x63\x0f\x27\xae\xe1\xc1\x98\x51\x17\x11\
\x7b\x24\x76\x6c\xe1\x8c\xf9\x8a\xd8\x35\x57\xcd\x1e\x1a\xff\x1c\
\x89\xbd\x01\x4c\x79\x86\x1c\x45\xa8\xa5\x9e\x43\x62\x6c\xb1\xeb\
\x7e\x3c\x64\x2f\x10\xf8\x8c\x7c\x40\x36\x91\x2d\x7b\x41\x44\x44\
\x44\x44\x44\x44\x42\x8b\xc5\x7f\xe5\x3f\x89\x9d\x4e\x70\xa6\x97\
\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
\x00\x00\x00\xd4\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x20\x00\x00\x00\x20\x08\x06\x00\x00\x00\x73\x7a\x7a\xf4\
\x00\x00\x00\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\
\xa7\x93\x00\x00\x00\x89\x49\x44\x41\x54\x58\x85\x63\x60\x18\x05\
\xa3\x80\x74\x30\x9f\x81\x81\xe1\x3f\x01\x7c\x9f\x58\xc3\x98\xc8\
\x70\x80\x03\x11\x6a\x0e\x90\x61\x2e\x59\x40\x8a\x01\xe2\xe3\xa7\
\xe4\x1a\x40\x4e\x08\x20\x03\x63\x28\x7d\x76\xc4\x3a\xc0\x04\x4a\
\x9f\xa1\xd0\x1c\xb2\xc1\x33\x06\x48\x1a\x90\x1c\x08\xcb\x29\x4e\
\x80\x0c\x0c\x94\x45\x01\xc5\xf1\x3f\xe4\x1d\x30\x9a\x00\x29\x4e\
\x80\x0c\x0c\xe4\x47\x01\x55\xe2\x7f\x48\x3b\x60\x34\x01\x52\x25\
\x01\x32\x30\x90\x17\x05\x54\x8b\xff\x21\xeb\x80\x91\x97\x00\xa9\
\xda\x0a\x46\x07\xc4\x44\xc1\xa0\x6a\x05\x8f\x82\xe1\x07\x00\x83\
\x09\x30\xf9\xc1\x98\x1d\x5e\x00\x00\x00\x00\x49\x45\x4e\x44\xae\
\x42\x60\x82\
"
qt_resource_name = b"\
\x00\x0f\
\x00\x7b\x2b\x75\
\x00\x49\
\x00\x63\x00\x6f\x00\x6e\x00\x73\x00\x5f\x00\x52\x00\x65\x00\x66\x00\x65\x00\x72\x00\x65\x00\x6e\x00\x63\x00\x65\
\x00\x05\
\x00\x4f\xa6\x53\
\x00\x49\
\x00\x63\x00\x6f\x00\x6e\x00\x73\
\x00\x07\
\x09\xc1\x57\xa7\
\x00\x72\
\x00\x75\x00\x6e\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x0e\
\x01\x21\x26\xa7\
\x00\x62\
\x00\x64\x00\x73\x00\x69\x00\x6d\x00\x5f\x00\x69\x00\x63\x00\x6f\x00\x6e\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x08\
\x08\xc8\x58\x67\
\x00\x73\
\x00\x61\x00\x76\x00\x65\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x09\
\x06\x97\x98\x67\
\x00\x61\
\x00\x62\x00\x6f\x00\x72\x00\x74\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x0b\
\x02\x6e\xc3\xe7\
\x00\x6f\
\x00\x76\x00\x65\x00\x72\x00\x6c\x00\x61\x00\x70\x00\x2e\x00\x73\x00\x76\x00\x67\
\x00\x08\
\x04\xb2\x58\xc7\
\x00\x75\
\x00\x6e\x00\x64\x00\x6f\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x10\
\x0c\xd3\x1f\x47\
\x00\x63\
\x00\x6f\x00\x6c\x00\x6f\x00\x72\x00\x5f\x00\x70\x00\x69\x00\x63\x00\x6b\x00\x65\x00\x72\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x0c\
\x02\xc1\xfc\xc7\
\x00\x6e\
\x00\x65\x00\x77\x00\x5f\x00\x66\x00\x69\x00\x6c\x00\x65\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x0f\
\x0a\x22\x33\x07\
\x00\x62\
\x00\x64\x00\x73\x00\x69\x00\x6d\x00\x5f\x00\x6c\x00\x6f\x00\x67\x00\x6f\x00\x32\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x08\
\x0b\xb2\x58\x47\
\x00\x72\
\x00\x65\x00\x64\x00\x6f\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x0d\
\x08\xd5\xc4\xe7\
\x00\x75\
\x00\x6e\x00\x64\x00\x65\x00\x72\x00\x6c\x00\x69\x00\x6e\x00\x65\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x10\
\x0a\x7b\xb6\x67\
\x00\x63\
\x00\x65\x00\x6e\x00\x74\x00\x65\x00\x72\x00\x5f\x00\x61\x00\x6c\x00\x69\x00\x67\x00\x6e\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x0b\
\x00\xc4\x52\x27\
\x00\x73\
\x00\x69\x00\x6d\x00\x54\x00\x69\x00\x6d\x00\x65\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x0f\
\x04\x54\x04\xe7\
\x00\x72\
\x00\x69\x00\x67\x00\x68\x00\x74\x00\x5f\x00\x61\x00\x6c\x00\x69\x00\x67\x00\x6e\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x08\
\x08\x01\x59\x27\
\x00\x6d\
\x00\x61\x00\x69\x00\x6e\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x0f\
\x02\x4f\x22\xa7\
\x00\x6f\
\x00\x70\x00\x65\x00\x6e\x00\x5f\x00\x66\x00\x6f\x00\x6c\x00\x64\x00\x65\x00\x72\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x0b\
\x0c\x53\x24\x67\
\x00\x73\
\x00\x75\x00\x63\x00\x63\x00\x65\x00\x73\x00\x73\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x0b\
\x05\x79\x4e\x27\
\x00\x73\
\x00\x61\x00\x76\x00\x65\x00\x5f\x00\x61\x00\x73\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x0e\
\x08\x95\xe3\xa7\
\x00\x6c\
\x00\x65\x00\x66\x00\x74\x00\x5f\x00\x61\x00\x6c\x00\x69\x00\x67\x00\x6e\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x0f\
\x02\x12\x49\x67\
\x00\x62\
\x00\x64\x00\x73\x00\x69\x00\x6d\x00\x5f\x00\x69\x00\x63\x00\x6f\x00\x6e\x00\x32\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x10\
\x02\x96\x70\x87\
\x00\x63\
\x00\x6c\x00\x65\x00\x61\x00\x72\x00\x5f\x00\x66\x00\x6f\x00\x72\x00\x6d\x00\x61\x00\x74\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x08\
\x0c\x33\x5a\x87\
\x00\x68\
\x00\x65\x00\x6c\x00\x70\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x08\
\x0c\x07\x58\x47\
\x00\x71\
\x00\x75\x00\x69\x00\x74\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x08\
\x06\x27\x5a\x67\
\x00\x62\
\x00\x6f\x00\x6c\x00\x64\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x0a\
\x06\xcb\x4f\xc7\
\x00\x72\
\x00\x65\x00\x6d\x00\x6f\x00\x76\x00\x65\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x09\
\x09\x65\x8e\x67\
\x00\x65\
\x00\x72\x00\x72\x00\x6f\x00\x72\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x0d\
\x0c\x6c\x85\xa7\
\x00\x65\
\x00\x78\x00\x70\x00\x6f\x00\x72\x00\x74\x00\x5f\x00\x61\x00\x73\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x0a\
\x02\xfc\x42\x47\
\x00\x69\
\x00\x74\x00\x61\x00\x6c\x00\x69\x00\x63\x00\x2e\x00\x70\x00\x6e\x00\x67\
"
qt_resource_struct_v1 = b"\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\
\x00\x00\x00\x24\x00\x02\x00\x00\x00\x1c\x00\x00\x00\x03\
\x00\x00\x01\x8e\x00\x00\x00\x00\x00\x01\x00\x00\x6f\x6f\
\x00\x00\x00\x48\x00\x00\x00\x00\x00\x01\x00\x00\x0e\xc8\
\x00\x00\x02\x62\x00\x00\x00\x00\x00\x01\x00\x00\x99\x8b\
\x00\x00\x01\xe4\x00\x00\x00\x00\x00\x01\x00\x00\x8b\xe8\
\x00\x00\x00\x98\x00\x00\x00\x00\x00\x01\x00\x00\x4a\x63\
\x00\x00\x02\x86\x00\x00\x00\x00\x00\x01\x00\x00\xb4\x48\
\x00\x00\x00\xf0\x00\x00\x00\x00\x00\x01\x00\x00\x50\x39\
\x00\x00\x03\x40\x00\x00\x00\x00\x00\x01\x00\x00\xc1\x16\
\x00\x00\x01\xaa\x00\x00\x00\x00\x00\x01\x00\x00\x7c\xae\
\x00\x00\x00\xb4\x00\x00\x00\x00\x00\x01\x00\x00\x4d\x74\
\x00\x00\x02\x24\x00\x00\x00\x00\x00\x01\x00\x00\x8f\xe5\
\x00\x00\x02\xd8\x00\x00\x00\x00\x00\x01\x00\x00\xb7\xf8\
\x00\x00\x00\x80\x00\x00\x00\x00\x00\x01\x00\x00\x3a\x24\
\x00\x00\x02\xee\x00\x00\x00\x00\x00\x01\x00\x00\xb9\xd3\
\x00\x00\x01\xce\x00\x00\x00\x00\x00\x01\x00\x00\x7d\x36\
\x00\x00\x02\x40\x00\x00\x00\x00\x00\x01\x00\x00\x99\x04\
\x00\x00\x00\x6a\x00\x00\x00\x00\x00\x01\x00\x00\x33\xe3\
\x00\x00\x01\x48\x00\x00\x00\x00\x00\x01\x00\x00\x6d\xc8\
\x00\x00\x03\x08\x00\x00\x00\x00\x00\x01\x00\x00\xba\x7e\
\x00\x00\x00\x34\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
\x00\x00\x01\x0e\x00\x00\x00\x00\x00\x01\x00\x00\x50\xec\
\x00\x00\x01\x68\x00\x00\x00\x00\x00\x01\x00\x00\x6e\xe6\
\x00\x00\x01\x32\x00\x00\x00\x00\x00\x01\x00\x00\x6c\xf3\
\x00\x00\x02\xc2\x00\x00\x00\x00\x00\x01\x00\x00\xb7\x46\
\x00\x00\x02\xac\x00\x00\x00\x00\x00\x01\x00\x00\xb5\xdf\
\x00\x00\x02\x08\x00\x00\x00\x00\x00\x01\x00\x00\x8c\xd3\
\x00\x00\x03\x20\x00\x00\x00\x00\x00\x01\x00\x00\xbd\xc5\
\x00\x00\x00\xca\x00\x00\x00\x00\x00\x01\x00\x00\x4e\x41\
"
qt_resource_struct_v2 = b"\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\
\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x24\x00\x02\x00\x00\x00\x1c\x00\x00\x00\x03\
\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x01\x8e\x00\x00\x00\x00\x00\x01\x00\x00\x6f\x6f\
\x00\x00\x01\x7f\x26\x32\x4b\x81\
\x00\x00\x00\x48\x00\x00\x00\x00\x00\x01\x00\x00\x0e\xc8\
\x00\x00\x01\x7a\x7a\xcc\x36\x6e\
\x00\x00\x02\x62\x00\x00\x00\x00\x00\x01\x00\x00\x99\x8b\
\x00\x00\x01\x7a\x7a\xcc\x36\x6e\
\x00\x00\x01\xe4\x00\x00\x00\x00\x00\x01\x00\x00\x8b\xe8\
\x00\x00\x01\x7d\xb2\xf7\x5e\xe7\
\x00\x00\x00\x98\x00\x00\x00\x00\x00\x01\x00\x00\x4a\x63\
\x00\x00\x01\x7d\xb6\xca\xd9\x30\
\x00\x00\x02\x86\x00\x00\x00\x00\x00\x01\x00\x00\xb4\x48\
\x00\x00\x01\x7d\xb3\x00\x7b\x5f\
\x00\x00\x00\xf0\x00\x00\x00\x00\x00\x01\x00\x00\x50\x39\
\x00\x00\x01\x7d\xb2\xf7\xf5\xc3\
\x00\x00\x03\x40\x00\x00\x00\x00\x00\x01\x00\x00\xc1\x16\
\x00\x00\x01\x7d\xb3\x02\x62\xed\
\x00\x00\x01\xaa\x00\x00\x00\x00\x00\x01\x00\x00\x7c\xae\
\x00\x00\x01\x7d\xb3\x01\x4d\x71\
\x00\x00\x00\xb4\x00\x00\x00\x00\x00\x01\x00\x00\x4d\x74\
\x00\x00\x01\x7d\xb2\xf2\xf3\x99\
\x00\x00\x02\x24\x00\x00\x00\x00\x00\x01\x00\x00\x8f\xe5\
\x00\x00\x01\x7d\xb3\x18\xc2\xa3\
\x00\x00\x02\xd8\x00\x00\x00\x00\x00\x01\x00\x00\xb7\xf8\
\x00\x00\x01\x7d\xb3\x01\xfe\x34\
\x00\x00\x00\x80\x00\x00\x00\x00\x00\x01\x00\x00\x3a\x24\
\x00\x00\x01\x7e\xdd\xf3\x69\xe1\
\x00\x00\x02\xee\x00\x00\x00\x00\x00\x01\x00\x00\xb9\xd3\
\x00\x00\x01\x7d\xb2\xf5\xe9\xc9\
\x00\x00\x01\xce\x00\x00\x00\x00\x00\x01\x00\x00\x7d\x36\
\x00\x00\x01\x7b\xdd\xcc\x05\xd7\
\x00\x00\x02\x40\x00\x00\x00\x00\x00\x01\x00\x00\x99\x04\
\x00\x00\x01\x7d\xb3\x01\x1f\xc7\
\x00\x00\x00\x6a\x00\x00\x00\x00\x00\x01\x00\x00\x33\xe3\
\x00\x00\x01\x7d\xb3\x18\xd0\x59\
\x00\x00\x01\x48\x00\x00\x00\x00\x00\x01\x00\x00\x6d\xc8\
\x00\x00\x01\x7d\xb3\x02\x9b\xc6\
\x00\x00\x03\x08\x00\x00\x00\x00\x00\x01\x00\x00\xba\x7e\
\x00\x00\x01\x7b\xdd\x98\xbe\xba\
\x00\x00\x00\x34\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
\x00\x00\x01\x7e\xdd\xf7\x66\xb4\
\x00\x00\x01\x0e\x00\x00\x00\x00\x00\x01\x00\x00\x50\xec\
\x00\x00\x01\x7b\x71\x75\xd1\xa2\
\x00\x00\x01\x68\x00\x00\x00\x00\x00\x01\x00\x00\x6e\xe6\
\x00\x00\x01\x7d\xb3\x01\x83\x0f\
\x00\x00\x01\x32\x00\x00\x00\x00\x00\x01\x00\x00\x6c\xf3\
\x00\x00\x01\x7d\xb2\xf2\x00\x41\
\x00\x00\x02\xc2\x00\x00\x00\x00\x00\x01\x00\x00\xb7\x46\
\x00\x00\x01\x7d\xb2\xfd\x02\xf6\
\x00\x00\x02\xac\x00\x00\x00\x00\x00\x01\x00\x00\xb5\xdf\
\x00\x00\x01\x7d\xb3\x04\x21\xa1\
\x00\x00\x02\x08\x00\x00\x00\x00\x00\x01\x00\x00\x8c\xd3\
\x00\x00\x01\x7b\xec\x12\x34\x16\
\x00\x00\x03\x20\x00\x00\x00\x00\x00\x01\x00\x00\xbd\xc5\
\x00\x00\x01\x7e\xca\x15\xa4\x64\
\x00\x00\x00\xca\x00\x00\x00\x00\x00\x01\x00\x00\x4e\x41\
\x00\x00\x01\x7d\xb3\x1b\x2a\x81\
"
qt_version = [int(v) for v in QtCore.qVersion().split(".")]
if qt_version < [5, 8, 0]:
rcc_version = 1
qt_resource_struct = qt_resource_struct_v1
else:
rcc_version = 2
qt_resource_struct = qt_resource_struct_v2
def qInitResources():
QtCore.qRegisterResourceData(
rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data
)
def qCleanupResources():
QtCore.qUnregisterResourceData(
rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data
)
qInitResources()
================================================
FILE: bdsim/bdedit/Icons.qrc
================================================
Icons/bdsim_icon.pngIcons/bdsim_icon2.pngIcons/bdsim_logo2.pngIcons/run.pngIcons/abort.pngIcons/simTime.pngIcons/error.pngIcons/success.pngIcons/main.pngIcons/overlap.svgIcons/bold.pngIcons/italic.pngIcons/underline.pngIcons/left_align.pngIcons/center_align.pngIcons/right_align.pngIcons/color_picker.pngIcons/clear_format.pngIcons/new_file.pngIcons/open_folder.pngIcons/save.pngIcons/save_as.pngIcons/export_as.pngIcons/quit.pngIcons/undo.pngIcons/redo.pngIcons/remove.pngIcons/help.png
================================================
FILE: bdsim/bdedit/LICENSE
================================================
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
{one line to give the program's name and a brief idea of what it does.}
Copyright (C) {year} {name of author}
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
{project} Copyright (C) {year} {fullname}
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
.
================================================
FILE: bdsim/bdedit/README.md
================================================

`bdedit` is a multi-platform PyQt5-based graphical tool to create, edit, render and execute block diagram models.
Key features include:
* allows graphical creation of block diagrams
* the diagram is stored in a human readable/editable JSON file with extension `.bd`
* creates good-quality graphics for inclusion in publications
* can launch `bdsim` to import and execute the model
* automatically discovers all bsdim and toolbbox blocks and adds them to the block library menu
* icons can be easily created using any image creation tool or a LaTeX expression
**Note that `PyQt5` is licenced under GPL3.**
# Getting started
From the examples folder
```
% bdedit eg1.bd
```
will create a display like that shown above.
To run an existing `.bd` file
```
% bdrun eg1.bd
```
which will:
* parse the JSON file
* instantiate all blocks and wires
* compile and run the diagram
It takes standard options like
```
% bdrun +g -a eg1.bd
```
to enable graphics but disable animation.
Pushing the run button, top left (triangle in circle) will save the file then spawn `bdrun` as a subprocess.
## Adding a block
Click a block from the library panel on the left-hand side. Each category is initially closed,
click it, to open it and reveal the blocks within.
All blocks, when added are instantiated in the middle of the canvas.
The key elements of a block are:
* input ports, small blue boxes
* output ports, small red triangles or arrow heads
* icon, which occupies the middle of the box (a 250x250 PNG image)
* block label, beneath the block, must be unique in the diagram
* block class, this appears when you hover the cursor over a block
* port labels, small text inside the box, against input and/or output ports.
Most ports don't have port labels.
* parameters, these are set by right clicking the block, see [details here](block-parameters).
Blocks can be flipped by typing "f" while the block is selected.
## Wiring blocks together
* Click one port then click another port, or
* Click and drag from one port to another.
An output port can connect to an arbitrary number of input ports.
## Selecting and moving elements

All selected elements, wires or blocks have an orange highlight when selected.
You can drag a region to select all blocks and wires within.
Selected items can be moved: click and drag them. Blocks cannot be resized.
Selected wires can be adjusted:
* horizontal segments can be dragged up and down,
* vertical segments can be dragged left or right.
## Connectors

The wire dragging is a little limited, and sometimes it is hard to get the layout you want. In this
case try adding a "Connector" from the "Canvas Items" category. Run a wire to the input of the connector
and one or more wires from the output of the connector. You can drag the connector by dragging it, click
close to, but not on, the connector to highlight it. A wire can have an arbitrary number of connectors in it.
## Block parameters

Right clicking a block opens a panel on the right. The parameters are initialized to values taken
from the docstring for the block.
Make changes and then click "Update parameters". This will check validity of the types and values.
Click "View documentation" will open a browser window at the GitHub documentation page for the block
class.
Block parameters can be:
* constants
* a native Python expression, prefix it with an equal sign, for example
`=[x**2 for x in range(10)]`.
* an expression which relies on global variables or other run-time context, add a Main block
to the diagram. It contain the name of a Python script (by definition, for a block diagram `model` it would be `model-main.py` which will be spawned when you hit
the Run button. This can create the runtime environment, load the `.bd` file,
for example:
```
from bdsim import bdload, BDSim
sim = BDSim() #debug='i')
bd = sim.blockdiagram()
lmbda = 0.08
bd = bdload(bd, "IBVS.bd", globals=globals())
bd.compile()
bd.report()
out = sim.run(bd, 100)
print(out)
```*

# Grouping boxes

These are transparent colored boxes that are drawn below all other graphical
items. They can be used to add structure to the diagrams.
# Free text
Click `Canvas Items/Text Item` to drop a default string `Text` onto the canvas.
Select the text to edit it. Formatting options are in the toolbar. Multiline
text with left/right/centred alignment is supported.
# Further details
More detail about how the tool works and key datastructures are in the [technical report](TechReport.md). This is a little dated now, and the visual appearance
of the GUI has evolved.
================================================
FILE: bdsim/bdedit/TechReport.md
================================================
bdedit was developed by a QUT computer science student project team. The following is the final report of that student project. Significant
subsequent work has been on this tool since the project completed.
# BdEdit Technical Report
Contact Details
Developers
Samara - Email: samara.barwick@connect.qut.edu.au
Rory - Email: rory.higgins@connect.qut.edu.au
John - Email: john.wishart@connect.qut.edu.au
Daniel - Email: daniel.petkov@connect.qut.edu.au
Supervisor
Professor Peter Corke - GitHub: https://github.com/petercorke
# Table of Contents
1. [Context](#h1)
2. [Feature Exploration of Bdedit](#h2)
[Interface](#h2-sh1)
[Adding Blocks](#h2-sh2)
[Sockets](#h2-sh3)
[Socket Flipping](#h2-sh4)
[Further Block Manipulation](#h2-sh5)
[Wires](#h2-sh6)
[Connector Block](#h2-sh7)
[Intersection Management](#h2-sh8)
[Editing Block Parameters](#h2-sh9)
[Screenshot](#h2-sh10)
[Grid Mode](#h2-sh11)
[Grid Snapping](#h2-sh12)
[Saving and Loading](#h2-sh13)
3. [Class Architecture (High Level)](#h3)
[1) The Interface Class](#h3-sh1)
[2) The Scene Class](#h3-sh2)
[3) The GraphicsView Class](#h3-sh3)
[4) The Block Class](#h3-sh4)
[5) The Socket Class](#h3-sh5)
[6) The Wire Class](#h3-sh6)
4. [Making changes to code](#h4)
[Adding more blocks types to application](#h4-sh1)
[Block parameters explained](#h4-sh1)
[JSON file structure outline](#h4-sh2)
[How icons were created](#h4-sh3)
[Procedure for updating changes to existing icons, or adding new ones](#h4-sh4)
5. [Appendices](#h5)
[APPENDIX A – High Level Class Architecture Diagram](#h5-sh1)
[APPENDIX B – Stepped Wire Drawing Logic](#h5-sh2)
[Embedded Links](#h5-sh3)
# 1. Context
In engineering, complex systems are often represented with block diagrams (refer to Figure 1.1), where blocks represent functions with inputs and outputs, and wires represent the flow of values between the ports of these functions.
These block diagrams can be modelled and simulated as code through the bdsim [[1]](#h5-sh3-item1) Python package developed by Professor Peter Corke, where the blocks and wires are represented in terms of Python class and method calls.
To aid with the conceptualization of the developed block diagram model and its modelling process, the bdedit package was developed as an addition to bdsim, allowing for block diagrams to be created graphically with items that visually represent the blocks, in/out ports and the wires (refer to Figure 1.2). Bdedit supports the saving and loading of these diagrams to and from a JSON file, which stores all the necessary data for the diagram to later be simulated through bdsim.
# 2. Feature Exploration of Bdedit
## Interface
Installing the bdsim package and its necessary files, then running the bdedit.py [[2]](#h5-sh3-item2) file, launches a new window containing a graphical user interface (refer to Figure 2.1). This interface contains three areas of focus, the canvas (grey grid space), the library browser panel, and the toolbar.
## Adding Blocks
Through this interface, the user can create a block diagram by choosing from a list of available blocks found within the Library Browser panel. These will call on the classes related to those blocks, to create a block which both stores its values internally within the program and graphically represents that block within the diagram. The graphical information of these blocks and wires is then stored within the canvas area (refer to Figure 2.2).
## Sockets
These blocks have sockets, representing its inputs and outputs. These are determined through the block type, with some blocks only having input sockets (sink blocks or INPORT blocks), some only having output sockets (source blocks or OUTPORT blocks), and others having both input and output sockets (function, transfer, discrete or SUBSYSTEM blocks) (refer to Figure 2.3).
These sockets can be used to connect the output of one block to one or more other blocks, creating a flow of data. The following logic is applied to these sockets based on their types:
* Sockets cannot connect to the same socket type (Output cannot connect to Output, Input cannot connect to Input)
* Input sockets can only have one wire connecting into them (any further wires that are connected will be disconnected until the existing wire is removed)
* Output sockets can have any number of wires connected to them
## Socket Flipping
Blocks can also be flipped, reversing the sides on which the input and output sockets are located. This can be achieved through pressing the 'F' key (F for flip). These are only graphically updated and do not impact the flow of logic to those sockets (refer to Figure 2.4).
## Further Block Manipulation
Blocks can also be selected/ moved and deleted as desired. All items are restriced to being moved around within the borders of the canvas. Wires can also be selected and deleted, but not moved. Sockets cannot be selected, moved or deleted through mouse interaction. Selecting, or rather clicking on, a socket creates a draggable wire. As the block is moved, so too are its sockets. The only instance where sockets move relative to the block, is when the number of input or output sockets changes (which is controlled through the [parameter window](#h2-sh9)).
The selection of an item is indicated by a colour change. When a block, connector block or wire is selected, its outline changes from a thin black line, to a thicker bright orange outline (refer to Figure 2.5).
As mentioned above, blocks and wires can be deleted when desired. This is done through first selecting the item, then pressing either the 'Backspace' or the 'Del' keys on the keyboard. If a wire is deleted, only the wire will be removed. If a block is deleted, any wires that were connected to it will also be deleted with the block.
## Wires
Blocks can be connected to one another by either clicking on a socket of one block, then clicking on a socket of another block, or by click-and-dragging from one socket and releasing over the socket of another block (refer to Figure 2.6). When a wire is connected between two points, wire logic will be applied to it, in order to determine the path it should take to connect those two blocks. Moving the block around once the wire is connected, will update the position of the wire end points, and as such, will cycle through the wire logic to determine what path the wire should follow (refer to [APPENDIX B](#h5-sh2) for examples and a walkthrough of this logic).
## Connector Block
The sections of the wires cannot be pulled out and positioned to the user's liking, as their path is solely dependent on the position of the two points it connects. Hence, to assist with routing the wires when the diagrams become more complex with wires travelling in multiple directions, a connector block can be used as an intermediary point through which the wire must travel. These provide the user with more control over how the wire travels between any two points, by creating more points in between the start and end point, which the wire must first connect. The comparison between using a connector block and not, can be seen in Figure 2.7. The connect block appears as a single Input and Output socket joined together on one edge; and similarly to other blocks, it is also flip-able.
## Intersection Management
As seen in the bottom part of Figure 2.7, wires can overlap at times, and although they are fairly easy to follow in this figure, it can become difficult to follow the flow of logic when the diagram becomes more complex. To address this problem area, parts of wires that cross over each other can be separated to indicate they do not cross, but instead pass over each other (refer to Figure 2.8). This feature might not always be desired, so it has been disabled by default, however can be toggled on or off by the user through pressing the 'I' key (I for intersection). The wire logic at these intersection points, keeps all vertical segments of wires solid, and erases parts of any horizontal segments that they pass through.
## Editing Block Parameters
Integral to the creation and simulation of block diagrams, is the ability to edit the parameter values related to each block, as this dictates what output value a block produces and how blocks process any inputs that feed into it to produce an output. If supported for the given block, it is also possible to edit the number of input or output sockets a block has. All blocks (aside from connector blocks) can be named as desired by the user. As blocks are spawned they are given a default name which is auto incremented depending on the block type.
These user-editable block parameters are editable through a Parameter Window panel that appears on the right hand side of the screen when triggered to do so (refer to Figure 2.9). It can be toggled to open by first selecting a block, then right clicking the mouse; subsequently, it can be closed at any moment by either right clicking again or left clicking anywhere in the screen. Closing the Parameter Window will retain any values that have been edited, but will only update the block parameters once the 'Updated Parameters' button has been clicked.
When parameters are edited and the user selects update, all editable values within the Parameter Window will be checked to ensure they adhere to the conditions placed on them. If the block title is changed, this will be checked against other existing block titles, to ensure the name of the current block would not be a duplicate. If the block parameters are changed, they will be compared against their required types to ensure they match (e.g. float, int, bool, list, str), and if any further restrictions are placed on these parameters (e.g. matching to certain strings, or being within a certain range), they will be checked against those too. This information is defined internally within the block class, and applied to the block when it is created.
User feedback pop-up windows are also connected to this Parameter Window. If the user provides values that are incorrect - be they a duplicate block title, incorrect types or not adhering to further restrictions – the block parameters will not be updated, and an error message will be displayed notifying the user with useful information for where the issue occurred. If all values are correctly inputted, a success message will be displayed in the same area (refer to Figure 2.10).
## Screenshot
Upon creating a block diagram, the user can take a screenshot of all items within the canvas by simply pressing the 'Screenshot' button located within the toolbar. This will save a 4k resolution image of the entire canvas and everything in it. This resolution is chosen due to canvas size potentially being 5x the desktop screen size due to the zooming feature. Due to limited time to further develop this feature, at present time, this image will be saved with the '.png' file extension, under the name 'Scene Picture' in the same folder the interface is run from. **If taking multiple screenshots this way, be aware that this will override any previous screenshot you may have taken.**
## Grid Mode
To improve the viewing quality of the screenshots taken, and reduce the amount of visual noise/messiness created by having the background be a grid, an option is available from the toolbar to disable the background by navigating to the 'Grid Mode" button in the toolbar, and selecting 'Off' from the drop down menu. Alternatively, the grid can be displayed in two other modes, Light (the default mode) and Dark (refer to Figure 2.11).
## Grid Snapping
To improve the usability of the interface and the user experience when moving/aligning blocks within the canvas, a grid snapping feature has been implemented, where movement of the mouse will be restricted to moving the block in increments of 20 pixels (the width of the smaller grid squares). Additionally, all sockets are indexed in increments of the same value (20 pixels) in order to line up with these smaller grid lines. As such, since wires are automatically drawn between the socket positions, it is much easier to move blocks around in order to make them straight.
## Saving and Loading
An integral component to this bdedit tool is the support for saving the current progress made on a block diagram, and the support to load a previously worked on block diagram (provided it is in a compatible format). Block diagrams are saved as JSON files, containing information about the canvas size, all the blocks (its name, on-screen position, parameters, and sockets), and finally all the wires and the sockets they connect to. This information is stored as a dictionary within the JSON file, which is parse-able as key-value pairs, where the key represents the name of the variable or parameter related to the scene, block, socket or wire, and the value representing the value that variable holds.
A file can be saved or loaded from through the associated 'Save' or 'Save As' and 'Load' buttons within the toolbar. Upon clicking on one of these buttons, the a file browser window will pop up (allowing the user to browse their devices' file structure), prompting the user to either select a file to load or to choose the location they wish for their file to be saved (and the name of the file if it's the first time saving or if saving the diagram as a new file).
Due to a limitation of time to further develop this feature, whether this file is in a compatible format is not checked before it is attempted to be parsed, so any errors that may occur due to an incorrect file being loaded, will result in the crashing of the bdedit tool.
# 3. Class Architecture (High Level)
The architecture of BDEdit can be summarize through the connectivity between 6 main classes as seen in Figure 3.1. Other classes are also essential, however it is through the interactions between these 6 main classes that the application is able to run. For a full size image of this architecture refer to [APPENDIX A](#h5-sh1). These classes break down into the following:
### 1) **The Interface Class** –
This class is responsible for the dimensions of the BDEdit window that appears when the application is run, as well as managing the layout of where all the interact-able areas of the application are, these being:
* The toolbar;
* The left side panel (otherwise named the Library Browser);
* The right side panel (otherwise named the Parameter Window); and
* The canvas or work-area (which is an instance of the GraphicsScene class, who itself is a child class of the Scene class, AND is connected to a GraphicsView class instance).
It is namely the creation of the GraphicsScene class that allows for the graphical representation of Blocks, Sockets and Wires, the culmination of which allows for the making of a Block Diagram.
### 2) **The Scene Class** –
This class is responsible for three things.
* Storing all instances of any Wires and Blocks (and their Sockets) that are created, i.e. their structures, internal variables, lists, properties, etc. It also manages the adding/removing of these instances.
* Creating and storing a GraphicsScene class instance, in which all the GraphicsBlock, GraphicsSocket, and GraphicsWire class instances are added to graphically represent their class respectively. This allows for the all the relevant internal information of the Block, Socket and Wire classes to be represented graphically!
* Managing the intersection points at which any two (or more) wires overlap.
### 3) **The GraphicsView Class** –
This class instance is connected to the GraphicsScene through the Interface class, and is responsible for monitoring the GraphicsScene and implementing logic to any user interactions within it. These interactions being: key presses, mouse press/release, mouse movement, scroll click and scroll movement events. These detected events are caught in real time, allowing for logic within the GraphicsScene to also be updated in real time. Some examples of this includes:
* the creation of a Wire (and subsequent GraphicsWire) when a GraphicsSocket is clicked on;
* the real-time updates to how the GraphicsWire is drawn while being pulled from one GraphicsSocket to another;
* the real-time updates to how the GraphicsBlock is drawn when the number of sockets on it changes, or when it is selected;
* the zooming in and out of, and panning of the canvas (GraphicsScene).
### 4) **The Block Class** –
An instance of this class is created when a respective button is clicked from the Library Browser side panel in the Interface. This class is responsible for holding all Block related variables, these beings things like its name, position within the canvas, block type, icon, dimensions, user-editable parameters and a list of input and output Socket instances that are related to this Block. Additionally, this class relates and instance of the **ParamWindow** class and GraphicsBlock class to this Block.
The **ParamWindow** is a class which creates a Parameter Window in which are displayed this Blocks' type, title and user-editable parameters, and through which a user can edit the parameters of a given block. When this Parameter Window is opened, it appears in a right side panel within the Interface.
Similar to how the GraphicsScene represents a Scene class instance, the GraphicsBlock graphically represents a given Block, and sends that graphical information to the GraphicsScene to display.
### 5) **The Socket Class** –
An instance of this class is created and connected to a Block, whenever one is made. This class is responsible for holding all Socket related variables, like its index (from the top of the Block, these are auto incremented as more Socket are made for a Block), the position to be drawn at (Left or Right of the Block), the type of Socket being drawn (Input or Output) and finally a list of all Wires that are connected to this Socket.
Additionally, some special blocks (PROD and SUM Blocks) have math operators (+,-,×,÷) drawn alongside their input Sockets depending on what string for one of those block's parameters. For example, that parameter may be the string "`*/*`" in the PROD block, and this will draw a '×', '÷', '×' alongside the first, second, third input sockets respectively.
The Socket class also holds an instance of GraphicsSocket which graphically represents the Socket, and is sent to the GraphicsScene to be drawn.
### 6) **The Wire Class** –
As was mentioned in the GraphicsView, when it has detected that a GraphicsSocket has been clicked, this will create a Wire instance from that Socket, and a subsequent GraphicsWire from the GraphicsSocket to the mouse cursor, until either the GraphicsWire is clicked off of into an empty space within the GraphicsScene, or the wire is clicked off of onto another GraphicsSocket. If these socket types are different (i.e. both aren't input or output sockets), then the wire is connected and will remain so, even as the GraphicsBlock is moved around. The Wire class is responsible for holding all Wire related variables, these being what Sockets this Wire connects (start/end sockets) and the type of wire being drawn (Direct, Bezier or Step). The wire type dictates the style with which the wire is drawn. Direct draws the wire as a straight line between two points. Bezier draws the wire as a cubic between two points (think sinusoidal wave). Step draws a wire with 90 degree bends at each point the wire must turn to reach the end socket.
Although other methods and classes are involved in the process of making this application meet further functional requirements, these 6 classes are what tie everything together.
# 4. Making changes to code
## Adding more blocks types to application
If the new block type falls under one of the following, already existing categories: Source, Sink, Function, Transfer, Discrete, INPORT, OUTPORT or SUBSYSTEM block (these last three are located within the hierarchy file), then that block simply needs to be added as a class of one of the Python files relating to those block types. These Python files are located in the "**_`bdsim/bdsim/bdedit/Block_Classes`_**" folder (refer to Figure 4.1), with the names seen in Figure 4.2.
Within each of those files, the first few lines import the block type they inherit, for example, the "**_`block_function_blocks.py`_**" file imports the FunctionBlock class from the "**_`block.py`_**" file (located in "**_`bdsim/bdsim/bdedit`_** ") inheriting its properties. An example of one of the blocks within these files (without the block comments) is given below:
``` python
class Function(FunctionBlock):
def __init__(self,
scene,
window,
func="Provide Function",
nin=1,
nout=1,
dictionary=False,
args=(),
kwargs={},
name="Function Block",
pos=(0, 0)):
super().__init__(scene, window, name, pos)
self.setDefaultTitle(name)
self.block_type = blockname(self.__class__)
self.parameters = [
["func", str, func, []],
["nin", int, nin, [["range", [0, 1000]]]],
["nout", int, nout, [["range", [0, 1000]]]],
["dict", bool, dictionary, []],
["args", tuple, args, []],
["kwargs", dict, kwargs, []]
]
self.inputsNum = nin
self.outputsNum = nout
self.icon = ":/Icons_Reference/Icons/function.png"
self.width = 100
self.height = 100
self._createBlock(self.inputsNum, self.outputsNum)
```
This block class type is constructed based on the definition of the corresponding bdsim block [[3]](#h5-sh3-item3). When adding in a new block, the following template can be copied and adjusted as needed.
``` python
# The name of this new block class should be unique, and
# it should inherit whichever block type it belongs to.
class My_New_Block(Class_the_new_block_relates_to):
# Next, the scene and window are required to be passed to the
# creation of this block (and will be done so automatically from
# the interface). The following input parameters are the parameters
# of the block and their respective default values.
# Finally comes the block's default name (if the user doesn't provide
# one), and the position is set to always spawn the block at the
# centre of the work area.
def __init__(self,
scene,
window,
param1="parm1_default_value",
param2="parm2_default_value",
param3="parm3_default_value",
name="My_New_Block Block",
pos=(0, 0)):
super().__init__(scene, window, name, pos)
# The chosen default name for this block is passed to
# the setDefaultTitle function which will ensure no duplicate
# names names of this block exist.
self.setDefaultTitle(name)
# The block type is set as the given name of this block class
self.block_type = blockname(self.__class__)
# The parameters of the block are wrapped into a list, where each
# parameter sits inside its own list and defines
# the name, type, default value, and any further restrictions
# for each respective parameter.
self.parameters = [
["parameter 1", str, param1, []],
["parameter 2", str, param2, []],
["parameter 3", str, param3, []]
]
# The icon file path is matched to whatever name the icon for
# this block was named within the Icons folder (this procedure
# will require the icons resource file to be updated for a new
# image to be findable within this folder).
self.icon = ":/Icons_Reference/Icons/my_new_block.png"
# The height and width are set for this block
self.width = 100
self.height = 100
# Finally the block is created, with the number of input and
# output sockets that have been assigned to this block. (This
# will be inherited from the class this block inherits).
self._createBlock(self.inputsNum, self.outputsNum)
```
This simply needs to be added to the end of the appropriate file (as chosen from Figure 4.2), and this will make the block automatically appear within the interface.
## Block parameters explained
Each block has its own unique parameters, with their own unique names, types, default values and further restrictions (like being restricted to a certain range of allowable numbers). All of a given blocks' parameters are stored within the self.parameters variable list, with each individual parameter being stored as a list within the self.parameters list. Each individual parameter is defined with the following format:
* **_parameter = ["name", type, value, [restrictions]]_**
_e.g. parameter = [["Gain", float, gain, []], ["Premul", bool, premul, []]]_
The items which make up this list of the parameter, are as follows:
* **_name_**: _this is the name of the parameter as a string_
* **_type_**: _this is the type this parameter must be (e.g. int, str, float)_
* **_value_**: _this is the default value the parameter will be set to, if no other value is given. It must also adhere to the required type of the parameter._
* **_restrictions_**: _this is a list (can be list of lists) containing further restrictions applied to the parameter._
As multiple restrictions can be applied to a single parameter, each individual restriction is enclosed as a list. If no restrictions are applied to a parameter, the main restrictions list (inside the parameter list) will simply be an empty list, as seen in the example. These restrictions follow the following structure:
* **_restriction = ["restriction name", [condition(s)]]_**
What these two items within the restriction list represent is explained below:
* **_restriction name_** : _can be only one of the following "keywords", "range", "type" or "signs"._
* **_condition(s)_**: _differ based on the restriction name used, and will be of the following format:_
Currently, only the four restriction types mentioned below are recognized. These must be entered as a string in the first item within the restriction list ("restriction name"), to indicate what kind of restriction is being applied to this parameter. Following this first value, a list containing one or more conditions placed on the restriction is defined. These depend on the type of restriction chosen. Examples of these restrictions are given below:
```python
[["keywords", ["sine", "square", "triangle"]]]
```
* This restriction compares the parameter value against the strings defined within the conditions list. This restriction should only be used on parameters whose required type is 'str' (string). If the parameter value doesn't match any of these strings, this will throw an error notifying the user that their input must match one of those strings.
* Here the conditions list is just a list of all the variations the parameter value can be.
```python
[["range", [-math.inf, math.inf]]]
```
* This restriction compares the parameter value against being within a range of given numbers, defined by a min and a max. This restriction should only be used on parameters whose required type is either 'float' or 'int'. If the parameter value is outside the allowable range, this will throw an error notifying the user that their input must be within the given range.
* Here the conditions list simply is made up of a minimum and maximum value.
```python
[["type", [type(None), int, float]]]
```
* This restriction compares the type of the parameter value against one of the additional allowable types for this parameter. If for instance, a parameter can either an integer or a float when defined, or a None type otherwise, this means the parameter can be one of 3 different types, and this restriction allows the parameter to pass as long as its type matches one of the defined types. In order to allow other types, the type set for this parameter (as the second item in the parameters list), must also be included in this conditions list, usually as the last item (for consistency sake). Note, when allowing a parameter to have None as a value, since None isn't a type, but rather a NoneType, type(None) is used to extract the type of None. If the type of the parameter value doesn't match one of the other allowable types, this will notify the user of the error, and the allowable types.
* Here the conditions list is just a list of all the acceptable types for that parameter, with the required type of the parameter also being in that list (usually as the last value in the list; which is float in this case).
```python
[["signs", ["*", "/"]]] or[["signs", ["+", "-"]]]
```
* This restriction compares the parameter value against the various characters that have been defined in the conditions list. This restriction should only be used for SUM and PROD type blocks, as these have input sockets which are labelled according to the signs defined in this condition list. The parameter value for these blocks (SUM and PROD) is entered as a string of characters, and each character for the respective block is checked against the ones that are allowed from the conditions list. If that string is made up of any number of characters that don't match the ones that are allowed, an error will be thrown, notifying the user of the allowable inputs.
* Here the conditions list is just a list of all the allowable characters for that parameter
## JSON file structure outline
The JSON file structure contains all the necessary information of the reconstruction of blocks, sockets and wires that exist within a block diagram, and represents them as dictionaries, of key-value pairs which represent the name and value of parameters relevant to those items. All of these items (blocks, sockets, and wires) are contained within a Scene as explained in [Section 3](#Class_Architecture(High), hence they follow the following hierarchy:
* A Scene is represented as dictionary with:
* Dimensions: these are two parameters of the width and height of the scene.
* Blocks: this is a list of all the blocks within the diagram, with each block as a dictionary.
* Sockets: each block has its own unique sockets, so these are stored as part of the block they belong to, also in a list, with each socket as a dictionary.
* Wires: this is a dictionary list of all the wires within the diagram.
The following block diagram was made to aid with understanding this structure.
There are 3 blocks, created in the order:
1. Function Block – has 1 input socket, 1 output socket
2. Scope Block – has 2 input sockets, no output sockets
3. Constant Block – has no input sockets, 1 output socket
There are also 2 wires, created in the order:
1. Function block -> 1st input socket of Scope Block
2. Constant block -> 2nd input socket of Scope Block
Below, is the resulting JSON file that was generated.
The important points to take away from this JSON structure, is that each block, socket and wire has unique ID's. Although the ID's of the blocks are less useful (can be helpful for differentiating between different blocks of the same time, although their name should be sufficient), the ID's of the sockets are very important. By definition each wire has a start socket and end socket that it is drawn between, and these are referred to by their unique ID. These unique ID's of the sockets, can then be traced back to the block they belong to, hence providing the crucial information of which block connects to which.
As an example, in this block diagram that was made, wire #1 connects the **Function block** from its **output**, to the **1st input** of the **Scope block**. In the wire, these start/end sockets are stored as "start_socket": 2427529113712 and "end_socket": 2427529150816,and if we check the socket id's of the **output socket** of the **Function block**, it is stored as "id": 2427529113712, which we expect to match our "start_socket"(which it does), and doing the same for the **1st input socket** of the **Scope block**, it is stored as "id": 2427529150816, which also matches our ID of the "end_socket".
## How icons were created
Icons for bdedit were creating using the free image editing application, paint.net [[4]](#h5-sh3-item4). Paint.net is only compatible with windows operating systems, however there are other options available for image editing applications on Mac or Linux systems.
The sought after properties of image editing tools for creating/editing these icons were: for the ability to create layered images, moving layer position in the layer stack, hiding/showing the layer, selecting parts of images and separating them from the background (leaving only the outline/shape), and more importantly, support for transparent backgrounds.
Paint.net provides support for all these requirements, but other software options may also, so feel free to use whichever software, as long as the final images are saved in '.png' format and have transparent backgrounds. Paint.net also allows for files to be saved in their separate state as layers with the '.pdn' file type, however only Paint.net can open these files. For Windows users this shouldn't be a problem, but for users on other systems, the layers that make up each icon have been saved separately, which will allow them to be added as layers to which ever software is used on those operating systems.
Icons in general, were developed on a 250x250 pixel, transparent background. These dimensions were based off the blocks being 100x100 pixels when drawn within the interface, and the icon being drawn within these blocks having a space of 50x50 pixels to occupy. Having a 250x250 pixel raw icon image allows it to be scaled down to a 50x50 image through PyQt5's scaling tool, which retains the quality of the image better, resulting in it being less pixelated when zoomed in.
The items (text, dividing lines, function lines, etc.) within the icons were positioned with the help of a grid (named "layout_grid.png"), located within the Icons folder in which all the icons are stored. There wasn't a specific method for positioning the items within these icons, but depending on what the icon was (text, shape, axis with function) the lines of the grid were used to symmetrically place items and position them to allow for satisfactory visibility. These icons were developed in monochrome mode (black and white). The following values were used for lines and text:
* linewidth:
* 6 for axis lines and outline of gain,
* 8 for bolded thin lines (particularly as dividing lines),
* 15 for outline of stop icon
* 19 for function lines (clip, constant, piecewise, step, waveform)
* text font: Calibri
* text size: various amongst the text used, but will be one of the following:
* 36, 48, 59, 72, 84, 108, 144
* text bolding: True for all text, apart from the stop icon
## Procedure for updating changes to existing icons, or adding new ones
As Python creates some difficulties in accessing absolute or relative file paths, and making this consistent across all users, an alternative available from PyQt5 was used, which is a QReferenceFile.
Similar to zipping files into a folder, this reference file packages image files into a Python importable file, which after importing, can then be accessed locally within the same directory. Hence all icons which were used, were placed into the Icons folder, located at "**_`bdsim/bdsim/bdedit/Icons`_**" folder (see Figure 4.1), and a reference file named " Icons.qrc " was made (following the structure below) in the bdedit package, located at "**_`bdsim/bdsim/bdedit`_**" folder (see Figure 4.1).
In order to make the "**_`.qrc`_**" (resource) file importable and usable in the Python scripts, it must be converted to a "**_`.py`_**" (Python) file (in our case named "**_`Icons.py`_**"). The steps for this procedure will be outlined below.
The following steps should be followed for updating an icon that already exists
1. The new icon (under the same name as the existing icon it's replacing) should be added as a "**_`.png`_**" to the "**_`bdsim/bdsim/bdedit/Icons`_**" folder, replacing the old version of the icon.
2. The "**_Icons.qrc_**" file located at "**_`bdsim/bdsim/bdedit`_**" should be converted to "**_`Icons.py`_**" with the following steps:
1. Via the terminal, navigate to the bdedit directory
2. Via the terminal, type "**_`pyrcc5 Icons.qrc -o Icons.py`_**" to convert and write the contents of the resource file (named "**_`Icons.qrc`_**") to a Python file (named "**_`Icons.py`_**"). The name of the resource file should match that of what was given to the resource file, and the name of the Python file will be what is called when importing into other Python files (as "**_`from bdsim.bdedit.Icons import *`_**"). DO NOT make any changes to this generated Python file, as this could result in unforeseen errors.
3. Assuming the icon that is being replaced, was previously set up and being used, re-running the program after updating the "**_`Icons.py`_**" file will update the changes made to this icon.
The following steps should be followed for adding in a new icon, that doesn't exist anywhere in the code:
1. The new icon (with a unique name) should be added as a "**_`.png`_**" to the "**_`bdsim/bdsim/bdedit/Icons`_**" folder.
2. The structure of the "**_`Icons.qrc`_**" resource file located at "**_`bdsim/bdsim/bdedit`_**" should be edited to include the file path to this newly added icon. The following steps should be taken:
1. Open the resource file with any text viewer (should see a file similar to Figure 4.3)
2. Add the file path to the new icon as "**_`Icons/filename.png`_**" enclosed in the <file> and </file> tags, indicating that this icon is located within the Icons folder. Note the qresource prefix name; this will be used for picking out specific icons from this file.
3. Save the resource file and proceed to Step 3.
3. The "**_`Icons.qrc`_**" resource file located at "**_`bdsim/bdsim/bdedit`_**" should be converted to "**_`Icons.py`_**" with the following steps:
1. Via the terminal, navigate to the bdedit directory
2. Via the terminal, type "**_`pyrcc5 Icons.qrc -o Icons.py`_**" to convert and write the contents of the resource file (named "**_`Icons.qrc`_**") to a Python file (named "**_`Icons.py`_**"). The name of the resource file should match that of what was given to the resource file, and the name of the Python file will be what is called when importing into other Python files (as "**_`import Icons`_**"). DO NOT make any changes to this generated Python file, as this could result in unforeseen errors.
4. Next, you should open the file where you planned to use the icon (this should be one of the files in either the "**_`bdsim/bdsim/bdedit/Block_Classes`_**" folder or in the "**_`bdsim/bdsim/bdedit`_**" package).
1. If in any file within the Block_Classes folder, continue to Step 5.
2. If in any other within the bdedit package: 1. Import the "**_`Icons.py`_**" file from the bdedit package as: "**_`from bdsim.bdedit.Icons import *`_**".
5. Still in the same file as Step 4, continue to the code where you want the Icon file path to be defined and insert the following string: "**_`:/Icons_Reference/Icons/filename.png`_**". The "**_`:/`_**" notation is important for navigating the "**_`Icons.py`_**" file. Also, remember from the note in Step 2, the qreference name is used here as "**_`Icons_Reference`_**" to refer to the "**_`Icons.py`_**" file. The "**_`/Icons/filename.png`_**" points to the path defined in the "**_`Icons.qrc`_**" file. Replace "**_`filename`_**" with whatever name you saved the icon under.
6. This should complete the process for adding in a new icon.
# 5. Appendices
## APPENDIX A – High Level Class Architecture Diagram
## APPENDIX B – Stepped Wire Drawing Logic
Drawing the step wire falls into three steps of logic.
The first step: when a wire is being pulled from one socket to another, and has not yet been connected.
In this step, the wire is simply drawn as a straight light from the starting socket to the mouse cursor, up until the point the wire is connected to another socket. This is when the wire drawing logic falls into the following two steps of logic.
The second step: Wire routing logic between two blocks where the input and output sockets are on same sides
The third step: Wire routing logic between two blocks where the input and output sockets are on opposite sides
## Embedded Links
1 - https://github.com/petercorke/bdsim
2 - File located at path: https://github.com/petercorke/bdsim/blob/bdedit/bdsim/bin/bdedit.py
3 - https://petercorke.github.io/bdsim/bdsim.blocks.html?highlight=Function#bdsim.blocks.functions.Function
4 - Free paint.net download link - https://www.getpaint.net/download.html#download
================================================
FILE: bdsim/bdedit/__init__.py
================================================
# print("bdedit package __init__ start")
from .block import *
from .block_wire import *
from .block_socket import *
from .block_graphics_block import *
from .block_graphics_wire import *
from .block_graphics_socket import *
# from .block_importer import *
from .block_param_window import *
from .Icons import *
from .interface import *
from .interface_scene import *
from .interface_graphics_scene import *
from .interface_graphics_view import *
from .interface_serialize import *
from .bdedit import main
# print("bdedit package __init__ end")
================================================
FILE: bdsim/bdedit/bdedit.py
================================================
#!/usr/bin/env python3
# Library imports
import os
import sys
import ctypes
import argparse
from pathlib import Path
from sys import platform
from pathlib import Path
from colored import fg, attr
# PyQt5 imports
from PyQt5.QtWidgets import *
from PyQt5.QtCore import QTimer
from PyQt5.QtGui import QIcon
# BdEdit imports
from bdsim.bdedit.interface_manager import InterfaceWindow
# Executable code to launch the BdEdit application window
def main():
print(fg("red"))
print("bdedit is beta code and prone to random crashing, save your work often")
print(attr(0))
# handle command line options, bdedit -h for details
parser = argparse.ArgumentParser(description="Interactive edit for bdsim models")
parser.add_argument(
"file", type=str, nargs="?", help="Load this model into interactive session"
)
parser.add_argument(
"--print",
"-p",
nargs="?",
action="store",
const="",
default=None,
help="Save model to screenshot and exit, can optionally specify a filename, PDF extension is default",
)
parser.add_argument(
"--debug",
"-d",
action="store_const",
const=True,
default=False,
help="Enable debugging",
)
parser.add_argument(
"--pdb",
action="store_const",
const=True,
default=False,
help="Enable pdb for spawned python subprocess",
)
parser.add_argument(
"--background",
"-b",
type=str,
default="grey",
choices=["white", "grey"],
help="Set background color",
)
parser.add_argument(
"--fontsize", "-s", type=int, default="12", help="Set font size of block names"
)
parser.add_argument(
"--format",
"-f",
type=str,
nargs="?",
help="Specify screenshot extension type; PDF (default) or PNG",
)
args, unparsed_args = parser.parse_known_args()
# args holds all the command line info:
# args.file file name if given, else None
# args.debug True if -d option given
# args.print True if -p option given, load the file, save screenshot, then exit
# args.fontsize integer fontsize if given, sets default size of block names
# args.format PDF if unspecified, PDF or PNG if specified
# insert argv[0] into head of list of remaining args, and hand that to Qt
unparsed_args.insert(0, sys.argv[0])
# A QApplication instance is made, which is the window that holds everything
app = QApplication(unparsed_args)
# The resolution of the user's screen is extracted (used for determining
# the size of the application window)
screen_resolution = app.desktop().screenGeometry()
# Set the desktop toolbar icon for this application
icon = Path(__file__).parent.parent / "bdedit" / "Icons" / "bdsim_logo.png"
app.setWindowIcon(QIcon(str(icon)))
myappid = "bdsim.bdsim.bin.bdedit.application" # arbitrary string for application
try:
if platform == "win32":
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid)
elif platform == "darwin":
ctypes.cdll.kernel32.SetCurrentProcessExplicitAppUserModelID(myappid)
except Exception as e:
# Toolbar icon for application could not be set.
pass
# Finally the window is displayed by creating an instance of Interface,
# which holds all the logic for how the application should appear and which
# connects all the other Classes through the Interface.
# window = Interface(screen_resolution, args.debug)
window = InterfaceWindow(screen_resolution, args.debug)
window.args = args
# Check what command line arguments have been passed, if any
if args.file or args.print or args.debug or args.fontsize or args.format:
# Call bdedit functionality based on passed args
window.centralWidget().scene.block_name_fontsize = args.fontsize
if args.file is not None:
# Attempt to load the .bd file
if os.path.isfile(args.file):
window.loadFromFilePath(args.file)
else:
raise ValueError(f"bdfile {args.file} not found")
# fire up the GUI
window.centralWidget().scene.grScene.updateBackgroundMode(args.background, True)
if args.print is not None:
# render a screenshot to file
def screenshot(model_path, screenshot_name):
# Set the background mode to white, no grid lines
window.centralWidget().scene.grScene.updateBackgroundMode(
"white", False
)
window.centralWidget().scene.grScene.checkMode()
# Hide and then unselect all connector blocks present in the model
window.centralWidget().scene.hide_connector_blocks = True
for block in window.centralWidget().scene.blocks:
if block.block_type in ["Connector", "CONNECTOR"]:
block.grBlock.setSelected(False)
# Update the points where wires overlap within the scene to draw the wire separations
if window.centralWidget().scene.wires:
window.centralWidget().scene.wires[0].checkIntersections()
window.centralWidget().save_image(
model_path, screenshot_name
) # in interface.py
sys.exit(0)
# figure out the filename to save it as
file = Path(args.print)
if args.print == "":
# no filename given on command line
# use the model file name, drop the path, and set extension pdf if none given
# wait till python 3.9 for the next line to work
# path = Path(args.file).with_stem(filename.stem + "-screenshot").with_suffix('.pdf').name
if args.format == "png":
path = Path(args.file).with_suffix(".png")
else:
path = Path(args.file).with_suffix(".pdf")
path = path.stem + path.suffix
else:
# filename was given on command line
path = Path(args.print)
if path.suffix == "":
if args.format == "png":
path = path.with_suffix(".png")
else:
path = path.with_suffix(".pdf")
# After 100ms non-blocking delay, screenshot the model
QTimer.singleShot(100, lambda: screenshot(args.file, str(path)))
# run the GUI until it exits
sys.exit(app.exec_())
if __name__ == "__main__":
main()
================================================
FILE: bdsim/bdedit/block.py
================================================
# Library imports
import os
import json
from collections import OrderedDict
# BdEdit imports
from bdsim.bdedit.block_socket import *
from bdsim.bdedit.block_param_window import ParamWindow
from bdsim.bdedit.block_graphics_block import GraphicsBlock
# =============================================================================
#
# Defining and setting global variables
#
# =============================================================================
# Socket positioning variables (in relation to where they're drawn on the block)
LEFT = 1
TOP = 2
RIGHT = 3
BOTTOM = 4
# Socket type classification variables
INPUT = 1
OUTPUT = 2
# List of auto-imported blocks
blocklist = []
# Variable for enabling/disabling debug comments
DEBUG = False
# =============================================================================
#
# Defining the parent Block Class, which is inherited by all blocks
#
# =============================================================================
class Block(Serializable):
"""
The ``Block`` Class extends the ``Serializable`` Class from BdEdit, and
defines how a block is represented, and has all the necessary methods
for creating, manipulating and interacting with a block.
This class includes information about the blocks':
- name;
- type;
- appearance;
- on-screen positioning;
- parameters, and their values;
- number of inputs and outputs.
"""
# -----------------------------------------------------------------------------
def __init__(self, scene, window, pos=(0, 0)):
"""
This method initializes an instance of the ``Block`` Class.
It maps the following internal parameters of the block, initializing
them to their defaults values. These are overwritten when an instance of
the grandchild block is created. The parameters are defined as:
- title: the name of the ``Block``.
This defaults to the name of the name of the grandchild class, and
is incremented if an instance with the same default name already exists.
- type: the type of ``Block``.
This defaults to the type of the grandchild class, and is determined
through calling blockname(self.__class__) when a grandchild class is created.
- icon: the icon for this ``Block``.
This is a locally referenced string filepath, defined within the grandchild class.
- inputs: a list of containing input ``Sockets`` relating to this ``Block``.
The number of input sockets is restricted to 0 or n based on the inputsNum
variable defined within the child class.
- outputs: a list of containing output ``Sockets`` relating to this ``Block``.
The number of output sockets is restricted to 0 or n based on the outputsNum
variable defined within the child class.
- parameters: a list of editable parameters relating to this ``Block``.
This defaults to the list defined within the grandchild class, but follows
the following structure of being a list of lists, where each 'lists' is a list
defining the parameter as below:
- parameters = ["name", type, value, [restrictions]]
e.g. parameters = [["Gain", float, gain, []], ["Premul", bool, premul, []]]
- name: is the name of the variable as a string
- type: is the required type the variable should be (e.g. int, str, float)
- value: is the default value the variable is set to should one not be provided
- restrictions: is a list (can be list of lists) containing further restrictions
applied to the parameter. These restrictions follow the following structure, of
being a list with a string as the first list element, followed by a list of
conditions being applied to the parameter as the second list element:
- restriction = ["restriction name", [condition(s)]]
- restriction name: can be only one of the following "keywords", "range", "type"
or "signs".
- condition(s): differ based on the restriction name used, and will be of the
following format:
- for keywords: a list of string words the parameter must exactly match to,
e.g. ["keywords", ["sine", "square", "triangle"]]
- for range: a list containing a min and max allowable value for this parameter,
e.g. ["range", [0, 1000]] or ["range", [-math.inf, math.inf]]
- for type: a list containing alternative types, with the last value repeating
the initial type required for this parameter,
e.g. ["type", [type(None), tuple]] (initial type = tuple) or ["type", [type(None), bool]] (initial type = bool)
- for signs: a list containing each allowable character this parameter can match,
e.g. ["signs", ["*", "/"]] or ["signs", ["+", "-"]]
currently this is used for drawing signs along certain input sockets, so only these characters are supported,
:param scene: a scene (or canvas) in which the Block is stored and
shown (or painted into). Provided by the ``Interface``.
:type scene: ``Scene``, required
:param window: layout information of where all ``Widgets`` are located
in the bdedit window. Provided by the ``Interface``.
:type window: ``QGridLayout``, required
:param title: set to grandchild class's default name "__class__.__name__ Block" when it is created
:type title: str, optional
:param pos: (x,y) coordinates of the block's positioning within the ``Scene``, defaults to (0,0)
:type pos: tuple of 2-ints, optional
"""
super().__init__()
self.scene = scene
self.window = window
self.position = pos
# Set block's orientation to be facing towards the right by default. If flipped is True, this means block is facing left
self.flipped = False
try:
self.setDefaultTitle(self.title)
except AttributeError:
# When trying to set title of connector block, it will throw an attribute error
# This is fine, as connector block isn't supposed to have a title
# print("block.py -> Error occured while setting default title")
pass
# Lists that will contain the input/output sockets of the Block
self.inputs = []
self.outputs = []
# Variable for controlling whether or not a ParamWindow should be
# displayed for this instance of a Block
self._param_visible = False
# Initially, parameterWindow is set to None, later replaced by the ParamWindow class, if block should have one
self.parameterWindow = None
# Minimum spacing distance between Sockets
self.socket_spacing = 20
# print("creating block instance - after:")
# [print(item) for item in self.__dict__.items()]
# print("_______________________________________")
# self._createBlock(self.inputsNum, self.outputsNum)
# print("after block instance made:")
# [print(item) for item in self.__dict__.items()]
# print("_______________________________________")
# Todo - update docstring and inline comments
# -----------------------------------------------------------------------------
def _createBlock(self, inputs, outputs):
"""
This private method is inherited and called by the grandchild class, and
should only be called once when the block is being created.
It populates the block's internal parameters; calls for the block to be
drawn; creates the input and output sockets of the block; adds it to be
stored and drawn in the ``Scene``; and if the block has user-editable
parameters, initializes the private _createParamWindow method to create a
parameter window linked to editing this block instance's parameters.
:param inputs: number of input ``Sockets`` to create for this ``Block``
:type inputs: int, required
:param outputs: number of output ``Sockets`` to create for this ``Block``
:type outputs: int, required
"""
# * the graphics of the blocks are generated,
# * the input and output sockets are created and linked to the block,
# * the block information is stored within the Scene class,
# * the blocks' graphical information is stored within the graphical section of the Scene class
# * if the block has user-editable parameters, then a parameter window is generated for this block
# if allowed_to_generate:
self.grBlock = GraphicsBlock(self)
self.makeInputSockets(inputs, LEFT)
self.makeOutputSockets(outputs, RIGHT)
self.scene.addBlock(self)
self.scene.grScene.addItem(self.grBlock)
self._createParamWindow()
self.scene.has_been_modified = True
# -----------------------------------------------------------------------------
def _createParamWindow(self):
"""
This private method takes no inputs, and should only be called once
when generating a parameter window for it's associated block.
It creates an instance of the ``ParamWindow`` class relating to
this ``Block`` and references the 'self.window' variable stored within
the ``Block`` class to make the parameter window part of the bdedit window.
"""
# Creates a parameter window variable associated to this Block instance, and sets its
# visibility based on the private 'self._param_visible' variable
# (True - allowed to display, False - cannot be displayed).
self.parameterWindow = ParamWindow(self)
self.parameterWindow.setVisible(self._param_visible)
# ParamWindow instance is added to the application window
self.window.addWidget(self.parameterWindow, 1, 10, 9, 1)
# -----------------------------------------------------------------------------
def makeInputSockets(self, inputs, position, socketType=INPUT):
"""
This method is called to create a number of input ``Sockets`` for this ``Block``.
:param inputs: number of input sockets to create
:type inputs: int, required
:param position: an enum representing the position of where to place
the ``Socket`` on the ``Block`` currently only supports LEFT (1), or RIGHT (3).
:type position: enumerate, required
:param socketType: an enum representing the type of ``Socket`` to create.
This is used for the graphics of the socket, but was also intended to be used
to reduce two methods for creating input and output sockets, to a single method.
:type socketType: enumerate, optional, defaults to INPUT(1)
"""
# Input sockets are created, starting from index 0 to the number of 'inputs'
# For each index:
# * an instance of a Socket Class is created, which:
# ** relates this Socket instance to this Block instance
# ** sets the 'index' of this Socket as the current index (counter)
# ** sets the 'position' of this Socket to the given position (LEFT or RIGHT)
# ** sets the 'socketType' of this Socket to the given socketType (INPUT by default)
# * the instance is appended to this Block's list of inputs
counter = 0
while counter < inputs:
try:
if self.input_names:
socket = Socket(
node=self,
index=counter,
position=position,
socket_type=socketType,
socket_label=self.input_names[counter],
)
else:
socket = Socket(
node=self,
index=counter,
position=position,
socket_type=socketType,
)
except (AttributeError, IndexError):
socket = Socket(
node=self, index=counter, position=position, socket_type=socketType
)
counter += 1
self.inputs.append(socket)
# Some Blocks (PROD and SUM) have additional logic for drawing signs alongside
# the input sockets. The method below is checks and applies that logic if required.
self.updateSocketSigns()
# -----------------------------------------------------------------------------
def makeOutputSockets(self, outputs, position, socketType=OUTPUT):
"""
This method is called to create a number of outputs ``Sockets`` for this ``Block``.
:param outputs: number of output sockets to create
:type outputs: int, required
:param position: an enum representing the position of where to place
the ``Socket`` on the ``Block`` currently only supports LEFT (1), or RIGHT (3).
:type position: enumerate, required
:param socketType: an enum representing the type of ``Socket`` to create.
This is used for the graphics of the socket, but was also intended to be used
to reduce two methods for creating input and output sockets, to a single method.
:type socketType: enumerate, optional, defaults to OUTPUT(2)
"""
# Output sockets are created, starting from index 0 to the number of 'outputs'
# For each index:
# * an instance of a Socket Class is created, which:
# ** relates this Socket instance to this Block instance
# ** sets the 'index' of this Socket as the current index (counter)
# ** sets the 'position' of this Socket to the given position (LEFT or RIGHT)
# ** sets the 'socketType' of this Socket to the given socketType (OUTPUT by default)
# * the instance is appended to this Block's list of outputs
counter = 0
while counter < outputs:
try:
if self.output_names:
socket = Socket(
node=self,
index=counter,
position=position,
socket_type=socketType,
socket_label=self.output_names[counter],
)
else:
socket = Socket(
node=self,
index=counter,
position=position,
socket_type=socketType,
)
except (AttributeError, IndexError):
socket = Socket(
node=self, index=counter, position=position, socket_type=socketType
)
counter += 1
self.outputs.append(socket)
# -----------------------------------------------------------------------------
def toggleParamWindow(self):
"""
This method toggles the visibility of the ``ParamWindow`` of this ``Block``
"""
# Sets the visibility of the parameter window to opposite of what the
# variable 'self._param_visible' is set to, and flips the boolean state of
# that variable (True -> False, or False -> True)
if self.parameterWindow:
self.parameterWindow.setVisible(not self._param_visible)
self._param_visible = not self._param_visible
# -----------------------------------------------------------------------------
def closeParamWindow(self):
"""
This method closes the ``ParamWindow`` of this ``Block``
"""
# Sets the visibility of the parameter window to False
# and sets 'self._param_visible' False
self.parameterWindow.setVisible(False)
self._param_visible = False
# -----------------------------------------------------------------------------
def updateSocketSigns(self):
"""
As some Blocks - namely the ``PROD`` and ``SUM`` Blocks - have additional logic for
drawing signs (+,-,*,/) alongside the input sockets, this method updates
these signs of the socket, if the block type is a ``PROD`` or ``SUM`` Block
"""
# Checks if the block type is a Prod or Sum block
if (
self.block_type == "PROD"
or self.block_type == "SUM"
or self.block_type == "Prod"
or self.block_type == "Sum"
):
# Iterates through user-editable parameters stored within the block and checks
# if one by the name of 'Operations' or 'Signs' exists (these block types should
# have them). These parameters hold characters (+,-,*,/) representing what signs
# should be displayed and the order they should be displayed in (left to right
# in the parameter, representing top to bottom when displayed on the block).
# Parameter is represented as a list of 4 items:
# parameter = [name, type, value, special_conditions]
for parameter in self.parameters:
# If parameter name is equal to:
if parameter[0] == "ops" or parameter[0] == "signs":
index = 0
# print("\nblock: updatingSocketSigns()")
# [print(item) for item in self.__dict__.items()]
# print("_______________________________________\n")
# Sets the socket_sign of Socket within the block, equal to the respective
# character (sign) stored within either the 'Operations' or 'Signs' parameter.
# Note, since this method is only ever called after the number of input sockets
# has been created, or after this number has been updated (when the user edits
# the number of signs to display), the number of input sockets will always
# exactly match the number of signs stored within the parameter.
for sign in parameter[2]:
self.inputs[index].socket_sign = sign
index += 1
# -----------------------------------------------------------------------------
def setFocusOfBlocks(self):
"""
This method sends all ``Block`` instances within the ``Scene`` to back
and then sends the currently selected ``Block`` instance to front.
"""
# Iterates through each Block within block list stored in the Scene Class
# and sets the graphical component of each block to a zValue of 0.
for block in self.scene.blocks:
block.grBlock.setZValue(0.0)
# Then sets the graphical component of the currently selected block to a
# zValue of 1, which makes it display above all other blocks on screen.
self.grBlock.setZValue(1.0)
# -----------------------------------------------------------------------------
@property
def pos(self):
"""
This method is called to access the positional coordinates of this ``Block``
in terms of where it is displayed within the ``Scene``
:return: the (x,y) coordinates of this ``Block``
:rtype: tuple (int, int)
"""
return self.grBlock.pos()
# -----------------------------------------------------------------------------
def setPos(self, x, y):
"""
This method is called to set the positional coordinates of this ``Block``
in terms of where it is displayed within the ``Scene``
:param x: the x coordinate of this ``Block``
:type x: int, required
:param y: the y coordinate of this ``Block``
:type y: int, required
"""
self.grBlock.setPos(x, y)
# -----------------------------------------------------------------------------
def setTitle(self, name=None):
"""
This method is called to determine if a this ``Block`` can be named with the
provided name. It applies logic to check if the given name of type `str`,
and if no other ``Block`` instance already has the given name. If either of
these conditions are not met, the user will be notified to provide a
different name.
:param name: given name to be set for this ``Block``, defaults to None if
not provided
:type name: str, optional
:return: - nothing (if name successfully set);
- [duplicate error message, given name] (if duplicate found);
- invalid type error message (if name is not of type `str`).
:rtype: - nothing (if name successfully set);
- list of [str, str] (if duplicate found);
- str (if name is not of type `str`).
"""
# This method should only do something, if a name is given for the block
# Hence, only do something if the name is not None
if name is not None:
# The name only needs to be checked to be updated if it's different
# the this blocks' current name (title)
if name != self.title:
# If the given name is of type str
if isinstance(name, str):
# Check if the given name already exists for any other block
duplicates = self.scene.checkForDuplicates(name)
# If the given name is not found to be a duplicate
if not duplicates:
# Set this blocks' title to the given name
self.title = name
return
# Else the given name is a duplicate
else:
# So return a list containing a duplicate error message and the given name
return ["@DuplicateName@", name]
# Else, the type of the given name is invalid
else:
return "@InvalidType@"
# -----------------------------------------------------------------------------
def setDefaultTitle(self, name, increment=None):
"""
This method is called to give a block a generic name, and if that name
already exists, to increment it by 1.
:param name: the generic name to be given to this ``Block``
:type name: str, required
:param increment: the number to display next to the generic name, to make
it unique. Defaults to None if this is the first instance of this block type.
:type increment: int, optional
"""
# Creates a temporary copy of the given name
block_name = name
# If the given name is of type str
if isinstance(name, str):
# If this isn't the first instance of this block type, increment will
# be a number greater than 0, and this if statement will be run.
if increment is not None:
# The temporary copy of the given name has the increment added to it
# to later check if that will make it unique
block_name += " " + str(increment)
# The increment is increased by one in case the previous line doesn't
# make the name unique
increment += 1
# The copy of the given name is checked against being a duplicate
duplicates = self.scene.checkForDuplicates(block_name)
# If it is not a duplicate, the name of the current block is set to
# the copy of the given name (this will be with an increment, or the
# original given name if this is the first instance of this block type).
if not duplicates:
self.title = block_name
# Else, it is a duplicate, and this method will call itself to increment
# the given name and check against that name being a duplicate, until
# a non-duplicate generic name is found.
else:
# If this is a second instance of this block type (hence the increment
# would be None), this method calls itself with the increment set to 1
if increment is None:
self.setDefaultTitle(name, 1)
# Else, this is more than a second instance of this block type, and
# the increment would of already been set, and internally incremented.
else:
self.setDefaultTitle(name, increment)
# -----------------------------------------------------------------------------
def getSocketPosition(self, index, position):
"""
This method is called to determine the coordinates of where a given ``Socket``
should be positioned on the sides of the this ``Block``. The returned
coordinates are in reference to the coordinates of this ``Block``.
:param index: the index of this ``Socket`` in the list of sockets for this ``Block``
:type index: int, required
:param position: the (LEFT(1) or RIGHT(3)) side of the block this socket
should be displayed on.
:type position: enumerate, required
:return: the [x,y] coordinates at which to place this ``Socket`` instance.
:rtype: list of int, int
"""
# If the position of the Socket is given to be on the LEFT of the block,
# * x is returned as 0.
# * y is returned as the index of this socket multiplied by the socket
# spacing set within this block class, PLUS an offset, determined by the
# height at which the block's title is placed below the block, and
# the thickness of this block's outline, and how curved its corners are.
if position == LEFT:
x = 0
y = (
self.grBlock._padding
+ self.grBlock.edge_size
+ self.grBlock.title_height
+ index * self.socket_spacing
)
# Else, the position of the Socket is given to be on the RIGHT of the block,
# * x is returned as the width of block.
# * y is returned as above.
elif position == RIGHT:
x = self.grBlock.width
y = (
self.grBlock._padding
+ self.grBlock.edge_size
+ self.grBlock.title_height
+ index * self.socket_spacing
)
return [x, y]
# -----------------------------------------------------------------------------
def updateSocketPositions(self):
"""
This method updates flips the position (LEFT or RIGHT) of where the
input and output sockets needs to be placed within this ``Block``.
After the positions of all the Blocks' sockets are updated,
the updateConnectedEdges method is called to update the locations for
where the wires connect to.
"""
# Iterates through every input Socket this Block has
for i in range(0, len(self.inputs)):
# Flips the position of the input sockets (LEFT to RIGHT, or RIGHT to LEFT)
if self.inputs[i].position == LEFT:
self.inputs[i].position = RIGHT
else:
self.inputs[i].position = LEFT
# Grabs the coordinates for where this Socket should be drawn
[x, y] = self.getSocketPosition(i, self.inputs[i].position)
# And sets the position of the current socket to these coordinates
self.inputs[i].grSocket.setPos(*[float(x), float(y)])
# Iterates through every output Socket this Block has
for i in range(0, len(self.outputs)):
# Flips the position of the output sockets (RIGHT to LEFT, or LEFT to RIGHT)
if self.outputs[i].position == RIGHT:
self.outputs[i].position = LEFT
else:
self.outputs[i].position = RIGHT
# Grabs the coordinates for where this Socket should be drawn
[x, y] = self.getSocketPosition(i, self.outputs[i].position)
# And sets the position of the current socket to these coordinates
self.outputs[i].grSocket.setPos(*[float(x), float(y)])
self.updateConnectedEdges()
# -----------------------------------------------------------------------------
def updateConnectedEdges(self):
"""
This method calls for any and all ``Wire`` instances that are connected to
a ``Socket`` instance, to update where it is drawn TO and FROM.
"""
# For each socket that exists in this block
for socket in self.inputs + self.outputs:
# Update the wire(s) connected to this socket
for wire in socket.wires:
wire.updatePositions()
# -----------------------------------------------------------------------------
def updateWireRoutingLogic(self):
"""
Wire routing logic is automatically determined by bdedit when moving blocks,
however users can adjust certain segments of these wires. When the user
interacts with these segments, the wire routing logic follows the custom
routing path. When blocks are moved again after wires segments are adjusted
by the user, the wiring logic will revert to following the automatic routing
logic. This method updates which wires should be drawn following the automatic
routing logic.
"""
for socket in self.inputs + self.outputs:
for wire in socket.wires:
if wire:
# If both blocks connected by these wires are selected, don't do
# anything, as both are being moved in respects to each other,
# so no need to update wiring logic.
start_block = wire.start_socket.node
end_block = wire.end_socket.node
if (
start_block.grBlock.isSelected()
and end_block.grBlock.isSelected()
):
pass
# wire.grWire.customlogicOverride = True
# start_block.updateSocketPositions()
# end_block.updateSocketPositions()
# Otherwise if only one block is selected, update the wiring logic
# to be displayed based on the automatic wire routing logic.
else:
wire.grWire.customlogicOverride = False
# -----------------------------------------------------------------------------
def removeSockets(self, type):
"""
This method removes all sockets of given type, associated with this ``Block``.
:param type: the type of ``Socket`` to remove ("Input" for input type,
"Output" for output type)
:type type: str, required
"""
# Depending on the given type, either the inputs or outputs list - stored within
# the block - will be cleared.
if type == "Input":
self.inputs.clear()
elif type == "Output":
self.outputs.clear()
# -----------------------------------------------------------------------------
def remove(self):
"""
This method is called to remove:
- the selected ``Block`` instance;
- any sockets associated with this Block;
- any wires that were connected to this Blocks' sockets; and
- the parameter window associated with this Block (if one existed).
"""
# For each socket associated with this block, remove the connected wires
if DEBUG:
print("> Removing Block", self)
if DEBUG:
print(" - removing all wires from sockets")
for socket in self.inputs + self.outputs:
for wire in socket.wires.copy():
# for wire in socket.wires:
if DEBUG:
print(" - removing from socket:", socket, "wire:", wire)
wire.remove()
# Remove the graphical representation of this block from the scene
# This will also remove the associated graphical representation of the
# blocks' sockets.
if DEBUG:
print(" - removing grBlock")
self.scene.grScene.removeItem(self.grBlock)
self.grBlock = None
# Remove the blocks' parameter window if one existed
if DEBUG:
print(" - removing parameterWindow")
if self.parameterWindow:
self.window.removeWidget(self.parameterWindow)
self.parameterWindow = None
# Finally, call the removeBlock method from within the Scene, which
# removes this block from the list of blocks stored in the Scene.
if DEBUG:
print(" - removing block from the scene")
self.scene.removeBlock(self)
if DEBUG:
print(" - everything was done.")
# -----------------------------------------------------------------------------
def serialize(self):
"""
This method is called to create an ordered dictionary of all of this Blocks'
parameters - necessary for the reconstruction of this Block - as key-value
pairs. This dictionary is later used for writing into a JSON file.
:return: an ``OrderedDict`` of [keys, values] pairs of all essential ``Block``
parameters.
:rtype: ``OrderedDict`` ([keys, values]*)
"""
# The sockets associated with this block, have their own parameters that are
# required for their reconstruction, so the serialize method within the
# Socket class is called to package this information for each socket, also into
# an OrderedDict. These ordered dictionaries are then stored in a temporary
# inputs/outputs parameter and are returned as part of the OrderedDict of this Block.
# Similarly, the user-editable parameters associated with this Block must be
# remembered for the reconstruction of this block. However as some of them
# need to be stored as tuples and JSON does not support this, hence the
# TupleEncoder is used. Additionally, to reconstruct the Block's user-editable
# parameters, only the name and value of these parameters are needed, as their
# type and special_conditions should never change from their definition within
# their Class. (As a reminder, parameter = [name, type, value, special_conditions])
if self.block_type in ["Connector", "CONNECTOR"]:
inputs, outputs, parameters = [], [], []
for socket in self.inputs:
inputs.append(socket.serialize())
for socket in self.outputs:
outputs.append(socket.serialize())
return OrderedDict(
[
("id", self.id),
("block_type", self.block_type),
("pos_x", self.grBlock.scenePos().x()),
("pos_y", self.grBlock.scenePos().y()),
("inputs", inputs),
("outputs", outputs),
]
)
else:
inputs, outputs, parameters = [], [], []
for socket in self.inputs:
inputs.append(socket.serialize())
for socket in self.outputs:
outputs.append(socket.serialize())
for parameter in self.parameters:
parameters.append([parameter[0], parameter[2]])
return OrderedDict(
[
("id", self.id),
("block_type", self.block_type),
("title", self.title),
("pos_x", self.grBlock.scenePos().x()),
("pos_y", self.grBlock.scenePos().y()),
("width", self.width),
("height", self.height),
("flipped", self.flipped),
("inputsNum", self.inputsNum),
("outputsNum", self.outputsNum),
("inputs", inputs),
("outputs", outputs),
("parameters", parameters),
]
)
# -----------------------------------------------------------------------------
def deserialize(self, data, hashmap={}):
"""
This method is called to reconstruct a ``Block`` when loading a saved JSON
file containing all relevant information to recreate the ``Scene`` with all
its items.
:param data: a Dictionary of essential information for reconstructing a ``Block``
:type data: OrderedDict, required
:param hashmap: a Dictionary for directly mapping the essential block parameters
to this instance of ``Block``, without having to individually map each parameter
:type hashmap: Dict, required
:return: True when completed successfully
:rtype: Boolean
"""
# The id of this Block is set to whatever was stored as its id in the JSON file.
self.id = data["id"]
try:
# The remaining parameters associated to this Block are mapped to itself
# hashmap[data['id']] = self
if self.block_type not in ["Connector", "CONNECTOR"]:
self.title = data["title"]
self.inputsNum = data["inputsNum"]
self.outputsNum = data["outputsNum"]
self.width = data["width"]
self.height = data["height"]
# If a model contains data on whether a block should be flipped, assign variable to that value
# If error occurs, model doesn't contain this variable, so ignore
try:
if data["flipped"]:
self.flipped = data["flipped"]
except KeyError:
pass
# The position of the Block within the Scene, are set accordingly.
self.setPos(data["pos_x"], data["pos_y"])
# When block is drawn, by default it is created with its allocated number of input/output sockets.
# When deserializing a block, we want the sockets to be in the locations where they were saved.
# Hence, we must delete the default created input/output sockets to override them with the saved sockets.
if self.inputs:
# RemoveSockets is a method accessible only through a socket, while self.inputs is a list of sockets
# 'removeSockets' removes all sockets associated with a block.
self.inputs[0].removeSockets("Input")
if self.outputs:
# Same usage of 'removeSocket' as above
self.outputs[0].removeSockets("Output")
# The input and output lists for this Block are cleared
self.inputs = []
self.outputs = []
# The saved user-editable parameters associated with the Block, are written over the default ones
# this instance of the block was created with, after reconstruction.
# Iterator for parameters
if self.block_type not in ["Connector", "CONNECTOR"]:
i = 0
for paramName, paramVal in data["parameters"]:
# If debug mode is enabled, this code will print to console to validate that the
# parameters are being overwritten into the same location they were previously stored in.
if DEBUG:
print("----------------------")
if DEBUG:
print("Cautionary check")
if DEBUG:
print(
"current value:",
[
self.parameters[i][0],
self.parameters[i][1],
self.parameters[i][2],
],
)
if DEBUG:
print(
"setting to value:",
[paramName, self.parameters[i][1], paramVal],
)
self.parameters[i][0] = paramName
self.parameters[i][2] = paramVal
# If there are subsystem, outport or inport blocks with labels for their sockets, extract that information into self.input_names and self.output_names as needed
if self.block_type in ["SUBSYSTEM", "OUTPORT", "INPORT"]:
if paramName == "inport labels":
if paramVal:
self.input_names = [str(j) for j in paramVal]
if paramName == "outport labels":
if paramVal:
self.output_names = [str(j) for j in paramVal]
i += 1
# And the saved (input and output) sockets are written into these lists respectively,
# deserializing the socket-relevant information while doing so.
for i, socket_data in enumerate(data["inputs"]):
try:
if self.input_names:
new_socket = Socket(
node=self,
index=socket_data["index"],
position=socket_data["position"],
socket_type=socket_data["socket_type"],
socket_label=self.input_names[i],
)
else:
new_socket = Socket(
node=self,
index=socket_data["index"],
position=socket_data["position"],
socket_type=socket_data["socket_type"],
)
except (AttributeError, IndexError):
new_socket = Socket(
node=self,
index=socket_data["index"],
position=socket_data["position"],
socket_type=socket_data["socket_type"],
)
new_socket.deserialize(socket_data, hashmap)
self.inputs.append(new_socket)
self.updateSocketSigns()
for i, socket_data in enumerate(data["outputs"]):
try:
if self.output_names:
new_socket = Socket(
node=self,
index=socket_data["index"],
position=socket_data["position"],
socket_type=socket_data["socket_type"],
socket_label=self.output_names[i],
)
else:
new_socket = Socket(
node=self,
index=socket_data["index"],
position=socket_data["position"],
socket_type=socket_data["socket_type"],
)
except (AttributeError, IndexError):
new_socket = Socket(
node=self,
index=socket_data["index"],
position=socket_data["position"],
socket_type=socket_data["socket_type"],
)
new_socket.deserialize(socket_data, hashmap)
self.outputs.append(new_socket)
if self.block_type not in ["Connector", "CONNECTOR"]:
if self.parameters:
self._createParamWindow()
# print("block type, name: ", [self.block_type, self.title])
# print("input sockets:")
# for socket in self.inputs:
# if socket:
# print("socket, id:", [socket, id(socket)])
# print()
# print("output sockets:")
# for socket in self.outputs:
# if socket:
# print("socket, id:", [socket, id(socket)])
# print("----------------------")
return True
except (ValueError, NameError, IndexError):
print(
f"error deserializing block [{self.block_type}::{self.title}] - maybe JSON file has old function parameters"
)
# -----------------------------------------------------------------------------
def block(cls):
"""
This method is called whenever a grandchild class of the ``Block`` is called,
adding it to a list of usable blocks.
This code has been adapted from: https://github.com/petercorke/bdsim/blob/bdedit/bdsim/components.py
:param cls: the class of the ``Block`` Class's grandchild block Class.
:type cls: Class, required
"""
# If the given Block is a subclass of the Block Class, it is added to the
# blocklist global variable
if issubclass(cls, Block):
blocklist.append(cls)
# Otherwise an error message is printed to console
else:
print("Error: @block used on a non Block subclass")
# -----------------------------------------------------------------------------
def blockname(cls):
"""
This method strips any underscores from a grandchild Class of the ``Block``
Class, and capitalizes the Class.__name__ to be used as the the Class's name.
This code has been adapted from: https://github.com/petercorke/bdsim/blob/bdedit/bdsim/bdsim.py
:param cls: the class of the ``Block`` Class's grandchild block Class.
:type cls: Class, required
:return: a reformatted string of the block's class name
:rtype: str
"""
return cls.__name__.strip("_").upper()
================================================
FILE: bdsim/bdedit/block_connector_block.py
================================================
# BdEdit imports
from bdsim.bdedit.block import *
from bdsim.bdedit.block_socket import *
from bdsim.bdedit.block_graphics_block import *
# =============================================================================
#
# Defining the Connector Class, which allows for the redirecting of Wires
# to create more neater Block Diagrams.
#
# =============================================================================
class Connector(Block):
"""
The ``Connector`` Class is a subclass of ``Block``, and referred to as a
child class of ``Block``. It inherits all the methods and variables of its
parent class to behave as a Block. It allows for wires to be more neatly
redirected, acting as a node through which the wires can be moved around
more freely within the work area.
The idea of this Connector block was for it to be a single socket which
allows a wire to be redirected through it, however currently it works by
mimicking a Block that only has 1 input and 1 output socket. The same socket
logic that applies to a Block, also applies to the Connector Block.
That being:
- an input: can only have 1 Wire connecting into it
- an output: can have n Wires connecting into it
"""
# -----------------------------------------------------------------------------
def __init__(self, scene, window, title="Unnamed Connector Block"):
"""
This method initializes an instance of the ``Connector`` Block Class.
:param scene: inherited through ``Block``
:type scene: ``Scene``, required
:param window: inherited through ``Block``
:type window: ``QGridLayout``, required
:param title: defaults to "Unnamed Connector Block"
:type title: str, optional
:param pos: inherited through ``Block``
:type pos: tuple of 2-ints, optional
"""
super().__init__(scene, window)
# Same variables inherited from the Block class
self.scene = scene
self.window = window
# No block title as the Connector Blocks have no name, as
# this type of block is more of a tool than a Block
# self.position = pos
# The Connector Block doesn't have its own subclass like the other Block types,
# hence some of the variables are defined in this class level, these being:
# * the block type
# * the block dimensions (width, height)
# * the grBlock (graphical representation of how this block looks)
# * the number of spawned input and output sockets (1 of each)
# * the paramWindow is disabled (this block doesn't have a paramWindow, as it is a tool)
self.block_type = blockname(self.__class__)
self.width = 13
self.height = 12
self.title = ""
self.parameters = []
self.block_url = ""
self.icon = ""
self.flipped = False
self.flipped_icon = ""
self.inputsNum = 1
self.outputsNum = 1
self.grBlock = GraphicsConnectorBlock(self)
self.makeInputSockets(self.inputsNum, LEFT, socketType=INPUT)
self.makeOutputSockets(self.outputsNum, RIGHT, socketType=OUTPUT)
self.parameterWindow = None
# The Connector block is automatically stored into the Scene,
# and visually added into the GraphicsScene
self.scene.addBlock(self)
self.scene.grScene.addItem(self.grBlock)
self.scene.has_been_modified = True
================================================
FILE: bdsim/bdedit/block_graphics_block.py
================================================
# Library imports
import sys
import traceback
# PyQt5 imports
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
# BdEdit imports
from bdsim.bdedit.Icons import *
# =============================================================================
#
# Defining and setting global variables
#
# =============================================================================
# Socket positioning variables - used for determining what side of the block the
# socket should be drawn
LEFT = 1
RIGHT = 3
# =============================================================================
#
# Defining the GraphicsBlock Class, which is inherited by all Blocks and
# controls the graphical appearance of each Block.
#
# =============================================================================
class GraphicsBlock(QGraphicsItem):
"""
The ``GraphicsBlock`` Class extends the ``QGraphicsItem`` Class from PyQt5.
This class is responsible for graphically drawing Blocks within the GraphicsScene.
Using the provided Block dimensions, it specifies the Blocks' shape and colour.
"""
# -----------------------------------------------------------------------------
def __init__(self, block, parent=None):
"""
This method initializes an instance of the ``GraphicsBlock`` Class.
It inherits the dimensions of its Block, and defines its shape and colour.
:param block: the Block this GraphicsBlock instance relates to
:type block: Block, required
:param parent: the parent widget this class instance belongs to (None)
:type parent: NoneType, optional, defaults to None
"""
super().__init__(parent)
# The block properties are inherited from the provided block
self.block = block
self.icon = self.block.icon
self.width = self.block.width
self.height = self.block.height
# The color mode of the block is also stored (Light or Dark mode)
self.mode = self.block.scene.grScene.mode
# Internal variable which dictate whether a title needs to be drawn
# The first time the Block is drawn, this is True, then it is set to
# False, and only changed to True when the title is called to update
self._draw_title = True
# These dimensions are not updated
self._default_width = self.block.width
self._default_height = self.block.height
# Pen thickness and block-related spacings are defined
self.edge_size = 10.0 # How rounded the rectangle corners are
self.title_height = (
25.0 # How many pixels underneath the block the title is displayed at
)
self._padding = (
5.0 # Minimum distance inside the block that things should be displayed at
)
self._line_thickness = 3.0 # Thickness of the block outline by default
self._selected_line_thickness = (
5.0 # Thickness of the block outline on selection
)
# Colours for pens are defined, and the text font is set
self._default_title_color = (
Qt.black
) # Title colour (set to Light mode by default)
# self._pen_selected = QPen(QColor("#FFFFA637"), self._selected_line_thickness)
self._pen_selected = QPen(
QColorConstants.Svg.orange, self._selected_line_thickness
) # Orange
self._title_font = QFont("Arial", self.block.scene.block_name_fontsize)
# Internal variable for catching fatal errors, and allowing user to save work before crashing
self.FATAL_ERROR = False
# Methods called to:
# * draw the title for the block
# * check current colour mode the block should display in (Light/Dark)
# * further initialize necessary block settings
self.initTitle()
self.checkMode()
self.initUI()
# Variable for storing whether block was moved or not
self.wasMoved = False
self.lastPos = self.pos()
# -----------------------------------------------------------------------------
def initUI(self):
"""
This method sets flags to allow for this Block to be movable and selectable.
"""
self.setFlag(QGraphicsItem.ItemIsSelectable)
self.setFlag(QGraphicsItem.ItemIsMovable)
self.setAcceptHoverEvents(True)
# -----------------------------------------------------------------------------
def initTitle(self):
"""
This method initializes a QGraphicsTextItem which will graphically represent
the title (name) of this Block.
"""
self.title_item = QGraphicsTextItem(self)
self.title_item.setDefaultTextColor(self._default_title_color)
self.title_item.setFont(self._title_font)
# -----------------------------------------------------------------------------
def titleLength(self):
"""
This method calculates and returns the length of this Blocks' title in pixels.
:return: the pixel length of this Blocks' title
:rtype: int
"""
# Using the font of the text and the block's title, determine the length of the
# title in terms of pixels
title_pixel_len = QFontMetrics(self._title_font).width(self.block.title)
# As the block width is an even number (100 pixels), to center properly, the
# width of the title must also be even
# If title width is odd, add 1 pixel to it to make it even
if title_pixel_len % 2 != 0:
title_pixel_len += 1
return title_pixel_len
# -----------------------------------------------------------------------------
def getTitle(self):
"""
This method returns the current title of this Block.
:return: Block title
:rtype: str
"""
return self.block.title
# -----------------------------------------------------------------------------
def setTitle(self):
"""
This method updates this Blocks' graphical title to the stored title of the Block.
"""
# Once the title has been set, this method will handle redrawing the title
# Hence the title doesn't need to be redrawn after
self._draw_title = False
# Graphical title is set to the block's title is set
self.title_item.setPlainText(self.block.title)
# Title length is found (using self.titleLength()), and centered under the block
self.title_item.setPos(
(self.width - self._padding - self.titleLength()) / 2,
self.height + self._padding,
)
# The GraphicsBlock instance is called to be updated
self.update()
# -----------------------------------------------------------------------------
def checkMode(self):
"""
This method checks the mode of the GraphicsScene's background (Light, Dark)
and updates the colour mode of the pens and brushes used to paint this Block.
"""
# If dark mode is selected, draw blocks tailored to dark mode
# if self.mode == "Dark":
# self._title_color = Qt.white
# self._pen_default = QPen(Qt.white, self._line_thickness)
# self._brush_background = QBrush(Qt.white)
# # Else light or off mode is selected (No off mode for blocks), draw blocks tailored to light mode
# else:
self._title_color = Qt.black
# self._pen_default = QPen(QColor("#7F000000"), self._line_thickness)
self._pen_default = QPen(QColorConstants.Svg.dimgrey, self._line_thickness)
self._brush_background = QBrush(QColor("#FFE1E0E8"))
self.title_item.setDefaultTextColor(self._title_color)
# Todo - update code
# -----------------------------------------------------------------------------
def updateMode(self, value):
"""
This method updates the mode of the Block to the provided value (should only
ever be "Light", "Dark" or "Off").
:param value: current mode of the GraphicsScene's background ("Light", "Dark", "Off")
:type value: str, required
"""
self.mode = value
self.checkMode()
self.update()
# -----------------------------------------------------------------------------
def checkBlockHeight(self):
"""
This method checks if the current height of the Block is enough to fit all
the Sockets that are to be drawn, while following the set socket spacing.
It also handles the resizing of the Block (if there isn't enough space for
all the sockets), ensuring the sockets are evenly spaced while following
the set socket spacing.
"""
# The offset distance from the top of the Block to the first Socket.
# The same offset is used for from the bottom of the Block to the last Socket.
socket_spacer = self._padding + self.edge_size + self.title_height
# This code grabs the coordinates ([x,y]) of last input and output sockets if any exist
if self.block.inputs:
last_input = self.block.inputs[-1].getSocketPosition()
else:
last_input = [0, 0]
if self.block.outputs:
last_output = self.block.outputs[-1].getSocketPosition()
else:
last_output = [0, 0]
# The max height of the Block could depend on either the input or output sockets
# Hence the max height of both types are found (max height is the height at which
# the last socket should be placed, in order for sockets to be evenly spaced)
# Max height of input/output sockets - adds socket_spacer height to height of last input/output socket
max_input_socket_height = last_input[1] + socket_spacer
max_output_socket_height = last_output[1] + socket_spacer
# Max block height (determined by which ever has more sockets - inputs or outputs)
max_block_height = max(max_input_socket_height, max_output_socket_height)
# If max_block_height is greater than the default block height, set current_block_height to max_block_height
# Otherwise keep it at the default block height
if max_block_height > self._default_height:
self.block.height = max_block_height
else:
self.block.height = self._default_height
# Update the internal height of the GraphicsBlock to the updated height of the Block
self.height = self.block.height
self.update()
# -----------------------------------------------------------------------------
def hoverEnterEvent(self, event):
"""
When a ``GraphicsBlock`` is hovered over with the cursor, this method will display
a tooltip with the type of block underneath the mouse.
:param event: mouse hover detected over block
:type event: QGraphicsSceneHoverEvent
"""
# QToolTip.setFont(QFont("Ubuntu", 10))
self.setToolTip("" + self.block.block_type + " block")
# self.setToolTip("" + self.block.block_type + "")
# -----------------------------------------------------------------------------
def boundingRect(self):
"""
This is an inbuilt method of QGraphicsItem, that is overwritten by ``GraphicsBlock``
which returns the area within which the GraphicsBlock can be interacted with.
When a mouse click event is detected within this area, this will trigger logic
that relates to a Block (that being, selecting/deselecting, moving, deleting,
flipping or opening a parameter window).
:return: a rectangle within which the Block can be interacted with
:rtype: QRectF
"""
return QRectF(0, 0, self.width, self.height)
# -----------------------------------------------------------------------------
def paint(self, painter, style, widget=None):
"""
This is an inbuilt method of QGraphicsItem, that is overwritten by ``GraphicsBlock``.
This method is automatically called by the GraphicsView Class whenever even
a slight user-interaction is detected within the Scene.
Before drawing, the dimensions of the Block are checked, to ensure they can
hold all the necessary Sockets. Then the following are drawn in order:
- the title of the block
- the fill of the block (a rounded rectangle)
- the outline of the block (a rounded rectangle)
- the icon of the block (if one exists)
:param painter: a painter (paint brush) that paints and fills the shape of this GraphicsBlock
:type painter: QPainter, automatically recognized and overwritten from this method
:param style: style of the painter (isn't used but must be defined)
:type style: QStyleOptionGraphicsItem, automatically recognized from this method
:param widget: the widget this class is being painted on (None)
:type widget: NoneType, optional, defaults to None
"""
try:
# Block dimensions are checked for to ensure there's enough space for all sockets
self.checkBlockHeight()
# Title will be redrawn, if needed
if self._draw_title:
self.setTitle()
# Background (fill) of the block is drawn
path_content = QPainterPath()
path_content.setFillRule(Qt.WindingFill)
path_content.addRoundedRect(
0, 0, self.width, self.height, self.edge_size, self.edge_size
)
path_content.addRect(0, self.title_height, self.edge_size, self.edge_size)
path_content.addRect(
self.width - self.edge_size,
self.title_height,
self.edge_size,
self.edge_size,
)
painter.setPen(Qt.NoPen)
painter.setBrush(self._brush_background)
painter.drawPath(path_content.simplified())
# Outline of the block is drawn
path_outline = QPainterPath()
path_outline.addRoundedRect(
0, 0, self.width, self.height, self.edge_size, self.edge_size
)
painter.setPen(
self._pen_default if not self.isSelected() else self._pen_selected
)
painter.setBrush(Qt.NoBrush)
painter.drawPath(path_outline.simplified())
# Icon of the block is drawn overtop the blocks' background
if QtCore.QFile.exists(self.icon):
if self.block.flipped and QtCore.QFile.exists(self.block.flipped_icon):
icon_image = QImage(self.block.flipped_icon)
# icon_item = QPixmap(self.block.flipped_icon).scaledToWidth(50) if self.block.flipped_icon else QPixmap(self.block.flipped_icon) # Icons are scaled down to 50 pixels
else:
icon_image = QImage(self.icon)
# icon_item = QPixmap(self.icon).scaledToWidth(50) if self.icon else QPixmap(self.icon)
# target = QRect((self.width - icon_item.width()) / 2, (self.height - icon_item.height()) / 2, self.width, self.height)
# source = QRect(0, 0, self.width, self.height)
painter.drawImage(
QRectF(
(self.width - (icon_image.width()) / 5) / 2,
(self.height - (icon_image.height()) / 5) / 2,
50,
50,
),
icon_image,
)
# painter.drawPixmap(target, icon_item, source)
except Exception as e:
if self.FATAL_ERROR == False:
print(
"--------------------------------------------------------------------------"
)
print(
"Caught fatal exception while trying to draw blocks. Please save your work."
)
print(
"--------------------------------------------------------------------------"
)
traceback.print_exc(file=sys.stderr)
self.FATAL_ERROR = True
# -----------------------------------------------------------------------------
def mousePressEvent(self, event):
"""
This is an inbuilt method of QGraphicsItem, that is overwritten by
``GraphicsBlock`` to detect, and assign logic to a right mouse press event.
Currently a detected mouse press event on the GraphicsBlock will select
or deselect it.
- If selected, the GraphicsBlock will be sent to front and will appear on
top of other blocks.
- Additionally, if the right mouse button is pressed and a GraphicsBlock
is selected, a parameter window will be toggled for this Block.
:param event: a mouse press event (Left, Middle or Right)
:type event: QMousePressEvent, automatically recognized by the inbuilt function
"""
# When the current GraphicsBlock is pressed on, it is sent to the front
# of the work area (in the GraphicsScene)
self.block.setFocusOfBlocks()
# If the GraphicsBlock is currently selected when the right mouse button
# is pressed, the parameter window will be toggled (On/Off)
if event.button() == Qt.RightButton:
self.block.toggleParamWindow()
super().mousePressEvent(event)
# Todo - add documentation
# -----------------------------------------------------------------------------
def mouseReleaseEvent(self, event):
super().mouseReleaseEvent(event)
# If block has been moved, update the variable within the model, to then update the
# title of the model, to indicate that there is unsaved progress
if self.wasMoved:
self.wasMoved = False
self.block.scene.has_been_modified = True
self.block.scene.history.storeHistory("Block moved")
class GraphicsConnectorBlock(QGraphicsItem):
"""
The ``GraphicsConnectorBlock`` Class extends the ``QGraphicsItem`` Class from PyQt5.
This class is responsible for graphically drawing Connector Blocks within the
GraphicsScene.
"""
# -----------------------------------------------------------------------------
def __init__(self, block, parent=None):
"""
This method initializes an instance of the ``GraphicsConnectorBlock`` Class
(otherwise known as the Graphics Class of the Connector Block).
:param block: the Connector Block this GraphicsConnectorBlock instance relates to
:type block: Connector Block
:param parent: the parent widget this class instance belongs to (None)
:type parent: NoneType, optional, defaults to None
"""
super().__init__(parent)
self.block = block
self.icon = self.block.icon
self._draw_title = False
self.width = self.block.width
self.height = self.block.height
# As the connector block consists of two sockets (1 input, 1 output) which
# use the following commands in determining where they need to be placed,
# these commands must be included, but are set to 0 as no shape is drawn for
# the connector block, aside from these two sockets.
self.edge_size = 0
self.title_height = 0
self._padding = 0
# Definition for the line thickness when the Connector block is selected
# Internal padding is half this value
# Corner rounding is by how many pixels the corners are rounded of the selected box that is drawn
self._selected_line_thickness = 5.0
self._internal_padding = 2.5
self._corner_rounding = 10
# Color of the selected line is set
# self._pen_selected = QPen(QColor("#FFFFA637"), self._selected_line_thickness) # Orange
self._pen_selected = QPen(
QColorConstants.Svg.orange, self._selected_line_thickness
) # Orange
# Color of wire to be drawn between sockets, when connector block is hidden (to make solid line)
self._color = QColor("#000000")
# Internal variable for catching fatal errors, and allowing user to save work before crashing
self.FATAL_ERROR = False
# Further initialize necessary Connector Block settings
self.initUI()
self.wasMoved = False
self.lastPos = self.pos()
# -----------------------------------------------------------------------------
def initUI(self):
"""
This method sets flags to allow for this Connector Block to be movable and selectable.
"""
self.setFlag(QGraphicsItem.ItemIsSelectable)
self.setFlag(QGraphicsItem.ItemIsMovable)
# When first created, the Connector block spawns highlighted
self.setSelected(True)
# -----------------------------------------------------------------------------
def boundingRect(self):
"""
This is an inbuilt method of QGraphicsItem, that is overwritten by ``GraphicsConnectorBlock``
which returns the area within which the GraphicsConnectorBlock can be interacted with.
When a mouse click event is detected within this area, this will trigger logic
that relates to a Block (that being, selecting/deselecting, moving, deleting,
flipping or opening a parameter window. Or if its Sockets are clicked on,
this will trigger a wire to be created or ended).
:return: a rectangle within which the Block can be interacted with
:rtype: QRectF
"""
W = self.width
P = self._internal_padding
# return QRectF(
# 1 - W - P,
# 1 - W - P,
# 3 * W + P,
# 2 * W + P
# ).normalized()
# Alternative selection area that is larger, but will overlap wires directly
# one grid block step above the connector block, when the connector block is
# selected.
return QRectF(
1 - 1.5 * W - P, 1 - 1.5 * W - P, 4 * W + P, 3 * W + P
).normalized()
# -----------------------------------------------------------------------------
def paint(self, painter, style, widget=None):
"""
This is an inbuilt method of QGraphicsItem, that is overwritten by
``GraphicsConnectorBlock`` (otherwise referred to as the Graphics Class of
the Connector Block. This method is automatically called by the GraphicsView
Class whenever even a slight user-interaction is detected within the Scene.
When the Connector Block is selected, this method will draw an orange
outline around the Connector Block, within which it can be interacted with.
:param painter:a painter (paint brush) that paints and fills the shape of this GraphicsConnectorBlock
:type painter: QPainter, automatically recognized and overwritten from this method
:param style: style of the painter (isn't used but must be defined)
:type style: QStyleOptionGraphicsItem, automatically recognized from this method
:param widget: the widget this class is being painted on (None)
:type widget: NoneType, optional, defaults to None
"""
try:
if self.isSelected():
# Draws orange outline around the Connector Block when it is selected
path_outline = QPainterPath()
# The size of the rectangle drawn, is dictated by the boundingRect (interactive area)
path_outline.addRoundedRect(
self.boundingRect(), self._corner_rounding, self._corner_rounding
)
painter.setPen(self._pen_selected)
painter.setBrush(Qt.NoBrush)
painter.drawPath(path_outline.simplified())
# If the user has chosen to hide the connector blocks, redraw the sockets to be hidden
if self.block.scene.hide_connector_blocks:
# Grab the [x,y] coordinates of both the input and output sockets of the
# connector block, and create a wire path to be drawn between them
input_pos = self.block.inputs[0].getSocketPosition()
output_pos = self.block.outputs[0].getSocketPosition()
multi = 1
# If connector block is flipped, draw the wire path in the opposite direction
if self.block.inputs[0].position == RIGHT:
multi = -1
wire_path = QPainterPath(
QPointF(input_pos[0] + (multi * 4.5), input_pos[1])
)
wire_path.lineTo(output_pos[0] - (multi * 4.5), output_pos[1])
# Set the paint brush width and colour
wire_pen = QPen(self._color)
wire_pen.setWidth(5)
painter.setPen(wire_pen)
painter.drawPath(wire_path)
except Exception as e:
if self.FATAL_ERROR == False:
print(
"------------------------------------------------------------------------------------"
)
print(
"Caught fatal exception while trying to draw connector blocks. Please save your work."
)
print(
"------------------------------------------------------------------------------------"
)
traceback.print_exc(file=sys.stderr)
self.FATAL_ERROR = True
# -----------------------------------------------------------------------------
def mousePressEvent(self, event):
"""
This is an inbuilt method of QGraphicsItem, that is overwritten by
``GraphicsConnectorBlock`` to detect, and assign logic to a right mouse press event.
Currently a detected mouse press event on the GraphicsConnectorBlock will
select or deselect it.
Additionally if selected, the GraphicsBlock will be sent to front and will
appear on top of other blocks.
:param event: a mouse press event (Left, Middle or Right)
:type event: QMousePressEvent, automatically recognized by the inbuilt function
"""
# When the current GraphicsSocketBlock is pressed on, it is sent to the front
# of the work area (in the GraphicsScene)
self.block.setFocusOfBlocks()
super().mousePressEvent(event)
# Todo - add documentation
# -----------------------------------------------------------------------------
def mouseReleaseEvent(self, event):
super().mouseReleaseEvent(event)
# If block has been moved, update the variable within the model, to then update the
# title of the model, to indicate that there is unsaved progress
if self.wasMoved:
self.wasMoved = False
self.block.scene.has_been_modified = True
self.block.scene.history.storeHistory("Connector Block moved")
================================================
FILE: bdsim/bdedit/block_graphics_socket.py
================================================
# Library imports
import sys
import traceback
from PIL import ImageFont
# PyQt5 imports
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
# =============================================================================
#
# Defining and setting global variables
#
# =============================================================================
# Socket positioning variables - used for determining what side of the block the
# socket should be drawn
LEFT = 1
RIGHT = 3
# Socket type classification variables
INPUT = 1
OUTPUT = 2
# Input Socket sign classification variables
PLUS = "+"
MINUS = "-"
MULTIPLY = "*"
DIVIDE = "/"
# =============================================================================
#
# Defining the GraphicsSocket Class, which is inherited by all Sockets, and
# controls the graphical appearance of each Socket.
#
# =============================================================================
class GraphicsSocket(QGraphicsItem):
"""
The ``GraphicsSocket`` Class extends the ``QGraphicsItem`` Class from PyQt5.
This class is responsible for graphically drawing Sockets on Blocks. It
specifies the shape, colour, style and dimensions of the Socket and also
implements the logic for drawing signs alongside the input sockets of ``PROD``
and ``SUM``` Blocks.
"""
# -----------------------------------------------------------------------------
def __init__(self, socket):
"""
This method initializes an instance of the ``GraphicsSocket`` Class. It
defines the shapes and sizes for a given input or output Socket. Depending
on the socket_type, stored within the provided Socket, the shape and colour
of the given Socket is decided.
:param socket: the Socket this GraphicsSocket instance relates to
:type socket: Socket
"""
self.socket = socket
# The GraphicsBlock class is initialized for the Block Class this Socket relates to
super().__init__(socket.node.grBlock)
# Sizes for the various socket shapes are defined
self.radius = 6.0
self.triangle_left = 6
self.triangle_right = 8
self.triangle_up = 6
self.square = 6
# Outlines of the shapes and signs are defined
self.outline_width = 1.0
self.sign_width = 1.5
# Fill colors of the socket shapes are defined
self._color_background_input = QColor("#3483eb") # Blue
self._color_background_output = QColor("#f54242") # Red
self._color_background_connector = QColor(
"#42f587"
) # Lime Green (currently not used)
self._color_outline = QColor("#000000") # Black
# Painter pens are assigned a colour and outline thickness
self._pen = QPen(self._color_outline)
self._pen.setWidthF(self.outline_width)
self._sign_pen = QPen(self._color_outline)
self._sign_pen.setWidthF(self.sign_width)
self._char_font = QFont("Arial", 14)
self.setFlag(QGraphicsItem.ItemIsSelectable)
self.setBrush()
# Internal variable for catching fatal errors, and allowing user to save work before crashing
self.FATAL_ERROR = False
def setBrush(self):
# Depending on the socket type, the painter brush is set
if self.socket.socket_type == INPUT:
self._brush = QBrush(self._color_background_input)
elif self.socket.socket_type == OUTPUT:
self._brush = QBrush(self._color_background_output)
# Todo - update docs, and inline comments
# -----------------------------------------------------------------------------
def paint(self, painter, style, widget=None):
"""
This is an inbuilt method of QGraphicsItem, that is overwritten by ``GraphicsSocket``.
This method is automatically called by the GraphicsView Class whenever even
a slight user-interaction is detected within the Scene.
It dictates how both input and output Sockets are painted on their relating Block.
The position at which to draw the Socket is determined internally by the Socket
class, so when the GraphicsSocket class paints the Socket, it is painted with
respects to the point where the Socket should be.
:param painter: a painter (paint brush) that paints and fills the shape of this GraphicsSocket
:type painter: QPainter, automatically recognized and overwritten from this method
:param style: style of the painter (isn't used but must be defined)
:type style: QStyleOptionGraphicsItem, automatically recognized from this method
:param widget: the widget this class is being painted on (None)
:type widget: NoneType, optional, Defaults to None
"""
# Painter pen(outline) and brush(fill) are set
painter.setPen(self._pen)
try:
painter.setBrush(self._brush)
except AttributeError as e:
# For some reason, brush was not set, set it again based on socket type
self.setBrush()
# If sockets don't need to be hidden, draw them normally, otherwise don't draw them at all
if not self.shouldSocketsBeHidden():
# Multi is an internal variable that dictates the direction the socket shapes
# should point (this comes into affect when the block sockets are flipped, and the
# output triangle socket shape should point either right (default), or left (flipped))
multi = 1
offset = 0
# If the socket has a name (character) to display, find the characters' dimensions
# Dimensions of the socket sign - contains [width, height] of character
if self.socket.socket_sign:
(char_width, char_height) = self.charDimensions()
else:
(char_width, char_height) = [0, 0]
# If the socket is flipped, adjust the internal multi variable
if self.socket.position == RIGHT:
multi = -1
if self.socket.socket_sign:
offset = char_width
# This code paints a square for the input socket
if self.socket.socket_type == INPUT:
painter.drawRect(
-self.square, -self.square, 2 * self.square, 2 * self.square
)
# If the input socket has a sign (will be true for the PROD and SUM Blocks)
# paint the relevant sign (+,-,*,/) next to the input socket
try:
if self.socket.socket_sign is not None:
path = self.getSignPath(self.socket.socket_sign, multi)
if path is None:
painter.setPen(self._sign_pen)
painter.setFont(self._char_font)
painter.drawText(
(10 + offset) * multi,
char_height,
self.socket.socket_sign,
)
else:
# The painter path for the respective sign depends on the sign relating to this socket
painter.setPen(self._sign_pen)
painter.drawPath(path)
except Exception as e:
if self.FATAL_ERROR == False:
print(
"---------------------------------------------------------------------------------------"
)
print(
"Caught fatal exception while trying to draw input socket labels. Please save your work."
)
print(
"---------------------------------------------------------------------------------------"
)
traceback.print_exc(file=sys.stderr)
self.FATAL_ERROR = True
# This code paints a triangle for the output socket
if self.socket.socket_type == OUTPUT:
path = QPainterPath()
path.moveTo(multi * self.triangle_left, multi * self.triangle_up)
path.lineTo(-multi * self.triangle_right, 0)
path.lineTo(multi * self.triangle_left, -multi * self.triangle_up)
path.lineTo(multi * self.triangle_left, multi * self.triangle_up)
painter.drawPath(path)
try:
if self.socket.socket_sign is not None:
painter.setPen(self._sign_pen)
painter.setFont(self._char_font)
painter.drawText(
(10 + offset) * multi, char_height, self.socket.socket_sign
)
except Exception as e:
if self.FATAL_ERROR == False:
print(
"----------------------------------------------------------------------------------------"
)
print(
"Caught fatal exception while trying to draw output socket labels. Please save your work."
)
print(
"----------------------------------------------------------------------------------------"
)
traceback.print_exc(file=sys.stderr)
self.FATAL_ERROR = True
# -----------------------------------------------------------------------------
def paintPlus(self, multi):
"""
This method creates a painter path for drawing the '+' character next
to an input socket.
:param multi: internal variable (1 when default orientation, -1 when flipped)
:type multi: int, required, 1 or -1
:return: the painter path to draw this sign
:rtype: QPainterPath
"""
path = QPainterPath(QPointF(multi * 2.5 * self.square, 0))
path.lineTo(multi * 4.5 * self.square - multi * 2, 0)
path.moveTo(multi * 3.5 * self.square - multi * 1, -self.square + 1)
path.lineTo(multi * 3.5 * self.square - multi * 1, self.square - 1)
return path
# -----------------------------------------------------------------------------
def paintMinus(self, multi):
"""
This method creates a painter path for drawing the '-' character next
to an input socket.
:param multi: internal variable (1 when default orientation, -1 when flipped)
:type multi: int, required, 1 or -1
:return: the painter path to draw this sign
:rtype: QPainterPath
"""
path = QPainterPath(QPointF(multi * 2.5 * self.square, 0))
path.lineTo(multi * 4.5 * self.square - multi * 2, 0)
return path
# -----------------------------------------------------------------------------
def paintMultiply(self, multi):
"""
This method creates a painter path for drawing the 'x' character next
to an input socket.
:param multi: internal variable (1 when default orientation, -1 when flipped)
:type multi: int, required, 1 or -1
:return: the painter path to draw this sign
:rtype: QPainterPath
"""
path = QPainterPath(QPointF(multi * 2.5 * self.square, -self.square + 1))
path.lineTo(multi * 4.5 * self.square - multi * 2, self.square - 1)
path.moveTo(multi * 4.5 * self.square - multi * 2, -self.square + 1)
path.lineTo(multi * 2.5 * self.square, self.square - 1)
return path
# -----------------------------------------------------------------------------
def paintDivide(self, multi):
"""
This method creates a painter path for drawing a divide sign character next
to an input socket.
:param multi: internal variable (1 when default orientation, -1 when flipped)
:type multi: int, required, 1 or -1
:return: the painter path to draw this sign
:rtype: QPainterPath
"""
path = QPainterPath(QPointF(multi * 2.5 * self.square, 0))
path.lineTo(multi * 4.5 * self.square - 1, 0)
path.moveTo(multi * 3.5 * self.square - 1, -self.square + 1)
path.addEllipse(multi * 3.5 * self.square - 1, -self.square + 1, 1, 1)
path.moveTo(multi * 3.5 * self.square - 1, self.square - 2)
path.addEllipse(multi * 3.5 * self.square - 1, self.square - 2, 1, 1)
return path
# Todo - doc comments
# -----------------------------------------------------------------------------
def charDimensions(self):
# Find how many pixels - height wise - this sockets' character is
(width, baseline), (
offset_x,
offset_y,
) = self.socket.node.scene._system_font.font.getsize(self.socket.socket_sign)
char_width = QFontMetrics(self._char_font).width(self.socket.socket_sign)
height = 5
# For letters like: a,c,e,m,n,o,r,s,u,v,w,x,z
if baseline == 8 and offset_y == 5:
height = 5
# For letters like: b,d,f,h,i,k,l
elif baseline == 10 and offset_y == 3:
height = 7
# For letters like: g,p,q,y
elif baseline == 11 and offset_y == 5:
height = 4
# For letter: t
elif baseline == 11 and offset_y == 2:
height = 7
dimension = [char_width, height]
return dimension
# -----------------------------------------------------------------------------
def getSignPath(self, sign, multi):
"""
This method determines and returns what method should be called to paint
the sign (+,-,*,/) next to an input socket (for PROD and SUM blocks only).
:param sign: the sign associated with the current Socket (can be '+','-','*', or '/')
:type sign: str, required
:param multi: internal variable (1 when default orientation, -1 when flipped)
:type multi: int, required, 1 or -1
:return: the relevant painter path method for drawing the desired sign
:rtype: QPainterPath
"""
if sign == PLUS:
return self.paintPlus(multi)
if sign == MINUS:
return self.paintMinus(multi)
if sign == MULTIPLY:
return self.paintMultiply(multi)
if sign == DIVIDE:
return self.paintDivide(multi)
# Todo - doc comments
# -----------------------------------------------------------------------------
def shouldSocketsBeHidden(self):
# Check if the sockets belong to a connector type block
if (
self.socket.node.block_type == "CONNECTOR"
or self.socket.node.block_type == "Connector"
):
# Check if the toolbar checkbox for hiding connector blocks has been selected
if self.socket.node.scene.hide_connector_blocks:
return True
else:
return False
else:
return False
# -----------------------------------------------------------------------------
def boundingRect(self):
"""
This is an inbuilt method of QGraphicsItem, that is overwritten by ``GraphicsSocket``
which returns the area within which the GraphicsSocket can be interacted with.
When a mouse click event is detected within this area, this will trigger logic
that relates to a Socket (that being, the generating or completion of a Wire).
:return: a rectangle within which the Socket can be interacted with
:rtype: QRectF
"""
return QRectF(
-self.radius - self.outline_width,
-self.radius - self.outline_width,
2 * (self.radius + self.outline_width),
2 * (self.radius + self.outline_width),
)
================================================
FILE: bdsim/bdedit/block_graphics_wire.py
================================================
# Library imports
import sys
import traceback
from math import dist
# PyQt5 imports
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
# =============================================================================
#
# Defining and setting global variables
#
# =============================================================================
# Socket positioning variables - used for determining what side of the block the
# socket should be drawn
LEFT = 1
TOP = 2
RIGHT = 3
BOTTOM = 4
# Variable for enabling/disabling debug comments
DEBUG = False
DEBUG_COORDINATES = False
# =============================================================================
#
# Defining the GraphicsWire Class, which is inherited by all Wires and controls
# the graphical appearance of each Wire.
#
# =============================================================================
class GraphicsWire(QGraphicsPathItem):
# Handles for displaying cursors when trying to move wire segments
handleHSeg1 = 0
handleVSeg1 = 1
handleHSeg2 = 2
handleVSeg2 = 3
handleHSeg3 = 4
handleSize = +4.0
handleCursors = {
handleHSeg1: Qt.ArrowCursor,
handleVSeg1: Qt.SizeHorCursor,
handleHSeg2: Qt.SizeVerCursor,
handleVSeg2: Qt.SizeHorCursor,
handleHSeg3: Qt.ArrowCursor,
}
handleSegments = 5
"""
The ``GraphicsWire`` Class extends the ``QGraphicsPathItem`` Class from PyQt5.
This class is responsible for graphically drawing Wires between Sockets.
This class takes a Wire as an input and then looks for the coordinates of the
start and end socket defined within it. Then based on these coordinates,
connects them with a Wire of the selected type. It is also used to redraw
the wires when they are moved around, and if a wire is selected it will
redraw the wire thicker and in a different colour.
"""
# -----------------------------------------------------------------------------
def __init__(self, wire):
"""
This method initializes an instance of the ``GraphicsWire`` Class. It
initially specifies the starting and ending sockets as being None, sets
the Wire to always be drawn underneath other items within the GraphicsScene,
and defines the colors with which the wire can be drawn.
:param wire: the Wire Class instance this GraphicsWire relates to
:type wire: Wire
"""
super().__init__()
# Dictionary for storing which mouse cursor to display when mouse hovering over
# vertical or horizontal wire segment
self.segment_handles = {}
self.handleSelected = None
self.mousePressPos = None
self.wire = wire
# Setting the colour, pens, and pen thickness
self._color = QColorConstants.Svg.black
self._color_selected = QColorConstants.Svg.orange
# self._pen = QPen(self._color, 5, Qt.SolidLine, Qt.SquareCap, Qt.BevelJoin)
self._pen = QPen(self._color, 5, Qt.SolidLine, Qt.SquareCap, Qt.RoundJoin)
self._pen_selected = QPen(
self._color_selected, 8, Qt.SolidLine, Qt.SquareCap, Qt.BevelJoin
)
# Initializing the start and end sockets
self.posSource = [0, 0]
self.posDestination = [100, 100]
self.posSource_Orientation = None
self.posDestination_Orientation = None
# Method called to further intialize necessary block settings
self.initUI()
# Internal variables for:
# * knowing if wire segments were moved since diagram was saved
# * setting which routing logic to display (custom or hard-coded)
# * catching fatal errors, and allowing user to save work before crashing
self.wasMoved = False
self.customlogicOverride = False
self.FATAL_ERROR = False
# -----------------------------------------------------------------------------
def initUI(self):
"""
This method sets flags to allow for this Wire to be selectable and be
displayed at the correct z-level.
"""
# Setting the wire to be selectable and drawn behind all items
self.setFlag(QGraphicsItem.ItemIsSelectable)
self.setFlag(QGraphicsItem.ItemSendsGeometryChanges)
self.setFlag(QGraphicsItem.ItemIsFocusable)
self.setAcceptHoverEvents(True)
self.setZValue(-1)
# -----------------------------------------------------------------------------
def setSource(self, x, y):
"""
This method sets the point from where the Wire will start. This is
based on the position of the start Socket.
:param x: x coordinate of the start Socket
:type x: int, required
:param y: y coordinate of the start Socket
:type y: int, required
"""
self.posSource = [x, y]
# -----------------------------------------------------------------------------
def setDestination(self, x, y):
"""
This method sets the point of where the Wire will end. This is
based on the position of the end Socket.
:param x: x coordinate of the end Socket
:type x: int, required
:param y: y coordinate of the end Socket
:type y: int, required
"""
self.posDestination = [x, y]
# -----------------------------------------------------------------------------
def setSourceOrientation(self, orientation):
"""
This method sets the orientation (position) of the source (start)
Socket - in terms of where it is drawn on the block (LEFT/RIGHT) - to
the provided orientation.
:param orientation: where on the Block the start Socket is drawn (LEFT(1) or RIGHT(2))
:type orientation: enumerate, required
"""
self.posSource_Orientation = orientation
# -----------------------------------------------------------------------------
def setDestinationOrientation(self, orientation):
"""
This method sets the orientation (position) of the destination (end)
Socket - in terms of where it is drawn on the block (LEFT/RIGHT) - to
the provided orientation.
:param orientation: where on the Block the end Socket is drawn (LEFT(1) or RIGHT(2))
:type orientation: enumerate, required
"""
self.posDestination_Orientation = orientation
# Todo add doc to describe purpose of this method (overrides the shape this drawn path takes, with custom path)
# This method is used by PyQt to interpret the bounding box area within which this line can be interacted with
# -----------------------------------------------------------------------------
def shape(self):
return self.polyPath()
# -----------------------------------------------------------------------------
def paint(self, painter, style, widget=None):
"""
This is an inbuilt method of QGraphicsItem, that is overwritten by ``GraphicsWire``.
This method is automatically called by the GraphicsView Class whenever even
a slight user-interaction is detected within the Scene.
It sets up the painter object and draws the line based on the path that
will be set by the specific implementation of GraphicsWire that is
calling paint. Then the painter will select the way the wire will be
drawn depending on whether or not the wire is selected.
:param painter: a painter that paints the path (line) of this GraphicsWire
:type painter: QPainter, automatically recognized and overwritten from this method
:param style: style of the painter (isn't used but must be defined)
:type style: QStyleOptionGraphicsItem, automatically recognized from this method
:param widget: the widget this class is being painted on (None)
:type widget: NoneType, optional, Defaults to None
"""
# Update the wire with the drawn intersection point(s)
try:
self.setPath(self.updatePath())
painter.setPen(self._pen if not self.isSelected() else self._pen_selected)
painter.setBrush(Qt.NoBrush)
painter.drawPath(self.path())
# if self.isSelected():
# painter.setRenderHint(QPainter.Antialiasing)
# painter.setBrush(QBrush(QColor("#FFFF4538")))
# painter.setPen(QPen(QColor(0, 0, 0, 255), 1.0, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
# for handle, rect in self.segment_handles.items():
# if rect:
# painter.drawRect(rect)
except Exception as e:
if self.FATAL_ERROR == False:
print(
"-------------------------------------------------------------------------"
)
print(
"Caught fatal exception while trying to draw wires. Please save your work."
)
print(
"-------------------------------------------------------------------------"
)
traceback.print_exc(file=sys.stderr)
self.FATAL_ERROR = True
# Todo - add docstring to this new method, add inline comments (makes custom polygon around drawn line)
# -----------------------------------------------------------------------------
def polyPath(self):
if self.wire.wire_coordinates:
newpolyPath = QPainterPath()
width = 8
self.wire_points = []
(p1x, p1y) = self.wire.wire_coordinates[0]
self.wire_points.append(QPointF(p1x, p1y))
for i, (x, y) in enumerate(self.wire.wire_coordinates):
if i == 0 or i == len(self.wire.wire_coordinates):
self.wire_points.append(QPointF(x, y + width))
else:
self.wire_points.append(QPointF(x + width, y + width))
for i, (x, y) in enumerate(reversed(self.wire.wire_coordinates)):
if i == 0 or i == len(self.wire.wire_coordinates):
self.wire_points.append(QPointF(x, y - width))
else:
self.wire_points.append(QPointF(x - width, y - width))
poly = QPolygonF(self.wire_points)
newpolyPath.addPolygon(poly)
return newpolyPath
else:
return self.updatePath()
# -----------------------------------------------------------------------------
def updatePath(self):
"""
This method is inherited and overwritten (currently) by the GraphicsWireDirect,
GraphicsWireBezier or GraphicsWireStep classes, which dictate the pathing
logic of the wire between the start and end socket.
"""
raise NotImplemented("This method is to be over written by child class")
# -----------------------------------------------------------------------------
def updateCursorSegments(self, segments):
"""
This method updates which mouse cursor should be displayed for each line segment of
the wire, depending on how many wire segments there are, which is given as an input.
:param segments: Number of line segments in this wire
:type segments: int
"""
# Upate cursor handles
if segments == 5:
self.handleCursors[self.handleHSeg1] = Qt.ArrowCursor
self.handleCursors[self.handleVSeg1] = Qt.SizeHorCursor
self.handleCursors[self.handleHSeg2] = Qt.SizeVerCursor
self.handleCursors[self.handleVSeg2] = Qt.SizeHorCursor
self.handleCursors[self.handleHSeg3] = Qt.ArrowCursor
self.handleSegments = 5
elif segments == 3:
self.handleCursors = self.handleCursors.fromkeys(
self.handleCursors.keys(), Qt.ArrowCursor
)
self.handleCursors[self.handleVSeg1] = Qt.SizeHorCursor
self.handleSegments = 3
else:
self.handleCursors = self.handleCursors.fromkeys(
self.handleCursors.keys(), Qt.ArrowCursor
)
self.handleSegments = segments
# -----------------------------------------------------------------------------
def updateLineSegments(self):
"""
This method uses the coordinates of the points this wire goes through, to
determine the coordinates that make up the horizontal and vertical line
segments of this wire (this logic is only applicable to GraphicsWireStep).
"""
# If the wire coordinates exist
if self.wire.wire_coordinates:
# Clear current horizontal and vertical segemnt lists, and clear cursor handles
self.wire.horizontal_segments.clear()
self.wire.vertical_segments.clear()
self.segment_handles = self.segment_handles.fromkeys(
self.segment_handles.keys(), None
)
# Find max number of segments in our line
max_seg = len(self.wire.wire_coordinates) - 1
# From first to 2nd last coordinate point of the wire
for counter in range(0, max_seg):
# Find top left and btm right points
top_left = min(
(
self.wire.wire_coordinates[counter],
self.wire.wire_coordinates[counter + 1],
)
)
btm_right = max(
(
self.wire.wire_coordinates[counter],
self.wire.wire_coordinates[counter + 1],
)
)
s = self.handleSize
# Line segments always alternate, from horizontal to vertical to horizontal etc.
# Even iterations of coordinate points are always the beginning to horizontal segments
# Append a line represented as ((x1,y2),(x2,y2)) to either horizontal or vertical line segment list
if counter % 2 == 0:
# Current and next coordinates are added into the horizontal line segments list
self.wire.horizontal_segments.append(
[
self.wire.wire_coordinates[counter],
self.wire.wire_coordinates[counter + 1],
]
)
# Update rectangles for horizontal segments
self.segment_handles[counter] = QRectF(
QPointF(top_left[0] + s, top_left[1] - s),
QPointF(btm_right[0] - s, btm_right[1] + s),
)
else:
# Current and next coordinates are added into the vertical line segments list
self.wire.vertical_segments.append(
[
self.wire.wire_coordinates[counter],
self.wire.wire_coordinates[counter + 1],
]
)
# Update rectangles for vertical segments
self.segment_handles[counter] = QRectF(
QPointF(top_left[0] - s, top_left[1] + s),
QPointF(btm_right[0] + s, btm_right[1] - s),
)
# Upate cursor handles
if self.handleSegments != max_seg:
self.updateCursorSegments(max_seg)
# -----------------------------------------------------------------------------
def updateWireCoordinates(self, new_coordinates):
"""
This method checks if the list of coordinate points this wire passes through,
has changed and needs to be updated. This method reduces the computational
resources required to otherwise re-write the list of coordinate points for
this wire, every time a user-interaction is detected within the GraphicsView.
:param new_coordinates: proposed coordinate points for this Wire
:type new_coordinates: list
"""
# Update current wire coordinates, if the new coordinates are different
# Also update the horizontal and vertical line segments
if new_coordinates != self.wire.wire_coordinates:
self.wire.wire_coordinates.clear()
self.wire.wire_coordinates = new_coordinates
self.updateLineSegments()
# If in DEBUG mode, this code will print the coordinates list and the
# separated horizontal and vertical line segments of this Wire
if DEBUG_COORDINATES:
print("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@")
if DEBUG_COORDINATES:
print("coordinates:", [self.wire.wire_coordinates])
if DEBUG_COORDINATES:
print("\nhorizontal lines:", [self.wire.horizontal_segments])
if DEBUG_COORDINATES:
print("\nvertical lines:", [self.wire.vertical_segments])
if DEBUG_COORDINATES:
print("\nline segments:")
if DEBUG_COORDINATES:
[
print("segment" + str(i) + ":", segment)
for i, segment in enumerate(self.segment_handles.items())
]
if DEBUG_COORDINATES:
print("-------------------------------------------------------")
# -----------------------------------------------------------------------------
def handleAt(self, point):
"""
Returns the resize handle below the given point.
"""
for (
k,
v,
) in self.segment_handles.items():
if v is None:
return None
elif v.contains(point):
return k
return None
# -----------------------------------------------------------------------------
def hoverMoveEvent(self, moveEvent):
"""
Executed when the mouse moves over the shape (NOT PRESSED).
"""
if self.isSelected():
handle = self.handleAt(moveEvent.pos())
# print("handle:", handle)
cursor = Qt.ArrowCursor if handle is None else self.handleCursors[handle]
self.setCursor(cursor)
super().hoverMoveEvent(moveEvent)
# -----------------------------------------------------------------------------
def hoverLeaveEvent(self, moveEvent):
"""
Executed when the mouse leaves the shape (NOT PRESSED).
"""
self.setCursor(Qt.ArrowCursor)
super().hoverLeaveEvent(moveEvent)
# -----------------------------------------------------------------------------
def mousePressEvent(self, mouseEvent):
"""
Executed when the mouse is pressed on the item.
"""
self.wire.setFocusOfWire()
self.handleSelected = self.handleAt(mouseEvent.pos())
if self.handleSelected is not None:
self.mousePressPos = mouseEvent.pos()
self.mousePressRect = self.segment_handles[self.handleSelected]
super().mousePressEvent(mouseEvent)
# -----------------------------------------------------------------------------
def mouseMoveEvent(self, mouseEvent):
"""
Executed when the mouse is being moved over the item while being pressed.
"""
if self.handleSelected is not None:
if not self.customlogicOverride:
self.customlogicOverride = True
self.interactiveResize(mouseEvent.pos())
self.wasMoved = True
self.wire.checkIntersections()
else:
super().mouseMoveEvent(mouseEvent)
# -----------------------------------------------------------------------------
def mouseReleaseEvent(self, mouseEvent):
"""
Executed when the mouse is released from the item.
"""
super().mouseReleaseEvent(mouseEvent)
self.handleSelected = None
self.mousePressPos = None
self.mousePressRect = None
self.update()
# If wire segments have been moved, update the variable within the model, to then
# update the title of the model, to indicate that there is unsaved progress
if self.wasMoved:
self.wasMoved = False
self.wire.scene.has_been_modified = True
self.wire.scene.history.storeHistory("Wire segment moved")
# -----------------------------------------------------------------------------
def interactiveResize(self, mousePos):
"""
Perform shape interactive resize.
"""
diff = QPointF(0, 0)
x_diff = mousePos.x() - self.mousePressPos.x()
y_diff = mousePos.y() - self.mousePressPos.y()
# Quantize resizing of grouping box
spacing = 10
x = round(x_diff / spacing) * spacing
y = round(y_diff / spacing) * spacing
# Calculate how far the mouse has moved from the point it was initially clicked from
fromCenter = self.mousePressRect.center()
toX = fromCenter.x() + x
toY = fromCenter.y() + y
custom_wire_coordinates = self.wire.wire_coordinates.copy()
self.prepareGeometryChange()
# If there are three segments, 1st and last segments cannot be moved (which are horizontally attacked to the sockets)
# so this leaves only the vertical segment connecting them. If that segment is dragged, adjust the points accordingly.
# If any other segments are being dragged, don't do anything
if self.handleSegments == 3:
if self.handleSelected == self.handleVSeg1:
# Only 1 vertical segment in this case, so take the first vert segment [0]
segment = self.wire.vertical_segments[0].copy()
# Copy that segment, and add the difference the mouse has moved to the x [0] coord of the two points that make up this segment
for i, point in enumerate(segment.copy()):
new_point = list(point)
new_point[0] = toX
segment[i] = tuple(new_point)
# Override the points making up this semgent in the temporary wire_coordinates -> 2nd and 3rd points [1:3]
custom_wire_coordinates[1:3] = segment
# Otherwise if there are five segments, since first and last segment cannot be moved, this leaves us with 3 segments which can
# Two vertical segments, and one horizontal segment. If any of those three are selected, adjust the points accordingly.
elif self.handleSegments == 5:
if self.handleSelected == self.handleHSeg2:
# There are three horizontal segments to choose from, 1st and 3rd (last) cannot be moved, this means our segment is #2 [1].
segment = self.wire.horizontal_segments[1].copy()
# Copy that segment, and add the difference the mouse has moved to the y [1]) coord of the two points that make up this segment
for i, point in enumerate(segment.copy()):
new_point = list(point)
new_point[1] = toY
segment[i] = tuple(new_point)
# Override the points making up this semgent in the temporary wire_coordinates -> 3rd and 4th points [2:4]
custom_wire_coordinates[2:4] = segment
elif self.handleSelected in [self.handleVSeg1, self.handleVSeg2]:
# There are two vertical segments to choose from, either can be moved as they do not attach directly to a socket.
if self.handleSelected == self.handleVSeg1:
segment = self.wire.vertical_segments[0].copy()
else:
segment = self.wire.vertical_segments[1].copy()
# Copy that segment, and add the difference the mouse has moved to the x [0]) coord of the two points that make up this segment
for i, point in enumerate(segment.copy()):
new_point = list(point)
new_point[0] = toX
segment[i] = tuple(new_point)
# Override the points making up this semgent in the temporary wire_coordinates. Since we can either select the 1st or 2nd
# vertical segment, these points correspond to 2nd and 3rd points [1:3] or the 4th and 5th points [3:5]
if self.handleSelected == self.handleVSeg1:
custom_wire_coordinates[1:3] = segment
else:
custom_wire_coordinates[3:5] = segment
self.updateWireCoordinates(custom_wire_coordinates)
self.updatePath()
# -----------------------------------------------------------------------------
def adjustCustomRoutingWireCoordinates(self):
# When both blocks connected to a wire are being moved, both start and end sockets
# that this wire is connected to will move the same amount. So we will just grab
# the data from the start_socket.
# Start sockets could be an input or output socket, so find its true position w.r.t its block
start_point = (
self.wire.start_socket.node.grBlock.pos()
+ self.wire.start_socket.grSocket.pos()
)
start_coords = (start_point.x(), start_point.y())
# print("\nsocket coords:", [start_coords])
# print("wire coords:", self.wire.wire_coordinates)
# Wire can be drawn from either input to output socket, or output to input socket. This means
# our start_socket can either be the first or last point in the wire.wire_coordinates list
# Check which of these are closest to our start_socket_coords, then take the difference between those
dist1 = dist(start_coords, self.wire.wire_coordinates[0])
dist2 = dist(start_coords, self.wire.wire_coordinates[-1])
# Take difference between start_socket_coords and whichever point is closest from wire.wire_coordinates
if dist1 < dist2:
diff = [
start_coords[0] - self.wire.wire_coordinates[0][0],
start_coords[1] - self.wire.wire_coordinates[0][1],
]
else:
diff = [
start_coords[0] - self.wire.wire_coordinates[-1][0],
start_coords[1] - self.wire.wire_coordinates[-1][1],
]
# print("difference:", diff)
# If there is a difference, then adjust the wire coordinates
if diff == [0, 0]:
return
# Adjust wire.wire_coordinates by subtracting that diff from each point
new_wire_coordinates = []
for point in self.wire.wire_coordinates:
new_point = (point[0] + diff[0], point[1] + diff[1])
new_wire_coordinates.append(new_point)
# print("old wire coords before:", self.wire.wire_coordinates)
# print("new_wire_coords: ", new_wire_coordinates)
# Once points are adjusted, replace the wire.wire_coordinates list with this list
self.updateWireCoordinates(new_wire_coordinates)
# print("old wire coords after: ", self.wire.wire_coordinates)
class GraphicsWireDirect(GraphicsWire):
"""
The ``GraphicsWireDirect`` Class extends the ``GraphicsWire`` Class from BdEdit.
This class is responsible for providing a straight painter path that the
GraphicsWire class should follow when drawing the Wire. This wire type will draw
a straight line between two Sockets. It will take the shortest distance between
these two points, and will go through other Blocks to do so.
"""
# -----------------------------------------------------------------------------
def updatePath(self):
"""
This method creates a painter path that connects two points (start/end sockets)
with a straight line.
"""
# A straight line is drawn between the two provided points
path = QPainterPath(QPointF(self.posSource[0], self.posSource[1]))
path.lineTo(self.posDestination[0], self.posDestination[1])
return path
class GraphicsWireBezier(GraphicsWire):
"""
The ``GraphicsWireBezier`` Class extends the ``GraphicsWire`` Class from BdEdit.
This class is responsible for providing a bezier painter path that the
GraphicsWire class should follow when drawing the Wire. This wire type option
looks good in the first direction it is drawn (e.g. left-to-right) but will not
wrap logically when blocks are flipped or moved past each other (e.g. such that
the wire would now be right-to-left).
"""
# -----------------------------------------------------------------------------
def updatePath(self):
"""
This method creates a painter path that connects two points (start/end sockets)
with a bezier line. This line is drawn as a cubic (think sine wave).
"""
# The start and end coordinates are grabbed into variables s and d
s = self.posSource
d = self.posDestination
# This code decides the direction the bezier should point from the start socket
# either left or right of the start socket.
dist = (d[0] - s[0]) * 0.5
if s[0] > d[0]:
dist *= -1
# Then a cubic line is drawn between the two provided points
path = QPainterPath(QPointF(self.posSource[0], self.posSource[1]))
path.cubicTo(
s[0] + dist,
s[1],
d[0] - dist,
d[1] - dist,
self.posDestination[0],
self.posDestination[1],
)
return path
class GraphicsWireStep(GraphicsWire):
"""
The ``GraphicsWireStep`` Class extends the ``GraphicsWire`` Class from BdEdit.
This class is responsible for providing a stepped painter path that the
GraphicsWire class should follow when drawing the Wire. This is the default wire
style used within BdEdit, and has the most supporting logic built around it.
This wire option draws a straight line between two sockets when the two blocks
side by side at equal heights, are connected with a wire in the middle.
Otherwise if the two blocks are at varying heights, a stepped line will be drawn
from the starting socket, with 90 degree bends at each point the wire must turn
to reach the end socket.
"""
def updatePath(self):
if self.customlogicOverride:
self.adjustCustomRoutingWireCoordinates()
# The path of the wire is set to be drawn with either
# custom routing logic or with hard-coded routing logic
for i, (x, y) in enumerate(self.wire.wire_coordinates):
if i == 0:
path = QPainterPath(QPointF(x, y))
elif i == len(self.wire.wire_coordinates):
path.lineTo(x, y)
path.moveTo(x, y)
else:
path.lineTo(x, y)
return path
else:
return self.wireRoutingLogic()
# -----------------------------------------------------------------------------
def wireRoutingLogic(self):
"""
This method creates a painter path that connects two points (start/end sockets)
with a stepped line. This path is returned as a straight line if two blocks
at equal heights, are connected with a wire on the inside of each of the blocks.
Otherwise the path is returned as a stepped line with 90 degree bends at each
point the wire must turn.
The logic for when this wire should turn is calculated internally. Please refer
to the technical document accompanying the BdEdit code for visual explanations
for how this logic is determined.
"""
try:
# _____________________________________ Preparing Wire related variables ______________________________________
# List into which the coordinate points of the wire will be appended into when
# this wire is updated. This will be compared against the current list of this
# wires' coordinates, to check if it needs to be updated
temporary_wire_coordinates = []
# This variable prevents a stepped wire from being drawn until it is connected
# to the end socket. Until then a straight line will be drawn
wire_completed = False
# Block padding is the space at which wires will be wrapped around blocks
block_padding = 20
# The title height is extracted from the block this wire starts from
title_height = self.wire.start_socket.node.grBlock.title_height - 5
# __________________________________ Extracting Logic of Start/End Sockets ____________________________________
# The global (scene) x,y coordinates of the source (start) and destination (end) sockets are extracted
sx = self.posSource[0]
sy = self.posSource[1]
dx = self.posDestination[0]
dy = self.posDestination[1]
# The horizontal distance between these two sockets is found
xDist = (dx - sx) / 2
# The index at which the start socket is drawn on its block is extracted + 1
# (0th index will be our first index, as this variable is used as a multiplier)
s_index = self.wire.start_socket.index + 1
# Dimensions of the start sockets' block are extracted
source_block_width = self.wire.start_socket.node.width
source_block_height = self.wire.start_socket.node.height
# The local (in reference to its block) x-y coordinates of the start socket
s_Offset = self.wire.start_socket.getSocketPosition()
# Same logic (as above) is extracted for the destination (end) socket if it has been set
if self.wire.end_socket is not None:
d_index = self.wire.end_socket.index + 1
destination_block_width = self.wire.end_socket.node.width
destination_block_height = self.wire.end_socket.node.height
d_Offset = self.wire.end_socket.getSocketPosition()
else:
d_index = 0
destination_block_width = 0
destination_block_height = 0
d_Offset = [0, 0]
# The previous temporary coordinates of this wire are cleared, and the new start point coordinate is added
temporary_wire_coordinates.clear()
temporary_wire_coordinates.append((sx, sy))
# ########################################### Start of Wire Logic ##########################################
# ====================================== If Wire hasn't been completed =====================================
if self.wire.end_socket is None:
# If two sockets haven't been connected yet
# Don't do anything, start and end points of the path have already been defined, so a straight line will be drawn
if DEBUG:
print("Wire style: O")
pass
# ========================= Start & End Sockets are on the same side of two Blocks =========================
elif self.posSource_Orientation == self.posDestination_Orientation:
# If sockets are both on the same side (both coming out of the left or right)
# ----------------------------------- Start Socket LEFT OF End Socket ----------------------------------
if sx < dx:
# - - - - - - - - - - - - Continue with Extracted Logic of Start/End Sockets - - - - - - - - - - - - -
# Continue path from source
# Destination_block & Source_block are kept the same
pass
# ------------------------------ Start Socket EQUAL or RIGHT OF End Socket -----------------------------
else:
# - - - - - - - - - - - Re-Extract Logic of Start/End Sockets (Switching them) - - - - - - - - - - - -
# Use the same logic as for above, but swap positions of start socket with end socket
sx, sy = self.posDestination[0], self.posDestination[1]
dx, dy = self.posSource[0], self.posSource[1]
# Destination_block & Source_block = node of start_socket and end_socket respectively
d_index = self.wire.start_socket.index + 1
destination_block_width = self.wire.start_socket.node.width
destination_block_height = self.wire.start_socket.node.height
# Switch the indexes of the sockets
if self.wire.end_socket is not None:
s_index = self.wire.end_socket.index + 1
source_block_width = self.wire.end_socket.node.width
source_block_height = self.wire.end_socket.node.height
else:
s_index = 0
source_block_width = 0
source_block_height = 0
# Restart path from destination
temporary_wire_coordinates.clear()
temporary_wire_coordinates.append((sx, sy))
# ------------------------------- End Socket on RHS of Destination Block -------------------------------
if self.posDestination_Orientation == RIGHT:
# xDist is from RHS of source block, to LHS of destination block
xDist = (dx - destination_block_width - sx) / 2
# Top of the destination block is above source block
# Should be dy > sy, but graphics view draws the y-axis inverted
if dy - d_Offset[1] - (d_index * block_padding) < sy:
# Bottom of destination block is above top of source block OR
# LHS of destination block is further left than RHS of source block
# Wire from multiple sockets spaced from bottom of destination block at index (no overlap)
if (
dy
- d_Offset[1]
+ destination_block_height
+ title_height
+ (d_index * block_padding)
< sy
) or (sx + xDist <= sx + (block_padding / 2)):
if DEBUG:
print("Wire style: A")
# Draw C (inverted equivalent) line from S up to D, clipped to RHS of destination block
# ----------------------
# (d-block)-<-|
# |
# (s-block)->------|
# ----------------------
temporary_wire_coordinates.append(
(dx + (d_index * block_padding), sy)
)
temporary_wire_coordinates.append(
(dx + (d_index * block_padding), dy)
)
# Bottom of destination block is equal to or below top of source block
else:
if DEBUG:
print("Wire style: B")
# Draw wrapped line between source and destination block, then above and around destination block
# --------------------------------
# |---------------|
# | |
# | (d-block)-<-|
# |
# (s-block)->-|
# --------------------------------
temporary_wire_coordinates.append((sx + xDist, sy))
temporary_wire_coordinates.append(
(
sx + xDist,
dy - d_Offset[1] - (d_index * block_padding),
)
)
temporary_wire_coordinates.append(
(
dx + d_index * block_padding,
dy - d_Offset[1] - (d_index * block_padding),
)
)
temporary_wire_coordinates.append(
(dx + d_index * block_padding, dy)
)
# Top of destination block is equal to or below source block socket
else:
if DEBUG:
print("Wire style: C")
# Draw C (inverted equivalent) line from S down to D, clipped to RHS of destination block
# ------------------------
# (s-block)->---------|
# |
# (d-block)-<-|
# ------------------------
temporary_wire_coordinates.append(
(dx + d_index * block_padding, sy)
)
temporary_wire_coordinates.append(
(dx + d_index * block_padding, dy)
)
# ------------------------------- End Socket on LHS of Destination Block -------------------------------
else:
# xDist is from RHS of source block, to LHS of destination block
xDist = (dx - (sx + source_block_width)) / 2
# Should be sy > dy, but graphics view draws the y-axis inverted
# Top of source block is above destination block
if sy - s_Offset[1] - (s_index * block_padding) < dy:
# Bottom of source block is above top of destination block OR
# RHS of source block further left than LHS of destination block
# Wire from multiple sockets spaced from bottom of source block at index (no overlap)
if (
sy
- s_Offset[1]
+ source_block_height
+ title_height
+ (s_index * block_padding)
< dy
) or (dx + xDist <= dx + (block_padding / 2)):
if DEBUG:
print("Wire style: D")
# Draw C line from S down to D, clipped to LHS of source block
# ----------------------
# |--<-(s-block)
# |
# |----->-(d-block)
# ----------------------
temporary_wire_coordinates.append(
(sx - (s_index * block_padding), sy)
)
temporary_wire_coordinates.append(
(sx - (s_index * block_padding), dy)
)
# Bottom of source block is equal to or below top of destination block
else:
if DEBUG:
print("Wire style: E")
# Draw wrapped line above and around the source block, then between the source and destination block
# --------------------------------
# |---------------|
# | |
# |-<-(s-block) |
# |
# |->-(d-block)
# --------------------------------
temporary_wire_coordinates.append(
(sx - s_index * block_padding, sy)
)
temporary_wire_coordinates.append(
(
sx - s_index * block_padding,
sy - s_Offset[1] - (s_index * block_padding),
)
)
temporary_wire_coordinates.append(
(
sx + source_block_width + xDist,
sy - s_Offset[1] - (s_index * block_padding),
)
)
temporary_wire_coordinates.append(
(sx + source_block_width + xDist, dy)
)
# Top of source block is equal to or below destination block
else:
if DEBUG:
print("Wire style: F")
# Draw C line from S up to D, clipped to LHS of source block
# --------------------
# |------->-(d-block)
# |
# |-<-(s-block)
# --------------------
temporary_wire_coordinates.append(
(sx - s_index * block_padding, sy)
)
temporary_wire_coordinates.append(
(sx - s_index * block_padding, dy)
)
# Update boolean that wire is completed, as to get here, the end point of the wire must be dropped
wire_completed = True
# ======================== Start & End Sockets are on opposite sides of two blocks =========================
elif self.posSource_Orientation != self.posDestination_Orientation:
# Otherwise sockets are on different sides (out from left into right, or out of right into left)
# -------------------------------- Start Socket on LHS of Source Block ---------------------------------
if self.posSource_Orientation == LEFT:
# - - - - - - - - - - - - Continue with Extracted Logic of Start/End Sockets - - - - - - - - - - - - -
# Continue path from source
# Destination_block & Source_block are kept the same
xDist = (sx - dx) / 2
# -------------------------------- Start Socket on RHS of Source Block ---------------------------------
else:
# - - - - - - - - - - - Re-Extract Logic of Start/End Sockets (Switching them) - - - - - - - - - - - -
# Use the same logic as for above, but swap positions of start socket with end socket
sx, sy = self.posDestination[0], self.posDestination[1]
dx, dy = self.posSource[0], self.posSource[1]
# Destination_block & Source_block = node of start_socket and end_socket respectively
d_index = self.wire.start_socket.index + 1
destination_block_width = self.wire.start_socket.node.width
destination_block_height = self.wire.start_socket.node.height
d_Offset = self.wire.start_socket.getSocketPosition()
# Switch the indexes of the sockets
if self.wire.end_socket is not None:
s_index = self.wire.end_socket.index + 1
source_block_width = self.wire.end_socket.node.width
source_block_height = self.wire.end_socket.node.height
s_Offset = self.wire.end_socket.getSocketPosition()
else:
s_index = 0
source_block_width = 0
source_block_height = 0
s_Offset = [0, 0]
# Restart path from destination
temporary_wire_coordinates.clear()
temporary_wire_coordinates.append((sx, sy))
# ---------------------------------- Start Socket RIGHT OF End Socket ----------------------------------
if sx > dx:
# If start socket is not on same height as end socket
# Otherwise a straight line will be drawn when this logic is passed through
if sy != dy:
if DEBUG:
print("Wire style: G")
# Draw normal step line
# ---------------------------
# |-<-(s-block)
# |
# (d-block)-<-|
# ---------------------------
temporary_wire_coordinates.append((sx - xDist, sy))
temporary_wire_coordinates.append((sx - xDist, dy))
# ------------------------------ Start Socket EQUAL or LEFT OF End Socket ------------------------------
else:
# Source block is above destination block
if sy - s_Offset[1] - (s_index * block_padding) < dy - d_Offset[
1
] - (d_index * block_padding):
# Distance between bottom of source block and top of destination block
yDist = (
(dy - d_Offset[1])
- (sy - s_Offset[1] + source_block_height + title_height)
) / 2
# Bottom of source block is above top of destination block OR
# --
if (sy - s_Offset[1] + source_block_height + title_height) < (
dy - d_Offset[1] - block_padding
):
if DEBUG:
print("Wire style: H")
# Draw S line
# |---<-(s-block)
# |
# |--------------|
# |
# (d-block)-<--|
# ------------------
temporary_wire_coordinates.append(
(sx - (s_index * block_padding), sy)
)
temporary_wire_coordinates.append(
(
sx - (s_index * block_padding),
dy - d_Offset[1] - yDist,
)
)
temporary_wire_coordinates.append(
(
dx + (d_index * block_padding),
dy - d_Offset[1] - yDist,
)
)
temporary_wire_coordinates.append(
(dx + (d_index * block_padding), dy)
)
# Bottom of source block is at level with or below top of destination block
else:
# RHS of destination block is further left than RHS of source block
if (dx + block_padding) < (
sx + source_block_width + block_padding
):
if DEBUG:
print("Wire style: I")
# Draw line going around the top of the source block, clipped to RHS of source block + padding
# --------------------------------------------------
# |--------------| |--------------|
# | | | |
# |-<-(s-block) | or |-<-(s-block) |
# (d-block)-<-------| (d-block)-<-|
# --------------------------------------------------
temporary_wire_coordinates.append(
(sx - (s_index * block_padding), sy)
)
temporary_wire_coordinates.append(
(
sx - (s_index * block_padding),
sy - s_Offset[1] - (s_index * block_padding),
)
)
temporary_wire_coordinates.append(
(
sx
+ source_block_width
+ (s_index * block_padding),
sy - s_Offset[1] - (s_index * block_padding),
)
)
temporary_wire_coordinates.append(
(
sx
+ source_block_width
+ (s_index * block_padding),
dy,
)
)
# path.lineTo(sx + source_block_width + block_padding, sy - s_Offset[1] - (s_index * block_padding))
# path.lineTo(sx + source_block_width + block_padding, dy)
# RHS of destination block is equal to or right of RHS of source block
else:
if DEBUG:
print("Wire style: J")
# Draw line going around the top of the source block, clipped to RHS of destination block + padding
# -------------------------------------------------------------------------
# |-----------------------------| |---------------------------|
# | | | |
# |-<-(s-block) | or |-<-(s-block) (d-block)-<-|
# (d-block)-<-|
# -------------------------------------------------------------------------
temporary_wire_coordinates.append(
(sx - (s_index * block_padding), sy)
)
temporary_wire_coordinates.append(
(
sx - (s_index * block_padding),
sy - s_Offset[1] - (s_index * block_padding),
)
)
temporary_wire_coordinates.append(
(
dx + (d_index * block_padding),
sy - s_Offset[1] - (s_index * block_padding),
)
)
temporary_wire_coordinates.append(
(dx + (d_index * block_padding), dy)
)
# Source block is below destination block
else:
# Distance between top of source block and bottom of destination block
yDist = (
(sy - s_Offset[1])
- (
dy
- d_Offset[1]
+ destination_block_height
+ title_height
)
) / 2
# Top of source block is below bottom of destination block OR
# --
if (sy - s_Offset[1] - block_padding) > (
dy - d_Offset[1] + destination_block_height + title_height
):
if DEBUG:
print("Wire style: K")
# Draw Z line
# -----------------------
# (d-block)-<--|
# |
# |------------------|
# |
# |-<-(s-block)
# -----------------------
temporary_wire_coordinates.append(
(sx - (s_index * block_padding), sy)
)
temporary_wire_coordinates.append(
(
sx - (s_index * block_padding),
sy - yDist - s_Offset[1],
)
)
temporary_wire_coordinates.append(
(
dx + (s_index * block_padding),
sy - yDist - s_Offset[1],
)
)
temporary_wire_coordinates.append(
(dx + (s_index * block_padding), dy)
)
# Top of source block is at level with or above bottom of destination block
else:
# LHS of destination is further left than LHS of source block
if (dx - destination_block_width - block_padding) < (
sx - block_padding
):
if DEBUG:
print("Wire style: L")
# Draw line going around the top of the destination block, clipped to the LHS of destination block minus padding
# ------------------------
# |--------------|
# | |
# | (d-block)-<-|
# |
# |----------<-(s-block)
# ------------------------
temporary_wire_coordinates.append(
(
dx
- destination_block_width
- (s_index * block_padding),
sy,
)
)
temporary_wire_coordinates.append(
(
dx
- destination_block_width
- (s_index * block_padding),
dy - d_Offset[1] - (d_index * block_padding),
)
)
temporary_wire_coordinates.append(
(
dx + d_index * block_padding,
dy - d_Offset[1] - (d_index * block_padding),
)
)
temporary_wire_coordinates.append(
(dx + d_index * block_padding, dy)
)
# LHS of destination is equal to or right of LHS of source block
else:
if DEBUG:
print("Wire style: M")
# Draw line going around the top of the destination block, clipped to the LHS of source block minus padding
# ----------------------
# |----------------|
# | |
# | (d-block)-<-|
# |
# |-<-(s-block)
# ----------------------
temporary_wire_coordinates.append(
(sx - s_index * block_padding, sy)
)
temporary_wire_coordinates.append(
(
sx - s_index * block_padding,
dy - d_Offset[1] - (d_index * block_padding),
)
)
temporary_wire_coordinates.append(
(
dx + d_index * block_padding,
dy - d_Offset[1] - (d_index * block_padding),
)
)
temporary_wire_coordinates.append(
(dx + d_index * block_padding, dy)
)
# Update boolean that wire is completed, as to get here, the end point of the wire must be dropped
wire_completed = True
# ############################################ End of Wire Logic ###########################################
# Finally the Wire is finished, by connecting the path to the destination (end) Socket coordinates
# that coordinate is also added as the final coordinate point of the wire to the temporary coordinates list
temporary_wire_coordinates.append((dx, dy))
# The path of the wire is set to be drawn under the path logic that has just been calculated
for i, (x, y) in enumerate(temporary_wire_coordinates):
if i == 0:
path = QPainterPath(QPointF(x, y))
elif i == len(temporary_wire_coordinates):
path.lineTo(x, y)
path.moveTo(x, y)
else:
path.lineTo(x, y)
# If the wire has been dropped on a destination socket (and is not being dragged around), update its coordinates
if wire_completed:
self.updateWireCoordinates(temporary_wire_coordinates)
return path
except Exception as e:
if self.FATAL_ERROR == False:
print(
"------------------------------------------------------------------------------------"
)
print(
"Caught fatal exception while trying to calculate wire bends. Please save your work."
)
print(
"------------------------------------------------------------------------------------"
)
traceback.print_exc(file=sys.stderr)
self.FATAL_ERROR = True
================================================
FILE: bdsim/bdedit/block_importer.py
================================================
# !/usr/bin/env python
# -*- coding: utf-8 -*-
import re
import inspect
import copy
import numpy as np
import importlib.util
import inspect
import os.path
from pathlib import Path
from bdsim.bdedit.block import blockname, blocklist, Block
# from examples import docstring_parser as parser
import bdsim
def import_blocks(scene, window):
size_map = {
"InPort": [50, 100],
"OutPort": [50, 100],
"SubSystem": [200, 150],
"DiffSteer": [150, 100],
"VehiclePlot": [125, 100],
"MultiRotor": [125, 100],
"IDyn": [125, 100],
"FDyn": [125, 100],
"Tr2Delta": [125, 100],
"MultiRotorMixer": [125, 100],
"JTraj": [125, 100],
}
# Make in/out labels parameter for subsystem blocks
inlabels_param = [
"inport labels",
list,
None,
[["type", [type(None), list]]],
"List of names for respective inport sockets",
]
outlabels_param = [
"outport labels",
list,
None,
[["type", [type(None), list]]],
"List of names for respective outport sockets",
]
# block_list = parser.docstring_parser()
sim = bdsim.BDSim() # create simulator
block_list = sim._blocklibrary
block_library = []
imported_block_groups = []
# for i, block in enumerate(block_list.items()):
for block_type, block_ds in sim.blockinfo().items():
# if i == 4:
# blocks is a dic of tuples
# (block_type, {block_docstring_data})
# print(f"reading definition of block {block_type}")
# block_type = block[0].upper() # Block type
# block_ds = block[1] # Block docstring
# block_name = block_type.lower().capitalize() + " Block"
block_name = block_ds["classname"] + " Block"
block_classname = block_ds["classname"]
block_parentclass = block_ds["blockclass"]
block_path = block_ds["path"]
block_icon = os.path.join(block_path[0], "Icons", block_type.lower() + ".png")
# # Make a block instance of the given class
# try:
# # Grab number of input/output sockets for block, once it has been instantiated
# if block_ds["nin"] < 0 or block_ds["nout"] < 0:
# block_instance = block_ds["class"]()
# block_inputsNum = block_instance.nin
# block_outputsNum = block_instance.nout
# else:
# block_inputsNum = block_ds["nin"]
# block_outputsNum = block_ds["nout"]
#
# except Exception as e:
# # When exception occurs here it is related to an assertion being raised in bdsim
# # This can be ignored as we only need the nin/nout values once the block is instantiated
# block_inputsNum = block_instance.nin
# block_outputsNum = block_instance.nout
# Grab values assigned to this block's nin and nout class variables
# If the variables are >= 0, copy the values, otherwise if negative, set equal to 1 (aside from some blocks)
# If nin or nout not defined as a class variable, assign value of 0 (no inputs or outputs)
if hasattr(block_ds["class"], "nin"):
if block_name in ["Sum Block", "Prod Block", "Traj Block"]:
if block_name == "Traj Block":
block_inputsNum = 0
else:
block_inputsNum = 2
else:
if block_ds["class"].nin > -1:
block_inputsNum = block_ds["class"].nin
else:
block_inputsNum = 1
else:
block_inputsNum = 0
if hasattr(block_ds["class"], "nout"):
if block_ds["class"].nout > -1:
block_outputsNum = block_ds["class"].nout
else:
block_outputsNum = 1
else:
block_outputsNum = 0
# Grab the names of the input/output sockets
block_input_names, block_output_names = [], []
if hasattr(block_ds["class"], "inlabels"):
for input_socket_name in block_ds["class"].inlabels:
block_input_names.append(input_socket_name)
if hasattr(block_ds["class"], "outlabels"):
for output_socket_name in block_ds["class"].outlabels:
block_output_names.append(output_socket_name)
# Reconstruct URL from block type and path
block_group = block_ds["module"].split(".")[-1]
try:
block_url = block_ds["url"]
except KeyError:
block_url = None
block_parameters = (
[]
) # Once name, type, value, restrictions are extracted, this will be populated
for param in block_ds["params"].items():
# Extract parameter name
param_name = param[0]
if param[1][1]:
param_tooltip = param[1][1]
else:
param_tooltip = ""
# Extract parameter type
# Split string based on white spaces
# if one type - no white spaces
# if multiple types - several white spaces
try:
param_type_docstring = param[1][0].split()
# Remove any left over commas or dashes (shouldn't be needed for type)
for i, item in enumerate(param_type_docstring):
param_type_docstring[i] = item.strip(",-.")
# 1st value should be the type, with following values being either
# * other accepted types,
# * the optional keyword (also indicates if value should have a default),
# * or human-readable string
# 1. go through each word in the split string, searching for likely terms (sequence, string, etc)
# 2. match found strings to their desired interpretation, sequence = list/tuple/range, string = str
# 3. create list of strings matched to required types
# 4. evaluate and assign first item from that list of types, as the param type
# 5. create list for holding found restrictions
# 5.
param_restrictions = []
# ---------------------------------------------------------------------------------------
# Section for extracting parameter type information (and restriction if relating to type)
# ---------------------------------------------------------------------------------------
# 3.
found_types = []
found_size_restrictions = []
found_range_restrictions = []
found_symbol_restrictions = []
found_keyword_restrictions = []
# 1.
for item in param_type_docstring:
# Go through and try to evaluate the first type, if it works assign that as the param type
try:
# 2.
param_type = eval(item)
# Check to see if evaluated item is NOT a class type, e.g. NOT .
# In this case, wrap the evaluated item in type()
if not inspect.isclass(param_type):
found_types.append(type(param_type))
# This should only occur for the callable or any, type, but just to be safe we can check that it is one of those
# and then append the 'str' type to pass through any user input from bdedit, as this will be validated in bdsim.
if isinstance(param_type, type(callable)):
found_types.append(str)
# If a tuple type has been found, convert this to list
if issubclass(param_type, tuple):
param_type = list
# Otherwise, if item is in the form of a string, append that value to list of found types
else:
found_types.append(param_type)
# If evaluation fails - most likely human readible string instead of actual type
except:
regex_search = re.findall(
r"array_like\([0-9]\)|array_like", item
)
# If current word is array_like
if regex_search:
# Search each array_like word found in type docstring, looking for size restriction
for match in regex_search:
element_restriction_match = re.findall(r"[0-9]", match)
# If an element size restriction has been detected
if element_restriction_match:
# If size restriction is already entered, this will stop it from being entered multiple times
restriction_to_insert = eval(
element_restriction_match[0]
)
if (
not restriction_to_insert
in found_size_restrictions
):
found_size_restrictions.append(
restriction_to_insert
)
# Todo - add size 0 if no regex size found
else:
pass
# If array_like has already been added, this will stop it from being entered multiple times
# Lists can be interpreted easily and converted into a numpy array, so in JSON these will be stored as lists
# type_to_insert = type(np.array([]))
# If size restrictions were found, then this parameter is limited to being either a list of dict
if found_size_restrictions:
types_to_insert = [list, dict]
# If no size restriction was found, then parameter retains all of array_like properties
else:
types_to_insert = [list, dict, int, float]
for found_type in types_to_insert:
if found_type not in found_types:
found_types.append(found_type)
elif item.lower() in ["string"]:
if str not in found_types:
found_types.append(str)
elif item.lower() in ["sequence", "string"]:
# 2.
if list not in found_types:
found_types.append(list)
else:
pass
# 4.
# If any known types have been found, set the parameter type
if found_types:
# Extract first detected type as the default type
param_type = found_types[0]
else:
# If no param type was found from the docstrings, this parameter most likely has a bdsim defined class
# These will be passed through as a str type, and evaluated on bdsim's end. If any issues occur, it is
# the user's job to ensure a suitable and meaningful value is entered for the parameter
param_type = str
found_types.append(str)
# -----------------------------------------------------------------------------------------
# Section for extracting parameter value information (and restriction if relating to value)
# -----------------------------------------------------------------------------------------
param_value = None
# Extract parameter value information
param_value_docstring = param[1][1].split()
# String docstring of commas
for i, item in enumerate(param_value_docstring):
param_value_docstring[i] = item.strip(",.")
# Parse the docstring ignoring words until finding a known "defaults to:"
for i in range(0, len(param_value_docstring) - 1):
if param_value_docstring[i] in ["range"]:
# This parameter must be within a certain range, extract the provided range values
# These should be in the form of "range [a,b]"
# Hence we can check if evaluating the word after range gives a list of length 2
try:
next_item = eval(param_value_docstring[i + 1])
if isinstance(next_item, list) and len(next_item) == 2:
# Add a,b of range to restriction items
found_range_restrictions.append(next_item[0])
found_range_restrictions.append(next_item[1])
else:
# Either not list or greater than 2, so unexpected format, return error
# found_range_restrictions.append("Unexpected format for: range restriction")
print(
"Unexpected format for: range restriction. Occured in:",
block_name,
param_name,
)
except:
# Word cannot be evaluated
# found_range_restrictions.append("Unexpected format for: range restriction")
print(
"Unexpected format for: range restriction. Occured in:",
block_name,
param_name,
)
if param_value_docstring[i] in [
"accepted"
] and param_value_docstring[i + 1] in ["characters:"]:
# Value is restricted to being certain characters, these are seperated by the word 'or'
# Iterate through every 2nd value after 'accepted characters:' (seperated by 'or')
for j in range(i + 2, len(param_value_docstring), 2):
# If special character (.isalnum() returns False), append to list of detected signs
if not param_value_docstring[j].isalnum():
found_symbol_restrictions.append(
param_value_docstring[j]
)
# If the next value isn't 'or', we have reached end of character list
if param_value_docstring[j + 1] not in ["or"]:
break
if param_value_docstring[i] in [
"defaults"
] and param_value_docstring[i + 1] in ["to"]:
# Value only has 1 default, which should follow after the word 'to'
# Try to evaluate value, if successful, this is some form of non string
try:
param_value = eval(param_value_docstring[i + 2])
# If unsuccesful, trying to eval a string, so set default value as str instead
except NameError:
param_value = param_value_docstring[i + 2]
elif param_value_docstring[i] in ["one"] and param_value_docstring[
i + 1
] in ["of:"]:
# Value has list of possible options, parse list to find value after which is '[default]'
found_default_value = False
for j in range(i + 2, len(param_value_docstring)):
# Append found value (if not '[default]', to list of keyword restrictions)
if param_value_docstring[j] not in ["[default]"]:
found_keyword_restrictions.append(
param_value_docstring[j].strip("'").lower()
)
# Check if this is the default value, (next value should say '[default]')
if not found_default_value and param_value_docstring[
j + 1
] in ["[default]"]:
# Default value found in list of possible values
# Try to evaluate value, if successful, then some form of non string
try:
param_value = eval(param_value_docstring[j])
# If unsuccesful, trying to eval a string, so set default value as str instead
except NameError:
param_value = param_value_docstring[j]
found_default_value = True
# If no defualt value was found, param_value will stay as None for safety
# if not found_default_value:
# param_value = None
# Important break!
# Once the inner loop has gone through the remainder of the words from the docstring, and
# found the default value and the other keywords, we need to break out of the outer loop, to
# continue to the next parameter
break
# If any keyword restrictions were found
if found_keyword_restrictions:
restriction = ["keywords"]
# Append the found keyword restrictions into the restriction
restriction.append(found_keyword_restrictions)
param_restrictions.append(restriction)
# If any range restrictions were found
if found_range_restrictions:
restriction = ["range"]
# Append the found range restrictions into the restriction
restriction.append(found_range_restrictions)
param_restrictions.append(restriction)
# If any size restrictions were found
if found_size_restrictions:
restriction = ["size"]
# Append the found size restrictions into the restriction
restriction.append(found_size_restrictions)
param_restrictions.append(restriction)
# If any symbol restrictions were found
if found_symbol_restrictions:
restriction = ["symbol"]
# Append the found symbol restrictions into the restriction
restriction.append(found_symbol_restrictions)
param_restrictions.append(restriction)
# Check if parameter value is None, if so, add NoneType to type restriction
if param_value is None:
# If Nonetype has already been added, this will stop it from being entered multiple times
type_to_insert = type(None)
if not type_to_insert in found_types:
found_types.append(type_to_insert)
# If several types for a parameter are detected, create a parameter restriction accordingly
if len(found_types) > 1 or type(None) in found_types:
found_type_restrictions = []
for item in found_types:
found_type_restrictions.insert(0, item)
restriction = ["type"]
restriction.append(found_type_restrictions)
param_restrictions.append(restriction)
# Using the extracted information, construct the parameter list
block_parameters.append(
[
param_name,
param_type,
param_value,
param_restrictions,
param_tooltip,
]
)
except Exception as e:
print(
"@@@@@@@ Fatal error: Cannot parse parameter info to construct parameter for block: -> '"
+ block_type
+ "', parameter name: -> '"
+ param_name
+ "'.@@@@@@"
)
print("@@@@@@@ Printing exception below: @@@@@@@")
print(e)
if block_classname in ["SubSystem", "OutPort"]:
block_parameters.append(inlabels_param)
if block_classname in ["SubSystem", "InPort"]:
block_parameters.append(outlabels_param)
# -----------------------------------------------------------------------------------------------------
# Section for importing block class from its module, and assigning to it the extracted information
# -----------------------------------------------------------------------------------------------------
try:
def __block_init__(self):
Block.__init__(self, scene, window)
self.title = copy.copy(self.title)
self.block_type = copy.copy(self.block_type)
self.parameters = copy.deepcopy(self.parameters)
self.inputsNum = copy.copy(self.inputsNum)
self.outputsNum = copy.copy(self.outputsNum)
self.input_names = copy.deepcopy(self.input_names)
self.output_names = copy.deepcopy(self.output_names)
self.icon = copy.copy(self.icon)
self.flipped_icon = os.path.join(
os.path.splitext(copy.copy(self.icon))[0] + "_flipped.png"
)
self.block_url = copy.copy(self.block_url)
self.width = copy.copy(self.width)
self.height = copy.copy(self.height)
self._createBlock(self.inputsNum, self.outputsNum)
# Default size for all blocks
size = [100, 100]
try:
size = size_map[block_classname]
except KeyError:
pass
# Dynamically create class for this block
# Assign the extracted block variables to this block
new_block_class = type(
block_classname,
(Block,),
{
"__init__": __block_init__,
"title": block_name,
"block_type": block_type,
"parameters": block_parameters,
"inputsNum": block_inputsNum,
"outputsNum": block_outputsNum,
"input_names": block_input_names,
"output_names": block_output_names,
"icon": block_icon,
"block_url": block_url,
"width": size[0],
"height": size[1],
},
)
# Add this block to blocklist
blocklist.append(new_block_class)
# # If this block belongs to a new group of blocks, for which a list hasn't been made yet
# # then make a list in the block_library, to hold those blocks
# if block_parentclass not in imported_block_groups:
# imported_block_groups.append(block_parentclass)
# block_library.append([block_parentclass, []])
#
# # Add this block to the group of blocks it belongs to
# for i, group in enumerate(block_library):
# # 1st element of group, will always be the group name (sinks, sources, functions, etc)
# if group[0] == block_parentclass:
# block_library[i][1].append([blockname(new_block_class), new_block_class])
# break
# -----------------------------------------------------------------------------------------------
# If this block belongs to a new group of blocks, for which a list hasn't been made yet
# then make a list in the block_library, to hold those blocks
if block_group not in imported_block_groups:
imported_block_groups.append(block_group)
block_library.append([block_group, []])
# Add this block to the group of blocks it belongs to
for i, group in enumerate(block_library):
# 1st element of group, will always be the group name (sinks, sources, functions, etc)
if group[0] == block_group:
block_library[i][1].append(
[blockname(new_block_class), new_block_class]
)
break
except KeyError:
print(
"Error: attempted to create a block class that isn't supported. Attempted class type: ",
block_classname,
)
return block_library
================================================
FILE: bdsim/bdedit/block_main_block.py
================================================
# BdEdit imports
from bdsim.bdedit.block import *
from bdsim.bdedit.block_socket import *
from bdsim.bdedit.block_graphics_block import *
# =============================================================================
#
# Defining the Main Block Class, which allows for the loaded/built model to
# be invoked as a subprocess when that model is run
#
# =============================================================================
# Todo - update doc string
class Main(Block):
""" """
# -----------------------------------------------------------------------------
def __init__(self, scene, window, file_name=None, name="Main Block", pos=(0, 0)):
""" """
super().__init__(scene, window)
# Same variables inherited from the Block class
self.scene = scene
self.window = window
self.block_type = blockname(self.__class__)
self.width = 100
self.height = 100
self.setDefaultTitle(name)
self.parameters = [["file name", str, file_name, []]]
self.block_url = ""
self.icon = ":/Icons_Reference/Icons/main.png"
self.flipped = False
self.flipped_icon = os.path.join(
os.path.splitext(self.icon)[0] + "_flipped.png"
)
self.inputsNum = 0
self.outputsNum = 0
self.grBlock = GraphicsBlock(self)
self.parameterWindow = None
# The Main block is automatically stored into the Scene,
# and visually added into the GraphicsScene
self.scene.addBlock(self)
self.scene.grScene.addItem(self.grBlock)
self._createParamWindow()
self.scene.has_been_modified = True
================================================
FILE: bdsim/bdedit/block_param_window.py
================================================
# Library imports
import ast
import math
# PyQt5 Imports
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QPixmap, QDesktopServices
from PyQt5.QtCore import Qt, QRect
# BdEdit imports
from bdsim.bdedit.Icons import *
# =============================================================================
#
# Defining and setting global variables
#
# =============================================================================
# Socket positioning variables - used for determining what side of the block the
# socket should be drawn
LEFT = 1
RIGHT = 3
# Socket sign variables - used for logic associated with drawing symbols for the
# PROD and SUM blocks
PLUS = "+"
MINUS = "-"
MULTIPLY = "*"
DIVIDE = "/"
# Variable for enabling/disabling debug comments
DEBUG = False
# =============================================================================
#
# Defining the ParamWindow Class, which holds information of how the parameter
# window - that holds all the user-editable block parameters - appears. It also
# contains the logic for creating the ParamWindow and the logic for sanity
# checking the block parameters once they have been edited by the user.
#
# =============================================================================
class ParamWindow(QWidget):
"""
The ``ParamWindow`` Class extends the ``QWidget`` Class from PyQt5.
The ParamWindow Class controls:
- how the parameter window appears visually,
- where it is located within the BdEdit application window,
- the displayed parameters from the Block the parameter window is related to,
- sanity checking on user-edits to the Block parameters,
- pop-up user feedback for successful or unsuccessful Block parameter edits.
"""
# -----------------------------------------------------------------------------
def __init__(self, block, parent=None):
"""
This method initializes an instance of the ``ParamWindow`` Class.
:param block: the Block this ParamWindow instance relates to
:type block: ``Block``
:param parent: the parent widget this ParamWindow belongs to (should be None)
:type parent: None, optional
"""
super().__init__(parent)
# The Block this parameter window relates to is stored internally,
# so are its parameters
self.block = block
self.parameters = self.block.parameters
# Parameter_values is a list into which the text responses of the user
# will be appended to, when they make changes to a Block parameter
self.parameter_values = []
# The parameter window will display vertically on the RHS of the BdEdit
# application window, hence its layout manager will be a vertical one
self.layout = QVBoxLayout()
# Definition of with of the parameter window, and the lines holding
# the block parameters inside it. The width is fixed to 300 pixels, scaled
# to what 300 pixels should look like on 2560 screen width resolution
self._parameter_line_width = 150
self._width = 300 * self.block.window.scale
self.setFixedWidth(self._width)
# Variable to update title of model when parameter values have been changed,
# to indicate that there is unsaved progress
self.paramsWereChanged = False
# Further initializing necessary parameter window settings, and calling
# the method that will build the it
self.initUI()
self.buildParamWindow()
# -----------------------------------------------------------------------------
def initUI(self):
"""
This method adds a 'Parameter Window' label to the ParamWindow, sets the
alignment of items within the parameter window, sets the background to
auto fill, and finally, sets the layout manager of the ParamWindow.
"""
# The follow label is added to the parameter window, naming it
# Items within the parameter window layout manager are set to align towards the top
param_window_label = QLabel("Block settings")
param_window_label.setAlignment(Qt.AlignCenter)
self.layout.addWidget(param_window_label)
self.layout.setAlignment(Qt.AlignTop)
# Its background is filled
self.setAutoFillBackground(True)
self.setLayout(self.layout)
# -----------------------------------------------------------------------------
def displayDocumentationURL(self):
"""
This method opens the url link associated with this blocks' documentation.
"""
QDesktopServices.openUrl(QtCore.QUrl(self.block.block_url))
# -----------------------------------------------------------------------------
def closeQMessageBox(self):
"""
This method closes a pop-up user-feedback message if one already exists
within the parameter window. This prevents multiple messages from being
displayed at the same time, and ensure the message the user sees, is the
most relevant one.
"""
# If a message widget already exists in the ParamWindow, remove it
# ParamWindow (self) has several widgets already, some of which hold QLabels, QEditLines or a QPushButton
# Iterate through all of ParamWindow's widgets
for widget in self.children():
# Grab the children of the ParamWindow's child widget
widgets_children = widget.children()
# Iterate through all this widget's children widgets
for child in widgets_children:
# If a child widget happens to be a QMessageBox, then remove that widget from the ParamWindow layout
if child.__class__ == QMessageBox:
self.layout.removeWidget(widget)
break
# -----------------------------------------------------------------------------
def displayPopUpMessage(self, title, text, messageType):
"""
This method displays a pop-up user-feedback message within the parameter window,
notifying them of either a successful or unsuccessful update to the Blocks'
parameters. This method will also trigger the message to auto-close, after 1.5
seconds for a successful update, and after 5 seconds for an unsuccessful update.
If at any point the user updates the Block parameters before this time is elapsed,
the current (old) message will be removed and replaced by the most relevant message.
An unsuccessful update attempt will also issue an error sound when the message is
opened.
:param title: the title of the message box displayed
:type title: str
:param text: the text that fills the body of the displayed message box
:type text: str
:param messageType: variable that calls what type of message to display ("Success", "Error")
:type messageType: str
"""
def closeMessage():
self.timer.stop()
self.message.close()
# If a message box is already displayed within the ParamWindow, it will be closed
self.closeQMessageBox()
# Create a widget to wrap the QMessageBox into, that it may be displayed in the ParamWindow
self.popUp = QWidget()
self.popUp.layout = QVBoxLayout()
self.message = QMessageBox(self)
# Manually set the width of the QMessageBox layout to control text wrapping
# The layout is a grid, so setting width of 1st row/column cell will set width of the widget
self.message.item = self.message.layout().itemAtPosition(0, 1)
self.message.item.widget().setFixedWidth(self.width() - 100)
# If an error message - critical icon, if success message - green tick icon
if messageType == "Error":
self.message.setIcon(QMessageBox.Critical)
self.message.setIconPixmap(QPixmap(":/Icons_Reference/Icons/error.png"))
message_duration = 5
elif messageType == "Success":
self.message.setIconPixmap(QPixmap(":/Icons_Reference/Icons/success.png"))
message_duration = 1.5
# Set the title and text for the message
self.message.setText("" + title + "")
self.message.setInformativeText(text)
# Set style (adding a black border around messagebox)
self.message.setStyleSheet("QMessageBox { border : 1px solid black;}")
# Set message modality to be non-blocking (by default, QMessageBox blocks other actions until closed)
self.message.setWindowModality(Qt.NonModal)
# Add the QMessageBox to the popUp widget, then add to the layout of the ParamWindow widget
self.popUp.layout.addWidget(self.message)
self.popUp.setLayout(self.popUp.layout)
self.layout.addWidget(self.popUp)
# Create timer to keep message opened for 5 seconds if error, 1.5 seconds if success
self.timer = QtCore.QTimer()
self.timer.setInterval(int(message_duration * 1000))
self.timer.timeout.connect(closeMessage)
self.timer.start()
# -----------------------------------------------------------------------------
def buildParamWindow(self):
"""
This method handles the building of the ParamWindow instance. These instances
will always look exactly the same in terms of the information they contain,
however the Block parameters and the block type will vary depending on the Block
this ParamWindow relates to.
The ParamWindow is built by adding items into the QWidget that represents this
parameter window. For each item added into the QWidget, a label is displayed on
the left-hand-side, and either the non-editable value (label) is displayed on the
right-hand-side, or an editable line is displayed and populated with the respective
parameters' current value.
The ParamWindow is populated by, first, adding a non-editable line displaying the
selected Blocks' type. Next, the Blocks' current title is added with an editable
line. Following this, each Block parameter looped through and added with an editable
line in which the current value of the Block parameter is populated. Changing this
value will prompt the sanity checking of the value entered, which is handled by
the updateBlockParameters() method.
"""
# Make the first row, which contains two labels for the block's type
self.row1 = QWidget()
self.row1.layout = QHBoxLayout()
# Make a label of the block type
self.block_type_label = QLabel("type: ")
# Make an editable line for the type, and populate it with the current block type
self.block_type = QLabel(
"" + str(self.block.block_type) + " Block "
)
# Set the width of the editable line to the above-defined width (150 pixels)
self.block_type.setFixedWidth(self._parameter_line_width)
# Add the label and editable line into our row widget
self.row1.layout.addWidget(self.block_type_label, alignment=Qt.AlignCenter)
self.row1.layout.addWidget(self.block_type, alignment=Qt.AlignCenter)
# Add out type row widget to the layout of the parameter window
self.row1.setLayout(self.row1.layout)
self.layout.addWidget(self.row1)
# Make the second row, which contains the label and editable line for the block's title
self.row2 = QWidget()
self.row2.layout = QHBoxLayout()
# Make a label of the block title
self.title_label = QLabel("name: ")
# Make an editable line for the title, and populate it with the current block title
self.title_line = QLineEdit(self.block.title)
# Set the width of the editable line to the above-defined width (150 pixels)
self.title_line.setFixedWidth(self._parameter_line_width)
# Add the label and editable line into our row widget
self.row2.layout.addWidget(self.title_label, alignment=Qt.AlignCenter)
self.row2.layout.addWidget(self.title_line)
# Add out title row widget to the layout of the parameter window
self.row2.setLayout(self.row2.layout)
self.layout.addWidget(self.row2)
# If the block has parameters, build part of the paramWindow that displays those
if self.parameters:
# For each block parameter
for parameter in self.parameters:
# Create a QWidget that will represent the row that parameter is displayed in
self.row_x = QWidget()
self.row_x.layout = QHBoxLayout()
# Make a label of that parameters' name
self.label = QLabel(
"" + parameter[0] + ": " + ""
)
try:
self.label.setToolTip(parameter[4])
except IndexError:
print(parameter)
# If the parameter type is a boolean, create the intractable space as a checkbox, otherwise
# make an editable line for that parameter, and populate it with the parameters' current value
if not issubclass(parameter[1], bool):
self.line = QLineEdit(str(parameter[2]))
else:
try:
self.line = QCheckBox()
self.line.setChecked(parameter[2])
except TypeError:
print("bad thing")
# Set the width of the editable line to the above-defined width (150 pixels)
self.line.setFixedWidth(self._parameter_line_width)
# Append the current value of the parameter into the following list (for later comparison)
self.parameter_values.append(self.line)
# Add the label and editable line into our row widget
self.row_x.layout.addWidget(self.label, alignment=Qt.AlignCenter)
self.row_x.layout.addWidget(self.line, alignment=Qt.AlignCenter)
# Add out row widget to the layout of the parameter window
self.row_x.setLayout(self.row_x.layout)
self.layout.addWidget(self.row_x)
# Finally add an update button, which will trigger the sanity checking of the
# current values within the editable lines
self.update_button = QPushButton("Update Parameters")
self.update_button.clicked.connect(self.updateBlockParameters)
self.layout.addWidget(self.update_button)
# Add a button linked to the URL of this block's documentation
self.block_url_Button = QPushButton("View documentation")
self.block_url_Button.clicked.connect(self.displayDocumentationURL)
self.layout.addWidget(self.block_url_Button)
# -----------------------------------------------------------------------------
def updateBlockParameters(self):
"""
This method calls for each of the parameters within the parameter window to be
sanity checked by the getSafeValue() method, which determines whether or not
a provided value is compatible with the parameter type (defined in the Block
Class) and is safe to override the current value. If that check is returned
to be safe, this method will handle the updating of the Block parameters, as
well as triggering a successful update attempt message.
If the check is returned as not safe, meaning the given value is not compatible,
an unsuccessful update attempt error message will be prompted, notifying the
user of the incompatible parameter value they have set, and either what the
compatible types or values are. This logic also applies when a user changes the
blocks' title to one that already exists, which will cause a duplicate error
message to display.
Some parameters values directly affect the GraphicsBlock of the Block they relate
to. For example, blocks that can have multiple input or output sockets, will
have a parameter that controls how many of these sockets the block has. And once
edited, this method will trigger an appropriate number of sockets to be created
or deleted. This parameter can also affect the GraphicsBlock when too many sockets
are created, requiring the block to be resized. The triggering of this resizing
will also be issued from within this method.
"""
# -----------------------------------------------------------------------------
def makeBadInputErrorMsg(options):
"""
This method returns the correct text that should be displayed within the body
of the pop-up user-feedback message. The text that is displayed here is extracted
from the associated extra-options as defined in the relating Block.
:param options: the extra-options associated with this parameter (defined in this Block)
:type options: list, of str, list
:return: the formatted message to be displayed
:rtype: str
"""
# Start with an empty message
message = ""
# Num_options is the number of lists (of accepted keywords, types, range, symbol) inside the option list
num_options = len(options)
# Check the options that have been assigned to this parameter
for option in options:
# If the options consist keywords that this parameter is restricted to
if option[0] == "keywords":
message += "one of " + str(option[1]) + ""
# If the options consist of a range this parameters is restricted to
elif option[0] == "range":
message += (
"a value between "
+ str(option[1][0])
+ " and "
+ str(option[1][1])
+ ""
)
# If the options consist of additional types this parameter is restricted to
elif option[0] == "type":
typeString = []
for optionType in option[1]:
typeString.append(optionType.__name__)
message += "of type " + str(typeString) + ""
# If the options consist of certain sign characters this parameter is restricted to
elif option[0] == "symbol":
message += "a combination of " + str(option[1]) + ""
# If the options consists of a size restriction on how many elements are allowed in the list
elif option[0] == "size":
message += (
"limited to a size of " + str(option[1]) + ""
)
# If a parameter has multiple options (e.g. range and type restrictions)
# separate the options with "or" until only 1 option remains
if num_options > 1:
message += " or "
num_options -= 1
return message
# Update the title
duplicate_title = []
# UpdateName is returned as None if there are no issues with setting a title
# If title is a duplicate, a list of ["@DuplicateName@", given_name] is returned
updateName = self.block.setTitle(self.title_line.text())
self.block.grBlock._draw_title = True
if updateName:
if updateName[0] == "@DuplicateName@":
duplicate_title.append(updateName[1])
else:
self.paramsWereChanged = True
# Iterator for loop
i = -1
# An error message can consist of an invalid_input (incorrect parameter type)
# or a bad_input (incompatible with option restrictions), and initially these
# are set to being empty. If parameters cannot be set due to errors, these will
# be appended into these empty lists
invalid_input, bad_inputs, bad_socket_labels = [], [], []
# Check if the block has parameters, if so, go through the sanity checking of each parameter value
if self.parameters:
# For each definition of a parameter, in the blocks' defined parameters
for [paramName, paramType, paramVal, paramOptions, _] in self.parameters:
i += 1
# If parameter type is boolean, then retrieve checked state of checkbox, otherwise
# extract the text from the editable line as the value to set the parameter to
if not issubclass(paramType, bool):
inputValue = self.parameter_values[i].text()
else:
inputValue = str(self.parameter_values[i].isChecked())
# If a value has been provided for that parameter, perform sanity checking on that input
if inputValue:
if self.parameters[i][0] in ["nin", "ops", "signs", "nout"]:
inputInCompatibleFormat = self.getSafeValue(
inputValue, paramType, paramOptions
)
else:
if inputValue.startswith("="):
inputInCompatibleFormat = inputValue
else:
inputInCompatibleFormat = self.getSafeValue(
inputValue, paramType, paramOptions
)
# If in DEBUG mode, this code will return the name, type, current value of the parameter attempting to update
# and then for the value that will override the parameter, the value, type(of the value), and whether it is or isn't compatible
if DEBUG:
print(
"paramName, paramType, paramVal - inputValue, type, compatible",
[
paramName,
paramType,
paramVal,
"-",
inputValue,
type(inputValue),
inputInCompatibleFormat,
],
)
# Once the sanity check has been performed, if the type is valid, check for parameter restrictions
if inputInCompatibleFormat != "@InvalidType@":
# If the sanity check returns that the parameter doesn't meet its restrictions
if inputInCompatibleFormat == "@BadFormat@":
# Append the parameter edited, and the parameter options, as a bad_input
bad_inputs.append([paramName, paramOptions])
else:
# Otherwise if both sanity checks pass, value is safe to update, so
# Check if the given value is different to what is already set as the param value
# If it is the same, don't update the value
if inputInCompatibleFormat == paramVal:
pass
# Otherwise update the value
else:
# Set the current parameter equal to edited parameter value
self.parameters[i][2] = inputInCompatibleFormat
self.paramsWereChanged = True
# If self.parameter relates to controlling the number of inputs a block has
if self.parameters[i][0] in ["nin", "ops", "signs"]:
# Grab the number of required input sockets
if self.parameters[i][0] == "nin":
num_sockets = self.parameters[i][2]
else:
num_sockets = len(
self.parameter_values[i].text()
)
# Don't do anything, if the provided number of input sockets matches the number the block already has,
# or if the symbols (+,-,*,/) for the block haven't changed
# if len(self.block.inputs) == num_sockets and inputInCompatibleFormat == paramVal:
# pass
# else:
# If the given number of input sockets matches the number the block already has, or if the number of
# symbols (+,-,*,/) for the block hasn't changed
if len(self.block.inputs) == num_sockets:
# If the values of the signs hasn't changed, then don't do anything
if inputInCompatibleFormat == paramVal:
pass
# If the values of the signs has changed (but the number of signs is still the same), just
# update the signs without removing the wires
else:
# Split the socket signs by number of characters given
chars = [
char for char in inputInCompatibleFormat
]
# Go through each of the chars from the string of symbols for this block's signs
# and set the respective socket to that symbol
for j, char in enumerate(chars):
self.block.inputs[j].socket_sign = char
else:
# If the block already has input sockets, grab their orientation (LEFT / RIGHT) then delete
# Else, draw input socket with default orientation (LEFT) and no need to delete as block has no input sockets
if self.block.inputs:
orientation = self.block.inputs[0].position
# Remove all current input sockets
self.block.inputs[0].removeSockets("Input")
else:
orientation = LEFT
# Recreate input sockets to the number provided
# If self.block is a SUM or PROD block, this will also update the input sockets' sign (+,_,*,/)
self.block.inputsNum = num_sockets
self.block.makeInputSockets(
self.block.inputsNum, orientation
)
# If self.parameter relates to controlling the number of outputs a block has
if self.parameters[i][0] in ["nout"]:
# Grab number of required output sockets
num_sockets = self.parameters[i][2]
# If provided number of output sockets matches the number the block already has, don't do anything
if len(self.block.outputs) == num_sockets:
pass
else:
# If the block already has output sockets, grab their orientation (LEFT / RIGHT) then delete
# Else, draw output socket with default orientation (RIGHT) and no need to delete as block has no output sockets
if self.block.outputs:
orientation = self.block.outputs[0].position
# Remove all current output sockets
self.block.outputs[0].removeSockets(
"Output"
)
else:
orientation = RIGHT
# Recreate output sockets to the number provided
self.block.outputsNum = num_sockets
self.block.makeOutputSockets(
self.block.outputsNum, orientation
)
# If self.parameter relates to controlling the names of inport labels on subsystem blocks
if self.parameters[i][0] == "inport labels":
# First check if labels are given for the sockets, if not, don't do anything special
if self.parameters[i][2] is not None:
input_length = len(self.parameters[i][2])
if input_length > 0:
# Find number of inputs controlled by nin
found_nin = False
for params in self.parameters:
if params[0] == "nin":
num_nin_sockets = params[2]
found_nin = True
break
# Check if nin parameter was found, if not, return error as we need to know how many sockets to draw
if found_nin == False:
print(
"Error: Cannot draw InPort labels as no 'nin' parameter was found to know how many sockets to draw."
)
else:
# If nin parameter was found, check if number of given InPort labels matches number of sockets
if input_length != num_nin_sockets:
bad_socket_labels.append(
[paramName, paramOptions]
)
else:
# If parameter value hasn't changed, don't do anything
if (
inputInCompatibleFormat
== paramVal
):
pass
else:
# If the block already has input sockets, grab their orientation (LEFT / RIGHT) then delete
# Else, draw input socket with default orientation (LEFT) and no need to delete as block has no input sockets
self.block.input_names = [
str(j)
for j in self.parameters[i][
2
]
]
if self.block.inputs:
for k, socket in enumerate(
self.block.inputs
):
socket.updateSocketSign(
self.block.input_names[
k
]
)
# Otherwise if the parameter value is None or [], then remove all the socket labels for a block if there are any.
elif not self.parameters[i][2]:
if self.block.inputs:
if self.block.input_names:
for socket in self.block.inputs:
socket.updateSocketSign(None)
# If self.parameter relates to controlling the names of outport labels on subsystem blocks
if self.parameters[i][0] == "outport labels":
# First check if labels are given for the sockets, if not, don't do anything special
if self.parameters[i][2] is not None:
input_length = len(self.parameters[i][2])
if input_length > 0:
# Find number of outputs controlled by nout
found_nout = False
for params in self.parameters:
if params[0] == "nout":
num_nout_sockets = params[2]
found_nout = True
break
# Check if nout parameter was found, if not, return error as we need to know how many sockets to draw
if found_nout == False:
print(
"Error: Cannot draw OutPort labels as no 'nout' parameter was found to know how many sockets to draw."
)
else:
# If nout parameter was found, check if number of given OutPort labels matches number of sockets
if input_length != num_nout_sockets:
bad_socket_labels.append(
[paramName, paramOptions]
)
else:
# If parameter value hasn't changed, don't do anything
if (
inputInCompatibleFormat
== paramVal
):
pass
else:
# If the block already has output sockets, grab their orientation (LEFT / RIGHT) then delete
# Else, draw output socket with default orientation (RIGHT) and no need to delete as block has no output sockets
self.block.output_names = [
str(j)
for j in self.parameters[i][
2
]
]
if self.block.outputs:
for k, socket in enumerate(
self.block.outputs
):
socket.updateSocketSign(
self.block.output_names[
k
]
)
# Otherwise if the parameter value is None or [], then remove all the socket labels for a block if there are any.
elif not self.parameters[i][2]:
if self.block.outputs:
if self.block.output_names:
for socket in self.block.outputs:
socket.updateSocketSign(None)
# Else the edited value is of the wrong type, display an error message
else:
# Append the parameter edited, and the required type, as an invalid_input
invalid_input.append([paramName, paramType])
# Else no value was given for that input, display an error message
else:
# Append the parameter edited, and the required type, as an invalid_input
invalid_input.append([paramName, paramType])
# Once all the parameters are sanity checked,
# If the title has been set to a duplicate name, display a duplicate error message
if duplicate_title:
errorMessageText = ""
errorMessageTitle = "Duplicate Block Title"
errorMessageText += (
"A block named '"
+ duplicate_title[0]
+ "' already exists, please choose another."
)
self.displayPopUpMessage(errorMessageTitle, errorMessageText, "Error")
# If any parameters have been returned with invalid types, display an invalid type error message
elif invalid_input:
errorMessageText = ""
errorMessageTitle = "Input Types Not Compatible"
for incompatibleInputs in invalid_input:
errorMessageText += (
"Expected '"
+ ""
+ incompatibleInputs[0]
+ "' to be type "
+ incompatibleInputs[1].__name__
+ ""
)
errorMessageText += " "
self.displayPopUpMessage(errorMessageTitle, errorMessageText, "Error")
# If any parameters don't meet their option restrictions, display a bad input error message
elif bad_inputs:
errorMessageText = ""
errorMessageTitle = "Input Value Not Allowed"
for badInput in bad_inputs:
# Different error message based on type of option
errorMessageText += (
"Parameter '" + "" + badInput[0] + "' must be "
)
errorMessageText += makeBadInputErrorMsg(badInput[1])
errorMessageText += " "
self.displayPopUpMessage(errorMessageTitle, errorMessageText, "Error")
# If labels are given for InPort, OutPort or SubSystem blocks which don't match the respective nin/nout value for number of sockets, display a bad socket label input error message
elif bad_socket_labels:
errorMessageText = ""
errorMessageTitle = "Inconsistent Number of Given Socket Labels"
for badSocketLabel in bad_socket_labels:
# Different error message based on type of option
errorMessageText += (
"Parameter '"
+ ""
+ badSocketLabel[0]
+ "' must correspond to number of nin/nout sockets."
)
self.displayPopUpMessage(errorMessageTitle, errorMessageText, "Error")
# Otherwise if there were no issues with updating the block parameters, display a success message, yay!
else:
successMessageText = "Successfully updated block parameter values!"
successMessageTitle = "Success!"
self.displayPopUpMessage(successMessageTitle, successMessageText, "Success")
# If a parameter update has changed a value then update the title of the model,
# to indicate that there is unsaved progress
if self.paramsWereChanged:
self.paramsWereChanged = False
self.block.scene.has_been_modified = True
self.block.scene.history.storeHistory("Block parameters updated")
# Finally, notify the GraphicsBlock to update itself, should the number of sockets, or the block
# height have been called to change
self.block.grBlock.update()
@staticmethod
# -----------------------------------------------------------------------------
def getSafeValue(inputValue, requiredType, requiredOptions):
"""
This method takes an input value (which is the value a parameter is being checked
if it can be updated to), and checks whether it matches an allowable type that
has been defined for that parameter within the grandchild Block Class. If the
input value doesn't match the required type, an invalid type str will be returned.
If the input value does match the required type, it is further checked, whether
it matches any further restrictions placed onto that parameter from within the
grandchild Block Class. If the value doesn't meet the criteria of the restrictions,
a bad input str will be returned. If the input does match the criteria of the
restriction, it will be converted to the type it must be in and returned.
:param inputValue: the value which the parameter would be updated to
:type inputValue: str
:param requiredType: the value type which is required for this parameter
:type requiredType: type, determined by the grandchild Block Class
:param requiredOptions: a list of restrictions placed onto this parameter
:type requiredOptions: list
:return: - str (if incompatible type or restriction criteria not met),
- requiredType (if compatible type and restrictions are met)
:rtype: type, determined by the grandchild Block Class
"""
# -----------------------------------------------------------------------------
def isValueInOption(value, options):
"""
This method checks whether the edited parameter value meets the option
restrictions placed on it by the Block it was defined in. The option
restrictions consist of a list equivalent to:
- [["restriction type1" [restrictions]], ["restriction type2" [restrictions]]].
The edited parameter is checked whether it meets the conditions of 'restrictions'
for each 'restriction type'.
:param value: the edited parameter value being checked
:type value: any
:param options: the list of restriction options placed on this parameter
:type options: list
:return: - value (if meets criteria of placed restriction),
- bad_format (if criteria is not met)
:rtype: - any (if criteria met), - str (if criteria not met)
"""
# If the parameter has restrictions placed on it
if options:
returnValue = "@BadFormat@"
# For each restriction that is placed onto the parameter
for option in options:
# If the placed restriction is a set of keywords,
if option[0] == "keywords":
# Check if the given value matches one of those keywords
if value.lower() in option[1]:
returnValue = value
break
# If the placed restriction is a range of values
elif option[0] == "range":
# Check if given value is within that range
if option[1][0] <= value <= option[1][1]:
returnValue = value
break
# If the placed restriction are additional accepted types
elif option[0] == "type":
# Check if the None is one of the accepted types
if type(None) in option[1]:
# If the value given is None, return None
if isinstance(value, str) and value.lower() in ["none"]:
returnValue = None
break
# Check if given value matches any accepted types
if type(value) in option[1]:
returnValue = value
break
# If the placed restriction are a set of allowable character symbol
elif option[0] == "symbol":
# Check if value is a string
if isinstance(value, str):
# First get the max possible wrong characters in this string
num_of_wrong_symbols = len(value)
# Check each character within the given value against the set of allowable characters
for sign in value:
# For every character in the set of allowable characters, reduce the number
# of wrong characters by 1
if sign in option[1]:
num_of_wrong_symbols -= 1
# If all characters within the string match a set of allowable characters
if num_of_wrong_symbols == 0:
returnValue = value
break
# Otherwise return badformat
else:
returnValue = "@BadFormat@"
break
# If the placed restriction are to the number of elements the parameter can have
elif option[0] == "size":
# Try to evalute the param value, and catch if it is a string
try:
# If input isn't a word (is a tuple, list, dict, num) try to evaluate it
try:
param_val = eval(value)
# If a type error is thrown, then the input might already have been evaluated previously
except TypeError:
param_val = value
# Check if the size of parameter is measureable, if not then its an int or float
try:
param_length = len(param_val)
# If the size of the parameter meets one of the allowable sizes (e.g. 0, 2 or 4) then return the value
if param_length in option[1]:
returnValue = value
else:
returnValue = "@BadFormat@"
break
# If parameter isn't measureable, return bad format as param is an int/float, and size of a singular number cannot be checked
except TypeError:
returnValue = "@BadFormat@"
break
# If input is a word, evaluating it will try to match it to a variable name, which doesn't exist,
# so in this case, don't check the size restriction on this parameter value
except NameError:
pass
# Return the value that has been set to be returned
return returnValue
# Else, if no restrictions are placed on this parameter, return the value
else:
return value
try:
# If input must be string, only strings can be accepted
if issubclass(requiredType, str):
# If the input is not a number, but an acceptable string
if isinstance(inputValue, str):
# Check if no input has been given
if len(inputValue) == 0:
return "@InvalidType@"
else:
# return isValueInOption(inputValue.lower(), requiredOptions)
return isValueInOption(inputValue, requiredOptions)
# # Check if the input is made up of normal characters [a-zA-z0-9]
# if inputValue.isalnum():
# return isValueInOption(inputValue.lower(), requiredOptions)
#
# # Otherwise the input has special characters (=,-,+,*,/,:,etc)
# else:
# # Check if string contains '=', as this is restricted to variable name definitions, and is not allowed for regular strings
# if "=" in inputValue:
# outcome = isValueInOption(inputValue, requiredOptions)
# if outcome == "@BadFormat@":
# return outcome
# else:
# return "@InvalidType@"
# else:
# return isValueInOption(inputValue.lower(), requiredOptions)
else:
return "@InvalidType@"
# If input must be bool, only booleans can be accepted
elif issubclass(requiredType, bool):
# All input starts off as text, so True/False will be 'True'/'False'
if isinstance(inputValue, str):
# Check if the string matches true/false, and return accordingly
if inputValue in ["True", "true"]:
return True
elif inputValue in ["False", "false"]:
return False
# Otherwise if string is None, check if this boolean parameter allows that type
elif inputValue.lower() in ["none"]:
return isValueInOption(inputValue.lower(), requiredOptions)
else:
return "@InvalidType@"
else:
return "@InvalidType@"
# If input must be int, floats can be converted to int
elif issubclass(requiredType, int):
# Try applying int() to the input value, if possible, check restrictions on value
try:
requiredType(inputValue)
return isValueInOption(requiredType(inputValue), requiredOptions)
except ValueError:
# If applying int() doesn't work but value is None, check if this is an allowable type
if inputValue.lower() in ["none"]:
return isValueInOption(inputValue, requiredOptions)
else:
return "@InvalidType@"
# If input must be float, int can be converted to float
elif issubclass(requiredType, float):
# All inputValues come in as a string, so first check if this evaluated string is a float
try:
evaluated_value = eval(inputValue)
# If value can be evaluated safely, check if the value is an instance of float
if isinstance(evaluated_value, float):
# If so, check further restrictions on this parameter, return the outcome
return isValueInOption(evaluated_value, requiredOptions)
# If value is not a float, but is none, check if this is an allowable type
elif inputValue.lower() in ["none"]:
return isValueInOption(inputValue, requiredOptions)
# If value is not a float, and None is not allowed, return invalid type
else:
try:
float_value = float(evaluated_value)
return isValueInOption(float_value, requiredOptions)
except (ValueError, TypeError):
return "@InvalidType@"
# If any exceptions arise while trying to evaluate, then the value is incorrect
except:
return "@InvalidType@"
# If input must be a list, only list can be accepted
elif (
issubclass(requiredType, list)
or issubclass(requiredType, tuple)
or issubclass(requiredType, dict)
):
try:
# If the input value can be evaluated as a list, tuple or dict, check restrictions on value
ast.literal_eval(inputValue)
if inputValue.lower() in ["none"]:
return isValueInOption(inputValue, requiredOptions)
else:
return isValueInOption(
ast.literal_eval(inputValue), requiredOptions
)
except ValueError:
return "@InvalidType@"
# If input can be of type 'any', allow any value to be saved. This will also process the 'callable' type, in the same way.
elif issubclass(requiredType, type(any)):
# Return the outcome of check this input against any restrictions for this parameter
# Type any or callable should be allowed to pass through a string
return isValueInOption(inputValue, requiredOptions)
except Exception as e:
print(e)
print(
"Fatal Error: Recent changes to a parameter have caused an unforseen error.\nKnown info about parameter causing the error: given value ->",
inputValue,
"expected type ->",
requiredType,
"parameter restrictions ->",
requiredOptions,
)
return "@InvalidType@"
================================================
FILE: bdsim/bdedit/block_socket.py
================================================
# Library imports
from collections import OrderedDict
# BdEdit imports
from bdsim.bdedit.interface_serialize import Serializable
from bdsim.bdedit.block_graphics_socket import GraphicsSocket
# =============================================================================
#
# Defining and setting global variables
#
# =============================================================================
# Socket positioning variables (in relation to where they're drawn on the block)
LEFT = 1
TOP = 2
RIGHT = 3
BOTTOM = 4
# Socket type classification variables
INPUT = 1
OUTPUT = 2
CONNECTOR = 3
# Variable for enabling/disabling debug comments
DEBUG = False
# =============================================================================
#
# Defining the Socket Class, which controls the type of Socket drawn, its
# position within the Block it relates to, and allows for Wires to connect
# to the Block through these Sockets.
#
# =============================================================================
class Socket(Serializable):
"""
The ``Socket`` Class extends the ``Serializable`` Class from BdEdit, and
defines how a socket is represented, and has all the necessary methods
for creating, manipulating and interacting with a socket. This class allows
for Wires to be connected to Blocks, while also controlling where on the
Block the Sockets are drawn, and how they appear.
This class includes information about the sockets':
- type;
- index;
- position;
- appearance;
- parent Block; and
- connected wire(s).
"""
# -----------------------------------------------------------------------------
def __init__(
self,
node,
index=0,
position=LEFT,
socket_type=INPUT,
multi_wire=True,
socket_label=None,
):
"""
This method initializes an instance of the ``Socket`` Class.
:param node: the associated Block this Socket relates to
:type node: Block, required
:param index: the height (along the side of the Block) this Socket should be drawn at
:type index: int, optional, defaults to 0
:param position: the side ( LEFT(1) or RIGHT(3) ) this Socket should be drawn on
:type position: enumerate, optional, defaults to LEFT(1)
:param socket_type: this Socket's type (INPUT(1) or OUTPUT(2))
:type socket_type: enumerate, optional, defaults to INPUT(1)
:param multi_wire: boolean of whether this Socket has multiple wires
:type multi_wire: bool, optional, defaults to True
"""
super().__init__()
self.node = node
self.index = index
self.position = position
self.socket_type = socket_type
self.socket_sign = socket_label
self.is_multi_wire = multi_wire
self.grSocket = GraphicsSocket(self)
self.grSocket.setPos(*self.node.getSocketPosition(index, position))
self.wires = []
# -----------------------------------------------------------------------------
def getSocketPosition(self):
"""
This method retrieves and returns the [x,y] coordinates for where the
current Socket should be drawn.
:return: the [x,y] coordinates at which to place this Socket.
:rtype: list of int, int
"""
res = self.node.getSocketPosition(self.index, self.position)
return res
# -----------------------------------------------------------------------------
def setConnectedEdge(self, wire):
"""
This method adds the given wire to the list of Wires that are connected to
this Socket.
:param wire: the wire connecting to this Socket
:type wire: Wire, required
"""
self.wires.append(wire)
# -----------------------------------------------------------------------------
def hasEdge(self):
"""
This method returns True if the current Socket has Wires connected to it,
and False if no Wires are connected to it.
:return: - True (If wires are connected to this Socket)
- False (If no wires are connected to this Socket)
:rtype: bool
"""
return self.wires is not None
# -----------------------------------------------------------------------------
def removeWire(self, wire):
"""
This method removes the given Wire from the list of Wires connected to this
Socket, if it is connected to this Socket.
:param wire: the wire to be removed
:type wire: Wire, required
"""
if wire in self.wires:
self.wires.remove(wire)
else:
print("Socket remove edge not in list")
# -----------------------------------------------------------------------------
def removeAllWires(self):
"""
This method removes all Wires connected to this Socket.
"""
# While there are Wires in this Socket's list of Wires, remove the first Wire
while self.wires:
wire = self.wires.pop(0)
wire.remove()
# -----------------------------------------------------------------------------
def isInputSocket(self):
"""
This method returns True if the current Socket is an input socket.
:return: - True (If current Socket is an input Socket)
- False (If current Socket is not an input Socket)
:rtype: bool
"""
isInputSocket = False
# Compare the id of the current socket against the id's of sockets
# within the associated Blocks' list of input sockets
for socket in self.node.inputs:
# If current socket is in that list, it is an input socket
if self.id == socket.id:
isInputSocket = True
break
return isInputSocket
# -----------------------------------------------------------------------------
def isOutputSocket(self):
"""
This method returns True if the current Socket is an output socket.
:return: - True (If current Socket is an output Socket)
- False (If current Socket is not an output Socket)
:rtype: bool
"""
isOutputSocket = False
# Compare the id of the current socket against the id's of sockets
# within the associated Blocks' list of output sockets
for socket in self.node.outputs:
# If current socket is in that list, it is an output socket
if self.id == socket.id:
isOutputSocket = True
break
return isOutputSocket
# -----------------------------------------------------------------------------
def updateSocketSign(self, value):
"""
This method updates the value of the socket label assigned to this socket.
As none but a select few blocks (SubSystem, OutPort, InPort) support dynamic
updating of the socket labels, this method should not be used unless it is
for one of the mentioned blocks.
:param value: new value to assign for socket label
:type value: str, int, None or []
"""
try:
self.socket_sign = value
except Exception:
self.socket_sign = None
# -----------------------------------------------------------------------------
def removeSockets(self, type):
"""
This method removes all of the input or output Sockets, relating to this
Block, as specified by the type.
This method removes all sockets of given type, associated with this ``Block``.
:param type: the type of Socket to remove ("Input" or "Output")
:type type: str, required
"""
# If in DEBUG mode, this code will return the type of Socket that has just
# been removed, and that the socket removal process has started. When this
# process is finished, a done message will be printed.
if DEBUG:
print("# Removing " + type + " Sockets", self)
if DEBUG:
print(" - removing grSockets")
# This allows one method to be used for deleting input OR output sockets
if type == "Input":
socketTypes = self.node.inputs
elif type == "Output":
socketTypes = self.node.outputs
# For each socket within the list determined by either Input or Output
# socket type
for socket in socketTypes:
# Remove the graphics parent item (the associated graphics block class)
# Remove the graphics socket class
socket.grSocket.setParentItem(None)
socket.grSocket = None
# If this socket has any wires attached to it, remove them
if socket.hasEdge():
for wire in socket.wires:
wire.remove()
# Finally remove the socket class from the associated block
self.node.removeSockets(type)
if DEBUG:
print(" - everything is done.")
# -----------------------------------------------------------------------------
def serialize(self):
"""
This method is called to create an ordered dictionary of all of this Sockets'
parameters - necessary for the reconstruction of this Socket - as key-value
pairs. This dictionary is later used for writing into a JSON file.
:return: an ``OrderedDict`` of [keys, values] pairs of all essential ``Socket``
parameters.
:rtype: ``OrderedDict`` ([keys, values]*)
"""
return OrderedDict(
[
("id", self.id),
("index", self.index),
("multi_wire", self.is_multi_wire),
("position", self.position),
("socket_type", self.socket_type),
]
)
# -----------------------------------------------------------------------------
def deserialize(self, data, hashmap={}):
"""
This method is called to reconstruct a ``Socket`` when loading a saved JSON
file containing all relevant information to recreate the ``Scene`` with all
its items.
:param data: a Dictionary of essential information for reconstructing a ``Socket``
:type data: OrderedDict, required
:param hashmap: a Dictionary for directly mapping the essential socket variables
to this instance of ``Socket``, without having to individually map each variable
:type hashmap: Dict, required
:return: True when completed successfully
:rtype: Boolean
"""
# The id of this Socket is set to whatever was stored as its id in the JSON file.
self.id = data["id"]
# The remaining variables associated to this Socket are mapped to itself
hashmap[data["id"]] = self
return True
================================================
FILE: bdsim/bdedit/block_wire.py
================================================
# Library imports
import time
import copy
from collections import OrderedDict
# BdEdit imports
from bdsim.bdedit.block_graphics_wire import *
from bdsim.bdedit.interface_serialize import Serializable
# =============================================================================
#
# Defining and setting global variables
#
# =============================================================================
# Wire type variables for choosing between the 3 possible wire styles
WIRE_TYPE_DIRECT = 1
WIRE_TYPE_BEZIER = 2
WIRE_TYPE_STEP = 3
# Variable for enabling/disabling debug comments
DEBUG = False
DEBUG_OVERLAP = False
# =============================================================================
#
# Defining the Wire Class, which is used to define the Wires that connect the
# blocks via the sockets, each wire has a start socket and a end socket and a
# wire type that defines how the wires will be drawn. The code also updates
# the wires as the blocks are moved around so they stay connected.
#
# =============================================================================
class Wire(Serializable):
"""
The ``Wire`` Class extends the ``Serializable`` Class from BdEdit, and
defines how a wire is represented, and has all the necessary methods
for creating, manipulating and interacting with a wire. This class connects
start and end sockets to a created wire. The style of wire being drawn is
also controlled by this Class:
- a straight wire will have type DIRECT(1),
- a curved or wave-like wire will have type BEZIER(2),
- a stepped wire will have type STEP(3)
This class includes information about the wires':
- style;
- end_socket;
- start_socket;
- point-to-point coordinates;
- horizontal and vertical line segments;
- intersection points with other wires (has been disabled).
"""
# -----------------------------------------------------------------------------
def __init__(self, scene, start_socket=None, end_socket=None, wire_type=3):
"""
This method initializes an instance of the ``Wire`` Class.
:param scene: a scene (or canvas) in which the Wire is stored and shown (or painted into). Provided by the ``Interface``.
:type scene: ``Scene``, required
:param start_socket: the start Socket of this Wire
:type start_socket: Socket, optional, defaults to None (automatically set)
:param end_socket: the end Socket of this Wire
:type end_socket: Socket, optional, defaults to None (automatically set)
:param wire_type: the wire style of this Wire (DIRECT(1), BEZIER(2), STEP(3))
:type wire_type: enumerate, optional, defaults to STEP(3) (automatically set)
"""
super().__init__()
self.scene = scene
# By default the Wire starts with no sockets, these are automatically
# set by decorators when a Wire instance is created
self._start_socket = None
self._end_socket = None
self.start_socket = start_socket
self.end_socket = end_socket
self.wire_type = wire_type
self.wire_coordinates = []
self.horizontal_segments = []
self.vertical_segments = []
self.intersections = []
# Once created, the wire is added to the Scene
self.scene.addWire(self)
# -----------------------------------------------------------------------------
@property
def start_socket(self):
"""
This method is a decorate that gets the start socket of this Wire.
:return: the start Socket of this Wire
:rtype: Socket
"""
return self._start_socket
# -----------------------------------------------------------------------------
@start_socket.setter
def start_socket(self, value):
"""
This method is a decorator that sets the start socket of this Wire to the
given value (which is a Socket).
:param value: the Socket being assigned
:type value: Socket
"""
# If this wire was assigned to some socket before, delete this wire instance from that socket
if self._start_socket is not None:
self._start_socket.removeWire(self)
# Assign a new start socket for this wire
self._start_socket = value
# Add this wire to the associated Socket (in the Socket Class)
if self.start_socket is not None:
self.start_socket.setConnectedEdge(self)
# -----------------------------------------------------------------------------
@property
def end_socket(self):
"""
This method is a decorate that gets the end socket of this Wire.
:return: the end Socket of this Wire
:rtype: Socket
"""
return self._end_socket
# -----------------------------------------------------------------------------
@end_socket.setter
def end_socket(self, value):
"""
This method is a decorator that sets the end socket of this Wire to the
given value (which is a Socket).
:param value: the Socket being assigned
:type value: Socket
"""
# If this wire was assigned to some socket before, delete this wire instance from that socket
if self._end_socket is not None:
self._end_socket.removeWire(self)
# Assign a new start socket for this wire
self._end_socket = value
# Add this wire to the associated Socket (in the Socket Class)
if self.end_socket is not None:
self.end_socket.setConnectedEdge(self)
# -----------------------------------------------------------------------------
@property
def wire_type(self):
"""
This method is a decorate that gets the wire type (or style) of this Wire.
:return: the style of this Wire (DIRECT(1), BEZIER(2), STEP(3))
:rtype: enumerate
"""
return self._wire_type
# -----------------------------------------------------------------------------
@wire_type.setter
def wire_type(self, value):
"""
This method is a decorator that sets the wire type (or style) of this Wire to the
given value (which is an enum). This method will determine how the wire is drawn.
By default the wire type is set to draw STEP(3) wires, however other line styles
can also be added here. The wire type dictate which corresponding GraphicsWire
class is called to draw the wire.
:param value: the wire type this Wire is being set to
:type value: enumerate
"""
# If this was already previously assigned, remove its GraphicsWire
if hasattr(self, "grWire") and self.grWire is not None:
self.scene.grScene.removeItem(self.grWire)
# Assign a new wire type for this wire
self._wire_type = value
# Depending on the updated wire_type of this Wire, create a
# instance of a GraphicsWire for this Wire
if self.wire_type == WIRE_TYPE_DIRECT:
self.grWire = GraphicsWireDirect(self)
elif self.wire_type == WIRE_TYPE_STEP:
self.grWire = GraphicsWireStep(self)
else:
self.grWire = GraphicsWireBezier(self)
# Add the wire to the GraphicsScene
self.scene.grScene.addItem(self.grWire)
# If a start socket has been assigned, update where the Wire is drawn from
if self.start_socket is not None:
self.updatePositions()
def setFocusOfWire(self):
"""
This method sends all ``Wire`` instances within the ``Scene`` to back
and then sends the currently selected ``Wire`` instance to front.
"""
# Iterates through each wire within wire list stored in the Scene Class
# and sets the graphical component of each wire to a zValue of -2.
for wire in self.scene.wires:
wire.grWire.setZValue(-2)
# Then sets the graphical component of the currently selected wire to a
# zValue of -1, which makes it display above all other wires on screen.
self.grWire.setZValue(-1)
# -----------------------------------------------------------------------------
def updatePositions(self):
"""
This method grabs the new positions of sockets on blocks as they are moved
around within the scene, in order to determine the positions which the
wire should connect. The redrawing of the wire to these positions will also
be handled within this method.
"""
# Grabs the current position (LEFT/RIGHT) of the starting socket
# and sets the associated source (start) socket orientation (position) within
# the GraphicsWire Class
source_pos_orientation = self.start_socket.position
self.grWire.setSourceOrientation(source_pos_orientation)
# Grabs the position of the start socket and splits it into x,y coordinates
# then assigns the position of the source (start) socket to these coordinates
source_pos = self.start_socket.getSocketPosition()
source_pos[0] += self.start_socket.node.grBlock.pos().x()
source_pos[1] += self.start_socket.node.grBlock.pos().y()
self.grWire.setSource(*source_pos)
# If an end socket has been set for this wire, the same logic as above will
# be applied, otherwise the destination (end) socket will be set to the coordinates
# of the source (start) socket. This will be fixed when the wire is completed and remade.
if self.end_socket is not None:
destination_pos_orientation = self.end_socket.position
self.grWire.setDestinationOrientation(destination_pos_orientation)
end_pos = self.end_socket.getSocketPosition()
end_pos[0] += self.end_socket.node.grBlock.pos().x()
end_pos[1] += self.end_socket.node.grBlock.pos().y()
self.grWire.setDestination(*end_pos)
else:
self.grWire.setDestination(*source_pos)
# The wire is called to be updated
self.grWire.update()
# -----------------------------------------------------------------------------
def remove_from_sockets(self):
"""
This method will un-assign the start and end sockets of this Wire.
"""
self.end_socket = None
self.start_socket = None
# -----------------------------------------------------------------------------
def remove(self):
"""
This method will remove the selected Wire from the Scene, un-assign
the Sockets that related to it, and remove the Wire from these Sockets.
"""
if self in self.scene.wires:
if DEBUG:
print("# Removing Wire", self)
if DEBUG:
print(" - hiding grWire")
self.grWire.hide()
if DEBUG:
print(" - removing grWire")
self.scene.grScene.removeItem(self.grWire)
if DEBUG:
print(" - removing wire from all sockets", self)
self.remove_from_sockets()
if DEBUG:
print(" - removing wire from scene")
try:
self.scene.removeWire(self)
except ValueError as e:
print("Error removing wire:", e)
pass
if DEBUG:
print(" - updating wire intersection points")
if self.scene.wires:
self.scene.wires[0].checkIntersections()
if DEBUG:
print(" - everything is done.")
else:
if DEBUG:
print("# Wire already removed")
# -----------------------------------------------------------------------------
def serialize(self):
"""
This method is called to create an ordered dictionary of all of this Wires'
parameters - necessary for the reconstruction of this Wire - as key-value
pairs. This dictionary is later used for writing into a JSON file.
:return: an ``OrderedDict`` of [keys, values] pairs of all essential ``Wire``
parameters.
:rtype: OrderedDict, ([keys, values]*)
"""
if self.grWire.customlogicOverride:
wire_coords = copy.copy(self.wire_coordinates)
else:
wire_coords = []
return OrderedDict(
[
("id", self.id),
("start_socket", self.start_socket.id),
("end_socket", self.end_socket.id),
("wire_type", self.wire_type),
("custom_routing", self.grWire.customlogicOverride),
("wire_coordinates", wire_coords),
]
)
# -----------------------------------------------------------------------------
def deserialize(self, data, hashmap={}):
"""
This method is called to reconstruct a ``Wire`` when loading a saved JSON
file containing all relevant information to recreate the ``Scene`` with all
its items.
:param data: a Dictionary of essential information for reconstructing a ``Wire``
:type data: OrderedDict, required
:param hashmap: a Dictionary for directly mapping the essential wire variables
to this instance of ``Wire``, without having to individually map each variable
:type hashmap: Dict, required
:return: True when completed successfully
:rtype: Boolean
"""
# The id, and other variables of this Wire are set to whatever was stored
# as its id and other variables in the JSON file.
self.id = data["id"]
# self.start_socket = data['start_socket']
# self.end_socket = data['end_socket']
self.start_socket = hashmap[data["start_socket"]]
self.end_socket = hashmap[data["end_socket"]]
self.wire_type = data["wire_type"]
# For newer custom routing logic. If custom_routing exists within the saved JSON
# data, and that variable is true, override the current wire_coordiantes of the wire
# to the ones saved in the file.
try:
if data["custom_routing"]:
self.grWire.customlogicOverride = data["custom_routing"]
try:
if data["wire_coordinates"]:
# Wire coordinates is supposed to be a list of tuples, but in JSON they
# are stored as a list of lists. So convert the points to tuples
new_wire_coordinates = []
for point in data["wire_coordinates"]:
new_wire_coordinates.append(tuple(point))
self.grWire.updateWireCoordinates(new_wire_coordinates)
except KeyError:
pass
except KeyError:
pass
return True
# -----------------------------------------------------------------------------
def checkIntersections(self):
"""
This method checks all active wires in the scene for intersections with other
wires. This method will be called any time a mouse movement is detected in
the GraphicsView class, which will cause the GraphicsScene to draw points
at these intersections to separate the wires.
To reduce computation for finding these intersection points, only vertical
line segments of wires are checked for intersections. This is because an
intersection point can only occur when a horizontal line segment of one wire
meets a vertical line segment of another wire, and every single wire has a
horizontal segment (as sockets are drawn on the LEFT or RIGHT sides of a Block).
When this method is called, the current intersection points are deleted, as
all wires are checked against in this method, and as such, any new (or previous)
intersection points will be appended into a list of intersection points that
is stored within the GraphicsScene Class.
"""
# Clear the intersection list stored within the scene of any previous intersection points
self.scene.intersection_list.clear()
# Grab the number of wires currently in the scene
number_of_wires = len(self.scene.wires)
# If there are more than 1 wires, check for overlapping
if number_of_wires > 1:
# Iterate through each wire in list of wires
for i in range(0, number_of_wires):
# If the wire has a vertical segment, check intersections against other wires
# Else ignore (as wire only has horizontal segments, and these cant create an intersection point
# unless a vertical line passes through them)
wire_has_vert = self.scene.wires[i].vertical_segments
if wire_has_vert:
# Check each vertical segment against horizontal segments of other wires
for vertical_segment in wire_has_vert:
for j in range(0, number_of_wires):
# If j==i this means the same wire is being checked, ignore checking this wire (cannot overlap with itself)
if j == i:
pass
# Or if wire 'j' starts from the same socket as 'i', ignore this wire
elif (
self.scene.wires[j].start_socket
== self.scene.wires[i].start_socket
):
pass
else:
# Iterate through each horizontal segments of the wire being checked
for horizontal_segment in self.scene.wires[
j
].horizontal_segments:
# In a vertical wire with points [(a1,b1), (a2,b2)], the horizontal coordinates will be
# equal, hence the wire is essentially [(a,b1), (a,b2)]
# In a horizontal wire with points [(x1,y1), (x2,y2)], the vertical coordinates will be
# equal, hence the wire is essentially [(x1,y), (x2,y)]
# If vertical points of wire with a vertical segment, are intersecting the y coordinate
# of a horizontal segment of the wire being checked against
# Essentially checking if b1 <= y <= b2 (if y is between b1 and b2)
if (
vertical_segment[0][1]
<= horizontal_segment[0][1]
<= vertical_segment[1][1]
or vertical_segment[0][1]
>= horizontal_segment[0][1]
>= vertical_segment[1][1]
):
if DEBUG_OVERLAP:
print(
"y coords of vert segment within y coord of horizontal seg"
)
# There may be a possible intersection, so now
# check if the horizontal points of wire with a vertical segment, intersects through
# the x coordinate of a horizontal segment of the wire being checked against
# Essentially checking if x1 <= a <= x2 (if a is between x1 and x2)
if (
horizontal_segment[0][0]
<= vertical_segment[0][0]
<= horizontal_segment[1][0]
or horizontal_segment[0][0]
>= vertical_segment[0][0]
>= horizontal_segment[1][0]
):
if DEBUG_OVERLAP:
print(
"x coord of vert segment within x coords of horizontal seg"
)
# The intersection point is (a, y)
# (a -> x coord from vertical segment, y -> y coord from horizontal segment)
# An intersection is found, append the point to the wire's list of intersections
# self.intersections.append((vertical_segment[0][0], horizontal_segment[0][1]))
# Append intersection point into list of intersection points (stored within the scene)
if (
vertical_segment[0][0],
horizontal_segment[0][1],
) not in self.scene.intersection_list:
self.scene.intersection_list.append(
(
vertical_segment[0][0],
horizontal_segment[0][1],
)
)
================================================
FILE: bdsim/bdedit/docs/.buildinfo
================================================
# Sphinx build info version 1
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
config: 9b83c4d3849f0701fab540b588e30695
tags: 645f666f9bcd5a90fca523b33c5a78b7
================================================
FILE: bdsim/bdedit/docs/_sources/bdedit.rst.txt
================================================
bdedit package
==============
Submodules
----------
bdedit.Icons module
-------------------
.. automodule:: bdedit.Icons
:members:
:undoc-members:
:show-inheritance:
bdedit.block module
-------------------
.. automodule:: bdedit.block
:members:
:special-members: __init__
:undoc-members:
:show-inheritance:
bdedit.block\_graphics\_block module
------------------------------------
.. automodule:: bdedit.block_graphics_block
:members:
:special-members: __init__
:undoc-members:
:show-inheritance:
bdedit.block\_graphics\_socket module
-------------------------------------
.. automodule:: bdedit.block_graphics_socket
:members:
:special-members: __init__
:undoc-members:
:show-inheritance:
bdedit.block\_graphics\_wire module
-----------------------------------
.. automodule:: bdedit.block_graphics_wire
:members:
:special-members: __init__
:undoc-members:
:show-inheritance:
bdedit.block\_param\_window module
----------------------------------
.. automodule:: bdedit.block_param_window
:members:
:special-members: __init__
:undoc-members:
:show-inheritance:
bdedit.block\_socket module
---------------------------
.. automodule:: bdedit.block_socket
:members:
:special-members: __init__
:undoc-members:
:show-inheritance:
bdedit.block\_socket\_block module
----------------------------------
.. automodule:: bdedit.block_socket_block
:members:
:special-members: __init__
:undoc-members:
:show-inheritance:
bdedit.block\_wire module
-------------------------
.. automodule:: bdedit.block_wire
:members:
:special-members: __init__
:undoc-members:
:show-inheritance:
bdedit.interface module
-----------------------
.. automodule:: bdedit.interface
:members:
:special-members: __init__
:undoc-members:
:show-inheritance:
bdedit.interface\_graphics\_scene module
----------------------------------------
.. automodule:: bdedit.interface_graphics_scene
:members:
:special-members: __init__
:undoc-members:
:show-inheritance:
bdedit.interface\_graphics\_view module
---------------------------------------
.. automodule:: bdedit.interface_graphics_view
:members:
:special-members: __init__
:undoc-members:
:show-inheritance:
bdedit.interface\_scene module
------------------------------
.. automodule:: bdedit.interface_scene
:members:
:special-members: __init__
:undoc-members:
:show-inheritance:
bdedit.interface\_serialize module
----------------------------------
.. automodule:: bdedit.interface_serialize
:members:
:special-members: __init__
:undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: bdedit
:members:
:special-members: __init__
:undoc-members:
:show-inheritance:
================================================
FILE: bdsim/bdedit/docs/_sources/index.rst.txt
================================================
.. BdEdit documentation master file, created by
sphinx-quickstart on Wed Jun 9 03:42:11 2021.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to BdEdit's documentation!
==================================
.. toctree::
:maxdepth: 2
:caption: Contents:
modules
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
================================================
FILE: bdsim/bdedit/docs/_sources/modules.rst.txt
================================================
bdedit
======
.. toctree::
:maxdepth: 4
bdedit
================================================
FILE: bdsim/bdedit/docs/_static/alabaster.css
================================================
@import url("basic.css");
/* -- page layout ----------------------------------------------------------- */
body {
font-family: Georgia, serif;
font-size: 17px;
background-color: #fff;
color: #000;
margin: 0;
padding: 0;
}
div.document {
width: 940px;
margin: 30px auto 0 auto;
}
div.documentwrapper {
float: left;
width: 100%;
}
div.bodywrapper {
margin: 0 0 0 220px;
}
div.sphinxsidebar {
width: 220px;
font-size: 14px;
line-height: 1.5;
}
hr {
border: 1px solid #B1B4B6;
}
div.body {
background-color: #fff;
color: #3E4349;
padding: 0 30px 0 30px;
}
div.body > .section {
text-align: left;
}
div.footer {
width: 940px;
margin: 20px auto 30px auto;
font-size: 14px;
color: #888;
text-align: right;
}
div.footer a {
color: #888;
}
p.caption {
font-family: inherit;
font-size: inherit;
}
div.relations {
display: none;
}
div.sphinxsidebar a {
color: #444;
text-decoration: none;
border-bottom: 1px dotted #999;
}
div.sphinxsidebar a:hover {
border-bottom: 1px solid #999;
}
div.sphinxsidebarwrapper {
padding: 18px 10px;
}
div.sphinxsidebarwrapper p.logo {
padding: 0;
margin: -10px 0 0 0px;
text-align: center;
}
div.sphinxsidebarwrapper h1.logo {
margin-top: -10px;
text-align: center;
margin-bottom: 5px;
text-align: left;
}
div.sphinxsidebarwrapper h1.logo-name {
margin-top: 0px;
}
div.sphinxsidebarwrapper p.blurb {
margin-top: 0;
font-style: normal;
}
div.sphinxsidebar h3,
div.sphinxsidebar h4 {
font-family: Georgia, serif;
color: #444;
font-size: 24px;
font-weight: normal;
margin: 0 0 5px 0;
padding: 0;
}
div.sphinxsidebar h4 {
font-size: 20px;
}
div.sphinxsidebar h3 a {
color: #444;
}
div.sphinxsidebar p.logo a,
div.sphinxsidebar h3 a,
div.sphinxsidebar p.logo a:hover,
div.sphinxsidebar h3 a:hover {
border: none;
}
div.sphinxsidebar p {
color: #555;
margin: 10px 0;
}
div.sphinxsidebar ul {
margin: 10px 0;
padding: 0;
color: #000;
}
div.sphinxsidebar ul li.toctree-l1 > a {
font-size: 120%;
}
div.sphinxsidebar ul li.toctree-l2 > a {
font-size: 110%;
}
div.sphinxsidebar input {
border: 1px solid #CCC;
font-family: Georgia, serif;
font-size: 1em;
}
div.sphinxsidebar hr {
border: none;
height: 1px;
color: #AAA;
background: #AAA;
text-align: left;
margin-left: 0;
width: 50%;
}
div.sphinxsidebar .badge {
border-bottom: none;
}
div.sphinxsidebar .badge:hover {
border-bottom: none;
}
/* To address an issue with donation coming after search */
div.sphinxsidebar h3.donation {
margin-top: 10px;
}
/* -- body styles ----------------------------------------------------------- */
a {
color: #004B6B;
text-decoration: underline;
}
a:hover {
color: #6D4100;
text-decoration: underline;
}
div.body h1,
div.body h2,
div.body h3,
div.body h4,
div.body h5,
div.body h6 {
font-family: Georgia, serif;
font-weight: normal;
margin: 30px 0px 10px 0px;
padding: 0;
}
div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; }
div.body h2 { font-size: 180%; }
div.body h3 { font-size: 150%; }
div.body h4 { font-size: 130%; }
div.body h5 { font-size: 100%; }
div.body h6 { font-size: 100%; }
a.headerlink {
color: #DDD;
padding: 0 4px;
text-decoration: none;
}
a.headerlink:hover {
color: #444;
background: #EAEAEA;
}
div.body p, div.body dd, div.body li {
line-height: 1.4em;
}
div.admonition {
margin: 20px 0px;
padding: 10px 30px;
background-color: #EEE;
border: 1px solid #CCC;
}
div.admonition tt.xref, div.admonition code.xref, div.admonition a tt {
background-color: #FBFBFB;
border-bottom: 1px solid #fafafa;
}
div.admonition p.admonition-title {
font-family: Georgia, serif;
font-weight: normal;
font-size: 24px;
margin: 0 0 10px 0;
padding: 0;
line-height: 1;
}
div.admonition p.last {
margin-bottom: 0;
}
div.highlight {
background-color: #fff;
}
dt:target, .highlight {
background: #FAF3E8;
}
div.warning {
background-color: #FCC;
border: 1px solid #FAA;
}
div.danger {
background-color: #FCC;
border: 1px solid #FAA;
-moz-box-shadow: 2px 2px 4px #D52C2C;
-webkit-box-shadow: 2px 2px 4px #D52C2C;
box-shadow: 2px 2px 4px #D52C2C;
}
div.error {
background-color: #FCC;
border: 1px solid #FAA;
-moz-box-shadow: 2px 2px 4px #D52C2C;
-webkit-box-shadow: 2px 2px 4px #D52C2C;
box-shadow: 2px 2px 4px #D52C2C;
}
div.caution {
background-color: #FCC;
border: 1px solid #FAA;
}
div.attention {
background-color: #FCC;
border: 1px solid #FAA;
}
div.important {
background-color: #EEE;
border: 1px solid #CCC;
}
div.note {
background-color: #EEE;
border: 1px solid #CCC;
}
div.tip {
background-color: #EEE;
border: 1px solid #CCC;
}
div.hint {
background-color: #EEE;
border: 1px solid #CCC;
}
div.seealso {
background-color: #EEE;
border: 1px solid #CCC;
}
div.topic {
background-color: #EEE;
}
p.admonition-title {
display: inline;
}
p.admonition-title:after {
content: ":";
}
pre, tt, code {
font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
font-size: 0.9em;
}
.hll {
background-color: #FFC;
margin: 0 -12px;
padding: 0 12px;
display: block;
}
img.screenshot {
}
tt.descname, tt.descclassname, code.descname, code.descclassname {
font-size: 0.95em;
}
tt.descname, code.descname {
padding-right: 0.08em;
}
img.screenshot {
-moz-box-shadow: 2px 2px 4px #EEE;
-webkit-box-shadow: 2px 2px 4px #EEE;
box-shadow: 2px 2px 4px #EEE;
}
table.docutils {
border: 1px solid #888;
-moz-box-shadow: 2px 2px 4px #EEE;
-webkit-box-shadow: 2px 2px 4px #EEE;
box-shadow: 2px 2px 4px #EEE;
}
table.docutils td, table.docutils th {
border: 1px solid #888;
padding: 0.25em 0.7em;
}
table.field-list, table.footnote {
border: none;
-moz-box-shadow: none;
-webkit-box-shadow: none;
box-shadow: none;
}
table.footnote {
margin: 15px 0;
width: 100%;
border: 1px solid #EEE;
background: #FDFDFD;
font-size: 0.9em;
}
table.footnote + table.footnote {
margin-top: -15px;
border-top: none;
}
table.field-list th {
padding: 0 0.8em 0 0;
}
table.field-list td {
padding: 0;
}
table.field-list p {
margin-bottom: 0.8em;
}
/* Cloned from
* https://github.com/sphinx-doc/sphinx/commit/ef60dbfce09286b20b7385333d63a60321784e68
*/
.field-name {
-moz-hyphens: manual;
-ms-hyphens: manual;
-webkit-hyphens: manual;
hyphens: manual;
}
table.footnote td.label {
width: .1px;
padding: 0.3em 0 0.3em 0.5em;
}
table.footnote td {
padding: 0.3em 0.5em;
}
dl {
margin: 0;
padding: 0;
}
dl dd {
margin-left: 30px;
}
blockquote {
margin: 0 0 0 30px;
padding: 0;
}
ul, ol {
/* Matches the 30px from the narrow-screen "li > ul" selector below */
margin: 10px 0 10px 30px;
padding: 0;
}
pre {
background: #EEE;
padding: 7px 30px;
margin: 15px 0px;
line-height: 1.3em;
}
div.viewcode-block:target {
background: #ffd;
}
dl pre, blockquote pre, li pre {
margin-left: 0;
padding-left: 30px;
}
tt, code {
background-color: #ecf0f3;
color: #222;
/* padding: 1px 2px; */
}
tt.xref, code.xref, a tt {
background-color: #FBFBFB;
border-bottom: 1px solid #fff;
}
a.reference {
text-decoration: none;
border-bottom: 1px dotted #004B6B;
}
/* Don't put an underline on images */
a.image-reference, a.image-reference:hover {
border-bottom: none;
}
a.reference:hover {
border-bottom: 1px solid #6D4100;
}
a.footnote-reference {
text-decoration: none;
font-size: 0.7em;
vertical-align: top;
border-bottom: 1px dotted #004B6B;
}
a.footnote-reference:hover {
border-bottom: 1px solid #6D4100;
}
a:hover tt, a:hover code {
background: #EEE;
}
@media screen and (max-width: 870px) {
div.sphinxsidebar {
display: none;
}
div.document {
width: 100%;
}
div.documentwrapper {
margin-left: 0;
margin-top: 0;
margin-right: 0;
margin-bottom: 0;
}
div.bodywrapper {
margin-top: 0;
margin-right: 0;
margin-bottom: 0;
margin-left: 0;
}
ul {
margin-left: 0;
}
li > ul {
/* Matches the 30px from the "ul, ol" selector above */
margin-left: 30px;
}
.document {
width: auto;
}
.footer {
width: auto;
}
.bodywrapper {
margin: 0;
}
.footer {
width: auto;
}
.github {
display: none;
}
}
@media screen and (max-width: 875px) {
body {
margin: 0;
padding: 20px 30px;
}
div.documentwrapper {
float: none;
background: #fff;
}
div.sphinxsidebar {
display: block;
float: none;
width: 102.5%;
margin: 50px -30px -20px -30px;
padding: 10px 20px;
background: #333;
color: #FFF;
}
div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p,
div.sphinxsidebar h3 a {
color: #fff;
}
div.sphinxsidebar a {
color: #AAA;
}
div.sphinxsidebar p.logo {
display: none;
}
div.document {
width: 100%;
margin: 0;
}
div.footer {
display: none;
}
div.bodywrapper {
margin: 0;
}
div.body {
min-height: 0;
padding: 0;
}
.rtd_doc_footer {
display: none;
}
.document {
width: auto;
}
.footer {
width: auto;
}
.footer {
width: auto;
}
.github {
display: none;
}
}
/* misc. */
.revsys-inline {
display: none!important;
}
/* Make nested-list/multi-paragraph items look better in Releases changelog
* pages. Without this, docutils' magical list fuckery causes inconsistent
* formatting between different release sub-lists.
*/
div#changelog > div.section > ul > li > p:only-child {
margin-bottom: 0;
}
/* Hide fugly table cell borders in ..bibliography:: directive output */
table.docutils.citation, table.docutils.citation td, table.docutils.citation th {
border: none;
/* Below needed in some edge cases; if not applied, bottom shadows appear */
-moz-box-shadow: none;
-webkit-box-shadow: none;
box-shadow: none;
}
/* relbar */
.related {
line-height: 30px;
width: 100%;
font-size: 0.9rem;
}
.related.top {
border-bottom: 1px solid #EEE;
margin-bottom: 20px;
}
.related.bottom {
border-top: 1px solid #EEE;
}
.related ul {
padding: 0;
margin: 0;
list-style: none;
}
.related li {
display: inline;
}
nav#rellinks {
float: right;
}
nav#rellinks li+li:before {
content: "|";
}
nav#breadcrumbs li+li:before {
content: "\00BB";
}
/* Hide certain items when printing */
@media print {
div.related {
display: none;
}
}
================================================
FILE: bdsim/bdedit/docs/_static/basic.css
================================================
/*
* basic.css
* ~~~~~~~~~
*
* Sphinx stylesheet -- basic theme.
*
* :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
/* -- main layout ----------------------------------------------------------- */
div.clearer {
clear: both;
}
div.section::after {
display: block;
content: '';
clear: left;
}
/* -- relbar ---------------------------------------------------------------- */
div.related {
width: 100%;
font-size: 90%;
}
div.related h3 {
display: none;
}
div.related ul {
margin: 0;
padding: 0 0 0 10px;
list-style: none;
}
div.related li {
display: inline;
}
div.related li.right {
float: right;
margin-right: 5px;
}
/* -- sidebar --------------------------------------------------------------- */
div.sphinxsidebarwrapper {
padding: 10px 5px 0 10px;
}
div.sphinxsidebar {
float: left;
width: 230px;
margin-left: -100%;
font-size: 90%;
word-wrap: break-word;
overflow-wrap : break-word;
}
div.sphinxsidebar ul {
list-style: none;
}
div.sphinxsidebar ul ul,
div.sphinxsidebar ul.want-points {
margin-left: 20px;
list-style: square;
}
div.sphinxsidebar ul ul {
margin-top: 0;
margin-bottom: 0;
}
div.sphinxsidebar form {
margin-top: 10px;
}
div.sphinxsidebar input {
border: 1px solid #98dbcc;
font-family: sans-serif;
font-size: 1em;
}
div.sphinxsidebar #searchbox form.search {
overflow: hidden;
}
div.sphinxsidebar #searchbox input[type="text"] {
float: left;
width: 80%;
padding: 0.25em;
box-sizing: border-box;
}
div.sphinxsidebar #searchbox input[type="submit"] {
float: left;
width: 20%;
border-left: none;
padding: 0.25em;
box-sizing: border-box;
}
img {
border: 0;
max-width: 100%;
}
/* -- search page ----------------------------------------------------------- */
ul.search {
margin: 10px 0 0 20px;
padding: 0;
}
ul.search li {
padding: 5px 0 5px 20px;
background-image: url(file.png);
background-repeat: no-repeat;
background-position: 0 7px;
}
ul.search li a {
font-weight: bold;
}
ul.search li p.context {
color: #888;
margin: 2px 0 0 30px;
text-align: left;
}
ul.keywordmatches li.goodmatch a {
font-weight: bold;
}
/* -- index page ------------------------------------------------------------ */
table.contentstable {
width: 90%;
margin-left: auto;
margin-right: auto;
}
table.contentstable p.biglink {
line-height: 150%;
}
a.biglink {
font-size: 1.3em;
}
span.linkdescr {
font-style: italic;
padding-top: 5px;
font-size: 90%;
}
/* -- general index --------------------------------------------------------- */
table.indextable {
width: 100%;
}
table.indextable td {
text-align: left;
vertical-align: top;
}
table.indextable ul {
margin-top: 0;
margin-bottom: 0;
list-style-type: none;
}
table.indextable > tbody > tr > td > ul {
padding-left: 0em;
}
table.indextable tr.pcap {
height: 10px;
}
table.indextable tr.cap {
margin-top: 10px;
background-color: #f2f2f2;
}
img.toggler {
margin-right: 3px;
margin-top: 3px;
cursor: pointer;
}
div.modindex-jumpbox {
border-top: 1px solid #ddd;
border-bottom: 1px solid #ddd;
margin: 1em 0 1em 0;
padding: 0.4em;
}
div.genindex-jumpbox {
border-top: 1px solid #ddd;
border-bottom: 1px solid #ddd;
margin: 1em 0 1em 0;
padding: 0.4em;
}
/* -- domain module index --------------------------------------------------- */
table.modindextable td {
padding: 2px;
border-collapse: collapse;
}
/* -- general body styles --------------------------------------------------- */
div.body {
min-width: 450px;
max-width: 800px;
}
div.body p, div.body dd, div.body li, div.body blockquote {
-moz-hyphens: auto;
-ms-hyphens: auto;
-webkit-hyphens: auto;
hyphens: auto;
}
a.headerlink {
visibility: hidden;
}
a.brackets:before,
span.brackets > a:before{
content: "[";
}
a.brackets:after,
span.brackets > a:after {
content: "]";
}
h1:hover > a.headerlink,
h2:hover > a.headerlink,
h3:hover > a.headerlink,
h4:hover > a.headerlink,
h5:hover > a.headerlink,
h6:hover > a.headerlink,
dt:hover > a.headerlink,
caption:hover > a.headerlink,
p.caption:hover > a.headerlink,
div.code-block-caption:hover > a.headerlink {
visibility: visible;
}
div.body p.caption {
text-align: inherit;
}
div.body td {
text-align: left;
}
.first {
margin-top: 0 !important;
}
p.rubric {
margin-top: 30px;
font-weight: bold;
}
img.align-left, figure.align-left, .figure.align-left, object.align-left {
clear: left;
float: left;
margin-right: 1em;
}
img.align-right, figure.align-right, .figure.align-right, object.align-right {
clear: right;
float: right;
margin-left: 1em;
}
img.align-center, figure.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
img.align-default, figure.align-default, .figure.align-default {
display: block;
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left;
}
.align-center {
text-align: center;
}
.align-default {
text-align: center;
}
.align-right {
text-align: right;
}
/* -- sidebars -------------------------------------------------------------- */
div.sidebar,
aside.sidebar {
margin: 0 0 0.5em 1em;
border: 1px solid #ddb;
padding: 7px;
background-color: #ffe;
width: 40%;
float: right;
clear: right;
overflow-x: auto;
}
p.sidebar-title {
font-weight: bold;
}
div.admonition, div.topic, blockquote {
clear: left;
}
/* -- topics ---------------------------------------------------------------- */
div.topic {
border: 1px solid #ccc;
padding: 7px;
margin: 10px 0 10px 0;
}
p.topic-title {
font-size: 1.1em;
font-weight: bold;
margin-top: 10px;
}
/* -- admonitions ----------------------------------------------------------- */
div.admonition {
margin-top: 10px;
margin-bottom: 10px;
padding: 7px;
}
div.admonition dt {
font-weight: bold;
}
p.admonition-title {
margin: 0px 10px 5px 0px;
font-weight: bold;
}
div.body p.centered {
text-align: center;
margin-top: 25px;
}
/* -- content of sidebars/topics/admonitions -------------------------------- */
div.sidebar > :last-child,
aside.sidebar > :last-child,
div.topic > :last-child,
div.admonition > :last-child {
margin-bottom: 0;
}
div.sidebar::after,
aside.sidebar::after,
div.topic::after,
div.admonition::after,
blockquote::after {
display: block;
content: '';
clear: both;
}
/* -- tables ---------------------------------------------------------------- */
table.docutils {
margin-top: 10px;
margin-bottom: 10px;
border: 0;
border-collapse: collapse;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
table.align-default {
margin-left: auto;
margin-right: auto;
}
table caption span.caption-number {
font-style: italic;
}
table caption span.caption-text {
}
table.docutils td, table.docutils th {
padding: 1px 8px 1px 5px;
border-top: 0;
border-left: 0;
border-right: 0;
border-bottom: 1px solid #aaa;
}
table.footnote td, table.footnote th {
border: 0 !important;
}
th {
text-align: left;
padding-right: 5px;
}
table.citation {
border-left: solid 1px gray;
margin-left: 1px;
}
table.citation td {
border-bottom: none;
}
th > :first-child,
td > :first-child {
margin-top: 0px;
}
th > :last-child,
td > :last-child {
margin-bottom: 0px;
}
/* -- figures --------------------------------------------------------------- */
div.figure, figure {
margin: 0.5em;
padding: 0.5em;
}
div.figure p.caption, figcaption {
padding: 0.3em;
}
div.figure p.caption span.caption-number,
figcaption span.caption-number {
font-style: italic;
}
div.figure p.caption span.caption-text,
figcaption span.caption-text {
}
/* -- field list styles ----------------------------------------------------- */
table.field-list td, table.field-list th {
border: 0 !important;
}
.field-list ul {
margin: 0;
padding-left: 1em;
}
.field-list p {
margin: 0;
}
.field-name {
-moz-hyphens: manual;
-ms-hyphens: manual;
-webkit-hyphens: manual;
hyphens: manual;
}
/* -- hlist styles ---------------------------------------------------------- */
table.hlist {
margin: 1em 0;
}
table.hlist td {
vertical-align: top;
}
/* -- object description styles --------------------------------------------- */
.sig {
font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
}
.sig-name, code.descname {
background-color: transparent;
font-weight: bold;
}
.sig-name {
font-size: 1.1em;
}
code.descname {
font-size: 1.2em;
}
.sig-prename, code.descclassname {
background-color: transparent;
}
.optional {
font-size: 1.3em;
}
.sig-paren {
font-size: larger;
}
.sig-param.n {
font-style: italic;
}
/* C++ specific styling */
.sig-inline.c-texpr,
.sig-inline.cpp-texpr {
font-family: unset;
}
.sig.c .k, .sig.c .kt,
.sig.cpp .k, .sig.cpp .kt {
color: #0033B3;
}
.sig.c .m,
.sig.cpp .m {
color: #1750EB;
}
.sig.c .s, .sig.c .sc,
.sig.cpp .s, .sig.cpp .sc {
color: #067D17;
}
/* -- other body styles ----------------------------------------------------- */
ol.arabic {
list-style: decimal;
}
ol.loweralpha {
list-style: lower-alpha;
}
ol.upperalpha {
list-style: upper-alpha;
}
ol.lowerroman {
list-style: lower-roman;
}
ol.upperroman {
list-style: upper-roman;
}
:not(li) > ol > li:first-child > :first-child,
:not(li) > ul > li:first-child > :first-child {
margin-top: 0px;
}
:not(li) > ol > li:last-child > :last-child,
:not(li) > ul > li:last-child > :last-child {
margin-bottom: 0px;
}
ol.simple ol p,
ol.simple ul p,
ul.simple ol p,
ul.simple ul p {
margin-top: 0;
}
ol.simple > li:not(:first-child) > p,
ul.simple > li:not(:first-child) > p {
margin-top: 0;
}
ol.simple p,
ul.simple p {
margin-bottom: 0;
}
dl.footnote > dt,
dl.citation > dt {
float: left;
margin-right: 0.5em;
}
dl.footnote > dd,
dl.citation > dd {
margin-bottom: 0em;
}
dl.footnote > dd:after,
dl.citation > dd:after {
content: "";
clear: both;
}
dl.field-list {
display: grid;
grid-template-columns: fit-content(30%) auto;
}
dl.field-list > dt {
font-weight: bold;
word-break: break-word;
padding-left: 0.5em;
padding-right: 5px;
}
dl.field-list > dt:after {
content: ":";
}
dl.field-list > dd {
padding-left: 0.5em;
margin-top: 0em;
margin-left: 0em;
margin-bottom: 0em;
}
dl {
margin-bottom: 15px;
}
dd > :first-child {
margin-top: 0px;
}
dd ul, dd table {
margin-bottom: 10px;
}
dd {
margin-top: 3px;
margin-bottom: 10px;
margin-left: 30px;
}
dl > dd:last-child,
dl > dd:last-child > :last-child {
margin-bottom: 0;
}
dt:target, span.highlighted {
background-color: #fbe54e;
}
rect.highlighted {
fill: #fbe54e;
}
dl.glossary dt {
font-weight: bold;
font-size: 1.1em;
}
.versionmodified {
font-style: italic;
}
.system-message {
background-color: #fda;
padding: 5px;
border: 3px solid red;
}
.footnote:target {
background-color: #ffa;
}
.line-block {
display: block;
margin-top: 1em;
margin-bottom: 1em;
}
.line-block .line-block {
margin-top: 0;
margin-bottom: 0;
margin-left: 1.5em;
}
.guilabel, .menuselection {
font-family: sans-serif;
}
.accelerator {
text-decoration: underline;
}
.classifier {
font-style: oblique;
}
.classifier:before {
font-style: normal;
margin: 0.5em;
content: ":";
}
abbr, acronym {
border-bottom: dotted 1px;
cursor: help;
}
/* -- code displays --------------------------------------------------------- */
pre {
overflow: auto;
overflow-y: hidden; /* fixes display issues on Chrome browsers */
}
pre, div[class*="highlight-"] {
clear: both;
}
span.pre {
-moz-hyphens: none;
-ms-hyphens: none;
-webkit-hyphens: none;
hyphens: none;
}
div[class*="highlight-"] {
margin: 1em 0;
}
td.linenos pre {
border: 0;
background-color: transparent;
color: #aaa;
}
table.highlighttable {
display: block;
}
table.highlighttable tbody {
display: block;
}
table.highlighttable tr {
display: flex;
}
table.highlighttable td {
margin: 0;
padding: 0;
}
table.highlighttable td.linenos {
padding-right: 0.5em;
}
table.highlighttable td.code {
flex: 1;
overflow: hidden;
}
.highlight .hll {
display: block;
}
div.highlight pre,
table.highlighttable pre {
margin: 0;
}
div.code-block-caption + div {
margin-top: 0;
}
div.code-block-caption {
margin-top: 1em;
padding: 2px 5px;
font-size: small;
}
div.code-block-caption code {
background-color: transparent;
}
table.highlighttable td.linenos,
span.linenos,
div.doctest > div.highlight span.gp { /* gp: Generic.Prompt */
user-select: none;
-webkit-user-select: text; /* Safari fallback only */
-webkit-user-select: none; /* Chrome/Safari */
-moz-user-select: none; /* Firefox */
-ms-user-select: none; /* IE10+ */
}
div.code-block-caption span.caption-number {
padding: 0.1em 0.3em;
font-style: italic;
}
div.code-block-caption span.caption-text {
}
div.literal-block-wrapper {
margin: 1em 0;
}
code.xref, a code {
background-color: transparent;
font-weight: bold;
}
h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
background-color: transparent;
}
.viewcode-link {
float: right;
}
.viewcode-back {
float: right;
font-family: sans-serif;
}
div.viewcode-block:target {
margin: -1px -10px;
padding: 0 10px;
}
/* -- math display ---------------------------------------------------------- */
img.math {
vertical-align: middle;
}
div.body div.math p {
text-align: center;
}
span.eqno {
float: right;
}
span.eqno a.headerlink {
position: absolute;
z-index: 1;
}
div.math:hover a.headerlink {
visibility: visible;
}
/* -- printout stylesheet --------------------------------------------------- */
@media print {
div.document,
div.documentwrapper,
div.bodywrapper {
margin: 0 !important;
width: 100%;
}
div.sphinxsidebar,
div.related,
div.footer,
#top-link {
display: none;
}
}
================================================
FILE: bdsim/bdedit/docs/_static/css/badge_only.css
================================================
.fa:before{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-style:normal;font-weight:400;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#FontAwesome) format("svg")}.fa:before{font-family:FontAwesome;font-style:normal;font-weight:400;line-height:1}.fa:before,a .fa{text-decoration:inherit}.fa:before,a .fa,li .fa{display:inline-block}li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-.8em}ul.fas li .fa{width:.8em}ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before,.icon-book:before{content:"\f02d"}.fa-caret-down:before,.icon-caret-down:before{content:"\f0d7"}.fa-caret-up:before,.icon-caret-up:before{content:"\f0d8"}.fa-caret-left:before,.icon-caret-left:before{content:"\f0d9"}.fa-caret-right:before,.icon-caret-right:before{content:"\f0da"}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60}.rst-versions .rst-current-version:after{clear:both;content:"";display:block}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}
================================================
FILE: bdsim/bdedit/docs/_static/css/theme.css
================================================
html{box-sizing:border-box}*,:after,:before{box-sizing:inherit}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}[hidden],audio:not([controls]){display:none}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}blockquote{margin:0}dfn{font-style:italic}ins{background:#ff9;text-decoration:none}ins,mark{color:#000}mark{background:#ff0;font-style:italic;font-weight:700}.rst-content code,.rst-content tt,code,kbd,pre,samp{font-family:monospace,serif;_font-family:courier new,monospace;font-size:1em}pre{white-space:pre}q{quotes:none}q:after,q:before{content:"";content:none}small{font-size:85%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}dl,ol,ul{margin:0;padding:0;list-style:none;list-style-image:none}li{list-style:none}dd{margin:0}img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;max-width:100%}svg:not(:root){overflow:hidden}figure,form{margin:0}label{cursor:pointer}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,input[type=button],input[type=reset],input[type=submit]{cursor:pointer;-webkit-appearance:button;*overflow:visible}button[disabled],input[disabled]{cursor:default}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}textarea{resize:vertical}table{border-collapse:collapse;border-spacing:0}td{vertical-align:top}.chromeframe{margin:.2em 0;background:#ccc;color:#000;padding:.2em 0}.ir{display:block;border:0;text-indent:-999em;overflow:hidden;background-color:transparent;background-repeat:no-repeat;text-align:left;direction:ltr;*line-height:0}.ir br{display:none}.hidden{display:none!important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.relative{position:relative}big,small{font-size:100%}@media print{body,html,section{background:none!important}*{box-shadow:none!important;text-shadow:none!important;filter:none!important;-ms-filter:none!important}a,a:visited{text-decoration:underline}.ir a:after,a[href^="#"]:after,a[href^="javascript:"]:after{content:""}blockquote,pre{page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}.rst-content .toctree-wrapper>p.caption,h2,h3,p{orphans:3;widows:3}.rst-content .toctree-wrapper>p.caption,h2,h3{page-break-after:avoid}}.btn,.fa:before,.icon:before,.rst-content .admonition,.rst-content .admonition-title:before,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .code-block-caption .headerlink:before,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-alert,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a,.wy-menu-vertical li.current>a span.toctree-expand:before,.wy-menu-vertical li.on a,.wy-menu-vertical li.on a span.toctree-expand:before,.wy-menu-vertical li span.toctree-expand:before,.wy-nav-top a,.wy-side-nav-search .wy-dropdown>a,.wy-side-nav-search>a,input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week],select,textarea{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}/*!
* Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome
* License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
*/@font-face{font-family:FontAwesome;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713);src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix&v=4.7.0) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#fontawesomeregular) format("svg");font-weight:400;font-style:normal}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-menu-vertical li.current>a span.toctree-expand,.wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li span.toctree-expand{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14286em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14286em;width:2.14286em;top:.14286em;text-align:center}.fa-li.fa-lg{left:-1.85714em}.fa-border{padding:.2em .25em .15em;border:.08em solid #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa-pull-left.icon,.fa.fa-pull-left,.rst-content .code-block-caption .fa-pull-left.headerlink,.rst-content .fa-pull-left.admonition-title,.rst-content code.download span.fa-pull-left:first-child,.rst-content dl dt .fa-pull-left.headerlink,.rst-content h1 .fa-pull-left.headerlink,.rst-content h2 .fa-pull-left.headerlink,.rst-content h3 .fa-pull-left.headerlink,.rst-content h4 .fa-pull-left.headerlink,.rst-content h5 .fa-pull-left.headerlink,.rst-content h6 .fa-pull-left.headerlink,.rst-content p.caption .fa-pull-left.headerlink,.rst-content table>caption .fa-pull-left.headerlink,.rst-content tt.download span.fa-pull-left:first-child,.wy-menu-vertical li.current>a span.fa-pull-left.toctree-expand,.wy-menu-vertical li.on a span.fa-pull-left.toctree-expand,.wy-menu-vertical li span.fa-pull-left.toctree-expand{margin-right:.3em}.fa-pull-right.icon,.fa.fa-pull-right,.rst-content .code-block-caption .fa-pull-right.headerlink,.rst-content .fa-pull-right.admonition-title,.rst-content code.download span.fa-pull-right:first-child,.rst-content dl dt .fa-pull-right.headerlink,.rst-content h1 .fa-pull-right.headerlink,.rst-content h2 .fa-pull-right.headerlink,.rst-content h3 .fa-pull-right.headerlink,.rst-content h4 .fa-pull-right.headerlink,.rst-content h5 .fa-pull-right.headerlink,.rst-content h6 .fa-pull-right.headerlink,.rst-content p.caption .fa-pull-right.headerlink,.rst-content table>caption .fa-pull-right.headerlink,.rst-content tt.download span.fa-pull-right:first-child,.wy-menu-vertical li.current>a span.fa-pull-right.toctree-expand,.wy-menu-vertical li.on a span.fa-pull-right.toctree-expand,.wy-menu-vertical li span.fa-pull-right.toctree-expand{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left,.pull-left.icon,.rst-content .code-block-caption .pull-left.headerlink,.rst-content .pull-left.admonition-title,.rst-content code.download span.pull-left:first-child,.rst-content dl dt .pull-left.headerlink,.rst-content h1 .pull-left.headerlink,.rst-content h2 .pull-left.headerlink,.rst-content h3 .pull-left.headerlink,.rst-content h4 .pull-left.headerlink,.rst-content h5 .pull-left.headerlink,.rst-content h6 .pull-left.headerlink,.rst-content p.caption .pull-left.headerlink,.rst-content table>caption .pull-left.headerlink,.rst-content tt.download span.pull-left:first-child,.wy-menu-vertical li.current>a span.pull-left.toctree-expand,.wy-menu-vertical li.on a span.pull-left.toctree-expand,.wy-menu-vertical li span.pull-left.toctree-expand{margin-right:.3em}.fa.pull-right,.pull-right.icon,.rst-content .code-block-caption .pull-right.headerlink,.rst-content .pull-right.admonition-title,.rst-content code.download span.pull-right:first-child,.rst-content dl dt .pull-right.headerlink,.rst-content h1 .pull-right.headerlink,.rst-content h2 .pull-right.headerlink,.rst-content h3 .pull-right.headerlink,.rst-content h4 .pull-right.headerlink,.rst-content h5 .pull-right.headerlink,.rst-content h6 .pull-right.headerlink,.rst-content p.caption .pull-right.headerlink,.rst-content table>caption .pull-right.headerlink,.rst-content tt.download span.pull-right:first-child,.wy-menu-vertical li.current>a span.pull-right.toctree-expand,.wy-menu-vertical li.on a span.pull-right.toctree-expand,.wy-menu-vertical li span.pull-right.toctree-expand{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s linear infinite;animation:fa-spin 2s linear infinite}.fa-pulse{-webkit-animation:fa-spin 1s steps(8) infinite;animation:fa-spin 1s steps(8) infinite}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);-ms-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:""}.fa-music:before{content:""}.fa-search:before,.icon-search:before{content:""}.fa-envelope-o:before{content:""}.fa-heart:before{content:""}.fa-star:before{content:""}.fa-star-o:before{content:""}.fa-user:before{content:""}.fa-film:before{content:""}.fa-th-large:before{content:""}.fa-th:before{content:""}.fa-th-list:before{content:""}.fa-check:before{content:""}.fa-close:before,.fa-remove:before,.fa-times:before{content:""}.fa-search-plus:before{content:""}.fa-search-minus:before{content:""}.fa-power-off:before{content:""}.fa-signal:before{content:""}.fa-cog:before,.fa-gear:before{content:""}.fa-trash-o:before{content:""}.fa-home:before,.icon-home:before{content:""}.fa-file-o:before{content:""}.fa-clock-o:before{content:""}.fa-road:before{content:""}.fa-download:before,.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{content:""}.fa-arrow-circle-o-down:before{content:""}.fa-arrow-circle-o-up:before{content:""}.fa-inbox:before{content:""}.fa-play-circle-o:before{content:""}.fa-repeat:before,.fa-rotate-right:before{content:""}.fa-refresh:before{content:""}.fa-list-alt:before{content:""}.fa-lock:before{content:""}.fa-flag:before{content:""}.fa-headphones:before{content:""}.fa-volume-off:before{content:""}.fa-volume-down:before{content:""}.fa-volume-up:before{content:""}.fa-qrcode:before{content:""}.fa-barcode:before{content:""}.fa-tag:before{content:""}.fa-tags:before{content:""}.fa-book:before,.icon-book:before{content:""}.fa-bookmark:before{content:""}.fa-print:before{content:""}.fa-camera:before{content:""}.fa-font:before{content:""}.fa-bold:before{content:""}.fa-italic:before{content:""}.fa-text-height:before{content:""}.fa-text-width:before{content:""}.fa-align-left:before{content:""}.fa-align-center:before{content:""}.fa-align-right:before{content:""}.fa-align-justify:before{content:""}.fa-list:before{content:""}.fa-dedent:before,.fa-outdent:before{content:""}.fa-indent:before{content:""}.fa-video-camera:before{content:""}.fa-image:before,.fa-photo:before,.fa-picture-o:before{content:""}.fa-pencil:before{content:""}.fa-map-marker:before{content:""}.fa-adjust:before{content:""}.fa-tint:before{content:""}.fa-edit:before,.fa-pencil-square-o:before{content:""}.fa-share-square-o:before{content:""}.fa-check-square-o:before{content:""}.fa-arrows:before{content:""}.fa-step-backward:before{content:""}.fa-fast-backward:before{content:""}.fa-backward:before{content:""}.fa-play:before{content:""}.fa-pause:before{content:""}.fa-stop:before{content:""}.fa-forward:before{content:""}.fa-fast-forward:before{content:""}.fa-step-forward:before{content:""}.fa-eject:before{content:""}.fa-chevron-left:before{content:""}.fa-chevron-right:before{content:""}.fa-plus-circle:before{content:""}.fa-minus-circle:before{content:""}.fa-times-circle:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before{content:""}.fa-check-circle:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before{content:""}.fa-question-circle:before{content:""}.fa-info-circle:before{content:""}.fa-crosshairs:before{content:""}.fa-times-circle-o:before{content:""}.fa-check-circle-o:before{content:""}.fa-ban:before{content:""}.fa-arrow-left:before{content:""}.fa-arrow-right:before{content:""}.fa-arrow-up:before{content:""}.fa-arrow-down:before{content:""}.fa-mail-forward:before,.fa-share:before{content:""}.fa-expand:before{content:""}.fa-compress:before{content:""}.fa-plus:before{content:""}.fa-minus:before{content:""}.fa-asterisk:before{content:""}.fa-exclamation-circle:before,.rst-content .admonition-title:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before{content:""}.fa-gift:before{content:""}.fa-leaf:before{content:""}.fa-fire:before,.icon-fire:before{content:""}.fa-eye:before{content:""}.fa-eye-slash:before{content:""}.fa-exclamation-triangle:before,.fa-warning:before{content:""}.fa-plane:before{content:""}.fa-calendar:before{content:""}.fa-random:before{content:""}.fa-comment:before{content:""}.fa-magnet:before{content:""}.fa-chevron-up:before{content:""}.fa-chevron-down:before{content:""}.fa-retweet:before{content:""}.fa-shopping-cart:before{content:""}.fa-folder:before{content:""}.fa-folder-open:before{content:""}.fa-arrows-v:before{content:""}.fa-arrows-h:before{content:""}.fa-bar-chart-o:before,.fa-bar-chart:before{content:""}.fa-twitter-square:before{content:""}.fa-facebook-square:before{content:""}.fa-camera-retro:before{content:""}.fa-key:before{content:""}.fa-cogs:before,.fa-gears:before{content:""}.fa-comments:before{content:""}.fa-thumbs-o-up:before{content:""}.fa-thumbs-o-down:before{content:""}.fa-star-half:before{content:""}.fa-heart-o:before{content:""}.fa-sign-out:before{content:""}.fa-linkedin-square:before{content:""}.fa-thumb-tack:before{content:""}.fa-external-link:before{content:""}.fa-sign-in:before{content:""}.fa-trophy:before{content:""}.fa-github-square:before{content:""}.fa-upload:before{content:""}.fa-lemon-o:before{content:""}.fa-phone:before{content:""}.fa-square-o:before{content:""}.fa-bookmark-o:before{content:""}.fa-phone-square:before{content:""}.fa-twitter:before{content:""}.fa-facebook-f:before,.fa-facebook:before{content:""}.fa-github:before,.icon-github:before{content:""}.fa-unlock:before{content:""}.fa-credit-card:before{content:""}.fa-feed:before,.fa-rss:before{content:""}.fa-hdd-o:before{content:""}.fa-bullhorn:before{content:""}.fa-bell:before{content:""}.fa-certificate:before{content:""}.fa-hand-o-right:before{content:""}.fa-hand-o-left:before{content:""}.fa-hand-o-up:before{content:""}.fa-hand-o-down:before{content:""}.fa-arrow-circle-left:before,.icon-circle-arrow-left:before{content:""}.fa-arrow-circle-right:before,.icon-circle-arrow-right:before{content:""}.fa-arrow-circle-up:before{content:""}.fa-arrow-circle-down:before{content:""}.fa-globe:before{content:""}.fa-wrench:before{content:""}.fa-tasks:before{content:""}.fa-filter:before{content:""}.fa-briefcase:before{content:""}.fa-arrows-alt:before{content:""}.fa-group:before,.fa-users:before{content:""}.fa-chain:before,.fa-link:before,.icon-link:before{content:""}.fa-cloud:before{content:""}.fa-flask:before{content:""}.fa-cut:before,.fa-scissors:before{content:""}.fa-copy:before,.fa-files-o:before{content:""}.fa-paperclip:before{content:""}.fa-floppy-o:before,.fa-save:before{content:""}.fa-square:before{content:""}.fa-bars:before,.fa-navicon:before,.fa-reorder:before{content:""}.fa-list-ul:before{content:""}.fa-list-ol:before{content:""}.fa-strikethrough:before{content:""}.fa-underline:before{content:""}.fa-table:before{content:""}.fa-magic:before{content:""}.fa-truck:before{content:""}.fa-pinterest:before{content:""}.fa-pinterest-square:before{content:""}.fa-google-plus-square:before{content:""}.fa-google-plus:before{content:""}.fa-money:before{content:""}.fa-caret-down:before,.icon-caret-down:before,.wy-dropdown .caret:before{content:""}.fa-caret-up:before{content:""}.fa-caret-left:before{content:""}.fa-caret-right:before{content:""}.fa-columns:before{content:""}.fa-sort:before,.fa-unsorted:before{content:""}.fa-sort-desc:before,.fa-sort-down:before{content:""}.fa-sort-asc:before,.fa-sort-up:before{content:""}.fa-envelope:before{content:""}.fa-linkedin:before{content:""}.fa-rotate-left:before,.fa-undo:before{content:""}.fa-gavel:before,.fa-legal:before{content:""}.fa-dashboard:before,.fa-tachometer:before{content:""}.fa-comment-o:before{content:""}.fa-comments-o:before{content:""}.fa-bolt:before,.fa-flash:before{content:""}.fa-sitemap:before{content:""}.fa-umbrella:before{content:""}.fa-clipboard:before,.fa-paste:before{content:""}.fa-lightbulb-o:before{content:""}.fa-exchange:before{content:""}.fa-cloud-download:before{content:""}.fa-cloud-upload:before{content:""}.fa-user-md:before{content:""}.fa-stethoscope:before{content:""}.fa-suitcase:before{content:""}.fa-bell-o:before{content:""}.fa-coffee:before{content:""}.fa-cutlery:before{content:""}.fa-file-text-o:before{content:""}.fa-building-o:before{content:""}.fa-hospital-o:before{content:""}.fa-ambulance:before{content:""}.fa-medkit:before{content:""}.fa-fighter-jet:before{content:""}.fa-beer:before{content:""}.fa-h-square:before{content:""}.fa-plus-square:before{content:""}.fa-angle-double-left:before{content:""}.fa-angle-double-right:before{content:""}.fa-angle-double-up:before{content:""}.fa-angle-double-down:before{content:""}.fa-angle-left:before{content:""}.fa-angle-right:before{content:""}.fa-angle-up:before{content:""}.fa-angle-down:before{content:""}.fa-desktop:before{content:""}.fa-laptop:before{content:""}.fa-tablet:before{content:""}.fa-mobile-phone:before,.fa-mobile:before{content:""}.fa-circle-o:before{content:""}.fa-quote-left:before{content:""}.fa-quote-right:before{content:""}.fa-spinner:before{content:""}.fa-circle:before{content:""}.fa-mail-reply:before,.fa-reply:before{content:""}.fa-github-alt:before{content:""}.fa-folder-o:before{content:""}.fa-folder-open-o:before{content:""}.fa-smile-o:before{content:""}.fa-frown-o:before{content:""}.fa-meh-o:before{content:""}.fa-gamepad:before{content:""}.fa-keyboard-o:before{content:""}.fa-flag-o:before{content:""}.fa-flag-checkered:before{content:""}.fa-terminal:before{content:""}.fa-code:before{content:""}.fa-mail-reply-all:before,.fa-reply-all:before{content:""}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:""}.fa-location-arrow:before{content:""}.fa-crop:before{content:""}.fa-code-fork:before{content:""}.fa-chain-broken:before,.fa-unlink:before{content:""}.fa-question:before{content:""}.fa-info:before{content:""}.fa-exclamation:before{content:""}.fa-superscript:before{content:""}.fa-subscript:before{content:""}.fa-eraser:before{content:""}.fa-puzzle-piece:before{content:""}.fa-microphone:before{content:""}.fa-microphone-slash:before{content:""}.fa-shield:before{content:""}.fa-calendar-o:before{content:""}.fa-fire-extinguisher:before{content:""}.fa-rocket:before{content:""}.fa-maxcdn:before{content:""}.fa-chevron-circle-left:before{content:""}.fa-chevron-circle-right:before{content:""}.fa-chevron-circle-up:before{content:""}.fa-chevron-circle-down:before{content:""}.fa-html5:before{content:""}.fa-css3:before{content:""}.fa-anchor:before{content:""}.fa-unlock-alt:before{content:""}.fa-bullseye:before{content:""}.fa-ellipsis-h:before{content:""}.fa-ellipsis-v:before{content:""}.fa-rss-square:before{content:""}.fa-play-circle:before{content:""}.fa-ticket:before{content:""}.fa-minus-square:before{content:""}.fa-minus-square-o:before,.wy-menu-vertical li.current>a span.toctree-expand:before,.wy-menu-vertical li.on a span.toctree-expand:before{content:""}.fa-level-up:before{content:""}.fa-level-down:before{content:""}.fa-check-square:before{content:""}.fa-pencil-square:before{content:""}.fa-external-link-square:before{content:""}.fa-share-square:before{content:""}.fa-compass:before{content:""}.fa-caret-square-o-down:before,.fa-toggle-down:before{content:""}.fa-caret-square-o-up:before,.fa-toggle-up:before{content:""}.fa-caret-square-o-right:before,.fa-toggle-right:before{content:""}.fa-eur:before,.fa-euro:before{content:""}.fa-gbp:before{content:""}.fa-dollar:before,.fa-usd:before{content:""}.fa-inr:before,.fa-rupee:before{content:""}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen:before{content:""}.fa-rouble:before,.fa-rub:before,.fa-ruble:before{content:""}.fa-krw:before,.fa-won:before{content:""}.fa-bitcoin:before,.fa-btc:before{content:""}.fa-file:before{content:""}.fa-file-text:before{content:""}.fa-sort-alpha-asc:before{content:""}.fa-sort-alpha-desc:before{content:""}.fa-sort-amount-asc:before{content:""}.fa-sort-amount-desc:before{content:""}.fa-sort-numeric-asc:before{content:""}.fa-sort-numeric-desc:before{content:""}.fa-thumbs-up:before{content:""}.fa-thumbs-down:before{content:""}.fa-youtube-square:before{content:""}.fa-youtube:before{content:""}.fa-xing:before{content:""}.fa-xing-square:before{content:""}.fa-youtube-play:before{content:""}.fa-dropbox:before{content:""}.fa-stack-overflow:before{content:""}.fa-instagram:before{content:""}.fa-flickr:before{content:""}.fa-adn:before{content:""}.fa-bitbucket:before,.icon-bitbucket:before{content:""}.fa-bitbucket-square:before{content:""}.fa-tumblr:before{content:""}.fa-tumblr-square:before{content:""}.fa-long-arrow-down:before{content:""}.fa-long-arrow-up:before{content:""}.fa-long-arrow-left:before{content:""}.fa-long-arrow-right:before{content:""}.fa-apple:before{content:""}.fa-windows:before{content:""}.fa-android:before{content:""}.fa-linux:before{content:""}.fa-dribbble:before{content:""}.fa-skype:before{content:""}.fa-foursquare:before{content:""}.fa-trello:before{content:""}.fa-female:before{content:""}.fa-male:before{content:""}.fa-gittip:before,.fa-gratipay:before{content:""}.fa-sun-o:before{content:""}.fa-moon-o:before{content:""}.fa-archive:before{content:""}.fa-bug:before{content:""}.fa-vk:before{content:""}.fa-weibo:before{content:""}.fa-renren:before{content:""}.fa-pagelines:before{content:""}.fa-stack-exchange:before{content:""}.fa-arrow-circle-o-right:before{content:""}.fa-arrow-circle-o-left:before{content:""}.fa-caret-square-o-left:before,.fa-toggle-left:before{content:""}.fa-dot-circle-o:before{content:""}.fa-wheelchair:before{content:""}.fa-vimeo-square:before{content:""}.fa-try:before,.fa-turkish-lira:before{content:""}.fa-plus-square-o:before,.wy-menu-vertical li span.toctree-expand:before{content:""}.fa-space-shuttle:before{content:""}.fa-slack:before{content:""}.fa-envelope-square:before{content:""}.fa-wordpress:before{content:""}.fa-openid:before{content:""}.fa-bank:before,.fa-institution:before,.fa-university:before{content:""}.fa-graduation-cap:before,.fa-mortar-board:before{content:""}.fa-yahoo:before{content:""}.fa-google:before{content:""}.fa-reddit:before{content:""}.fa-reddit-square:before{content:""}.fa-stumbleupon-circle:before{content:""}.fa-stumbleupon:before{content:""}.fa-delicious:before{content:""}.fa-digg:before{content:""}.fa-pied-piper-pp:before{content:""}.fa-pied-piper-alt:before{content:""}.fa-drupal:before{content:""}.fa-joomla:before{content:""}.fa-language:before{content:""}.fa-fax:before{content:""}.fa-building:before{content:""}.fa-child:before{content:""}.fa-paw:before{content:""}.fa-spoon:before{content:""}.fa-cube:before{content:""}.fa-cubes:before{content:""}.fa-behance:before{content:""}.fa-behance-square:before{content:""}.fa-steam:before{content:""}.fa-steam-square:before{content:""}.fa-recycle:before{content:""}.fa-automobile:before,.fa-car:before{content:""}.fa-cab:before,.fa-taxi:before{content:""}.fa-tree:before{content:""}.fa-spotify:before{content:""}.fa-deviantart:before{content:""}.fa-soundcloud:before{content:""}.fa-database:before{content:""}.fa-file-pdf-o:before{content:""}.fa-file-word-o:before{content:""}.fa-file-excel-o:before{content:""}.fa-file-powerpoint-o:before{content:""}.fa-file-image-o:before,.fa-file-photo-o:before,.fa-file-picture-o:before{content:""}.fa-file-archive-o:before,.fa-file-zip-o:before{content:""}.fa-file-audio-o:before,.fa-file-sound-o:before{content:""}.fa-file-movie-o:before,.fa-file-video-o:before{content:""}.fa-file-code-o:before{content:""}.fa-vine:before{content:""}.fa-codepen:before{content:""}.fa-jsfiddle:before{content:""}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-ring:before,.fa-life-saver:before,.fa-support:before{content:""}.fa-circle-o-notch:before{content:""}.fa-ra:before,.fa-rebel:before,.fa-resistance:before{content:""}.fa-empire:before,.fa-ge:before{content:""}.fa-git-square:before{content:""}.fa-git:before{content:""}.fa-hacker-news:before,.fa-y-combinator-square:before,.fa-yc-square:before{content:""}.fa-tencent-weibo:before{content:""}.fa-qq:before{content:""}.fa-wechat:before,.fa-weixin:before{content:""}.fa-paper-plane:before,.fa-send:before{content:""}.fa-paper-plane-o:before,.fa-send-o:before{content:""}.fa-history:before{content:""}.fa-circle-thin:before{content:""}.fa-header:before{content:""}.fa-paragraph:before{content:""}.fa-sliders:before{content:""}.fa-share-alt:before{content:""}.fa-share-alt-square:before{content:""}.fa-bomb:before{content:""}.fa-futbol-o:before,.fa-soccer-ball-o:before{content:""}.fa-tty:before{content:""}.fa-binoculars:before{content:""}.fa-plug:before{content:""}.fa-slideshare:before{content:""}.fa-twitch:before{content:""}.fa-yelp:before{content:""}.fa-newspaper-o:before{content:""}.fa-wifi:before{content:""}.fa-calculator:before{content:""}.fa-paypal:before{content:""}.fa-google-wallet:before{content:""}.fa-cc-visa:before{content:""}.fa-cc-mastercard:before{content:""}.fa-cc-discover:before{content:""}.fa-cc-amex:before{content:""}.fa-cc-paypal:before{content:""}.fa-cc-stripe:before{content:""}.fa-bell-slash:before{content:""}.fa-bell-slash-o:before{content:""}.fa-trash:before{content:""}.fa-copyright:before{content:""}.fa-at:before{content:""}.fa-eyedropper:before{content:""}.fa-paint-brush:before{content:""}.fa-birthday-cake:before{content:""}.fa-area-chart:before{content:""}.fa-pie-chart:before{content:""}.fa-line-chart:before{content:""}.fa-lastfm:before{content:""}.fa-lastfm-square:before{content:""}.fa-toggle-off:before{content:""}.fa-toggle-on:before{content:""}.fa-bicycle:before{content:""}.fa-bus:before{content:""}.fa-ioxhost:before{content:""}.fa-angellist:before{content:""}.fa-cc:before{content:""}.fa-ils:before,.fa-shekel:before,.fa-sheqel:before{content:""}.fa-meanpath:before{content:""}.fa-buysellads:before{content:""}.fa-connectdevelop:before{content:""}.fa-dashcube:before{content:""}.fa-forumbee:before{content:""}.fa-leanpub:before{content:""}.fa-sellsy:before{content:""}.fa-shirtsinbulk:before{content:""}.fa-simplybuilt:before{content:""}.fa-skyatlas:before{content:""}.fa-cart-plus:before{content:""}.fa-cart-arrow-down:before{content:""}.fa-diamond:before{content:""}.fa-ship:before{content:""}.fa-user-secret:before{content:""}.fa-motorcycle:before{content:""}.fa-street-view:before{content:""}.fa-heartbeat:before{content:""}.fa-venus:before{content:""}.fa-mars:before{content:""}.fa-mercury:before{content:""}.fa-intersex:before,.fa-transgender:before{content:""}.fa-transgender-alt:before{content:""}.fa-venus-double:before{content:""}.fa-mars-double:before{content:""}.fa-venus-mars:before{content:""}.fa-mars-stroke:before{content:""}.fa-mars-stroke-v:before{content:""}.fa-mars-stroke-h:before{content:""}.fa-neuter:before{content:""}.fa-genderless:before{content:""}.fa-facebook-official:before{content:""}.fa-pinterest-p:before{content:""}.fa-whatsapp:before{content:""}.fa-server:before{content:""}.fa-user-plus:before{content:""}.fa-user-times:before{content:""}.fa-bed:before,.fa-hotel:before{content:""}.fa-viacoin:before{content:""}.fa-train:before{content:""}.fa-subway:before{content:""}.fa-medium:before{content:""}.fa-y-combinator:before,.fa-yc:before{content:""}.fa-optin-monster:before{content:""}.fa-opencart:before{content:""}.fa-expeditedssl:before{content:""}.fa-battery-4:before,.fa-battery-full:before,.fa-battery:before{content:""}.fa-battery-3:before,.fa-battery-three-quarters:before{content:""}.fa-battery-2:before,.fa-battery-half:before{content:""}.fa-battery-1:before,.fa-battery-quarter:before{content:""}.fa-battery-0:before,.fa-battery-empty:before{content:""}.fa-mouse-pointer:before{content:""}.fa-i-cursor:before{content:""}.fa-object-group:before{content:""}.fa-object-ungroup:before{content:""}.fa-sticky-note:before{content:""}.fa-sticky-note-o:before{content:""}.fa-cc-jcb:before{content:""}.fa-cc-diners-club:before{content:""}.fa-clone:before{content:""}.fa-balance-scale:before{content:""}.fa-hourglass-o:before{content:""}.fa-hourglass-1:before,.fa-hourglass-start:before{content:""}.fa-hourglass-2:before,.fa-hourglass-half:before{content:""}.fa-hourglass-3:before,.fa-hourglass-end:before{content:""}.fa-hourglass:before{content:""}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:""}.fa-hand-paper-o:before,.fa-hand-stop-o:before{content:""}.fa-hand-scissors-o:before{content:""}.fa-hand-lizard-o:before{content:""}.fa-hand-spock-o:before{content:""}.fa-hand-pointer-o:before{content:""}.fa-hand-peace-o:before{content:""}.fa-trademark:before{content:""}.fa-registered:before{content:""}.fa-creative-commons:before{content:""}.fa-gg:before{content:""}.fa-gg-circle:before{content:""}.fa-tripadvisor:before{content:""}.fa-odnoklassniki:before{content:""}.fa-odnoklassniki-square:before{content:""}.fa-get-pocket:before{content:""}.fa-wikipedia-w:before{content:""}.fa-safari:before{content:""}.fa-chrome:before{content:""}.fa-firefox:before{content:""}.fa-opera:before{content:""}.fa-internet-explorer:before{content:""}.fa-television:before,.fa-tv:before{content:""}.fa-contao:before{content:""}.fa-500px:before{content:""}.fa-amazon:before{content:""}.fa-calendar-plus-o:before{content:""}.fa-calendar-minus-o:before{content:""}.fa-calendar-times-o:before{content:""}.fa-calendar-check-o:before{content:""}.fa-industry:before{content:""}.fa-map-pin:before{content:""}.fa-map-signs:before{content:""}.fa-map-o:before{content:""}.fa-map:before{content:""}.fa-commenting:before{content:""}.fa-commenting-o:before{content:""}.fa-houzz:before{content:""}.fa-vimeo:before{content:""}.fa-black-tie:before{content:""}.fa-fonticons:before{content:""}.fa-reddit-alien:before{content:""}.fa-edge:before{content:""}.fa-credit-card-alt:before{content:""}.fa-codiepie:before{content:""}.fa-modx:before{content:""}.fa-fort-awesome:before{content:""}.fa-usb:before{content:""}.fa-product-hunt:before{content:""}.fa-mixcloud:before{content:""}.fa-scribd:before{content:""}.fa-pause-circle:before{content:""}.fa-pause-circle-o:before{content:""}.fa-stop-circle:before{content:""}.fa-stop-circle-o:before{content:""}.fa-shopping-bag:before{content:""}.fa-shopping-basket:before{content:""}.fa-hashtag:before{content:""}.fa-bluetooth:before{content:""}.fa-bluetooth-b:before{content:""}.fa-percent:before{content:""}.fa-gitlab:before,.icon-gitlab:before{content:""}.fa-wpbeginner:before{content:""}.fa-wpforms:before{content:""}.fa-envira:before{content:""}.fa-universal-access:before{content:""}.fa-wheelchair-alt:before{content:""}.fa-question-circle-o:before{content:""}.fa-blind:before{content:""}.fa-audio-description:before{content:""}.fa-volume-control-phone:before{content:""}.fa-braille:before{content:""}.fa-assistive-listening-systems:before{content:""}.fa-american-sign-language-interpreting:before,.fa-asl-interpreting:before{content:""}.fa-deaf:before,.fa-deafness:before,.fa-hard-of-hearing:before{content:""}.fa-glide:before{content:""}.fa-glide-g:before{content:""}.fa-sign-language:before,.fa-signing:before{content:""}.fa-low-vision:before{content:""}.fa-viadeo:before{content:""}.fa-viadeo-square:before{content:""}.fa-snapchat:before{content:""}.fa-snapchat-ghost:before{content:""}.fa-snapchat-square:before{content:""}.fa-pied-piper:before{content:""}.fa-first-order:before{content:""}.fa-yoast:before{content:""}.fa-themeisle:before{content:""}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:""}.fa-fa:before,.fa-font-awesome:before{content:""}.fa-handshake-o:before{content:""}.fa-envelope-open:before{content:""}.fa-envelope-open-o:before{content:""}.fa-linode:before{content:""}.fa-address-book:before{content:""}.fa-address-book-o:before{content:""}.fa-address-card:before,.fa-vcard:before{content:""}.fa-address-card-o:before,.fa-vcard-o:before{content:""}.fa-user-circle:before{content:""}.fa-user-circle-o:before{content:""}.fa-user-o:before{content:""}.fa-id-badge:before{content:""}.fa-drivers-license:before,.fa-id-card:before{content:""}.fa-drivers-license-o:before,.fa-id-card-o:before{content:""}.fa-quora:before{content:""}.fa-free-code-camp:before{content:""}.fa-telegram:before{content:""}.fa-thermometer-4:before,.fa-thermometer-full:before,.fa-thermometer:before{content:""}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:""}.fa-thermometer-2:before,.fa-thermometer-half:before{content:""}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:""}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:""}.fa-shower:before{content:""}.fa-bath:before,.fa-bathtub:before,.fa-s15:before{content:""}.fa-podcast:before{content:""}.fa-window-maximize:before{content:""}.fa-window-minimize:before{content:""}.fa-window-restore:before{content:""}.fa-times-rectangle:before,.fa-window-close:before{content:""}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:""}.fa-bandcamp:before{content:""}.fa-grav:before{content:""}.fa-etsy:before{content:""}.fa-imdb:before{content:""}.fa-ravelry:before{content:""}.fa-eercast:before{content:""}.fa-microchip:before{content:""}.fa-snowflake-o:before{content:""}.fa-superpowers:before{content:""}.fa-wpexplorer:before{content:""}.fa-meetup:before{content:""}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-dropdown .caret,.wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-info .wy-input-context,.wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-menu-vertical li.current>a span.toctree-expand,.wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li span.toctree-expand{font-family:inherit}.fa:before,.icon:before,.rst-content .admonition-title:before,.rst-content .code-block-caption .headerlink:before,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a span.toctree-expand:before,.wy-menu-vertical li.on a span.toctree-expand:before,.wy-menu-vertical li span.toctree-expand:before{font-family:FontAwesome;display:inline-block;font-style:normal;font-weight:400;line-height:1;text-decoration:inherit}.rst-content .code-block-caption a .headerlink,.rst-content a .admonition-title,.rst-content code.download a span:first-child,.rst-content dl dt a .headerlink,.rst-content h1 a .headerlink,.rst-content h2 a .headerlink,.rst-content h3 a .headerlink,.rst-content h4 a .headerlink,.rst-content h5 a .headerlink,.rst-content h6 a .headerlink,.rst-content p.caption a .headerlink,.rst-content table>caption a .headerlink,.rst-content tt.download a span:first-child,.wy-menu-vertical li.current>a span.toctree-expand,.wy-menu-vertical li.on a span.toctree-expand,.wy-menu-vertical li a span.toctree-expand,a .fa,a .icon,a .rst-content .admonition-title,a .rst-content .code-block-caption .headerlink,a .rst-content code.download span:first-child,a .rst-content dl dt .headerlink,a .rst-content h1 .headerlink,a .rst-content h2 .headerlink,a .rst-content h3 .headerlink,a .rst-content h4 .headerlink,a .rst-content h5 .headerlink,a .rst-content h6 .headerlink,a .rst-content p.caption .headerlink,a .rst-content table>caption .headerlink,a .rst-content tt.download span:first-child,a .wy-menu-vertical li span.toctree-expand{display:inline-block;text-decoration:inherit}.btn .fa,.btn .icon,.btn .rst-content .admonition-title,.btn .rst-content .code-block-caption .headerlink,.btn .rst-content code.download span:first-child,.btn .rst-content dl dt .headerlink,.btn .rst-content h1 .headerlink,.btn .rst-content h2 .headerlink,.btn .rst-content h3 .headerlink,.btn .rst-content h4 .headerlink,.btn .rst-content h5 .headerlink,.btn .rst-content h6 .headerlink,.btn .rst-content p.caption .headerlink,.btn .rst-content table>caption .headerlink,.btn .rst-content tt.download span:first-child,.btn .wy-menu-vertical li.current>a span.toctree-expand,.btn .wy-menu-vertical li.on a span.toctree-expand,.btn .wy-menu-vertical li span.toctree-expand,.nav .fa,.nav .icon,.nav .rst-content .admonition-title,.nav .rst-content .code-block-caption .headerlink,.nav .rst-content code.download span:first-child,.nav .rst-content dl dt .headerlink,.nav .rst-content h1 .headerlink,.nav .rst-content h2 .headerlink,.nav .rst-content h3 .headerlink,.nav .rst-content h4 .headerlink,.nav .rst-content h5 .headerlink,.nav .rst-content h6 .headerlink,.nav .rst-content p.caption .headerlink,.nav .rst-content table>caption .headerlink,.nav .rst-content tt.download span:first-child,.nav .wy-menu-vertical li.current>a span.toctree-expand,.nav .wy-menu-vertical li.on a span.toctree-expand,.nav .wy-menu-vertical li span.toctree-expand,.rst-content .btn .admonition-title,.rst-content .code-block-caption .btn .headerlink,.rst-content .code-block-caption .nav .headerlink,.rst-content .nav .admonition-title,.rst-content code.download .btn span:first-child,.rst-content code.download .nav span:first-child,.rst-content dl dt .btn .headerlink,.rst-content dl dt .nav .headerlink,.rst-content h1 .btn .headerlink,.rst-content h1 .nav .headerlink,.rst-content h2 .btn .headerlink,.rst-content h2 .nav .headerlink,.rst-content h3 .btn .headerlink,.rst-content h3 .nav .headerlink,.rst-content h4 .btn .headerlink,.rst-content h4 .nav .headerlink,.rst-content h5 .btn .headerlink,.rst-content h5 .nav .headerlink,.rst-content h6 .btn .headerlink,.rst-content h6 .nav .headerlink,.rst-content p.caption .btn .headerlink,.rst-content p.caption .nav .headerlink,.rst-content table>caption .btn .headerlink,.rst-content table>caption .nav .headerlink,.rst-content tt.download .btn span:first-child,.rst-content tt.download .nav span:first-child,.wy-menu-vertical li .btn span.toctree-expand,.wy-menu-vertical li.current>a .btn span.toctree-expand,.wy-menu-vertical li.current>a .nav span.toctree-expand,.wy-menu-vertical li .nav span.toctree-expand,.wy-menu-vertical li.on a .btn span.toctree-expand,.wy-menu-vertical li.on a .nav span.toctree-expand{display:inline}.btn .fa-large.icon,.btn .fa.fa-large,.btn .rst-content .code-block-caption .fa-large.headerlink,.btn .rst-content .fa-large.admonition-title,.btn .rst-content code.download span.fa-large:first-child,.btn .rst-content dl dt .fa-large.headerlink,.btn .rst-content h1 .fa-large.headerlink,.btn .rst-content h2 .fa-large.headerlink,.btn .rst-content h3 .fa-large.headerlink,.btn .rst-content h4 .fa-large.headerlink,.btn .rst-content h5 .fa-large.headerlink,.btn .rst-content h6 .fa-large.headerlink,.btn .rst-content p.caption .fa-large.headerlink,.btn .rst-content table>caption .fa-large.headerlink,.btn .rst-content tt.download span.fa-large:first-child,.btn .wy-menu-vertical li span.fa-large.toctree-expand,.nav .fa-large.icon,.nav .fa.fa-large,.nav .rst-content .code-block-caption .fa-large.headerlink,.nav .rst-content .fa-large.admonition-title,.nav .rst-content code.download span.fa-large:first-child,.nav .rst-content dl dt .fa-large.headerlink,.nav .rst-content h1 .fa-large.headerlink,.nav .rst-content h2 .fa-large.headerlink,.nav .rst-content h3 .fa-large.headerlink,.nav .rst-content h4 .fa-large.headerlink,.nav .rst-content h5 .fa-large.headerlink,.nav .rst-content h6 .fa-large.headerlink,.nav .rst-content p.caption .fa-large.headerlink,.nav .rst-content table>caption .fa-large.headerlink,.nav .rst-content tt.download span.fa-large:first-child,.nav .wy-menu-vertical li span.fa-large.toctree-expand,.rst-content .btn .fa-large.admonition-title,.rst-content .code-block-caption .btn .fa-large.headerlink,.rst-content .code-block-caption .nav .fa-large.headerlink,.rst-content .nav .fa-large.admonition-title,.rst-content code.download .btn span.fa-large:first-child,.rst-content code.download .nav span.fa-large:first-child,.rst-content dl dt .btn .fa-large.headerlink,.rst-content dl dt .nav .fa-large.headerlink,.rst-content h1 .btn .fa-large.headerlink,.rst-content h1 .nav .fa-large.headerlink,.rst-content h2 .btn .fa-large.headerlink,.rst-content h2 .nav .fa-large.headerlink,.rst-content h3 .btn .fa-large.headerlink,.rst-content h3 .nav .fa-large.headerlink,.rst-content h4 .btn .fa-large.headerlink,.rst-content h4 .nav .fa-large.headerlink,.rst-content h5 .btn .fa-large.headerlink,.rst-content h5 .nav .fa-large.headerlink,.rst-content h6 .btn .fa-large.headerlink,.rst-content h6 .nav .fa-large.headerlink,.rst-content p.caption .btn .fa-large.headerlink,.rst-content p.caption .nav .fa-large.headerlink,.rst-content table>caption .btn .fa-large.headerlink,.rst-content table>caption .nav .fa-large.headerlink,.rst-content tt.download .btn span.fa-large:first-child,.rst-content tt.download .nav span.fa-large:first-child,.wy-menu-vertical li .btn span.fa-large.toctree-expand,.wy-menu-vertical li .nav span.fa-large.toctree-expand{line-height:.9em}.btn .fa-spin.icon,.btn .fa.fa-spin,.btn .rst-content .code-block-caption .fa-spin.headerlink,.btn .rst-content .fa-spin.admonition-title,.btn .rst-content code.download span.fa-spin:first-child,.btn .rst-content dl dt .fa-spin.headerlink,.btn .rst-content h1 .fa-spin.headerlink,.btn .rst-content h2 .fa-spin.headerlink,.btn .rst-content h3 .fa-spin.headerlink,.btn .rst-content h4 .fa-spin.headerlink,.btn .rst-content h5 .fa-spin.headerlink,.btn .rst-content h6 .fa-spin.headerlink,.btn .rst-content p.caption .fa-spin.headerlink,.btn .rst-content table>caption .fa-spin.headerlink,.btn .rst-content tt.download span.fa-spin:first-child,.btn .wy-menu-vertical li span.fa-spin.toctree-expand,.nav .fa-spin.icon,.nav .fa.fa-spin,.nav .rst-content .code-block-caption .fa-spin.headerlink,.nav .rst-content .fa-spin.admonition-title,.nav .rst-content code.download span.fa-spin:first-child,.nav .rst-content dl dt .fa-spin.headerlink,.nav .rst-content h1 .fa-spin.headerlink,.nav .rst-content h2 .fa-spin.headerlink,.nav .rst-content h3 .fa-spin.headerlink,.nav .rst-content h4 .fa-spin.headerlink,.nav .rst-content h5 .fa-spin.headerlink,.nav .rst-content h6 .fa-spin.headerlink,.nav .rst-content p.caption .fa-spin.headerlink,.nav .rst-content table>caption .fa-spin.headerlink,.nav .rst-content tt.download span.fa-spin:first-child,.nav .wy-menu-vertical li span.fa-spin.toctree-expand,.rst-content .btn .fa-spin.admonition-title,.rst-content .code-block-caption .btn .fa-spin.headerlink,.rst-content .code-block-caption .nav .fa-spin.headerlink,.rst-content .nav .fa-spin.admonition-title,.rst-content code.download .btn span.fa-spin:first-child,.rst-content code.download .nav span.fa-spin:first-child,.rst-content dl dt .btn .fa-spin.headerlink,.rst-content dl dt .nav .fa-spin.headerlink,.rst-content h1 .btn .fa-spin.headerlink,.rst-content h1 .nav .fa-spin.headerlink,.rst-content h2 .btn .fa-spin.headerlink,.rst-content h2 .nav .fa-spin.headerlink,.rst-content h3 .btn .fa-spin.headerlink,.rst-content h3 .nav .fa-spin.headerlink,.rst-content h4 .btn .fa-spin.headerlink,.rst-content h4 .nav .fa-spin.headerlink,.rst-content h5 .btn .fa-spin.headerlink,.rst-content h5 .nav .fa-spin.headerlink,.rst-content h6 .btn .fa-spin.headerlink,.rst-content h6 .nav .fa-spin.headerlink,.rst-content p.caption .btn .fa-spin.headerlink,.rst-content p.caption .nav .fa-spin.headerlink,.rst-content table>caption .btn .fa-spin.headerlink,.rst-content table>caption .nav .fa-spin.headerlink,.rst-content tt.download .btn span.fa-spin:first-child,.rst-content tt.download .nav span.fa-spin:first-child,.wy-menu-vertical li .btn span.fa-spin.toctree-expand,.wy-menu-vertical li .nav span.fa-spin.toctree-expand{display:inline-block}.btn.fa:before,.btn.icon:before,.rst-content .btn.admonition-title:before,.rst-content .code-block-caption .btn.headerlink:before,.rst-content code.download span.btn:first-child:before,.rst-content dl dt .btn.headerlink:before,.rst-content h1 .btn.headerlink:before,.rst-content h2 .btn.headerlink:before,.rst-content h3 .btn.headerlink:before,.rst-content h4 .btn.headerlink:before,.rst-content h5 .btn.headerlink:before,.rst-content h6 .btn.headerlink:before,.rst-content p.caption .btn.headerlink:before,.rst-content table>caption .btn.headerlink:before,.rst-content tt.download span.btn:first-child:before,.wy-menu-vertical li span.btn.toctree-expand:before{opacity:.5;-webkit-transition:opacity .05s ease-in;-moz-transition:opacity .05s ease-in;transition:opacity .05s ease-in}.btn.fa:hover:before,.btn.icon:hover:before,.rst-content .btn.admonition-title:hover:before,.rst-content .code-block-caption .btn.headerlink:hover:before,.rst-content code.download span.btn:first-child:hover:before,.rst-content dl dt .btn.headerlink:hover:before,.rst-content h1 .btn.headerlink:hover:before,.rst-content h2 .btn.headerlink:hover:before,.rst-content h3 .btn.headerlink:hover:before,.rst-content h4 .btn.headerlink:hover:before,.rst-content h5 .btn.headerlink:hover:before,.rst-content h6 .btn.headerlink:hover:before,.rst-content p.caption .btn.headerlink:hover:before,.rst-content table>caption .btn.headerlink:hover:before,.rst-content tt.download span.btn:first-child:hover:before,.wy-menu-vertical li span.btn.toctree-expand:hover:before{opacity:1}.btn-mini .fa:before,.btn-mini .icon:before,.btn-mini .rst-content .admonition-title:before,.btn-mini .rst-content .code-block-caption .headerlink:before,.btn-mini .rst-content code.download span:first-child:before,.btn-mini .rst-content dl dt .headerlink:before,.btn-mini .rst-content h1 .headerlink:before,.btn-mini .rst-content h2 .headerlink:before,.btn-mini .rst-content h3 .headerlink:before,.btn-mini .rst-content h4 .headerlink:before,.btn-mini .rst-content h5 .headerlink:before,.btn-mini .rst-content h6 .headerlink:before,.btn-mini .rst-content p.caption .headerlink:before,.btn-mini .rst-content table>caption .headerlink:before,.btn-mini .rst-content tt.download span:first-child:before,.btn-mini .wy-menu-vertical li span.toctree-expand:before,.rst-content .btn-mini .admonition-title:before,.rst-content .code-block-caption .btn-mini .headerlink:before,.rst-content code.download .btn-mini span:first-child:before,.rst-content dl dt .btn-mini .headerlink:before,.rst-content h1 .btn-mini .headerlink:before,.rst-content h2 .btn-mini .headerlink:before,.rst-content h3 .btn-mini .headerlink:before,.rst-content h4 .btn-mini .headerlink:before,.rst-content h5 .btn-mini .headerlink:before,.rst-content h6 .btn-mini .headerlink:before,.rst-content p.caption .btn-mini .headerlink:before,.rst-content table>caption .btn-mini .headerlink:before,.rst-content tt.download .btn-mini span:first-child:before,.wy-menu-vertical li .btn-mini span.toctree-expand:before{font-size:14px;vertical-align:-15%}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.wy-alert{padding:12px;line-height:24px;margin-bottom:24px;background:#e7f2fa}.rst-content .admonition-title,.wy-alert-title{font-weight:700;display:block;color:#fff;background:#6ab0de;padding:6px 12px;margin:-12px -12px 12px}.rst-content .danger,.rst-content .error,.rst-content .wy-alert-danger.admonition,.rst-content .wy-alert-danger.admonition-todo,.rst-content .wy-alert-danger.attention,.rst-content .wy-alert-danger.caution,.rst-content .wy-alert-danger.hint,.rst-content .wy-alert-danger.important,.rst-content .wy-alert-danger.note,.rst-content .wy-alert-danger.seealso,.rst-content .wy-alert-danger.tip,.rst-content .wy-alert-danger.warning,.wy-alert.wy-alert-danger{background:#fdf3f2}.rst-content .danger .admonition-title,.rst-content .danger .wy-alert-title,.rst-content .error .admonition-title,.rst-content .error .wy-alert-title,.rst-content .wy-alert-danger.admonition-todo .admonition-title,.rst-content .wy-alert-danger.admonition-todo .wy-alert-title,.rst-content .wy-alert-danger.admonition .admonition-title,.rst-content .wy-alert-danger.admonition .wy-alert-title,.rst-content .wy-alert-danger.attention .admonition-title,.rst-content .wy-alert-danger.attention .wy-alert-title,.rst-content .wy-alert-danger.caution .admonition-title,.rst-content .wy-alert-danger.caution .wy-alert-title,.rst-content .wy-alert-danger.hint .admonition-title,.rst-content .wy-alert-danger.hint .wy-alert-title,.rst-content .wy-alert-danger.important .admonition-title,.rst-content .wy-alert-danger.important .wy-alert-title,.rst-content .wy-alert-danger.note .admonition-title,.rst-content .wy-alert-danger.note .wy-alert-title,.rst-content .wy-alert-danger.seealso .admonition-title,.rst-content .wy-alert-danger.seealso .wy-alert-title,.rst-content .wy-alert-danger.tip .admonition-title,.rst-content .wy-alert-danger.tip .wy-alert-title,.rst-content .wy-alert-danger.warning .admonition-title,.rst-content .wy-alert-danger.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-danger .admonition-title,.wy-alert.wy-alert-danger .rst-content .admonition-title,.wy-alert.wy-alert-danger .wy-alert-title{background:#f29f97}.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .warning,.rst-content .wy-alert-warning.admonition,.rst-content .wy-alert-warning.danger,.rst-content .wy-alert-warning.error,.rst-content .wy-alert-warning.hint,.rst-content .wy-alert-warning.important,.rst-content .wy-alert-warning.note,.rst-content .wy-alert-warning.seealso,.rst-content .wy-alert-warning.tip,.wy-alert.wy-alert-warning{background:#ffedcc}.rst-content .admonition-todo .admonition-title,.rst-content .admonition-todo .wy-alert-title,.rst-content .attention .admonition-title,.rst-content .attention .wy-alert-title,.rst-content .caution .admonition-title,.rst-content .caution .wy-alert-title,.rst-content .warning .admonition-title,.rst-content .warning .wy-alert-title,.rst-content .wy-alert-warning.admonition .admonition-title,.rst-content .wy-alert-warning.admonition .wy-alert-title,.rst-content .wy-alert-warning.danger .admonition-title,.rst-content .wy-alert-warning.danger .wy-alert-title,.rst-content .wy-alert-warning.error .admonition-title,.rst-content .wy-alert-warning.error .wy-alert-title,.rst-content .wy-alert-warning.hint .admonition-title,.rst-content .wy-alert-warning.hint .wy-alert-title,.rst-content .wy-alert-warning.important .admonition-title,.rst-content .wy-alert-warning.important .wy-alert-title,.rst-content .wy-alert-warning.note .admonition-title,.rst-content .wy-alert-warning.note .wy-alert-title,.rst-content .wy-alert-warning.seealso .admonition-title,.rst-content .wy-alert-warning.seealso .wy-alert-title,.rst-content .wy-alert-warning.tip .admonition-title,.rst-content .wy-alert-warning.tip .wy-alert-title,.rst-content .wy-alert.wy-alert-warning .admonition-title,.wy-alert.wy-alert-warning .rst-content .admonition-title,.wy-alert.wy-alert-warning .wy-alert-title{background:#f0b37e}.rst-content .note,.rst-content .seealso,.rst-content .wy-alert-info.admonition,.rst-content .wy-alert-info.admonition-todo,.rst-content .wy-alert-info.attention,.rst-content .wy-alert-info.caution,.rst-content .wy-alert-info.danger,.rst-content .wy-alert-info.error,.rst-content .wy-alert-info.hint,.rst-content .wy-alert-info.important,.rst-content .wy-alert-info.tip,.rst-content .wy-alert-info.warning,.wy-alert.wy-alert-info{background:#e7f2fa}.rst-content .note .admonition-title,.rst-content .note .wy-alert-title,.rst-content .seealso .admonition-title,.rst-content .seealso .wy-alert-title,.rst-content .wy-alert-info.admonition-todo .admonition-title,.rst-content .wy-alert-info.admonition-todo .wy-alert-title,.rst-content .wy-alert-info.admonition .admonition-title,.rst-content .wy-alert-info.admonition .wy-alert-title,.rst-content .wy-alert-info.attention .admonition-title,.rst-content .wy-alert-info.attention .wy-alert-title,.rst-content .wy-alert-info.caution .admonition-title,.rst-content .wy-alert-info.caution .wy-alert-title,.rst-content .wy-alert-info.danger .admonition-title,.rst-content .wy-alert-info.danger .wy-alert-title,.rst-content .wy-alert-info.error .admonition-title,.rst-content .wy-alert-info.error .wy-alert-title,.rst-content .wy-alert-info.hint .admonition-title,.rst-content .wy-alert-info.hint .wy-alert-title,.rst-content .wy-alert-info.important .admonition-title,.rst-content .wy-alert-info.important .wy-alert-title,.rst-content .wy-alert-info.tip .admonition-title,.rst-content .wy-alert-info.tip .wy-alert-title,.rst-content .wy-alert-info.warning .admonition-title,.rst-content .wy-alert-info.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-info .admonition-title,.wy-alert.wy-alert-info .rst-content .admonition-title,.wy-alert.wy-alert-info .wy-alert-title{background:#6ab0de}.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .wy-alert-success.admonition,.rst-content .wy-alert-success.admonition-todo,.rst-content .wy-alert-success.attention,.rst-content .wy-alert-success.caution,.rst-content .wy-alert-success.danger,.rst-content .wy-alert-success.error,.rst-content .wy-alert-success.note,.rst-content .wy-alert-success.seealso,.rst-content .wy-alert-success.warning,.wy-alert.wy-alert-success{background:#dbfaf4}.rst-content .hint .admonition-title,.rst-content .hint .wy-alert-title,.rst-content .important .admonition-title,.rst-content .important .wy-alert-title,.rst-content .tip .admonition-title,.rst-content .tip .wy-alert-title,.rst-content .wy-alert-success.admonition-todo .admonition-title,.rst-content .wy-alert-success.admonition-todo .wy-alert-title,.rst-content .wy-alert-success.admonition .admonition-title,.rst-content .wy-alert-success.admonition .wy-alert-title,.rst-content .wy-alert-success.attention .admonition-title,.rst-content .wy-alert-success.attention .wy-alert-title,.rst-content .wy-alert-success.caution .admonition-title,.rst-content .wy-alert-success.caution .wy-alert-title,.rst-content .wy-alert-success.danger .admonition-title,.rst-content .wy-alert-success.danger .wy-alert-title,.rst-content .wy-alert-success.error .admonition-title,.rst-content .wy-alert-success.error .wy-alert-title,.rst-content .wy-alert-success.note .admonition-title,.rst-content .wy-alert-success.note .wy-alert-title,.rst-content .wy-alert-success.seealso .admonition-title,.rst-content .wy-alert-success.seealso .wy-alert-title,.rst-content .wy-alert-success.warning .admonition-title,.rst-content .wy-alert-success.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-success .admonition-title,.wy-alert.wy-alert-success .rst-content .admonition-title,.wy-alert.wy-alert-success .wy-alert-title{background:#1abc9c}.rst-content .wy-alert-neutral.admonition,.rst-content .wy-alert-neutral.admonition-todo,.rst-content .wy-alert-neutral.attention,.rst-content .wy-alert-neutral.caution,.rst-content .wy-alert-neutral.danger,.rst-content .wy-alert-neutral.error,.rst-content .wy-alert-neutral.hint,.rst-content .wy-alert-neutral.important,.rst-content .wy-alert-neutral.note,.rst-content .wy-alert-neutral.seealso,.rst-content .wy-alert-neutral.tip,.rst-content .wy-alert-neutral.warning,.wy-alert.wy-alert-neutral{background:#f3f6f6}.rst-content .wy-alert-neutral.admonition-todo .admonition-title,.rst-content .wy-alert-neutral.admonition-todo .wy-alert-title,.rst-content .wy-alert-neutral.admonition .admonition-title,.rst-content .wy-alert-neutral.admonition .wy-alert-title,.rst-content .wy-alert-neutral.attention .admonition-title,.rst-content .wy-alert-neutral.attention .wy-alert-title,.rst-content .wy-alert-neutral.caution .admonition-title,.rst-content .wy-alert-neutral.caution .wy-alert-title,.rst-content .wy-alert-neutral.danger .admonition-title,.rst-content .wy-alert-neutral.danger .wy-alert-title,.rst-content .wy-alert-neutral.error .admonition-title,.rst-content .wy-alert-neutral.error .wy-alert-title,.rst-content .wy-alert-neutral.hint .admonition-title,.rst-content .wy-alert-neutral.hint .wy-alert-title,.rst-content .wy-alert-neutral.important .admonition-title,.rst-content .wy-alert-neutral.important .wy-alert-title,.rst-content .wy-alert-neutral.note .admonition-title,.rst-content .wy-alert-neutral.note .wy-alert-title,.rst-content .wy-alert-neutral.seealso .admonition-title,.rst-content .wy-alert-neutral.seealso .wy-alert-title,.rst-content .wy-alert-neutral.tip .admonition-title,.rst-content .wy-alert-neutral.tip .wy-alert-title,.rst-content .wy-alert-neutral.warning .admonition-title,.rst-content .wy-alert-neutral.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-neutral .admonition-title,.wy-alert.wy-alert-neutral .rst-content .admonition-title,.wy-alert.wy-alert-neutral .wy-alert-title{color:#404040;background:#e1e4e5}.rst-content .wy-alert-neutral.admonition-todo a,.rst-content .wy-alert-neutral.admonition a,.rst-content .wy-alert-neutral.attention a,.rst-content .wy-alert-neutral.caution a,.rst-content .wy-alert-neutral.danger a,.rst-content .wy-alert-neutral.error a,.rst-content .wy-alert-neutral.hint a,.rst-content .wy-alert-neutral.important a,.rst-content .wy-alert-neutral.note a,.rst-content .wy-alert-neutral.seealso a,.rst-content .wy-alert-neutral.tip a,.rst-content .wy-alert-neutral.warning a,.wy-alert.wy-alert-neutral a{color:#2980b9}.rst-content .admonition-todo p:last-child,.rst-content .admonition p:last-child,.rst-content .attention p:last-child,.rst-content .caution p:last-child,.rst-content .danger p:last-child,.rst-content .error p:last-child,.rst-content .hint p:last-child,.rst-content .important p:last-child,.rst-content .note p:last-child,.rst-content .seealso p:last-child,.rst-content .tip p:last-child,.rst-content .warning p:last-child,.wy-alert p:last-child{margin-bottom:0}.wy-tray-container{position:fixed;bottom:0;left:0;z-index:600}.wy-tray-container li{display:block;width:300px;background:transparent;color:#fff;text-align:center;box-shadow:0 5px 5px 0 rgba(0,0,0,.1);padding:0 24px;min-width:20%;opacity:0;height:0;line-height:56px;overflow:hidden;-webkit-transition:all .3s ease-in;-moz-transition:all .3s ease-in;transition:all .3s ease-in}.wy-tray-container li.wy-tray-item-success{background:#27ae60}.wy-tray-container li.wy-tray-item-info{background:#2980b9}.wy-tray-container li.wy-tray-item-warning{background:#e67e22}.wy-tray-container li.wy-tray-item-danger{background:#e74c3c}.wy-tray-container li.on{opacity:1;height:56px}@media screen and (max-width:768px){.wy-tray-container{bottom:auto;top:0;width:100%}.wy-tray-container li{width:100%}}button{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle;cursor:pointer;line-height:normal;-webkit-appearance:button;*overflow:visible}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}button[disabled]{cursor:default}.btn{display:inline-block;border-radius:2px;line-height:normal;white-space:nowrap;text-align:center;cursor:pointer;font-size:100%;padding:6px 12px 8px;color:#fff;border:1px solid rgba(0,0,0,.1);background-color:#27ae60;text-decoration:none;font-weight:400;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 2px -1px hsla(0,0%,100%,.5),inset 0 -2px 0 0 rgba(0,0,0,.1);outline-none:false;vertical-align:middle;*display:inline;zoom:1;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transition:all .1s linear;-moz-transition:all .1s linear;transition:all .1s linear}.btn-hover{background:#2e8ece;color:#fff}.btn:hover{background:#2cc36b;color:#fff}.btn:focus{background:#2cc36b;outline:0}.btn:active{box-shadow:inset 0 -1px 0 0 rgba(0,0,0,.05),inset 0 2px 0 0 rgba(0,0,0,.1);padding:8px 12px 6px}.btn:visited{color:#fff}.btn-disabled,.btn-disabled:active,.btn-disabled:focus,.btn-disabled:hover,.btn:disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:.4;cursor:not-allowed;box-shadow:none}.btn::-moz-focus-inner{padding:0;border:0}.btn-small{font-size:80%}.btn-info{background-color:#2980b9!important}.btn-info:hover{background-color:#2e8ece!important}.btn-neutral{background-color:#f3f6f6!important;color:#404040!important}.btn-neutral:hover{background-color:#e5ebeb!important;color:#404040}.btn-neutral:visited{color:#404040!important}.btn-success{background-color:#27ae60!important}.btn-success:hover{background-color:#295!important}.btn-danger{background-color:#e74c3c!important}.btn-danger:hover{background-color:#ea6153!important}.btn-warning{background-color:#e67e22!important}.btn-warning:hover{background-color:#e98b39!important}.btn-invert{background-color:#222}.btn-invert:hover{background-color:#2f2f2f!important}.btn-link{background-color:transparent!important;color:#2980b9;box-shadow:none;border-color:transparent!important}.btn-link:active,.btn-link:hover{background-color:transparent!important;color:#409ad5!important;box-shadow:none}.btn-link:visited{color:#9b59b6}.wy-btn-group .btn,.wy-control .btn{vertical-align:middle}.wy-btn-group{margin-bottom:24px;*zoom:1}.wy-btn-group:after,.wy-btn-group:before{display:table;content:""}.wy-btn-group:after{clear:both}.wy-dropdown{position:relative;display:inline-block}.wy-dropdown-active .wy-dropdown-menu{display:block}.wy-dropdown-menu{position:absolute;left:0;display:none;float:left;top:100%;min-width:100%;background:#fcfcfc;z-index:100;border:1px solid #cfd7dd;box-shadow:0 2px 2px 0 rgba(0,0,0,.1);padding:12px}.wy-dropdown-menu>dd>a{display:block;clear:both;color:#404040;white-space:nowrap;font-size:90%;padding:0 12px;cursor:pointer}.wy-dropdown-menu>dd>a:hover{background:#2980b9;color:#fff}.wy-dropdown-menu>dd.divider{border-top:1px solid #cfd7dd;margin:6px 0}.wy-dropdown-menu>dd.search{padding-bottom:12px}.wy-dropdown-menu>dd.search input[type=search]{width:100%}.wy-dropdown-menu>dd.call-to-action{background:#e3e3e3;text-transform:uppercase;font-weight:500;font-size:80%}.wy-dropdown-menu>dd.call-to-action:hover{background:#e3e3e3}.wy-dropdown-menu>dd.call-to-action .btn{color:#fff}.wy-dropdown.wy-dropdown-up .wy-dropdown-menu{bottom:100%;top:auto;left:auto;right:0}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu{background:#fcfcfc;margin-top:2px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a{padding:6px 12px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a:hover{background:#2980b9;color:#fff}.wy-dropdown.wy-dropdown-left .wy-dropdown-menu{right:0;left:auto;text-align:right}.wy-dropdown-arrow:before{content:" ";border-bottom:5px solid #f5f5f5;border-left:5px solid transparent;border-right:5px solid transparent;position:absolute;display:block;top:-4px;left:50%;margin-left:-3px}.wy-dropdown-arrow.wy-dropdown-arrow-left:before{left:11px}.wy-form-stacked select{display:block}.wy-form-aligned .wy-help-inline,.wy-form-aligned input,.wy-form-aligned label,.wy-form-aligned select,.wy-form-aligned textarea{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-form-aligned .wy-control-group>label{display:inline-block;vertical-align:middle;width:10em;margin:6px 12px 0 0;float:left}.wy-form-aligned .wy-control{float:left}.wy-form-aligned .wy-control label{display:block}.wy-form-aligned .wy-control select{margin-top:6px}fieldset{margin:0}fieldset,legend{border:0;padding:0}legend{width:100%;white-space:normal;margin-bottom:24px;font-size:150%;*margin-left:-7px}label,legend{display:block}label{margin:0 0 .3125em;color:#333;font-size:90%}input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}.wy-control-group{margin-bottom:24px;max-width:1200px;margin-left:auto;margin-right:auto;*zoom:1}.wy-control-group:after,.wy-control-group:before{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group.wy-control-group-required>label:after{content:" *";color:#e74c3c}.wy-control-group .wy-form-full,.wy-control-group .wy-form-halves,.wy-control-group .wy-form-thirds{padding-bottom:12px}.wy-control-group .wy-form-full input[type=color],.wy-control-group .wy-form-full input[type=date],.wy-control-group .wy-form-full input[type=datetime-local],.wy-control-group .wy-form-full input[type=datetime],.wy-control-group .wy-form-full input[type=email],.wy-control-group .wy-form-full input[type=month],.wy-control-group .wy-form-full input[type=number],.wy-control-group .wy-form-full input[type=password],.wy-control-group .wy-form-full input[type=search],.wy-control-group .wy-form-full input[type=tel],.wy-control-group .wy-form-full input[type=text],.wy-control-group .wy-form-full input[type=time],.wy-control-group .wy-form-full input[type=url],.wy-control-group .wy-form-full input[type=week],.wy-control-group .wy-form-full select,.wy-control-group .wy-form-halves input[type=color],.wy-control-group .wy-form-halves input[type=date],.wy-control-group .wy-form-halves input[type=datetime-local],.wy-control-group .wy-form-halves input[type=datetime],.wy-control-group .wy-form-halves input[type=email],.wy-control-group .wy-form-halves input[type=month],.wy-control-group .wy-form-halves input[type=number],.wy-control-group .wy-form-halves input[type=password],.wy-control-group .wy-form-halves input[type=search],.wy-control-group .wy-form-halves input[type=tel],.wy-control-group .wy-form-halves input[type=text],.wy-control-group .wy-form-halves input[type=time],.wy-control-group .wy-form-halves input[type=url],.wy-control-group .wy-form-halves input[type=week],.wy-control-group .wy-form-halves select,.wy-control-group .wy-form-thirds input[type=color],.wy-control-group .wy-form-thirds input[type=date],.wy-control-group .wy-form-thirds input[type=datetime-local],.wy-control-group .wy-form-thirds input[type=datetime],.wy-control-group .wy-form-thirds input[type=email],.wy-control-group .wy-form-thirds input[type=month],.wy-control-group .wy-form-thirds input[type=number],.wy-control-group .wy-form-thirds input[type=password],.wy-control-group .wy-form-thirds input[type=search],.wy-control-group .wy-form-thirds input[type=tel],.wy-control-group .wy-form-thirds input[type=text],.wy-control-group .wy-form-thirds input[type=time],.wy-control-group .wy-form-thirds input[type=url],.wy-control-group .wy-form-thirds input[type=week],.wy-control-group .wy-form-thirds select{width:100%}.wy-control-group .wy-form-full{float:left;display:block;width:100%;margin-right:0}.wy-control-group .wy-form-full:last-child{margin-right:0}.wy-control-group .wy-form-halves{float:left;display:block;margin-right:2.35765%;width:48.82117%}.wy-control-group .wy-form-halves:last-child,.wy-control-group .wy-form-halves:nth-of-type(2n){margin-right:0}.wy-control-group .wy-form-halves:nth-of-type(odd){clear:left}.wy-control-group .wy-form-thirds{float:left;display:block;margin-right:2.35765%;width:31.76157%}.wy-control-group .wy-form-thirds:last-child,.wy-control-group .wy-form-thirds:nth-of-type(3n){margin-right:0}.wy-control-group .wy-form-thirds:nth-of-type(3n+1){clear:left}.wy-control-group.wy-control-group-no-input .wy-control,.wy-control-no-input{margin:6px 0 0;font-size:90%}.wy-control-no-input{display:inline-block}.wy-control-group.fluid-input input[type=color],.wy-control-group.fluid-input input[type=date],.wy-control-group.fluid-input input[type=datetime-local],.wy-control-group.fluid-input input[type=datetime],.wy-control-group.fluid-input input[type=email],.wy-control-group.fluid-input input[type=month],.wy-control-group.fluid-input input[type=number],.wy-control-group.fluid-input input[type=password],.wy-control-group.fluid-input input[type=search],.wy-control-group.fluid-input input[type=tel],.wy-control-group.fluid-input input[type=text],.wy-control-group.fluid-input input[type=time],.wy-control-group.fluid-input input[type=url],.wy-control-group.fluid-input input[type=week]{width:100%}.wy-form-message-inline{padding-left:.3em;color:#666;font-size:90%}.wy-form-message{display:block;color:#999;font-size:70%;margin-top:.3125em;font-style:italic}.wy-form-message p{font-size:inherit;font-style:italic;margin-bottom:6px}.wy-form-message p:last-child{margin-bottom:0}input{line-height:normal}input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;*overflow:visible}input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week]{-webkit-appearance:none;padding:6px;display:inline-block;border:1px solid #ccc;font-size:80%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 3px #ddd;border-radius:0;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}input[type=datetime-local]{padding:.34375em .625em}input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{padding:0;margin-right:.3125em;*height:13px;*width:13px}input[type=checkbox],input[type=radio],input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}input[type=color]:focus,input[type=date]:focus,input[type=datetime-local]:focus,input[type=datetime]:focus,input[type=email]:focus,input[type=month]:focus,input[type=number]:focus,input[type=password]:focus,input[type=search]:focus,input[type=tel]:focus,input[type=text]:focus,input[type=time]:focus,input[type=url]:focus,input[type=week]:focus{outline:0;outline:thin dotted\9;border-color:#333}input.no-focus:focus{border-color:#ccc!important}input[type=checkbox]:focus,input[type=file]:focus,input[type=radio]:focus{outline:thin dotted #333;outline:1px auto #129fea}input[type=color][disabled],input[type=date][disabled],input[type=datetime-local][disabled],input[type=datetime][disabled],input[type=email][disabled],input[type=month][disabled],input[type=number][disabled],input[type=password][disabled],input[type=search][disabled],input[type=tel][disabled],input[type=text][disabled],input[type=time][disabled],input[type=url][disabled],input[type=week][disabled]{cursor:not-allowed;background-color:#fafafa}input:focus:invalid,select:focus:invalid,textarea:focus:invalid{color:#e74c3c;border:1px solid #e74c3c}input:focus:invalid:focus,select:focus:invalid:focus,textarea:focus:invalid:focus{border-color:#e74c3c}input[type=checkbox]:focus:invalid:focus,input[type=file]:focus:invalid:focus,input[type=radio]:focus:invalid:focus{outline-color:#e74c3c}input.wy-input-large{padding:12px;font-size:100%}textarea{overflow:auto;vertical-align:top;width:100%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif}select,textarea{padding:.5em .625em;display:inline-block;border:1px solid #ccc;font-size:80%;box-shadow:inset 0 1px 3px #ddd;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}select{border:1px solid #ccc;background-color:#fff}select[multiple]{height:auto}select:focus,textarea:focus{outline:0}input[readonly],select[disabled],select[readonly],textarea[disabled],textarea[readonly]{cursor:not-allowed;background-color:#fafafa}input[type=checkbox][disabled],input[type=radio][disabled]{cursor:not-allowed}.wy-checkbox,.wy-radio{margin:6px 0;color:#404040;display:block}.wy-checkbox input,.wy-radio input{vertical-align:baseline}.wy-form-message-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-input-prefix,.wy-input-suffix{white-space:nowrap;padding:6px}.wy-input-prefix .wy-input-context,.wy-input-suffix .wy-input-context{line-height:27px;padding:0 8px;display:inline-block;font-size:80%;background-color:#f3f6f6;border:1px solid #ccc;color:#999}.wy-input-suffix .wy-input-context{border-left:0}.wy-input-prefix .wy-input-context{border-right:0}.wy-switch{position:relative;display:block;height:24px;margin-top:12px;cursor:pointer}.wy-switch:before{left:0;top:0;width:36px;height:12px;background:#ccc}.wy-switch:after,.wy-switch:before{position:absolute;content:"";display:block;border-radius:4px;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.wy-switch:after{width:18px;height:18px;background:#999;left:-3px;top:-3px}.wy-switch span{position:absolute;left:48px;display:block;font-size:12px;color:#ccc;line-height:1}.wy-switch.active:before{background:#1e8449}.wy-switch.active:after{left:24px;background:#27ae60}.wy-switch.disabled{cursor:not-allowed;opacity:.8}.wy-control-group.wy-control-group-error .wy-form-message,.wy-control-group.wy-control-group-error>label{color:#e74c3c}.wy-control-group.wy-control-group-error input[type=color],.wy-control-group.wy-control-group-error input[type=date],.wy-control-group.wy-control-group-error input[type=datetime-local],.wy-control-group.wy-control-group-error input[type=datetime],.wy-control-group.wy-control-group-error input[type=email],.wy-control-group.wy-control-group-error input[type=month],.wy-control-group.wy-control-group-error input[type=number],.wy-control-group.wy-control-group-error input[type=password],.wy-control-group.wy-control-group-error input[type=search],.wy-control-group.wy-control-group-error input[type=tel],.wy-control-group.wy-control-group-error input[type=text],.wy-control-group.wy-control-group-error input[type=time],.wy-control-group.wy-control-group-error input[type=url],.wy-control-group.wy-control-group-error input[type=week],.wy-control-group.wy-control-group-error textarea{border:1px solid #e74c3c}.wy-inline-validate{white-space:nowrap}.wy-inline-validate .wy-input-context{padding:.5em .625em;display:inline-block;font-size:80%}.wy-inline-validate.wy-inline-validate-success .wy-input-context{color:#27ae60}.wy-inline-validate.wy-inline-validate-danger .wy-input-context{color:#e74c3c}.wy-inline-validate.wy-inline-validate-warning .wy-input-context{color:#e67e22}.wy-inline-validate.wy-inline-validate-info .wy-input-context{color:#2980b9}.rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.rotate-180{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.rotate-270{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.mirror{-webkit-transform:scaleX(-1);-moz-transform:scaleX(-1);-ms-transform:scaleX(-1);-o-transform:scaleX(-1);transform:scaleX(-1)}.mirror.rotate-90{-webkit-transform:scaleX(-1) rotate(90deg);-moz-transform:scaleX(-1) rotate(90deg);-ms-transform:scaleX(-1) rotate(90deg);-o-transform:scaleX(-1) rotate(90deg);transform:scaleX(-1) rotate(90deg)}.mirror.rotate-180{-webkit-transform:scaleX(-1) rotate(180deg);-moz-transform:scaleX(-1) rotate(180deg);-ms-transform:scaleX(-1) rotate(180deg);-o-transform:scaleX(-1) rotate(180deg);transform:scaleX(-1) rotate(180deg)}.mirror.rotate-270{-webkit-transform:scaleX(-1) rotate(270deg);-moz-transform:scaleX(-1) rotate(270deg);-ms-transform:scaleX(-1) rotate(270deg);-o-transform:scaleX(-1) rotate(270deg);transform:scaleX(-1) rotate(270deg)}@media only screen and (max-width:480px){.wy-form button[type=submit]{margin:.7em 0 0}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=text],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week],.wy-form label{margin-bottom:.3em;display:block}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week]{margin-bottom:0}.wy-form-aligned .wy-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.wy-form-aligned .wy-control{margin:1.5em 0 0}.wy-form-message,.wy-form-message-inline,.wy-form .wy-help-inline{display:block;font-size:80%;padding:6px 0}}@media screen and (max-width:768px){.tablet-hide{display:none}}@media screen and (max-width:480px){.mobile-hide{display:none}}.float-left{float:left}.float-right{float:right}.full-width{width:100%}.rst-content table.docutils,.rst-content table.field-list,.wy-table{border-collapse:collapse;border-spacing:0;empty-cells:show;margin-bottom:24px}.rst-content table.docutils caption,.rst-content table.field-list caption,.wy-table caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.rst-content table.docutils td,.rst-content table.docutils th,.rst-content table.field-list td,.rst-content table.field-list th,.wy-table td,.wy-table th{font-size:90%;margin:0;overflow:visible;padding:8px 16px}.rst-content table.docutils td:first-child,.rst-content table.docutils th:first-child,.rst-content table.field-list td:first-child,.rst-content table.field-list th:first-child,.wy-table td:first-child,.wy-table th:first-child{border-left-width:0}.rst-content table.docutils thead,.rst-content table.field-list thead,.wy-table thead{color:#000;text-align:left;vertical-align:bottom;white-space:nowrap}.rst-content table.docutils thead th,.rst-content table.field-list thead th,.wy-table thead th{font-weight:700;border-bottom:2px solid #e1e4e5}.rst-content table.docutils td,.rst-content table.field-list td,.wy-table td{background-color:transparent;vertical-align:middle}.rst-content table.docutils td p,.rst-content table.field-list td p,.wy-table td p{line-height:18px}.rst-content table.docutils td p:last-child,.rst-content table.field-list td p:last-child,.wy-table td p:last-child{margin-bottom:0}.rst-content table.docutils .wy-table-cell-min,.rst-content table.field-list .wy-table-cell-min,.wy-table .wy-table-cell-min{width:1%;padding-right:0}.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox],.wy-table .wy-table-cell-min input[type=checkbox]{margin:0}.wy-table-secondary{color:grey;font-size:90%}.wy-table-tertiary{color:grey;font-size:80%}.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td,.wy-table-backed,.wy-table-odd td,.wy-table-striped tr:nth-child(2n-1) td{background-color:#f3f6f6}.rst-content table.docutils,.wy-table-bordered-all{border:1px solid #e1e4e5}.rst-content table.docutils td,.wy-table-bordered-all td{border-bottom:1px solid #e1e4e5;border-left:1px solid #e1e4e5}.rst-content table.docutils tbody>tr:last-child td,.wy-table-bordered-all tbody>tr:last-child td{border-bottom-width:0}.wy-table-bordered{border:1px solid #e1e4e5}.wy-table-bordered-rows td{border-bottom:1px solid #e1e4e5}.wy-table-bordered-rows tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal td,.wy-table-horizontal th{border-width:0 0 1px;border-bottom:1px solid #e1e4e5}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-responsive{margin-bottom:24px;max-width:100%;overflow:auto}.wy-table-responsive table{margin-bottom:0!important}.wy-table-responsive table td,.wy-table-responsive table th{white-space:nowrap}a{color:#2980b9;text-decoration:none;cursor:pointer}a:hover{color:#3091d1}a:visited{color:#9b59b6}html{height:100%}body,html{overflow-x:hidden}body{font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;font-weight:400;color:#404040;min-height:100%;background:#edf0f2}.wy-text-left{text-align:left}.wy-text-center{text-align:center}.wy-text-right{text-align:right}.wy-text-large{font-size:120%}.wy-text-normal{font-size:100%}.wy-text-small,small{font-size:80%}.wy-text-strike{text-decoration:line-through}.wy-text-warning{color:#e67e22!important}a.wy-text-warning:hover{color:#eb9950!important}.wy-text-info{color:#2980b9!important}a.wy-text-info:hover{color:#409ad5!important}.wy-text-success{color:#27ae60!important}a.wy-text-success:hover{color:#36d278!important}.wy-text-danger{color:#e74c3c!important}a.wy-text-danger:hover{color:#ed7669!important}.wy-text-neutral{color:#404040!important}a.wy-text-neutral:hover{color:#595959!important}.rst-content .toctree-wrapper>p.caption,h1,h2,h3,h4,h5,h6,legend{margin-top:0;font-weight:700;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif}p{line-height:24px;font-size:16px;margin:0 0 24px}h1{font-size:175%}.rst-content .toctree-wrapper>p.caption,h2{font-size:150%}h3{font-size:125%}h4{font-size:115%}h5{font-size:110%}h6{font-size:100%}hr{display:block;height:1px;border:0;border-top:1px solid #e1e4e5;margin:24px 0;padding:0}.rst-content code,.rst-content tt,code{white-space:nowrap;max-width:100%;background:#fff;border:1px solid #e1e4e5;font-size:75%;padding:0 5px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;color:#e74c3c;overflow-x:auto}.rst-content tt.code-large,code.code-large{font-size:90%}.rst-content .section ul,.rst-content .toctree-wrapper ul,.wy-plain-list-disc,article ul{list-style:disc;line-height:24px;margin-bottom:24px}.rst-content .section ul li,.rst-content .toctree-wrapper ul li,.wy-plain-list-disc li,article ul li{list-style:disc;margin-left:24px}.rst-content .section ul li p:last-child,.rst-content .section ul li ul,.rst-content .toctree-wrapper ul li p:last-child,.rst-content .toctree-wrapper ul li ul,.wy-plain-list-disc li p:last-child,.wy-plain-list-disc li ul,article ul li p:last-child,article ul li ul{margin-bottom:0}.rst-content .section ul li li,.rst-content .toctree-wrapper ul li li,.wy-plain-list-disc li li,article ul li li{list-style:circle}.rst-content .section ul li li li,.rst-content .toctree-wrapper ul li li li,.wy-plain-list-disc li li li,article ul li li li{list-style:square}.rst-content .section ul li ol li,.rst-content .toctree-wrapper ul li ol li,.wy-plain-list-disc li ol li,article ul li ol li{list-style:decimal}.rst-content .section ol,.rst-content ol.arabic,.wy-plain-list-decimal,article ol{list-style:decimal;line-height:24px;margin-bottom:24px}.rst-content .section ol li,.rst-content ol.arabic li,.wy-plain-list-decimal li,article ol li{list-style:decimal;margin-left:24px}.rst-content .section ol li p:last-child,.rst-content .section ol li ul,.rst-content ol.arabic li p:last-child,.rst-content ol.arabic li ul,.wy-plain-list-decimal li p:last-child,.wy-plain-list-decimal li ul,article ol li p:last-child,article ol li ul{margin-bottom:0}.rst-content .section ol li ul li,.rst-content ol.arabic li ul li,.wy-plain-list-decimal li ul li,article ol li ul li{list-style:disc}.wy-breadcrumbs{*zoom:1}.wy-breadcrumbs:after,.wy-breadcrumbs:before{display:table;content:""}.wy-breadcrumbs:after{clear:both}.wy-breadcrumbs li{display:inline-block}.wy-breadcrumbs li.wy-breadcrumbs-aside{float:right}.wy-breadcrumbs li a{display:inline-block;padding:5px}.wy-breadcrumbs li a:first-child{padding-left:0}.rst-content .wy-breadcrumbs li tt,.wy-breadcrumbs li .rst-content tt,.wy-breadcrumbs li code{padding:5px;border:none;background:none}.rst-content .wy-breadcrumbs li tt.literal,.wy-breadcrumbs li .rst-content tt.literal,.wy-breadcrumbs li code.literal{color:#404040}.wy-breadcrumbs-extra{margin-bottom:0;color:#b3b3b3;font-size:80%;display:inline-block}@media screen and (max-width:480px){.wy-breadcrumbs-extra,.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}@media print{.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}html{font-size:16px}.wy-affix{position:fixed;top:1.618em}.wy-menu a:hover{text-decoration:none}.wy-menu-horiz{*zoom:1}.wy-menu-horiz:after,.wy-menu-horiz:before{display:table;content:""}.wy-menu-horiz:after{clear:both}.wy-menu-horiz li,.wy-menu-horiz ul{display:inline-block}.wy-menu-horiz li:hover{background:hsla(0,0%,100%,.1)}.wy-menu-horiz li.divide-left{border-left:1px solid #404040}.wy-menu-horiz li.divide-right{border-right:1px solid #404040}.wy-menu-horiz a{height:32px;display:inline-block;line-height:32px;padding:0 16px}.wy-menu-vertical{width:300px}.wy-menu-vertical header,.wy-menu-vertical p.caption{color:#55a5d9;height:32px;line-height:32px;padding:0 1.618em;margin:12px 0 0;display:block;font-weight:700;text-transform:uppercase;font-size:85%;white-space:nowrap}.wy-menu-vertical ul{margin-bottom:0}.wy-menu-vertical li.divide-top{border-top:1px solid #404040}.wy-menu-vertical li.divide-bottom{border-bottom:1px solid #404040}.wy-menu-vertical li.current{background:#e3e3e3}.wy-menu-vertical li.current a{color:grey;border-right:1px solid #c9c9c9;padding:.4045em 2.427em}.wy-menu-vertical li.current a:hover{background:#d6d6d6}.rst-content .wy-menu-vertical li tt,.wy-menu-vertical li .rst-content tt,.wy-menu-vertical li code{border:none;background:inherit;color:inherit;padding-left:0;padding-right:0}.wy-menu-vertical li span.toctree-expand{display:block;float:left;margin-left:-1.2em;font-size:.8em;line-height:1.6em;color:#4d4d4d}.wy-menu-vertical li.current>a,.wy-menu-vertical li.on a{color:#404040;font-weight:700;position:relative;background:#fcfcfc;border:none;padding:.4045em 1.618em}.wy-menu-vertical li.current>a:hover,.wy-menu-vertical li.on a:hover{background:#fcfcfc}.wy-menu-vertical li.current>a:hover span.toctree-expand,.wy-menu-vertical li.on a:hover span.toctree-expand{color:grey}.wy-menu-vertical li.current>a span.toctree-expand,.wy-menu-vertical li.on a span.toctree-expand{display:block;font-size:.8em;line-height:1.6em;color:#333}.wy-menu-vertical li.toctree-l1.current>a{border-bottom:1px solid #c9c9c9;border-top:1px solid #c9c9c9}.wy-menu-vertical .toctree-l1.current .toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .toctree-l11>ul{display:none}.wy-menu-vertical .toctree-l1.current .current.toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .current.toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .current.toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .current.toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .current.toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .current.toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .current.toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .current.toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .current.toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .current.toctree-l11>ul{display:block}.wy-menu-vertical li.toctree-l3,.wy-menu-vertical li.toctree-l4{font-size:.9em}.wy-menu-vertical li.toctree-l2 a,.wy-menu-vertical li.toctree-l3 a,.wy-menu-vertical li.toctree-l4 a,.wy-menu-vertical li.toctree-l5 a,.wy-menu-vertical li.toctree-l6 a,.wy-menu-vertical li.toctree-l7 a,.wy-menu-vertical li.toctree-l8 a,.wy-menu-vertical li.toctree-l9 a,.wy-menu-vertical li.toctree-l10 a{color:#404040}.wy-menu-vertical li.toctree-l2 a:hover span.toctree-expand,.wy-menu-vertical li.toctree-l3 a:hover span.toctree-expand,.wy-menu-vertical li.toctree-l4 a:hover span.toctree-expand,.wy-menu-vertical li.toctree-l5 a:hover span.toctree-expand,.wy-menu-vertical li.toctree-l6 a:hover span.toctree-expand,.wy-menu-vertical li.toctree-l7 a:hover span.toctree-expand,.wy-menu-vertical li.toctree-l8 a:hover span.toctree-expand,.wy-menu-vertical li.toctree-l9 a:hover span.toctree-expand,.wy-menu-vertical li.toctree-l10 a:hover span.toctree-expand{color:grey}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a,.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a,.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a,.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a,.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a,.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a,.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a,.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{display:block}.wy-menu-vertical li.toctree-l2.current>a{padding:.4045em 2.427em}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a,.wy-menu-vertical li.toctree-l3.current>a{padding:.4045em 4.045em}.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a,.wy-menu-vertical li.toctree-l4.current>a{padding:.4045em 5.663em}.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a,.wy-menu-vertical li.toctree-l5.current>a{padding:.4045em 7.281em}.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a,.wy-menu-vertical li.toctree-l6.current>a{padding:.4045em 8.899em}.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a,.wy-menu-vertical li.toctree-l7.current>a{padding:.4045em 10.517em}.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a,.wy-menu-vertical li.toctree-l8.current>a{padding:.4045em 12.135em}.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a,.wy-menu-vertical li.toctree-l9.current>a{padding:.4045em 13.753em}.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a,.wy-menu-vertical li.toctree-l10.current>a{padding:.4045em 15.371em}.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{padding:.4045em 16.989em}.wy-menu-vertical li.toctree-l2.current>a,.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{background:#c9c9c9}.wy-menu-vertical li.toctree-l2 span.toctree-expand{color:#a3a3a3}.wy-menu-vertical li.toctree-l3.current>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{background:#bdbdbd}.wy-menu-vertical li.toctree-l3 span.toctree-expand{color:#969696}.wy-menu-vertical li.current ul{display:block}.wy-menu-vertical li ul{margin-bottom:0;display:none}.wy-menu-vertical li ul li a{margin-bottom:0;color:#d9d9d9;font-weight:400}.wy-menu-vertical a{line-height:18px;padding:.4045em 1.618em;display:block;position:relative;font-size:90%;color:#d9d9d9}.wy-menu-vertical a:hover{background-color:#4e4a4a;cursor:pointer}.wy-menu-vertical a:hover span.toctree-expand{color:#d9d9d9}.wy-menu-vertical a:active{background-color:#2980b9;cursor:pointer;color:#fff}.wy-menu-vertical a:active span.toctree-expand{color:#fff}.wy-side-nav-search{display:block;width:300px;padding:.809em;margin-bottom:.809em;z-index:200;background-color:#2980b9;text-align:center;color:#fcfcfc}.wy-side-nav-search input[type=text]{width:100%;border-radius:50px;padding:6px 12px;border-color:#2472a4}.wy-side-nav-search img{display:block;margin:auto auto .809em;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-side-nav-search .wy-dropdown>a,.wy-side-nav-search>a{color:#fcfcfc;font-size:100%;font-weight:700;display:inline-block;padding:4px 6px;margin-bottom:.809em}.wy-side-nav-search .wy-dropdown>a:hover,.wy-side-nav-search>a:hover{background:hsla(0,0%,100%,.1)}.wy-side-nav-search .wy-dropdown>a img.logo,.wy-side-nav-search>a img.logo{display:block;margin:0 auto;height:auto;width:auto;border-radius:0;max-width:100%;background:transparent}.wy-side-nav-search .wy-dropdown>a.icon img.logo,.wy-side-nav-search>a.icon img.logo{margin-top:.85em}.wy-side-nav-search>div.version{margin-top:-.4045em;margin-bottom:.809em;font-weight:400;color:hsla(0,0%,100%,.3)}.wy-nav .wy-menu-vertical header{color:#2980b9}.wy-nav .wy-menu-vertical a{color:#b3b3b3}.wy-nav .wy-menu-vertical a:hover{background-color:#2980b9;color:#fff}[data-menu-wrap]{-webkit-transition:all .2s ease-in;-moz-transition:all .2s ease-in;transition:all .2s ease-in;position:absolute;opacity:1;width:100%;opacity:0}[data-menu-wrap].move-center{left:0;right:auto;opacity:1}[data-menu-wrap].move-left{right:auto;left:-100%;opacity:0}[data-menu-wrap].move-right{right:-100%;left:auto;opacity:0}.wy-body-for-nav{background:#fcfcfc}.wy-grid-for-nav{position:absolute;width:100%;height:100%}.wy-nav-side{position:fixed;top:0;bottom:0;left:0;padding-bottom:2em;width:300px;overflow-x:hidden;overflow-y:hidden;min-height:100%;color:#9b9b9b;background:#343131;z-index:200}.wy-side-scroll{width:320px;position:relative;overflow-x:hidden;overflow-y:scroll;height:100%}.wy-nav-top{display:none;background:#2980b9;color:#fff;padding:.4045em .809em;position:relative;line-height:50px;text-align:center;font-size:100%;*zoom:1}.wy-nav-top:after,.wy-nav-top:before{display:table;content:""}.wy-nav-top:after{clear:both}.wy-nav-top a{color:#fff;font-weight:700}.wy-nav-top img{margin-right:12px;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-nav-top i{font-size:30px;float:left;cursor:pointer;padding-top:inherit}.wy-nav-content-wrap{margin-left:300px;background:#fcfcfc;min-height:100%}.wy-nav-content{padding:1.618em 3.236em;height:100%;max-width:800px;margin:auto}.wy-body-mask{position:fixed;width:100%;height:100%;background:rgba(0,0,0,.2);display:none;z-index:499}.wy-body-mask.on{display:block}footer{color:grey}footer p{margin-bottom:12px}.rst-content footer span.commit tt,footer span.commit .rst-content tt,footer span.commit code{padding:0;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:1em;background:none;border:none;color:grey}.rst-footer-buttons{*zoom:1}.rst-footer-buttons:after,.rst-footer-buttons:before{width:100%;display:table;content:""}.rst-footer-buttons:after{clear:both}.rst-breadcrumbs-buttons{margin-top:12px;*zoom:1}.rst-breadcrumbs-buttons:after,.rst-breadcrumbs-buttons:before{display:table;content:""}.rst-breadcrumbs-buttons:after{clear:both}#search-results .search li{margin-bottom:24px;border-bottom:1px solid #e1e4e5;padding-bottom:24px}#search-results .search li:first-child{border-top:1px solid #e1e4e5;padding-top:24px}#search-results .search li a{font-size:120%;margin-bottom:12px;display:inline-block}#search-results .context{color:grey;font-size:90%}.genindextable li>ul{margin-left:24px}@media screen and (max-width:768px){.wy-body-for-nav{background:#fcfcfc}.wy-nav-top{display:block}.wy-nav-side{left:-300px}.wy-nav-side.shift{width:85%;left:0}.wy-menu.wy-menu-vertical,.wy-side-nav-search,.wy-side-scroll{width:auto}.wy-nav-content-wrap{margin-left:0}.wy-nav-content-wrap .wy-nav-content{padding:1.618em}.wy-nav-content-wrap.shift{position:fixed;min-width:100%;left:85%;top:0;height:100%;overflow:hidden}}@media screen and (min-width:1100px){.wy-nav-content-wrap{background:rgba(0,0,0,.05)}.wy-nav-content{margin:0;background:#fcfcfc}}@media print{.rst-versions,.wy-nav-side,footer{display:none}.wy-nav-content-wrap{margin-left:0}}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60;*zoom:1}.rst-versions .rst-current-version:after,.rst-versions .rst-current-version:before{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-content .code-block-caption .rst-versions .rst-current-version .headerlink,.rst-content .rst-versions .rst-current-version .admonition-title,.rst-content code.download .rst-versions .rst-current-version span:first-child,.rst-content dl dt .rst-versions .rst-current-version .headerlink,.rst-content h1 .rst-versions .rst-current-version .headerlink,.rst-content h2 .rst-versions .rst-current-version .headerlink,.rst-content h3 .rst-versions .rst-current-version .headerlink,.rst-content h4 .rst-versions .rst-current-version .headerlink,.rst-content h5 .rst-versions .rst-current-version .headerlink,.rst-content h6 .rst-versions .rst-current-version .headerlink,.rst-content p.caption .rst-versions .rst-current-version .headerlink,.rst-content table>caption .rst-versions .rst-current-version .headerlink,.rst-content tt.download .rst-versions .rst-current-version span:first-child,.rst-versions .rst-current-version .fa,.rst-versions .rst-current-version .icon,.rst-versions .rst-current-version .rst-content .admonition-title,.rst-versions .rst-current-version .rst-content .code-block-caption .headerlink,.rst-versions .rst-current-version .rst-content code.download span:first-child,.rst-versions .rst-current-version .rst-content dl dt .headerlink,.rst-versions .rst-current-version .rst-content h1 .headerlink,.rst-versions .rst-current-version .rst-content h2 .headerlink,.rst-versions .rst-current-version .rst-content h3 .headerlink,.rst-versions .rst-current-version .rst-content h4 .headerlink,.rst-versions .rst-current-version .rst-content h5 .headerlink,.rst-versions .rst-current-version .rst-content h6 .headerlink,.rst-versions .rst-current-version .rst-content p.caption .headerlink,.rst-versions .rst-current-version .rst-content table>caption .headerlink,.rst-versions .rst-current-version .rst-content tt.download span:first-child,.rst-versions .rst-current-version .wy-menu-vertical li span.toctree-expand,.wy-menu-vertical li .rst-versions .rst-current-version span.toctree-expand{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}.rst-content img{max-width:100%;height:auto}.rst-content div.figure{margin-bottom:24px}.rst-content div.figure p.caption{font-style:italic}.rst-content div.figure p:last-child.caption{margin-bottom:0}.rst-content div.figure.align-center{text-align:center}.rst-content .section>a>img,.rst-content .section>img{margin-bottom:24px}.rst-content abbr[title]{text-decoration:none}.rst-content.style-external-links a.reference.external:after{font-family:FontAwesome;content:"\f08e";color:#b3b3b3;vertical-align:super;font-size:60%;margin:0 .2em}.rst-content blockquote{margin-left:24px;line-height:24px;margin-bottom:24px}.rst-content pre.literal-block{white-space:pre;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;display:block;overflow:auto}.rst-content div[class^=highlight],.rst-content pre.literal-block{border:1px solid #e1e4e5;overflow-x:auto;margin:1px 0 24px}.rst-content div[class^=highlight] div[class^=highlight],.rst-content pre.literal-block div[class^=highlight]{padding:0;border:none;margin:0}.rst-content div[class^=highlight] td.code{width:100%}.rst-content .linenodiv pre{border-right:1px solid #e6e9ea;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;user-select:none;pointer-events:none}.rst-content div[class^=highlight] pre{white-space:pre;margin:0;padding:12px;display:block;overflow:auto}.rst-content div[class^=highlight] pre .hll{display:block;margin:0 -12px;padding:0 12px}.rst-content .linenodiv pre,.rst-content div[class^=highlight] pre,.rst-content pre.literal-block{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:12px;line-height:1.4}.rst-content div.highlight .gp{user-select:none;pointer-events:none}.rst-content .code-block-caption{font-style:italic;font-size:85%;line-height:1;padding:1em 0;text-align:center}@media print{.rst-content .codeblock,.rst-content div[class^=highlight],.rst-content div[class^=highlight] pre{white-space:pre-wrap}}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning{clear:both}.rst-content .admonition-todo .last,.rst-content .admonition-todo>:last-child,.rst-content .admonition .last,.rst-content .admonition>:last-child,.rst-content .attention .last,.rst-content .attention>:last-child,.rst-content .caution .last,.rst-content .caution>:last-child,.rst-content .danger .last,.rst-content .danger>:last-child,.rst-content .error .last,.rst-content .error>:last-child,.rst-content .hint .last,.rst-content .hint>:last-child,.rst-content .important .last,.rst-content .important>:last-child,.rst-content .note .last,.rst-content .note>:last-child,.rst-content .seealso .last,.rst-content .seealso>:last-child,.rst-content .tip .last,.rst-content .tip>:last-child,.rst-content .warning .last,.rst-content .warning>:last-child{margin-bottom:0}.rst-content .admonition-title:before{margin-right:4px}.rst-content .admonition table{border-color:rgba(0,0,0,.1)}.rst-content .admonition table td,.rst-content .admonition table th{background:transparent!important;border-color:rgba(0,0,0,.1)!important}.rst-content .section ol.loweralpha,.rst-content .section ol.loweralpha>li{list-style:lower-alpha}.rst-content .section ol.upperalpha,.rst-content .section ol.upperalpha>li{list-style:upper-alpha}.rst-content .section ol li>*,.rst-content .section ul li>*{margin-top:12px;margin-bottom:12px}.rst-content .section ol li>:first-child,.rst-content .section ul li>:first-child{margin-top:0}.rst-content .section ol li>p,.rst-content .section ol li>p:last-child,.rst-content .section ul li>p,.rst-content .section ul li>p:last-child{margin-bottom:12px}.rst-content .section ol li>p:only-child,.rst-content .section ol li>p:only-child:last-child,.rst-content .section ul li>p:only-child,.rst-content .section ul li>p:only-child:last-child{margin-bottom:0}.rst-content .section ol li>ol,.rst-content .section ol li>ul,.rst-content .section ul li>ol,.rst-content .section ul li>ul{margin-bottom:12px}.rst-content .section ol.simple li>*,.rst-content .section ol.simple li ol,.rst-content .section ol.simple li ul,.rst-content .section ul.simple li>*,.rst-content .section ul.simple li ol,.rst-content .section ul.simple li ul{margin-top:0;margin-bottom:0}.rst-content .line-block{margin-left:0;margin-bottom:24px;line-height:24px}.rst-content .line-block .line-block{margin-left:24px;margin-bottom:0}.rst-content .topic-title{font-weight:700;margin-bottom:12px}.rst-content .toc-backref{color:#404040}.rst-content .align-right{float:right;margin:0 0 24px 24px}.rst-content .align-left{float:left;margin:0 24px 24px 0}.rst-content .align-center{margin:auto}.rst-content .align-center:not(table){display:block}.rst-content .code-block-caption .headerlink,.rst-content .toctree-wrapper>p.caption .headerlink,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content table>caption .headerlink{visibility:hidden;font-size:14px}.rst-content .code-block-caption .headerlink:after,.rst-content .toctree-wrapper>p.caption .headerlink:after,.rst-content dl dt .headerlink:after,.rst-content h1 .headerlink:after,.rst-content h2 .headerlink:after,.rst-content h3 .headerlink:after,.rst-content h4 .headerlink:after,.rst-content h5 .headerlink:after,.rst-content h6 .headerlink:after,.rst-content p.caption .headerlink:after,.rst-content table>caption .headerlink:after{content:"\f0c1";font-family:FontAwesome}.rst-content .code-block-caption:hover .headerlink:after,.rst-content .toctree-wrapper>p.caption:hover .headerlink:after,.rst-content dl dt:hover .headerlink:after,.rst-content h1:hover .headerlink:after,.rst-content h2:hover .headerlink:after,.rst-content h3:hover .headerlink:after,.rst-content h4:hover .headerlink:after,.rst-content h5:hover .headerlink:after,.rst-content h6:hover .headerlink:after,.rst-content p.caption:hover .headerlink:after,.rst-content table>caption:hover .headerlink:after{visibility:visible}.rst-content table>caption .headerlink:after{font-size:12px}.rst-content .centered{text-align:center}.rst-content .sidebar{float:right;width:40%;display:block;margin:0 0 24px 24px;padding:24px;background:#f3f6f6;border:1px solid #e1e4e5}.rst-content .sidebar dl,.rst-content .sidebar p,.rst-content .sidebar ul{font-size:90%}.rst-content .sidebar .last,.rst-content .sidebar>:last-child{margin-bottom:0}.rst-content .sidebar .sidebar-title{display:block;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif;font-weight:700;background:#e1e4e5;padding:6px 12px;margin:-24px -24px 24px;font-size:100%}.rst-content .highlighted{background:#f1c40f;box-shadow:0 0 0 2px #f1c40f;display:inline;font-weight:700}.rst-content .citation-reference,.rst-content .footnote-reference{vertical-align:baseline;position:relative;top:-.4em;line-height:0;font-size:90%}.rst-content .hlist{width:100%}html.writer-html4 .rst-content table.docutils.citation,html.writer-html4 .rst-content table.docutils.footnote{background:none;border:none}html.writer-html4 .rst-content table.docutils.citation td,html.writer-html4 .rst-content table.docutils.citation tr,html.writer-html4 .rst-content table.docutils.footnote td,html.writer-html4 .rst-content table.docutils.footnote tr{border:none;background-color:transparent!important;white-space:normal}html.writer-html4 .rst-content table.docutils.citation td.label,html.writer-html4 .rst-content table.docutils.footnote td.label{padding-left:0;padding-right:0;vertical-align:top}html.writer-html5 .rst-content dl dt span.classifier:before{content:" : "}html.writer-html5 .rst-content dl.field-list,html.writer-html5 .rst-content dl.footnote{display:grid;grid-template-columns:max-content auto}html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dt{padding-left:1rem}html.writer-html5 .rst-content dl.field-list>dt:after,html.writer-html5 .rst-content dl.footnote>dt:after{content:":"}html.writer-html5 .rst-content dl.field-list>dd,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dd,html.writer-html5 .rst-content dl.footnote>dt{margin-bottom:0}html.writer-html5 .rst-content dl.footnote{font-size:.9rem}html.writer-html5 .rst-content dl.footnote>dt{margin:0 .5rem .5rem 0;line-height:1.2rem;word-break:break-all;font-weight:400}html.writer-html5 .rst-content dl.footnote>dt>span.brackets{margin-right:.5rem}html.writer-html5 .rst-content dl.footnote>dt>span.brackets:before{content:"["}html.writer-html5 .rst-content dl.footnote>dt>span.brackets:after{content:"]"}html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref{font-style:italic}html.writer-html5 .rst-content dl.footnote>dd{margin:0 0 .5rem;line-height:1.2rem}html.writer-html5 .rst-content dl.footnote>dd p,html.writer-html5 .rst-content dl.option-list kbd{font-size:.9rem}.rst-content table.docutils.footnote,html.writer-html4 .rst-content table.docutils.citation,html.writer-html5 .rst-content dl.footnote{color:grey}.rst-content table.docutils.footnote code,.rst-content table.docutils.footnote tt,html.writer-html4 .rst-content table.docutils.citation code,html.writer-html4 .rst-content table.docutils.citation tt,html.writer-html5 .rst-content dl.footnote code,html.writer-html5 .rst-content dl.footnote tt{color:#555}.rst-content .wy-table-responsive.citation,.rst-content .wy-table-responsive.footnote{margin-bottom:0}.rst-content .wy-table-responsive.citation+:not(.citation),.rst-content .wy-table-responsive.footnote+:not(.footnote){margin-top:24px}.rst-content .wy-table-responsive.citation:last-child,.rst-content .wy-table-responsive.footnote:last-child{margin-bottom:24px}.rst-content table.docutils th{border-color:#e1e4e5}html.writer-html5 .rst-content table.docutils th{border:1px solid #e1e4e5}html.writer-html5 .rst-content table.docutils td>p,html.writer-html5 .rst-content table.docutils th>p{line-height:1rem;margin-bottom:0;font-size:.9rem}.rst-content table.docutils td .last,.rst-content table.docutils td .last>:last-child{margin-bottom:0}.rst-content table.field-list,.rst-content table.field-list td{border:none}.rst-content table.field-list td p{font-size:inherit;line-height:inherit}.rst-content table.field-list td>strong{display:inline-block}.rst-content table.field-list .field-name{padding-right:10px;text-align:left;white-space:nowrap}.rst-content table.field-list .field-body{text-align:left}.rst-content code,.rst-content tt{color:#000;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;padding:2px 5px}.rst-content code big,.rst-content code em,.rst-content tt big,.rst-content tt em{font-size:100%!important;line-height:normal}.rst-content code.literal,.rst-content tt.literal{color:#e74c3c}.rst-content code.xref,.rst-content tt.xref,a .rst-content code,a .rst-content tt{font-weight:700;color:#404040}.rst-content kbd,.rst-content pre,.rst-content samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace}.rst-content a code,.rst-content a tt{color:#2980b9}.rst-content dl{margin-bottom:24px}.rst-content dl dt{font-weight:700;margin-bottom:12px}.rst-content dl ol,.rst-content dl p,.rst-content dl table,.rst-content dl ul{margin-bottom:12px}.rst-content dl dd{margin:0 0 12px 24px;line-height:24px}html.writer-html4 .rst-content dl:not(.docutils),html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple){margin-bottom:24px}html.writer-html4 .rst-content dl:not(.docutils)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple)>dt{display:table;margin:6px 0;font-size:90%;line-height:normal;background:#e7f2fa;color:#2980b9;border-top:3px solid #6ab0de;padding:6px;position:relative}html.writer-html4 .rst-content dl:not(.docutils)>dt:before,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple)>dt:before{color:#6ab0de}html.writer-html4 .rst-content dl:not(.docutils)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.field-list)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) dl:not(.field-list)>dt{margin-bottom:6px;border:none;border-left:3px solid #ccc;background:#f0f0f0;color:#555}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.field-list)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) dl:not(.field-list)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils)>dt:first-child,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple)>dt:first-child{margin-top:0}html.writer-html4 .rst-content dl:not(.docutils) code,html.writer-html4 .rst-content dl:not(.docutils) tt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) code,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) tt{font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) code.descclassname,html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descclassname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) code.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) tt.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) tt.descname{background-color:transparent;border:none;padding:0;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) tt.descname{font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .optional,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) .optional{display:inline-block;padding:0 4px;color:#000;font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .property,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) .property{display:inline-block;padding-right:8px}.rst-content .viewcode-back,.rst-content .viewcode-link{display:inline-block;color:#27ae60;font-size:80%;padding-left:24px}.rst-content .viewcode-back{display:block;float:right}.rst-content p.rubric{margin-bottom:12px;font-weight:700}.rst-content code.download,.rst-content tt.download{background:inherit;padding:inherit;font-weight:400;font-family:inherit;font-size:inherit;color:inherit;border:inherit;white-space:inherit}.rst-content code.download span:first-child,.rst-content tt.download span:first-child{-webkit-font-smoothing:subpixel-antialiased}.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{margin-right:4px}.rst-content .guilabel{border:1px solid #7fbbe3;background:#e7f2fa;font-size:80%;font-weight:700;border-radius:4px;padding:2.4px 6px;margin:auto 2px}.rst-content .versionmodified{font-style:italic}@media screen and (max-width:480px){.rst-content .sidebar{width:100%}}span[id*=MathJax-Span]{color:#404040}.math{text-align:center}@font-face{font-family:Lato;src:url(fonts/lato-normal.woff2?bd03a2cc277bbbc338d464e679fe9942) format("woff2"),url(fonts/lato-normal.woff?27bd77b9162d388cb8d4c4217c7c5e2a) format("woff");font-weight:400;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold.woff2?cccb897485813c7c256901dbca54ecf2) format("woff2"),url(fonts/lato-bold.woff?d878b6c29b10beca227e9eef4246111b) format("woff");font-weight:700;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold-italic.woff2?0b6bb6725576b072c5d0b02ecdd1900d) format("woff2"),url(fonts/lato-bold-italic.woff?9c7e4e9eb485b4a121c760e61bc3707c) format("woff");font-weight:700;font-style:italic;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-normal-italic.woff2?4eb103b4d12be57cb1d040ed5e162e9d) format("woff2"),url(fonts/lato-normal-italic.woff?f28f2d6482446544ef1ea1ccc6dd5892) format("woff");font-weight:400;font-style:italic;font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:400;src:url(fonts/Roboto-Slab-Regular.woff2?7abf5b8d04d26a2cafea937019bca958) format("woff2"),url(fonts/Roboto-Slab-Regular.woff?c1be9284088d487c5e3ff0a10a92e58c) format("woff");font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:700;src:url(fonts/Roboto-Slab-Bold.woff2?9984f4a9bda09be08e83f2506954adbe) format("woff2"),url(fonts/Roboto-Slab-Bold.woff?bed5564a116b05148e3b3bea6fb1162a) format("woff");font-display:block}
================================================
FILE: bdsim/bdedit/docs/_static/custom.css
================================================
/* This file intentionally left blank. */
================================================
FILE: bdsim/bdedit/docs/_static/doctools.js
================================================
/*
* doctools.js
* ~~~~~~~~~~~
*
* Sphinx JavaScript utilities for all documentation.
*
* :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
/**
* select a different prefix for underscore
*/
$u = _.noConflict();
/**
* make the code below compatible with browsers without
* an installed firebug like debugger
if (!window.console || !console.firebug) {
var names = ["log", "debug", "info", "warn", "error", "assert", "dir",
"dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace",
"profile", "profileEnd"];
window.console = {};
for (var i = 0; i < names.length; ++i)
window.console[names[i]] = function() {};
}
*/
/**
* small helper function to urldecode strings
*
* See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL
*/
jQuery.urldecode = function(x) {
if (!x) {
return x
}
return decodeURIComponent(x.replace(/\+/g, ' '));
};
/**
* small helper function to urlencode strings
*/
jQuery.urlencode = encodeURIComponent;
/**
* This function returns the parsed url parameters of the
* current request. Multiple values per key are supported,
* it will always return arrays of strings for the value parts.
*/
jQuery.getQueryParameters = function(s) {
if (typeof s === 'undefined')
s = document.location.search;
var parts = s.substr(s.indexOf('?') + 1).split('&');
var result = {};
for (var i = 0; i < parts.length; i++) {
var tmp = parts[i].split('=', 2);
var key = jQuery.urldecode(tmp[0]);
var value = jQuery.urldecode(tmp[1]);
if (key in result)
result[key].push(value);
else
result[key] = [value];
}
return result;
};
/**
* highlight a given string on a jquery object by wrapping it in
* span elements with the given class name.
*/
jQuery.fn.highlightText = function(text, className) {
function highlight(node, addItems) {
if (node.nodeType === 3) {
var val = node.nodeValue;
var pos = val.toLowerCase().indexOf(text);
if (pos >= 0 &&
!jQuery(node.parentNode).hasClass(className) &&
!jQuery(node.parentNode).hasClass("nohighlight")) {
var span;
var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg");
if (isInSVG) {
span = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
} else {
span = document.createElement("span");
span.className = className;
}
span.appendChild(document.createTextNode(val.substr(pos, text.length)));
node.parentNode.insertBefore(span, node.parentNode.insertBefore(
document.createTextNode(val.substr(pos + text.length)),
node.nextSibling));
node.nodeValue = val.substr(0, pos);
if (isInSVG) {
var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
var bbox = node.parentElement.getBBox();
rect.x.baseVal.value = bbox.x;
rect.y.baseVal.value = bbox.y;
rect.width.baseVal.value = bbox.width;
rect.height.baseVal.value = bbox.height;
rect.setAttribute('class', className);
addItems.push({
"parent": node.parentNode,
"target": rect});
}
}
}
else if (!jQuery(node).is("button, select, textarea")) {
jQuery.each(node.childNodes, function() {
highlight(this, addItems);
});
}
}
var addItems = [];
var result = this.each(function() {
highlight(this, addItems);
});
for (var i = 0; i < addItems.length; ++i) {
jQuery(addItems[i].parent).before(addItems[i].target);
}
return result;
};
/*
* backward compatibility for jQuery.browser
* This will be supported until firefox bug is fixed.
*/
if (!jQuery.browser) {
jQuery.uaMatch = function(ua) {
ua = ua.toLowerCase();
var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
/(webkit)[ \/]([\w.]+)/.exec(ua) ||
/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
/(msie) ([\w.]+)/.exec(ua) ||
ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
[];
return {
browser: match[ 1 ] || "",
version: match[ 2 ] || "0"
};
};
jQuery.browser = {};
jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true;
}
/**
* Small JavaScript module for the documentation.
*/
var Documentation = {
init : function() {
this.fixFirefoxAnchorBug();
this.highlightSearchWords();
this.initIndexTable();
if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) {
this.initOnKeyListeners();
}
},
/**
* i18n support
*/
TRANSLATIONS : {},
PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; },
LOCALE : 'unknown',
// gettext and ngettext don't access this so that the functions
// can safely bound to a different name (_ = Documentation.gettext)
gettext : function(string) {
var translated = Documentation.TRANSLATIONS[string];
if (typeof translated === 'undefined')
return string;
return (typeof translated === 'string') ? translated : translated[0];
},
ngettext : function(singular, plural, n) {
var translated = Documentation.TRANSLATIONS[singular];
if (typeof translated === 'undefined')
return (n == 1) ? singular : plural;
return translated[Documentation.PLURALEXPR(n)];
},
addTranslations : function(catalog) {
for (var key in catalog.messages)
this.TRANSLATIONS[key] = catalog.messages[key];
this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')');
this.LOCALE = catalog.locale;
},
/**
* add context elements like header anchor links
*/
addContextElements : function() {
$('div[id] > :header:first').each(function() {
$('\u00B6').
attr('href', '#' + this.id).
attr('title', _('Permalink to this headline')).
appendTo(this);
});
$('dt[id]').each(function() {
$('\u00B6').
attr('href', '#' + this.id).
attr('title', _('Permalink to this definition')).
appendTo(this);
});
},
/**
* workaround a firefox stupidity
* see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075
*/
fixFirefoxAnchorBug : function() {
if (document.location.hash && $.browser.mozilla)
window.setTimeout(function() {
document.location.href += '';
}, 10);
},
/**
* highlight the search words provided in the url in the text
*/
highlightSearchWords : function() {
var params = $.getQueryParameters();
var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : [];
if (terms.length) {
var body = $('div.body');
if (!body.length) {
body = $('body');
}
window.setTimeout(function() {
$.each(terms, function() {
body.highlightText(this.toLowerCase(), 'highlighted');
});
}, 10);
$('
')
.appendTo($('#searchbox'));
}
},
/**
* init the domain index toggle buttons
*/
initIndexTable : function() {
var togglers = $('img.toggler').click(function() {
var src = $(this).attr('src');
var idnum = $(this).attr('id').substr(7);
$('tr.cg-' + idnum).toggle();
if (src.substr(-9) === 'minus.png')
$(this).attr('src', src.substr(0, src.length-9) + 'plus.png');
else
$(this).attr('src', src.substr(0, src.length-8) + 'minus.png');
}).css('display', '');
if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) {
togglers.click();
}
},
/**
* helper function to hide the search marks again
*/
hideSearchWords : function() {
$('#searchbox .highlight-link').fadeOut(300);
$('span.highlighted').removeClass('highlighted');
},
/**
* make the url absolute
*/
makeURL : function(relativeURL) {
return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL;
},
/**
* get the current relative url
*/
getCurrentURL : function() {
var path = document.location.pathname;
var parts = path.split(/\//);
$.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() {
if (this === '..')
parts.pop();
});
var url = parts.join('/');
return path.substring(url.lastIndexOf('/') + 1, path.length - 1);
},
initOnKeyListeners: function() {
$(document).keydown(function(event) {
var activeElementType = document.activeElement.tagName;
// don't navigate when in search box, textarea, dropdown or button
if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT'
&& activeElementType !== 'BUTTON' && !event.altKey && !event.ctrlKey && !event.metaKey
&& !event.shiftKey) {
switch (event.keyCode) {
case 37: // left
var prevHref = $('link[rel="prev"]').prop('href');
if (prevHref) {
window.location.href = prevHref;
return false;
}
case 39: // right
var nextHref = $('link[rel="next"]').prop('href');
if (nextHref) {
window.location.href = nextHref;
return false;
}
}
}
});
}
};
// quick alias for translations
_ = Documentation.gettext;
$(document).ready(function() {
Documentation.init();
});
================================================
FILE: bdsim/bdedit/docs/_static/documentation_options.js
================================================
var DOCUMENTATION_OPTIONS = {
URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
VERSION: '',
LANGUAGE: 'None',
COLLAPSE_INDEX: false,
BUILDER: 'html',
FILE_SUFFIX: '.html',
LINK_SUFFIX: '.html',
HAS_SOURCE: true,
SOURCELINK_SUFFIX: '.txt',
NAVIGATION_WITH_KEYS: false
};
================================================
FILE: bdsim/bdedit/docs/_static/jquery-3.5.1.js
================================================
/*!
* jQuery JavaScript Library v3.5.1
* https://jquery.com/
*
* Includes Sizzle.js
* https://sizzlejs.com/
*
* Copyright JS Foundation and other contributors
* Released under the MIT license
* https://jquery.org/license
*
* Date: 2020-05-04T22:49Z
*/
( function( global, factory ) {
"use strict";
if ( typeof module === "object" && typeof module.exports === "object" ) {
// For CommonJS and CommonJS-like environments where a proper `window`
// is present, execute the factory and get jQuery.
// For environments that do not have a `window` with a `document`
// (such as Node.js), expose a factory as module.exports.
// This accentuates the need for the creation of a real `window`.
// e.g. var jQuery = require("jquery")(window);
// See ticket #14549 for more info.
module.exports = global.document ?
factory( global, true ) :
function( w ) {
if ( !w.document ) {
throw new Error( "jQuery requires a window with a document" );
}
return factory( w );
};
} else {
factory( global );
}
// Pass this if window is not defined yet
} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1
// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode
// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common
// enough that all such attempts are guarded in a try block.
"use strict";
var arr = [];
var getProto = Object.getPrototypeOf;
var slice = arr.slice;
var flat = arr.flat ? function( array ) {
return arr.flat.call( array );
} : function( array ) {
return arr.concat.apply( [], array );
};
var push = arr.push;
var indexOf = arr.indexOf;
var class2type = {};
var toString = class2type.toString;
var hasOwn = class2type.hasOwnProperty;
var fnToString = hasOwn.toString;
var ObjectFunctionString = fnToString.call( Object );
var support = {};
var isFunction = function isFunction( obj ) {
// Support: Chrome <=57, Firefox <=52
// In some browsers, typeof returns "function" for HTML