diff --git a/.github/workflows/python-wasm.yml b/.github/workflows/python-wasm.yml index 232d89364..39d64e35f 100644 --- a/.github/workflows/python-wasm.yml +++ b/.github/workflows/python-wasm.yml @@ -25,7 +25,7 @@ jobs: matrix: os: [ubuntu-22.04, windows-2022, macos-14] python-minor-version: [11, 12] - package: [compress-stringify, compare-images, dicom, mesh-io, image-io, downsample] + package: [compress-stringify, compare-images, dicom, mesh-io, image-io, transform-io, downsample] steps: - name: Checkout diff --git a/packages/core/python/itkwasm/itkwasm/__init__.py b/packages/core/python/itkwasm/itkwasm/__init__.py index 52ca8e475..caf4eb3d3 100644 --- a/packages/core/python/itkwasm/itkwasm/__init__.py +++ b/packages/core/python/itkwasm/itkwasm/__init__.py @@ -1,6 +1,6 @@ """itkwasm: Python interface to itk-wasm WebAssembly modules.""" -__version__ = "1.0b180" +__version__ = "1.0b185" from .interface_types import InterfaceTypes from .image import Image, ImageType, ImageRegion diff --git a/packages/core/python/itkwasm/itkwasm/interface_types.py b/packages/core/python/itkwasm/itkwasm/interface_types.py index 6c52b69b2..7346af5a0 100644 --- a/packages/core/python/itkwasm/itkwasm/interface_types.py +++ b/packages/core/python/itkwasm/itkwasm/interface_types.py @@ -9,5 +9,5 @@ class InterfaceTypes(str, Enum): Mesh = "Mesh" PointSet = "PointSet" PolyData = "PolyData" - Transform = "Transform" + TransformList = "TransformList" JsonCompatible = "JsonCompatible" diff --git a/packages/core/python/itkwasm/itkwasm/pipeline.py b/packages/core/python/itkwasm/itkwasm/pipeline.py index 36b5d0c45..3018aef21 100644 --- a/packages/core/python/itkwasm/itkwasm/pipeline.py +++ b/packages/core/python/itkwasm/itkwasm/pipeline.py @@ -22,6 +22,7 @@ from .binary_file import BinaryFile from .image import Image from .mesh import Mesh +from .transform import Transform from .point_set import PointSet from .polydata import PolyData from .json_compatible import JsonCompatible @@ -45,6 +46,8 @@ WasiConfig, Linker, WasmtimeError, + DirPerms, + FilePerms ) # Get the value of the ITKWASM_CACHE_DIR environment variable @@ -83,7 +86,7 @@ def __init__( wasi_config.argv = args for preopen in preopen_directories: - wasi_config.preopen_dir(preopen, preopen) + wasi_config.preopen_dir(preopen, preopen, DirPerms.READ_WRITE, FilePerms.READ_WRITE) store.set_wasi(wasi_config) @@ -299,6 +302,34 @@ def run( "pointData": f"data:application/vnd.itk.address,0:{point_data_ptr}", } ri.set_input_json(point_set_json, index) + elif input_.type == InterfaceTypes.TransformList: + transform_list = input_.data + transform_list_json = [] + for idx, transform in enumerate(transform_list): + if transform.numberOfFixedParameters: + fpv = array_like_to_bytes(transform.fixedParameters) + else: + fpv = bytes([]) + fixed_parameters_ptr = ri.set_input_array(fpv, index, idx * 2) + fixed_parameters = f"data:application/vnd.itk.address,0:{fixed_parameters_ptr}" + if transform.numberOfParameters: + pv = array_like_to_bytes(transform.parameters) + else: + pv = bytes([]) + parameters_ptr = ri.set_input_array(pv, index, idx * 2 + 1) + parameters = f"data:application/vnd.itk.address,0:{parameters_ptr}" + transform_json = { + "transformType": asdict(transform.transformType), + "numberOfFixedParameters": transform.numberOfFixedParameters, + "numberOfParameters": transform.numberOfParameters, + "name": transform.name, + "inputSpaceName": transform.inputSpaceName, + "outputSpaceName": transform.outputSpaceName, + "fixedParameters": fixed_parameters, + "parameters": parameters, + } + transform_list_json.append(transform_json) + ri.set_input_json(transform_list_json, index) elif input_.type == InterfaceTypes.PolyData: polydata = input_.data if polydata.numberOfPoints: @@ -489,6 +520,27 @@ def run( point_set.pointData = buffer_to_numpy_array(point_set.pointSetType.pointPixelComponentType, bytes([])) output_data = PipelineOutput(InterfaceTypes.PointSet, point_set) + elif output.type == InterfaceTypes.TransformList: + transform_list_json = ri.get_output_json(index) + transform_list = [] + for idx, transform_json in enumerate(transform_list_json): + transform = Transform(**transform_json) + if transform.numberOfFixedParameters > 0: + data_ptr = ri.get_output_array_address(0, index, idx * 2) + data_size = ri.get_output_array_size(0, index, idx * 2) + transform.fixedParameters = buffer_to_numpy_array( + transform.transformType.parametersValueType, + ri.wasmtime_lift(data_ptr, data_size), + ) + if transform.numberOfParameters > 0: + data_ptr = ri.get_output_array_address(0, index, idx * 2 + 1) + data_size = ri.get_output_array_size(0, index, idx * 2 + 1) + transform.parameters = buffer_to_numpy_array( + transform.transformType.parametersValueType, + ri.wasmtime_lift(data_ptr, data_size), + ) + transform_list.append(transform) + output_data = PipelineOutput(InterfaceTypes.TransformList, transform_list) elif output.type == InterfaceTypes.PolyData: polydata_json = ri.get_output_json(index) polydata = PolyData(**polydata_json) diff --git a/packages/core/python/itkwasm/itkwasm/pyodide.py b/packages/core/python/itkwasm/itkwasm/pyodide.py index 9ae88bed4..0df0b04c9 100644 --- a/packages/core/python/itkwasm/itkwasm/pyodide.py +++ b/packages/core/python/itkwasm/itkwasm/pyodide.py @@ -5,6 +5,7 @@ from .point_set import PointSet, PointSetType from .mesh import Mesh, MeshType from .polydata import PolyData, PolyDataType +from .transform import Transform, TransformType from .binary_file import BinaryFile from .binary_stream import BinaryStream from .text_file import TextFile @@ -147,6 +148,20 @@ def to_py(js_proxy): if polydata_dict["cellData"] is not None: polydata_dict["cellData"] = buffer_to_numpy_array(cell_pixel_component_type, polydata_dict["cellData"]) return PolyData(**polydata_dict) + elif hasattr(js_proxy, "transformType"): + transform_dict = js_proxy.to_py() + transform_type = TransformType(**transform_dict["transformType"]) + transform_dict["transformType"] = transform_type + parameters_value_type = transform_type.parametersValueType + if transform_dict["fixedParameters"] is not None: + transform_dict["fixedParameters"] = buffer_to_numpy_array( + parameters_value_type, transform_dict["fixedParameters"] + ) + if transform_dict["parameters"] is not None: + transform_dict["parameters"] = buffer_to_numpy_array( + parameters_value_type, transform_dict["parameters"] + ) + return Transform(**transform_dict) elif hasattr(js_proxy, "path") and hasattr(js_proxy, "data") and isinstance(js_proxy.data, str): with open(js_proxy.path, "w") as fp: fp.write(js_proxy.data) @@ -222,6 +237,13 @@ def to_js(py, **kwargs): if polydata_dict["cellData"] is not None: polydata_dict["cellData"] = polydata_dict["cellData"].ravel() return pyodide.ffi.to_js(polydata_dict, dict_converter=js.Object.fromEntries) + elif isinstance(py, Transform): + transform_dict = asdict(py) + if transform_dict["fixedParameters"] is not None: + transform_dict["fixedParameters"] = transform_dict["fixedParameters"].ravel() + if transform_dict["parameters"] is not None: + transform_dict["parameters"] = transform_dict["parameters"].ravel() + return pyodide.ffi.to_js(transform_dict, dict_converter=js.Object.fromEntries) elif isinstance(py, TextStream): text_stream_dict = asdict(py) return pyodide.ffi.to_js(text_stream_dict, dict_converter=js.Object.fromEntries) diff --git a/packages/core/python/itkwasm/itkwasm/transform.py b/packages/core/python/itkwasm/itkwasm/transform.py index 62b7ea645..41ad18a87 100644 --- a/packages/core/python/itkwasm/itkwasm/transform.py +++ b/packages/core/python/itkwasm/itkwasm/transform.py @@ -8,6 +8,8 @@ from numpy import ndarray as ArrayLike import numpy as np +from .float_types import FloatTypes + class TransformParameterizations(str, Enum): Composite = "Composite" Identity = "Identity" @@ -40,9 +42,10 @@ class TransformParameterizations(str, Enum): @dataclass class TransformType: + transformParameterization: TransformParameterizations = TransformParameterizations.Identity + parametersValueType: FloatTypes = FloatTypes.Float64 inputDimension: int = 3 outputDimension: int = 3 - transformParameterization: TransformParameterizations = TransformParameterizations.Identity @dataclass class Transform: diff --git a/packages/core/python/itkwasm/pixi.lock b/packages/core/python/itkwasm/pixi.lock index ddf883db9..f93694185 100644 --- a/packages/core/python/itkwasm/pixi.lock +++ b/packages/core/python/itkwasm/pixi.lock @@ -125,7 +125,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/3c/83/ec3196c360afffbc5b342ead48d1eb7393dd74fa70bca75d33905a86f211/trio-0.27.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/48/be/a9ae5f50cad5b6f85bd2574c2c923730098530096e170c1ce7452394d7aa/trio_websocket-0.11.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ce/d9/5f4c13cecde62396b0d3fe530a50ccea91e7dfc1ccf0e09c228841bb5ba8/urllib3-2.2.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/5c/ba/f551b829378d65d0e0494fdb492942a0ed2dc7f40681b2438a47d1f4af86/wasmtime-25.0.0-py3-none-manylinux1_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/5e/24/806c5bd1b5e30c83cc9d182795edebfbfe24483f82fb18823b309a6656b5/wasmtime-27.0.1-py3-none-manylinux1_x86_64.whl - pypi: https://files.pythonhosted.org/packages/5a/84/44687a29792a70e111c5c477230a72c4b957d88d16141199bf9acb7537a3/websocket_client-1.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/78/58/e860788190eba3bcce367f74d29c4675466ce8dddfba85f7827588416f01/wsproto-1.2.0-py3-none-any.whl - pypi: . @@ -248,7 +248,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/3c/83/ec3196c360afffbc5b342ead48d1eb7393dd74fa70bca75d33905a86f211/trio-0.27.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/48/be/a9ae5f50cad5b6f85bd2574c2c923730098530096e170c1ce7452394d7aa/trio_websocket-0.11.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ce/d9/5f4c13cecde62396b0d3fe530a50ccea91e7dfc1ccf0e09c228841bb5ba8/urllib3-2.2.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b7/36/5e83b5f7858fe1003cbb89d0d5716f628b9a00fafc3762665f06ca4ef75d/wasmtime-25.0.0-py3-none-manylinux2014_aarch64.whl + - pypi: https://files.pythonhosted.org/packages/3a/57/cd877b4797be239b4433f89a5a85c7bf2c5319dd91c7777b1867bebb664e/wasmtime-27.0.1-py3-none-manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/5a/84/44687a29792a70e111c5c477230a72c4b957d88d16141199bf9acb7537a3/websocket_client-1.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/78/58/e860788190eba3bcce367f74d29c4675466ce8dddfba85f7827588416f01/wsproto-1.2.0-py3-none-any.whl - pypi: . @@ -356,7 +356,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/3c/83/ec3196c360afffbc5b342ead48d1eb7393dd74fa70bca75d33905a86f211/trio-0.27.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/48/be/a9ae5f50cad5b6f85bd2574c2c923730098530096e170c1ce7452394d7aa/trio_websocket-0.11.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ce/d9/5f4c13cecde62396b0d3fe530a50ccea91e7dfc1ccf0e09c228841bb5ba8/urllib3-2.2.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/cc/f0/d415d6b31ba69cfca04b2d5e83fbb5fc05335323712fd91948a1a53d13be/wasmtime-25.0.0-py3-none-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/6e/d8/38d1af31c1787e09642354c81215920a5bf59722a6786ed7e9622fd1f033/wasmtime-27.0.1-py3-none-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/5a/84/44687a29792a70e111c5c477230a72c4b957d88d16141199bf9acb7537a3/websocket_client-1.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/78/58/e860788190eba3bcce367f74d29c4675466ce8dddfba85f7827588416f01/wsproto-1.2.0-py3-none-any.whl - pypi: . @@ -466,7 +466,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/3c/83/ec3196c360afffbc5b342ead48d1eb7393dd74fa70bca75d33905a86f211/trio-0.27.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/48/be/a9ae5f50cad5b6f85bd2574c2c923730098530096e170c1ce7452394d7aa/trio_websocket-0.11.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ce/d9/5f4c13cecde62396b0d3fe530a50ccea91e7dfc1ccf0e09c228841bb5ba8/urllib3-2.2.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/1b/21/c0f3e031efe5f009215975eb7dbea86b55a69c4f02420965d1f45f43865e/wasmtime-25.0.0-py3-none-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/14/6f/f6b99d9ab1511398686e00d2a26371d99a7949531514379d731b3b7e6309/wasmtime-27.0.1-py3-none-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/5a/84/44687a29792a70e111c5c477230a72c4b957d88d16141199bf9acb7537a3/websocket_client-1.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/78/58/e860788190eba3bcce367f74d29c4675466ce8dddfba85f7827588416f01/wsproto-1.2.0-py3-none-any.whl - pypi: . @@ -968,7 +968,7 @@ packages: - lz4>=4.3.2 ; extra == 'complete' - dask[array] ; extra == 'dataframe' - pandas>=2.0 ; extra == 'dataframe' - - dask-expr<1.2,>=1.1 ; extra == 'dataframe' + - dask-expr>=1.1,<1.2 ; extra == 'dataframe' - bokeh>=3.1.0 ; extra == 'diagnostics' - jinja2>=2.10.3 ; extra == 'diagnostics' - distributed==2024.11.2 ; extra == 'distributed' @@ -1178,10 +1178,10 @@ packages: - pytest-recording ; extra == 'test' - pytest-rerunfailures ; extra == 'test' - requests ; extra == 'test' - - aiobotocore<3.0.0,>=2.5.4 ; extra == 'test-downstream' + - aiobotocore>=2.5.4,<3.0.0 ; extra == 'test-downstream' - dask-expr ; extra == 'test-downstream' - dask[dataframe,test] ; extra == 'test-downstream' - - moto[server]<5,>4 ; extra == 'test-downstream' + - moto[server]>4,<5 ; extra == 'test-downstream' - pytest-timeout ; extra == 'test-downstream' - xarray ; extra == 'test-downstream' - adlfs ; extra == 'test-full' @@ -1466,7 +1466,7 @@ packages: sha256: 77ff76a995ef40999b96e70abb6ab839d077df2f6127230f36bf9ed24c67473b requires_dist: - attrs>=22.2.0 - - sortedcontainers<3.0.0,>=2.1.0 + - sortedcontainers>=2.1.0,<3.0.0 - exceptiongroup>=1.0.0 ; python_full_version < '3.11' - black>=19.10b0 ; extra == 'all' - click>=7.0 ; extra == 'all' @@ -1824,16 +1824,15 @@ packages: requires_python: '>=3.8' - kind: pypi name: itkwasm - version: 1.0b180 + version: 1.0b183 path: . - sha256: 9d34d23674f0f764ee29b9f6365bf02c13ff249a1a5973ed0253ea3c84814a2a + sha256: f3a2be453630d9e7826f816563f455d922f50f6965deb35e0716814db9270165 requires_dist: - - dask[array]<2025,>=2024.11.2 - importlib-metadata ; python_full_version < '3.10' - numpy - platformdirs ; sys_platform != 'emscripten' - typing-extensions - - wasmtime>=13.0.2 ; sys_platform != 'emscripten' + - wasmtime>=27.0.1 ; sys_platform != 'emscripten' requires_python: '>=3.9' editable: true - kind: conda @@ -3147,7 +3146,7 @@ packages: url: https://files.pythonhosted.org/packages/96/31/6607dab48616902f76885dfcf62c08d929796fc3b2d2318faf9fd54dbed9/pytest_asyncio-0.24.0-py3-none-any.whl sha256: a811296ed596b69bf0b6f3dc40f83bcaf341b155a269052d82efa2b25ac7037b requires_dist: - - pytest<9,>=8.2 + - pytest>=8.2,<9 - sphinx>=5.3 ; extra == 'docs' - sphinx-rtd-theme>=1.0 ; extra == 'docs' - coverage>=6.2 ; extra == 'testing' @@ -3790,8 +3789,8 @@ packages: requires_dist: - brotli>=1.0.9 ; platform_python_implementation == 'CPython' and extra == 'brotli' - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'brotli' - - h2<5,>=4 ; extra == 'h2' - - pysocks!=1.5.7,<2.0,>=1.5.6 ; extra == 'socks' + - h2>=4,<5 ; extra == 'h2' + - pysocks>=1.5.6,!=1.5.7,<2.0 ; extra == 'socks' - zstandard>=0.18.0 ; extra == 'zstd' requires_python: '>=3.8' - kind: conda @@ -3954,9 +3953,9 @@ packages: timestamp: 1728400827536 - kind: pypi name: wasmtime - version: 25.0.0 - url: https://files.pythonhosted.org/packages/1b/21/c0f3e031efe5f009215975eb7dbea86b55a69c4f02420965d1f45f43865e/wasmtime-25.0.0-py3-none-win_amd64.whl - sha256: f8a2a213b9179965db2d2eedececd69a37e287e902330509afae51c71a3a6842 + version: 27.0.1 + url: https://files.pythonhosted.org/packages/14/6f/f6b99d9ab1511398686e00d2a26371d99a7949531514379d731b3b7e6309/wasmtime-27.0.1-py3-none-win_amd64.whl + sha256: e691aafe8881a872a69a52822f24c209f54fe6f06154d1dfadd977ee86374169 requires_dist: - importlib-resources>=5.10 - coverage ; extra == 'testing' @@ -3964,12 +3963,12 @@ packages: - pycparser ; extra == 'testing' - pytest-mypy ; extra == 'testing' - componentize-py ; extra == 'testing' - requires_python: '>=3.8' + requires_python: '>=3.9' - kind: pypi name: wasmtime - version: 25.0.0 - url: https://files.pythonhosted.org/packages/5c/ba/f551b829378d65d0e0494fdb492942a0ed2dc7f40681b2438a47d1f4af86/wasmtime-25.0.0-py3-none-manylinux1_x86_64.whl - sha256: b4364e14d44e3b7afe6a40bf608e9d0d2c40b09dece441d20f4f6e31906b729c + version: 27.0.1 + url: https://files.pythonhosted.org/packages/3a/57/cd877b4797be239b4433f89a5a85c7bf2c5319dd91c7777b1867bebb664e/wasmtime-27.0.1-py3-none-manylinux2014_aarch64.whl + sha256: dac4e2232cc44b6bfc290f84ff9244621b7e99ee1da4036afb83113dd93b13bf requires_dist: - importlib-resources>=5.10 - coverage ; extra == 'testing' @@ -3977,12 +3976,12 @@ packages: - pycparser ; extra == 'testing' - pytest-mypy ; extra == 'testing' - componentize-py ; extra == 'testing' - requires_python: '>=3.8' + requires_python: '>=3.9' - kind: pypi name: wasmtime - version: 25.0.0 - url: https://files.pythonhosted.org/packages/b7/36/5e83b5f7858fe1003cbb89d0d5716f628b9a00fafc3762665f06ca4ef75d/wasmtime-25.0.0-py3-none-manylinux2014_aarch64.whl - sha256: a07445073cf36a6e5d1dc28246a897dcbdaa537ba8be8805be65422ecca297eb + version: 27.0.1 + url: https://files.pythonhosted.org/packages/5e/24/806c5bd1b5e30c83cc9d182795edebfbfe24483f82fb18823b309a6656b5/wasmtime-27.0.1-py3-none-manylinux1_x86_64.whl + sha256: 99339ed56b7bc4d280bcb0d5527725a7cfe51c269941cf888f57b46f05c249a6 requires_dist: - importlib-resources>=5.10 - coverage ; extra == 'testing' @@ -3990,12 +3989,12 @@ packages: - pycparser ; extra == 'testing' - pytest-mypy ; extra == 'testing' - componentize-py ; extra == 'testing' - requires_python: '>=3.8' + requires_python: '>=3.9' - kind: pypi name: wasmtime - version: 25.0.0 - url: https://files.pythonhosted.org/packages/cc/f0/d415d6b31ba69cfca04b2d5e83fbb5fc05335323712fd91948a1a53d13be/wasmtime-25.0.0-py3-none-macosx_11_0_arm64.whl - sha256: 5bdf1214ee3ee78a4a8a92da339f4c4c8c109e65af881b37f4adfc05d02af426 + version: 27.0.1 + url: https://files.pythonhosted.org/packages/6e/d8/38d1af31c1787e09642354c81215920a5bf59722a6786ed7e9622fd1f033/wasmtime-27.0.1-py3-none-macosx_11_0_arm64.whl + sha256: 1082442529d06c5c50fb9377dbb599460c175f98ca0d332625bf76661c7309b4 requires_dist: - importlib-resources>=5.10 - coverage ; extra == 'testing' @@ -4003,7 +4002,7 @@ packages: - pycparser ; extra == 'testing' - pytest-mypy ; extra == 'testing' - componentize-py ; extra == 'testing' - requires_python: '>=3.8' + requires_python: '>=3.9' - kind: pypi name: websocket-client version: 1.8.0 @@ -4023,7 +4022,7 @@ packages: url: https://files.pythonhosted.org/packages/78/58/e860788190eba3bcce367f74d29c4675466ce8dddfba85f7827588416f01/wsproto-1.2.0-py3-none-any.whl sha256: b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736 requires_dist: - - h11<1,>=0.9.0 + - h11>=0.9.0,<1 requires_python: '>=3.7.0' - kind: conda name: xz diff --git a/packages/core/python/itkwasm/pyproject.toml b/packages/core/python/itkwasm/pyproject.toml index 9adf2c4e6..d35a961b4 100644 --- a/packages/core/python/itkwasm/pyproject.toml +++ b/packages/core/python/itkwasm/pyproject.toml @@ -33,8 +33,8 @@ dependencies = [ "numpy", "typing_extensions", "platformdirs; sys_platform != \"emscripten\"", - "wasmtime >= 13.0.2; sys_platform != \"emscripten\"", - "importlib_metadata; python_version < \"3.10\"", "dask[array]>=2024.11.2,<2025", + "wasmtime >= 27.0.1; sys_platform != \"emscripten\"", + "importlib_metadata; python_version < \"3.10\"", ] [project.urls] @@ -64,6 +64,7 @@ pyodide-py = ">=0.26.3, <0.27" pytest-pyodide = ">=0.58.3, <0.59" itk = ">=5.4.0" test_accelerator = { path = "test/test-accelerator", editable = true } +dask = { extras = ["array"], version = ">=2024.11.2,<2025" } [tool.pixi.tasks.build] cmd = "hatch build" diff --git a/packages/core/python/itkwasm/test/input/LinearTransform.h5 b/packages/core/python/itkwasm/test/input/LinearTransform.h5 new file mode 100644 index 000000000..aa1d99f26 Binary files /dev/null and b/packages/core/python/itkwasm/test/input/LinearTransform.h5 differ diff --git a/packages/core/python/itkwasm/test/input/transform-read-write-test.wasi.wasm b/packages/core/python/itkwasm/test/input/transform-read-write-test.wasi.wasm new file mode 100755 index 000000000..2e5d2d4fd Binary files /dev/null and b/packages/core/python/itkwasm/test/input/transform-read-write-test.wasi.wasm differ diff --git a/packages/core/python/itkwasm/test/test_pipeline.py b/packages/core/python/itkwasm/test/test_pipeline.py index ace299c01..e92867ce7 100644 --- a/packages/core/python/itkwasm/test/test_pipeline.py +++ b/packages/core/python/itkwasm/test/test_pipeline.py @@ -19,6 +19,10 @@ BinaryFile, Image, Mesh, + Transform, + TransformList, + TransformParameterizations, + FloatTypes, ) test_input_dir = Path(__file__).resolve().parent / "input" @@ -297,3 +301,41 @@ def test_pipeline_write_read_polydata(): assert out_mesh.GetNumberOfPoints() == 2903 assert out_mesh.GetNumberOfCells() == 3263 + +def test_pipeline_write_read_transform(): + pipeline = Pipeline(test_input_dir / "transform-read-write-test.wasi.wasm") + + data = test_input_dir / "LinearTransform.h5" + itk_transform = itk.transformread(data) + itk_transform_list = itk.dict_from_transform(itk_transform) + itkwasm_transform_list = [Transform(**t) for t in itk_transform_list] + + pipeline_inputs = [ + PipelineInput(InterfaceTypes.TransformList, itkwasm_transform_list), + ] + + pipeline_outputs = [ + PipelineOutput(InterfaceTypes.TransformList), + ] + + args = [ + "--memory-io", + "0", + "0", + ] + + outputs = pipeline.run(args, pipeline_outputs, pipeline_inputs) + transform_list = outputs[0].data + + assert len(transform_list) == 1 + transform = transform_list[0] + assert transform.transformType.transformParameterization == TransformParameterizations.Affine + assert transform.transformType.parametersValueType == FloatTypes.Float64 + assert transform.numberOfParameters == 12 + assert transform.numberOfFixedParameters == 3 + np.testing.assert_allclose(transform.fixedParameters, np.array([0.0, 0.0, 0.0])) + np.testing.assert_allclose(transform.parameters, np.array([ + 0.65631490118447, 0.5806583745824385, -0.4817536741017158, + -0.7407986817430222, 0.37486398378429736, -0.5573995934598175, + -0.14306664045479867, 0.7227121458012518, 0.676179776908723, + -65.99999999999997, 69.00000000000004, 32.000000000000036])) \ No newline at end of file diff --git a/packages/core/python/itkwasm/test/test_pyodide.py b/packages/core/python/itkwasm/test/test_pyodide.py index 017748321..e1e851fe5 100644 --- a/packages/core/python/itkwasm/test/test_pyodide.py +++ b/packages/core/python/itkwasm/test/test_pyodide.py @@ -198,6 +198,41 @@ async def test_polydata_conversion(selenium, package_wheel): assert polydata.numberOfPointPixels == polydata_py.numberOfPointPixels assert np.array_equal(polydata.pointData, polydata_py.pointData) +@run_in_pyodide(packages=["micropip", "numpy"]) +async def test_transform_conversion(selenium, package_wheel): + import micropip + + await micropip.install(package_wheel) + + from itkwasm import Transform, TransformType, TransformParameterizations + from itkwasm.pyodide import to_js, to_py + import numpy as np + + dimension = 3 + transform_type = TransformType(TransformParameterizations.Affine) + fixed_parameters = np.array([0.0, 0.0, 0.0]).astype(np.float64) + parameters = np.array([ + 0.65631490118447, 0.5806583745824385, -0.4817536741017158, + -0.7407986817430222, 0.37486398378429736, -0.5573995934598175, + -0.14306664045479867, 0.7227121458012518, 0.676179776908723, + -65.99999999999997, 69.00000000000004, 32.000000000000036]).astype(np.float64) + transform = Transform(transform_type, dimension, 12, fixedParameters=fixed_parameters, parameters=parameters) + transform_list = [transform,] + + transform_list_js = to_js(transform_list) + transform_list_py = to_py(transform_list_js) + + transform_py = transform_list_py[0] + assert transform_py.transformType.transformParameterization == TransformParameterizations.Affine + assert transform_py.numberOfParameters == 12 + assert transform_py.numberOfFixedParameters == 3 + np.testing.assert_allclose(transform_py.fixedParameters, np.array([0.0, 0.0, 0.0])) + np.testing.assert_allclose(transform_py.parameters, np.array([ + 0.65631490118447, 0.5806583745824385, -0.4817536741017158, + -0.7407986817430222, 0.37486398378429736, -0.5573995934598175, + -0.14306664045479867, 0.7227121458012518, 0.676179776908723, + -65.99999999999997, 69.00000000000004, 32.000000000000036])) + print('transform_py', transform_py) @run_in_pyodide(packages=["micropip", "numpy"]) async def test_binary_stream_conversion(selenium, package_wheel): diff --git a/packages/core/typescript/itk-wasm/src/bindgen/python/resources/template.pyproject.toml b/packages/core/typescript/itk-wasm/src/bindgen/python/resources/template.pyproject.toml index 99336c99b..674c57547 100644 --- a/packages/core/typescript/itk-wasm/src/bindgen/python/resources/template.pyproject.toml +++ b/packages/core/typescript/itk-wasm/src/bindgen/python/resources/template.pyproject.toml @@ -19,11 +19,11 @@ classifiers = [ "Intended Audience :: Developers", "Intended Audience :: Science/Research", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", ] keywords = [ "itkwasm", @@ -32,7 +32,7 @@ keywords = [ requires-python = ">=3.8" dependencies = [ - "itkwasm >= 1.0.b171",@bindgenDependencies@ + "itkwasm >= 1.0.b184",@bindgenDependencies@ ] [tool.hatch.version] diff --git a/packages/image-io/pixi.toml b/packages/image-io/pixi.toml index e40eed57c..beb414424 100644 --- a/packages/image-io/pixi.toml +++ b/packages/image-io/pixi.toml @@ -85,6 +85,7 @@ pyodide-py = ">=0.26.3, <0.27" pytest-pyodide = ">=0.58.3, <0.59" itk-webassemblyinterface = ">=1.0b175, <2" itkwasm = ">=1.0b179, <2" +itkwasm-image-io-wasi = { path = "python/itkwasm-image-io-wasi", editable = true } [feature.python.tasks.test-wasi] cmd = "pytest" diff --git a/packages/mesh-io/pixi.toml b/packages/mesh-io/pixi.toml index 21d11abaa..77b297e2a 100644 --- a/packages/mesh-io/pixi.toml +++ b/packages/mesh-io/pixi.toml @@ -85,6 +85,7 @@ pyodide-py = ">=0.26.3, <0.27" pytest-pyodide = ">=0.58.3, <0.59" itk-webassemblyinterface = ">=1.0b175, <2" itkwasm = ">=1.0b179, <2" +itkwasm-mesh-io-wasi = { path = "python/itkwasm-mesh-io-wasi", editable = true } [feature.python.tasks.test-wasi] cmd = "pytest" diff --git a/packages/transform-io/.gitignore b/packages/transform-io/.gitignore index 201ef91f3..ad23cb0ad 100644 --- a/packages/transform-io/.gitignore +++ b/packages/transform-io/.gitignore @@ -4,3 +4,6 @@ wasi-build/ typescript/dist typescript/src/version.ts pyodide/ +python/itkwasm-transform-io-emscripten/dist/ +python/itkwasm-transform-io-wasi/dist/ +python/itkwasm-transform-io/dist/ diff --git a/packages/transform-io/pixi.lock b/packages/transform-io/pixi.lock index 5ef57aa47..3c49798b0 100644 --- a/packages/transform-io/pixi.lock +++ b/packages/transform-io/pixi.lock @@ -472,9 +472,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.23.0-py312hef9b889_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.6-ha6fb4c9_0.conda - pypi: https://files.pythonhosted.org/packages/6a/21/5b6702a7f963e95456c0de2d495f67bf5fd62840ac655dc451586d23d39a/attrs-24.2.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/48/41/e1d85ca3cab0b674e277c8c4f678cf66a91cd2cecf93df94353a606fe0db/cloudpickle-3.1.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/2a/72/33ff765a07913cb5061baa94718f3a17003aa29adc89642a68c295d47582/dask-2024.11.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c6/b2/454d6e7f0158951d8a78c2e1eb4f69ae81beb8dca5fee9809c6c99e9d0d0/fsspec-2024.10.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f1/66/033e58a50fd9ec9df00a8671c74f1f3a320564c6415a4ed82a1c651654ba/greenlet-3.1.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/13/0e/3f934459c4aab461281ad24b01de08bd612118fbc70ecc7b0fa5ed156a94/hypothesis-6.115.6-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/7e/14/577a2a26c81ab6e2db821d7a5da3c6ff8dbf27ab3d8ebe74a3d4f203ab38/itk-5.4.0-cp311-abi3-manylinux_2_28_x86_64.whl @@ -486,28 +483,25 @@ environments: - pypi: https://files.pythonhosted.org/packages/dc/58/ec1bf790ed9657fd8a651189d40eedd765bf1cd75355ffa3f8f9bd67f4df/itk_registration-5.4.0-cp311-abi3-manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/1a/e5/94a596fba3dbecdea33059b455294fbfea91fcfc0d6cfd92372e10a6da93/itk_segmentation-5.4.0-cp311-abi3-manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/a6/3c/ac3bad4ff24fe2b07064be5e44db8f4ed32a4e3708dff084e3b58c5b608c/itk_webassemblyinterface-1.0b175-cp311-abi3-manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/bd/a5/329525eeaf0ac895a37b0a498b311e6d2991d47c827804908a815ae088f3/itkwasm-1.0b180-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bc/f3/db24f14dfed1f631e4568440542dce7330b1c17a5c098666164872db4404/itkwasm-1.0b185-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9b/b4/e3c7e6fab0f77fff6194afa173d1f2342073d91b1d3b4b30b17c3fb4407a/numpy-2.1.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/55/8b/5ab7257531a5d830fc8000c476e63c935488d74609b50f9384a643ec0a62/outcome-1.3.0.post0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f9/0c/8cde1a86a9a7449a0ba95197f42156198083be1749b717831fba16ab2b5f/playwright-1.48.0-py3-none-manylinux1_x86_64.whl - pypi: https://files.pythonhosted.org/packages/1d/0d/95993c08c721ec68892547f2117e8f9dfbcef2ca71e098533541b4a54d5f/pyee-12.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/6f/ec/70457045923b005761b19f78b85b467a64808e886c10c449f7758a1ba5f7/pyodide_py-0.26.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2e/4a/970d2604a72e9d44904533b5438135187aa3b08b8d6fc75e5404cd8a1dd1/pyodide_py-0.26.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8d/59/b4572118e098ac8e46e399a1dd0f2d85403ce8bbaad9ec79373ed6badaf9/PySocks-1.7.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/96/31/6607dab48616902f76885dfcf62c08d929796fc3b2d2318faf9fd54dbed9/pytest_asyncio-0.24.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/cd/98/7a2d160bd1a997c6fc422647ccf907fcc1b14b8e4a89790fa1427b8f4d16/pytest_pyodide-0.58.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/aa/85/fa44f23dd5d5066a72f7c4304cce4b5ff9a6e7fd92431a48b2c63fbf63ec/selenium-4.25.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9b/87/ce70db7cae60e67851eb94e1a2127d4abb573d3866d2efd302ceb0d4d2a5/tblib-3.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/03/98/eb27cc78ad3af8e302c9d8ff4977f5026676e130d28dd7578132a457170c/toolz-1.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/3c/83/ec3196c360afffbc5b342ead48d1eb7393dd74fa70bca75d33905a86f211/trio-0.27.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/48/be/a9ae5f50cad5b6f85bd2574c2c923730098530096e170c1ce7452394d7aa/trio_websocket-0.11.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ce/d9/5f4c13cecde62396b0d3fe530a50ccea91e7dfc1ccf0e09c228841bb5ba8/urllib3-2.2.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/5c/ba/f551b829378d65d0e0494fdb492942a0ed2dc7f40681b2438a47d1f4af86/wasmtime-25.0.0-py3-none-manylinux1_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/5e/24/806c5bd1b5e30c83cc9d182795edebfbfe24483f82fb18823b309a6656b5/wasmtime-27.0.1-py3-none-manylinux1_x86_64.whl - pypi: https://files.pythonhosted.org/packages/5a/84/44687a29792a70e111c5c477230a72c4b957d88d16141199bf9acb7537a3/websocket_client-1.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/78/58/e860788190eba3bcce367f74d29c4675466ce8dddfba85f7827588416f01/wsproto-1.2.0-py3-none-any.whl + - pypi: python/itkwasm-transform-io-wasi linux-aarch64: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-2_gnu.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.6.2.post1-pyhd8ed1ab_0.conda @@ -620,9 +614,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstandard-0.23.0-py312hb698573_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.6-h02f22dd_0.conda - pypi: https://files.pythonhosted.org/packages/6a/21/5b6702a7f963e95456c0de2d495f67bf5fd62840ac655dc451586d23d39a/attrs-24.2.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/48/41/e1d85ca3cab0b674e277c8c4f678cf66a91cd2cecf93df94353a606fe0db/cloudpickle-3.1.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/2a/72/33ff765a07913cb5061baa94718f3a17003aa29adc89642a68c295d47582/dask-2024.11.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c6/b2/454d6e7f0158951d8a78c2e1eb4f69ae81beb8dca5fee9809c6c99e9d0d0/fsspec-2024.10.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/66/d4/c8c04958870f482459ab5956c2942c4ec35cac7fe245527f1039837c17a9/greenlet-3.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/13/0e/3f934459c4aab461281ad24b01de08bd612118fbc70ecc7b0fa5ed156a94/hypothesis-6.115.6-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8a/a0/732ddb5575a5be47d1088def8b1db91c799263a8d583181341271a4f6e6d/itk-5.4.0-cp311-abi3-manylinux_2_28_aarch64.whl @@ -634,28 +625,25 @@ environments: - pypi: https://files.pythonhosted.org/packages/e7/f0/a21ddf56263ad6c5f87164032aaeb2235ee2de688cb8a8eeec01a5f01bd7/itk_registration-5.4.0-cp311-abi3-manylinux_2_28_aarch64.whl - pypi: https://files.pythonhosted.org/packages/79/b9/ba9598bb8b7ee3962980d481065a58f75569c5a2df1d01520083288894b0/itk_segmentation-5.4.0-cp311-abi3-manylinux_2_28_aarch64.whl - pypi: https://files.pythonhosted.org/packages/f2/f5/cd8ed297bd1b9f816d7492bfa857c53bd8fd68aefc2aa9bef7a0d5a61d85/itk_webassemblyinterface-1.0b175-cp311-abi3-manylinux_2_28_aarch64.whl - - pypi: https://files.pythonhosted.org/packages/bd/a5/329525eeaf0ac895a37b0a498b311e6d2991d47c827804908a815ae088f3/itkwasm-1.0b180-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bc/f3/db24f14dfed1f631e4568440542dce7330b1c17a5c098666164872db4404/itkwasm-1.0b185-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c4/a7/af3329fda3c3ec31d9b650e42bbcd3422fc62a765cbb1405fde4177a0996/numpy-2.1.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/55/8b/5ab7257531a5d830fc8000c476e63c935488d74609b50f9384a643ec0a62/outcome-1.3.0.post0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/31/dc/121be574222fc74d12ac42921728fb6ba8ac17264a1fdab1993263389082/playwright-1.48.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/1d/0d/95993c08c721ec68892547f2117e8f9dfbcef2ca71e098533541b4a54d5f/pyee-12.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/6f/ec/70457045923b005761b19f78b85b467a64808e886c10c449f7758a1ba5f7/pyodide_py-0.26.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2e/4a/970d2604a72e9d44904533b5438135187aa3b08b8d6fc75e5404cd8a1dd1/pyodide_py-0.26.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8d/59/b4572118e098ac8e46e399a1dd0f2d85403ce8bbaad9ec79373ed6badaf9/PySocks-1.7.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/96/31/6607dab48616902f76885dfcf62c08d929796fc3b2d2318faf9fd54dbed9/pytest_asyncio-0.24.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/cd/98/7a2d160bd1a997c6fc422647ccf907fcc1b14b8e4a89790fa1427b8f4d16/pytest_pyodide-0.58.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/aa/85/fa44f23dd5d5066a72f7c4304cce4b5ff9a6e7fd92431a48b2c63fbf63ec/selenium-4.25.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9b/87/ce70db7cae60e67851eb94e1a2127d4abb573d3866d2efd302ceb0d4d2a5/tblib-3.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/03/98/eb27cc78ad3af8e302c9d8ff4977f5026676e130d28dd7578132a457170c/toolz-1.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/3c/83/ec3196c360afffbc5b342ead48d1eb7393dd74fa70bca75d33905a86f211/trio-0.27.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/48/be/a9ae5f50cad5b6f85bd2574c2c923730098530096e170c1ce7452394d7aa/trio_websocket-0.11.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ce/d9/5f4c13cecde62396b0d3fe530a50ccea91e7dfc1ccf0e09c228841bb5ba8/urllib3-2.2.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b7/36/5e83b5f7858fe1003cbb89d0d5716f628b9a00fafc3762665f06ca4ef75d/wasmtime-25.0.0-py3-none-manylinux2014_aarch64.whl + - pypi: https://files.pythonhosted.org/packages/3a/57/cd877b4797be239b4433f89a5a85c7bf2c5319dd91c7777b1867bebb664e/wasmtime-27.0.1-py3-none-manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/5a/84/44687a29792a70e111c5c477230a72c4b957d88d16141199bf9acb7537a3/websocket_client-1.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/78/58/e860788190eba3bcce367f74d29c4675466ce8dddfba85f7827588416f01/wsproto-1.2.0-py3-none-any.whl + - pypi: python/itkwasm-transform-io-wasi osx-arm64: - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.6.2.post1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/backports-1.0-pyhd8ed1ab_4.conda @@ -751,9 +739,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstandard-0.23.0-py312h15fbf35_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.6-hb46c0d2_0.conda - pypi: https://files.pythonhosted.org/packages/6a/21/5b6702a7f963e95456c0de2d495f67bf5fd62840ac655dc451586d23d39a/attrs-24.2.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/48/41/e1d85ca3cab0b674e277c8c4f678cf66a91cd2cecf93df94353a606fe0db/cloudpickle-3.1.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/2a/72/33ff765a07913cb5061baa94718f3a17003aa29adc89642a68c295d47582/dask-2024.11.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c6/b2/454d6e7f0158951d8a78c2e1eb4f69ae81beb8dca5fee9809c6c99e9d0d0/fsspec-2024.10.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/7d/ec/bad1ac26764d26aa1353216fcbfa4670050f66d445448aafa227f8b16e80/greenlet-3.1.1-cp312-cp312-macosx_11_0_universal2.whl - pypi: https://files.pythonhosted.org/packages/13/0e/3f934459c4aab461281ad24b01de08bd612118fbc70ecc7b0fa5ed156a94/hypothesis-6.115.6-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0b/dc/c0c76414440ea1520b496801b9ee82f7cfbe5c4c1643e1e82c383897b3ae/itk-5.4.0-cp311-abi3-macosx_11_0_arm64.whl @@ -765,28 +750,25 @@ environments: - pypi: https://files.pythonhosted.org/packages/88/99/3db052a349efaf1ddbb51252e7e4c7a6a10ed5b3b87e2076afb622b711fd/itk_registration-5.4.0-cp311-abi3-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/3a/92/7d32413898fe4068f0b2da97ab783057e6af84123aa6c54af3706476fed9/itk_segmentation-5.4.0-cp311-abi3-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/77/66/73fa21a0439eacae5156c73611b35eec2c9c3d83ae4f987754043fce1d67/itk_webassemblyinterface-1.0b175-cp311-abi3-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/bd/a5/329525eeaf0ac895a37b0a498b311e6d2991d47c827804908a815ae088f3/itkwasm-1.0b180-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bc/f3/db24f14dfed1f631e4568440542dce7330b1c17a5c098666164872db4404/itkwasm-1.0b185-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b0/29/cb48a402ea879e645b16218718f3f7d9588a77d674a9dcf22e4c43487636/numpy-2.1.2-cp312-cp312-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/55/8b/5ab7257531a5d830fc8000c476e63c935488d74609b50f9384a643ec0a62/outcome-1.3.0.post0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/64/41/d77c47743800fbeb86657611e651e56a17cbb4ebfefa1da0318dc39092df/playwright-1.48.0-py3-none-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/1d/0d/95993c08c721ec68892547f2117e8f9dfbcef2ca71e098533541b4a54d5f/pyee-12.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/6f/ec/70457045923b005761b19f78b85b467a64808e886c10c449f7758a1ba5f7/pyodide_py-0.26.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2e/4a/970d2604a72e9d44904533b5438135187aa3b08b8d6fc75e5404cd8a1dd1/pyodide_py-0.26.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8d/59/b4572118e098ac8e46e399a1dd0f2d85403ce8bbaad9ec79373ed6badaf9/PySocks-1.7.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/96/31/6607dab48616902f76885dfcf62c08d929796fc3b2d2318faf9fd54dbed9/pytest_asyncio-0.24.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/cd/98/7a2d160bd1a997c6fc422647ccf907fcc1b14b8e4a89790fa1427b8f4d16/pytest_pyodide-0.58.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/aa/85/fa44f23dd5d5066a72f7c4304cce4b5ff9a6e7fd92431a48b2c63fbf63ec/selenium-4.25.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9b/87/ce70db7cae60e67851eb94e1a2127d4abb573d3866d2efd302ceb0d4d2a5/tblib-3.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/03/98/eb27cc78ad3af8e302c9d8ff4977f5026676e130d28dd7578132a457170c/toolz-1.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/3c/83/ec3196c360afffbc5b342ead48d1eb7393dd74fa70bca75d33905a86f211/trio-0.27.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/48/be/a9ae5f50cad5b6f85bd2574c2c923730098530096e170c1ce7452394d7aa/trio_websocket-0.11.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ce/d9/5f4c13cecde62396b0d3fe530a50ccea91e7dfc1ccf0e09c228841bb5ba8/urllib3-2.2.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/cc/f0/d415d6b31ba69cfca04b2d5e83fbb5fc05335323712fd91948a1a53d13be/wasmtime-25.0.0-py3-none-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/6e/d8/38d1af31c1787e09642354c81215920a5bf59722a6786ed7e9622fd1f033/wasmtime-27.0.1-py3-none-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/5a/84/44687a29792a70e111c5c477230a72c4b957d88d16141199bf9acb7537a3/websocket_client-1.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/78/58/e860788190eba3bcce367f74d29c4675466ce8dddfba85f7827588416f01/wsproto-1.2.0-py3-none-any.whl + - pypi: python/itkwasm-transform-io-wasi win-64: - conda: https://conda.anaconda.org/conda-forge/noarch/anyio-4.6.2.post1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/backports-1.0-pyhd8ed1ab_4.conda @@ -887,9 +869,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/zstandard-0.23.0-py312h7606c53_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.6-h0ea2cb4_0.conda - pypi: https://files.pythonhosted.org/packages/6a/21/5b6702a7f963e95456c0de2d495f67bf5fd62840ac655dc451586d23d39a/attrs-24.2.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/48/41/e1d85ca3cab0b674e277c8c4f678cf66a91cd2cecf93df94353a606fe0db/cloudpickle-3.1.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/2a/72/33ff765a07913cb5061baa94718f3a17003aa29adc89642a68c295d47582/dask-2024.11.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c6/b2/454d6e7f0158951d8a78c2e1eb4f69ae81beb8dca5fee9809c6c99e9d0d0/fsspec-2024.10.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/43/21/a5d9df1d21514883333fc86584c07c2b49ba7c602e670b174bd73cfc9c7f/greenlet-3.1.1-cp312-cp312-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/13/0e/3f934459c4aab461281ad24b01de08bd612118fbc70ecc7b0fa5ed156a94/hypothesis-6.115.6-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e6/05/b876851fc885a3e3cb85f4167bcbc35020da23b98d50da3947041fc82224/itk-5.4.0-cp311-abi3-win_amd64.whl @@ -901,28 +880,25 @@ environments: - pypi: https://files.pythonhosted.org/packages/89/f6/686c2d2650065495720889c2e6ebcf6af2e5c2692fc6d8768793b08c641a/itk_registration-5.4.0-cp311-abi3-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/77/8d/916c078544ac29a5ac215d2e5a2b07c9314b515b63136be92d6856a41f55/itk_segmentation-5.4.0-cp311-abi3-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/6c/cf/af6554bd0fd831ba2f8ed7840904a1b0828b1ea348b5000b78ad34c5688f/itk_webassemblyinterface-1.0b175-cp311-abi3-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/bd/a5/329525eeaf0ac895a37b0a498b311e6d2991d47c827804908a815ae088f3/itkwasm-1.0b180-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/bc/f3/db24f14dfed1f631e4568440542dce7330b1c17a5c098666164872db4404/itkwasm-1.0b185-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/4c/79/73735a6a5dad6059c085f240a4e74c9270feccd2bc66e4d31b5ca01d329c/numpy-2.1.2-cp312-cp312-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/55/8b/5ab7257531a5d830fc8000c476e63c935488d74609b50f9384a643ec0a62/outcome-1.3.0.post0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/45/88/b6459c93a8bc0b96e7a33b6744bbef2740a0b78b0534542a037d220427f0/playwright-1.48.0-py3-none-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/1d/0d/95993c08c721ec68892547f2117e8f9dfbcef2ca71e098533541b4a54d5f/pyee-12.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/6f/ec/70457045923b005761b19f78b85b467a64808e886c10c449f7758a1ba5f7/pyodide_py-0.26.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2e/4a/970d2604a72e9d44904533b5438135187aa3b08b8d6fc75e5404cd8a1dd1/pyodide_py-0.26.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8d/59/b4572118e098ac8e46e399a1dd0f2d85403ce8bbaad9ec79373ed6badaf9/PySocks-1.7.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/96/31/6607dab48616902f76885dfcf62c08d929796fc3b2d2318faf9fd54dbed9/pytest_asyncio-0.24.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/cd/98/7a2d160bd1a997c6fc422647ccf907fcc1b14b8e4a89790fa1427b8f4d16/pytest_pyodide-0.58.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/aa/85/fa44f23dd5d5066a72f7c4304cce4b5ff9a6e7fd92431a48b2c63fbf63ec/selenium-4.25.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9b/87/ce70db7cae60e67851eb94e1a2127d4abb573d3866d2efd302ceb0d4d2a5/tblib-3.0.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/03/98/eb27cc78ad3af8e302c9d8ff4977f5026676e130d28dd7578132a457170c/toolz-1.0.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/3c/83/ec3196c360afffbc5b342ead48d1eb7393dd74fa70bca75d33905a86f211/trio-0.27.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/48/be/a9ae5f50cad5b6f85bd2574c2c923730098530096e170c1ce7452394d7aa/trio_websocket-0.11.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ce/d9/5f4c13cecde62396b0d3fe530a50ccea91e7dfc1ccf0e09c228841bb5ba8/urllib3-2.2.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/1b/21/c0f3e031efe5f009215975eb7dbea86b55a69c4f02420965d1f45f43865e/wasmtime-25.0.0-py3-none-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/14/6f/f6b99d9ab1511398686e00d2a26371d99a7949531514379d731b3b7e6309/wasmtime-27.0.1-py3-none-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/5a/84/44687a29792a70e111c5c477230a72c4b957d88d16141199bf9acb7537a3/websocket_client-1.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/78/58/e860788190eba3bcce367f74d29c4675466ce8dddfba85f7827588416f01/wsproto-1.2.0-py3-none-any.whl + - pypi: python/itkwasm-transform-io-wasi packages: - kind: conda name: _libgcc_mutex @@ -1332,12 +1308,6 @@ packages: - pkg:pypi/click?source=hash-mapping size: 85051 timestamp: 1692312207348 -- kind: pypi - name: cloudpickle - version: 3.1.0 - url: https://files.pythonhosted.org/packages/48/41/e1d85ca3cab0b674e277c8c4f678cf66a91cd2cecf93df94353a606fe0db/cloudpickle-3.1.0-py3-none-any.whl - sha256: fe11acda67f61aaaec473e3afe030feb131d78a43461b718185363384f1ba12e - requires_python: '>=3.8' - kind: conda name: colorama version: 0.4.6 @@ -1401,38 +1371,6 @@ packages: - pkg:pypi/cryptography?source=hash-mapping size: 1480456 timestamp: 1729287055014 -- kind: pypi - name: dask - version: 2024.11.2 - url: https://files.pythonhosted.org/packages/2a/72/33ff765a07913cb5061baa94718f3a17003aa29adc89642a68c295d47582/dask-2024.11.2-py3-none-any.whl - sha256: 6115c4b76015e8d9d9c2922b6a0a1c850e283fb7fee74eebbd2e28e9c117c30d - requires_dist: - - click>=8.1 - - cloudpickle>=3.0.0 - - fsspec>=2021.9.0 - - packaging>=20.0 - - partd>=1.4.0 - - pyyaml>=5.3.1 - - toolz>=0.10.0 - - importlib-metadata>=4.13.0 ; python_full_version < '3.12' - - numpy>=1.24 ; extra == 'array' - - dask[array,dataframe,diagnostics,distributed] ; extra == 'complete' - - pyarrow>=14.0.1 ; extra == 'complete' - - lz4>=4.3.2 ; extra == 'complete' - - dask[array] ; extra == 'dataframe' - - pandas>=2.0 ; extra == 'dataframe' - - dask-expr<1.2,>=1.1 ; extra == 'dataframe' - - bokeh>=3.1.0 ; extra == 'diagnostics' - - jinja2>=2.10.3 ; extra == 'diagnostics' - - distributed==2024.11.2 ; extra == 'distributed' - - pandas[test] ; extra == 'test' - - pytest ; extra == 'test' - - pytest-cov ; extra == 'test' - - pytest-rerunfailures ; extra == 'test' - - pytest-timeout ; extra == 'test' - - pytest-xdist ; extra == 'test' - - pre-commit ; extra == 'test' - requires_python: '>=3.10' - kind: conda name: dbus version: 1.13.6 @@ -1637,115 +1575,6 @@ packages: purls: [] size: 642092 timestamp: 1694617858496 -- kind: pypi - name: fsspec - version: 2024.10.0 - url: https://files.pythonhosted.org/packages/c6/b2/454d6e7f0158951d8a78c2e1eb4f69ae81beb8dca5fee9809c6c99e9d0d0/fsspec-2024.10.0-py3-none-any.whl - sha256: 03b9a6785766a4de40368b88906366755e2819e758b83705c88cd7cb5fe81871 - requires_dist: - - adlfs ; extra == 'abfs' - - adlfs ; extra == 'adl' - - pyarrow>=1 ; extra == 'arrow' - - dask ; extra == 'dask' - - distributed ; extra == 'dask' - - pre-commit ; extra == 'dev' - - ruff ; extra == 'dev' - - numpydoc ; extra == 'doc' - - sphinx ; extra == 'doc' - - sphinx-design ; extra == 'doc' - - sphinx-rtd-theme ; extra == 'doc' - - yarl ; extra == 'doc' - - dropbox ; extra == 'dropbox' - - dropboxdrivefs ; extra == 'dropbox' - - requests ; extra == 'dropbox' - - adlfs ; extra == 'full' - - aiohttp!=4.0.0a0,!=4.0.0a1 ; extra == 'full' - - dask ; extra == 'full' - - distributed ; extra == 'full' - - dropbox ; extra == 'full' - - dropboxdrivefs ; extra == 'full' - - fusepy ; extra == 'full' - - gcsfs ; extra == 'full' - - libarchive-c ; extra == 'full' - - ocifs ; extra == 'full' - - panel ; extra == 'full' - - paramiko ; extra == 'full' - - pyarrow>=1 ; extra == 'full' - - pygit2 ; extra == 'full' - - requests ; extra == 'full' - - s3fs ; extra == 'full' - - smbprotocol ; extra == 'full' - - tqdm ; extra == 'full' - - fusepy ; extra == 'fuse' - - gcsfs ; extra == 'gcs' - - pygit2 ; extra == 'git' - - requests ; extra == 'github' - - gcsfs ; extra == 'gs' - - panel ; extra == 'gui' - - pyarrow>=1 ; extra == 'hdfs' - - aiohttp!=4.0.0a0,!=4.0.0a1 ; extra == 'http' - - libarchive-c ; extra == 'libarchive' - - ocifs ; extra == 'oci' - - s3fs ; extra == 's3' - - paramiko ; extra == 'sftp' - - smbprotocol ; extra == 'smb' - - paramiko ; extra == 'ssh' - - aiohttp!=4.0.0a0,!=4.0.0a1 ; extra == 'test' - - numpy ; extra == 'test' - - pytest ; extra == 'test' - - pytest-asyncio!=0.22.0 ; extra == 'test' - - pytest-benchmark ; extra == 'test' - - pytest-cov ; extra == 'test' - - pytest-mock ; extra == 'test' - - pytest-recording ; extra == 'test' - - pytest-rerunfailures ; extra == 'test' - - requests ; extra == 'test' - - aiobotocore<3.0.0,>=2.5.4 ; extra == 'test-downstream' - - dask-expr ; extra == 'test-downstream' - - dask[dataframe,test] ; extra == 'test-downstream' - - moto[server]<5,>4 ; extra == 'test-downstream' - - pytest-timeout ; extra == 'test-downstream' - - xarray ; extra == 'test-downstream' - - adlfs ; extra == 'test-full' - - aiohttp!=4.0.0a0,!=4.0.0a1 ; extra == 'test-full' - - cloudpickle ; extra == 'test-full' - - dask ; extra == 'test-full' - - distributed ; extra == 'test-full' - - dropbox ; extra == 'test-full' - - dropboxdrivefs ; extra == 'test-full' - - fastparquet ; extra == 'test-full' - - fusepy ; extra == 'test-full' - - gcsfs ; extra == 'test-full' - - jinja2 ; extra == 'test-full' - - kerchunk ; extra == 'test-full' - - libarchive-c ; extra == 'test-full' - - lz4 ; extra == 'test-full' - - notebook ; extra == 'test-full' - - numpy ; extra == 'test-full' - - ocifs ; extra == 'test-full' - - pandas ; extra == 'test-full' - - panel ; extra == 'test-full' - - paramiko ; extra == 'test-full' - - pyarrow ; extra == 'test-full' - - pyarrow>=1 ; extra == 'test-full' - - pyftpdlib ; extra == 'test-full' - - pygit2 ; extra == 'test-full' - - pytest ; extra == 'test-full' - - pytest-asyncio!=0.22.0 ; extra == 'test-full' - - pytest-benchmark ; extra == 'test-full' - - pytest-cov ; extra == 'test-full' - - pytest-mock ; extra == 'test-full' - - pytest-recording ; extra == 'test-full' - - pytest-rerunfailures ; extra == 'test-full' - - python-snappy ; extra == 'test-full' - - requests ; extra == 'test-full' - - smbprotocol ; extra == 'test-full' - - tqdm ; extra == 'test-full' - - urllib3 ; extra == 'test-full' - - zarr ; extra == 'test-full' - - zstandard ; extra == 'test-full' - - tqdm ; extra == 'tqdm' - requires_python: '>=3.8' - kind: pypi name: greenlet version: 3.1.1 @@ -2465,17 +2294,26 @@ packages: requires_python: '>=3.8' - kind: pypi name: itkwasm - version: 1.0b180 - url: https://files.pythonhosted.org/packages/bd/a5/329525eeaf0ac895a37b0a498b311e6d2991d47c827804908a815ae088f3/itkwasm-1.0b180-py3-none-any.whl - sha256: d2ca6988f64ba779679981b73164dfdc3adbc06eb52f235dca4092ce390d6ebe + version: 1.0b185 + url: https://files.pythonhosted.org/packages/bc/f3/db24f14dfed1f631e4568440542dce7330b1c17a5c098666164872db4404/itkwasm-1.0b185-py3-none-any.whl + sha256: 5d976f244f645e8c1700d59a32dd4461f9ade152693b64d6ebefdfe6b97a2413 requires_dist: - - dask[array]<2025,>=2024.11.2 - importlib-metadata ; python_full_version < '3.10' - numpy - platformdirs ; sys_platform != 'emscripten' - typing-extensions - - wasmtime>=13.0.2 ; sys_platform != 'emscripten' + - wasmtime>=27.0.1 ; sys_platform != 'emscripten' + requires_python: '>=3.9' +- kind: pypi + name: itkwasm-transform-io-wasi + version: 0.1.1 + path: python/itkwasm-transform-io-wasi + sha256: 21ef72cc91a6d86bbd3bd2382298a91ac15c667baac37e946c4e112f76234bac + requires_dist: + - importlib-resources + - itkwasm>=1.0b185 requires_python: '>=3.9' + editable: true - kind: conda name: jaraco.classes version: 3.4.0 @@ -3929,12 +3767,6 @@ packages: purls: [] size: 60963 timestamp: 1727963148474 -- kind: pypi - name: locket - version: 1.0.0 - url: https://files.pythonhosted.org/packages/db/bc/83e112abc66cd466c6b83f99118035867cecd41802f8d044638aa78a106e/locket-1.0.0-py2.py3-none-any.whl - sha256: b6c819a722f7b6bd955b80781788e4a66a55628b858d347536b7e81325a3a5e3 - requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*' - kind: conda name: m2w64-gcc-libgfortran version: 5.3.0 @@ -4471,19 +4303,6 @@ packages: - pkg:pypi/packaging?source=hash-mapping size: 50290 timestamp: 1718189540074 -- kind: pypi - name: partd - version: 1.4.2 - url: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl - sha256: 978e4ac767ec4ba5b86c6eaa52e5a2a3bc748a2ca839e8cc798f1cc6ce6efb0f - requires_dist: - - locket - - toolz - - numpy>=1.20.0 ; extra == 'complete' - - pandas>=1.3 ; extra == 'complete' - - pyzmq ; extra == 'complete' - - blosc ; extra == 'complete' - requires_python: '>=3.9' - kind: conda name: pathspec version: 0.12.1 @@ -4969,9 +4788,9 @@ packages: timestamp: 1714846885370 - kind: pypi name: pyodide-py - version: 0.26.3 - url: https://files.pythonhosted.org/packages/6f/ec/70457045923b005761b19f78b85b467a64808e886c10c449f7758a1ba5f7/pyodide_py-0.26.3-py3-none-any.whl - sha256: b63b6847c8906aa8f3c17df362135d0407aabf1d4b023557aed721d822e347a8 + version: 0.26.4 + url: https://files.pythonhosted.org/packages/2e/4a/970d2604a72e9d44904533b5438135187aa3b08b8d6fc75e5404cd8a1dd1/pyodide_py-0.26.4-py3-none-any.whl + sha256: a5bc814aba54a25f3292b91de44ff05629c941d5c27483f43d9e85775a6bf158 requires_python: '>=3.12' - kind: pypi name: pysocks @@ -5232,30 +5051,6 @@ packages: - pkg:pypi/pywin32-ctypes?source=hash-mapping size: 57449 timestamp: 1727282288065 -- kind: pypi - name: pyyaml - version: 6.0.2 - url: https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl - sha256: 7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8 - requires_python: '>=3.8' -- kind: pypi - name: pyyaml - version: 6.0.2 - url: https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl - sha256: ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725 - requires_python: '>=3.8' -- kind: pypi - name: pyyaml - version: 6.0.2 - url: https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476 - requires_python: '>=3.8' -- kind: pypi - name: pyyaml - version: 6.0.2 - url: https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5 - requires_python: '>=3.8' - kind: conda name: readline version: '8.2' @@ -5561,12 +5356,6 @@ packages: - pkg:pypi/tomlkit?source=hash-mapping size: 37279 timestamp: 1723631592742 -- kind: pypi - name: toolz - version: 1.0.0 - url: https://files.pythonhosted.org/packages/03/98/eb27cc78ad3af8e302c9d8ff4977f5026676e130d28dd7578132a457170c/toolz-1.0.0-py3-none-any.whl - sha256: 292c8f1c4e7516bf9086f8850935c799a874039c8bcf959d47b600e4c44a6236 - requires_python: '>=3.8' - kind: pypi name: trio version: 0.27.0 @@ -5825,9 +5614,9 @@ packages: timestamp: 1728400827536 - kind: pypi name: wasmtime - version: 25.0.0 - url: https://files.pythonhosted.org/packages/1b/21/c0f3e031efe5f009215975eb7dbea86b55a69c4f02420965d1f45f43865e/wasmtime-25.0.0-py3-none-win_amd64.whl - sha256: f8a2a213b9179965db2d2eedececd69a37e287e902330509afae51c71a3a6842 + version: 27.0.1 + url: https://files.pythonhosted.org/packages/14/6f/f6b99d9ab1511398686e00d2a26371d99a7949531514379d731b3b7e6309/wasmtime-27.0.1-py3-none-win_amd64.whl + sha256: e691aafe8881a872a69a52822f24c209f54fe6f06154d1dfadd977ee86374169 requires_dist: - importlib-resources>=5.10 - coverage ; extra == 'testing' @@ -5835,12 +5624,12 @@ packages: - pycparser ; extra == 'testing' - pytest-mypy ; extra == 'testing' - componentize-py ; extra == 'testing' - requires_python: '>=3.8' + requires_python: '>=3.9' - kind: pypi name: wasmtime - version: 25.0.0 - url: https://files.pythonhosted.org/packages/5c/ba/f551b829378d65d0e0494fdb492942a0ed2dc7f40681b2438a47d1f4af86/wasmtime-25.0.0-py3-none-manylinux1_x86_64.whl - sha256: b4364e14d44e3b7afe6a40bf608e9d0d2c40b09dece441d20f4f6e31906b729c + version: 27.0.1 + url: https://files.pythonhosted.org/packages/3a/57/cd877b4797be239b4433f89a5a85c7bf2c5319dd91c7777b1867bebb664e/wasmtime-27.0.1-py3-none-manylinux2014_aarch64.whl + sha256: dac4e2232cc44b6bfc290f84ff9244621b7e99ee1da4036afb83113dd93b13bf requires_dist: - importlib-resources>=5.10 - coverage ; extra == 'testing' @@ -5848,12 +5637,12 @@ packages: - pycparser ; extra == 'testing' - pytest-mypy ; extra == 'testing' - componentize-py ; extra == 'testing' - requires_python: '>=3.8' + requires_python: '>=3.9' - kind: pypi name: wasmtime - version: 25.0.0 - url: https://files.pythonhosted.org/packages/b7/36/5e83b5f7858fe1003cbb89d0d5716f628b9a00fafc3762665f06ca4ef75d/wasmtime-25.0.0-py3-none-manylinux2014_aarch64.whl - sha256: a07445073cf36a6e5d1dc28246a897dcbdaa537ba8be8805be65422ecca297eb + version: 27.0.1 + url: https://files.pythonhosted.org/packages/5e/24/806c5bd1b5e30c83cc9d182795edebfbfe24483f82fb18823b309a6656b5/wasmtime-27.0.1-py3-none-manylinux1_x86_64.whl + sha256: 99339ed56b7bc4d280bcb0d5527725a7cfe51c269941cf888f57b46f05c249a6 requires_dist: - importlib-resources>=5.10 - coverage ; extra == 'testing' @@ -5861,12 +5650,12 @@ packages: - pycparser ; extra == 'testing' - pytest-mypy ; extra == 'testing' - componentize-py ; extra == 'testing' - requires_python: '>=3.8' + requires_python: '>=3.9' - kind: pypi name: wasmtime - version: 25.0.0 - url: https://files.pythonhosted.org/packages/cc/f0/d415d6b31ba69cfca04b2d5e83fbb5fc05335323712fd91948a1a53d13be/wasmtime-25.0.0-py3-none-macosx_11_0_arm64.whl - sha256: 5bdf1214ee3ee78a4a8a92da339f4c4c8c109e65af881b37f4adfc05d02af426 + version: 27.0.1 + url: https://files.pythonhosted.org/packages/6e/d8/38d1af31c1787e09642354c81215920a5bf59722a6786ed7e9622fd1f033/wasmtime-27.0.1-py3-none-macosx_11_0_arm64.whl + sha256: 1082442529d06c5c50fb9377dbb599460c175f98ca0d332625bf76661c7309b4 requires_dist: - importlib-resources>=5.10 - coverage ; extra == 'testing' @@ -5874,7 +5663,7 @@ packages: - pycparser ; extra == 'testing' - pytest-mypy ; extra == 'testing' - componentize-py ; extra == 'testing' - requires_python: '>=3.8' + requires_python: '>=3.9' - kind: pypi name: websocket-client version: 1.8.0 diff --git a/packages/transform-io/pixi.toml b/packages/transform-io/pixi.toml index 56f983bfe..e6f8f6f6f 100644 --- a/packages/transform-io/pixi.toml +++ b/packages/transform-io/pixi.toml @@ -81,10 +81,11 @@ pytest = ">=8.3.3,<9" pillow = ">=10.4.0,<12" [feature.python.pypi-dependencies] -pyodide-py = ">=0.26.3, <0.27" +pyodide-py = ">=0.26.4, <0.27" pytest-pyodide = ">=0.58.3, <0.59" itk-webassemblyinterface = ">=1.0b175, <2" -itkwasm = ">=1.0b180, <2" +itkwasm = ">=1.0b185, <2" +itkwasm-transform-io-wasi = { path = "python/itkwasm-transform-io-wasi", editable = true } [feature.python.tasks.test-wasi] cmd = "pytest" @@ -92,7 +93,7 @@ cwd = "python/itkwasm-transform-io-wasi" description = "Run tests for itkwasm-transform-io-wasi" [feature.python.tasks.download-pyodide] -cmd = '''curl -L https://github.com/pyodide/pyodide/releases/download/0.26.3/pyodide-0.26.3.tar.bz2 -o pyodide.tar.bz2 && +cmd = '''curl -L https://github.com/pyodide/pyodide/releases/download/0.26.4/pyodide-0.26.4.tar.bz2 -o pyodide.tar.bz2 && tar xjf pyodide.tar.bz2 && rm pyodide.tar.bz2''' outputs = ["pyodide"] diff --git a/packages/transform-io/python/itkwasm-transform-io-emscripten/itkwasm_transform_io_emscripten/__init__.py b/packages/transform-io/python/itkwasm-transform-io-emscripten/itkwasm_transform_io_emscripten/__init__.py index 73df3a55c..ad54fe823 100644 --- a/packages/transform-io/python/itkwasm-transform-io-emscripten/itkwasm_transform_io_emscripten/__init__.py +++ b/packages/transform-io/python/itkwasm-transform-io-emscripten/itkwasm_transform_io_emscripten/__init__.py @@ -1,7 +1,8 @@ -# Generated file. To retain edits, remove this comment. - """itkwasm-transform-io-emscripten: Input and output for scientific and medical coordinate transform file formats. Emscripten implementation.""" +from .read_transform_async import read_transform_async +from .write_transform_async import write_transform_async + from .hdf5_read_transform_async import hdf5_read_transform_async from .hdf5_write_transform_async import hdf5_write_transform_async from .mat_read_transform_async import mat_read_transform_async diff --git a/packages/transform-io/python/itkwasm-transform-io-emscripten/itkwasm_transform_io_emscripten/_version.py b/packages/transform-io/python/itkwasm-transform-io-emscripten/itkwasm_transform_io_emscripten/_version.py index 3dc1f76bc..485f44ac2 100644 --- a/packages/transform-io/python/itkwasm-transform-io-emscripten/itkwasm_transform_io_emscripten/_version.py +++ b/packages/transform-io/python/itkwasm-transform-io-emscripten/itkwasm_transform_io_emscripten/_version.py @@ -1 +1 @@ -__version__ = "0.1.0" +__version__ = "0.1.1" diff --git a/packages/transform-io/python/itkwasm-transform-io-emscripten/itkwasm_transform_io_emscripten/extension_to_transform_io.py b/packages/transform-io/python/itkwasm-transform-io-emscripten/itkwasm_transform_io_emscripten/extension_to_transform_io.py new file mode 100644 index 000000000..76f705b4e --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io-emscripten/itkwasm_transform_io_emscripten/extension_to_transform_io.py @@ -0,0 +1,12 @@ +from collections import OrderedDict + +extension_to_transform_io = OrderedDict([ + ("h5", "hdf5"), + ("hdf5", "hdf5"), + ("txt", "txt"), + ("mat", "mat"), + ("xfm", "mnc"), + ("iwt", "wasm"), + ("iwt.cbor", "wasm"), + ("iwt.cbor.zst", "wasmZstd"), +]) diff --git a/packages/transform-io/python/itkwasm-transform-io-emscripten/itkwasm_transform_io_emscripten/js_package.py b/packages/transform-io/python/itkwasm-transform-io-emscripten/itkwasm_transform_io_emscripten/js_package.py index 57c176bba..a17265d05 100644 --- a/packages/transform-io/python/itkwasm-transform-io-emscripten/itkwasm_transform_io_emscripten/js_package.py +++ b/packages/transform-io/python/itkwasm-transform-io-emscripten/itkwasm_transform_io_emscripten/js_package.py @@ -3,6 +3,6 @@ from itkwasm.pyodide import JsPackageConfig, JsPackage from ._version import __version__ -default_js_module = """data:text/javascript;base64,dmFyIGN0PU9iamVjdC5kZWZpbmVQcm9wZXJ0eTt2YXIgdXQ9KEEsZSk9Pntmb3IodmFyIHQgaW4gZSljdChBLHQse2dldDplW3RdLGVudW1lcmFibGU6ITB9KX07dmFyIEV0PSIwLjEuMSIsa0E9RXQ7dmFyIFF0PXtJbnQ4OiJpbnQ4IixVSW50ODoidWludDgiLEludDE2OiJpbnQxNiIsVUludDE2OiJ1aW50MTYiLEludDMyOiJpbnQzMiIsVUludDMyOiJ1aW50MzIiLEludDY0OiJpbnQ2NCIsVUludDY0OiJ1aW50NjQiLFNpemVWYWx1ZVR5cGU6InVpbnQ2NCIsSWRlbnRpZmllclR5cGU6InVpbnQ2NCIsSW5kZXhWYWx1ZVR5cGU6ImludDY0IixPZmZzZXRWYWx1ZVR5cGU6ImludDY0In0sRj1RdDt2YXIgcHQ9e0Zsb2F0MzI6ImZsb2F0MzIiLEZsb2F0NjQ6ImZsb2F0NjQiLFNwYWNlUHJlY2lzaW9uVHlwZToiZmxvYXQ2NCJ9LE09cHQ7ZnVuY3Rpb24gbXQoQSxlKXtsZXQgdD1udWxsO3N3aXRjaChBKXtjYXNlIEYuVUludDg6e3Q9bmV3IFVpbnQ4QXJyYXkoZSk7YnJlYWt9Y2FzZSBGLkludDg6e3Q9bmV3IEludDhBcnJheShlKTticmVha31jYXNlIEYuVUludDE2Ont0PW5ldyBVaW50MTZBcnJheShlKTticmVha31jYXNlIEYuSW50MTY6e3Q9bmV3IEludDE2QXJyYXkoZSk7YnJlYWt9Y2FzZSBGLlVJbnQzMjp7dD1uZXcgVWludDMyQXJyYXkoZSk7YnJlYWt9Y2FzZSBGLkludDMyOnt0PW5ldyBJbnQzMkFycmF5KGUpO2JyZWFrfWNhc2UgRi5VSW50NjQ6e3R5cGVvZiBnbG9iYWxUaGlzLkJpZ1VpbnQ2NEFycmF5PT0iZnVuY3Rpb24iP3Q9bmV3IEJpZ1VpbnQ2NEFycmF5KGUpOnQ9bmV3IFVpbnQ4QXJyYXkoZSk7YnJlYWt9Y2FzZSBGLkludDY0Ont0eXBlb2YgZ2xvYmFsVGhpcy5CaWdJbnQ2NEFycmF5PT0iZnVuY3Rpb24iP3Q9bmV3IEJpZ0ludDY0QXJyYXkoZSk6dD1uZXcgVWludDhBcnJheShlKTticmVha31jYXNlIE0uRmxvYXQzMjp7dD1uZXcgRmxvYXQzMkFycmF5KGUpO2JyZWFrfWNhc2UgTS5GbG9hdDY0Ont0PW5ldyBGbG9hdDY0QXJyYXkoZSk7YnJlYWt9Y2FzZSJudWxsIjp7dD1udWxsO2JyZWFrfWNhc2UgbnVsbDp7dD1udWxsO2JyZWFrfWRlZmF1bHQ6dGhyb3cgbmV3IEVycm9yKCJUeXBlIGlzIG5vdCBzdXBwb3J0ZWQgYXMgYSBUeXBlZEFycmF5Iil9cmV0dXJuIHR9dmFyIEw9bXQ7dmFyIGR0PXtUZXh0RmlsZToiVGV4dEZpbGUiLEJpbmFyeUZpbGU6IkJpbmFyeUZpbGUiLFRleHRTdHJlYW06IlRleHRTdHJlYW0iLEJpbmFyeVN0cmVhbToiQmluYXJ5U3RyZWFtIixJbWFnZToiSW1hZ2UiLFBvaW50U2V0OiJQb2ludFNldCIsTWVzaDoiTWVzaCIsUG9seURhdGE6IlBvbHlEYXRhIixUcmFuc2Zvcm1MaXN0OiJUcmFuc2Zvcm1MaXN0IixKc29uQ29tcGF0aWJsZToiSnNvbkNvbXBhdGlibGUifSxFPWR0O3ZhciBpZT1TeW1ib2woIkNvbWxpbmsucHJveHkiKSx5dD1TeW1ib2woIkNvbWxpbmsuZW5kcG9pbnQiKSxOQT1TeW1ib2woIkNvbWxpbmsucmVsZWFzZVByb3h5IiksRkE9U3ltYm9sKCJDb21saW5rLmZpbmFsaXplciIpLElBPVN5bWJvbCgiQ29tbGluay50aHJvd24iKSxhZT1BPT50eXBlb2YgQT09Im9iamVjdCImJkEhPT1udWxsfHx0eXBlb2YgQT09ImZ1bmN0aW9uIixodD17Y2FuSGFuZGxlOkE9PmFlKEEpJiZBW2llXSxzZXJpYWxpemUoQSl7bGV0e3BvcnQxOmUscG9ydDI6dH09bmV3IE1lc3NhZ2VDaGFubmVsO3JldHVybiBJZShBLGUpLFt0LFt0XV19LGRlc2VyaWFsaXplKEEpe3JldHVybiBBLnN0YXJ0KCksVEEoQSl9fSx3dD17Y2FuSGFuZGxlOkE9PmFlKEEpJiZJQSBpbiBBLHNlcmlhbGl6ZSh7dmFsdWU6QX0pe2xldCBlO3JldHVybiBBIGluc3RhbmNlb2YgRXJyb3I/ZT17aXNFcnJvcjohMCx2YWx1ZTp7bWVzc2FnZTpBLm1lc3NhZ2UsbmFtZTpBLm5hbWUsc3RhY2s6QS5zdGFja319OmU9e2lzRXJyb3I6ITEsdmFsdWU6QX0sW2UsW11dfSxkZXNlcmlhbGl6ZShBKXt0aHJvdyBBLmlzRXJyb3I/T2JqZWN0LmFzc2lnbihuZXcgRXJyb3IoQS52YWx1ZS5tZXNzYWdlKSxBLnZhbHVlKTpBLnZhbHVlfX0sc2U9bmV3IE1hcChbWyJwcm94eSIsaHRdLFsidGhyb3ciLHd0XV0pO2Z1bmN0aW9uIER0KEEsZSl7Zm9yKGxldCB0IG9mIEEpaWYoZT09PXR8fHQ9PT0iKiJ8fHQgaW5zdGFuY2VvZiBSZWdFeHAmJnQudGVzdChlKSlyZXR1cm4hMDtyZXR1cm4hMX1mdW5jdGlvbiBJZShBLGU9Z2xvYmFsVGhpcyx0PVsiKiJdKXtlLmFkZEV2ZW50TGlzdGVuZXIoIm1lc3NhZ2UiLGZ1bmN0aW9uIHIobil7aWYoIW58fCFuLmRhdGEpcmV0dXJuO2lmKCFEdCh0LG4ub3JpZ2luKSl7Y29uc29sZS53YXJuKGBJbnZhbGlkIG9yaWdpbiAnJHtuLm9yaWdpbn0nIGZvciBjb21saW5rIHByb3h5YCk7cmV0dXJufWxldHtpZDpvLHR5cGU6aSxwYXRoOkJ9PU9iamVjdC5hc3NpZ24oe3BhdGg6W119LG4uZGF0YSksdT0obi5kYXRhLmFyZ3VtZW50TGlzdHx8W10pLm1hcChIKSxDO3RyeXtsZXQgcz1CLnNsaWNlKDAsLTEpLnJlZHVjZSgoYyxJKT0+Y1tJXSxBKSxhPUIucmVkdWNlKChjLEkpPT5jW0ldLEEpO3N3aXRjaChpKXtjYXNlIkdFVCI6Qz1hO2JyZWFrO2Nhc2UiU0VUIjpzW0Iuc2xpY2UoLTEpWzBdXT1IKG4uZGF0YS52YWx1ZSksQz0hMDticmVhaztjYXNlIkFQUExZIjpDPWEuYXBwbHkocyx1KTticmVhaztjYXNlIkNPTlNUUlVDVCI6e2xldCBjPW5ldyBhKC4uLnUpO0M9RnQoYyl9YnJlYWs7Y2FzZSJFTkRQT0lOVCI6e2xldHtwb3J0MTpjLHBvcnQyOkl9PW5ldyBNZXNzYWdlQ2hhbm5lbDtJZShBLEkpLEM9TEEoYyxbY10pfWJyZWFrO2Nhc2UiUkVMRUFTRSI6Qz12b2lkIDA7YnJlYWs7ZGVmYXVsdDpyZXR1cm59fWNhdGNoKHMpe0M9e3ZhbHVlOnMsW0lBXTowfX1Qcm9taXNlLnJlc29sdmUoQykuY2F0Y2gocz0+KHt2YWx1ZTpzLFtJQV06MH0pKS50aGVuKHM9PntsZXRbYSxjXT1DQShzKTtlLnBvc3RNZXNzYWdlKE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSxhKSx7aWQ6b30pLGMpLGk9PT0iUkVMRUFTRSImJihlLnJlbW92ZUV2ZW50TGlzdGVuZXIoIm1lc3NhZ2UiLHIpLGdlKGUpLEZBIGluIEEmJnR5cGVvZiBBW0ZBXT09ImZ1bmN0aW9uIiYmQVtGQV0oKSl9KS5jYXRjaChzPT57bGV0W2EsY109Q0Eoe3ZhbHVlOm5ldyBUeXBlRXJyb3IoIlVuc2VyaWFsaXphYmxlIHJldHVybiB2YWx1ZSIpLFtJQV06MH0pO2UucG9zdE1lc3NhZ2UoT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LGEpLHtpZDpvfSksYyl9KX0pLGUuc3RhcnQmJmUuc3RhcnQoKX1mdW5jdGlvbiBTdChBKXtyZXR1cm4gQS5jb25zdHJ1Y3Rvci5uYW1lPT09Ik1lc3NhZ2VQb3J0In1mdW5jdGlvbiBnZShBKXtTdChBKSYmQS5jbG9zZSgpfWZ1bmN0aW9uIFRBKEEsZSl7cmV0dXJuIFVBKEEsW10sZSl9ZnVuY3Rpb24gc0EoQSl7aWYoQSl0aHJvdyBuZXcgRXJyb3IoIlByb3h5IGhhcyBiZWVuIHJlbGVhc2VkIGFuZCBpcyBub3QgdXNlYWJsZSIpfWZ1bmN0aW9uIEJlKEEpe3JldHVybiBZKEEse3R5cGU6IlJFTEVBU0UifSkudGhlbigoKT0+e2dlKEEpfSl9dmFyIGdBPW5ldyBXZWFrTWFwLEJBPSJGaW5hbGl6YXRpb25SZWdpc3RyeSJpbiBnbG9iYWxUaGlzJiZuZXcgRmluYWxpemF0aW9uUmVnaXN0cnkoQT0+e2xldCBlPShnQS5nZXQoQSl8fDApLTE7Z0Euc2V0KEEsZSksZT09PTAmJkJlKEEpfSk7ZnVuY3Rpb24gUnQoQSxlKXtsZXQgdD0oZ0EuZ2V0KGUpfHwwKSsxO2dBLnNldChlLHQpLEJBJiZCQS5yZWdpc3RlcihBLGUsQSl9ZnVuY3Rpb24gYnQoQSl7QkEmJkJBLnVucmVnaXN0ZXIoQSl9ZnVuY3Rpb24gVUEoQSxlPVtdLHQ9ZnVuY3Rpb24oKXt9KXtsZXQgcj0hMSxuPW5ldyBQcm94eSh0LHtnZXQobyxpKXtpZihzQShyKSxpPT09TkEpcmV0dXJuKCk9PntidChuKSxCZShBKSxyPSEwfTtpZihpPT09InRoZW4iKXtpZihlLmxlbmd0aD09PTApcmV0dXJue3RoZW46KCk9Pm59O2xldCBCPVkoQSx7dHlwZToiR0VUIixwYXRoOmUubWFwKHU9PnUudG9TdHJpbmcoKSl9KS50aGVuKEgpO3JldHVybiBCLnRoZW4uYmluZChCKX1yZXR1cm4gVUEoQSxbLi4uZSxpXSl9LHNldChvLGksQil7c0Eocik7bGV0W3UsQ109Q0EoQik7cmV0dXJuIFkoQSx7dHlwZToiU0VUIixwYXRoOlsuLi5lLGldLm1hcChzPT5zLnRvU3RyaW5nKCkpLHZhbHVlOnV9LEMpLnRoZW4oSCl9LGFwcGx5KG8saSxCKXtzQShyKTtsZXQgdT1lW2UubGVuZ3RoLTFdO2lmKHU9PT15dClyZXR1cm4gWShBLHt0eXBlOiJFTkRQT0lOVCJ9KS50aGVuKEgpO2lmKHU9PT0iYmluZCIpcmV0dXJuIFVBKEEsZS5zbGljZSgwLC0xKSk7bGV0W0Msc109bmUoQik7cmV0dXJuIFkoQSx7dHlwZToiQVBQTFkiLHBhdGg6ZS5tYXAoYT0+YS50b1N0cmluZygpKSxhcmd1bWVudExpc3Q6Q30scykudGhlbihIKX0sY29uc3RydWN0KG8saSl7c0Eocik7bGV0W0IsdV09bmUoaSk7cmV0dXJuIFkoQSx7dHlwZToiQ09OU1RSVUNUIixwYXRoOmUubWFwKEM9PkMudG9TdHJpbmcoKSksYXJndW1lbnRMaXN0OkJ9LHUpLnRoZW4oSCl9fSk7cmV0dXJuIFJ0KG4sQSksbn1mdW5jdGlvbiBrdChBKXtyZXR1cm4gQXJyYXkucHJvdG90eXBlLmNvbmNhdC5hcHBseShbXSxBKX1mdW5jdGlvbiBuZShBKXtsZXQgZT1BLm1hcChDQSk7cmV0dXJuW2UubWFwKHQ9PnRbMF0pLGt0KGUubWFwKHQ9PnRbMV0pKV19dmFyIENlPW5ldyBXZWFrTWFwO2Z1bmN0aW9uIExBKEEsZSl7cmV0dXJuIENlLnNldChBLGUpLEF9ZnVuY3Rpb24gRnQoQSl7cmV0dXJuIE9iamVjdC5hc3NpZ24oQSx7W2llXTohMH0pfWZ1bmN0aW9uIENBKEEpe2ZvcihsZXRbZSx0XW9mIHNlKWlmKHQuY2FuSGFuZGxlKEEpKXtsZXRbcixuXT10LnNlcmlhbGl6ZShBKTtyZXR1cm5be3R5cGU6IkhBTkRMRVIiLG5hbWU6ZSx2YWx1ZTpyfSxuXX1yZXR1cm5be3R5cGU6IlJBVyIsdmFsdWU6QX0sQ2UuZ2V0KEEpfHxbXV19ZnVuY3Rpb24gSChBKXtzd2l0Y2goQS50eXBlKXtjYXNlIkhBTkRMRVIiOnJldHVybiBzZS5nZXQoQS5uYW1lKS5kZXNlcmlhbGl6ZShBLnZhbHVlKTtjYXNlIlJBVyI6cmV0dXJuIEEudmFsdWV9fWZ1bmN0aW9uIFkoQSxlLHQpe3JldHVybiBuZXcgUHJvbWlzZShyPT57bGV0IG49VXQoKTtBLmFkZEV2ZW50TGlzdGVuZXIoIm1lc3NhZ2UiLGZ1bmN0aW9uIG8oaSl7IWkuZGF0YXx8IWkuZGF0YS5pZHx8aS5kYXRhLmlkIT09bnx8KEEucmVtb3ZlRXZlbnRMaXN0ZW5lcigibWVzc2FnZSIsbykscihpLmRhdGEpKX0pLEEuc3RhcnQmJkEuc3RhcnQoKSxBLnBvc3RNZXNzYWdlKE9iamVjdC5hc3NpZ24oe2lkOm59LGUpLHQpfSl9ZnVuY3Rpb24gVXQoKXtyZXR1cm4gbmV3IEFycmF5KDQpLmZpbGwoMCkubWFwKCgpPT5NYXRoLmZsb29yKE1hdGgucmFuZG9tKCkqTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVIpLnRvU3RyaW5nKDE2KSkuam9pbigiLSIpfWZ1bmN0aW9uIFooQSxlKXtyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gQS5hcHBseShlLGFyZ3VtZW50cyl9fXZhcnt0b1N0cmluZzpOdH09T2JqZWN0LnByb3RvdHlwZSx7Z2V0UHJvdG90eXBlT2Y6T0F9PU9iamVjdCxmQT0oQT0+ZT0+e2xldCB0PU50LmNhbGwoZSk7cmV0dXJuIEFbdF18fChBW3RdPXQuc2xpY2UoOCwtMSkudG9Mb3dlckNhc2UoKSl9KShPYmplY3QuY3JlYXRlKG51bGwpKSxQPUE9PihBPUEudG9Mb3dlckNhc2UoKSxlPT5mQShlKT09PUEpLGNBPUE9PmU9PnR5cGVvZiBlPT09QSx7aXNBcnJheTpxfT1BcnJheSxYPWNBKCJ1bmRlZmluZWQiKTtmdW5jdGlvbiBUdChBKXtyZXR1cm4gQSE9PW51bGwmJiFYKEEpJiZBLmNvbnN0cnVjdG9yIT09bnVsbCYmIVgoQS5jb25zdHJ1Y3RvcikmJlQoQS5jb25zdHJ1Y3Rvci5pc0J1ZmZlcikmJkEuY29uc3RydWN0b3IuaXNCdWZmZXIoQSl9dmFyIHVlPVAoIkFycmF5QnVmZmVyIik7ZnVuY3Rpb24gTHQoQSl7bGV0IGU7cmV0dXJuIHR5cGVvZiBBcnJheUJ1ZmZlcjwidSImJkFycmF5QnVmZmVyLmlzVmlldz9lPUFycmF5QnVmZmVyLmlzVmlldyhBKTplPUEmJkEuYnVmZmVyJiZ1ZShBLmJ1ZmZlciksZX12YXIgUHQ9Y0EoInN0cmluZyIpLFQ9Y0EoImZ1bmN0aW9uIiksRWU9Y0EoIm51bWJlciIpLHVBPUE9PkEhPT1udWxsJiZ0eXBlb2YgQT09Im9iamVjdCIsR3Q9QT0+QT09PSEwfHxBPT09ITEsbEE9QT0+e2lmKGZBKEEpIT09Im9iamVjdCIpcmV0dXJuITE7bGV0IGU9T0EoQSk7cmV0dXJuKGU9PT1udWxsfHxlPT09T2JqZWN0LnByb3RvdHlwZXx8T2JqZWN0LmdldFByb3RvdHlwZU9mKGUpPT09bnVsbCkmJiEoU3ltYm9sLnRvU3RyaW5nVGFnIGluIEEpJiYhKFN5bWJvbC5pdGVyYXRvciBpbiBBKX0sT3Q9UCgiRGF0ZSIpLHh0PVAoIkZpbGUiKSxKdD1QKCJCbG9iIiksV3Q9UCgiRmlsZUxpc3QiKSxIdD1BPT51QShBKSYmVChBLnBpcGUpLE10PUE9PntsZXQgZTtyZXR1cm4gQSYmKHR5cGVvZiBGb3JtRGF0YT09ImZ1bmN0aW9uIiYmQSBpbnN0YW5jZW9mIEZvcm1EYXRhfHxUKEEuYXBwZW5kKSYmKChlPWZBKEEpKT09PSJmb3JtZGF0YSJ8fGU9PT0ib2JqZWN0IiYmVChBLnRvU3RyaW5nKSYmQS50b1N0cmluZygpPT09IltvYmplY3QgRm9ybURhdGFdIikpfSxZdD1QKCJVUkxTZWFyY2hQYXJhbXMiKSxxdD1BPT5BLnRyaW0/QS50cmltKCk6QS5yZXBsYWNlKC9eW1xzXHVGRUZGXHhBMF0rfFtcc1x1RkVGRlx4QTBdKyQvZywiIik7ZnVuY3Rpb24gJChBLGUse2FsbE93bktleXM6dD0hMX09e30pe2lmKEE9PT1udWxsfHx0eXBlb2YgQT4idSIpcmV0dXJuO2xldCByLG47aWYodHlwZW9mIEEhPSJvYmplY3QiJiYoQT1bQV0pLHEoQSkpZm9yKHI9MCxuPUEubGVuZ3RoO3I8bjtyKyspZS5jYWxsKG51bGwsQVtyXSxyLEEpO2Vsc2V7bGV0IG89dD9PYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhBKTpPYmplY3Qua2V5cyhBKSxpPW8ubGVuZ3RoLEI7Zm9yKHI9MDtyPGk7cisrKUI9b1tyXSxlLmNhbGwobnVsbCxBW0JdLEIsQSl9fWZ1bmN0aW9uIFFlKEEsZSl7ZT1lLnRvTG93ZXJDYXNlKCk7bGV0IHQ9T2JqZWN0LmtleXMoQSkscj10Lmxlbmd0aCxuO2Zvcig7ci0tID4wOylpZihuPXRbcl0sZT09PW4udG9Mb3dlckNhc2UoKSlyZXR1cm4gbjtyZXR1cm4gbnVsbH12YXIgcGU9dHlwZW9mIGdsb2JhbFRoaXM8InUiP2dsb2JhbFRoaXM6dHlwZW9mIHNlbGY8InUiP3NlbGY6dHlwZW9mIHdpbmRvdzwidSI/d2luZG93Omdsb2JhbCxtZT1BPT4hWChBKSYmQSE9PXBlO2Z1bmN0aW9uIEdBKCl7bGV0e2Nhc2VsZXNzOkF9PW1lKHRoaXMpJiZ0aGlzfHx7fSxlPXt9LHQ9KHIsbik9PntsZXQgbz1BJiZRZShlLG4pfHxuO2xBKGVbb10pJiZsQShyKT9lW29dPUdBKGVbb10scik6bEEocik/ZVtvXT1HQSh7fSxyKTpxKHIpP2Vbb109ci5zbGljZSgpOmVbb109cn07Zm9yKGxldCByPTAsbj1hcmd1bWVudHMubGVuZ3RoO3I8bjtyKyspYXJndW1lbnRzW3JdJiYkKGFyZ3VtZW50c1tyXSx0KTtyZXR1cm4gZX12YXIgS3Q9KEEsZSx0LHthbGxPd25LZXlzOnJ9PXt9KT0+KCQoZSwobixvKT0+e3QmJlQobik/QVtvXT1aKG4sdCk6QVtvXT1ufSx7YWxsT3duS2V5czpyfSksQSksanQ9QT0+KEEuY2hhckNvZGVBdCgwKT09PTY1Mjc5JiYoQT1BLnNsaWNlKDEpKSxBKSx2dD0oQSxlLHQscik9PntBLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKGUucHJvdG90eXBlLHIpLEEucHJvdG90eXBlLmNvbnN0cnVjdG9yPUEsT2JqZWN0LmRlZmluZVByb3BlcnR5KEEsInN1cGVyIix7dmFsdWU6ZS5wcm90b3R5cGV9KSx0JiZPYmplY3QuYXNzaWduKEEucHJvdG90eXBlLHQpfSxfdD0oQSxlLHQscik9PntsZXQgbixvLGksQj17fTtpZihlPWV8fHt9LEE9PW51bGwpcmV0dXJuIGU7ZG97Zm9yKG49T2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMoQSksbz1uLmxlbmd0aDtvLS0gPjA7KWk9bltvXSwoIXJ8fHIoaSxBLGUpKSYmIUJbaV0mJihlW2ldPUFbaV0sQltpXT0hMCk7QT10IT09ITEmJk9BKEEpfXdoaWxlKEEmJighdHx8dChBLGUpKSYmQSE9PU9iamVjdC5wcm90b3R5cGUpO3JldHVybiBlfSx6dD0oQSxlLHQpPT57QT1TdHJpbmcoQSksKHQ9PT12b2lkIDB8fHQ+QS5sZW5ndGgpJiYodD1BLmxlbmd0aCksdC09ZS5sZW5ndGg7bGV0IHI9QS5pbmRleE9mKGUsdCk7cmV0dXJuIHIhPT0tMSYmcj09PXR9LFZ0PUE9PntpZighQSlyZXR1cm4gbnVsbDtpZihxKEEpKXJldHVybiBBO2xldCBlPUEubGVuZ3RoO2lmKCFFZShlKSlyZXR1cm4gbnVsbDtsZXQgdD1uZXcgQXJyYXkoZSk7Zm9yKDtlLS0gPjA7KXRbZV09QVtlXTtyZXR1cm4gdH0sWnQ9KEE9PmU9PkEmJmUgaW5zdGFuY2VvZiBBKSh0eXBlb2YgVWludDhBcnJheTwidSImJk9BKFVpbnQ4QXJyYXkpKSxYdD0oQSxlKT0+e2xldCByPShBJiZBW1N5bWJvbC5pdGVyYXRvcl0pLmNhbGwoQSksbjtmb3IoOyhuPXIubmV4dCgpKSYmIW4uZG9uZTspe2xldCBvPW4udmFsdWU7ZS5jYWxsKEEsb1swXSxvWzFdKX19LCR0PShBLGUpPT57bGV0IHQscj1bXTtmb3IoOyh0PUEuZXhlYyhlKSkhPT1udWxsOylyLnB1c2godCk7cmV0dXJuIHJ9LEFyPVAoIkhUTUxGb3JtRWxlbWVudCIpLGVyPUE9PkEudG9Mb3dlckNhc2UoKS5yZXBsYWNlKC9bLV9cc10oW2EtelxkXSkoXHcqKS9nLGZ1bmN0aW9uKHQscixuKXtyZXR1cm4gci50b1VwcGVyQ2FzZSgpK259KSxmZT0oKHtoYXNPd25Qcm9wZXJ0eTpBfSk9PihlLHQpPT5BLmNhbGwoZSx0KSkoT2JqZWN0LnByb3RvdHlwZSksdHI9UCgiUmVnRXhwIiksZGU9KEEsZSk9PntsZXQgdD1PYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycyhBKSxyPXt9OyQodCwobixvKT0+e2xldCBpOyhpPWUobixvLEEpKSE9PSExJiYocltvXT1pfHxuKX0pLE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKEEscil9LHJyPUE9PntkZShBLChlLHQpPT57aWYoVChBKSYmWyJhcmd1bWVudHMiLCJjYWxsZXIiLCJjYWxsZWUiXS5pbmRleE9mKHQpIT09LTEpcmV0dXJuITE7bGV0IHI9QVt0XTtpZihUKHIpKXtpZihlLmVudW1lcmFibGU9ITEsIndyaXRhYmxlImluIGUpe2Uud3JpdGFibGU9ITE7cmV0dXJufWUuc2V0fHwoZS5zZXQ9KCk9Pnt0aHJvdyBFcnJvcigiQ2FuIG5vdCByZXdyaXRlIHJlYWQtb25seSBtZXRob2QgJyIrdCsiJyIpfSl9fSl9LG9yPShBLGUpPT57bGV0IHQ9e30scj1uPT57bi5mb3JFYWNoKG89Pnt0W29dPSEwfSl9O3JldHVybiBxKEEpP3IoQSk6cihTdHJpbmcoQSkuc3BsaXQoZSkpLHR9LG5yPSgpPT57fSxpcj0oQSxlKT0+KEE9K0EsTnVtYmVyLmlzRmluaXRlKEEpP0E6ZSksUEE9ImFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6IixjZT0iMDEyMzQ1Njc4OSIseWU9e0RJR0lUOmNlLEFMUEhBOlBBLEFMUEhBX0RJR0lUOlBBK1BBLnRvVXBwZXJDYXNlKCkrY2V9LGFyPShBPTE2LGU9eWUuQUxQSEFfRElHSVQpPT57bGV0IHQ9IiIse2xlbmd0aDpyfT1lO2Zvcig7QS0tOyl0Kz1lW01hdGgucmFuZG9tKCkqcnwwXTtyZXR1cm4gdH07ZnVuY3Rpb24gc3IoQSl7cmV0dXJuISEoQSYmVChBLmFwcGVuZCkmJkFbU3ltYm9sLnRvU3RyaW5nVGFnXT09PSJGb3JtRGF0YSImJkFbU3ltYm9sLml0ZXJhdG9yXSl9dmFyIElyPUE9PntsZXQgZT1uZXcgQXJyYXkoMTApLHQ9KHIsbik9PntpZih1QShyKSl7aWYoZS5pbmRleE9mKHIpPj0wKXJldHVybjtpZighKCJ0b0pTT04iaW4gcikpe2Vbbl09cjtsZXQgbz1xKHIpP1tdOnt9O3JldHVybiAkKHIsKGksQik9PntsZXQgdT10KGksbisxKTshWCh1KSYmKG9bQl09dSl9KSxlW25dPXZvaWQgMCxvfX1yZXR1cm4gcn07cmV0dXJuIHQoQSwwKX0sZ3I9UCgiQXN5bmNGdW5jdGlvbiIpLEJyPUE9PkEmJih1QShBKXx8VChBKSkmJlQoQS50aGVuKSYmVChBLmNhdGNoKSxnPXtpc0FycmF5OnEsaXNBcnJheUJ1ZmZlcjp1ZSxpc0J1ZmZlcjpUdCxpc0Zvcm1EYXRhOk10LGlzQXJyYXlCdWZmZXJWaWV3Okx0LGlzU3RyaW5nOlB0LGlzTnVtYmVyOkVlLGlzQm9vbGVhbjpHdCxpc09iamVjdDp1QSxpc1BsYWluT2JqZWN0OmxBLGlzVW5kZWZpbmVkOlgsaXNEYXRlOk90LGlzRmlsZTp4dCxpc0Jsb2I6SnQsaXNSZWdFeHA6dHIsaXNGdW5jdGlvbjpULGlzU3RyZWFtOkh0LGlzVVJMU2VhcmNoUGFyYW1zOll0LGlzVHlwZWRBcnJheTpadCxpc0ZpbGVMaXN0Old0LGZvckVhY2g6JCxtZXJnZTpHQSxleHRlbmQ6S3QsdHJpbTpxdCxzdHJpcEJPTTpqdCxpbmhlcml0czp2dCx0b0ZsYXRPYmplY3Q6X3Qsa2luZE9mOmZBLGtpbmRPZlRlc3Q6UCxlbmRzV2l0aDp6dCx0b0FycmF5OlZ0LGZvckVhY2hFbnRyeTpYdCxtYXRjaEFsbDokdCxpc0hUTUxGb3JtOkFyLGhhc093blByb3BlcnR5OmZlLGhhc093blByb3A6ZmUscmVkdWNlRGVzY3JpcHRvcnM6ZGUsZnJlZXplTWV0aG9kczpycix0b09iamVjdFNldDpvcix0b0NhbWVsQ2FzZTplcixub29wOm5yLHRvRmluaXRlTnVtYmVyOmlyLGZpbmRLZXk6UWUsZ2xvYmFsOnBlLGlzQ29udGV4dERlZmluZWQ6bWUsQUxQSEFCRVQ6eWUsZ2VuZXJhdGVTdHJpbmc6YXIsaXNTcGVjQ29tcGxpYW50Rm9ybTpzcix0b0pTT05PYmplY3Q6SXIsaXNBc3luY0ZuOmdyLGlzVGhlbmFibGU6QnJ9O2Z1bmN0aW9uIEsoQSxlLHQscixuKXtFcnJvci5jYWxsKHRoaXMpLEVycm9yLmNhcHR1cmVTdGFja1RyYWNlP0Vycm9yLmNhcHR1cmVTdGFja1RyYWNlKHRoaXMsdGhpcy5jb25zdHJ1Y3Rvcik6dGhpcy5zdGFjaz1uZXcgRXJyb3IoKS5zdGFjayx0aGlzLm1lc3NhZ2U9QSx0aGlzLm5hbWU9IkF4aW9zRXJyb3IiLGUmJih0aGlzLmNvZGU9ZSksdCYmKHRoaXMuY29uZmlnPXQpLHImJih0aGlzLnJlcXVlc3Q9ciksbiYmKHRoaXMucmVzcG9uc2U9bil9Zy5pbmhlcml0cyhLLEVycm9yLHt0b0pTT046ZnVuY3Rpb24oKXtyZXR1cm57bWVzc2FnZTp0aGlzLm1lc3NhZ2UsbmFtZTp0aGlzLm5hbWUsZGVzY3JpcHRpb246dGhpcy5kZXNjcmlwdGlvbixudW1iZXI6dGhpcy5udW1iZXIsZmlsZU5hbWU6dGhpcy5maWxlTmFtZSxsaW5lTnVtYmVyOnRoaXMubGluZU51bWJlcixjb2x1bW5OdW1iZXI6dGhpcy5jb2x1bW5OdW1iZXIsc3RhY2s6dGhpcy5zdGFjayxjb25maWc6Zy50b0pTT05PYmplY3QodGhpcy5jb25maWcpLGNvZGU6dGhpcy5jb2RlLHN0YXR1czp0aGlzLnJlc3BvbnNlJiZ0aGlzLnJlc3BvbnNlLnN0YXR1cz90aGlzLnJlc3BvbnNlLnN0YXR1czpudWxsfX19KTt2YXIgaGU9Sy5wcm90b3R5cGUsd2U9e307WyJFUlJfQkFEX09QVElPTl9WQUxVRSIsIkVSUl9CQURfT1BUSU9OIiwiRUNPTk5BQk9SVEVEIiwiRVRJTUVET1VUIiwiRVJSX05FVFdPUksiLCJFUlJfRlJfVE9PX01BTllfUkVESVJFQ1RTIiwiRVJSX0RFUFJFQ0FURUQiLCJFUlJfQkFEX1JFU1BPTlNFIiwiRVJSX0JBRF9SRVFVRVNUIiwiRVJSX0NBTkNFTEVEIiwiRVJSX05PVF9TVVBQT1JUIiwiRVJSX0lOVkFMSURfVVJMIl0uZm9yRWFjaChBPT57d2VbQV09e3ZhbHVlOkF9fSk7T2JqZWN0LmRlZmluZVByb3BlcnRpZXMoSyx3ZSk7T2JqZWN0LmRlZmluZVByb3BlcnR5KGhlLCJpc0F4aW9zRXJyb3IiLHt2YWx1ZTohMH0pO0suZnJvbT0oQSxlLHQscixuLG8pPT57bGV0IGk9T2JqZWN0LmNyZWF0ZShoZSk7cmV0dXJuIGcudG9GbGF0T2JqZWN0KEEsaSxmdW5jdGlvbih1KXtyZXR1cm4gdSE9PUVycm9yLnByb3RvdHlwZX0sQj0+QiE9PSJpc0F4aW9zRXJyb3IiKSxLLmNhbGwoaSxBLm1lc3NhZ2UsZSx0LHIsbiksaS5jYXVzZT1BLGkubmFtZT1BLm5hbWUsbyYmT2JqZWN0LmFzc2lnbihpLG8pLGl9O3ZhciBwPUs7dmFyIEVBPW51bGw7ZnVuY3Rpb24geEEoQSl7cmV0dXJuIGcuaXNQbGFpbk9iamVjdChBKXx8Zy5pc0FycmF5KEEpfWZ1bmN0aW9uIFNlKEEpe3JldHVybiBnLmVuZHNXaXRoKEEsIltdIik/QS5zbGljZSgwLC0yKTpBfWZ1bmN0aW9uIERlKEEsZSx0KXtyZXR1cm4gQT9BLmNvbmNhdChlKS5tYXAoZnVuY3Rpb24obixvKXtyZXR1cm4gbj1TZShuKSwhdCYmbz8iWyIrbisiXSI6bn0pLmpvaW4odD8iLiI6IiIpOmV9ZnVuY3Rpb24gQ3IoQSl7cmV0dXJuIGcuaXNBcnJheShBKSYmIUEuc29tZSh4QSl9dmFyIGxyPWcudG9GbGF0T2JqZWN0KGcse30sbnVsbCxmdW5jdGlvbihlKXtyZXR1cm4vXmlzW0EtWl0vLnRlc3QoZSl9KTtmdW5jdGlvbiBmcihBLGUsdCl7aWYoIWcuaXNPYmplY3QoQSkpdGhyb3cgbmV3IFR5cGVFcnJvcigidGFyZ2V0IG11c3QgYmUgYW4gb2JqZWN0Iik7ZT1lfHxuZXcoRUF8fEZvcm1EYXRhKSx0PWcudG9GbGF0T2JqZWN0KHQse21ldGFUb2tlbnM6ITAsZG90czohMSxpbmRleGVzOiExfSwhMSxmdW5jdGlvbihmLFEpe3JldHVybiFnLmlzVW5kZWZpbmVkKFFbZl0pfSk7bGV0IHI9dC5tZXRhVG9rZW5zLG49dC52aXNpdG9yfHxzLG89dC5kb3RzLGk9dC5pbmRleGVzLHU9KHQuQmxvYnx8dHlwZW9mIEJsb2I8InUiJiZCbG9iKSYmZy5pc1NwZWNDb21wbGlhbnRGb3JtKGUpO2lmKCFnLmlzRnVuY3Rpb24obikpdGhyb3cgbmV3IFR5cGVFcnJvcigidmlzaXRvciBtdXN0IGJlIGEgZnVuY3Rpb24iKTtmdW5jdGlvbiBDKGwpe2lmKGw9PT1udWxsKXJldHVybiIiO2lmKGcuaXNEYXRlKGwpKXJldHVybiBsLnRvSVNPU3RyaW5nKCk7aWYoIXUmJmcuaXNCbG9iKGwpKXRocm93IG5ldyBwKCJCbG9iIGlzIG5vdCBzdXBwb3J0ZWQuIFVzZSBhIEJ1ZmZlciBpbnN0ZWFkLiIpO3JldHVybiBnLmlzQXJyYXlCdWZmZXIobCl8fGcuaXNUeXBlZEFycmF5KGwpP3UmJnR5cGVvZiBCbG9iPT0iZnVuY3Rpb24iP25ldyBCbG9iKFtsXSk6QnVmZmVyLmZyb20obCk6bH1mdW5jdGlvbiBzKGwsZixRKXtsZXQgbT1sO2lmKGwmJiFRJiZ0eXBlb2YgbD09Im9iamVjdCIpe2lmKGcuZW5kc1dpdGgoZiwie30iKSlmPXI/ZjpmLnNsaWNlKDAsLTIpLGw9SlNPTi5zdHJpbmdpZnkobCk7ZWxzZSBpZihnLmlzQXJyYXkobCkmJkNyKGwpfHwoZy5pc0ZpbGVMaXN0KGwpfHxnLmVuZHNXaXRoKGYsIltdIikpJiYobT1nLnRvQXJyYXkobCkpKXJldHVybiBmPVNlKGYpLG0uZm9yRWFjaChmdW5jdGlvbihOLGZ0KXshKGcuaXNVbmRlZmluZWQoTil8fE49PT1udWxsKSYmZS5hcHBlbmQoaT09PSEwP0RlKFtmXSxmdCxvKTppPT09bnVsbD9mOmYrIltdIixDKE4pKX0pLCExfXJldHVybiB4QShsKT8hMDooZS5hcHBlbmQoRGUoUSxmLG8pLEMobCkpLCExKX1sZXQgYT1bXSxjPU9iamVjdC5hc3NpZ24obHIse2RlZmF1bHRWaXNpdG9yOnMsY29udmVydFZhbHVlOkMsaXNWaXNpdGFibGU6eEF9KTtmdW5jdGlvbiBJKGwsZil7aWYoIWcuaXNVbmRlZmluZWQobCkpe2lmKGEuaW5kZXhPZihsKSE9PS0xKXRocm93IEVycm9yKCJDaXJjdWxhciByZWZlcmVuY2UgZGV0ZWN0ZWQgaW4gIitmLmpvaW4oIi4iKSk7YS5wdXNoKGwpLGcuZm9yRWFjaChsLGZ1bmN0aW9uKG0sVSl7KCEoZy5pc1VuZGVmaW5lZChtKXx8bT09PW51bGwpJiZuLmNhbGwoZSxtLGcuaXNTdHJpbmcoVSk/VS50cmltKCk6VSxmLGMpKT09PSEwJiZJKG0sZj9mLmNvbmNhdChVKTpbVV0pfSksYS5wb3AoKX19aWYoIWcuaXNPYmplY3QoQSkpdGhyb3cgbmV3IFR5cGVFcnJvcigiZGF0YSBtdXN0IGJlIGFuIG9iamVjdCIpO3JldHVybiBJKEEpLGV9dmFyIE89ZnI7ZnVuY3Rpb24gUmUoQSl7bGV0IGU9eyIhIjoiJTIxIiwiJyI6IiUyNyIsIigiOiIlMjgiLCIpIjoiJTI5IiwifiI6IiU3RSIsIiUyMCI6IisiLCIlMDAiOiJcMCJ9O3JldHVybiBlbmNvZGVVUklDb21wb25lbnQoQSkucmVwbGFjZSgvWyEnKCl+XXwlMjB8JTAwL2csZnVuY3Rpb24ocil7cmV0dXJuIGVbcl19KX1mdW5jdGlvbiBiZShBLGUpe3RoaXMuX3BhaXJzPVtdLEEmJk8oQSx0aGlzLGUpfXZhciBrZT1iZS5wcm90b3R5cGU7a2UuYXBwZW5kPWZ1bmN0aW9uKGUsdCl7dGhpcy5fcGFpcnMucHVzaChbZSx0XSl9O2tlLnRvU3RyaW5nPWZ1bmN0aW9uKGUpe2xldCB0PWU/ZnVuY3Rpb24ocil7cmV0dXJuIGUuY2FsbCh0aGlzLHIsUmUpfTpSZTtyZXR1cm4gdGhpcy5fcGFpcnMubWFwKGZ1bmN0aW9uKG4pe3JldHVybiB0KG5bMF0pKyI9Iit0KG5bMV0pfSwiIikuam9pbigiJiIpfTt2YXIgUUE9YmU7ZnVuY3Rpb24gY3IoQSl7cmV0dXJuIGVuY29kZVVSSUNvbXBvbmVudChBKS5yZXBsYWNlKC8lM0EvZ2ksIjoiKS5yZXBsYWNlKC8lMjQvZywiJCIpLnJlcGxhY2UoLyUyQy9naSwiLCIpLnJlcGxhY2UoLyUyMC9nLCIrIikucmVwbGFjZSgvJTVCL2dpLCJbIikucmVwbGFjZSgvJTVEL2dpLCJdIil9ZnVuY3Rpb24gQUEoQSxlLHQpe2lmKCFlKXJldHVybiBBO2xldCByPXQmJnQuZW5jb2RlfHxjcixuPXQmJnQuc2VyaWFsaXplLG87aWYobj9vPW4oZSx0KTpvPWcuaXNVUkxTZWFyY2hQYXJhbXMoZSk/ZS50b1N0cmluZygpOm5ldyBRQShlLHQpLnRvU3RyaW5nKHIpLG8pe2xldCBpPUEuaW5kZXhPZigiIyIpO2khPT0tMSYmKEE9QS5zbGljZSgwLGkpKSxBKz0oQS5pbmRleE9mKCI/Iik9PT0tMT8iPyI6IiYiKStvfXJldHVybiBBfXZhciBKQT1jbGFzc3tjb25zdHJ1Y3Rvcigpe3RoaXMuaGFuZGxlcnM9W119dXNlKGUsdCxyKXtyZXR1cm4gdGhpcy5oYW5kbGVycy5wdXNoKHtmdWxmaWxsZWQ6ZSxyZWplY3RlZDp0LHN5bmNocm9ub3VzOnI/ci5zeW5jaHJvbm91czohMSxydW5XaGVuOnI/ci5ydW5XaGVuOm51bGx9KSx0aGlzLmhhbmRsZXJzLmxlbmd0aC0xfWVqZWN0KGUpe3RoaXMuaGFuZGxlcnNbZV0mJih0aGlzLmhhbmRsZXJzW2VdPW51bGwpfWNsZWFyKCl7dGhpcy5oYW5kbGVycyYmKHRoaXMuaGFuZGxlcnM9W10pfWZvckVhY2goZSl7Zy5mb3JFYWNoKHRoaXMuaGFuZGxlcnMsZnVuY3Rpb24ocil7ciE9PW51bGwmJmUocil9KX19LFdBPUpBO3ZhciBwQT17c2lsZW50SlNPTlBhcnNpbmc6ITAsZm9yY2VkSlNPTlBhcnNpbmc6ITAsY2xhcmlmeVRpbWVvdXRFcnJvcjohMX07dmFyIEZlPXR5cGVvZiBVUkxTZWFyY2hQYXJhbXM8InUiP1VSTFNlYXJjaFBhcmFtczpRQTt2YXIgVWU9dHlwZW9mIEZvcm1EYXRhPCJ1Ij9Gb3JtRGF0YTpudWxsO3ZhciBOZT10eXBlb2YgQmxvYjwidSI/QmxvYjpudWxsO3ZhciBUZT17aXNCcm93c2VyOiEwLGNsYXNzZXM6e1VSTFNlYXJjaFBhcmFtczpGZSxGb3JtRGF0YTpVZSxCbG9iOk5lfSxwcm90b2NvbHM6WyJodHRwIiwiaHR0cHMiLCJmaWxlIiwiYmxvYiIsInVybCIsImRhdGEiXX07dmFyIEhBPXt9O3V0KEhBLHtoYXNCcm93c2VyRW52OigpPT5MZSxoYXNTdGFuZGFyZEJyb3dzZXJFbnY6KCk9PnVyLGhhc1N0YW5kYXJkQnJvd3NlcldlYldvcmtlckVudjooKT0+RXJ9KTt2YXIgTGU9dHlwZW9mIHdpbmRvdzwidSImJnR5cGVvZiBkb2N1bWVudDwidSIsdXI9KEE9PkxlJiZbIlJlYWN0TmF0aXZlIiwiTmF0aXZlU2NyaXB0IiwiTlMiXS5pbmRleE9mKEEpPDApKHR5cGVvZiBuYXZpZ2F0b3I8InUiJiZuYXZpZ2F0b3IucHJvZHVjdCksRXI9dHlwZW9mIFdvcmtlckdsb2JhbFNjb3BlPCJ1IiYmc2VsZiBpbnN0YW5jZW9mIFdvcmtlckdsb2JhbFNjb3BlJiZ0eXBlb2Ygc2VsZi5pbXBvcnRTY3JpcHRzPT0iZnVuY3Rpb24iO3ZhciBiPXsuLi5IQSwuLi5UZX07ZnVuY3Rpb24gTUEoQSxlKXtyZXR1cm4gTyhBLG5ldyBiLmNsYXNzZXMuVVJMU2VhcmNoUGFyYW1zLE9iamVjdC5hc3NpZ24oe3Zpc2l0b3I6ZnVuY3Rpb24odCxyLG4sbyl7cmV0dXJuIGIuaXNOb2RlJiZnLmlzQnVmZmVyKHQpPyh0aGlzLmFwcGVuZChyLHQudG9TdHJpbmcoImJhc2U2NCIpKSwhMSk6by5kZWZhdWx0VmlzaXRvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9fSxlKSl9ZnVuY3Rpb24gUXIoQSl7cmV0dXJuIGcubWF0Y2hBbGwoL1x3K3xcWyhcdyopXS9nLEEpLm1hcChlPT5lWzBdPT09IltdIj8iIjplWzFdfHxlWzBdKX1mdW5jdGlvbiBwcihBKXtsZXQgZT17fSx0PU9iamVjdC5rZXlzKEEpLHIsbj10Lmxlbmd0aCxvO2ZvcihyPTA7cjxuO3IrKylvPXRbcl0sZVtvXT1BW29dO3JldHVybiBlfWZ1bmN0aW9uIG1yKEEpe2Z1bmN0aW9uIGUodCxyLG4sbyl7bGV0IGk9dFtvKytdO2lmKGk9PT0iX19wcm90b19fIilyZXR1cm4hMDtsZXQgQj1OdW1iZXIuaXNGaW5pdGUoK2kpLHU9bz49dC5sZW5ndGg7cmV0dXJuIGk9IWkmJmcuaXNBcnJheShuKT9uLmxlbmd0aDppLHU/KGcuaGFzT3duUHJvcChuLGkpP25baV09W25baV0scl06bltpXT1yLCFCKTooKCFuW2ldfHwhZy5pc09iamVjdChuW2ldKSkmJihuW2ldPVtdKSxlKHQscixuW2ldLG8pJiZnLmlzQXJyYXkobltpXSkmJihuW2ldPXByKG5baV0pKSwhQil9aWYoZy5pc0Zvcm1EYXRhKEEpJiZnLmlzRnVuY3Rpb24oQS5lbnRyaWVzKSl7bGV0IHQ9e307cmV0dXJuIGcuZm9yRWFjaEVudHJ5KEEsKHIsbik9PntlKFFyKHIpLG4sdCwwKX0pLHR9cmV0dXJuIG51bGx9dmFyIG1BPW1yO2Z1bmN0aW9uIGRyKEEsZSx0KXtpZihnLmlzU3RyaW5nKEEpKXRyeXtyZXR1cm4oZXx8SlNPTi5wYXJzZSkoQSksZy50cmltKEEpfWNhdGNoKHIpe2lmKHIubmFtZSE9PSJTeW50YXhFcnJvciIpdGhyb3cgcn1yZXR1cm4odHx8SlNPTi5zdHJpbmdpZnkpKEEpfXZhciBZQT17dHJhbnNpdGlvbmFsOnBBLGFkYXB0ZXI6WyJ4aHIiLCJodHRwIl0sdHJhbnNmb3JtUmVxdWVzdDpbZnVuY3Rpb24oZSx0KXtsZXQgcj10LmdldENvbnRlbnRUeXBlKCl8fCIiLG49ci5pbmRleE9mKCJhcHBsaWNhdGlvbi9qc29uIik+LTEsbz1nLmlzT2JqZWN0KGUpO2lmKG8mJmcuaXNIVE1MRm9ybShlKSYmKGU9bmV3IEZvcm1EYXRhKGUpKSxnLmlzRm9ybURhdGEoZSkpcmV0dXJuIG4/SlNPTi5zdHJpbmdpZnkobUEoZSkpOmU7aWYoZy5pc0FycmF5QnVmZmVyKGUpfHxnLmlzQnVmZmVyKGUpfHxnLmlzU3RyZWFtKGUpfHxnLmlzRmlsZShlKXx8Zy5pc0Jsb2IoZSkpcmV0dXJuIGU7aWYoZy5pc0FycmF5QnVmZmVyVmlldyhlKSlyZXR1cm4gZS5idWZmZXI7aWYoZy5pc1VSTFNlYXJjaFBhcmFtcyhlKSlyZXR1cm4gdC5zZXRDb250ZW50VHlwZSgiYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkO2NoYXJzZXQ9dXRmLTgiLCExKSxlLnRvU3RyaW5nKCk7bGV0IEI7aWYobyl7aWYoci5pbmRleE9mKCJhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQiKT4tMSlyZXR1cm4gTUEoZSx0aGlzLmZvcm1TZXJpYWxpemVyKS50b1N0cmluZygpO2lmKChCPWcuaXNGaWxlTGlzdChlKSl8fHIuaW5kZXhPZigibXVsdGlwYXJ0L2Zvcm0tZGF0YSIpPi0xKXtsZXQgdT10aGlzLmVudiYmdGhpcy5lbnYuRm9ybURhdGE7cmV0dXJuIE8oQj97ImZpbGVzW10iOmV9OmUsdSYmbmV3IHUsdGhpcy5mb3JtU2VyaWFsaXplcil9fXJldHVybiBvfHxuPyh0LnNldENvbnRlbnRUeXBlKCJhcHBsaWNhdGlvbi9qc29uIiwhMSksZHIoZSkpOmV9XSx0cmFuc2Zvcm1SZXNwb25zZTpbZnVuY3Rpb24oZSl7bGV0IHQ9dGhpcy50cmFuc2l0aW9uYWx8fFlBLnRyYW5zaXRpb25hbCxyPXQmJnQuZm9yY2VkSlNPTlBhcnNpbmcsbj10aGlzLnJlc3BvbnNlVHlwZT09PSJqc29uIjtpZihlJiZnLmlzU3RyaW5nKGUpJiYociYmIXRoaXMucmVzcG9uc2VUeXBlfHxuKSl7bGV0IGk9ISh0JiZ0LnNpbGVudEpTT05QYXJzaW5nKSYmbjt0cnl7cmV0dXJuIEpTT04ucGFyc2UoZSl9Y2F0Y2goQil7aWYoaSl0aHJvdyBCLm5hbWU9PT0iU3ludGF4RXJyb3IiP3AuZnJvbShCLHAuRVJSX0JBRF9SRVNQT05TRSx0aGlzLG51bGwsdGhpcy5yZXNwb25zZSk6Qn19cmV0dXJuIGV9XSx0aW1lb3V0OjAseHNyZkNvb2tpZU5hbWU6IlhTUkYtVE9LRU4iLHhzcmZIZWFkZXJOYW1lOiJYLVhTUkYtVE9LRU4iLG1heENvbnRlbnRMZW5ndGg6LTEsbWF4Qm9keUxlbmd0aDotMSxlbnY6e0Zvcm1EYXRhOmIuY2xhc3Nlcy5Gb3JtRGF0YSxCbG9iOmIuY2xhc3Nlcy5CbG9ifSx2YWxpZGF0ZVN0YXR1czpmdW5jdGlvbihlKXtyZXR1cm4gZT49MjAwJiZlPDMwMH0saGVhZGVyczp7Y29tbW9uOntBY2NlcHQ6ImFwcGxpY2F0aW9uL2pzb24sIHRleHQvcGxhaW4sICovKiIsIkNvbnRlbnQtVHlwZSI6dm9pZCAwfX19O2cuZm9yRWFjaChbImRlbGV0ZSIsImdldCIsImhlYWQiLCJwb3N0IiwicHV0IiwicGF0Y2giXSxBPT57WUEuaGVhZGVyc1tBXT17fX0pO3ZhciBqPVlBO3ZhciB5cj1nLnRvT2JqZWN0U2V0KFsiYWdlIiwiYXV0aG9yaXphdGlvbiIsImNvbnRlbnQtbGVuZ3RoIiwiY29udGVudC10eXBlIiwiZXRhZyIsImV4cGlyZXMiLCJmcm9tIiwiaG9zdCIsImlmLW1vZGlmaWVkLXNpbmNlIiwiaWYtdW5tb2RpZmllZC1zaW5jZSIsImxhc3QtbW9kaWZpZWQiLCJsb2NhdGlvbiIsIm1heC1mb3J3YXJkcyIsInByb3h5LWF1dGhvcml6YXRpb24iLCJyZWZlcmVyIiwicmV0cnktYWZ0ZXIiLCJ1c2VyLWFnZW50Il0pLFBlPUE9PntsZXQgZT17fSx0LHIsbjtyZXR1cm4gQSYmQS5zcGxpdChgCmApLmZvckVhY2goZnVuY3Rpb24oaSl7bj1pLmluZGV4T2YoIjoiKSx0PWkuc3Vic3RyaW5nKDAsbikudHJpbSgpLnRvTG93ZXJDYXNlKCkscj1pLnN1YnN0cmluZyhuKzEpLnRyaW0oKSwhKCF0fHxlW3RdJiZ5clt0XSkmJih0PT09InNldC1jb29raWUiP2VbdF0/ZVt0XS5wdXNoKHIpOmVbdF09W3JdOmVbdF09ZVt0XT9lW3RdKyIsICIrcjpyKX0pLGV9O3ZhciBHZT1TeW1ib2woImludGVybmFscyIpO2Z1bmN0aW9uIGVBKEEpe3JldHVybiBBJiZTdHJpbmcoQSkudHJpbSgpLnRvTG93ZXJDYXNlKCl9ZnVuY3Rpb24gZEEoQSl7cmV0dXJuIEE9PT0hMXx8QT09bnVsbD9BOmcuaXNBcnJheShBKT9BLm1hcChkQSk6U3RyaW5nKEEpfWZ1bmN0aW9uIGhyKEEpe2xldCBlPU9iamVjdC5jcmVhdGUobnVsbCksdD0vKFteXHMsOz1dKylccyooPzo9XHMqKFteLDtdKykpPy9nLHI7Zm9yKDtyPXQuZXhlYyhBKTspZVtyWzFdXT1yWzJdO3JldHVybiBlfXZhciB3cj1BPT4vXlstX2EtekEtWjAtOV5gfH4sISMkJSYnKisuXSskLy50ZXN0KEEudHJpbSgpKTtmdW5jdGlvbiBxQShBLGUsdCxyLG4pe2lmKGcuaXNGdW5jdGlvbihyKSlyZXR1cm4gci5jYWxsKHRoaXMsZSx0KTtpZihuJiYoZT10KSwhIWcuaXNTdHJpbmcoZSkpe2lmKGcuaXNTdHJpbmcocikpcmV0dXJuIGUuaW5kZXhPZihyKSE9PS0xO2lmKGcuaXNSZWdFeHAocikpcmV0dXJuIHIudGVzdChlKX19ZnVuY3Rpb24gRHIoQSl7cmV0dXJuIEEudHJpbSgpLnRvTG93ZXJDYXNlKCkucmVwbGFjZSgvKFthLXpcZF0pKFx3KikvZywoZSx0LHIpPT50LnRvVXBwZXJDYXNlKCkrcil9ZnVuY3Rpb24gU3IoQSxlKXtsZXQgdD1nLnRvQ2FtZWxDYXNlKCIgIitlKTtbImdldCIsInNldCIsImhhcyJdLmZvckVhY2gocj0+e09iamVjdC5kZWZpbmVQcm9wZXJ0eShBLHIrdCx7dmFsdWU6ZnVuY3Rpb24obixvLGkpe3JldHVybiB0aGlzW3JdLmNhbGwodGhpcyxlLG4sbyxpKX0sY29uZmlndXJhYmxlOiEwfSl9KX12YXIgdj1jbGFzc3tjb25zdHJ1Y3RvcihlKXtlJiZ0aGlzLnNldChlKX1zZXQoZSx0LHIpe2xldCBuPXRoaXM7ZnVuY3Rpb24gbyhCLHUsQyl7bGV0IHM9ZUEodSk7aWYoIXMpdGhyb3cgbmV3IEVycm9yKCJoZWFkZXIgbmFtZSBtdXN0IGJlIGEgbm9uLWVtcHR5IHN0cmluZyIpO2xldCBhPWcuZmluZEtleShuLHMpOyghYXx8blthXT09PXZvaWQgMHx8Qz09PSEwfHxDPT09dm9pZCAwJiZuW2FdIT09ITEpJiYoblthfHx1XT1kQShCKSl9bGV0IGk9KEIsdSk9PmcuZm9yRWFjaChCLChDLHMpPT5vKEMscyx1KSk7cmV0dXJuIGcuaXNQbGFpbk9iamVjdChlKXx8ZSBpbnN0YW5jZW9mIHRoaXMuY29uc3RydWN0b3I/aShlLHQpOmcuaXNTdHJpbmcoZSkmJihlPWUudHJpbSgpKSYmIXdyKGUpP2koUGUoZSksdCk6ZSE9bnVsbCYmbyh0LGUsciksdGhpc31nZXQoZSx0KXtpZihlPWVBKGUpLGUpe2xldCByPWcuZmluZEtleSh0aGlzLGUpO2lmKHIpe2xldCBuPXRoaXNbcl07aWYoIXQpcmV0dXJuIG47aWYodD09PSEwKXJldHVybiBocihuKTtpZihnLmlzRnVuY3Rpb24odCkpcmV0dXJuIHQuY2FsbCh0aGlzLG4scik7aWYoZy5pc1JlZ0V4cCh0KSlyZXR1cm4gdC5leGVjKG4pO3Rocm93IG5ldyBUeXBlRXJyb3IoInBhcnNlciBtdXN0IGJlIGJvb2xlYW58cmVnZXhwfGZ1bmN0aW9uIil9fX1oYXMoZSx0KXtpZihlPWVBKGUpLGUpe2xldCByPWcuZmluZEtleSh0aGlzLGUpO3JldHVybiEhKHImJnRoaXNbcl0hPT12b2lkIDAmJighdHx8cUEodGhpcyx0aGlzW3JdLHIsdCkpKX1yZXR1cm4hMX1kZWxldGUoZSx0KXtsZXQgcj10aGlzLG49ITE7ZnVuY3Rpb24gbyhpKXtpZihpPWVBKGkpLGkpe2xldCBCPWcuZmluZEtleShyLGkpO0ImJighdHx8cUEocixyW0JdLEIsdCkpJiYoZGVsZXRlIHJbQl0sbj0hMCl9fXJldHVybiBnLmlzQXJyYXkoZSk/ZS5mb3JFYWNoKG8pOm8oZSksbn1jbGVhcihlKXtsZXQgdD1PYmplY3Qua2V5cyh0aGlzKSxyPXQubGVuZ3RoLG49ITE7Zm9yKDtyLS07KXtsZXQgbz10W3JdOyghZXx8cUEodGhpcyx0aGlzW29dLG8sZSwhMCkpJiYoZGVsZXRlIHRoaXNbb10sbj0hMCl9cmV0dXJuIG59bm9ybWFsaXplKGUpe2xldCB0PXRoaXMscj17fTtyZXR1cm4gZy5mb3JFYWNoKHRoaXMsKG4sbyk9PntsZXQgaT1nLmZpbmRLZXkocixvKTtpZihpKXt0W2ldPWRBKG4pLGRlbGV0ZSB0W29dO3JldHVybn1sZXQgQj1lP0RyKG8pOlN0cmluZyhvKS50cmltKCk7QiE9PW8mJmRlbGV0ZSB0W29dLHRbQl09ZEEobikscltCXT0hMH0pLHRoaXN9Y29uY2F0KC4uLmUpe3JldHVybiB0aGlzLmNvbnN0cnVjdG9yLmNvbmNhdCh0aGlzLC4uLmUpfXRvSlNPTihlKXtsZXQgdD1PYmplY3QuY3JlYXRlKG51bGwpO3JldHVybiBnLmZvckVhY2godGhpcywocixuKT0+e3IhPW51bGwmJnIhPT0hMSYmKHRbbl09ZSYmZy5pc0FycmF5KHIpP3Iuam9pbigiLCAiKTpyKX0pLHR9W1N5bWJvbC5pdGVyYXRvcl0oKXtyZXR1cm4gT2JqZWN0LmVudHJpZXModGhpcy50b0pTT04oKSlbU3ltYm9sLml0ZXJhdG9yXSgpfXRvU3RyaW5nKCl7cmV0dXJuIE9iamVjdC5lbnRyaWVzKHRoaXMudG9KU09OKCkpLm1hcCgoW2UsdF0pPT5lKyI6ICIrdCkuam9pbihgCmApfWdldFtTeW1ib2wudG9TdHJpbmdUYWddKCl7cmV0dXJuIkF4aW9zSGVhZGVycyJ9c3RhdGljIGZyb20oZSl7cmV0dXJuIGUgaW5zdGFuY2VvZiB0aGlzP2U6bmV3IHRoaXMoZSl9c3RhdGljIGNvbmNhdChlLC4uLnQpe2xldCByPW5ldyB0aGlzKGUpO3JldHVybiB0LmZvckVhY2gobj0+ci5zZXQobikpLHJ9c3RhdGljIGFjY2Vzc29yKGUpe2xldCByPSh0aGlzW0dlXT10aGlzW0dlXT17YWNjZXNzb3JzOnt9fSkuYWNjZXNzb3JzLG49dGhpcy5wcm90b3R5cGU7ZnVuY3Rpb24gbyhpKXtsZXQgQj1lQShpKTtyW0JdfHwoU3IobixpKSxyW0JdPSEwKX1yZXR1cm4gZy5pc0FycmF5KGUpP2UuZm9yRWFjaChvKTpvKGUpLHRoaXN9fTt2LmFjY2Vzc29yKFsiQ29udGVudC1UeXBlIiwiQ29udGVudC1MZW5ndGgiLCJBY2NlcHQiLCJBY2NlcHQtRW5jb2RpbmciLCJVc2VyLUFnZW50IiwiQXV0aG9yaXphdGlvbiJdKTtnLnJlZHVjZURlc2NyaXB0b3JzKHYucHJvdG90eXBlLCh7dmFsdWU6QX0sZSk9PntsZXQgdD1lWzBdLnRvVXBwZXJDYXNlKCkrZS5zbGljZSgxKTtyZXR1cm57Z2V0OigpPT5BLHNldChyKXt0aGlzW3RdPXJ9fX0pO2cuZnJlZXplTWV0aG9kcyh2KTt2YXIgaz12O2Z1bmN0aW9uIHRBKEEsZSl7bGV0IHQ9dGhpc3x8aixyPWV8fHQsbj1rLmZyb20oci5oZWFkZXJzKSxvPXIuZGF0YTtyZXR1cm4gZy5mb3JFYWNoKEEsZnVuY3Rpb24oQil7bz1CLmNhbGwodCxvLG4ubm9ybWFsaXplKCksZT9lLnN0YXR1czp2b2lkIDApfSksbi5ub3JtYWxpemUoKSxvfWZ1bmN0aW9uIHJBKEEpe3JldHVybiEhKEEmJkEuX19DQU5DRUxfXyl9ZnVuY3Rpb24gT2UoQSxlLHQpe3AuY2FsbCh0aGlzLEE/PyJjYW5jZWxlZCIscC5FUlJfQ0FOQ0VMRUQsZSx0KSx0aGlzLm5hbWU9IkNhbmNlbGVkRXJyb3IifWcuaW5oZXJpdHMoT2UscCx7X19DQU5DRUxfXzohMH0pO3ZhciB4PU9lO2Z1bmN0aW9uIEtBKEEsZSx0KXtsZXQgcj10LmNvbmZpZy52YWxpZGF0ZVN0YXR1czshdC5zdGF0dXN8fCFyfHxyKHQuc3RhdHVzKT9BKHQpOmUobmV3IHAoIlJlcXVlc3QgZmFpbGVkIHdpdGggc3RhdHVzIGNvZGUgIit0LnN0YXR1cyxbcC5FUlJfQkFEX1JFUVVFU1QscC5FUlJfQkFEX1JFU1BPTlNFXVtNYXRoLmZsb29yKHQuc3RhdHVzLzEwMCktNF0sdC5jb25maWcsdC5yZXF1ZXN0LHQpKX12YXIgeGU9Yi5oYXNTdGFuZGFyZEJyb3dzZXJFbnY/e3dyaXRlKEEsZSx0LHIsbixvKXtsZXQgaT1bQSsiPSIrZW5jb2RlVVJJQ29tcG9uZW50KGUpXTtnLmlzTnVtYmVyKHQpJiZpLnB1c2goImV4cGlyZXM9IituZXcgRGF0ZSh0KS50b0dNVFN0cmluZygpKSxnLmlzU3RyaW5nKHIpJiZpLnB1c2goInBhdGg9IityKSxnLmlzU3RyaW5nKG4pJiZpLnB1c2goImRvbWFpbj0iK24pLG89PT0hMCYmaS5wdXNoKCJzZWN1cmUiKSxkb2N1bWVudC5jb29raWU9aS5qb2luKCI7ICIpfSxyZWFkKEEpe2xldCBlPWRvY3VtZW50LmNvb2tpZS5tYXRjaChuZXcgUmVnRXhwKCIoXnw7XFxzKikoIitBKyIpPShbXjtdKikiKSk7cmV0dXJuIGU/ZGVjb2RlVVJJQ29tcG9uZW50KGVbM10pOm51bGx9LHJlbW92ZShBKXt0aGlzLndyaXRlKEEsIiIsRGF0ZS5ub3coKS04NjRlNSl9fTp7d3JpdGUoKXt9LHJlYWQoKXtyZXR1cm4gbnVsbH0scmVtb3ZlKCl7fX07ZnVuY3Rpb24gakEoQSl7cmV0dXJuL14oW2Etel1bYS16XGQrXC0uXSo6KT9cL1wvL2kudGVzdChBKX1mdW5jdGlvbiB2QShBLGUpe3JldHVybiBlP0EucmVwbGFjZSgvXC8/XC8kLywiIikrIi8iK2UucmVwbGFjZSgvXlwvKy8sIiIpOkF9ZnVuY3Rpb24gb0EoQSxlKXtyZXR1cm4gQSYmIWpBKGUpP3ZBKEEsZSk6ZX12YXIgSmU9Yi5oYXNTdGFuZGFyZEJyb3dzZXJFbnY/ZnVuY3Rpb24oKXtsZXQgZT0vKG1zaWV8dHJpZGVudCkvaS50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpLHQ9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiYSIpLHI7ZnVuY3Rpb24gbihvKXtsZXQgaT1vO3JldHVybiBlJiYodC5zZXRBdHRyaWJ1dGUoImhyZWYiLGkpLGk9dC5ocmVmKSx0LnNldEF0dHJpYnV0ZSgiaHJlZiIsaSkse2hyZWY6dC5ocmVmLHByb3RvY29sOnQucHJvdG9jb2w/dC5wcm90b2NvbC5yZXBsYWNlKC86JC8sIiIpOiIiLGhvc3Q6dC5ob3N0LHNlYXJjaDp0LnNlYXJjaD90LnNlYXJjaC5yZXBsYWNlKC9eXD8vLCIiKToiIixoYXNoOnQuaGFzaD90Lmhhc2gucmVwbGFjZSgvXiMvLCIiKToiIixob3N0bmFtZTp0Lmhvc3RuYW1lLHBvcnQ6dC5wb3J0LHBhdGhuYW1lOnQucGF0aG5hbWUuY2hhckF0KDApPT09Ii8iP3QucGF0aG5hbWU6Ii8iK3QucGF0aG5hbWV9fXJldHVybiByPW4od2luZG93LmxvY2F0aW9uLmhyZWYpLGZ1bmN0aW9uKGkpe2xldCBCPWcuaXNTdHJpbmcoaSk/bihpKTppO3JldHVybiBCLnByb3RvY29sPT09ci5wcm90b2NvbCYmQi5ob3N0PT09ci5ob3N0fX0oKTpmdW5jdGlvbigpe3JldHVybiBmdW5jdGlvbigpe3JldHVybiEwfX0oKTtmdW5jdGlvbiBfQShBKXtsZXQgZT0vXihbLStcd117MSwyNX0pKDo/XC9cL3w6KS8uZXhlYyhBKTtyZXR1cm4gZSYmZVsxXXx8IiJ9ZnVuY3Rpb24gUnIoQSxlKXtBPUF8fDEwO2xldCB0PW5ldyBBcnJheShBKSxyPW5ldyBBcnJheShBKSxuPTAsbz0wLGk7cmV0dXJuIGU9ZSE9PXZvaWQgMD9lOjFlMyxmdW5jdGlvbih1KXtsZXQgQz1EYXRlLm5vdygpLHM9cltvXTtpfHwoaT1DKSx0W25dPXUscltuXT1DO2xldCBhPW8sYz0wO2Zvcig7YSE9PW47KWMrPXRbYSsrXSxhPWElQTtpZihuPShuKzEpJUEsbj09PW8mJihvPShvKzEpJUEpLEMtaTxlKXJldHVybjtsZXQgST1zJiZDLXM7cmV0dXJuIEk/TWF0aC5yb3VuZChjKjFlMy9JKTp2b2lkIDB9fXZhciBXZT1ScjtmdW5jdGlvbiBIZShBLGUpe2xldCB0PTAscj1XZSg1MCwyNTApO3JldHVybiBuPT57bGV0IG89bi5sb2FkZWQsaT1uLmxlbmd0aENvbXB1dGFibGU/bi50b3RhbDp2b2lkIDAsQj1vLXQsdT1yKEIpLEM9bzw9aTt0PW87bGV0IHM9e2xvYWRlZDpvLHRvdGFsOmkscHJvZ3Jlc3M6aT9vL2k6dm9pZCAwLGJ5dGVzOkIscmF0ZTp1fHx2b2lkIDAsZXN0aW1hdGVkOnUmJmkmJkM/KGktbykvdTp2b2lkIDAsZXZlbnQ6bn07c1tlPyJkb3dubG9hZCI6InVwbG9hZCJdPSEwLEEocyl9fXZhciBicj10eXBlb2YgWE1MSHR0cFJlcXVlc3Q8InUiLE1lPWJyJiZmdW5jdGlvbihBKXtyZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24odCxyKXtsZXQgbj1BLmRhdGEsbz1rLmZyb20oQS5oZWFkZXJzKS5ub3JtYWxpemUoKSx7cmVzcG9uc2VUeXBlOmksd2l0aFhTUkZUb2tlbjpCfT1BLHU7ZnVuY3Rpb24gQygpe0EuY2FuY2VsVG9rZW4mJkEuY2FuY2VsVG9rZW4udW5zdWJzY3JpYmUodSksQS5zaWduYWwmJkEuc2lnbmFsLnJlbW92ZUV2ZW50TGlzdGVuZXIoImFib3J0Iix1KX1sZXQgcztpZihnLmlzRm9ybURhdGEobikpe2lmKGIuaGFzU3RhbmRhcmRCcm93c2VyRW52fHxiLmhhc1N0YW5kYXJkQnJvd3NlcldlYldvcmtlckVudilvLnNldENvbnRlbnRUeXBlKCExKTtlbHNlIGlmKChzPW8uZ2V0Q29udGVudFR5cGUoKSkhPT0hMSl7bGV0W2YsLi4uUV09cz9zLnNwbGl0KCI7IikubWFwKG09Pm0udHJpbSgpKS5maWx0ZXIoQm9vbGVhbik6W107by5zZXRDb250ZW50VHlwZShbZnx8Im11bHRpcGFydC9mb3JtLWRhdGEiLC4uLlFdLmpvaW4oIjsgIikpfX1sZXQgYT1uZXcgWE1MSHR0cFJlcXVlc3Q7aWYoQS5hdXRoKXtsZXQgZj1BLmF1dGgudXNlcm5hbWV8fCIiLFE9QS5hdXRoLnBhc3N3b3JkP3VuZXNjYXBlKGVuY29kZVVSSUNvbXBvbmVudChBLmF1dGgucGFzc3dvcmQpKToiIjtvLnNldCgiQXV0aG9yaXphdGlvbiIsIkJhc2ljICIrYnRvYShmKyI6IitRKSl9bGV0IGM9b0EoQS5iYXNlVVJMLEEudXJsKTthLm9wZW4oQS5tZXRob2QudG9VcHBlckNhc2UoKSxBQShjLEEucGFyYW1zLEEucGFyYW1zU2VyaWFsaXplciksITApLGEudGltZW91dD1BLnRpbWVvdXQ7ZnVuY3Rpb24gSSgpe2lmKCFhKXJldHVybjtsZXQgZj1rLmZyb20oImdldEFsbFJlc3BvbnNlSGVhZGVycyJpbiBhJiZhLmdldEFsbFJlc3BvbnNlSGVhZGVycygpKSxtPXtkYXRhOiFpfHxpPT09InRleHQifHxpPT09Impzb24iP2EucmVzcG9uc2VUZXh0OmEucmVzcG9uc2Usc3RhdHVzOmEuc3RhdHVzLHN0YXR1c1RleHQ6YS5zdGF0dXNUZXh0LGhlYWRlcnM6Zixjb25maWc6QSxyZXF1ZXN0OmF9O0tBKGZ1bmN0aW9uKE4pe3QoTiksQygpfSxmdW5jdGlvbihOKXtyKE4pLEMoKX0sbSksYT1udWxsfWlmKCJvbmxvYWRlbmQiaW4gYT9hLm9ubG9hZGVuZD1JOmEub25yZWFkeXN0YXRlY2hhbmdlPWZ1bmN0aW9uKCl7IWF8fGEucmVhZHlTdGF0ZSE9PTR8fGEuc3RhdHVzPT09MCYmIShhLnJlc3BvbnNlVVJMJiZhLnJlc3BvbnNlVVJMLmluZGV4T2YoImZpbGU6Iik9PT0wKXx8c2V0VGltZW91dChJKX0sYS5vbmFib3J0PWZ1bmN0aW9uKCl7YSYmKHIobmV3IHAoIlJlcXVlc3QgYWJvcnRlZCIscC5FQ09OTkFCT1JURUQsQSxhKSksYT1udWxsKX0sYS5vbmVycm9yPWZ1bmN0aW9uKCl7cihuZXcgcCgiTmV0d29yayBFcnJvciIscC5FUlJfTkVUV09SSyxBLGEpKSxhPW51bGx9LGEub250aW1lb3V0PWZ1bmN0aW9uKCl7bGV0IFE9QS50aW1lb3V0PyJ0aW1lb3V0IG9mICIrQS50aW1lb3V0KyJtcyBleGNlZWRlZCI6InRpbWVvdXQgZXhjZWVkZWQiLG09QS50cmFuc2l0aW9uYWx8fHBBO0EudGltZW91dEVycm9yTWVzc2FnZSYmKFE9QS50aW1lb3V0RXJyb3JNZXNzYWdlKSxyKG5ldyBwKFEsbS5jbGFyaWZ5VGltZW91dEVycm9yP3AuRVRJTUVET1VUOnAuRUNPTk5BQk9SVEVELEEsYSkpLGE9bnVsbH0sYi5oYXNTdGFuZGFyZEJyb3dzZXJFbnYmJihCJiZnLmlzRnVuY3Rpb24oQikmJihCPUIoQSkpLEJ8fEIhPT0hMSYmSmUoYykpKXtsZXQgZj1BLnhzcmZIZWFkZXJOYW1lJiZBLnhzcmZDb29raWVOYW1lJiZ4ZS5yZWFkKEEueHNyZkNvb2tpZU5hbWUpO2YmJm8uc2V0KEEueHNyZkhlYWRlck5hbWUsZil9bj09PXZvaWQgMCYmby5zZXRDb250ZW50VHlwZShudWxsKSwic2V0UmVxdWVzdEhlYWRlciJpbiBhJiZnLmZvckVhY2goby50b0pTT04oKSxmdW5jdGlvbihRLG0pe2Euc2V0UmVxdWVzdEhlYWRlcihtLFEpfSksZy5pc1VuZGVmaW5lZChBLndpdGhDcmVkZW50aWFscyl8fChhLndpdGhDcmVkZW50aWFscz0hIUEud2l0aENyZWRlbnRpYWxzKSxpJiZpIT09Impzb24iJiYoYS5yZXNwb25zZVR5cGU9QS5yZXNwb25zZVR5cGUpLHR5cGVvZiBBLm9uRG93bmxvYWRQcm9ncmVzcz09ImZ1bmN0aW9uIiYmYS5hZGRFdmVudExpc3RlbmVyKCJwcm9ncmVzcyIsSGUoQS5vbkRvd25sb2FkUHJvZ3Jlc3MsITApKSx0eXBlb2YgQS5vblVwbG9hZFByb2dyZXNzPT0iZnVuY3Rpb24iJiZhLnVwbG9hZCYmYS51cGxvYWQuYWRkRXZlbnRMaXN0ZW5lcigicHJvZ3Jlc3MiLEhlKEEub25VcGxvYWRQcm9ncmVzcykpLChBLmNhbmNlbFRva2VufHxBLnNpZ25hbCkmJih1PWY9PnthJiYocighZnx8Zi50eXBlP25ldyB4KG51bGwsQSxhKTpmKSxhLmFib3J0KCksYT1udWxsKX0sQS5jYW5jZWxUb2tlbiYmQS5jYW5jZWxUb2tlbi5zdWJzY3JpYmUodSksQS5zaWduYWwmJihBLnNpZ25hbC5hYm9ydGVkP3UoKTpBLnNpZ25hbC5hZGRFdmVudExpc3RlbmVyKCJhYm9ydCIsdSkpKTtsZXQgbD1fQShjKTtpZihsJiZiLnByb3RvY29scy5pbmRleE9mKGwpPT09LTEpe3IobmV3IHAoIlVuc3VwcG9ydGVkIHByb3RvY29sICIrbCsiOiIscC5FUlJfQkFEX1JFUVVFU1QsQSkpO3JldHVybn1hLnNlbmQobnx8bnVsbCl9KX07dmFyIHpBPXtodHRwOkVBLHhocjpNZX07Zy5mb3JFYWNoKHpBLChBLGUpPT57aWYoQSl7dHJ5e09iamVjdC5kZWZpbmVQcm9wZXJ0eShBLCJuYW1lIix7dmFsdWU6ZX0pfWNhdGNoe31PYmplY3QuZGVmaW5lUHJvcGVydHkoQSwiYWRhcHRlck5hbWUiLHt2YWx1ZTplfSl9fSk7dmFyIFllPUE9PmAtICR7QX1gLGtyPUE9PmcuaXNGdW5jdGlvbihBKXx8QT09PW51bGx8fEE9PT0hMSx5QT17Z2V0QWRhcHRlcjpBPT57QT1nLmlzQXJyYXkoQSk/QTpbQV07bGV0e2xlbmd0aDplfT1BLHQscixuPXt9O2ZvcihsZXQgbz0wO288ZTtvKyspe3Q9QVtvXTtsZXQgaTtpZihyPXQsIWtyKHQpJiYocj16QVsoaT1TdHJpbmcodCkpLnRvTG93ZXJDYXNlKCldLHI9PT12b2lkIDApKXRocm93IG5ldyBwKGBVbmtub3duIGFkYXB0ZXIgJyR7aX0nYCk7aWYocilicmVhaztuW2l8fCIjIitvXT1yfWlmKCFyKXtsZXQgbz1PYmplY3QuZW50cmllcyhuKS5tYXAoKFtCLHVdKT0+YGFkYXB0ZXIgJHtCfSBgKyh1PT09ITE/ImlzIG5vdCBzdXBwb3J0ZWQgYnkgdGhlIGVudmlyb25tZW50IjoiaXMgbm90IGF2YWlsYWJsZSBpbiB0aGUgYnVpbGQiKSksaT1lP28ubGVuZ3RoPjE/YHNpbmNlIDoKYCtvLm1hcChZZSkuam9pbihgCmApOiIgIitZZShvWzBdKToiYXMgbm8gYWRhcHRlciBzcGVjaWZpZWQiO3Rocm93IG5ldyBwKCJUaGVyZSBpcyBubyBzdWl0YWJsZSBhZGFwdGVyIHRvIGRpc3BhdGNoIHRoZSByZXF1ZXN0ICIraSwiRVJSX05PVF9TVVBQT1JUIil9cmV0dXJuIHJ9LGFkYXB0ZXJzOnpBfTtmdW5jdGlvbiBWQShBKXtpZihBLmNhbmNlbFRva2VuJiZBLmNhbmNlbFRva2VuLnRocm93SWZSZXF1ZXN0ZWQoKSxBLnNpZ25hbCYmQS5zaWduYWwuYWJvcnRlZCl0aHJvdyBuZXcgeChudWxsLEEpfWZ1bmN0aW9uIGhBKEEpe3JldHVybiBWQShBKSxBLmhlYWRlcnM9ay5mcm9tKEEuaGVhZGVycyksQS5kYXRhPXRBLmNhbGwoQSxBLnRyYW5zZm9ybVJlcXVlc3QpLFsicG9zdCIsInB1dCIsInBhdGNoIl0uaW5kZXhPZihBLm1ldGhvZCkhPT0tMSYmQS5oZWFkZXJzLnNldENvbnRlbnRUeXBlKCJhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQiLCExKSx5QS5nZXRBZGFwdGVyKEEuYWRhcHRlcnx8ai5hZGFwdGVyKShBKS50aGVuKGZ1bmN0aW9uKHIpe3JldHVybiBWQShBKSxyLmRhdGE9dEEuY2FsbChBLEEudHJhbnNmb3JtUmVzcG9uc2Usciksci5oZWFkZXJzPWsuZnJvbShyLmhlYWRlcnMpLHJ9LGZ1bmN0aW9uKHIpe3JldHVybiByQShyKXx8KFZBKEEpLHImJnIucmVzcG9uc2UmJihyLnJlc3BvbnNlLmRhdGE9dEEuY2FsbChBLEEudHJhbnNmb3JtUmVzcG9uc2Usci5yZXNwb25zZSksci5yZXNwb25zZS5oZWFkZXJzPWsuZnJvbShyLnJlc3BvbnNlLmhlYWRlcnMpKSksUHJvbWlzZS5yZWplY3Qocil9KX12YXIgcWU9QT0+QSBpbnN0YW5jZW9mIGs/ey4uLkF9OkE7ZnVuY3Rpb24gRyhBLGUpe2U9ZXx8e307bGV0IHQ9e307ZnVuY3Rpb24gcihDLHMsYSl7cmV0dXJuIGcuaXNQbGFpbk9iamVjdChDKSYmZy5pc1BsYWluT2JqZWN0KHMpP2cubWVyZ2UuY2FsbCh7Y2FzZWxlc3M6YX0sQyxzKTpnLmlzUGxhaW5PYmplY3Qocyk/Zy5tZXJnZSh7fSxzKTpnLmlzQXJyYXkocyk/cy5zbGljZSgpOnN9ZnVuY3Rpb24gbihDLHMsYSl7aWYoZy5pc1VuZGVmaW5lZChzKSl7aWYoIWcuaXNVbmRlZmluZWQoQykpcmV0dXJuIHIodm9pZCAwLEMsYSl9ZWxzZSByZXR1cm4gcihDLHMsYSl9ZnVuY3Rpb24gbyhDLHMpe2lmKCFnLmlzVW5kZWZpbmVkKHMpKXJldHVybiByKHZvaWQgMCxzKX1mdW5jdGlvbiBpKEMscyl7aWYoZy5pc1VuZGVmaW5lZChzKSl7aWYoIWcuaXNVbmRlZmluZWQoQykpcmV0dXJuIHIodm9pZCAwLEMpfWVsc2UgcmV0dXJuIHIodm9pZCAwLHMpfWZ1bmN0aW9uIEIoQyxzLGEpe2lmKGEgaW4gZSlyZXR1cm4gcihDLHMpO2lmKGEgaW4gQSlyZXR1cm4gcih2b2lkIDAsQyl9bGV0IHU9e3VybDpvLG1ldGhvZDpvLGRhdGE6byxiYXNlVVJMOmksdHJhbnNmb3JtUmVxdWVzdDppLHRyYW5zZm9ybVJlc3BvbnNlOmkscGFyYW1zU2VyaWFsaXplcjppLHRpbWVvdXQ6aSx0aW1lb3V0TWVzc2FnZTppLHdpdGhDcmVkZW50aWFsczppLHdpdGhYU1JGVG9rZW46aSxhZGFwdGVyOmkscmVzcG9uc2VUeXBlOmkseHNyZkNvb2tpZU5hbWU6aSx4c3JmSGVhZGVyTmFtZTppLG9uVXBsb2FkUHJvZ3Jlc3M6aSxvbkRvd25sb2FkUHJvZ3Jlc3M6aSxkZWNvbXByZXNzOmksbWF4Q29udGVudExlbmd0aDppLG1heEJvZHlMZW5ndGg6aSxiZWZvcmVSZWRpcmVjdDppLHRyYW5zcG9ydDppLGh0dHBBZ2VudDppLGh0dHBzQWdlbnQ6aSxjYW5jZWxUb2tlbjppLHNvY2tldFBhdGg6aSxyZXNwb25zZUVuY29kaW5nOmksdmFsaWRhdGVTdGF0dXM6QixoZWFkZXJzOihDLHMpPT5uKHFlKEMpLHFlKHMpLCEwKX07cmV0dXJuIGcuZm9yRWFjaChPYmplY3Qua2V5cyhPYmplY3QuYXNzaWduKHt9LEEsZSkpLGZ1bmN0aW9uKHMpe2xldCBhPXVbc118fG4sYz1hKEFbc10sZVtzXSxzKTtnLmlzVW5kZWZpbmVkKGMpJiZhIT09Qnx8KHRbc109Yyl9KSx0fXZhciB3QT0iMS42LjgiO3ZhciBaQT17fTtbIm9iamVjdCIsImJvb2xlYW4iLCJudW1iZXIiLCJmdW5jdGlvbiIsInN0cmluZyIsInN5bWJvbCJdLmZvckVhY2goKEEsZSk9PntaQVtBXT1mdW5jdGlvbihyKXtyZXR1cm4gdHlwZW9mIHI9PT1BfHwiYSIrKGU8MT8ibiAiOiIgIikrQX19KTt2YXIgS2U9e307WkEudHJhbnNpdGlvbmFsPWZ1bmN0aW9uKGUsdCxyKXtmdW5jdGlvbiBuKG8saSl7cmV0dXJuIltBeGlvcyB2Iit3QSsiXSBUcmFuc2l0aW9uYWwgb3B0aW9uICciK28rIiciK2krKHI/Ii4gIityOiIiKX1yZXR1cm4obyxpLEIpPT57aWYoZT09PSExKXRocm93IG5ldyBwKG4oaSwiIGhhcyBiZWVuIHJlbW92ZWQiKyh0PyIgaW4gIit0OiIiKSkscC5FUlJfREVQUkVDQVRFRCk7cmV0dXJuIHQmJiFLZVtpXSYmKEtlW2ldPSEwLGNvbnNvbGUud2FybihuKGksIiBoYXMgYmVlbiBkZXByZWNhdGVkIHNpbmNlIHYiK3QrIiBhbmQgd2lsbCBiZSByZW1vdmVkIGluIHRoZSBuZWFyIGZ1dHVyZSIpKSksZT9lKG8saSxCKTohMH19O2Z1bmN0aW9uIEZyKEEsZSx0KXtpZih0eXBlb2YgQSE9Im9iamVjdCIpdGhyb3cgbmV3IHAoIm9wdGlvbnMgbXVzdCBiZSBhbiBvYmplY3QiLHAuRVJSX0JBRF9PUFRJT05fVkFMVUUpO2xldCByPU9iamVjdC5rZXlzKEEpLG49ci5sZW5ndGg7Zm9yKDtuLS0gPjA7KXtsZXQgbz1yW25dLGk9ZVtvXTtpZihpKXtsZXQgQj1BW29dLHU9Qj09PXZvaWQgMHx8aShCLG8sQSk7aWYodSE9PSEwKXRocm93IG5ldyBwKCJvcHRpb24gIitvKyIgbXVzdCBiZSAiK3UscC5FUlJfQkFEX09QVElPTl9WQUxVRSk7Y29udGludWV9aWYodCE9PSEwKXRocm93IG5ldyBwKCJVbmtub3duIG9wdGlvbiAiK28scC5FUlJfQkFEX09QVElPTil9fXZhciBEQT17YXNzZXJ0T3B0aW9uczpGcix2YWxpZGF0b3JzOlpBfTt2YXIgSj1EQS52YWxpZGF0b3JzLF89Y2xhc3N7Y29uc3RydWN0b3IoZSl7dGhpcy5kZWZhdWx0cz1lLHRoaXMuaW50ZXJjZXB0b3JzPXtyZXF1ZXN0Om5ldyBXQSxyZXNwb25zZTpuZXcgV0F9fWFzeW5jIHJlcXVlc3QoZSx0KXt0cnl7cmV0dXJuIGF3YWl0IHRoaXMuX3JlcXVlc3QoZSx0KX1jYXRjaChyKXtpZihyIGluc3RhbmNlb2YgRXJyb3Ipe2xldCBuO0Vycm9yLmNhcHR1cmVTdGFja1RyYWNlP0Vycm9yLmNhcHR1cmVTdGFja1RyYWNlKG49e30pOm49bmV3IEVycm9yO2xldCBvPW4uc3RhY2s/bi5zdGFjay5yZXBsYWNlKC9eLitcbi8sIiIpOiIiO3Iuc3RhY2s/byYmIVN0cmluZyhyLnN0YWNrKS5lbmRzV2l0aChvLnJlcGxhY2UoL14uK1xuLitcbi8sIiIpKSYmKHIuc3RhY2srPWAKYCtvKTpyLnN0YWNrPW99dGhyb3cgcn19X3JlcXVlc3QoZSx0KXt0eXBlb2YgZT09InN0cmluZyI/KHQ9dHx8e30sdC51cmw9ZSk6dD1lfHx7fSx0PUcodGhpcy5kZWZhdWx0cyx0KTtsZXR7dHJhbnNpdGlvbmFsOnIscGFyYW1zU2VyaWFsaXplcjpuLGhlYWRlcnM6b309dDtyIT09dm9pZCAwJiZEQS5hc3NlcnRPcHRpb25zKHIse3NpbGVudEpTT05QYXJzaW5nOkoudHJhbnNpdGlvbmFsKEouYm9vbGVhbiksZm9yY2VkSlNPTlBhcnNpbmc6Si50cmFuc2l0aW9uYWwoSi5ib29sZWFuKSxjbGFyaWZ5VGltZW91dEVycm9yOkoudHJhbnNpdGlvbmFsKEouYm9vbGVhbil9LCExKSxuIT1udWxsJiYoZy5pc0Z1bmN0aW9uKG4pP3QucGFyYW1zU2VyaWFsaXplcj17c2VyaWFsaXplOm59OkRBLmFzc2VydE9wdGlvbnMobix7ZW5jb2RlOkouZnVuY3Rpb24sc2VyaWFsaXplOkouZnVuY3Rpb259LCEwKSksdC5tZXRob2Q9KHQubWV0aG9kfHx0aGlzLmRlZmF1bHRzLm1ldGhvZHx8ImdldCIpLnRvTG93ZXJDYXNlKCk7bGV0IGk9byYmZy5tZXJnZShvLmNvbW1vbixvW3QubWV0aG9kXSk7byYmZy5mb3JFYWNoKFsiZGVsZXRlIiwiZ2V0IiwiaGVhZCIsInBvc3QiLCJwdXQiLCJwYXRjaCIsImNvbW1vbiJdLGw9PntkZWxldGUgb1tsXX0pLHQuaGVhZGVycz1rLmNvbmNhdChpLG8pO2xldCBCPVtdLHU9ITA7dGhpcy5pbnRlcmNlcHRvcnMucmVxdWVzdC5mb3JFYWNoKGZ1bmN0aW9uKGYpe3R5cGVvZiBmLnJ1bldoZW49PSJmdW5jdGlvbiImJmYucnVuV2hlbih0KT09PSExfHwodT11JiZmLnN5bmNocm9ub3VzLEIudW5zaGlmdChmLmZ1bGZpbGxlZCxmLnJlamVjdGVkKSl9KTtsZXQgQz1bXTt0aGlzLmludGVyY2VwdG9ycy5yZXNwb25zZS5mb3JFYWNoKGZ1bmN0aW9uKGYpe0MucHVzaChmLmZ1bGZpbGxlZCxmLnJlamVjdGVkKX0pO2xldCBzLGE9MCxjO2lmKCF1KXtsZXQgbD1baEEuYmluZCh0aGlzKSx2b2lkIDBdO2ZvcihsLnVuc2hpZnQuYXBwbHkobCxCKSxsLnB1c2guYXBwbHkobCxDKSxjPWwubGVuZ3RoLHM9UHJvbWlzZS5yZXNvbHZlKHQpO2E8Yzspcz1zLnRoZW4obFthKytdLGxbYSsrXSk7cmV0dXJuIHN9Yz1CLmxlbmd0aDtsZXQgST10O2ZvcihhPTA7YTxjOyl7bGV0IGw9QlthKytdLGY9QlthKytdO3RyeXtJPWwoSSl9Y2F0Y2goUSl7Zi5jYWxsKHRoaXMsUSk7YnJlYWt9fXRyeXtzPWhBLmNhbGwodGhpcyxJKX1jYXRjaChsKXtyZXR1cm4gUHJvbWlzZS5yZWplY3QobCl9Zm9yKGE9MCxjPUMubGVuZ3RoO2E8Yzspcz1zLnRoZW4oQ1thKytdLENbYSsrXSk7cmV0dXJuIHN9Z2V0VXJpKGUpe2U9Ryh0aGlzLmRlZmF1bHRzLGUpO2xldCB0PW9BKGUuYmFzZVVSTCxlLnVybCk7cmV0dXJuIEFBKHQsZS5wYXJhbXMsZS5wYXJhbXNTZXJpYWxpemVyKX19O2cuZm9yRWFjaChbImRlbGV0ZSIsImdldCIsImhlYWQiLCJvcHRpb25zIl0sZnVuY3Rpb24oZSl7Xy5wcm90b3R5cGVbZV09ZnVuY3Rpb24odCxyKXtyZXR1cm4gdGhpcy5yZXF1ZXN0KEcocnx8e30se21ldGhvZDplLHVybDp0LGRhdGE6KHJ8fHt9KS5kYXRhfSkpfX0pO2cuZm9yRWFjaChbInBvc3QiLCJwdXQiLCJwYXRjaCJdLGZ1bmN0aW9uKGUpe2Z1bmN0aW9uIHQocil7cmV0dXJuIGZ1bmN0aW9uKG8saSxCKXtyZXR1cm4gdGhpcy5yZXF1ZXN0KEcoQnx8e30se21ldGhvZDplLGhlYWRlcnM6cj97IkNvbnRlbnQtVHlwZSI6Im11bHRpcGFydC9mb3JtLWRhdGEifTp7fSx1cmw6byxkYXRhOml9KSl9fV8ucHJvdG90eXBlW2VdPXQoKSxfLnByb3RvdHlwZVtlKyJGb3JtIl09dCghMCl9KTt2YXIgbkE9Xzt2YXIgWEE9Y2xhc3MgQXtjb25zdHJ1Y3RvcihlKXtpZih0eXBlb2YgZSE9ImZ1bmN0aW9uIil0aHJvdyBuZXcgVHlwZUVycm9yKCJleGVjdXRvciBtdXN0IGJlIGEgZnVuY3Rpb24uIik7bGV0IHQ7dGhpcy5wcm9taXNlPW5ldyBQcm9taXNlKGZ1bmN0aW9uKG8pe3Q9b30pO2xldCByPXRoaXM7dGhpcy5wcm9taXNlLnRoZW4obj0+e2lmKCFyLl9saXN0ZW5lcnMpcmV0dXJuO2xldCBvPXIuX2xpc3RlbmVycy5sZW5ndGg7Zm9yKDtvLS0gPjA7KXIuX2xpc3RlbmVyc1tvXShuKTtyLl9saXN0ZW5lcnM9bnVsbH0pLHRoaXMucHJvbWlzZS50aGVuPW49PntsZXQgbyxpPW5ldyBQcm9taXNlKEI9PntyLnN1YnNjcmliZShCKSxvPUJ9KS50aGVuKG4pO3JldHVybiBpLmNhbmNlbD1mdW5jdGlvbigpe3IudW5zdWJzY3JpYmUobyl9LGl9LGUoZnVuY3Rpb24obyxpLEIpe3IucmVhc29ufHwoci5yZWFzb249bmV3IHgobyxpLEIpLHQoci5yZWFzb24pKX0pfXRocm93SWZSZXF1ZXN0ZWQoKXtpZih0aGlzLnJlYXNvbil0aHJvdyB0aGlzLnJlYXNvbn1zdWJzY3JpYmUoZSl7aWYodGhpcy5yZWFzb24pe2UodGhpcy5yZWFzb24pO3JldHVybn10aGlzLl9saXN0ZW5lcnM/dGhpcy5fbGlzdGVuZXJzLnB1c2goZSk6dGhpcy5fbGlzdGVuZXJzPVtlXX11bnN1YnNjcmliZShlKXtpZighdGhpcy5fbGlzdGVuZXJzKXJldHVybjtsZXQgdD10aGlzLl9saXN0ZW5lcnMuaW5kZXhPZihlKTt0IT09LTEmJnRoaXMuX2xpc3RlbmVycy5zcGxpY2UodCwxKX1zdGF0aWMgc291cmNlKCl7bGV0IGU7cmV0dXJue3Rva2VuOm5ldyBBKGZ1bmN0aW9uKG4pe2U9bn0pLGNhbmNlbDplfX19LGplPVhBO2Z1bmN0aW9uICRBKEEpe3JldHVybiBmdW5jdGlvbih0KXtyZXR1cm4gQS5hcHBseShudWxsLHQpfX1mdW5jdGlvbiBBZShBKXtyZXR1cm4gZy5pc09iamVjdChBKSYmQS5pc0F4aW9zRXJyb3I9PT0hMH12YXIgZWU9e0NvbnRpbnVlOjEwMCxTd2l0Y2hpbmdQcm90b2NvbHM6MTAxLFByb2Nlc3Npbmc6MTAyLEVhcmx5SGludHM6MTAzLE9rOjIwMCxDcmVhdGVkOjIwMSxBY2NlcHRlZDoyMDIsTm9uQXV0aG9yaXRhdGl2ZUluZm9ybWF0aW9uOjIwMyxOb0NvbnRlbnQ6MjA0LFJlc2V0Q29udGVudDoyMDUsUGFydGlhbENvbnRlbnQ6MjA2LE11bHRpU3RhdHVzOjIwNyxBbHJlYWR5UmVwb3J0ZWQ6MjA4LEltVXNlZDoyMjYsTXVsdGlwbGVDaG9pY2VzOjMwMCxNb3ZlZFBlcm1hbmVudGx5OjMwMSxGb3VuZDozMDIsU2VlT3RoZXI6MzAzLE5vdE1vZGlmaWVkOjMwNCxVc2VQcm94eTozMDUsVW51c2VkOjMwNixUZW1wb3JhcnlSZWRpcmVjdDozMDcsUGVybWFuZW50UmVkaXJlY3Q6MzA4LEJhZFJlcXVlc3Q6NDAwLFVuYXV0aG9yaXplZDo0MDEsUGF5bWVudFJlcXVpcmVkOjQwMixGb3JiaWRkZW46NDAzLE5vdEZvdW5kOjQwNCxNZXRob2ROb3RBbGxvd2VkOjQwNSxOb3RBY2NlcHRhYmxlOjQwNixQcm94eUF1dGhlbnRpY2F0aW9uUmVxdWlyZWQ6NDA3LFJlcXVlc3RUaW1lb3V0OjQwOCxDb25mbGljdDo0MDksR29uZTo0MTAsTGVuZ3RoUmVxdWlyZWQ6NDExLFByZWNvbmRpdGlvbkZhaWxlZDo0MTIsUGF5bG9hZFRvb0xhcmdlOjQxMyxVcmlUb29Mb25nOjQxNCxVbnN1cHBvcnRlZE1lZGlhVHlwZTo0MTUsUmFuZ2VOb3RTYXRpc2ZpYWJsZTo0MTYsRXhwZWN0YXRpb25GYWlsZWQ6NDE3LEltQVRlYXBvdDo0MTgsTWlzZGlyZWN0ZWRSZXF1ZXN0OjQyMSxVbnByb2Nlc3NhYmxlRW50aXR5OjQyMixMb2NrZWQ6NDIzLEZhaWxlZERlcGVuZGVuY3k6NDI0LFRvb0Vhcmx5OjQyNSxVcGdyYWRlUmVxdWlyZWQ6NDI2LFByZWNvbmRpdGlvblJlcXVpcmVkOjQyOCxUb29NYW55UmVxdWVzdHM6NDI5LFJlcXVlc3RIZWFkZXJGaWVsZHNUb29MYXJnZTo0MzEsVW5hdmFpbGFibGVGb3JMZWdhbFJlYXNvbnM6NDUxLEludGVybmFsU2VydmVyRXJyb3I6NTAwLE5vdEltcGxlbWVudGVkOjUwMSxCYWRHYXRld2F5OjUwMixTZXJ2aWNlVW5hdmFpbGFibGU6NTAzLEdhdGV3YXlUaW1lb3V0OjUwNCxIdHRwVmVyc2lvbk5vdFN1cHBvcnRlZDo1MDUsVmFyaWFudEFsc29OZWdvdGlhdGVzOjUwNixJbnN1ZmZpY2llbnRTdG9yYWdlOjUwNyxMb29wRGV0ZWN0ZWQ6NTA4LE5vdEV4dGVuZGVkOjUxMCxOZXR3b3JrQXV0aGVudGljYXRpb25SZXF1aXJlZDo1MTF9O09iamVjdC5lbnRyaWVzKGVlKS5mb3JFYWNoKChbQSxlXSk9PntlZVtlXT1BfSk7dmFyIHZlPWVlO2Z1bmN0aW9uIF9lKEEpe2xldCBlPW5ldyBuQShBKSx0PVoobkEucHJvdG90eXBlLnJlcXVlc3QsZSk7cmV0dXJuIGcuZXh0ZW5kKHQsbkEucHJvdG90eXBlLGUse2FsbE93bktleXM6ITB9KSxnLmV4dGVuZCh0LGUsbnVsbCx7YWxsT3duS2V5czohMH0pLHQuY3JlYXRlPWZ1bmN0aW9uKG4pe3JldHVybiBfZShHKEEsbikpfSx0fXZhciBEPV9lKGopO0QuQXhpb3M9bkE7RC5DYW5jZWxlZEVycm9yPXg7RC5DYW5jZWxUb2tlbj1qZTtELmlzQ2FuY2VsPXJBO0QuVkVSU0lPTj13QTtELnRvRm9ybURhdGE9TztELkF4aW9zRXJyb3I9cDtELkNhbmNlbD1ELkNhbmNlbGVkRXJyb3I7RC5hbGw9ZnVuY3Rpb24oZSl7cmV0dXJuIFByb21pc2UuYWxsKGUpfTtELnNwcmVhZD0kQTtELmlzQXhpb3NFcnJvcj1BZTtELm1lcmdlQ29uZmlnPUc7RC5BeGlvc0hlYWRlcnM9aztELmZvcm1Ub0pTT049QT0+bUEoZy5pc0hUTUxGb3JtKEEpP25ldyBGb3JtRGF0YShBKTpBKTtELmdldEFkYXB0ZXI9eUEuZ2V0QWRhcHRlcjtELkh0dHBTdGF0dXNDb2RlPXZlO0QuZGVmYXVsdD1EO3ZhciB6PUQ7dmFye0F4aW9zOkJhLEF4aW9zRXJyb3I6Q2EsQ2FuY2VsZWRFcnJvcjpsYSxpc0NhbmNlbDpmYSxDYW5jZWxUb2tlbjpjYSxWRVJTSU9OOnVhLGFsbDpFYSxDYW5jZWw6UWEsaXNBeGlvc0Vycm9yOnBhLHNwcmVhZDptYSx0b0Zvcm1EYXRhOmRhLEF4aW9zSGVhZGVyczp5YSxIdHRwU3RhdHVzQ29kZTpoYSxmb3JtVG9KU09OOndhLGdldEFkYXB0ZXI6RGEsbWVyZ2VDb25maWc6U2F9PXo7YXN5bmMgZnVuY3Rpb24gVXIoQSxlKXtsZXQgdD1BLHI9bnVsbDtpZih0PT1udWxsKXI9bmV3IFdvcmtlcihuZXcgVVJMKCIuL3dlYi13b3JrZXJzL2l0ay13YXNtLXBpcGVsaW5lLndvcmtlci5qcyIsaW1wb3J0Lm1ldGEudXJsKSx7dHlwZToibW9kdWxlIn0pO2Vsc2UgaWYodC5zdGFydHNXaXRoKCJodHRwIikpe2xldCBuPWF3YWl0IHouZ2V0KHQse3Jlc3BvbnNlVHlwZToiYmxvYiIscGFyYW1zOmV9KSxvPVVSTC5jcmVhdGVPYmplY3RVUkwobi5kYXRhKTtyPW5ldyBXb3JrZXIobyx7dHlwZToibW9kdWxlIn0pfWVsc2Ugcj1uZXcgV29ya2VyKHQse3R5cGU6Im1vZHVsZSJ9KTtyZXR1cm4gcn12YXIgaUE9VXI7ZnVuY3Rpb24gemUoQSl7bGV0IGU9VEEoQSksdD1BO3JldHVybiB0LnRlcm1pbmF0ZWQ9ITEsdC53b3JrZXJQcm94eT1lLHQub3JpZ2luYWxUZXJtaW5hdGU9dC50ZXJtaW5hdGUsdC50ZXJtaW5hdGU9KCk9Pnt0LnRlcm1pbmF0ZWQ9ITAsdC53b3JrZXJQcm94eVtOQV0oKSx0Lm9yaWdpbmFsVGVybWluYXRlKCl9LHt3b3JrZXJQcm94eTplLHdvcmtlcjp0fX1hc3luYyBmdW5jdGlvbiBOcihBLGUsdCl7bGV0IHI7aWYoQSE9bnVsbCl7bGV0IG89QTtyZXR1cm4gby53b3JrZXJQcm94eSE9PXZvaWQgMD8ocj1vLndvcmtlclByb3h5LHt3b3JrZXJQcm94eTpyLHdvcmtlcjpvfSk6emUoQSl9bGV0IG49YXdhaXQgaUEoZSx0KTtyZXR1cm4gemUobil9dmFyIFZlPU5yO2FzeW5jIGZ1bmN0aW9uIFRyKEEsZSx0KXtsZXQgcj0idW5rbm93biI7dHlwZW9mIEEhPSJzdHJpbmciP3I9QS5ocmVmOkEuc3RhcnRzV2l0aCgiaHR0cCIpP3I9QTpyPXR5cGVvZiBlPCJ1Ij9gJHtlfS8ke0F9YDpBLHIuZW5kc1dpdGgoIi5qcyIpJiYocj1yLnN1YnN0cmluZygwLHIubGVuZ3RoLTMpKSxyLmVuZHNXaXRoKCIud2FzbSIpJiYocj1yLnN1YnN0cmluZygwLHIubGVuZ3RoLTUpKTtsZXQgbj1gJHtyfS53YXNtYCxpPShhd2FpdCB6LmdldChuLHtyZXNwb25zZVR5cGU6ImFycmF5YnVmZmVyIixwYXJhbXM6dH0pKS5kYXRhO3JldHVybihhd2FpdCBpbXBvcnQoYCR7cn0uanNgKSkuZGVmYXVsdCh7d2FzbUJpbmFyeTppfSl9dmFyIFplPVRyO3ZhciBYZT1hc3luYygpPT5XZWJBc3NlbWJseS52YWxpZGF0ZShuZXcgVWludDhBcnJheShbMCw5NywxMTUsMTA5LDEsMCwwLDAsMSw1LDEsOTYsMCwxLDEyMywzLDIsMSwwLDEwLDEwLDEsOCwwLDY1LDAsMjUzLDE1LDI1Myw5OCwxMV0pKTt2YXIgZXQ9dHlwZW9mIGdsb2JhbFRoaXMuU2hhcmVkQXJyYXlCdWZmZXI9PSJmdW5jdGlvbiIsJGU9bmV3IFRleHRFbmNvZGVyLEF0PW5ldyBUZXh0RGVjb2RlcigidXRmLTgiKTtmdW5jdGlvbiBMcihBLGUpe2xldCB0PXtmbGFnczoiciIsZW5jb2Rpbmc6ImJpbmFyeSJ9LHI9QS5mc19vcGVuKGUsdC5mbGFncyksbz1BLmZzX3N0YXQoZSkuc2l6ZSxpPW51bGw7ZXQ/aT1uZXcgU2hhcmVkQXJyYXlCdWZmZXIobyk6aT1uZXcgQXJyYXlCdWZmZXIobyk7bGV0IEI9bmV3IFVpbnQ4QXJyYXkoaSk7cmV0dXJuIEEuZnNfcmVhZChyLEIsMCxvLDApLEEuZnNfY2xvc2UociksQn1mdW5jdGlvbiB0dChBLGUsdCl7bGV0IHI9bnVsbDtldD9yPW5ldyBTaGFyZWRBcnJheUJ1ZmZlcih0KTpyPW5ldyBBcnJheUJ1ZmZlcih0KTtsZXQgbj1uZXcgVWludDhBcnJheShyKSxvPW5ldyBVaW50OEFycmF5KEEuSEVBUFU4LmJ1ZmZlcixlLHQpO3JldHVybiBuLnNldChvKSxufWZ1bmN0aW9uIFMoQSxlLHQscil7bGV0IG49MDtyZXR1cm4gZSE9PW51bGwmJihuPUEuY2NhbGwoIml0a193YXNtX2lucHV0X2FycmF5X2FsbG9jIiwibnVtYmVyIixbIm51bWJlciIsIm51bWJlciIsIm51bWJlciIsIm51bWJlciJdLFswLHQscixlLmJ1ZmZlci5ieXRlTGVuZ3RoXSksQS5IRUFQVTguc2V0KG5ldyBVaW50OEFycmF5KGUuYnVmZmVyKSxuKSksbn1mdW5jdGlvbiBXKEEsZSx0KXtsZXQgcj1KU09OLnN0cmluZ2lmeShlKSxuPUEubGVuZ3RoQnl0ZXNVVEY4KHIpKzEsbz1BLmNjYWxsKCJpdGtfd2FzbV9pbnB1dF9qc29uX2FsbG9jIiwibnVtYmVyIixbIm51bWJlciIsIm51bWJlciIsIm51bWJlciJdLFswLHQsbl0pO0Euc3RyaW5nVG9VVEY4KHIsbyxuKX1mdW5jdGlvbiBSKEEsZSx0LHIpe2xldCBuPUEuY2NhbGwoIml0a193YXNtX291dHB1dF9hcnJheV9hZGRyZXNzIiwibnVtYmVyIixbIm51bWJlciIsIm51bWJlciIsIm51bWJlciJdLFswLGUsdF0pLG89QS5jY2FsbCgiaXRrX3dhc21fb3V0cHV0X2FycmF5X3NpemUiLCJudW1iZXIiLFsibnVtYmVyIiwibnVtYmVyIiwibnVtYmVyIl0sWzAsZSx0XSksaT10dChBLG4sbyk7cmV0dXJuIEwocixpLmJ1ZmZlcil9ZnVuY3Rpb24gYUEoQSxlKXtsZXQgdD1BLmNjYWxsKCJpdGtfd2FzbV9vdXRwdXRfanNvbl9hZGRyZXNzIiwibnVtYmVyIixbIm51bWJlciIsIm51bWJlciJdLFswLGVdKSxyPUEuVVRGOFRvU3RyaW5nKHQpO3JldHVybiBKU09OLnBhcnNlKHIpfWZ1bmN0aW9uIFByKEEsZSx0LHIpe3IhPW51bGwmJnIubGVuZ3RoPjAmJnIuZm9yRWFjaChmdW5jdGlvbihDLHMpe3N3aXRjaChDLnR5cGUpe2Nhc2UgRS5UZXh0U3RyZWFtOntsZXQgYT0kZS5lbmNvZGUoQy5kYXRhLmRhdGEpLGM9UyhBLGEscywwKSxJPXtzaXplOmEuYnVmZmVyLmJ5dGVMZW5ndGgsZGF0YTpgZGF0YTphcHBsaWNhdGlvbi92bmQuaXRrLmFkZHJlc3MsMDoke2N9YH07VyhBLEkscyk7YnJlYWt9Y2FzZSBFLkpzb25Db21wYXRpYmxlOntsZXQgYT0kZS5lbmNvZGUoSlNPTi5zdHJpbmdpZnkoQy5kYXRhKSksYz1TKEEsYSxzLDApLEk9e3NpemU6YS5idWZmZXIuYnl0ZUxlbmd0aCxkYXRhOmBkYXRhOmFwcGxpY2F0aW9uL3ZuZC5pdGsuYWRkcmVzcywwOiR7Y31gfTtXKEEsSSxzKTticmVha31jYXNlIEUuQmluYXJ5U3RyZWFtOntsZXQgYT1DLmRhdGEuZGF0YSxjPVMoQSxhLHMsMCksST17c2l6ZTphLmJ1ZmZlci5ieXRlTGVuZ3RoLGRhdGE6YGRhdGE6YXBwbGljYXRpb24vdm5kLml0ay5hZGRyZXNzLDA6JHtjfWB9O1coQSxJLHMpO2JyZWFrfWNhc2UgRS5UZXh0RmlsZTp7QS5mc193cml0ZUZpbGUoQy5kYXRhLnBhdGgsQy5kYXRhLmRhdGEpO2JyZWFrfWNhc2UgRS5CaW5hcnlGaWxlOntBLmZzX3dyaXRlRmlsZShDLmRhdGEucGF0aCxDLmRhdGEuZGF0YSk7YnJlYWt9Y2FzZSBFLkltYWdlOntsZXQgYT1DLmRhdGEsYz1TKEEsYS5kYXRhLHMsMCksST1TKEEsYS5kaXJlY3Rpb24scywxKSxsPXR5cGVvZiBhLm1ldGFkYXRhPy5lbnRyaWVzPCJ1Ij9BcnJheS5mcm9tKGEubWV0YWRhdGEuZW50cmllcygpKTpbXSxmPXtpbWFnZVR5cGU6YS5pbWFnZVR5cGUsbmFtZTphLm5hbWUsb3JpZ2luOmEub3JpZ2luLHNwYWNpbmc6YS5zcGFjaW5nLGRpcmVjdGlvbjpgZGF0YTphcHBsaWNhdGlvbi92bmQuaXRrLmFkZHJlc3MsMDoke0l9YCxzaXplOmEuc2l6ZSxkYXRhOmBkYXRhOmFwcGxpY2F0aW9uL3ZuZC5pdGsuYWRkcmVzcywwOiR7Y31gLG1ldGFkYXRhOmx9O1coQSxmLHMpO2JyZWFrfWNhc2UgRS5NZXNoOntsZXQgYT1DLmRhdGEsYz1TKEEsYS5wb2ludHMscywwKSxJPVMoQSxhLmNlbGxzLHMsMSksbD1TKEEsYS5wb2ludERhdGEscywyKSxmPVMoQSxhLmNlbGxEYXRhLHMsMyksUT17bWVzaFR5cGU6YS5tZXNoVHlwZSxuYW1lOmEubmFtZSxudW1iZXJPZlBvaW50czphLm51bWJlck9mUG9pbnRzLHBvaW50czpgZGF0YTphcHBsaWNhdGlvbi92bmQuaXRrLmFkZHJlc3MsMDoke2N9YCxudW1iZXJPZkNlbGxzOmEubnVtYmVyT2ZDZWxscyxjZWxsczpgZGF0YTphcHBsaWNhdGlvbi92bmQuaXRrLmFkZHJlc3MsMDoke0l9YCxjZWxsQnVmZmVyU2l6ZTphLmNlbGxCdWZmZXJTaXplLG51bWJlck9mUG9pbnRQaXhlbHM6YS5udW1iZXJPZlBvaW50UGl4ZWxzLHBvaW50RGF0YTpgZGF0YTphcHBsaWNhdGlvbi92bmQuaXRrLmFkZHJlc3MsMDoke2x9YCxudW1iZXJPZkNlbGxQaXhlbHM6YS5udW1iZXJPZkNlbGxQaXhlbHMsY2VsbERhdGE6YGRhdGE6YXBwbGljYXRpb24vdm5kLml0ay5hZGRyZXNzLDA6JHtmfWB9O1coQSxRLHMpO2JyZWFrfWNhc2UgRS5Qb2ludFNldDp7bGV0IGE9Qy5kYXRhLGM9UyhBLGEucG9pbnRzLHMsMCksST1TKEEsYS5wb2ludERhdGEscywxKSxsPXtwb2ludFNldFR5cGU6YS5wb2ludFNldFR5cGUsbmFtZTphLm5hbWUsbnVtYmVyT2ZQb2ludHM6YS5udW1iZXJPZlBvaW50cyxwb2ludHM6YGRhdGE6YXBwbGljYXRpb24vdm5kLml0ay5hZGRyZXNzLDA6JHtjfWAsbnVtYmVyT2ZQb2ludFBpeGVsczphLm51bWJlck9mUG9pbnRQaXhlbHMscG9pbnREYXRhOmBkYXRhOmFwcGxpY2F0aW9uL3ZuZC5pdGsuYWRkcmVzcywwOiR7SX1gfTtXKEEsbCxzKTticmVha31jYXNlIEUuVHJhbnNmb3JtTGlzdDp7bGV0IGE9Qy5kYXRhLGM9W107YS5mb3JFYWNoKChJLGwpPT57bGV0IFE9YGRhdGE6YXBwbGljYXRpb24vdm5kLml0ay5hZGRyZXNzLDA6JHtTKEEsSS5maXhlZFBhcmFtZXRlcnMscyxsKjIpfWAsVT1gZGF0YTphcHBsaWNhdGlvbi92bmQuaXRrLmFkZHJlc3MsMDoke1MoQSxJLnBhcmFtZXRlcnMscyxsKjIrMSl9YCxOPXt0cmFuc2Zvcm1UeXBlOkkudHJhbnNmb3JtVHlwZSxudW1iZXJPZkZpeGVkUGFyYW1ldGVyczpJLm51bWJlck9mRml4ZWRQYXJhbWV0ZXJzLG51bWJlck9mUGFyYW1ldGVyczpJLm51bWJlck9mUGFyYW1ldGVycyxuYW1lOkkubmFtZSxpbnB1dFNwYWNlTmFtZTpJLmlucHV0U3BhY2VOYW1lLG91dHB1dFNwYWNlTmFtZTpJLm91dHB1dFNwYWNlTmFtZSxwYXJhbWV0ZXJzOlUsZml4ZWRQYXJhbWV0ZXJzOlF9O2MucHVzaChOKX0pLFcoQSxjLHMpO2JyZWFrfWNhc2UgRS5Qb2x5RGF0YTp7bGV0IGE9Qy5kYXRhLGM9UyhBLGEucG9pbnRzLHMsMCksST1TKEEsYS52ZXJ0aWNlcyxzLDEpLGw9UyhBLGEubGluZXMscywyKSxmPVMoQSxhLnBvbHlnb25zLHMsMyksUT1TKEEsYS50cmlhbmdsZVN0cmlwcyxzLDQpLG09UyhBLGEucG9pbnREYXRhLHMsNSksVT1TKEEsYS5wb2ludERhdGEscyw2KSxOPXtwb2x5RGF0YVR5cGU6YS5wb2x5RGF0YVR5cGUsbmFtZTphLm5hbWUsbnVtYmVyT2ZQb2ludHM6YS5udW1iZXJPZlBvaW50cyxwb2ludHM6YGRhdGE6YXBwbGljYXRpb24vdm5kLml0ay5hZGRyZXNzLDA6JHtjfWAsdmVydGljZXNCdWZmZXJTaXplOmEudmVydGljZXNCdWZmZXJTaXplLHZlcnRpY2VzOmBkYXRhOmFwcGxpY2F0aW9uL3ZuZC5pdGsuYWRkcmVzcywwOiR7SX1gLGxpbmVzQnVmZmVyU2l6ZTphLmxpbmVzQnVmZmVyU2l6ZSxsaW5lczpgZGF0YTphcHBsaWNhdGlvbi92bmQuaXRrLmFkZHJlc3MsMDoke2x9YCxwb2x5Z29uc0J1ZmZlclNpemU6YS5wb2x5Z29uc0J1ZmZlclNpemUscG9seWdvbnM6YGRhdGE6YXBwbGljYXRpb24vdm5kLml0ay5hZGRyZXNzLDA6JHtmfWAsdHJpYW5nbGVTdHJpcHNCdWZmZXJTaXplOmEudHJpYW5nbGVTdHJpcHNCdWZmZXJTaXplLHRyaWFuZ2xlU3RyaXBzOmBkYXRhOmFwcGxpY2F0aW9uL3ZuZC5pdGsuYWRkcmVzcywwOiR7UX1gLG51bWJlck9mUG9pbnRQaXhlbHM6YS5udW1iZXJPZlBvaW50UGl4ZWxzLHBvaW50RGF0YTpgZGF0YTphcHBsaWNhdGlvbi92bmQuaXRrLmFkZHJlc3MsMDoke219YCxudW1iZXJPZkNlbGxQaXhlbHM6YS5udW1iZXJPZkNlbGxQaXhlbHMsY2VsbERhdGE6YGRhdGE6YXBwbGljYXRpb24vdm5kLml0ay5hZGRyZXNzLDA6JHtVfWB9O1coQSxOLHMpO2JyZWFrfWRlZmF1bHQ6dGhyb3cgRXJyb3IoIlVuc3VwcG9ydGVkIGlucHV0IEludGVyZmFjZVR5cGUiKX19KSxBLnJlc2V0TW9kdWxlU3Rkb3V0KCksQS5yZXNldE1vZHVsZVN0ZGVycigpO2xldCBuPUEuc3RhY2tTYXZlKCksbz0wO3RyeXtvPUEuY2FsbE1haW4oZS5zbGljZSgpKX1jYXRjaChDKXt0aHJvdyB0eXBlb2YgQz09Im51bWJlciImJihjb25zb2xlLmxvZygiRXhjZXB0aW9uIHdoaWxlIHJ1bm5pbmcgcGlwZWxpbmU6IiksY29uc29sZS5sb2coInN0ZG91dDoiLEEuZ2V0TW9kdWxlU3Rkb3V0KCkpLGNvbnNvbGUuZXJyb3IoInN0ZGVycjoiLEEuZ2V0TW9kdWxlU3RkZXJyKCkpLHR5cGVvZiBBLmdldEV4Y2VwdGlvbk1lc3NhZ2U8InUiP2NvbnNvbGUuZXJyb3IoImV4Y2VwdGlvbjoiLEEuZ2V0RXhjZXB0aW9uTWVzc2FnZShDKSk6Y29uc29sZS5lcnJvcigiQnVpbGQgbW9kdWxlIGluIERlYnVnIG1vZGUgZm9yIGV4Y2VwdGlvbiBtZXNzYWdlIGluZm9ybWF0aW9uLiIpKSxDfWZpbmFsbHl7QS5zdGFja1Jlc3RvcmUobil9bGV0IGk9QS5nZXRNb2R1bGVTdGRvdXQoKSxCPUEuZ2V0TW9kdWxlU3RkZXJyKCksdT1bXTtyZXR1cm4gdCE9bnVsbCYmdC5sZW5ndGg+MCYmbz09PTAmJnQuZm9yRWFjaChmdW5jdGlvbihDLHMpe2xldCBhPW51bGw7c3dpdGNoKEMudHlwZSl7Y2FzZSBFLlRleHRTdHJlYW06e2xldCBJPUEuY2NhbGwoIml0a193YXNtX291dHB1dF9hcnJheV9hZGRyZXNzIiwibnVtYmVyIixbIm51bWJlciIsIm51bWJlciIsIm51bWJlciJdLFswLHMsMF0pLGw9QS5jY2FsbCgiaXRrX3dhc21fb3V0cHV0X2FycmF5X3NpemUiLCJudW1iZXIiLFsibnVtYmVyIiwibnVtYmVyIiwibnVtYmVyIl0sWzAscywwXSksZj1uZXcgVWludDhBcnJheShBLkhFQVBVOC5idWZmZXIsSSxsKTthPXtkYXRhOkF0LmRlY29kZShmKX07YnJlYWt9Y2FzZSBFLkpzb25Db21wYXRpYmxlOntsZXQgST1BLmNjYWxsKCJpdGtfd2FzbV9vdXRwdXRfYXJyYXlfYWRkcmVzcyIsIm51bWJlciIsWyJudW1iZXIiLCJudW1iZXIiLCJudW1iZXIiXSxbMCxzLDBdKSxsPUEuY2NhbGwoIml0a193YXNtX291dHB1dF9hcnJheV9zaXplIiwibnVtYmVyIixbIm51bWJlciIsIm51bWJlciIsIm51bWJlciJdLFswLHMsMF0pLGY9bmV3IFVpbnQ4QXJyYXkoQS5IRUFQVTguYnVmZmVyLEksbCk7YT1KU09OLnBhcnNlKEF0LmRlY29kZShmKSk7YnJlYWt9Y2FzZSBFLkJpbmFyeVN0cmVhbTp7bGV0IEk9QS5jY2FsbCgiaXRrX3dhc21fb3V0cHV0X2FycmF5X2FkZHJlc3MiLCJudW1iZXIiLFsibnVtYmVyIiwibnVtYmVyIiwibnVtYmVyIl0sWzAscywwXSksbD1BLmNjYWxsKCJpdGtfd2FzbV9vdXRwdXRfYXJyYXlfc2l6ZSIsIm51bWJlciIsWyJudW1iZXIiLCJudW1iZXIiLCJudW1iZXIiXSxbMCxzLDBdKTthPXtkYXRhOnR0KEEsSSxsKX07YnJlYWt9Y2FzZSBFLlRleHRGaWxlOnthPXtwYXRoOkMuZGF0YS5wYXRoLGRhdGE6QS5mc19yZWFkRmlsZShDLmRhdGEucGF0aCx7ZW5jb2Rpbmc6InV0ZjgifSl9O2JyZWFrfWNhc2UgRS5CaW5hcnlGaWxlOnthPXtwYXRoOkMuZGF0YS5wYXRoLGRhdGE6THIoQSxDLmRhdGEucGF0aCl9O2JyZWFrfWNhc2UgRS5JbWFnZTp7bGV0IEk9YUEoQSxzKTtJLmRhdGE9UihBLHMsMCxJLmltYWdlVHlwZS5jb21wb25lbnRUeXBlKSxJLmRpcmVjdGlvbj1SKEEscywxLE0uRmxvYXQ2NCksSS5tZXRhZGF0YT1uZXcgTWFwKEkubWV0YWRhdGEpLGE9STticmVha31jYXNlIEUuTWVzaDp7bGV0IEk9YUEoQSxzKTtJLm51bWJlck9mUG9pbnRzPjA/SS5wb2ludHM9UihBLHMsMCxJLm1lc2hUeXBlLnBvaW50Q29tcG9uZW50VHlwZSk6SS5wb2ludHM9TChJLm1lc2hUeXBlLnBvaW50Q29tcG9uZW50VHlwZSxuZXcgQXJyYXlCdWZmZXIoMCkpLEkubnVtYmVyT2ZDZWxscz4wP0kuY2VsbHM9UihBLHMsMSxJLm1lc2hUeXBlLmNlbGxDb21wb25lbnRUeXBlKTpJLmNlbGxzPUwoSS5tZXNoVHlwZS5jZWxsQ29tcG9uZW50VHlwZSxuZXcgQXJyYXlCdWZmZXIoMCkpLEkubnVtYmVyT2ZQb2ludFBpeGVscz4wP0kucG9pbnREYXRhPVIoQSxzLDIsSS5tZXNoVHlwZS5wb2ludFBpeGVsQ29tcG9uZW50VHlwZSk6SS5wb2ludERhdGE9TChJLm1lc2hUeXBlLnBvaW50UGl4ZWxDb21wb25lbnRUeXBlLG5ldyBBcnJheUJ1ZmZlcigwKSksSS5udW1iZXJPZkNlbGxQaXhlbHM+MD9JLmNlbGxEYXRhPVIoQSxzLDMsSS5tZXNoVHlwZS5jZWxsUGl4ZWxDb21wb25lbnRUeXBlKTpJLmNlbGxEYXRhPUwoSS5tZXNoVHlwZS5jZWxsUGl4ZWxDb21wb25lbnRUeXBlLG5ldyBBcnJheUJ1ZmZlcigwKSksYT1JO2JyZWFrfWNhc2UgRS5Qb2ludFNldDp7bGV0IEk9YUEoQSxzKTtJLm51bWJlck9mUG9pbnRzPjA/SS5wb2ludHM9UihBLHMsMCxJLnBvaW50U2V0VHlwZS5wb2ludENvbXBvbmVudFR5cGUpOkkucG9pbnRzPUwoSS5wb2ludFNldFR5cGUucG9pbnRDb21wb25lbnRUeXBlLG5ldyBBcnJheUJ1ZmZlcigwKSksSS5udW1iZXJPZlBvaW50UGl4ZWxzPjA/SS5wb2ludERhdGE9UihBLHMsMSxJLnBvaW50U2V0VHlwZS5wb2ludFBpeGVsQ29tcG9uZW50VHlwZSk6SS5wb2ludERhdGE9TChJLnBvaW50U2V0VHlwZS5wb2ludFBpeGVsQ29tcG9uZW50VHlwZSxuZXcgQXJyYXlCdWZmZXIoMCkpLGE9STticmVha31jYXNlIEUuVHJhbnNmb3JtTGlzdDp7bGV0IEk9YUEoQSxzKTtJLmZvckVhY2goKGwsZik9PntsLm51bWJlck9mRml4ZWRQYXJhbWV0ZXJzPjAmJihJW2ZdLmZpeGVkUGFyYW1ldGVycz1SKEEscyxmKjIsbC50cmFuc2Zvcm1UeXBlLnBhcmFtZXRlcnNWYWx1ZVR5cGUpKSxsLm51bWJlck9mRml4ZWRQYXJhbWV0ZXJzPjAmJihJW2ZdLnBhcmFtZXRlcnM9UihBLHMsZioyKzEsbC50cmFuc2Zvcm1UeXBlLnBhcmFtZXRlcnNWYWx1ZVR5cGUpKX0pLGE9STticmVha31jYXNlIEUuUG9seURhdGE6e2xldCBJPWFBKEEscyk7SS5udW1iZXJPZlBvaW50cz4wP0kucG9pbnRzPVIoQSxzLDAsTS5GbG9hdDMyKTpJLnBvaW50cz1uZXcgRmxvYXQzMkFycmF5LEkudmVydGljZXNCdWZmZXJTaXplPjA/SS52ZXJ0aWNlcz1SKEEscywxLEYuVUludDMyKTpJLnZlcnRpY2VzPW5ldyBVaW50MzJBcnJheSxJLmxpbmVzQnVmZmVyU2l6ZT4wP0kubGluZXM9UihBLHMsMixGLlVJbnQzMik6SS5saW5lcz1uZXcgVWludDMyQXJyYXksSS5wb2x5Z29uc0J1ZmZlclNpemU+MD9JLnBvbHlnb25zPVIoQSxzLDMsRi5VSW50MzIpOkkucG9seWdvbnM9bmV3IFVpbnQzMkFycmF5LEkudHJpYW5nbGVTdHJpcHNCdWZmZXJTaXplPjA/SS50cmlhbmdsZVN0cmlwcz1SKEEscyw0LEYuVUludDMyKTpJLnRyaWFuZ2xlU3RyaXBzPW5ldyBVaW50MzJBcnJheSxJLm51bWJlck9mUG9pbnRQaXhlbHM+MD9JLnBvaW50RGF0YT1SKEEscyw1LEkucG9seURhdGFUeXBlLnBvaW50UGl4ZWxDb21wb25lbnRUeXBlKTpJLnBvaW50RGF0YT1MKEkucG9seURhdGFUeXBlLnBvaW50UGl4ZWxDb21wb25lbnRUeXBlLG5ldyBBcnJheUJ1ZmZlcigwKSksSS5udW1iZXJPZkNlbGxQaXhlbHM+MD9JLmNlbGxEYXRhPVIoQSxzLDYsSS5wb2x5RGF0YVR5cGUuY2VsbFBpeGVsQ29tcG9uZW50VHlwZSk6SS5jZWxsRGF0YT1MKEkucG9seURhdGFUeXBlLmNlbGxQaXhlbENvbXBvbmVudFR5cGUsbmV3IEFycmF5QnVmZmVyKDApKSxhPUk7YnJlYWt9ZGVmYXVsdDp0aHJvdyBFcnJvcigiVW5zdXBwb3J0ZWQgb3V0cHV0IEludGVyZmFjZVR5cGUiKX1sZXQgYz17dHlwZTpDLnR5cGUsZGF0YTphfTt1LnB1c2goYyl9KSx7cmV0dXJuVmFsdWU6byxzdGRvdXQ6aSxzdGRlcnI6QixvdXRwdXRzOnV9fXZhciBydD1Qcjt2YXIgR3I9dHlwZW9mIGdsb2JhbFRoaXMuU2hhcmVkQXJyYXlCdWZmZXI8InUiO2Z1bmN0aW9uIE9yKEEsZSl7aWYoQT09bnVsbClyZXR1cm5bXTtsZXQgdD1bXTtmb3IobGV0IHI9MDtyPEEubGVuZ3RoO3IrKyl7bGV0IG49eHIoQVtyXSxlKTtuIT09bnVsbCYmdC5wdXNoKG4pfXJldHVybiB0fWZ1bmN0aW9uIHhyKEEsZSl7aWYoQT09bnVsbClyZXR1cm4gbnVsbDtsZXQgdD1udWxsO3JldHVybiBBLmJ1ZmZlciE9PXZvaWQgMD90PUEuYnVmZmVyOkEuYnl0ZUxlbmd0aCE9PXZvaWQgMCYmKHQ9QSksR3ImJnQgaW5zdGFuY2VvZiBTaGFyZWRBcnJheUJ1ZmZlcj9udWxsOmU/dDp0LnNsaWNlKDApfXZhciBvdD1PcjtmdW5jdGlvbiBKcihBKXtyZXR1cm5bQS5kYXRhLEEuZGlyZWN0aW9uXX12YXIgbnQ9SnI7ZnVuY3Rpb24gV3IoQSl7cmV0dXJuW0EucG9pbnRzLEEucG9pbnREYXRhLEEuY2VsbHMsQS5jZWxsRGF0YV19dmFyIGl0PVdyO2Z1bmN0aW9uIEhyKEEpe3JldHVybltBLnBvaW50cyxBLnZlcnRpY2VzLEEubGluZXMsQS5wb2x5Z29ucyxBLnRyaWFuZ2xlU3RyaXBzLEEucG9pbnREYXRhLEEuY2VsbERhdGFdfXZhciBhdD1Icjt2YXIgTXI7ZnVuY3Rpb24gU0EoKXtyZXR1cm4gTXJ9dmFyIFlyO2Z1bmN0aW9uIHN0KCl7cmV0dXJuIFlyfXZhciBxcjtmdW5jdGlvbiBSQSgpe3JldHVybiBxcn12YXIgdGU9bmV3IE1hcDtmdW5jdGlvbiBLcigpe2xldCBBPVJBKCk7cmV0dXJuIHR5cGVvZiBBPiJ1IiYmKEE9bnVsbCksQX1mdW5jdGlvbiBJdCgpe2xldCBBPVNBKCk7cmV0dXJuIHR5cGVvZiBBPiJ1IiYmKEE9bmV3IFVSTCgiL3BpcGVsaW5lcyIsZG9jdW1lbnQubG9jYXRpb24ub3JpZ2luKS5ocmVmKSxBfWZ1bmN0aW9uIGJBKCl7bGV0IEE9c3QoKTtyZXR1cm4gdHlwZW9mIEE+InUiJiYoQT17fSksQX1hc3luYyBmdW5jdGlvbiBqcihBLGUsdCl7bGV0IHI9QSxuPUE7aWYodHlwZW9mIEEhPSJzdHJpbmciJiYocj1uZXcgVVJMKEEuaHJlZiksbj1yLmhyZWYpLHRlLmhhcyhuKSlyZXR1cm4gdGUuZ2V0KG4pO3tsZXQgbz1hd2FpdCBaZShBLGU/LnRvU3RyaW5nKCk/P0l0KCksdD8/YkEoKSk7cmV0dXJuIHRlLnNldChuLG8pLG99fWFzeW5jIGZ1bmN0aW9uIHZyKEEsZSx0LHIsbil7aWYoIWF3YWl0IFhlKCkpe2xldCBRPSJXZWJBc3NlbWJseSBTSU1EIHN1cHBvcnQgaXMgcmVxdWlyZWQgLS0gcGxlYXNlIHVwZGF0ZSB5b3VyIGJyb3dzZXIuIjt0aHJvdyBhbGVydChRKSxuZXcgRXJyb3IoUSl9bGV0IG89bj8ud2ViV29ya2VyPz9udWxsO2lmKG89PT0hMSl7bGV0IFE9YXdhaXQganIoQS50b1N0cmluZygpLG4/LnBpcGVsaW5lQmFzZVVybCxuPy5waXBlbGluZVF1ZXJ5UGFyYW1zPz9iQSgpKTtyZXR1cm4gcnQoUSxlLHQscil9bGV0IGk9byxCPW4/LnBpcGVsaW5lV29ya2VyVXJsPz9LcigpLHU9dHlwZW9mIEIhPSJzdHJpbmciJiZ0eXBlb2YgQj8uaHJlZjwidSI/Qi5ocmVmOkIse3dvcmtlclByb3h5OkMsd29ya2VyOnN9PWF3YWl0IFZlKGksdSxuPy5waXBlbGluZVF1ZXJ5UGFyYW1zPz9iQSgpKTtpPXM7bGV0IGE9W107ciE9bnVsbCYmci5sZW5ndGg+MCYmci5mb3JFYWNoKGZ1bmN0aW9uKFEpe2lmKFEudHlwZT09PUUuQmluYXJ5U3RyZWFtKXtsZXQgbT1RLmRhdGEuZGF0YTthLnB1c2gobSl9ZWxzZSBpZihRLnR5cGU9PT1FLkJpbmFyeUZpbGUpe2xldCBtPVEuZGF0YS5kYXRhO2EucHVzaChtKX1lbHNlIGlmKFEudHlwZT09PUUuSW1hZ2Upe2xldCBtPVEuZGF0YTttLmRhdGEhPT1udWxsJiZhLnB1c2goLi4ubnQobSkpfWVsc2UgaWYoUS50eXBlPT09RS5NZXNoKXtsZXQgbT1RLmRhdGE7YS5wdXNoKC4uLml0KG0pKX1lbHNlIGlmKFEudHlwZT09PUUuUG9seURhdGEpe2xldCBtPVEuZGF0YTthLnB1c2goLi4uYXQobSkpfX0pO2xldCBjPW4/LnBpcGVsaW5lQmFzZVVybD8/SXQoKSxJPXR5cGVvZiBjIT0ic3RyaW5nIiYmdHlwZW9mIGM/LmhyZWY8InUiP2MuaHJlZjpjLGw9ciE9bnVsbD9MQShyLG90KGEsbj8ubm9Db3B5KSk6bnVsbCxmPWF3YWl0IEMucnVuUGlwZWxpbmUoQS50b1N0cmluZygpLEksZSx0LGwsbj8ucGlwZWxpbmVRdWVyeVBhcmFtcz8/YkEoKSk7cmV0dXJue3JldHVyblZhbHVlOmYucmV0dXJuVmFsdWUsc3Rkb3V0OmYuc3Rkb3V0LHN0ZGVycjpmLnN0ZGVycixvdXRwdXRzOmYub3V0cHV0cyx3ZWJXb3JrZXI6aX19dmFyIHk9dnI7dmFyIF9yPW51bGw7ZnVuY3Rpb24gZ3QoKXtyZXR1cm4gX3J9dmFyIHJlLHpyPWBodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL0BpdGstd2FzbS90cmFuc2Zvcm0taW9AJHtrQX0vZGlzdC9waXBlbGluZXNgO2Z1bmN0aW9uIHVzKEEpe3JlPUF9ZnVuY3Rpb24gaCgpe2lmKHR5cGVvZiByZTwidSIpcmV0dXJuIHJlO2xldCBBPVNBKCk7cmV0dXJuIHR5cGVvZiBBPCJ1Ij9BOnpyfXZhciBvZSxWcj1udWxsO2Z1bmN0aW9uIEJ0KEEpe29lPUF9ZnVuY3Rpb24gZCgpe2lmKHR5cGVvZiBvZTwidSIpcmV0dXJuIG9lO2xldCBBPVJBKCk7cmV0dXJuIHR5cGVvZiBBPCJ1Ij9BOlZyfXZhciBWPW51bGw7YXN5bmMgZnVuY3Rpb24gQ3QoKXtsZXQgQT1kKCksZT10eXBlb2YgQSE9InN0cmluZyImJnR5cGVvZiBBPy5ocmVmPCJ1Ij9BLmhyZWY6QTtWPWF3YWl0IGlBKGUpfWZ1bmN0aW9uIGhzKEEpe1Y9QX1hc3luYyBmdW5jdGlvbiB3KCl7aWYoViE9PW51bGwpcmV0dXJuIFYudGVybWluYXRlZCYmYXdhaXQgQ3QoKSxWO2xldCBBPWd0KCk7cmV0dXJuIEEhPT1udWxsP0E6KGF3YWl0IEN0KCksVil9YXN5bmMgZnVuY3Rpb24gWnIoQSxlPXt9KXtsZXQgdD1be3R5cGU6RS5Kc29uQ29tcGF0aWJsZX0se3R5cGU6RS5UcmFuc2Zvcm1MaXN0fV0scj1BO2lmKEEgaW5zdGFuY2VvZiBGaWxlKXtsZXQgUT1hd2FpdCBBLmFycmF5QnVmZmVyKCk7cj17cGF0aDpBLm5hbWUsZGF0YTpuZXcgVWludDhBcnJheShRKX19bGV0IG49W3t0eXBlOkUuQmluYXJ5RmlsZSxkYXRhOnJ9XSxvPVtdLGk9ci5wYXRoO28ucHVzaChpKSxvLnB1c2goIjAiKSxvLnB1c2goIjEiKSxvLnB1c2goIi0tbWVtb3J5LWlvIiksZS5mbG9hdFBhcmFtZXRlcnMmJmUuZmxvYXRQYXJhbWV0ZXJzJiZvLnB1c2goIi0tZmxvYXQtcGFyYW1ldGVycyIpO2xldCBDPSJoZGY1LXJlYWQtdHJhbnNmb3JtIixzPWU/LndlYldvcmtlcjtzPT09dm9pZCAwJiYocz1hd2FpdCB3KCkpO2xldHt3ZWJXb3JrZXI6YSxyZXR1cm5WYWx1ZTpjLHN0ZGVycjpJLG91dHB1dHM6bH09YXdhaXQgeShDLG8sdCxuLHtwaXBlbGluZUJhc2VVcmw6aCgpLHBpcGVsaW5lV29ya2VyVXJsOmQoKSx3ZWJXb3JrZXI6cyxub0NvcHk6ZT8ubm9Db3B5fSk7aWYoYyE9PTAmJkkhPT0iIil0aHJvdyBuZXcgRXJyb3IoSSk7cmV0dXJue3dlYldvcmtlcjphLGNvdWxkUmVhZDpsWzBdPy5kYXRhLHRyYW5zZm9ybTpsWzFdPy5kYXRhfX12YXIgWHI9WnI7YXN5bmMgZnVuY3Rpb24gJHIoQSxlLHQ9e30pe2xldCByPVt7dHlwZTpFLkpzb25Db21wYXRpYmxlfSx7dHlwZTpFLkJpbmFyeUZpbGUsZGF0YTp7cGF0aDplLGRhdGE6bmV3IFVpbnQ4QXJyYXl9fV0sbj1be3R5cGU6RS5UcmFuc2Zvcm1MaXN0LGRhdGE6QX1dLG89W107by5wdXNoKCIwIiksby5wdXNoKCIwIik7bGV0IHU9ZTtvLnB1c2godSksby5wdXNoKCItLW1lbW9yeS1pbyIpLHQuZmxvYXRQYXJhbWV0ZXJzJiZ0LmZsb2F0UGFyYW1ldGVycyYmby5wdXNoKCItLWZsb2F0LXBhcmFtZXRlcnMiKSx0LnVzZUNvbXByZXNzaW9uJiZ0LnVzZUNvbXByZXNzaW9uJiZvLnB1c2goIi0tdXNlLWNvbXByZXNzaW9uIik7bGV0IEM9ImhkZjUtd3JpdGUtdHJhbnNmb3JtIixzPXQ/LndlYldvcmtlcjtzPT09dm9pZCAwJiYocz1hd2FpdCB3KCkpO2xldHt3ZWJXb3JrZXI6YSxyZXR1cm5WYWx1ZTpjLHN0ZGVycjpJLG91dHB1dHM6bH09YXdhaXQgeShDLG8scixuLHtwaXBlbGluZUJhc2VVcmw6aCgpLHBpcGVsaW5lV29ya2VyVXJsOmQoKSx3ZWJXb3JrZXI6cyxub0NvcHk6dD8ubm9Db3B5fSk7aWYoYyE9PTAmJkkhPT0iIil0aHJvdyBuZXcgRXJyb3IoSSk7cmV0dXJue3dlYldvcmtlcjphLGNvdWxkV3JpdGU6bFswXT8uZGF0YSxzZXJpYWxpemVkVHJhbnNmb3JtOmxbMV0/LmRhdGF9fXZhciBBbz0kcjthc3luYyBmdW5jdGlvbiBlbyhBLGU9e30pe2xldCB0PVt7dHlwZTpFLkpzb25Db21wYXRpYmxlfSx7dHlwZTpFLlRyYW5zZm9ybUxpc3R9XSxyPUE7aWYoQSBpbnN0YW5jZW9mIEZpbGUpe2xldCBRPWF3YWl0IEEuYXJyYXlCdWZmZXIoKTtyPXtwYXRoOkEubmFtZSxkYXRhOm5ldyBVaW50OEFycmF5KFEpfX1sZXQgbj1be3R5cGU6RS5CaW5hcnlGaWxlLGRhdGE6cn1dLG89W10saT1yLnBhdGg7by5wdXNoKGkpLG8ucHVzaCgiMCIpLG8ucHVzaCgiMSIpLG8ucHVzaCgiLS1tZW1vcnktaW8iKSxlLmZsb2F0UGFyYW1ldGVycyYmZS5mbG9hdFBhcmFtZXRlcnMmJm8ucHVzaCgiLS1mbG9hdC1wYXJhbWV0ZXJzIik7bGV0IEM9Im1hdC1yZWFkLXRyYW5zZm9ybSIscz1lPy53ZWJXb3JrZXI7cz09PXZvaWQgMCYmKHM9YXdhaXQgdygpKTtsZXR7d2ViV29ya2VyOmEscmV0dXJuVmFsdWU6YyxzdGRlcnI6SSxvdXRwdXRzOmx9PWF3YWl0IHkoQyxvLHQsbix7cGlwZWxpbmVCYXNlVXJsOmgoKSxwaXBlbGluZVdvcmtlclVybDpkKCksd2ViV29ya2VyOnMsbm9Db3B5OmU/Lm5vQ29weX0pO2lmKGMhPT0wJiZJIT09IiIpdGhyb3cgbmV3IEVycm9yKEkpO3JldHVybnt3ZWJXb3JrZXI6YSxjb3VsZFJlYWQ6bFswXT8uZGF0YSx0cmFuc2Zvcm06bFsxXT8uZGF0YX19dmFyIHRvPWVvO2FzeW5jIGZ1bmN0aW9uIHJvKEEsZSx0PXt9KXtsZXQgcj1be3R5cGU6RS5Kc29uQ29tcGF0aWJsZX0se3R5cGU6RS5CaW5hcnlGaWxlLGRhdGE6e3BhdGg6ZSxkYXRhOm5ldyBVaW50OEFycmF5fX1dLG49W3t0eXBlOkUuVHJhbnNmb3JtTGlzdCxkYXRhOkF9XSxvPVtdO28ucHVzaCgiMCIpLG8ucHVzaCgiMCIpO2xldCB1PWU7by5wdXNoKHUpLG8ucHVzaCgiLS1tZW1vcnktaW8iKSx0LmZsb2F0UGFyYW1ldGVycyYmdC5mbG9hdFBhcmFtZXRlcnMmJm8ucHVzaCgiLS1mbG9hdC1wYXJhbWV0ZXJzIiksdC51c2VDb21wcmVzc2lvbiYmdC51c2VDb21wcmVzc2lvbiYmby5wdXNoKCItLXVzZS1jb21wcmVzc2lvbiIpO2xldCBDPSJtYXQtd3JpdGUtdHJhbnNmb3JtIixzPXQ/LndlYldvcmtlcjtzPT09dm9pZCAwJiYocz1hd2FpdCB3KCkpO2xldHt3ZWJXb3JrZXI6YSxyZXR1cm5WYWx1ZTpjLHN0ZGVycjpJLG91dHB1dHM6bH09YXdhaXQgeShDLG8scixuLHtwaXBlbGluZUJhc2VVcmw6aCgpLHBpcGVsaW5lV29ya2VyVXJsOmQoKSx3ZWJXb3JrZXI6cyxub0NvcHk6dD8ubm9Db3B5fSk7aWYoYyE9PTAmJkkhPT0iIil0aHJvdyBuZXcgRXJyb3IoSSk7cmV0dXJue3dlYldvcmtlcjphLGNvdWxkV3JpdGU6bFswXT8uZGF0YSxzZXJpYWxpemVkVHJhbnNmb3JtOmxbMV0/LmRhdGF9fXZhciBvbz1ybzthc3luYyBmdW5jdGlvbiBubyhBLGU9e30pe2xldCB0PVt7dHlwZTpFLkpzb25Db21wYXRpYmxlfSx7dHlwZTpFLlRyYW5zZm9ybUxpc3R9XSxyPUE7aWYoQSBpbnN0YW5jZW9mIEZpbGUpe2xldCBRPWF3YWl0IEEuYXJyYXlCdWZmZXIoKTtyPXtwYXRoOkEubmFtZSxkYXRhOm5ldyBVaW50OEFycmF5KFEpfX1sZXQgbj1be3R5cGU6RS5CaW5hcnlGaWxlLGRhdGE6cn1dLG89W10saT1yLnBhdGg7by5wdXNoKGkpLG8ucHVzaCgiMCIpLG8ucHVzaCgiMSIpLG8ucHVzaCgiLS1tZW1vcnktaW8iKSxlLmZsb2F0UGFyYW1ldGVycyYmZS5mbG9hdFBhcmFtZXRlcnMmJm8ucHVzaCgiLS1mbG9hdC1wYXJhbWV0ZXJzIik7bGV0IEM9Im1uYy1yZWFkLXRyYW5zZm9ybSIscz1lPy53ZWJXb3JrZXI7cz09PXZvaWQgMCYmKHM9YXdhaXQgdygpKTtsZXR7d2ViV29ya2VyOmEscmV0dXJuVmFsdWU6YyxzdGRlcnI6SSxvdXRwdXRzOmx9PWF3YWl0IHkoQyxvLHQsbix7cGlwZWxpbmVCYXNlVXJsOmgoKSxwaXBlbGluZVdvcmtlclVybDpkKCksd2ViV29ya2VyOnMsbm9Db3B5OmU/Lm5vQ29weX0pO2lmKGMhPT0wJiZJIT09IiIpdGhyb3cgbmV3IEVycm9yKEkpO3JldHVybnt3ZWJXb3JrZXI6YSxjb3VsZFJlYWQ6bFswXT8uZGF0YSx0cmFuc2Zvcm06bFsxXT8uZGF0YX19dmFyIGlvPW5vO2FzeW5jIGZ1bmN0aW9uIGFvKEEsZSx0PXt9KXtsZXQgcj1be3R5cGU6RS5Kc29uQ29tcGF0aWJsZX0se3R5cGU6RS5CaW5hcnlGaWxlLGRhdGE6e3BhdGg6ZSxkYXRhOm5ldyBVaW50OEFycmF5fX1dLG49W3t0eXBlOkUuVHJhbnNmb3JtTGlzdCxkYXRhOkF9XSxvPVtdO28ucHVzaCgiMCIpLG8ucHVzaCgiMCIpO2xldCB1PWU7by5wdXNoKHUpLG8ucHVzaCgiLS1tZW1vcnktaW8iKSx0LmZsb2F0UGFyYW1ldGVycyYmdC5mbG9hdFBhcmFtZXRlcnMmJm8ucHVzaCgiLS1mbG9hdC1wYXJhbWV0ZXJzIiksdC51c2VDb21wcmVzc2lvbiYmdC51c2VDb21wcmVzc2lvbiYmby5wdXNoKCItLXVzZS1jb21wcmVzc2lvbiIpO2xldCBDPSJtbmMtd3JpdGUtdHJhbnNmb3JtIixzPXQ/LndlYldvcmtlcjtzPT09dm9pZCAwJiYocz1hd2FpdCB3KCkpO2xldHt3ZWJXb3JrZXI6YSxyZXR1cm5WYWx1ZTpjLHN0ZGVycjpJLG91dHB1dHM6bH09YXdhaXQgeShDLG8scixuLHtwaXBlbGluZUJhc2VVcmw6aCgpLHBpcGVsaW5lV29ya2VyVXJsOmQoKSx3ZWJXb3JrZXI6cyxub0NvcHk6dD8ubm9Db3B5fSk7aWYoYyE9PTAmJkkhPT0iIil0aHJvdyBuZXcgRXJyb3IoSSk7cmV0dXJue3dlYldvcmtlcjphLGNvdWxkV3JpdGU6bFswXT8uZGF0YSxzZXJpYWxpemVkVHJhbnNmb3JtOmxbMV0/LmRhdGF9fXZhciBzbz1hbzthc3luYyBmdW5jdGlvbiBJbyhBLGU9e30pe2xldCB0PVt7dHlwZTpFLkpzb25Db21wYXRpYmxlfSx7dHlwZTpFLlRyYW5zZm9ybUxpc3R9XSxyPUE7aWYoQSBpbnN0YW5jZW9mIEZpbGUpe2xldCBRPWF3YWl0IEEuYXJyYXlCdWZmZXIoKTtyPXtwYXRoOkEubmFtZSxkYXRhOm5ldyBVaW50OEFycmF5KFEpfX1sZXQgbj1be3R5cGU6RS5CaW5hcnlGaWxlLGRhdGE6cn1dLG89W10saT1yLnBhdGg7by5wdXNoKGkpLG8ucHVzaCgiMCIpLG8ucHVzaCgiMSIpLG8ucHVzaCgiLS1tZW1vcnktaW8iKSxlLmZsb2F0UGFyYW1ldGVycyYmZS5mbG9hdFBhcmFtZXRlcnMmJm8ucHVzaCgiLS1mbG9hdC1wYXJhbWV0ZXJzIik7bGV0IEM9InR4dC1yZWFkLXRyYW5zZm9ybSIscz1lPy53ZWJXb3JrZXI7cz09PXZvaWQgMCYmKHM9YXdhaXQgdygpKTtsZXR7d2ViV29ya2VyOmEscmV0dXJuVmFsdWU6YyxzdGRlcnI6SSxvdXRwdXRzOmx9PWF3YWl0IHkoQyxvLHQsbix7cGlwZWxpbmVCYXNlVXJsOmgoKSxwaXBlbGluZVdvcmtlclVybDpkKCksd2ViV29ya2VyOnMsbm9Db3B5OmU/Lm5vQ29weX0pO2lmKGMhPT0wJiZJIT09IiIpdGhyb3cgbmV3IEVycm9yKEkpO3JldHVybnt3ZWJXb3JrZXI6YSxjb3VsZFJlYWQ6bFswXT8uZGF0YSx0cmFuc2Zvcm06bFsxXT8uZGF0YX19dmFyIGdvPUlvO2FzeW5jIGZ1bmN0aW9uIEJvKEEsZSx0PXt9KXtsZXQgcj1be3R5cGU6RS5Kc29uQ29tcGF0aWJsZX0se3R5cGU6RS5CaW5hcnlGaWxlLGRhdGE6e3BhdGg6ZSxkYXRhOm5ldyBVaW50OEFycmF5fX1dLG49W3t0eXBlOkUuVHJhbnNmb3JtTGlzdCxkYXRhOkF9XSxvPVtdO28ucHVzaCgiMCIpLG8ucHVzaCgiMCIpO2xldCB1PWU7by5wdXNoKHUpLG8ucHVzaCgiLS1tZW1vcnktaW8iKSx0LmZsb2F0UGFyYW1ldGVycyYmdC5mbG9hdFBhcmFtZXRlcnMmJm8ucHVzaCgiLS1mbG9hdC1wYXJhbWV0ZXJzIiksdC51c2VDb21wcmVzc2lvbiYmdC51c2VDb21wcmVzc2lvbiYmby5wdXNoKCItLXVzZS1jb21wcmVzc2lvbiIpO2xldCBDPSJ0eHQtd3JpdGUtdHJhbnNmb3JtIixzPXQ/LndlYldvcmtlcjtzPT09dm9pZCAwJiYocz1hd2FpdCB3KCkpO2xldHt3ZWJXb3JrZXI6YSxyZXR1cm5WYWx1ZTpjLHN0ZGVycjpJLG91dHB1dHM6bH09YXdhaXQgeShDLG8scixuLHtwaXBlbGluZUJhc2VVcmw6aCgpLHBpcGVsaW5lV29ya2VyVXJsOmQoKSx3ZWJXb3JrZXI6cyxub0NvcHk6dD8ubm9Db3B5fSk7aWYoYyE9PTAmJkkhPT0iIil0aHJvdyBuZXcgRXJyb3IoSSk7cmV0dXJue3dlYldvcmtlcjphLGNvdWxkV3JpdGU6bFswXT8uZGF0YSxzZXJpYWxpemVkVHJhbnNmb3JtOmxbMV0/LmRhdGF9fXZhciBDbz1Cbzthc3luYyBmdW5jdGlvbiBsbyhBLGU9e30pe2xldCB0PVt7dHlwZTpFLkpzb25Db21wYXRpYmxlfSx7dHlwZTpFLlRyYW5zZm9ybUxpc3R9XSxyPUE7aWYoQSBpbnN0YW5jZW9mIEZpbGUpe2xldCBRPWF3YWl0IEEuYXJyYXlCdWZmZXIoKTtyPXtwYXRoOkEubmFtZSxkYXRhOm5ldyBVaW50OEFycmF5KFEpfX1sZXQgbj1be3R5cGU6RS5CaW5hcnlGaWxlLGRhdGE6cn1dLG89W10saT1yLnBhdGg7by5wdXNoKGkpLG8ucHVzaCgiMCIpLG8ucHVzaCgiMSIpLG8ucHVzaCgiLS1tZW1vcnktaW8iKSxlLmZsb2F0UGFyYW1ldGVycyYmZS5mbG9hdFBhcmFtZXRlcnMmJm8ucHVzaCgiLS1mbG9hdC1wYXJhbWV0ZXJzIik7bGV0IEM9Indhc20tcmVhZC10cmFuc2Zvcm0iLHM9ZT8ud2ViV29ya2VyO3M9PT12b2lkIDAmJihzPWF3YWl0IHcoKSk7bGV0e3dlYldvcmtlcjphLHJldHVyblZhbHVlOmMsc3RkZXJyOkksb3V0cHV0czpsfT1hd2FpdCB5KEMsbyx0LG4se3BpcGVsaW5lQmFzZVVybDpoKCkscGlwZWxpbmVXb3JrZXJVcmw6ZCgpLHdlYldvcmtlcjpzLG5vQ29weTplPy5ub0NvcHl9KTtpZihjIT09MCYmSSE9PSIiKXRocm93IG5ldyBFcnJvcihJKTtyZXR1cm57d2ViV29ya2VyOmEsY291bGRSZWFkOmxbMF0/LmRhdGEsdHJhbnNmb3JtOmxbMV0/LmRhdGF9fXZhciBmbz1sbzthc3luYyBmdW5jdGlvbiBjbyhBLGUsdD17fSl7bGV0IHI9W3t0eXBlOkUuSnNvbkNvbXBhdGlibGV9LHt0eXBlOkUuQmluYXJ5RmlsZSxkYXRhOntwYXRoOmUsZGF0YTpuZXcgVWludDhBcnJheX19XSxuPVt7dHlwZTpFLlRyYW5zZm9ybUxpc3QsZGF0YTpBfV0sbz1bXTtvLnB1c2goIjAiKSxvLnB1c2goIjAiKTtsZXQgdT1lO28ucHVzaCh1KSxvLnB1c2goIi0tbWVtb3J5LWlvIiksdC5mbG9hdFBhcmFtZXRlcnMmJnQuZmxvYXRQYXJhbWV0ZXJzJiZvLnB1c2goIi0tZmxvYXQtcGFyYW1ldGVycyIpLHQudXNlQ29tcHJlc3Npb24mJnQudXNlQ29tcHJlc3Npb24mJm8ucHVzaCgiLS11c2UtY29tcHJlc3Npb24iKTtsZXQgQz0id2FzbS13cml0ZS10cmFuc2Zvcm0iLHM9dD8ud2ViV29ya2VyO3M9PT12b2lkIDAmJihzPWF3YWl0IHcoKSk7bGV0e3dlYldvcmtlcjphLHJldHVyblZhbHVlOmMsc3RkZXJyOkksb3V0cHV0czpsfT1hd2FpdCB5KEMsbyxyLG4se3BpcGVsaW5lQmFzZVVybDpoKCkscGlwZWxpbmVXb3JrZXJVcmw6ZCgpLHdlYldvcmtlcjpzLG5vQ29weTp0Py5ub0NvcHl9KTtpZihjIT09MCYmSSE9PSIiKXRocm93IG5ldyBFcnJvcihJKTtyZXR1cm57d2ViV29ya2VyOmEsY291bGRXcml0ZTpsWzBdPy5kYXRhLHNlcmlhbGl6ZWRUcmFuc2Zvcm06bFsxXT8uZGF0YX19dmFyIHVvPWNvO2FzeW5jIGZ1bmN0aW9uIEVvKEEsZT17fSl7bGV0IHQ9W3t0eXBlOkUuSnNvbkNvbXBhdGlibGV9LHt0eXBlOkUuVHJhbnNmb3JtTGlzdH1dLHI9QTtpZihBIGluc3RhbmNlb2YgRmlsZSl7bGV0IFE9YXdhaXQgQS5hcnJheUJ1ZmZlcigpO3I9e3BhdGg6QS5uYW1lLGRhdGE6bmV3IFVpbnQ4QXJyYXkoUSl9fWxldCBuPVt7dHlwZTpFLkJpbmFyeUZpbGUsZGF0YTpyfV0sbz1bXSxpPXIucGF0aDtvLnB1c2goaSksby5wdXNoKCIwIiksby5wdXNoKCIxIiksby5wdXNoKCItLW1lbW9yeS1pbyIpLGUuZmxvYXRQYXJhbWV0ZXJzJiZlLmZsb2F0UGFyYW1ldGVycyYmby5wdXNoKCItLWZsb2F0LXBhcmFtZXRlcnMiKTtsZXQgQz0id2FzbS16c3RkLXJlYWQtdHJhbnNmb3JtIixzPWU/LndlYldvcmtlcjtzPT09dm9pZCAwJiYocz1hd2FpdCB3KCkpO2xldHt3ZWJXb3JrZXI6YSxyZXR1cm5WYWx1ZTpjLHN0ZGVycjpJLG91dHB1dHM6bH09YXdhaXQgeShDLG8sdCxuLHtwaXBlbGluZUJhc2VVcmw6aCgpLHBpcGVsaW5lV29ya2VyVXJsOmQoKSx3ZWJXb3JrZXI6cyxub0NvcHk6ZT8ubm9Db3B5fSk7aWYoYyE9PTAmJkkhPT0iIil0aHJvdyBuZXcgRXJyb3IoSSk7cmV0dXJue3dlYldvcmtlcjphLGNvdWxkUmVhZDpsWzBdPy5kYXRhLHRyYW5zZm9ybTpsWzFdPy5kYXRhfX12YXIgUW89RW87YXN5bmMgZnVuY3Rpb24gcG8oQSxlLHQ9e30pe2xldCByPVt7dHlwZTpFLkpzb25Db21wYXRpYmxlfSx7dHlwZTpFLkJpbmFyeUZpbGUsZGF0YTp7cGF0aDplLGRhdGE6bmV3IFVpbnQ4QXJyYXl9fV0sbj1be3R5cGU6RS5UcmFuc2Zvcm1MaXN0LGRhdGE6QX1dLG89W107by5wdXNoKCIwIiksby5wdXNoKCIwIik7bGV0IHU9ZTtvLnB1c2godSksby5wdXNoKCItLW1lbW9yeS1pbyIpLHQuZmxvYXRQYXJhbWV0ZXJzJiZ0LmZsb2F0UGFyYW1ldGVycyYmby5wdXNoKCItLWZsb2F0LXBhcmFtZXRlcnMiKSx0LnVzZUNvbXByZXNzaW9uJiZ0LnVzZUNvbXByZXNzaW9uJiZvLnB1c2goIi0tdXNlLWNvbXByZXNzaW9uIik7bGV0IEM9Indhc20tenN0ZC13cml0ZS10cmFuc2Zvcm0iLHM9dD8ud2ViV29ya2VyO3M9PT12b2lkIDAmJihzPWF3YWl0IHcoKSk7bGV0e3dlYldvcmtlcjphLHJldHVyblZhbHVlOmMsc3RkZXJyOkksb3V0cHV0czpsfT1hd2FpdCB5KEMsbyxyLG4se3BpcGVsaW5lQmFzZVVybDpoKCkscGlwZWxpbmVXb3JrZXJVcmw6ZCgpLHdlYldvcmtlcjpzLG5vQ29weTp0Py5ub0NvcHl9KTtpZihjIT09MCYmSSE9PSIiKXRocm93IG5ldyBFcnJvcihJKTtyZXR1cm57d2ViV29ya2VyOmEsY291bGRXcml0ZTpsWzBdPy5kYXRhLHNlcmlhbGl6ZWRUcmFuc2Zvcm06bFsxXT8uZGF0YX19dmFyIG1vPXBvO3ZhciBsdD0nZGF0YTp0ZXh0L2phdmFzY3JpcHQ7Y2hhcnNldD11dGYtOCx2YXIgSUk9T2JqZWN0LmRlZmluZVByb3BlcnR5O3ZhciBlST0oQSx0KT0+e2Zvcih2YXIgSSBpbiB0KUlJKEEsSSx7Z2V0OnRbSV0sZW51bWVyYWJsZTohMH0pfTt2YXIgdkE9U3ltYm9sKCJDb21saW5rLnByb3h5IiksZ0k9U3ltYm9sKCJDb21saW5rLmVuZHBvaW50Iiksckk9U3ltYm9sKCJDb21saW5rLnJlbGVhc2VQcm94eSIpLHBBPVN5bWJvbCgiQ29tbGluay5maW5hbGl6ZXIiKSxnQT1TeW1ib2woIkNvbWxpbmsudGhyb3duIiksJEE9QT0+dHlwZW9mIEE9PSJvYmplY3QiJiZBIT09bnVsbHx8dHlwZW9mIEE9PSJmdW5jdGlvbiIsb0k9e2NhbkhhbmRsZTpBPT4kQShBKSYmQVt2QV0sc2VyaWFsaXplKEEpe2xldHtwb3J0MTp0LHBvcnQyOkl9PW5ldyBNZXNzYWdlQ2hhbm5lbDtyZXR1cm4gQ0EoQSx0KSxbSSxbSV1dfSxkZXNlcmlhbGl6ZShBKXtyZXR1cm4gQS5zdGFydCgpLHNJKEEpfX0saUk9e2NhbkhhbmRsZTpBPT4kQShBKSYmZ0EgaW4gQSxzZXJpYWxpemUoe3ZhbHVlOkF9KXtsZXQgdDtyZXR1cm4gQSBpbnN0YW5jZW9mIEVycm9yP3Q9e2lzRXJyb3I6ITAsdmFsdWU6e21lc3NhZ2U6QS5tZXNzYWdlLG5hbWU6QS5uYW1lLHN0YWNrOkEuc3RhY2t9fTp0PXtpc0Vycm9yOiExLHZhbHVlOkF9LFt0LFtdXX0sZGVzZXJpYWxpemUoQSl7dGhyb3cgQS5pc0Vycm9yP09iamVjdC5hc3NpZ24obmV3IEVycm9yKEEudmFsdWUubWVzc2FnZSksQS52YWx1ZSk6QS52YWx1ZX19LEF0PW5ldyBNYXAoW1sicHJveHkiLG9JXSxbInRocm93IixpSV1dKTtmdW5jdGlvbiBDSShBLHQpe2ZvcihsZXQgSSBvZiBBKWlmKHQ9PT1JfHxJPT09IioifHxJIGluc3RhbmNlb2YgUmVnRXhwJiZJLnRlc3QodCkpcmV0dXJuITA7cmV0dXJuITF9ZnVuY3Rpb24gQ0EoQSx0PWdsb2JhbFRoaXMsST1bIioiXSl7dC5hZGRFdmVudExpc3RlbmVyKCJtZXNzYWdlIixmdW5jdGlvbiBlKGcpe2lmKCFnfHwhZy5kYXRhKXJldHVybjtpZighQ0koSSxnLm9yaWdpbikpe2NvbnNvbGUud2FybihgSW52YWxpZCBvcmlnaW4gXCcke2cub3JpZ2lufVwnIGZvciBjb21saW5rIHByb3h5YCk7cmV0dXJufWxldHtpZDpyLHR5cGU6byxwYXRoOm59PU9iamVjdC5hc3NpZ24oe3BhdGg6W119LGcuZGF0YSksYz0oZy5kYXRhLmFyZ3VtZW50TGlzdHx8W10pLm1hcChNKSxRO3RyeXtsZXQgQj1uLnNsaWNlKDAsLTEpLnJlZHVjZSgoZixzKT0+ZltzXSxBKSxpPW4ucmVkdWNlKChmLHMpPT5mW3NdLEEpO3N3aXRjaChvKXtjYXNlIkdFVCI6UT1pO2JyZWFrO2Nhc2UiU0VUIjpCW24uc2xpY2UoLTEpWzBdXT1NKGcuZGF0YS52YWx1ZSksUT0hMDticmVhaztjYXNlIkFQUExZIjpRPWkuYXBwbHkoQixjKTticmVhaztjYXNlIkNPTlNUUlVDVCI6e2xldCBmPW5ldyBpKC4uLmMpO1E9RUkoZil9YnJlYWs7Y2FzZSJFTkRQT0lOVCI6e2xldHtwb3J0MTpmLHBvcnQyOnN9PW5ldyBNZXNzYWdlQ2hhbm5lbDtDQShBLHMpLFE9RkEoZixbZl0pfWJyZWFrO2Nhc2UiUkVMRUFTRSI6UT12b2lkIDA7YnJlYWs7ZGVmYXVsdDpyZXR1cm59fWNhdGNoKEIpe1E9e3ZhbHVlOkIsW2dBXTowfX1Qcm9taXNlLnJlc29sdmUoUSkuY2F0Y2goQj0+KHt2YWx1ZTpCLFtnQV06MH0pKS50aGVuKEI9PntsZXRbaSxmXT1pQShCKTt0LnBvc3RNZXNzYWdlKE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSxpKSx7aWQ6cn0pLGYpLG89PT0iUkVMRUFTRSImJih0LnJlbW92ZUV2ZW50TGlzdGVuZXIoIm1lc3NhZ2UiLGUpLHR0KHQpLHBBIGluIEEmJnR5cGVvZiBBW3BBXT09ImZ1bmN0aW9uIiYmQVtwQV0oKSl9KS5jYXRjaChCPT57bGV0W2ksZl09aUEoe3ZhbHVlOm5ldyBUeXBlRXJyb3IoIlVuc2VyaWFsaXphYmxlIHJldHVybiB2YWx1ZSIpLFtnQV06MH0pO3QucG9zdE1lc3NhZ2UoT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LGkpLHtpZDpyfSksZil9KX0pLHQuc3RhcnQmJnQuc3RhcnQoKX1mdW5jdGlvbiBCSShBKXtyZXR1cm4gQS5jb25zdHJ1Y3Rvci5uYW1lPT09Ik1lc3NhZ2VQb3J0In1mdW5jdGlvbiB0dChBKXtCSShBKSYmQS5jbG9zZSgpfWZ1bmN0aW9uIHNJKEEsdCl7cmV0dXJuIFNBKEEsW10sdCl9ZnVuY3Rpb24gZUEoQSl7aWYoQSl0aHJvdyBuZXcgRXJyb3IoIlByb3h5IGhhcyBiZWVuIHJlbGVhc2VkIGFuZCBpcyBub3QgdXNlYWJsZSIpfWZ1bmN0aW9uIEl0KEEpe3JldHVybiBxKEEse3R5cGU6IlJFTEVBU0UifSkudGhlbigoKT0+e3R0KEEpfSl9dmFyIHJBPW5ldyBXZWFrTWFwLG9BPSJGaW5hbGl6YXRpb25SZWdpc3RyeSJpbiBnbG9iYWxUaGlzJiZuZXcgRmluYWxpemF0aW9uUmVnaXN0cnkoQT0+e2xldCB0PShyQS5nZXQoQSl8fDApLTE7ckEuc2V0KEEsdCksdD09PTAmJkl0KEEpfSk7ZnVuY3Rpb24gbkkoQSx0KXtsZXQgST0ockEuZ2V0KHQpfHwwKSsxO3JBLnNldCh0LEkpLG9BJiZvQS5yZWdpc3RlcihBLHQsQSl9ZnVuY3Rpb24gUUkoQSl7b0EmJm9BLnVucmVnaXN0ZXIoQSl9ZnVuY3Rpb24gU0EoQSx0PVtdLEk9ZnVuY3Rpb24oKXt9KXtsZXQgZT0hMSxnPW5ldyBQcm94eShJLHtnZXQocixvKXtpZihlQShlKSxvPT09ckkpcmV0dXJuKCk9PntRSShnKSxJdChBKSxlPSEwfTtpZihvPT09InRoZW4iKXtpZih0Lmxlbmd0aD09PTApcmV0dXJue3RoZW46KCk9Pmd9O2xldCBuPXEoQSx7dHlwZToiR0VUIixwYXRoOnQubWFwKGM9PmMudG9TdHJpbmcoKSl9KS50aGVuKE0pO3JldHVybiBuLnRoZW4uYmluZChuKX1yZXR1cm4gU0EoQSxbLi4udCxvXSl9LHNldChyLG8sbil7ZUEoZSk7bGV0W2MsUV09aUEobik7cmV0dXJuIHEoQSx7dHlwZToiU0VUIixwYXRoOlsuLi50LG9dLm1hcChCPT5CLnRvU3RyaW5nKCkpLHZhbHVlOmN9LFEpLnRoZW4oTSl9LGFwcGx5KHIsbyxuKXtlQShlKTtsZXQgYz10W3QubGVuZ3RoLTFdO2lmKGM9PT1nSSlyZXR1cm4gcShBLHt0eXBlOiJFTkRQT0lOVCJ9KS50aGVuKE0pO2lmKGM9PT0iYmluZCIpcmV0dXJuIFNBKEEsdC5zbGljZSgwLC0xKSk7bGV0W1EsQl09X0Eobik7cmV0dXJuIHEoQSx7dHlwZToiQVBQTFkiLHBhdGg6dC5tYXAoaT0+aS50b1N0cmluZygpKSxhcmd1bWVudExpc3Q6UX0sQikudGhlbihNKX0sY29uc3RydWN0KHIsbyl7ZUEoZSk7bGV0W24sY109X0Eobyk7cmV0dXJuIHEoQSx7dHlwZToiQ09OU1RSVUNUIixwYXRoOnQubWFwKFE9PlEudG9TdHJpbmcoKSksYXJndW1lbnRMaXN0Om59LGMpLnRoZW4oTSl9fSk7cmV0dXJuIG5JKGcsQSksZ31mdW5jdGlvbiBhSShBKXtyZXR1cm4gQXJyYXkucHJvdG90eXBlLmNvbmNhdC5hcHBseShbXSxBKX1mdW5jdGlvbiBfQShBKXtsZXQgdD1BLm1hcChpQSk7cmV0dXJuW3QubWFwKEk9PklbMF0pLGFJKHQubWFwKEk9PklbMV0pKV19dmFyIGV0PW5ldyBXZWFrTWFwO2Z1bmN0aW9uIEZBKEEsdCl7cmV0dXJuIGV0LnNldChBLHQpLEF9ZnVuY3Rpb24gRUkoQSl7cmV0dXJuIE9iamVjdC5hc3NpZ24oQSx7W3ZBXTohMH0pfWZ1bmN0aW9uIGlBKEEpe2ZvcihsZXRbdCxJXW9mIEF0KWlmKEkuY2FuSGFuZGxlKEEpKXtsZXRbZSxnXT1JLnNlcmlhbGl6ZShBKTtyZXR1cm5be3R5cGU6IkhBTkRMRVIiLG5hbWU6dCx2YWx1ZTplfSxnXX1yZXR1cm5be3R5cGU6IlJBVyIsdmFsdWU6QX0sZXQuZ2V0KEEpfHxbXV19ZnVuY3Rpb24gTShBKXtzd2l0Y2goQS50eXBlKXtjYXNlIkhBTkRMRVIiOnJldHVybiBBdC5nZXQoQS5uYW1lKS5kZXNlcmlhbGl6ZShBLnZhbHVlKTtjYXNlIlJBVyI6cmV0dXJuIEEudmFsdWV9fWZ1bmN0aW9uIHEoQSx0LEkpe3JldHVybiBuZXcgUHJvbWlzZShlPT57bGV0IGc9Y0koKTtBLmFkZEV2ZW50TGlzdGVuZXIoIm1lc3NhZ2UiLGZ1bmN0aW9uIHIobyl7IW8uZGF0YXx8IW8uZGF0YS5pZHx8by5kYXRhLmlkIT09Z3x8KEEucmVtb3ZlRXZlbnRMaXN0ZW5lcigibWVzc2FnZSIsciksZShvLmRhdGEpKX0pLEEuc3RhcnQmJkEuc3RhcnQoKSxBLnBvc3RNZXNzYWdlKE9iamVjdC5hc3NpZ24oe2lkOmd9LHQpLEkpfSl9ZnVuY3Rpb24gY0koKXtyZXR1cm4gbmV3IEFycmF5KDQpLmZpbGwoMCkubWFwKCgpPT5NYXRoLmZsb29yKE1hdGgucmFuZG9tKCkqTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVIpLnRvU3RyaW5nKDE2KSkuam9pbigiLSIpfWZ1bmN0aW9uIFcoQSx0KXtyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gQS5hcHBseSh0LGFyZ3VtZW50cyl9fXZhcnt0b1N0cmluZzpmSX09T2JqZWN0LnByb3RvdHlwZSx7Z2V0UHJvdG90eXBlT2Y6VUF9PU9iamVjdCxzQT0oQT0+dD0+e2xldCBJPWZJLmNhbGwodCk7cmV0dXJuIEFbSV18fChBW0ldPUkuc2xpY2UoOCwtMSkudG9Mb3dlckNhc2UoKSl9KShPYmplY3QuY3JlYXRlKG51bGwpKSxVPUE9PihBPUEudG9Mb3dlckNhc2UoKSx0PT5zQSh0KT09PUEpLG5BPUE9PnQ9PnR5cGVvZiB0PT09QSx7aXNBcnJheTpLfT1BcnJheSxaPW5BKCJ1bmRlZmluZWQiKTtmdW5jdGlvbiBsSShBKXtyZXR1cm4gQSE9PW51bGwmJiFaKEEpJiZBLmNvbnN0cnVjdG9yIT09bnVsbCYmIVooQS5jb25zdHJ1Y3RvcikmJk4oQS5jb25zdHJ1Y3Rvci5pc0J1ZmZlcikmJkEuY29uc3RydWN0b3IuaXNCdWZmZXIoQSl9dmFyIGl0PVUoIkFycmF5QnVmZmVyIik7ZnVuY3Rpb24gREkoQSl7bGV0IHQ7cmV0dXJuIHR5cGVvZiBBcnJheUJ1ZmZlcjwidSImJkFycmF5QnVmZmVyLmlzVmlldz90PUFycmF5QnVmZmVyLmlzVmlldyhBKTp0PUEmJkEuYnVmZmVyJiZpdChBLmJ1ZmZlciksdH12YXIgdUk9bkEoInN0cmluZyIpLE49bkEoImZ1bmN0aW9uIiksQ3Q9bkEoIm51bWJlciIpLFFBPUE9PkEhPT1udWxsJiZ0eXBlb2YgQT09Im9iamVjdCIsaEk9QT0+QT09PSEwfHxBPT09ITEsQkE9QT0+e2lmKHNBKEEpIT09Im9iamVjdCIpcmV0dXJuITE7bGV0IHQ9VUEoQSk7cmV0dXJuKHQ9PT1udWxsfHx0PT09T2JqZWN0LnByb3RvdHlwZXx8T2JqZWN0LmdldFByb3RvdHlwZU9mKHQpPT09bnVsbCkmJiEoU3ltYm9sLnRvU3RyaW5nVGFnIGluIEEpJiYhKFN5bWJvbC5pdGVyYXRvciBpbiBBKX0sZEk9VSgiRGF0ZSIpLHlJPVUoIkZpbGUiKSx3ST1VKCJCbG9iIiksbUk9VSgiRmlsZUxpc3QiKSxwST1BPT5RQShBKSYmTihBLnBpcGUpLFNJPUE9PntsZXQgdDtyZXR1cm4gQSYmKHR5cGVvZiBGb3JtRGF0YT09ImZ1bmN0aW9uIiYmQSBpbnN0YW5jZW9mIEZvcm1EYXRhfHxOKEEuYXBwZW5kKSYmKCh0PXNBKEEpKT09PSJmb3JtZGF0YSJ8fHQ9PT0ib2JqZWN0IiYmTihBLnRvU3RyaW5nKSYmQS50b1N0cmluZygpPT09IltvYmplY3QgRm9ybURhdGFdIikpfSxGST1VKCJVUkxTZWFyY2hQYXJhbXMiKSxSST1BPT5BLnRyaW0/QS50cmltKCk6QS5yZXBsYWNlKC9eW1xcc1xcdUZFRkZcXHhBMF0rfFtcXHNcXHVGRUZGXFx4QTBdKyQvZywiIik7ZnVuY3Rpb24gVihBLHQse2FsbE93bktleXM6ST0hMX09e30pe2lmKEE9PT1udWxsfHx0eXBlb2YgQT4idSIpcmV0dXJuO2xldCBlLGc7aWYodHlwZW9mIEEhPSJvYmplY3QiJiYoQT1bQV0pLEsoQSkpZm9yKGU9MCxnPUEubGVuZ3RoO2U8ZztlKyspdC5jYWxsKG51bGwsQVtlXSxlLEEpO2Vsc2V7bGV0IHI9ST9PYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhBKTpPYmplY3Qua2V5cyhBKSxvPXIubGVuZ3RoLG47Zm9yKGU9MDtlPG87ZSsrKW49cltlXSx0LmNhbGwobnVsbCxBW25dLG4sQSl9fWZ1bmN0aW9uIEJ0KEEsdCl7dD10LnRvTG93ZXJDYXNlKCk7bGV0IEk9T2JqZWN0LmtleXMoQSksZT1JLmxlbmd0aCxnO2Zvcig7ZS0tID4wOylpZihnPUlbZV0sdD09PWcudG9Mb3dlckNhc2UoKSlyZXR1cm4gZztyZXR1cm4gbnVsbH12YXIgc3Q9dHlwZW9mIGdsb2JhbFRoaXM8InUiP2dsb2JhbFRoaXM6dHlwZW9mIHNlbGY8InUiP3NlbGY6dHlwZW9mIHdpbmRvdzwidSI/d2luZG93Omdsb2JhbCxudD1BPT4hWihBKSYmQSE9PXN0O2Z1bmN0aW9uIE5BKCl7bGV0e2Nhc2VsZXNzOkF9PW50KHRoaXMpJiZ0aGlzfHx7fSx0PXt9LEk9KGUsZyk9PntsZXQgcj1BJiZCdCh0LGcpfHxnO0JBKHRbcl0pJiZCQShlKT90W3JdPU5BKHRbcl0sZSk6QkEoZSk/dFtyXT1OQSh7fSxlKTpLKGUpP3Rbcl09ZS5zbGljZSgpOnRbcl09ZX07Zm9yKGxldCBlPTAsZz1hcmd1bWVudHMubGVuZ3RoO2U8ZztlKyspYXJndW1lbnRzW2VdJiZWKGFyZ3VtZW50c1tlXSxJKTtyZXR1cm4gdH12YXIgTkk9KEEsdCxJLHthbGxPd25LZXlzOmV9PXt9KT0+KFYodCwoZyxyKT0+e0kmJk4oZyk/QVtyXT1XKGcsSSk6QVtyXT1nfSx7YWxsT3duS2V5czplfSksQSksVUk9QT0+KEEuY2hhckNvZGVBdCgwKT09PTY1Mjc5JiYoQT1BLnNsaWNlKDEpKSxBKSxHST0oQSx0LEksZSk9PntBLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHQucHJvdG90eXBlLGUpLEEucHJvdG90eXBlLmNvbnN0cnVjdG9yPUEsT2JqZWN0LmRlZmluZVByb3BlcnR5KEEsInN1cGVyIix7dmFsdWU6dC5wcm90b3R5cGV9KSxJJiZPYmplY3QuYXNzaWduKEEucHJvdG90eXBlLEkpfSxrST0oQSx0LEksZSk9PntsZXQgZyxyLG8sbj17fTtpZih0PXR8fHt9LEE9PW51bGwpcmV0dXJuIHQ7ZG97Zm9yKGc9T2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMoQSkscj1nLmxlbmd0aDtyLS0gPjA7KW89Z1tyXSwoIWV8fGUobyxBLHQpKSYmIW5bb10mJih0W29dPUFbb10sbltvXT0hMCk7QT1JIT09ITEmJlVBKEEpfXdoaWxlKEEmJighSXx8SShBLHQpKSYmQSE9PU9iamVjdC5wcm90b3R5cGUpO3JldHVybiB0fSxMST0oQSx0LEkpPT57QT1TdHJpbmcoQSksKEk9PT12b2lkIDB8fEk+QS5sZW5ndGgpJiYoST1BLmxlbmd0aCksSS09dC5sZW5ndGg7bGV0IGU9QS5pbmRleE9mKHQsSSk7cmV0dXJuIGUhPT0tMSYmZT09PUl9LEpJPUE9PntpZighQSlyZXR1cm4gbnVsbDtpZihLKEEpKXJldHVybiBBO2xldCB0PUEubGVuZ3RoO2lmKCFDdCh0KSlyZXR1cm4gbnVsbDtsZXQgST1uZXcgQXJyYXkodCk7Zm9yKDt0LS0gPjA7KUlbdF09QVt0XTtyZXR1cm4gSX0sSEk9KEE9PnQ9PkEmJnQgaW5zdGFuY2VvZiBBKSh0eXBlb2YgVWludDhBcnJheTwidSImJlVBKFVpbnQ4QXJyYXkpKSxZST0oQSx0KT0+e2xldCBlPShBJiZBW1N5bWJvbC5pdGVyYXRvcl0pLmNhbGwoQSksZztmb3IoOyhnPWUubmV4dCgpKSYmIWcuZG9uZTspe2xldCByPWcudmFsdWU7dC5jYWxsKEEsclswXSxyWzFdKX19LGJJPShBLHQpPT57bGV0IEksZT1bXTtmb3IoOyhJPUEuZXhlYyh0KSkhPT1udWxsOyllLnB1c2goSSk7cmV0dXJuIGV9LE1JPVUoIkhUTUxGb3JtRWxlbWVudCIpLHFJPUE9PkEudG9Mb3dlckNhc2UoKS5yZXBsYWNlKC9bLV9cXHNdKFthLXpcXGRdKShcXHcqKS9nLGZ1bmN0aW9uKEksZSxnKXtyZXR1cm4gZS50b1VwcGVyQ2FzZSgpK2d9KSxydD0oKHtoYXNPd25Qcm9wZXJ0eTpBfSk9Pih0LEkpPT5BLmNhbGwodCxJKSkoT2JqZWN0LnByb3RvdHlwZSksS0k9VSgiUmVnRXhwIiksUXQ9KEEsdCk9PntsZXQgST1PYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycyhBKSxlPXt9O1YoSSwoZyxyKT0+e2xldCBvOyhvPXQoZyxyLEEpKSE9PSExJiYoZVtyXT1vfHxnKX0pLE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKEEsZSl9LE9JPUE9PntRdChBLCh0LEkpPT57aWYoTihBKSYmWyJhcmd1bWVudHMiLCJjYWxsZXIiLCJjYWxsZWUiXS5pbmRleE9mKEkpIT09LTEpcmV0dXJuITE7bGV0IGU9QVtJXTtpZihOKGUpKXtpZih0LmVudW1lcmFibGU9ITEsIndyaXRhYmxlImluIHQpe3Qud3JpdGFibGU9ITE7cmV0dXJufXQuc2V0fHwodC5zZXQ9KCk9Pnt0aHJvdyBFcnJvcigiQ2FuIG5vdCByZXdyaXRlIHJlYWQtb25seSBtZXRob2QgXCciK0krIlwnIil9KX19KX0sVEk9KEEsdCk9PntsZXQgST17fSxlPWc9PntnLmZvckVhY2gocj0+e0lbcl09ITB9KX07cmV0dXJuIEsoQSk/ZShBKTplKFN0cmluZyhBKS5zcGxpdCh0KSksSX0sUEk9KCk9Pnt9LHhJPShBLHQpPT4oQT0rQSxOdW1iZXIuaXNGaW5pdGUoQSk/QTp0KSxSQT0iYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoiLG90PSIwMTIzNDU2Nzg5IixhdD17RElHSVQ6b3QsQUxQSEE6UkEsQUxQSEFfRElHSVQ6UkErUkEudG9VcHBlckNhc2UoKStvdH0sakk9KEE9MTYsdD1hdC5BTFBIQV9ESUdJVCk9PntsZXQgST0iIix7bGVuZ3RoOmV9PXQ7Zm9yKDtBLS07KUkrPXRbTWF0aC5yYW5kb20oKSplfDBdO3JldHVybiBJfTtmdW5jdGlvbiBXSShBKXtyZXR1cm4hIShBJiZOKEEuYXBwZW5kKSYmQVtTeW1ib2wudG9TdHJpbmdUYWddPT09IkZvcm1EYXRhIiYmQVtTeW1ib2wuaXRlcmF0b3JdKX12YXIgWkk9QT0+e2xldCB0PW5ldyBBcnJheSgxMCksST0oZSxnKT0+e2lmKFFBKGUpKXtpZih0LmluZGV4T2YoZSk+PTApcmV0dXJuO2lmKCEoInRvSlNPTiJpbiBlKSl7dFtnXT1lO2xldCByPUsoZSk/W106e307cmV0dXJuIFYoZSwobyxuKT0+e2xldCBjPUkobyxnKzEpOyFaKGMpJiYocltuXT1jKX0pLHRbZ109dm9pZCAwLHJ9fXJldHVybiBlfTtyZXR1cm4gSShBLDApfSxWST1VKCJBc3luY0Z1bmN0aW9uIiksWEk9QT0+QSYmKFFBKEEpfHxOKEEpKSYmTihBLnRoZW4pJiZOKEEuY2F0Y2gpLEM9e2lzQXJyYXk6Syxpc0FycmF5QnVmZmVyOml0LGlzQnVmZmVyOmxJLGlzRm9ybURhdGE6U0ksaXNBcnJheUJ1ZmZlclZpZXc6REksaXNTdHJpbmc6dUksaXNOdW1iZXI6Q3QsaXNCb29sZWFuOmhJLGlzT2JqZWN0OlFBLGlzUGxhaW5PYmplY3Q6QkEsaXNVbmRlZmluZWQ6Wixpc0RhdGU6ZEksaXNGaWxlOnlJLGlzQmxvYjp3SSxpc1JlZ0V4cDpLSSxpc0Z1bmN0aW9uOk4saXNTdHJlYW06cEksaXNVUkxTZWFyY2hQYXJhbXM6RkksaXNUeXBlZEFycmF5OkhJLGlzRmlsZUxpc3Q6bUksZm9yRWFjaDpWLG1lcmdlOk5BLGV4dGVuZDpOSSx0cmltOlJJLHN0cmlwQk9NOlVJLGluaGVyaXRzOkdJLHRvRmxhdE9iamVjdDprSSxraW5kT2Y6c0Esa2luZE9mVGVzdDpVLGVuZHNXaXRoOkxJLHRvQXJyYXk6SkksZm9yRWFjaEVudHJ5OllJLG1hdGNoQWxsOmJJLGlzSFRNTEZvcm06TUksaGFzT3duUHJvcGVydHk6cnQsaGFzT3duUHJvcDpydCxyZWR1Y2VEZXNjcmlwdG9yczpRdCxmcmVlemVNZXRob2RzOk9JLHRvT2JqZWN0U2V0OlRJLHRvQ2FtZWxDYXNlOnFJLG5vb3A6UEksdG9GaW5pdGVOdW1iZXI6eEksZmluZEtleTpCdCxnbG9iYWw6c3QsaXNDb250ZXh0RGVmaW5lZDpudCxBTFBIQUJFVDphdCxnZW5lcmF0ZVN0cmluZzpqSSxpc1NwZWNDb21wbGlhbnRGb3JtOldJLHRvSlNPTk9iamVjdDpaSSxpc0FzeW5jRm46VkksaXNUaGVuYWJsZTpYSX07ZnVuY3Rpb24gTyhBLHQsSSxlLGcpe0Vycm9yLmNhbGwodGhpcyksRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2U/RXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UodGhpcyx0aGlzLmNvbnN0cnVjdG9yKTp0aGlzLnN0YWNrPW5ldyBFcnJvcigpLnN0YWNrLHRoaXMubWVzc2FnZT1BLHRoaXMubmFtZT0iQXhpb3NFcnJvciIsdCYmKHRoaXMuY29kZT10KSxJJiYodGhpcy5jb25maWc9SSksZSYmKHRoaXMucmVxdWVzdD1lKSxnJiYodGhpcy5yZXNwb25zZT1nKX1DLmluaGVyaXRzKE8sRXJyb3Ise3RvSlNPTjpmdW5jdGlvbigpe3JldHVybnttZXNzYWdlOnRoaXMubWVzc2FnZSxuYW1lOnRoaXMubmFtZSxkZXNjcmlwdGlvbjp0aGlzLmRlc2NyaXB0aW9uLG51bWJlcjp0aGlzLm51bWJlcixmaWxlTmFtZTp0aGlzLmZpbGVOYW1lLGxpbmVOdW1iZXI6dGhpcy5saW5lTnVtYmVyLGNvbHVtbk51bWJlcjp0aGlzLmNvbHVtbk51bWJlcixzdGFjazp0aGlzLnN0YWNrLGNvbmZpZzpDLnRvSlNPTk9iamVjdCh0aGlzLmNvbmZpZyksY29kZTp0aGlzLmNvZGUsc3RhdHVzOnRoaXMucmVzcG9uc2UmJnRoaXMucmVzcG9uc2Uuc3RhdHVzP3RoaXMucmVzcG9uc2Uuc3RhdHVzOm51bGx9fX0pO3ZhciBFdD1PLnByb3RvdHlwZSxjdD17fTtbIkVSUl9CQURfT1BUSU9OX1ZBTFVFIiwiRVJSX0JBRF9PUFRJT04iLCJFQ09OTkFCT1JURUQiLCJFVElNRURPVVQiLCJFUlJfTkVUV09SSyIsIkVSUl9GUl9UT09fTUFOWV9SRURJUkVDVFMiLCJFUlJfREVQUkVDQVRFRCIsIkVSUl9CQURfUkVTUE9OU0UiLCJFUlJfQkFEX1JFUVVFU1QiLCJFUlJfQ0FOQ0VMRUQiLCJFUlJfTk9UX1NVUFBPUlQiLCJFUlJfSU5WQUxJRF9VUkwiXS5mb3JFYWNoKEE9PntjdFtBXT17dmFsdWU6QX19KTtPYmplY3QuZGVmaW5lUHJvcGVydGllcyhPLGN0KTtPYmplY3QuZGVmaW5lUHJvcGVydHkoRXQsImlzQXhpb3NFcnJvciIse3ZhbHVlOiEwfSk7Ty5mcm9tPShBLHQsSSxlLGcscik9PntsZXQgbz1PYmplY3QuY3JlYXRlKEV0KTtyZXR1cm4gQy50b0ZsYXRPYmplY3QoQSxvLGZ1bmN0aW9uKGMpe3JldHVybiBjIT09RXJyb3IucHJvdG90eXBlfSxuPT5uIT09ImlzQXhpb3NFcnJvciIpLE8uY2FsbChvLEEubWVzc2FnZSx0LEksZSxnKSxvLmNhdXNlPUEsby5uYW1lPUEubmFtZSxyJiZPYmplY3QuYXNzaWduKG8sciksb307dmFyIGw9Tzt2YXIgYUE9bnVsbDtmdW5jdGlvbiBHQShBKXtyZXR1cm4gQy5pc1BsYWluT2JqZWN0KEEpfHxDLmlzQXJyYXkoQSl9ZnVuY3Rpb24gbHQoQSl7cmV0dXJuIEMuZW5kc1dpdGgoQSwiW10iKT9BLnNsaWNlKDAsLTIpOkF9ZnVuY3Rpb24gZnQoQSx0LEkpe3JldHVybiBBP0EuY29uY2F0KHQpLm1hcChmdW5jdGlvbihnLHIpe3JldHVybiBnPWx0KGcpLCFJJiZyPyJbIitnKyJdIjpnfSkuam9pbihJPyIuIjoiIik6dH1mdW5jdGlvbiB6SShBKXtyZXR1cm4gQy5pc0FycmF5KEEpJiYhQS5zb21lKEdBKX12YXIgX0k9Qy50b0ZsYXRPYmplY3QoQyx7fSxudWxsLGZ1bmN0aW9uKHQpe3JldHVybi9eaXNbQS1aXS8udGVzdCh0KX0pO2Z1bmN0aW9uIHZJKEEsdCxJKXtpZighQy5pc09iamVjdChBKSl0aHJvdyBuZXcgVHlwZUVycm9yKCJ0YXJnZXQgbXVzdCBiZSBhbiBvYmplY3QiKTt0PXR8fG5ldyhhQXx8Rm9ybURhdGEpLEk9Qy50b0ZsYXRPYmplY3QoSSx7bWV0YVRva2VuczohMCxkb3RzOiExLGluZGV4ZXM6ITF9LCExLGZ1bmN0aW9uKEUsdSl7cmV0dXJuIUMuaXNVbmRlZmluZWQodVtFXSl9KTtsZXQgZT1JLm1ldGFUb2tlbnMsZz1JLnZpc2l0b3J8fEIscj1JLmRvdHMsbz1JLmluZGV4ZXMsYz0oSS5CbG9ifHx0eXBlb2YgQmxvYjwidSImJkJsb2IpJiZDLmlzU3BlY0NvbXBsaWFudEZvcm0odCk7aWYoIUMuaXNGdW5jdGlvbihnKSl0aHJvdyBuZXcgVHlwZUVycm9yKCJ2aXNpdG9yIG11c3QgYmUgYSBmdW5jdGlvbiIpO2Z1bmN0aW9uIFEoYSl7aWYoYT09PW51bGwpcmV0dXJuIiI7aWYoQy5pc0RhdGUoYSkpcmV0dXJuIGEudG9JU09TdHJpbmcoKTtpZighYyYmQy5pc0Jsb2IoYSkpdGhyb3cgbmV3IGwoIkJsb2IgaXMgbm90IHN1cHBvcnRlZC4gVXNlIGEgQnVmZmVyIGluc3RlYWQuIik7cmV0dXJuIEMuaXNBcnJheUJ1ZmZlcihhKXx8Qy5pc1R5cGVkQXJyYXkoYSk/YyYmdHlwZW9mIEJsb2I9PSJmdW5jdGlvbiI/bmV3IEJsb2IoW2FdKTpCdWZmZXIuZnJvbShhKTphfWZ1bmN0aW9uIEIoYSxFLHUpe2xldCB5PWE7aWYoYSYmIXUmJnR5cGVvZiBhPT0ib2JqZWN0Iil7aWYoQy5lbmRzV2l0aChFLCJ7fSIpKUU9ZT9FOkUuc2xpY2UoMCwtMiksYT1KU09OLnN0cmluZ2lmeShhKTtlbHNlIGlmKEMuaXNBcnJheShhKSYmekkoYSl8fChDLmlzRmlsZUxpc3QoYSl8fEMuZW5kc1dpdGgoRSwiW10iKSkmJih5PUMudG9BcnJheShhKSkpcmV0dXJuIEU9bHQoRSkseS5mb3JFYWNoKGZ1bmN0aW9uKFIsdEkpeyEoQy5pc1VuZGVmaW5lZChSKXx8Uj09PW51bGwpJiZ0LmFwcGVuZChvPT09ITA/ZnQoW0VdLHRJLHIpOm89PT1udWxsP0U6RSsiW10iLFEoUikpfSksITF9cmV0dXJuIEdBKGEpPyEwOih0LmFwcGVuZChmdCh1LEUsciksUShhKSksITEpfWxldCBpPVtdLGY9T2JqZWN0LmFzc2lnbihfSSx7ZGVmYXVsdFZpc2l0b3I6Qixjb252ZXJ0VmFsdWU6USxpc1Zpc2l0YWJsZTpHQX0pO2Z1bmN0aW9uIHMoYSxFKXtpZighQy5pc1VuZGVmaW5lZChhKSl7aWYoaS5pbmRleE9mKGEpIT09LTEpdGhyb3cgRXJyb3IoIkNpcmN1bGFyIHJlZmVyZW5jZSBkZXRlY3RlZCBpbiAiK0Uuam9pbigiLiIpKTtpLnB1c2goYSksQy5mb3JFYWNoKGEsZnVuY3Rpb24oeSxGKXsoIShDLmlzVW5kZWZpbmVkKHkpfHx5PT09bnVsbCkmJmcuY2FsbCh0LHksQy5pc1N0cmluZyhGKT9GLnRyaW0oKTpGLEUsZikpPT09ITAmJnMoeSxFP0UuY29uY2F0KEYpOltGXSl9KSxpLnBvcCgpfX1pZighQy5pc09iamVjdChBKSl0aHJvdyBuZXcgVHlwZUVycm9yKCJkYXRhIG11c3QgYmUgYW4gb2JqZWN0Iik7cmV0dXJuIHMoQSksdH12YXIgSj12STtmdW5jdGlvbiBEdChBKXtsZXQgdD17IiEiOiIlMjUyMSIsIlwnIjoiJTI1MjciLCIoIjoiJTI1MjgiLCIpIjoiJTI1MjkiLCJ+IjoiJTI1N0UiLCIlMjUyMCI6IisiLCIlMjUwMCI6IlxcMCJ9O3JldHVybiBlbmNvZGVVUklDb21wb25lbnQoQSkucmVwbGFjZSgvWyFcJygpfl18JTI1MjB8JTI1MDAvZyxmdW5jdGlvbihlKXtyZXR1cm4gdFtlXX0pfWZ1bmN0aW9uIHV0KEEsdCl7dGhpcy5fcGFpcnM9W10sQSYmSihBLHRoaXMsdCl9dmFyIGh0PXV0LnByb3RvdHlwZTtodC5hcHBlbmQ9ZnVuY3Rpb24odCxJKXt0aGlzLl9wYWlycy5wdXNoKFt0LEldKX07aHQudG9TdHJpbmc9ZnVuY3Rpb24odCl7bGV0IEk9dD9mdW5jdGlvbihlKXtyZXR1cm4gdC5jYWxsKHRoaXMsZSxEdCl9OkR0O3JldHVybiB0aGlzLl9wYWlycy5tYXAoZnVuY3Rpb24oZyl7cmV0dXJuIEkoZ1swXSkrIj0iK0koZ1sxXSl9LCIiKS5qb2luKCImIil9O3ZhciBFQT11dDtmdW5jdGlvbiAkSShBKXtyZXR1cm4gZW5jb2RlVVJJQ29tcG9uZW50KEEpLnJlcGxhY2UoLyUyNTNBL2dpLCI6IikucmVwbGFjZSgvJTI1MjQvZywiJCIpLnJlcGxhY2UoLyUyNTJDL2dpLCIsIikucmVwbGFjZSgvJTI1MjAvZywiKyIpLnJlcGxhY2UoLyUyNTVCL2dpLCJbIikucmVwbGFjZSgvJTI1NUQvZ2ksIl0iKX1mdW5jdGlvbiBYKEEsdCxJKXtpZighdClyZXR1cm4gQTtsZXQgZT1JJiZJLmVuY29kZXx8JEksZz1JJiZJLnNlcmlhbGl6ZSxyO2lmKGc/cj1nKHQsSSk6cj1DLmlzVVJMU2VhcmNoUGFyYW1zKHQpP3QudG9TdHJpbmcoKTpuZXcgRUEodCxJKS50b1N0cmluZyhlKSxyKXtsZXQgbz1BLmluZGV4T2YoIiUyMyIpO28hPT0tMSYmKEE9QS5zbGljZSgwLG8pKSxBKz0oQS5pbmRleE9mKCI/Iik9PT0tMT8iPyI6IiYiKStyfXJldHVybiBBfXZhciBrQT1jbGFzc3tjb25zdHJ1Y3Rvcigpe3RoaXMuaGFuZGxlcnM9W119dXNlKHQsSSxlKXtyZXR1cm4gdGhpcy5oYW5kbGVycy5wdXNoKHtmdWxmaWxsZWQ6dCxyZWplY3RlZDpJLHN5bmNocm9ub3VzOmU/ZS5zeW5jaHJvbm91czohMSxydW5XaGVuOmU/ZS5ydW5XaGVuOm51bGx9KSx0aGlzLmhhbmRsZXJzLmxlbmd0aC0xfWVqZWN0KHQpe3RoaXMuaGFuZGxlcnNbdF0mJih0aGlzLmhhbmRsZXJzW3RdPW51bGwpfWNsZWFyKCl7dGhpcy5oYW5kbGVycyYmKHRoaXMuaGFuZGxlcnM9W10pfWZvckVhY2godCl7Qy5mb3JFYWNoKHRoaXMuaGFuZGxlcnMsZnVuY3Rpb24oZSl7ZSE9PW51bGwmJnQoZSl9KX19LExBPWtBO3ZhciBjQT17c2lsZW50SlNPTlBhcnNpbmc6ITAsZm9yY2VkSlNPTlBhcnNpbmc6ITAsY2xhcmlmeVRpbWVvdXRFcnJvcjohMX07dmFyIGR0PXR5cGVvZiBVUkxTZWFyY2hQYXJhbXM8InUiP1VSTFNlYXJjaFBhcmFtczpFQTt2YXIgeXQ9dHlwZW9mIEZvcm1EYXRhPCJ1Ij9Gb3JtRGF0YTpudWxsO3ZhciB3dD10eXBlb2YgQmxvYjwidSI/QmxvYjpudWxsO3ZhciBtdD17aXNCcm93c2VyOiEwLGNsYXNzZXM6e1VSTFNlYXJjaFBhcmFtczpkdCxGb3JtRGF0YTp5dCxCbG9iOnd0fSxwcm90b2NvbHM6WyJodHRwIiwiaHR0cHMiLCJmaWxlIiwiYmxvYiIsInVybCIsImRhdGEiXX07dmFyIEpBPXt9O2VJKEpBLHtoYXNCcm93c2VyRW52OigpPT5wdCxoYXNTdGFuZGFyZEJyb3dzZXJFbnY6KCk9PkFlLGhhc1N0YW5kYXJkQnJvd3NlcldlYldvcmtlckVudjooKT0+dGV9KTt2YXIgcHQ9dHlwZW9mIHdpbmRvdzwidSImJnR5cGVvZiBkb2N1bWVudDwidSIsQWU9KEE9PnB0JiZbIlJlYWN0TmF0aXZlIiwiTmF0aXZlU2NyaXB0IiwiTlMiXS5pbmRleE9mKEEpPDApKHR5cGVvZiBuYXZpZ2F0b3I8InUiJiZuYXZpZ2F0b3IucHJvZHVjdCksdGU9dHlwZW9mIFdvcmtlckdsb2JhbFNjb3BlPCJ1IiYmc2VsZiBpbnN0YW5jZW9mIFdvcmtlckdsb2JhbFNjb3BlJiZ0eXBlb2Ygc2VsZi5pbXBvcnRTY3JpcHRzPT0iZnVuY3Rpb24iO3ZhciBtPXsuLi5KQSwuLi5tdH07ZnVuY3Rpb24gSEEoQSx0KXtyZXR1cm4gSihBLG5ldyBtLmNsYXNzZXMuVVJMU2VhcmNoUGFyYW1zLE9iamVjdC5hc3NpZ24oe3Zpc2l0b3I6ZnVuY3Rpb24oSSxlLGcscil7cmV0dXJuIG0uaXNOb2RlJiZDLmlzQnVmZmVyKEkpPyh0aGlzLmFwcGVuZChlLEkudG9TdHJpbmcoImJhc2U2NCIpKSwhMSk6ci5kZWZhdWx0VmlzaXRvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9fSx0KSl9ZnVuY3Rpb24gSWUoQSl7cmV0dXJuIEMubWF0Y2hBbGwoL1xcdyt8XFxbKFxcdyopXS9nLEEpLm1hcCh0PT50WzBdPT09IltdIj8iIjp0WzFdfHx0WzBdKX1mdW5jdGlvbiBlZShBKXtsZXQgdD17fSxJPU9iamVjdC5rZXlzKEEpLGUsZz1JLmxlbmd0aCxyO2ZvcihlPTA7ZTxnO2UrKylyPUlbZV0sdFtyXT1BW3JdO3JldHVybiB0fWZ1bmN0aW9uIGdlKEEpe2Z1bmN0aW9uIHQoSSxlLGcscil7bGV0IG89SVtyKytdO2lmKG89PT0iX19wcm90b19fIilyZXR1cm4hMDtsZXQgbj1OdW1iZXIuaXNGaW5pdGUoK28pLGM9cj49SS5sZW5ndGg7cmV0dXJuIG89IW8mJkMuaXNBcnJheShnKT9nLmxlbmd0aDpvLGM/KEMuaGFzT3duUHJvcChnLG8pP2dbb109W2dbb10sZV06Z1tvXT1lLCFuKTooKCFnW29dfHwhQy5pc09iamVjdChnW29dKSkmJihnW29dPVtdKSx0KEksZSxnW29dLHIpJiZDLmlzQXJyYXkoZ1tvXSkmJihnW29dPWVlKGdbb10pKSwhbil9aWYoQy5pc0Zvcm1EYXRhKEEpJiZDLmlzRnVuY3Rpb24oQS5lbnRyaWVzKSl7bGV0IEk9e307cmV0dXJuIEMuZm9yRWFjaEVudHJ5KEEsKGUsZyk9Pnt0KEllKGUpLGcsSSwwKX0pLEl9cmV0dXJuIG51bGx9dmFyIGZBPWdlO2Z1bmN0aW9uIHJlKEEsdCxJKXtpZihDLmlzU3RyaW5nKEEpKXRyeXtyZXR1cm4odHx8SlNPTi5wYXJzZSkoQSksQy50cmltKEEpfWNhdGNoKGUpe2lmKGUubmFtZSE9PSJTeW50YXhFcnJvciIpdGhyb3cgZX1yZXR1cm4oSXx8SlNPTi5zdHJpbmdpZnkpKEEpfXZhciBZQT17dHJhbnNpdGlvbmFsOmNBLGFkYXB0ZXI6WyJ4aHIiLCJodHRwIl0sdHJhbnNmb3JtUmVxdWVzdDpbZnVuY3Rpb24odCxJKXtsZXQgZT1JLmdldENvbnRlbnRUeXBlKCl8fCIiLGc9ZS5pbmRleE9mKCJhcHBsaWNhdGlvbi9qc29uIik+LTEscj1DLmlzT2JqZWN0KHQpO2lmKHImJkMuaXNIVE1MRm9ybSh0KSYmKHQ9bmV3IEZvcm1EYXRhKHQpKSxDLmlzRm9ybURhdGEodCkpcmV0dXJuIGc/SlNPTi5zdHJpbmdpZnkoZkEodCkpOnQ7aWYoQy5pc0FycmF5QnVmZmVyKHQpfHxDLmlzQnVmZmVyKHQpfHxDLmlzU3RyZWFtKHQpfHxDLmlzRmlsZSh0KXx8Qy5pc0Jsb2IodCkpcmV0dXJuIHQ7aWYoQy5pc0FycmF5QnVmZmVyVmlldyh0KSlyZXR1cm4gdC5idWZmZXI7aWYoQy5pc1VSTFNlYXJjaFBhcmFtcyh0KSlyZXR1cm4gSS5zZXRDb250ZW50VHlwZSgiYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkO2NoYXJzZXQ9dXRmLTgiLCExKSx0LnRvU3RyaW5nKCk7bGV0IG47aWYocil7aWYoZS5pbmRleE9mKCJhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQiKT4tMSlyZXR1cm4gSEEodCx0aGlzLmZvcm1TZXJpYWxpemVyKS50b1N0cmluZygpO2lmKChuPUMuaXNGaWxlTGlzdCh0KSl8fGUuaW5kZXhPZigibXVsdGlwYXJ0L2Zvcm0tZGF0YSIpPi0xKXtsZXQgYz10aGlzLmVudiYmdGhpcy5lbnYuRm9ybURhdGE7cmV0dXJuIEoobj97ImZpbGVzW10iOnR9OnQsYyYmbmV3IGMsdGhpcy5mb3JtU2VyaWFsaXplcil9fXJldHVybiByfHxnPyhJLnNldENvbnRlbnRUeXBlKCJhcHBsaWNhdGlvbi9qc29uIiwhMSkscmUodCkpOnR9XSx0cmFuc2Zvcm1SZXNwb25zZTpbZnVuY3Rpb24odCl7bGV0IEk9dGhpcy50cmFuc2l0aW9uYWx8fFlBLnRyYW5zaXRpb25hbCxlPUkmJkkuZm9yY2VkSlNPTlBhcnNpbmcsZz10aGlzLnJlc3BvbnNlVHlwZT09PSJqc29uIjtpZih0JiZDLmlzU3RyaW5nKHQpJiYoZSYmIXRoaXMucmVzcG9uc2VUeXBlfHxnKSl7bGV0IG89IShJJiZJLnNpbGVudEpTT05QYXJzaW5nKSYmZzt0cnl7cmV0dXJuIEpTT04ucGFyc2UodCl9Y2F0Y2gobil7aWYobyl0aHJvdyBuLm5hbWU9PT0iU3ludGF4RXJyb3IiP2wuZnJvbShuLGwuRVJSX0JBRF9SRVNQT05TRSx0aGlzLG51bGwsdGhpcy5yZXNwb25zZSk6bn19cmV0dXJuIHR9XSx0aW1lb3V0OjAseHNyZkNvb2tpZU5hbWU6IlhTUkYtVE9LRU4iLHhzcmZIZWFkZXJOYW1lOiJYLVhTUkYtVE9LRU4iLG1heENvbnRlbnRMZW5ndGg6LTEsbWF4Qm9keUxlbmd0aDotMSxlbnY6e0Zvcm1EYXRhOm0uY2xhc3Nlcy5Gb3JtRGF0YSxCbG9iOm0uY2xhc3Nlcy5CbG9ifSx2YWxpZGF0ZVN0YXR1czpmdW5jdGlvbih0KXtyZXR1cm4gdD49MjAwJiZ0PDMwMH0saGVhZGVyczp7Y29tbW9uOntBY2NlcHQ6ImFwcGxpY2F0aW9uL2pzb24sIHRleHQvcGxhaW4sICovKiIsIkNvbnRlbnQtVHlwZSI6dm9pZCAwfX19O0MuZm9yRWFjaChbImRlbGV0ZSIsImdldCIsImhlYWQiLCJwb3N0IiwicHV0IiwicGF0Y2giXSxBPT57WUEuaGVhZGVyc1tBXT17fX0pO3ZhciBUPVlBO3ZhciBvZT1DLnRvT2JqZWN0U2V0KFsiYWdlIiwiYXV0aG9yaXphdGlvbiIsImNvbnRlbnQtbGVuZ3RoIiwiY29udGVudC10eXBlIiwiZXRhZyIsImV4cGlyZXMiLCJmcm9tIiwiaG9zdCIsImlmLW1vZGlmaWVkLXNpbmNlIiwiaWYtdW5tb2RpZmllZC1zaW5jZSIsImxhc3QtbW9kaWZpZWQiLCJsb2NhdGlvbiIsIm1heC1mb3J3YXJkcyIsInByb3h5LWF1dGhvcml6YXRpb24iLCJyZWZlcmVyIiwicmV0cnktYWZ0ZXIiLCJ1c2VyLWFnZW50Il0pLFN0PUE9PntsZXQgdD17fSxJLGUsZztyZXR1cm4gQSYmQS5zcGxpdChgJTBBYCkuZm9yRWFjaChmdW5jdGlvbihvKXtnPW8uaW5kZXhPZigiOiIpLEk9by5zdWJzdHJpbmcoMCxnKS50cmltKCkudG9Mb3dlckNhc2UoKSxlPW8uc3Vic3RyaW5nKGcrMSkudHJpbSgpLCEoIUl8fHRbSV0mJm9lW0ldKSYmKEk9PT0ic2V0LWNvb2tpZSI/dFtJXT90W0ldLnB1c2goZSk6dFtJXT1bZV06dFtJXT10W0ldP3RbSV0rIiwgIitlOmUpfSksdH07dmFyIEZ0PVN5bWJvbCgiaW50ZXJuYWxzIik7ZnVuY3Rpb24geihBKXtyZXR1cm4gQSYmU3RyaW5nKEEpLnRyaW0oKS50b0xvd2VyQ2FzZSgpfWZ1bmN0aW9uIGxBKEEpe3JldHVybiBBPT09ITF8fEE9PW51bGw/QTpDLmlzQXJyYXkoQSk/QS5tYXAobEEpOlN0cmluZyhBKX1mdW5jdGlvbiBpZShBKXtsZXQgdD1PYmplY3QuY3JlYXRlKG51bGwpLEk9LyhbXlxccyw7PV0rKVxccyooPzo9XFxzKihbXiw7XSspKT8vZyxlO2Zvcig7ZT1JLmV4ZWMoQSk7KXRbZVsxXV09ZVsyXTtyZXR1cm4gdH12YXIgQ2U9QT0+L15bLV9hLXpBLVowLTleYHx+LCElMjMkJSZcJyorLl0rJC8udGVzdChBLnRyaW0oKSk7ZnVuY3Rpb24gYkEoQSx0LEksZSxnKXtpZihDLmlzRnVuY3Rpb24oZSkpcmV0dXJuIGUuY2FsbCh0aGlzLHQsSSk7aWYoZyYmKHQ9SSksISFDLmlzU3RyaW5nKHQpKXtpZihDLmlzU3RyaW5nKGUpKXJldHVybiB0LmluZGV4T2YoZSkhPT0tMTtpZihDLmlzUmVnRXhwKGUpKXJldHVybiBlLnRlc3QodCl9fWZ1bmN0aW9uIEJlKEEpe3JldHVybiBBLnRyaW0oKS50b0xvd2VyQ2FzZSgpLnJlcGxhY2UoLyhbYS16XFxkXSkoXFx3KikvZywodCxJLGUpPT5JLnRvVXBwZXJDYXNlKCkrZSl9ZnVuY3Rpb24gc2UoQSx0KXtsZXQgST1DLnRvQ2FtZWxDYXNlKCIgIit0KTtbImdldCIsInNldCIsImhhcyJdLmZvckVhY2goZT0+e09iamVjdC5kZWZpbmVQcm9wZXJ0eShBLGUrSSx7dmFsdWU6ZnVuY3Rpb24oZyxyLG8pe3JldHVybiB0aGlzW2VdLmNhbGwodGhpcyx0LGcscixvKX0sY29uZmlndXJhYmxlOiEwfSl9KX12YXIgUD1jbGFzc3tjb25zdHJ1Y3Rvcih0KXt0JiZ0aGlzLnNldCh0KX1zZXQodCxJLGUpe2xldCBnPXRoaXM7ZnVuY3Rpb24gcihuLGMsUSl7bGV0IEI9eihjKTtpZighQil0aHJvdyBuZXcgRXJyb3IoImhlYWRlciBuYW1lIG11c3QgYmUgYSBub24tZW1wdHkgc3RyaW5nIik7bGV0IGk9Qy5maW5kS2V5KGcsQik7KCFpfHxnW2ldPT09dm9pZCAwfHxRPT09ITB8fFE9PT12b2lkIDAmJmdbaV0hPT0hMSkmJihnW2l8fGNdPWxBKG4pKX1sZXQgbz0obixjKT0+Qy5mb3JFYWNoKG4sKFEsQik9PnIoUSxCLGMpKTtyZXR1cm4gQy5pc1BsYWluT2JqZWN0KHQpfHx0IGluc3RhbmNlb2YgdGhpcy5jb25zdHJ1Y3Rvcj9vKHQsSSk6Qy5pc1N0cmluZyh0KSYmKHQ9dC50cmltKCkpJiYhQ2UodCk/byhTdCh0KSxJKTp0IT1udWxsJiZyKEksdCxlKSx0aGlzfWdldCh0LEkpe2lmKHQ9eih0KSx0KXtsZXQgZT1DLmZpbmRLZXkodGhpcyx0KTtpZihlKXtsZXQgZz10aGlzW2VdO2lmKCFJKXJldHVybiBnO2lmKEk9PT0hMClyZXR1cm4gaWUoZyk7aWYoQy5pc0Z1bmN0aW9uKEkpKXJldHVybiBJLmNhbGwodGhpcyxnLGUpO2lmKEMuaXNSZWdFeHAoSSkpcmV0dXJuIEkuZXhlYyhnKTt0aHJvdyBuZXcgVHlwZUVycm9yKCJwYXJzZXIgbXVzdCBiZSBib29sZWFufHJlZ2V4cHxmdW5jdGlvbiIpfX19aGFzKHQsSSl7aWYodD16KHQpLHQpe2xldCBlPUMuZmluZEtleSh0aGlzLHQpO3JldHVybiEhKGUmJnRoaXNbZV0hPT12b2lkIDAmJighSXx8YkEodGhpcyx0aGlzW2VdLGUsSSkpKX1yZXR1cm4hMX1kZWxldGUodCxJKXtsZXQgZT10aGlzLGc9ITE7ZnVuY3Rpb24gcihvKXtpZihvPXoobyksbyl7bGV0IG49Qy5maW5kS2V5KGUsbyk7biYmKCFJfHxiQShlLGVbbl0sbixJKSkmJihkZWxldGUgZVtuXSxnPSEwKX19cmV0dXJuIEMuaXNBcnJheSh0KT90LmZvckVhY2gocik6cih0KSxnfWNsZWFyKHQpe2xldCBJPU9iamVjdC5rZXlzKHRoaXMpLGU9SS5sZW5ndGgsZz0hMTtmb3IoO2UtLTspe2xldCByPUlbZV07KCF0fHxiQSh0aGlzLHRoaXNbcl0scix0LCEwKSkmJihkZWxldGUgdGhpc1tyXSxnPSEwKX1yZXR1cm4gZ31ub3JtYWxpemUodCl7bGV0IEk9dGhpcyxlPXt9O3JldHVybiBDLmZvckVhY2godGhpcywoZyxyKT0+e2xldCBvPUMuZmluZEtleShlLHIpO2lmKG8pe0lbb109bEEoZyksZGVsZXRlIElbcl07cmV0dXJufWxldCBuPXQ/QmUocik6U3RyaW5nKHIpLnRyaW0oKTtuIT09ciYmZGVsZXRlIElbcl0sSVtuXT1sQShnKSxlW25dPSEwfSksdGhpc31jb25jYXQoLi4udCl7cmV0dXJuIHRoaXMuY29uc3RydWN0b3IuY29uY2F0KHRoaXMsLi4udCl9dG9KU09OKHQpe2xldCBJPU9iamVjdC5jcmVhdGUobnVsbCk7cmV0dXJuIEMuZm9yRWFjaCh0aGlzLChlLGcpPT57ZSE9bnVsbCYmZSE9PSExJiYoSVtnXT10JiZDLmlzQXJyYXkoZSk/ZS5qb2luKCIsICIpOmUpfSksSX1bU3ltYm9sLml0ZXJhdG9yXSgpe3JldHVybiBPYmplY3QuZW50cmllcyh0aGlzLnRvSlNPTigpKVtTeW1ib2wuaXRlcmF0b3JdKCl9dG9TdHJpbmcoKXtyZXR1cm4gT2JqZWN0LmVudHJpZXModGhpcy50b0pTT04oKSkubWFwKChbdCxJXSk9PnQrIjogIitJKS5qb2luKGAlMEFgKX1nZXRbU3ltYm9sLnRvU3RyaW5nVGFnXSgpe3JldHVybiJBeGlvc0hlYWRlcnMifXN0YXRpYyBmcm9tKHQpe3JldHVybiB0IGluc3RhbmNlb2YgdGhpcz90Om5ldyB0aGlzKHQpfXN0YXRpYyBjb25jYXQodCwuLi5JKXtsZXQgZT1uZXcgdGhpcyh0KTtyZXR1cm4gSS5mb3JFYWNoKGc9PmUuc2V0KGcpKSxlfXN0YXRpYyBhY2Nlc3Nvcih0KXtsZXQgZT0odGhpc1tGdF09dGhpc1tGdF09e2FjY2Vzc29yczp7fX0pLmFjY2Vzc29ycyxnPXRoaXMucHJvdG90eXBlO2Z1bmN0aW9uIHIobyl7bGV0IG49eihvKTtlW25dfHwoc2UoZyxvKSxlW25dPSEwKX1yZXR1cm4gQy5pc0FycmF5KHQpP3QuZm9yRWFjaChyKTpyKHQpLHRoaXN9fTtQLmFjY2Vzc29yKFsiQ29udGVudC1UeXBlIiwiQ29udGVudC1MZW5ndGgiLCJBY2NlcHQiLCJBY2NlcHQtRW5jb2RpbmciLCJVc2VyLUFnZW50IiwiQXV0aG9yaXphdGlvbiJdKTtDLnJlZHVjZURlc2NyaXB0b3JzKFAucHJvdG90eXBlLCh7dmFsdWU6QX0sdCk9PntsZXQgST10WzBdLnRvVXBwZXJDYXNlKCkrdC5zbGljZSgxKTtyZXR1cm57Z2V0OigpPT5BLHNldChlKXt0aGlzW0ldPWV9fX0pO0MuZnJlZXplTWV0aG9kcyhQKTt2YXIgcD1QO2Z1bmN0aW9uIF8oQSx0KXtsZXQgST10aGlzfHxULGU9dHx8SSxnPXAuZnJvbShlLmhlYWRlcnMpLHI9ZS5kYXRhO3JldHVybiBDLmZvckVhY2goQSxmdW5jdGlvbihuKXtyPW4uY2FsbChJLHIsZy5ub3JtYWxpemUoKSx0P3Quc3RhdHVzOnZvaWQgMCl9KSxnLm5vcm1hbGl6ZSgpLHJ9ZnVuY3Rpb24gdihBKXtyZXR1cm4hIShBJiZBLl9fQ0FOQ0VMX18pfWZ1bmN0aW9uIFJ0KEEsdCxJKXtsLmNhbGwodGhpcyxBPz8iY2FuY2VsZWQiLGwuRVJSX0NBTkNFTEVELHQsSSksdGhpcy5uYW1lPSJDYW5jZWxlZEVycm9yIn1DLmluaGVyaXRzKFJ0LGwse19fQ0FOQ0VMX186ITB9KTt2YXIgSD1SdDtmdW5jdGlvbiBNQShBLHQsSSl7bGV0IGU9SS5jb25maWcudmFsaWRhdGVTdGF0dXM7IUkuc3RhdHVzfHwhZXx8ZShJLnN0YXR1cyk/QShJKTp0KG5ldyBsKCJSZXF1ZXN0IGZhaWxlZCB3aXRoIHN0YXR1cyBjb2RlICIrSS5zdGF0dXMsW2wuRVJSX0JBRF9SRVFVRVNULGwuRVJSX0JBRF9SRVNQT05TRV1bTWF0aC5mbG9vcihJLnN0YXR1cy8xMDApLTRdLEkuY29uZmlnLEkucmVxdWVzdCxJKSl9dmFyIE50PW0uaGFzU3RhbmRhcmRCcm93c2VyRW52P3t3cml0ZShBLHQsSSxlLGcscil7bGV0IG89W0ErIj0iK2VuY29kZVVSSUNvbXBvbmVudCh0KV07Qy5pc051bWJlcihJKSYmby5wdXNoKCJleHBpcmVzPSIrbmV3IERhdGUoSSkudG9HTVRTdHJpbmcoKSksQy5pc1N0cmluZyhlKSYmby5wdXNoKCJwYXRoPSIrZSksQy5pc1N0cmluZyhnKSYmby5wdXNoKCJkb21haW49IitnKSxyPT09ITAmJm8ucHVzaCgic2VjdXJlIiksZG9jdW1lbnQuY29va2llPW8uam9pbigiOyAiKX0scmVhZChBKXtsZXQgdD1kb2N1bWVudC5jb29raWUubWF0Y2gobmV3IFJlZ0V4cCgiKF58O1xcXFxzKikoIitBKyIpPShbXjtdKikiKSk7cmV0dXJuIHQ/ZGVjb2RlVVJJQ29tcG9uZW50KHRbM10pOm51bGx9LHJlbW92ZShBKXt0aGlzLndyaXRlKEEsIiIsRGF0ZS5ub3coKS04NjRlNSl9fTp7d3JpdGUoKXt9LHJlYWQoKXtyZXR1cm4gbnVsbH0scmVtb3ZlKCl7fX07ZnVuY3Rpb24gcUEoQSl7cmV0dXJuL14oW2Etel1bYS16XFxkK1xcLS5dKjopP1xcL1xcLy9pLnRlc3QoQSl9ZnVuY3Rpb24gS0EoQSx0KXtyZXR1cm4gdD9BLnJlcGxhY2UoL1xcLz9cXC8kLywiIikrIi8iK3QucmVwbGFjZSgvXlxcLysvLCIiKTpBfWZ1bmN0aW9uICQoQSx0KXtyZXR1cm4gQSYmIXFBKHQpP0tBKEEsdCk6dH12YXIgVXQ9bS5oYXNTdGFuZGFyZEJyb3dzZXJFbnY/ZnVuY3Rpb24oKXtsZXQgdD0vKG1zaWV8dHJpZGVudCkvaS50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpLEk9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiYSIpLGU7ZnVuY3Rpb24gZyhyKXtsZXQgbz1yO3JldHVybiB0JiYoSS5zZXRBdHRyaWJ1dGUoImhyZWYiLG8pLG89SS5ocmVmKSxJLnNldEF0dHJpYnV0ZSgiaHJlZiIsbykse2hyZWY6SS5ocmVmLHByb3RvY29sOkkucHJvdG9jb2w/SS5wcm90b2NvbC5yZXBsYWNlKC86JC8sIiIpOiIiLGhvc3Q6SS5ob3N0LHNlYXJjaDpJLnNlYXJjaD9JLnNlYXJjaC5yZXBsYWNlKC9eXFw/LywiIik6IiIsaGFzaDpJLmhhc2g/SS5oYXNoLnJlcGxhY2UoL14lMjMvLCIiKToiIixob3N0bmFtZTpJLmhvc3RuYW1lLHBvcnQ6SS5wb3J0LHBhdGhuYW1lOkkucGF0aG5hbWUuY2hhckF0KDApPT09Ii8iP0kucGF0aG5hbWU6Ii8iK0kucGF0aG5hbWV9fXJldHVybiBlPWcod2luZG93LmxvY2F0aW9uLmhyZWYpLGZ1bmN0aW9uKG8pe2xldCBuPUMuaXNTdHJpbmcobyk/ZyhvKTpvO3JldHVybiBuLnByb3RvY29sPT09ZS5wcm90b2NvbCYmbi5ob3N0PT09ZS5ob3N0fX0oKTpmdW5jdGlvbigpe3JldHVybiBmdW5jdGlvbigpe3JldHVybiEwfX0oKTtmdW5jdGlvbiBPQShBKXtsZXQgdD0vXihbLStcXHddezEsMjV9KSg6P1xcL1xcL3w6KS8uZXhlYyhBKTtyZXR1cm4gdCYmdFsxXXx8IiJ9ZnVuY3Rpb24gbmUoQSx0KXtBPUF8fDEwO2xldCBJPW5ldyBBcnJheShBKSxlPW5ldyBBcnJheShBKSxnPTAscj0wLG87cmV0dXJuIHQ9dCE9PXZvaWQgMD90OjFlMyxmdW5jdGlvbihjKXtsZXQgUT1EYXRlLm5vdygpLEI9ZVtyXTtvfHwobz1RKSxJW2ddPWMsZVtnXT1RO2xldCBpPXIsZj0wO2Zvcig7aSE9PWc7KWYrPUlbaSsrXSxpPWklQTtpZihnPShnKzEpJUEsZz09PXImJihyPShyKzEpJUEpLFEtbzx0KXJldHVybjtsZXQgcz1CJiZRLUI7cmV0dXJuIHM/TWF0aC5yb3VuZChmKjFlMy9zKTp2b2lkIDB9fXZhciBHdD1uZTtmdW5jdGlvbiBrdChBLHQpe2xldCBJPTAsZT1HdCg1MCwyNTApO3JldHVybiBnPT57bGV0IHI9Zy5sb2FkZWQsbz1nLmxlbmd0aENvbXB1dGFibGU/Zy50b3RhbDp2b2lkIDAsbj1yLUksYz1lKG4pLFE9cjw9bztJPXI7bGV0IEI9e2xvYWRlZDpyLHRvdGFsOm8scHJvZ3Jlc3M6bz9yL286dm9pZCAwLGJ5dGVzOm4scmF0ZTpjfHx2b2lkIDAsZXN0aW1hdGVkOmMmJm8mJlE/KG8tcikvYzp2b2lkIDAsZXZlbnQ6Z307Qlt0PyJkb3dubG9hZCI6InVwbG9hZCJdPSEwLEEoQil9fXZhciBRZT10eXBlb2YgWE1MSHR0cFJlcXVlc3Q8InUiLEx0PVFlJiZmdW5jdGlvbihBKXtyZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24oSSxlKXtsZXQgZz1BLmRhdGEscj1wLmZyb20oQS5oZWFkZXJzKS5ub3JtYWxpemUoKSx7cmVzcG9uc2VUeXBlOm8sd2l0aFhTUkZUb2tlbjpufT1BLGM7ZnVuY3Rpb24gUSgpe0EuY2FuY2VsVG9rZW4mJkEuY2FuY2VsVG9rZW4udW5zdWJzY3JpYmUoYyksQS5zaWduYWwmJkEuc2lnbmFsLnJlbW92ZUV2ZW50TGlzdGVuZXIoImFib3J0IixjKX1sZXQgQjtpZihDLmlzRm9ybURhdGEoZykpe2lmKG0uaGFzU3RhbmRhcmRCcm93c2VyRW52fHxtLmhhc1N0YW5kYXJkQnJvd3NlcldlYldvcmtlckVudilyLnNldENvbnRlbnRUeXBlKCExKTtlbHNlIGlmKChCPXIuZ2V0Q29udGVudFR5cGUoKSkhPT0hMSl7bGV0W0UsLi4udV09Qj9CLnNwbGl0KCI7IikubWFwKHk9PnkudHJpbSgpKS5maWx0ZXIoQm9vbGVhbik6W107ci5zZXRDb250ZW50VHlwZShbRXx8Im11bHRpcGFydC9mb3JtLWRhdGEiLC4uLnVdLmpvaW4oIjsgIikpfX1sZXQgaT1uZXcgWE1MSHR0cFJlcXVlc3Q7aWYoQS5hdXRoKXtsZXQgRT1BLmF1dGgudXNlcm5hbWV8fCIiLHU9QS5hdXRoLnBhc3N3b3JkP3VuZXNjYXBlKGVuY29kZVVSSUNvbXBvbmVudChBLmF1dGgucGFzc3dvcmQpKToiIjtyLnNldCgiQXV0aG9yaXphdGlvbiIsIkJhc2ljICIrYnRvYShFKyI6Iit1KSl9bGV0IGY9JChBLmJhc2VVUkwsQS51cmwpO2kub3BlbihBLm1ldGhvZC50b1VwcGVyQ2FzZSgpLFgoZixBLnBhcmFtcyxBLnBhcmFtc1NlcmlhbGl6ZXIpLCEwKSxpLnRpbWVvdXQ9QS50aW1lb3V0O2Z1bmN0aW9uIHMoKXtpZighaSlyZXR1cm47bGV0IEU9cC5mcm9tKCJnZXRBbGxSZXNwb25zZUhlYWRlcnMiaW4gaSYmaS5nZXRBbGxSZXNwb25zZUhlYWRlcnMoKSkseT17ZGF0YTohb3x8bz09PSJ0ZXh0Inx8bz09PSJqc29uIj9pLnJlc3BvbnNlVGV4dDppLnJlc3BvbnNlLHN0YXR1czppLnN0YXR1cyxzdGF0dXNUZXh0Omkuc3RhdHVzVGV4dCxoZWFkZXJzOkUsY29uZmlnOkEscmVxdWVzdDppfTtNQShmdW5jdGlvbihSKXtJKFIpLFEoKX0sZnVuY3Rpb24oUil7ZShSKSxRKCl9LHkpLGk9bnVsbH1pZigib25sb2FkZW5kImluIGk/aS5vbmxvYWRlbmQ9czppLm9ucmVhZHlzdGF0ZWNoYW5nZT1mdW5jdGlvbigpeyFpfHxpLnJlYWR5U3RhdGUhPT00fHxpLnN0YXR1cz09PTAmJiEoaS5yZXNwb25zZVVSTCYmaS5yZXNwb25zZVVSTC5pbmRleE9mKCJmaWxlOiIpPT09MCl8fHNldFRpbWVvdXQocyl9LGkub25hYm9ydD1mdW5jdGlvbigpe2kmJihlKG5ldyBsKCJSZXF1ZXN0IGFib3J0ZWQiLGwuRUNPTk5BQk9SVEVELEEsaSkpLGk9bnVsbCl9LGkub25lcnJvcj1mdW5jdGlvbigpe2UobmV3IGwoIk5ldHdvcmsgRXJyb3IiLGwuRVJSX05FVFdPUkssQSxpKSksaT1udWxsfSxpLm9udGltZW91dD1mdW5jdGlvbigpe2xldCB1PUEudGltZW91dD8idGltZW91dCBvZiAiK0EudGltZW91dCsibXMgZXhjZWVkZWQiOiJ0aW1lb3V0IGV4Y2VlZGVkIix5PUEudHJhbnNpdGlvbmFsfHxjQTtBLnRpbWVvdXRFcnJvck1lc3NhZ2UmJih1PUEudGltZW91dEVycm9yTWVzc2FnZSksZShuZXcgbCh1LHkuY2xhcmlmeVRpbWVvdXRFcnJvcj9sLkVUSU1FRE9VVDpsLkVDT05OQUJPUlRFRCxBLGkpKSxpPW51bGx9LG0uaGFzU3RhbmRhcmRCcm93c2VyRW52JiYobiYmQy5pc0Z1bmN0aW9uKG4pJiYobj1uKEEpKSxufHxuIT09ITEmJlV0KGYpKSl7bGV0IEU9QS54c3JmSGVhZGVyTmFtZSYmQS54c3JmQ29va2llTmFtZSYmTnQucmVhZChBLnhzcmZDb29raWVOYW1lKTtFJiZyLnNldChBLnhzcmZIZWFkZXJOYW1lLEUpfWc9PT12b2lkIDAmJnIuc2V0Q29udGVudFR5cGUobnVsbCksInNldFJlcXVlc3RIZWFkZXIiaW4gaSYmQy5mb3JFYWNoKHIudG9KU09OKCksZnVuY3Rpb24odSx5KXtpLnNldFJlcXVlc3RIZWFkZXIoeSx1KX0pLEMuaXNVbmRlZmluZWQoQS53aXRoQ3JlZGVudGlhbHMpfHwoaS53aXRoQ3JlZGVudGlhbHM9ISFBLndpdGhDcmVkZW50aWFscyksbyYmbyE9PSJqc29uIiYmKGkucmVzcG9uc2VUeXBlPUEucmVzcG9uc2VUeXBlKSx0eXBlb2YgQS5vbkRvd25sb2FkUHJvZ3Jlc3M9PSJmdW5jdGlvbiImJmkuYWRkRXZlbnRMaXN0ZW5lcigicHJvZ3Jlc3MiLGt0KEEub25Eb3dubG9hZFByb2dyZXNzLCEwKSksdHlwZW9mIEEub25VcGxvYWRQcm9ncmVzcz09ImZ1bmN0aW9uIiYmaS51cGxvYWQmJmkudXBsb2FkLmFkZEV2ZW50TGlzdGVuZXIoInByb2dyZXNzIixrdChBLm9uVXBsb2FkUHJvZ3Jlc3MpKSwoQS5jYW5jZWxUb2tlbnx8QS5zaWduYWwpJiYoYz1FPT57aSYmKGUoIUV8fEUudHlwZT9uZXcgSChudWxsLEEsaSk6RSksaS5hYm9ydCgpLGk9bnVsbCl9LEEuY2FuY2VsVG9rZW4mJkEuY2FuY2VsVG9rZW4uc3Vic2NyaWJlKGMpLEEuc2lnbmFsJiYoQS5zaWduYWwuYWJvcnRlZD9jKCk6QS5zaWduYWwuYWRkRXZlbnRMaXN0ZW5lcigiYWJvcnQiLGMpKSk7bGV0IGE9T0EoZik7aWYoYSYmbS5wcm90b2NvbHMuaW5kZXhPZihhKT09PS0xKXtlKG5ldyBsKCJVbnN1cHBvcnRlZCBwcm90b2NvbCAiK2ErIjoiLGwuRVJSX0JBRF9SRVFVRVNULEEpKTtyZXR1cm59aS5zZW5kKGd8fG51bGwpfSl9O3ZhciBUQT17aHR0cDphQSx4aHI6THR9O0MuZm9yRWFjaChUQSwoQSx0KT0+e2lmKEEpe3RyeXtPYmplY3QuZGVmaW5lUHJvcGVydHkoQSwibmFtZSIse3ZhbHVlOnR9KX1jYXRjaHt9T2JqZWN0LmRlZmluZVByb3BlcnR5KEEsImFkYXB0ZXJOYW1lIix7dmFsdWU6dH0pfX0pO3ZhciBKdD1BPT5gLSAke0F9YCxhZT1BPT5DLmlzRnVuY3Rpb24oQSl8fEE9PT1udWxsfHxBPT09ITEsREE9e2dldEFkYXB0ZXI6QT0+e0E9Qy5pc0FycmF5KEEpP0E6W0FdO2xldHtsZW5ndGg6dH09QSxJLGUsZz17fTtmb3IobGV0IHI9MDtyPHQ7cisrKXtJPUFbcl07bGV0IG87aWYoZT1JLCFhZShJKSYmKGU9VEFbKG89U3RyaW5nKEkpKS50b0xvd2VyQ2FzZSgpXSxlPT09dm9pZCAwKSl0aHJvdyBuZXcgbChgVW5rbm93biBhZGFwdGVyIFwnJHtvfVwnYCk7aWYoZSlicmVhaztnW298fCIlMjMiK3JdPWV9aWYoIWUpe2xldCByPU9iamVjdC5lbnRyaWVzKGcpLm1hcCgoW24sY10pPT5gYWRhcHRlciAke259IGArKGM9PT0hMT8iaXMgbm90IHN1cHBvcnRlZCBieSB0aGUgZW52aXJvbm1lbnQiOiJpcyBub3QgYXZhaWxhYmxlIGluIHRoZSBidWlsZCIpKSxvPXQ/ci5sZW5ndGg+MT9gc2luY2UgOiUwQWArci5tYXAoSnQpLmpvaW4oYCUwQWApOiIgIitKdChyWzBdKToiYXMgbm8gYWRhcHRlciBzcGVjaWZpZWQiO3Rocm93IG5ldyBsKCJUaGVyZSBpcyBubyBzdWl0YWJsZSBhZGFwdGVyIHRvIGRpc3BhdGNoIHRoZSByZXF1ZXN0ICIrbywiRVJSX05PVF9TVVBQT1JUIil9cmV0dXJuIGV9LGFkYXB0ZXJzOlRBfTtmdW5jdGlvbiBQQShBKXtpZihBLmNhbmNlbFRva2VuJiZBLmNhbmNlbFRva2VuLnRocm93SWZSZXF1ZXN0ZWQoKSxBLnNpZ25hbCYmQS5zaWduYWwuYWJvcnRlZCl0aHJvdyBuZXcgSChudWxsLEEpfWZ1bmN0aW9uIHVBKEEpe3JldHVybiBQQShBKSxBLmhlYWRlcnM9cC5mcm9tKEEuaGVhZGVycyksQS5kYXRhPV8uY2FsbChBLEEudHJhbnNmb3JtUmVxdWVzdCksWyJwb3N0IiwicHV0IiwicGF0Y2giXS5pbmRleE9mKEEubWV0aG9kKSE9PS0xJiZBLmhlYWRlcnMuc2V0Q29udGVudFR5cGUoImFwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCIsITEpLERBLmdldEFkYXB0ZXIoQS5hZGFwdGVyfHxULmFkYXB0ZXIpKEEpLnRoZW4oZnVuY3Rpb24oZSl7cmV0dXJuIFBBKEEpLGUuZGF0YT1fLmNhbGwoQSxBLnRyYW5zZm9ybVJlc3BvbnNlLGUpLGUuaGVhZGVycz1wLmZyb20oZS5oZWFkZXJzKSxlfSxmdW5jdGlvbihlKXtyZXR1cm4gdihlKXx8KFBBKEEpLGUmJmUucmVzcG9uc2UmJihlLnJlc3BvbnNlLmRhdGE9Xy5jYWxsKEEsQS50cmFuc2Zvcm1SZXNwb25zZSxlLnJlc3BvbnNlKSxlLnJlc3BvbnNlLmhlYWRlcnM9cC5mcm9tKGUucmVzcG9uc2UuaGVhZGVycykpKSxQcm9taXNlLnJlamVjdChlKX0pfXZhciBIdD1BPT5BIGluc3RhbmNlb2YgcD97Li4uQX06QTtmdW5jdGlvbiBrKEEsdCl7dD10fHx7fTtsZXQgST17fTtmdW5jdGlvbiBlKFEsQixpKXtyZXR1cm4gQy5pc1BsYWluT2JqZWN0KFEpJiZDLmlzUGxhaW5PYmplY3QoQik/Qy5tZXJnZS5jYWxsKHtjYXNlbGVzczppfSxRLEIpOkMuaXNQbGFpbk9iamVjdChCKT9DLm1lcmdlKHt9LEIpOkMuaXNBcnJheShCKT9CLnNsaWNlKCk6Qn1mdW5jdGlvbiBnKFEsQixpKXtpZihDLmlzVW5kZWZpbmVkKEIpKXtpZighQy5pc1VuZGVmaW5lZChRKSlyZXR1cm4gZSh2b2lkIDAsUSxpKX1lbHNlIHJldHVybiBlKFEsQixpKX1mdW5jdGlvbiByKFEsQil7aWYoIUMuaXNVbmRlZmluZWQoQikpcmV0dXJuIGUodm9pZCAwLEIpfWZ1bmN0aW9uIG8oUSxCKXtpZihDLmlzVW5kZWZpbmVkKEIpKXtpZighQy5pc1VuZGVmaW5lZChRKSlyZXR1cm4gZSh2b2lkIDAsUSl9ZWxzZSByZXR1cm4gZSh2b2lkIDAsQil9ZnVuY3Rpb24gbihRLEIsaSl7aWYoaSBpbiB0KXJldHVybiBlKFEsQik7aWYoaSBpbiBBKXJldHVybiBlKHZvaWQgMCxRKX1sZXQgYz17dXJsOnIsbWV0aG9kOnIsZGF0YTpyLGJhc2VVUkw6byx0cmFuc2Zvcm1SZXF1ZXN0Om8sdHJhbnNmb3JtUmVzcG9uc2U6byxwYXJhbXNTZXJpYWxpemVyOm8sdGltZW91dDpvLHRpbWVvdXRNZXNzYWdlOm8sd2l0aENyZWRlbnRpYWxzOm8sd2l0aFhTUkZUb2tlbjpvLGFkYXB0ZXI6byxyZXNwb25zZVR5cGU6byx4c3JmQ29va2llTmFtZTpvLHhzcmZIZWFkZXJOYW1lOm8sb25VcGxvYWRQcm9ncmVzczpvLG9uRG93bmxvYWRQcm9ncmVzczpvLGRlY29tcHJlc3M6byxtYXhDb250ZW50TGVuZ3RoOm8sbWF4Qm9keUxlbmd0aDpvLGJlZm9yZVJlZGlyZWN0Om8sdHJhbnNwb3J0Om8saHR0cEFnZW50Om8saHR0cHNBZ2VudDpvLGNhbmNlbFRva2VuOm8sc29ja2V0UGF0aDpvLHJlc3BvbnNlRW5jb2Rpbmc6byx2YWxpZGF0ZVN0YXR1czpuLGhlYWRlcnM6KFEsQik9PmcoSHQoUSksSHQoQiksITApfTtyZXR1cm4gQy5mb3JFYWNoKE9iamVjdC5rZXlzKE9iamVjdC5hc3NpZ24oe30sQSx0KSksZnVuY3Rpb24oQil7bGV0IGk9Y1tCXXx8ZyxmPWkoQVtCXSx0W0JdLEIpO0MuaXNVbmRlZmluZWQoZikmJmkhPT1ufHwoSVtCXT1mKX0pLEl9dmFyIGhBPSIxLjYuOCI7dmFyIHhBPXt9O1sib2JqZWN0IiwiYm9vbGVhbiIsIm51bWJlciIsImZ1bmN0aW9uIiwic3RyaW5nIiwic3ltYm9sIl0uZm9yRWFjaCgoQSx0KT0+e3hBW0FdPWZ1bmN0aW9uKGUpe3JldHVybiB0eXBlb2YgZT09PUF8fCJhIisodDwxPyJuICI6IiAiKStBfX0pO3ZhciBZdD17fTt4QS50cmFuc2l0aW9uYWw9ZnVuY3Rpb24odCxJLGUpe2Z1bmN0aW9uIGcocixvKXtyZXR1cm4iW0F4aW9zIHYiK2hBKyJdIFRyYW5zaXRpb25hbCBvcHRpb24gXCciK3IrIlwnIitvKyhlPyIuICIrZToiIil9cmV0dXJuKHIsbyxuKT0+e2lmKHQ9PT0hMSl0aHJvdyBuZXcgbChnKG8sIiBoYXMgYmVlbiByZW1vdmVkIisoST8iIGluICIrSToiIikpLGwuRVJSX0RFUFJFQ0FURUQpO3JldHVybiBJJiYhWXRbb10mJihZdFtvXT0hMCxjb25zb2xlLndhcm4oZyhvLCIgaGFzIGJlZW4gZGVwcmVjYXRlZCBzaW5jZSB2IitJKyIgYW5kIHdpbGwgYmUgcmVtb3ZlZCBpbiB0aGUgbmVhciBmdXR1cmUiKSkpLHQ/dChyLG8sbik6ITB9fTtmdW5jdGlvbiBFZShBLHQsSSl7aWYodHlwZW9mIEEhPSJvYmplY3QiKXRocm93IG5ldyBsKCJvcHRpb25zIG11c3QgYmUgYW4gb2JqZWN0IixsLkVSUl9CQURfT1BUSU9OX1ZBTFVFKTtsZXQgZT1PYmplY3Qua2V5cyhBKSxnPWUubGVuZ3RoO2Zvcig7Zy0tID4wOyl7bGV0IHI9ZVtnXSxvPXRbcl07aWYobyl7bGV0IG49QVtyXSxjPW49PT12b2lkIDB8fG8obixyLEEpO2lmKGMhPT0hMCl0aHJvdyBuZXcgbCgib3B0aW9uICIrcisiIG11c3QgYmUgIitjLGwuRVJSX0JBRF9PUFRJT05fVkFMVUUpO2NvbnRpbnVlfWlmKEkhPT0hMCl0aHJvdyBuZXcgbCgiVW5rbm93biBvcHRpb24gIityLGwuRVJSX0JBRF9PUFRJT04pfX12YXIgZEE9e2Fzc2VydE9wdGlvbnM6RWUsdmFsaWRhdG9yczp4QX07dmFyIFk9ZEEudmFsaWRhdG9ycyx4PWNsYXNze2NvbnN0cnVjdG9yKHQpe3RoaXMuZGVmYXVsdHM9dCx0aGlzLmludGVyY2VwdG9ycz17cmVxdWVzdDpuZXcgTEEscmVzcG9uc2U6bmV3IExBfX1hc3luYyByZXF1ZXN0KHQsSSl7dHJ5e3JldHVybiBhd2FpdCB0aGlzLl9yZXF1ZXN0KHQsSSl9Y2F0Y2goZSl7aWYoZSBpbnN0YW5jZW9mIEVycm9yKXtsZXQgZztFcnJvci5jYXB0dXJlU3RhY2tUcmFjZT9FcnJvci5jYXB0dXJlU3RhY2tUcmFjZShnPXt9KTpnPW5ldyBFcnJvcjtsZXQgcj1nLnN0YWNrP2cuc3RhY2sucmVwbGFjZSgvXi4rXFxuLywiIik6IiI7ZS5zdGFjaz9yJiYhU3RyaW5nKGUuc3RhY2spLmVuZHNXaXRoKHIucmVwbGFjZSgvXi4rXFxuLitcXG4vLCIiKSkmJihlLnN0YWNrKz1gJTBBYCtyKTplLnN0YWNrPXJ9dGhyb3cgZX19X3JlcXVlc3QodCxJKXt0eXBlb2YgdD09InN0cmluZyI/KEk9SXx8e30sSS51cmw9dCk6ST10fHx7fSxJPWsodGhpcy5kZWZhdWx0cyxJKTtsZXR7dHJhbnNpdGlvbmFsOmUscGFyYW1zU2VyaWFsaXplcjpnLGhlYWRlcnM6cn09STtlIT09dm9pZCAwJiZkQS5hc3NlcnRPcHRpb25zKGUse3NpbGVudEpTT05QYXJzaW5nOlkudHJhbnNpdGlvbmFsKFkuYm9vbGVhbiksZm9yY2VkSlNPTlBhcnNpbmc6WS50cmFuc2l0aW9uYWwoWS5ib29sZWFuKSxjbGFyaWZ5VGltZW91dEVycm9yOlkudHJhbnNpdGlvbmFsKFkuYm9vbGVhbil9LCExKSxnIT1udWxsJiYoQy5pc0Z1bmN0aW9uKGcpP0kucGFyYW1zU2VyaWFsaXplcj17c2VyaWFsaXplOmd9OmRBLmFzc2VydE9wdGlvbnMoZyx7ZW5jb2RlOlkuZnVuY3Rpb24sc2VyaWFsaXplOlkuZnVuY3Rpb259LCEwKSksSS5tZXRob2Q9KEkubWV0aG9kfHx0aGlzLmRlZmF1bHRzLm1ldGhvZHx8ImdldCIpLnRvTG93ZXJDYXNlKCk7bGV0IG89ciYmQy5tZXJnZShyLmNvbW1vbixyW0kubWV0aG9kXSk7ciYmQy5mb3JFYWNoKFsiZGVsZXRlIiwiZ2V0IiwiaGVhZCIsInBvc3QiLCJwdXQiLCJwYXRjaCIsImNvbW1vbiJdLGE9PntkZWxldGUgclthXX0pLEkuaGVhZGVycz1wLmNvbmNhdChvLHIpO2xldCBuPVtdLGM9ITA7dGhpcy5pbnRlcmNlcHRvcnMucmVxdWVzdC5mb3JFYWNoKGZ1bmN0aW9uKEUpe3R5cGVvZiBFLnJ1bldoZW49PSJmdW5jdGlvbiImJkUucnVuV2hlbihJKT09PSExfHwoYz1jJiZFLnN5bmNocm9ub3VzLG4udW5zaGlmdChFLmZ1bGZpbGxlZCxFLnJlamVjdGVkKSl9KTtsZXQgUT1bXTt0aGlzLmludGVyY2VwdG9ycy5yZXNwb25zZS5mb3JFYWNoKGZ1bmN0aW9uKEUpe1EucHVzaChFLmZ1bGZpbGxlZCxFLnJlamVjdGVkKX0pO2xldCBCLGk9MCxmO2lmKCFjKXtsZXQgYT1bdUEuYmluZCh0aGlzKSx2b2lkIDBdO2ZvcihhLnVuc2hpZnQuYXBwbHkoYSxuKSxhLnB1c2guYXBwbHkoYSxRKSxmPWEubGVuZ3RoLEI9UHJvbWlzZS5yZXNvbHZlKEkpO2k8ZjspQj1CLnRoZW4oYVtpKytdLGFbaSsrXSk7cmV0dXJuIEJ9Zj1uLmxlbmd0aDtsZXQgcz1JO2ZvcihpPTA7aTxmOyl7bGV0IGE9bltpKytdLEU9bltpKytdO3RyeXtzPWEocyl9Y2F0Y2godSl7RS5jYWxsKHRoaXMsdSk7YnJlYWt9fXRyeXtCPXVBLmNhbGwodGhpcyxzKX1jYXRjaChhKXtyZXR1cm4gUHJvbWlzZS5yZWplY3QoYSl9Zm9yKGk9MCxmPVEubGVuZ3RoO2k8ZjspQj1CLnRoZW4oUVtpKytdLFFbaSsrXSk7cmV0dXJuIEJ9Z2V0VXJpKHQpe3Q9ayh0aGlzLmRlZmF1bHRzLHQpO2xldCBJPSQodC5iYXNlVVJMLHQudXJsKTtyZXR1cm4gWChJLHQucGFyYW1zLHQucGFyYW1zU2VyaWFsaXplcil9fTtDLmZvckVhY2goWyJkZWxldGUiLCJnZXQiLCJoZWFkIiwib3B0aW9ucyJdLGZ1bmN0aW9uKHQpe3gucHJvdG90eXBlW3RdPWZ1bmN0aW9uKEksZSl7cmV0dXJuIHRoaXMucmVxdWVzdChrKGV8fHt9LHttZXRob2Q6dCx1cmw6SSxkYXRhOihlfHx7fSkuZGF0YX0pKX19KTtDLmZvckVhY2goWyJwb3N0IiwicHV0IiwicGF0Y2giXSxmdW5jdGlvbih0KXtmdW5jdGlvbiBJKGUpe3JldHVybiBmdW5jdGlvbihyLG8sbil7cmV0dXJuIHRoaXMucmVxdWVzdChrKG58fHt9LHttZXRob2Q6dCxoZWFkZXJzOmU/eyJDb250ZW50LVR5cGUiOiJtdWx0aXBhcnQvZm9ybS1kYXRhIn06e30sdXJsOnIsZGF0YTpvfSkpfX14LnByb3RvdHlwZVt0XT1JKCkseC5wcm90b3R5cGVbdCsiRm9ybSJdPUkoITApfSk7dmFyIEFBPXg7dmFyIGpBPWNsYXNzIEF7Y29uc3RydWN0b3IodCl7aWYodHlwZW9mIHQhPSJmdW5jdGlvbiIpdGhyb3cgbmV3IFR5cGVFcnJvcigiZXhlY3V0b3IgbXVzdCBiZSBhIGZ1bmN0aW9uLiIpO2xldCBJO3RoaXMucHJvbWlzZT1uZXcgUHJvbWlzZShmdW5jdGlvbihyKXtJPXJ9KTtsZXQgZT10aGlzO3RoaXMucHJvbWlzZS50aGVuKGc9PntpZighZS5fbGlzdGVuZXJzKXJldHVybjtsZXQgcj1lLl9saXN0ZW5lcnMubGVuZ3RoO2Zvcig7ci0tID4wOyllLl9saXN0ZW5lcnNbcl0oZyk7ZS5fbGlzdGVuZXJzPW51bGx9KSx0aGlzLnByb21pc2UudGhlbj1nPT57bGV0IHIsbz1uZXcgUHJvbWlzZShuPT57ZS5zdWJzY3JpYmUobikscj1ufSkudGhlbihnKTtyZXR1cm4gby5jYW5jZWw9ZnVuY3Rpb24oKXtlLnVuc3Vic2NyaWJlKHIpfSxvfSx0KGZ1bmN0aW9uKHIsbyxuKXtlLnJlYXNvbnx8KGUucmVhc29uPW5ldyBIKHIsbyxuKSxJKGUucmVhc29uKSl9KX10aHJvd0lmUmVxdWVzdGVkKCl7aWYodGhpcy5yZWFzb24pdGhyb3cgdGhpcy5yZWFzb259c3Vic2NyaWJlKHQpe2lmKHRoaXMucmVhc29uKXt0KHRoaXMucmVhc29uKTtyZXR1cm59dGhpcy5fbGlzdGVuZXJzP3RoaXMuX2xpc3RlbmVycy5wdXNoKHQpOnRoaXMuX2xpc3RlbmVycz1bdF19dW5zdWJzY3JpYmUodCl7aWYoIXRoaXMuX2xpc3RlbmVycylyZXR1cm47bGV0IEk9dGhpcy5fbGlzdGVuZXJzLmluZGV4T2YodCk7SSE9PS0xJiZ0aGlzLl9saXN0ZW5lcnMuc3BsaWNlKEksMSl9c3RhdGljIHNvdXJjZSgpe2xldCB0O3JldHVybnt0b2tlbjpuZXcgQShmdW5jdGlvbihnKXt0PWd9KSxjYW5jZWw6dH19fSxidD1qQTtmdW5jdGlvbiBXQShBKXtyZXR1cm4gZnVuY3Rpb24oSSl7cmV0dXJuIEEuYXBwbHkobnVsbCxJKX19ZnVuY3Rpb24gWkEoQSl7cmV0dXJuIEMuaXNPYmplY3QoQSkmJkEuaXNBeGlvc0Vycm9yPT09ITB9dmFyIFZBPXtDb250aW51ZToxMDAsU3dpdGNoaW5nUHJvdG9jb2xzOjEwMSxQcm9jZXNzaW5nOjEwMixFYXJseUhpbnRzOjEwMyxPazoyMDAsQ3JlYXRlZDoyMDEsQWNjZXB0ZWQ6MjAyLE5vbkF1dGhvcml0YXRpdmVJbmZvcm1hdGlvbjoyMDMsTm9Db250ZW50OjIwNCxSZXNldENvbnRlbnQ6MjA1LFBhcnRpYWxDb250ZW50OjIwNixNdWx0aVN0YXR1czoyMDcsQWxyZWFkeVJlcG9ydGVkOjIwOCxJbVVzZWQ6MjI2LE11bHRpcGxlQ2hvaWNlczozMDAsTW92ZWRQZXJtYW5lbnRseTozMDEsRm91bmQ6MzAyLFNlZU90aGVyOjMwMyxOb3RNb2RpZmllZDozMDQsVXNlUHJveHk6MzA1LFVudXNlZDozMDYsVGVtcG9yYXJ5UmVkaXJlY3Q6MzA3LFBlcm1hbmVudFJlZGlyZWN0OjMwOCxCYWRSZXF1ZXN0OjQwMCxVbmF1dGhvcml6ZWQ6NDAxLFBheW1lbnRSZXF1aXJlZDo0MDIsRm9yYmlkZGVuOjQwMyxOb3RGb3VuZDo0MDQsTWV0aG9kTm90QWxsb3dlZDo0MDUsTm90QWNjZXB0YWJsZTo0MDYsUHJveHlBdXRoZW50aWNhdGlvblJlcXVpcmVkOjQwNyxSZXF1ZXN0VGltZW91dDo0MDgsQ29uZmxpY3Q6NDA5LEdvbmU6NDEwLExlbmd0aFJlcXVpcmVkOjQxMSxQcmVjb25kaXRpb25GYWlsZWQ6NDEyLFBheWxvYWRUb29MYXJnZTo0MTMsVXJpVG9vTG9uZzo0MTQsVW5zdXBwb3J0ZWRNZWRpYVR5cGU6NDE1LFJhbmdlTm90U2F0aXNmaWFibGU6NDE2LEV4cGVjdGF0aW9uRmFpbGVkOjQxNyxJbUFUZWFwb3Q6NDE4LE1pc2RpcmVjdGVkUmVxdWVzdDo0MjEsVW5wcm9jZXNzYWJsZUVudGl0eTo0MjIsTG9ja2VkOjQyMyxGYWlsZWREZXBlbmRlbmN5OjQyNCxUb29FYXJseTo0MjUsVXBncmFkZVJlcXVpcmVkOjQyNixQcmVjb25kaXRpb25SZXF1aXJlZDo0MjgsVG9vTWFueVJlcXVlc3RzOjQyOSxSZXF1ZXN0SGVhZGVyRmllbGRzVG9vTGFyZ2U6NDMxLFVuYXZhaWxhYmxlRm9yTGVnYWxSZWFzb25zOjQ1MSxJbnRlcm5hbFNlcnZlckVycm9yOjUwMCxOb3RJbXBsZW1lbnRlZDo1MDEsQmFkR2F0ZXdheTo1MDIsU2VydmljZVVuYXZhaWxhYmxlOjUwMyxHYXRld2F5VGltZW91dDo1MDQsSHR0cFZlcnNpb25Ob3RTdXBwb3J0ZWQ6NTA1LFZhcmlhbnRBbHNvTmVnb3RpYXRlczo1MDYsSW5zdWZmaWNpZW50U3RvcmFnZTo1MDcsTG9vcERldGVjdGVkOjUwOCxOb3RFeHRlbmRlZDo1MTAsTmV0d29ya0F1dGhlbnRpY2F0aW9uUmVxdWlyZWQ6NTExfTtPYmplY3QuZW50cmllcyhWQSkuZm9yRWFjaCgoW0EsdF0pPT57VkFbdF09QX0pO3ZhciBNdD1WQTtmdW5jdGlvbiBxdChBKXtsZXQgdD1uZXcgQUEoQSksST1XKEFBLnByb3RvdHlwZS5yZXF1ZXN0LHQpO3JldHVybiBDLmV4dGVuZChJLEFBLnByb3RvdHlwZSx0LHthbGxPd25LZXlzOiEwfSksQy5leHRlbmQoSSx0LG51bGwse2FsbE93bktleXM6ITB9KSxJLmNyZWF0ZT1mdW5jdGlvbihnKXtyZXR1cm4gcXQoayhBLGcpKX0sSX12YXIgaD1xdChUKTtoLkF4aW9zPUFBO2guQ2FuY2VsZWRFcnJvcj1IO2guQ2FuY2VsVG9rZW49YnQ7aC5pc0NhbmNlbD12O2guVkVSU0lPTj1oQTtoLnRvRm9ybURhdGE9SjtoLkF4aW9zRXJyb3I9bDtoLkNhbmNlbD1oLkNhbmNlbGVkRXJyb3I7aC5hbGw9ZnVuY3Rpb24odCl7cmV0dXJuIFByb21pc2UuYWxsKHQpfTtoLnNwcmVhZD1XQTtoLmlzQXhpb3NFcnJvcj1aQTtoLm1lcmdlQ29uZmlnPWs7aC5BeGlvc0hlYWRlcnM9cDtoLmZvcm1Ub0pTT049QT0+ZkEoQy5pc0hUTUxGb3JtKEEpP25ldyBGb3JtRGF0YShBKTpBKTtoLmdldEFkYXB0ZXI9REEuZ2V0QWRhcHRlcjtoLkh0dHBTdGF0dXNDb2RlPU10O2guZGVmYXVsdD1oO3ZhciB5QT1oO3ZhcntBeGlvczppbyxBeGlvc0Vycm9yOkNvLENhbmNlbGVkRXJyb3I6Qm8saXNDYW5jZWw6c28sQ2FuY2VsVG9rZW46bm8sVkVSU0lPTjpRbyxhbGw6YW8sQ2FuY2VsOkVvLGlzQXhpb3NFcnJvcjpjbyxzcHJlYWQ6Zm8sdG9Gb3JtRGF0YTpsbyxBeGlvc0hlYWRlcnM6RG8sSHR0cFN0YXR1c0NvZGU6dW8sZm9ybVRvSlNPTjpobyxnZXRBZGFwdGVyOnlvLG1lcmdlQ29uZmlnOndvfT15QTt2YXIgdEEsTCx6QSxYQT17ZW52OntlbXNjcmlwdGVuX25vdGlmeV9tZW1vcnlfZ3Jvd3RoOmZ1bmN0aW9uKEEpe3pBPW5ldyBVaW50OEFycmF5KEwuZXhwb3J0cy5tZW1vcnkuYnVmZmVyKX19fSx3QT1jbGFzc3tpbml0KCl7cmV0dXJuIHRBfHwodHlwZW9mIGZldGNoPCJ1Ij90QT1mZXRjaCgiZGF0YTphcHBsaWNhdGlvbi93YXNtO2Jhc2U2NCwiK0t0KS50aGVuKHQ9PnQuYXJyYXlCdWZmZXIoKSkudGhlbih0PT5XZWJBc3NlbWJseS5pbnN0YW50aWF0ZSh0LFhBKSkudGhlbih0aGlzLl9pbml0KTp0QT1XZWJBc3NlbWJseS5pbnN0YW50aWF0ZShCdWZmZXIuZnJvbShLdCwiYmFzZTY0IiksWEEpLnRoZW4odGhpcy5faW5pdCksdEEpfV9pbml0KHQpe0w9dC5pbnN0YW5jZSxYQS5lbnYuZW1zY3JpcHRlbl9ub3RpZnlfbWVtb3J5X2dyb3d0aCgwKX1kZWNvZGUodCxJPTApe2lmKCFMKXRocm93IG5ldyBFcnJvcigiWlNURERlY29kZXI6IEF3YWl0IC5pbml0KCkgYmVmb3JlIGRlY29kaW5nLiIpO2xldCBlPXQuYnl0ZUxlbmd0aCxnPUwuZXhwb3J0cy5tYWxsb2MoZSk7ekEuc2V0KHQsZyksST1JfHxOdW1iZXIoTC5leHBvcnRzLlpTVERfZmluZERlY29tcHJlc3NlZFNpemUoZyxlKSk7bGV0IHI9TC5leHBvcnRzLm1hbGxvYyhJKSxvPUwuZXhwb3J0cy5aU1REX2RlY29tcHJlc3MocixJLGcsZSksbj16QS5zbGljZShyLHIrbyk7cmV0dXJuIEwuZXhwb3J0cy5mcmVlKGcpLEwuZXhwb3J0cy5mcmVlKHIpLG59fSxLdD0iQUdGemJRRUFBQUFCYmc1Z0EzOS9md0YvWUFGL0FYOWdBbjkvQUdBQmZ3QmdCWDkvZjM5L0FYOWdBMzkvZndCZ0JIOS9mMzhCZjJBQUFYOWdBbjkvQVg5Z0IzOS9mMzkvZjM4QmYyQUNmMzhCZm1BSWYzOS9mMzkvZjM4QmYyQUZmMzkvZjM4QVlBNS9mMzkvZjM5L2YzOS9mMzkvZndGL0FpY0JBMlZ1ZGg5bGJYTmpjbWx3ZEdWdVgyNXZkR2xtZVY5dFpXMXZjbmxmWjNKdmQzUm9BQU1ESXlJSEFBQUJBUU1IQXdFQUNRUUFCUUVJQ0FFRkJnUUVCQU1HQUFBS0FBVUxEQTBHQkFVQmNBRUJBUVVIQVFHQUFvQ0FBZ1lJQVg4QlFZQ2pCQXNIcmdFTEJtMWxiVzl5ZVFJQUJtMWhiR3h2WXdBRkJHWnlaV1VBQmd4YVUxUkVYMmx6UlhKeWIzSUFFaGxhVTFSRVgyWnBibVJFWldOdmJYQnlaWE56WldSVGFYcGxBQndQV2xOVVJGOWtaV052YlhCeVpYTnpBQ0laWDE5cGJtUnBjbVZqZEY5bWRXNWpkR2x2Ymw5MFlXSnNaUUVBRUY5ZlpYSnlibTlmYkc5allYUnBiMjRBQVFsemRHRmphMU5oZG1VQUJ3eHpkR0ZqYTFKbGMzUnZjbVVBQ0FwemRHRmphMEZzYkc5akFBa0tpL0lCSWdVQVFZUWZDek1CQVg4Z0FnUkFJQUFoQXdOQUlBTWdBUzBBQURvQUFDQURRUUZxSVFNZ0FVRUJhaUVCSUFKQkFXc2lBZzBBQ3dzZ0FBc3BBUUYvSUFJRVFDQUFJUU1EUUNBRElBRTZBQUFnQTBFQmFpRURJQUpCQVdzaUFnMEFDd3NnQUF0c0FRSi9RWUFmS0FJQUlnRWdBRUVIYWtGNGNTSUNhaUVBQWtBZ0FrRUFJQUFnQVUwYkRRQWdBRDhBUVJCMFN3UkFJQUEvQUVFUWRHdEIvLzhEYWtFUWRrQUFRWDlHQkg5QkFBVkJBQkFBUVFFTFJRMEJDMEdBSHlBQU5nSUFJQUVQQzBHRUgwRXdOZ0lBUVg4THVTY0JDMzhqQUVFUWF5SUtKQUFDUUFKQUFrQUNRQUpBQWtBQ1FBSkFBa0FDUUFKQUFrQUNRQUpBSUFCQjlBRk5CRUJCaUI4b0FnQWlCa0VRSUFCQkMycEJlSEVnQUVFTFNSc2lCVUVEZGlJQWRpSUJRUU54QkVBQ1FDQUJRWDl6UVFGeElBQnFJZ0pCQTNRaUFVR3dIMm9pQUNBQlFiZ2ZhaWdDQUNJQktBSUlJZ1JHQkVCQmlCOGdCa0YrSUFKM2NUWUNBQXdCQ3lBRUlBQTJBZ3dnQUNBRU5nSUlDeUFCUVFocUlRQWdBU0FDUVFOMElnSkJBM0kyQWdRZ0FTQUNhaUlCSUFFb0FnUkJBWEkyQWdRTUR3c2dCVUdRSHlnQ0FDSUhUUTBCSUFFRVFBSkFRUUlnQUhRaUFrRUFJQUpyY2lBQklBQjBjV2dpQVVFRGRDSUFRYkFmYWlJQ0lBQkJ1QjlxS0FJQUlnQW9BZ2dpQkVZRVFFR0lIeUFHUVg0Z0FYZHhJZ1kyQWdBTUFRc2dCQ0FDTmdJTUlBSWdCRFlDQ0FzZ0FDQUZRUU55TmdJRUlBQWdCV29pQ0NBQlFRTjBJZ0VnQldzaUJFRUJjallDQkNBQUlBRnFJQVEyQWdBZ0J3UkFJQWRCZUhGQnNCOXFJUUZCbkI4b0FnQWhBZ0ovSUFaQkFTQUhRUU4yZENJRGNVVUVRRUdJSHlBRElBWnlOZ0lBSUFFTUFRc2dBU2dDQ0FzaEF5QUJJQUkyQWdnZ0F5QUNOZ0lNSUFJZ0FUWUNEQ0FDSUFNMkFnZ0xJQUJCQ0dvaEFFR2NIeUFJTmdJQVFaQWZJQVEyQWdBTUR3dEJqQjhvQWdBaUMwVU5BU0FMYUVFQ2RFRzRJV29vQWdBaUFpZ0NCRUY0Y1NBRmF5RURJQUloQVFOQUFrQWdBU2dDRUNJQVJRUkFJQUVvQWhRaUFFVU5BUXNnQUNnQ0JFRjRjU0FGYXlJQklBTWdBU0FEU1NJQkd5RURJQUFnQWlBQkd5RUNJQUFoQVF3QkN3c2dBaWdDR0NFSklBSWdBaWdDRENJRVJ3UkFRWmdmS0FJQUdpQUNLQUlJSWdBZ0JEWUNEQ0FFSUFBMkFnZ01EZ3NnQWtFVWFpSUJLQUlBSWdCRkJFQWdBaWdDRUNJQVJRMERJQUpCRUdvaEFRc0RRQ0FCSVFnZ0FDSUVRUlJxSWdFb0FnQWlBQTBBSUFSQkVHb2hBU0FFS0FJUUlnQU5BQXNnQ0VFQU5nSUFEQTBMUVg4aEJTQUFRYjkvU3cwQUlBQkJDMm9pQUVGNGNTRUZRWXdmS0FJQUlnaEZEUUJCQUNBRmF5RURBa0FDUUFKQUFuOUJBQ0FGUVlBQ1NRMEFHa0VmSUFWQi8vLy9CMHNOQUJvZ0JVRW1JQUJCQ0habklnQnJka0VCY1NBQVFRRjBhMEUrYWdzaUIwRUNkRUc0SVdvb0FnQWlBVVVFUUVFQUlRQU1BUXRCQUNFQUlBVkJHU0FIUVFGMmEwRUFJQWRCSDBjYmRDRUNBMEFDUUNBQktBSUVRWGh4SUFWcklnWWdBMDhOQUNBQklRUWdCaUlERFFCQkFDRURJQUVoQUF3REN5QUFJQUVvQWhRaUJpQUdJQUVnQWtFZGRrRUVjV29vQWhBaUFVWWJJQUFnQmhzaEFDQUNRUUYwSVFJZ0FRMEFDd3NnQUNBRWNrVUVRRUVBSVFSQkFpQUhkQ0lBUVFBZ0FHdHlJQWh4SWdCRkRRTWdBR2hCQW5SQnVDRnFLQUlBSVFBTElBQkZEUUVMQTBBZ0FDZ0NCRUY0Y1NBRmF5SUNJQU5KSVFFZ0FpQURJQUViSVFNZ0FDQUVJQUViSVFRZ0FDZ0NFQ0lCQkg4Z0FRVWdBQ2dDRkFzaUFBMEFDd3NnQkVVTkFDQURRWkFmS0FJQUlBVnJUdzBBSUFRb0FoZ2hCeUFFSUFRb0Fnd2lBa2NFUUVHWUh5Z0NBQm9nQkNnQ0NDSUFJQUkyQWd3Z0FpQUFOZ0lJREF3TElBUkJGR29pQVNnQ0FDSUFSUVJBSUFRb0FoQWlBRVVOQXlBRVFSQnFJUUVMQTBBZ0FTRUdJQUFpQWtFVWFpSUJLQUlBSWdBTkFDQUNRUkJxSVFFZ0FpZ0NFQ0lBRFFBTElBWkJBRFlDQUF3TEN5QUZRWkFmS0FJQUlnUk5CRUJCbkI4b0FnQWhBQUpBSUFRZ0JXc2lBVUVRVHdSQUlBQWdCV29pQWlBQlFRRnlOZ0lFSUFBZ0JHb2dBVFlDQUNBQUlBVkJBM0kyQWdRTUFRc2dBQ0FFUVFOeU5nSUVJQUFnQkdvaUFTQUJLQUlFUVFGeU5nSUVRUUFoQWtFQUlRRUxRWkFmSUFFMkFnQkJuQjhnQWpZQ0FDQUFRUWhxSVFBTURRc2dCVUdVSHlnQ0FDSUNTUVJBUVpRZklBSWdCV3NpQVRZQ0FFR2dIMEdnSHlnQ0FDSUFJQVZxSWdJMkFnQWdBaUFCUVFGeU5nSUVJQUFnQlVFRGNqWUNCQ0FBUVFocUlRQU1EUXRCQUNFQUlBVkJMMm9pQXdKL1FlQWlLQUlBQkVCQjZDSW9BZ0FNQVF0QjdDSkNmemNDQUVIa0lrS0FvSUNBZ0lBRU53SUFRZUFpSUFwQkRHcEJjSEZCMktyVnFnVnpOZ0lBUWZRaVFRQTJBZ0JCeENKQkFEWUNBRUdBSUFzaUFXb2lCa0VBSUFGcklnaHhJZ0VnQlUwTkRFSEFJaWdDQUNJRUJFQkJ1Q0lvQWdBaUJ5QUJhaUlKSUFkTklBUWdDVWx5RFEwTEFrQkJ4Q0l0QUFCQkJIRkZCRUFDUUFKQUFrQUNRRUdnSHlnQ0FDSUVCRUJCeUNJaEFBTkFJQVFnQUNnQ0FDSUhUd1JBSUFjZ0FDZ0NCR29nQkVzTkF3c2dBQ2dDQ0NJQURRQUxDMEVBRUFRaUFrRi9SZzBESUFFaEJrSGtJaWdDQUNJQVFRRnJJZ1FnQW5FRVFDQUJJQUpySUFJZ0JHcEJBQ0FBYTNGcUlRWUxJQVVnQms4TkEwSEFJaWdDQUNJQUJFQkJ1Q0lvQWdBaUJDQUdhaUlJSUFSTklBQWdDRWx5RFFRTElBWVFCQ0lBSUFKSERRRU1CUXNnQmlBQ2F5QUljU0lHRUFRaUFpQUFLQUlBSUFBb0FnUnFSZzBCSUFJaEFBc2dBRUYvUmcwQklBVkJNR29nQmswRVFDQUFJUUlNQkF0QjZDSW9BZ0FpQWlBRElBWnJha0VBSUFKcmNTSUNFQVJCZjBZTkFTQUNJQVpxSVFZZ0FDRUNEQU1MSUFKQmYwY05BZ3RCeENKQnhDSW9BZ0JCQkhJMkFnQUxJQUVRQkNJQ1FYOUdRUUFRQkNJQVFYOUdjaUFBSUFKTmNnMEZJQUFnQW1zaUJpQUZRU2hxVFEwRkMwRzRJa0c0SWlnQ0FDQUdhaUlBTmdJQVFid2lLQUlBSUFCSkJFQkJ2Q0lnQURZQ0FBc0NRRUdnSHlnQ0FDSURCRUJCeUNJaEFBTkFJQUlnQUNnQ0FDSUJJQUFvQWdRaUJHcEdEUUlnQUNnQ0NDSUFEUUFMREFRTFFaZ2ZLQUlBSWdCQkFDQUFJQUpORzBVRVFFR1lIeUFDTmdJQUMwRUFJUUJCekNJZ0JqWUNBRUhJSWlBQ05nSUFRYWdmUVg4MkFnQkJyQjlCNENJb0FnQTJBZ0JCMUNKQkFEWUNBQU5BSUFCQkEzUWlBVUc0SDJvZ0FVR3dIMm9pQkRZQ0FDQUJRYndmYWlBRU5nSUFJQUJCQVdvaUFFRWdSdzBBQzBHVUh5QUdRU2hySWdCQmVDQUNhMEVIY1NJQmF5SUVOZ0lBUWFBZklBRWdBbW9pQVRZQ0FDQUJJQVJCQVhJMkFnUWdBQ0FDYWtFb05nSUVRYVFmUWZBaUtBSUFOZ0lBREFRTElBSWdBMDBnQVNBRFMzSU5BaUFBS0FJTVFRaHhEUUlnQUNBRUlBWnFOZ0lFUWFBZklBTkJlQ0FEYTBFSGNTSUFhaUlCTmdJQVFaUWZRWlFmS0FJQUlBWnFJZ0lnQUdzaUFEWUNBQ0FCSUFCQkFYSTJBZ1FnQWlBRGFrRW9OZ0lFUWFRZlFmQWlLQUlBTmdJQURBTUxRUUFoQkF3S0MwRUFJUUlNQ0F0Qm1COG9BZ0FnQWtzRVFFR1lIeUFDTmdJQUN5QUNJQVpxSVFGQnlDSWhBQUpBQWtBQ1FBTkFJQUVnQUNnQ0FFY0VRQ0FBS0FJSUlnQU5BUXdDQ3dzZ0FDMEFERUVJY1VVTkFRdEJ5Q0loQUFOQUlBTWdBQ2dDQUNJQlR3UkFJQUVnQUNnQ0JHb2lCQ0FEU3cwREN5QUFLQUlJSVFBTUFBc0FDeUFBSUFJMkFnQWdBQ0FBS0FJRUlBWnFOZ0lFSUFKQmVDQUNhMEVIY1dvaUJ5QUZRUU55TmdJRUlBRkJlQ0FCYTBFSGNXb2lCaUFGSUFkcUlnVnJJUUFnQXlBR1JnUkFRYUFmSUFVMkFnQkJsQjlCbEI4b0FnQWdBR29pQURZQ0FDQUZJQUJCQVhJMkFnUU1DQXRCbkI4b0FnQWdCa1lFUUVHY0h5QUZOZ0lBUVpBZlFaQWZLQUlBSUFCcUlnQTJBZ0FnQlNBQVFRRnlOZ0lFSUFBZ0JXb2dBRFlDQUF3SUN5QUdLQUlFSWdOQkEzRkJBVWNOQmlBRFFYaHhJUWtnQTBIL0FVMEVRQ0FHS0FJTUlnRWdCaWdDQ0NJQ1JnUkFRWWdmUVlnZktBSUFRWDRnQTBFRGRuZHhOZ0lBREFjTElBSWdBVFlDRENBQklBSTJBZ2dNQmdzZ0JpZ0NHQ0VJSUFZZ0JpZ0NEQ0lDUndSQUlBWW9BZ2dpQVNBQ05nSU1JQUlnQVRZQ0NBd0ZDeUFHUVJScUlnRW9BZ0FpQTBVRVFDQUdLQUlRSWdORkRRUWdCa0VRYWlFQkN3TkFJQUVoQkNBRElnSkJGR29pQVNnQ0FDSUREUUFnQWtFUWFpRUJJQUlvQWhBaUF3MEFDeUFFUVFBMkFnQU1CQXRCbEI4Z0JrRW9heUlBUVhnZ0FtdEJCM0VpQVdzaUNEWUNBRUdnSHlBQklBSnFJZ0UyQWdBZ0FTQUlRUUZ5TmdJRUlBQWdBbXBCS0RZQ0JFR2tIMEh3SWlnQ0FEWUNBQ0FESUFSQkp5QUVhMEVIY1dwQkwyc2lBQ0FBSUFOQkVHcEpHeUlCUVJzMkFnUWdBVUhRSWlrQ0FEY0NFQ0FCUWNnaUtRSUFOd0lJUWRBaUlBRkJDR28yQWdCQnpDSWdCallDQUVISUlpQUNOZ0lBUWRRaVFRQTJBZ0FnQVVFWWFpRUFBMEFnQUVFSE5nSUVJQUJCQ0dvZ0FFRUVhaUVBSUFSSkRRQUxJQUVnQTBZTkFDQUJJQUVvQWdSQmZuRTJBZ1FnQXlBQklBTnJJZ0pCQVhJMkFnUWdBU0FDTmdJQUlBSkIvd0ZOQkVBZ0FrRjRjVUd3SDJvaEFBSi9RWWdmS0FJQUlnRkJBU0FDUVFOMmRDSUNjVVVFUUVHSUh5QUJJQUp5TmdJQUlBQU1BUXNnQUNnQ0NBc2hBU0FBSUFNMkFnZ2dBU0FETmdJTUlBTWdBRFlDRENBRElBRTJBZ2dNQVF0Qkh5RUFJQUpCLy8vL0IwMEVRQ0FDUVNZZ0FrRUlkbWNpQUd0MlFRRnhJQUJCQVhSclFUNXFJUUFMSUFNZ0FEWUNIQ0FEUWdBM0FoQWdBRUVDZEVHNElXb2hBUUpBQWtCQmpCOG9BZ0FpQkVFQklBQjBJZ1p4UlFSQVFZd2ZJQVFnQm5JMkFnQWdBU0FETmdJQURBRUxJQUpCR1NBQVFRRjJhMEVBSUFCQkgwY2JkQ0VBSUFFb0FnQWhCQU5BSUFRaUFTZ0NCRUY0Y1NBQ1JnMENJQUJCSFhZaEJDQUFRUUYwSVFBZ0FTQUVRUVJ4YWlJR0tBSVFJZ1FOQUFzZ0JpQUROZ0lRQ3lBRElBRTJBaGdnQXlBRE5nSU1JQU1nQXpZQ0NBd0JDeUFCS0FJSUlnQWdBellDRENBQklBTTJBZ2dnQTBFQU5nSVlJQU1nQVRZQ0RDQURJQUEyQWdnTFFaUWZLQUlBSWdBZ0JVME5BRUdVSHlBQUlBVnJJZ0UyQWdCQm9COUJvQjhvQWdBaUFDQUZhaUlDTmdJQUlBSWdBVUVCY2pZQ0JDQUFJQVZCQTNJMkFnUWdBRUVJYWlFQURBZ0xRWVFmUVRBMkFnQkJBQ0VBREFjTFFRQWhBZ3NnQ0VVTkFBSkFJQVlvQWh3aUFVRUNkRUc0SVdvaUJDZ0NBQ0FHUmdSQUlBUWdBallDQUNBQ0RRRkJqQjlCakI4b0FnQkJmaUFCZDNFMkFnQU1BZ3NnQ0VFUVFSUWdDQ2dDRUNBR1JodHFJQUkyQWdBZ0FrVU5BUXNnQWlBSU5nSVlJQVlvQWhBaUFRUkFJQUlnQVRZQ0VDQUJJQUkyQWhnTElBWW9BaFFpQVVVTkFDQUNJQUUyQWhRZ0FTQUNOZ0lZQ3lBQUlBbHFJUUFnQmlBSmFpSUdLQUlFSVFNTElBWWdBMEYrY1RZQ0JDQUZJQUJCQVhJMkFnUWdBQ0FGYWlBQU5nSUFJQUJCL3dGTkJFQWdBRUY0Y1VHd0gyb2hBUUovUVlnZktBSUFJZ0pCQVNBQVFRTjJkQ0lBY1VVRVFFR0lIeUFBSUFKeU5nSUFJQUVNQVFzZ0FTZ0NDQXNoQUNBQklBVTJBZ2dnQUNBRk5nSU1JQVVnQVRZQ0RDQUZJQUEyQWdnTUFRdEJIeUVESUFCQi8vLy9CMDBFUUNBQVFTWWdBRUVJZG1jaUFXdDJRUUZ4SUFGQkFYUnJRVDVxSVFNTElBVWdBellDSENBRlFnQTNBaEFnQTBFQ2RFRzRJV29oQVFKQUFrQkJqQjhvQWdBaUFrRUJJQU4wSWdSeFJRUkFRWXdmSUFJZ0JISTJBZ0FnQVNBRk5nSUFEQUVMSUFCQkdTQURRUUYyYTBFQUlBTkJIMGNiZENFRElBRW9BZ0FoQWdOQUlBSWlBU2dDQkVGNGNTQUFSZzBDSUFOQkhYWWhBaUFEUVFGMElRTWdBU0FDUVFSeGFpSUVLQUlRSWdJTkFBc2dCQ0FGTmdJUUN5QUZJQUUyQWhnZ0JTQUZOZ0lNSUFVZ0JUWUNDQXdCQ3lBQktBSUlJZ0FnQlRZQ0RDQUJJQVUyQWdnZ0JVRUFOZ0lZSUFVZ0FUWUNEQ0FGSUFBMkFnZ0xJQWRCQ0dvaEFBd0NDd0pBSUFkRkRRQUNRQ0FFS0FJY0lnQkJBblJCdUNGcUlnRW9BZ0FnQkVZRVFDQUJJQUkyQWdBZ0FnMEJRWXdmSUFoQmZpQUFkM0VpQ0RZQ0FBd0NDeUFIUVJCQkZDQUhLQUlRSUFSR0cyb2dBallDQUNBQ1JRMEJDeUFDSUFjMkFoZ2dCQ2dDRUNJQUJFQWdBaUFBTmdJUUlBQWdBallDR0FzZ0JDZ0NGQ0lBUlEwQUlBSWdBRFlDRkNBQUlBSTJBaGdMQWtBZ0EwRVBUUVJBSUFRZ0F5QUZhaUlBUVFOeU5nSUVJQUFnQkdvaUFDQUFLQUlFUVFGeU5nSUVEQUVMSUFRZ0JVRURjallDQkNBRUlBVnFJZ0lnQTBFQmNqWUNCQ0FDSUFOcUlBTTJBZ0FnQTBIL0FVMEVRQ0FEUVhoeFFiQWZhaUVBQW45QmlCOG9BZ0FpQVVFQklBTkJBM1owSWdOeFJRUkFRWWdmSUFFZ0EzSTJBZ0FnQUF3QkN5QUFLQUlJQ3lFQklBQWdBallDQ0NBQklBSTJBZ3dnQWlBQU5nSU1JQUlnQVRZQ0NBd0JDMEVmSVFBZ0EwSC8vLzhIVFFSQUlBTkJKaUFEUVFoMlp5SUFhM1pCQVhFZ0FFRUJkR3RCUG1vaEFBc2dBaUFBTmdJY0lBSkNBRGNDRUNBQVFRSjBRYmdoYWlFQkFrQUNRQ0FJUVFFZ0FIUWlCbkZGQkVCQmpCOGdCaUFJY2pZQ0FDQUJJQUkyQWdBTUFRc2dBMEVaSUFCQkFYWnJRUUFnQUVFZlJ4dDBJUUFnQVNnQ0FDRUZBMEFnQlNJQktBSUVRWGh4SUFOR0RRSWdBRUVkZGlFR0lBQkJBWFFoQUNBQklBWkJCSEZxSWdZb0FoQWlCUTBBQ3lBR0lBSTJBaEFMSUFJZ0FUWUNHQ0FDSUFJMkFnd2dBaUFDTmdJSURBRUxJQUVvQWdnaUFDQUNOZ0lNSUFFZ0FqWUNDQ0FDUVFBMkFoZ2dBaUFCTmdJTUlBSWdBRFlDQ0FzZ0JFRUlhaUVBREFFTEFrQWdDVVVOQUFKQUlBSW9BaHdpQUVFQ2RFRzRJV29pQVNnQ0FDQUNSZ1JBSUFFZ0JEWUNBQ0FFRFFGQmpCOGdDMEYrSUFCM2NUWUNBQXdDQ3lBSlFSQkJGQ0FKS0FJUUlBSkdHMm9nQkRZQ0FDQUVSUTBCQ3lBRUlBazJBaGdnQWlnQ0VDSUFCRUFnQkNBQU5nSVFJQUFnQkRZQ0dBc2dBaWdDRkNJQVJRMEFJQVFnQURZQ0ZDQUFJQVEyQWhnTEFrQWdBMEVQVFFSQUlBSWdBeUFGYWlJQVFRTnlOZ0lFSUFBZ0Ftb2lBQ0FBS0FJRVFRRnlOZ0lFREFFTElBSWdCVUVEY2pZQ0JDQUNJQVZxSWdRZ0EwRUJjallDQkNBRElBUnFJQU0yQWdBZ0J3UkFJQWRCZUhGQnNCOXFJUUJCbkI4b0FnQWhBUUovUVFFZ0IwRURkblFpQlNBR2NVVUVRRUdJSHlBRklBWnlOZ0lBSUFBTUFRc2dBQ2dDQ0FzaEJpQUFJQUUyQWdnZ0JpQUJOZ0lNSUFFZ0FEWUNEQ0FCSUFZMkFnZ0xRWndmSUFRMkFnQkJrQjhnQXpZQ0FBc2dBa0VJYWlFQUN5QUtRUkJxSkFBZ0FBdlNDd0VIZndKQUlBQkZEUUFnQUVFSWF5SUNJQUJCQkdzb0FnQWlBVUY0Y1NJQWFpRUZBa0FnQVVFQmNRMEFJQUZCQTNGRkRRRWdBaUFDS0FJQUlnRnJJZ0pCbUI4b0FnQkpEUUVnQUNBQmFpRUFBa0FDUUVHY0h5Z0NBQ0FDUndSQUlBRkIvd0ZOQkVBZ0FVRURkaUVFSUFJb0Fnd2lBU0FDS0FJSUlnTkdCRUJCaUI5QmlCOG9BZ0JCZmlBRWQzRTJBZ0FNQlFzZ0F5QUJOZ0lNSUFFZ0F6WUNDQXdFQ3lBQ0tBSVlJUVlnQWlBQ0tBSU1JZ0ZIQkVBZ0FpZ0NDQ0lESUFFMkFnd2dBU0FETmdJSURBTUxJQUpCRkdvaUJDZ0NBQ0lEUlFSQUlBSW9BaEFpQTBVTkFpQUNRUkJxSVFRTEEwQWdCQ0VISUFNaUFVRVVhaUlFS0FJQUlnTU5BQ0FCUVJCcUlRUWdBU2dDRUNJRERRQUxJQWRCQURZQ0FBd0NDeUFGS0FJRUlnRkJBM0ZCQTBjTkFrR1FIeUFBTmdJQUlBVWdBVUYrY1RZQ0JDQUNJQUJCQVhJMkFnUWdCU0FBTmdJQUR3dEJBQ0VCQ3lBR1JRMEFBa0FnQWlnQ0hDSURRUUowUWJnaGFpSUVLQUlBSUFKR0JFQWdCQ0FCTmdJQUlBRU5BVUdNSDBHTUh5Z0NBRUYrSUFOM2NUWUNBQXdDQ3lBR1FSQkJGQ0FHS0FJUUlBSkdHMm9nQVRZQ0FDQUJSUTBCQ3lBQklBWTJBaGdnQWlnQ0VDSURCRUFnQVNBRE5nSVFJQU1nQVRZQ0dBc2dBaWdDRkNJRFJRMEFJQUVnQXpZQ0ZDQURJQUUyQWhnTElBSWdCVThOQUNBRktBSUVJZ0ZCQVhGRkRRQUNRQUpBQWtBQ1FDQUJRUUp4UlFSQVFhQWZLQUlBSUFWR0JFQkJvQjhnQWpZQ0FFR1VIMEdVSHlnQ0FDQUFhaUlBTmdJQUlBSWdBRUVCY2pZQ0JDQUNRWndmS0FJQVJ3MEdRWkFmUVFBMkFnQkJuQjlCQURZQ0FBOExRWndmS0FJQUlBVkdCRUJCbkI4Z0FqWUNBRUdRSDBHUUh5Z0NBQ0FBYWlJQU5nSUFJQUlnQUVFQmNqWUNCQ0FBSUFKcUlBQTJBZ0FQQ3lBQlFYaHhJQUJxSVFBZ0FVSC9BVTBFUUNBQlFRTjJJUVFnQlNnQ0RDSUJJQVVvQWdnaUEwWUVRRUdJSDBHSUh5Z0NBRUYrSUFSM2NUWUNBQXdGQ3lBRElBRTJBZ3dnQVNBRE5nSUlEQVFMSUFVb0FoZ2hCaUFGSUFVb0Fnd2lBVWNFUUVHWUh5Z0NBQm9nQlNnQ0NDSURJQUUyQWd3Z0FTQUROZ0lJREFNTElBVkJGR29pQkNnQ0FDSURSUVJBSUFVb0FoQWlBMFVOQWlBRlFSQnFJUVFMQTBBZ0JDRUhJQU1pQVVFVWFpSUVLQUlBSWdNTkFDQUJRUkJxSVFRZ0FTZ0NFQ0lERFFBTElBZEJBRFlDQUF3Q0N5QUZJQUZCZm5FMkFnUWdBaUFBUVFGeU5nSUVJQUFnQW1vZ0FEWUNBQXdEQzBFQUlRRUxJQVpGRFFBQ1FDQUZLQUljSWdOQkFuUkJ1Q0ZxSWdRb0FnQWdCVVlFUUNBRUlBRTJBZ0FnQVEwQlFZd2ZRWXdmS0FJQVFYNGdBM2R4TmdJQURBSUxJQVpCRUVFVUlBWW9BaEFnQlVZYmFpQUJOZ0lBSUFGRkRRRUxJQUVnQmpZQ0dDQUZLQUlRSWdNRVFDQUJJQU0yQWhBZ0F5QUJOZ0lZQ3lBRktBSVVJZ05GRFFBZ0FTQUROZ0lVSUFNZ0FUWUNHQXNnQWlBQVFRRnlOZ0lFSUFBZ0Ftb2dBRFlDQUNBQ1Fad2ZLQUlBUncwQVFaQWZJQUEyQWdBUEN5QUFRZjhCVFFSQUlBQkJlSEZCc0I5cUlRRUNmMEdJSHlnQ0FDSURRUUVnQUVFRGRuUWlBSEZGQkVCQmlCOGdBQ0FEY2pZQ0FDQUJEQUVMSUFFb0FnZ0xJUUFnQVNBQ05nSUlJQUFnQWpZQ0RDQUNJQUUyQWd3Z0FpQUFOZ0lJRHd0Qkh5RURJQUJCLy8vL0IwMEVRQ0FBUVNZZ0FFRUlkbWNpQVd0MlFRRnhJQUZCQVhSclFUNXFJUU1MSUFJZ0F6WUNIQ0FDUWdBM0FoQWdBMEVDZEVHNElXb2hBUUpBQWtBQ1FFR01IeWdDQUNJRVFRRWdBM1FpQjNGRkJFQkJqQjhnQkNBSGNqWUNBQ0FCSUFJMkFnQWdBaUFCTmdJWURBRUxJQUJCR1NBRFFRRjJhMEVBSUFOQkgwY2JkQ0VESUFFb0FnQWhBUU5BSUFFaUJDZ0NCRUY0Y1NBQVJnMENJQU5CSFhZaEFTQURRUUYwSVFNZ0JDQUJRUVJ4YWlJSFFSQnFLQUlBSWdFTkFBc2dCeUFDTmdJUUlBSWdCRFlDR0FzZ0FpQUNOZ0lNSUFJZ0FqWUNDQXdCQ3lBRUtBSUlJZ0FnQWpZQ0RDQUVJQUkyQWdnZ0FrRUFOZ0lZSUFJZ0JEWUNEQ0FDSUFBMkFnZ0xRYWdmUWFnZktBSUFRUUZySWdCQmZ5QUFHellDQUFzTEJBQWpBQXNHQUNBQUpBQUxFQUFqQUNBQWEwRndjU0lBSkFBZ0FBdEtBUUYvSUFBZ0FVa0VRQ0FBSUFFZ0FoQUNEd3NnQWdSQUlBQWdBbW9oQXlBQklBSnFJUUVEUUNBRFFRRnJJZ01nQVVFQmF5SUJMUUFBT2dBQUlBSkJBV3NpQWcwQUN3c2dBQXY5RGdJUmZ3RitJd0JCTUdzaUJ5UUFRYmgvSVFnQ1FDQUZSUTBBSUFRc0FBQWlDVUgvQVhFaEN3SkFJQWxCQUVnRVFDQUxRZjRBYTBFQmRpSUdJQVZQRFFKQmJDRUlJQXRCL3dCcklndEIvd0ZMRFFJZ0JFRUJhaUVJUVFBaEJRTkFJQVVnQzA4RVFDQUxJUWdnQmlFTERBTUZJQUFnQldvZ0NDQUZRUUYyYWlJRUxRQUFRUVIyT2dBQUlBQWdCVUVCY21vZ0JDMEFBRUVQY1RvQUFDQUZRUUpxSVFVTUFRc0FDd0FMSUFVZ0MwME5BU0FIUWY4Qk5nSUVJQVlnQjBFRWFpQUhRUWhxSUFSQkFXb2lEaUFMRUF3aUJFR0lmMHNFUUNBRUlRZ01BZ3RCVkNFSUlBY29BZ2dpRUVFR1N3MEJJQWNvQWdRaUVVRUJkQ0lKUVFKcXJVSUJJQkN0aGlJWVFRRWdFSFFpRFVFQmFpSUZyVUlDaG54OFFndDhRdnovLy8vLy8vLy8vd0NEUXVRQ1ZnMEJRVkloQ0NBUlFmOEJTdzBCSUExQmYzTkJBblJCNUFKcXJTQVJRUUZxSWhWQkFYU3RJQmg4UWdoOFZBMEJJQXNnQkdzaEZpQUVJQTVxSVJjZ0JrR0FCR29pRWlBRlFRSjBhaUlSSUFscVFRSnFJUTRnQmtHRUJHb2hFMEdBZ0FJZ0VIUkJFSFloQ1VFQUlRVkJBU0VQSUExQkFXc2lGQ0VLQTBBZ0JTQVZSa1VFUUFKQUlBWWdCVUVCZENJSWFpOEJBQ0lFUWYvL0EwWUVRQ0FUSUFwQkFuUnFJQVU2QUFJZ0NrRUJheUVLUVFFaEJBd0JDeUFQUVFBZ0NTQUV3VW9iSVE4TElBZ2dFV29nQkRzQkFDQUZRUUZxSVFVTUFRc0xJQVlnRHpzQmdnUWdCaUFRT3dHQUJBSkFJQW9nRkVZRVFDQU5RUU4ySVFoQ0FDRVlRUUFoRHdOQUlBd2dGVVlFUUNBSUlBMUJBWFpxUVFOcUlnbEJBWFFoQ0VFQUlRUkJBQ0VLQTBCQkFDRUZJQW9nRFU4TkJBTkFJQVZCQWtaRkJFQWdFeUFGSUFsc0lBUnFJQlJ4UVFKMGFpQU9JQVVnQ21wcUxRQUFPZ0FDSUFWQkFXb2hCUXdCQ3dzZ0NrRUNhaUVLSUFRZ0NHb2dGSEVoQkF3QUN3QUZJQVlnREVFQmRHb3VBUUFoQ1NBT0lBOXFJZ1FnR0RjQUFFRUlJUVVEUUNBRklBbE9SUVJBSUFRZ0JXb2dHRGNBQUNBRlFRaHFJUVVNQVFzTElCaENnWUtFaUpDZ3dJQUJmQ0VZSUF4QkFXb2hEQ0FKSUE5cUlROE1BUXNBQ3dBTElBMUJBM1lnRFVFQmRtcEJBMm9oQ0VFQUlRVURRQ0FNSUJWR1JRUkFRUUFoQ1NBR0lBeEJBWFJxTGdFQUlnUkJBQ0FFUVFCS0d5RUVBMEFnQkNBSlJrVUVRQ0FUSUFWQkFuUnFJQXc2QUFJRFFDQUZJQWhxSUJSeElnVWdDa3NOQUFzZ0NVRUJhaUVKREFFTEN5QU1RUUZxSVF3TUFRc0xRWDhoQ0NBRkRRSUxJQkJCQVdvaENFRUFJUVVEUUNBRklBMUdSUVJBSUJFZ0V5QUZRUUowYWlJT0xRQUNRUUYwYWlJRUlBUXZBUUFpQ1VFQmFqc0JBQ0FPSUFnZ0NXZEJZSE5xSWdRNkFBTWdEaUFKSUFSMElBMXJPd0VBSUFWQkFXb2hCUXdCQ3dzQ1FBSkFJQVl2QVlJRUJFQWdCMEVjYWlJRUlCY2dGaEFOSWdoQmlIOUxEUUlnQjBFVWFpQUVJQklRRGlBSFFReHFJQVFnRWhBT1FRQWhCUU5BSUFkQkhHb2lCQkFQSUFWQit3RkxjZzBDSUFBZ0JXb2lCaUFIUVJScUlBUVFFRG9BQUNBR0lBZEJER29nQkJBUU9nQUJJQVZCQW5JaEJDQUhRUnhxRUE4RVFDQUVJUVVNQXdVZ0FDQUVhaUFIUVJScUlBZEJIR29pQkJBUU9nQUFJQVlnQjBFTWFpQUVFQkE2QUFNZ0JVRUVhaUVGREFFTEFBc0FDeUFIUVJ4cUlnUWdGeUFXRUEwaUNFR0lmMHNOQVNBSFFSUnFJQVFnRWhBT0lBZEJER29nQkNBU0VBNUJBQ0VGQTBBZ0IwRWNhaUlFRUE4Z0JVSDdBVXR5UlFSQUlBQWdCV29pQmlBSFFSUnFJQVFRRVRvQUFDQUdJQWRCREdvZ0JCQVJPZ0FCSUFWQkFuSWhCQ0FIUVJ4cUVBOEVRQ0FFSVFVRklBQWdCR29nQjBFVWFpQUhRUnhxSWdRUUVUb0FBQ0FHSUFkQkRHb2dCQkFST2dBRElBVkJCR29oQlF3Q0N3c0xBbjhEUUVHNmZ5RUlJQVZCL1FGTERRTWdBQ0FGYWlJR0lBZEJGR29nQjBFY2FpSUpFQkU2QUFBZ0JrRUJhaUVFSUFrUUQwRURSZ1JBSUFkQkRHb2hDRUVDREFJTElBVkIvQUZMRFFNZ0JpQUhRUXhxSUFkQkhHb2lCQkFST2dBQklBVkJBbW9oQlNBRUVBOUJBMGNOQUFzZ0FDQUZhaUVFSUFkQkZHb2hDRUVEQ3lBRUlBZ2dCMEVjYWhBUk9nQUFJQVpxSUFCcklRZ01BUXNDZndOQVFicC9JUWdnQlVIOUFVc05BaUFBSUFWcUlnWWdCMEVVYWlBSFFSeHFJZ2tRRURvQUFDQUdRUUZxSVFRZ0NSQVBRUU5HQkVBZ0IwRU1haUVJUVFJTUFnc2dCVUg4QVVzTkFpQUdJQWRCREdvZ0IwRWNhaUlFRUJBNkFBRWdCVUVDYWlFRklBUVFEMEVEUncwQUN5QUFJQVZxSVFRZ0IwRVVhaUVJUVFNTElBUWdDQ0FIUVJ4cUVCQTZBQUFnQm1vZ0FHc2hDQXNnQ0VHSWYwc05BUXNnQ0NFRVFRQWhCU0FCUVFCQk5CQURJUWxCQUNFS0EwQWdCQ0FGUndSQUlBQWdCV29pQmkwQUFDSUJRUXRMQkVCQmJDRUlEQU1GSUFrZ0FVRUNkR29pQVNBQktBSUFRUUZxTmdJQUlBVkJBV29oQlVFQklBWXRBQUIwUVFGMUlBcHFJUW9NQWdzQUN3dEJiQ0VJSUFwRkRRQWdDbWNpQlVFZmN5SUJRUXRMRFFBZ0EwRWdJQVZyTmdJQVFRRkJBaUFCZENBS2F5SURaMEVmY3lJQmRDQURSdzBBSUFBZ0JHb2dBVUVCYWlJQU9nQUFJQWtnQUVFQ2RHb2lBQ0FBS0FJQVFRRnFOZ0lBSUFrb0FnUWlBRUVDU1NBQVFRRnhjZzBBSUFJZ0JFRUJhallDQUNBTFFRRnFJUWdMSUFkQk1Hb2tBQ0FJQzZBRkFReC9Jd0JCRUdzaURDUUFBbjhnQkVFSFRRUkFJQXhDQURjRENDQU1RUWhxSWdVZ0F5QUVFQUlhUVd3Z0FDQUJJQUlnQlVFSUVBd2lBQ0FBSUFSTEd5QUFJQUJCaVg5Skd3d0JDeUFBUVFBZ0FTZ0NBRUVCYWlJTlFRRjBFQU1oRDBGVUlBTW9BQUFpQmtFUGNTSUFRUXBMRFFBYUlBSWdBRUVGYWpZQ0FDQURJQVJxSWdKQkJHc2hCeUFDUVFkcklRc2dBRUVHYWlFT1FRUWhBaUFHUVFSMklRVkJJQ0FBZENJSVFRRnlJUWxCQUNFQVFRRWhCaUFESVFRRFFBSkFJQVpCQVhGRkJFQURRQ0FGUVg5elFZQ0FnSUI0Y21naUJrRVlTVVVFUUNBQVFTUnFJUUFnQkNBTFRRUi9JQVJCQTJvRklBUWdDMnRCQTNRZ0FtcEJIM0VoQWlBSEN5SUVLQUFBSUFKMklRVU1BUXNMSUFJZ0JrRWVjU0lLYWtFQ2FpRUNJQVpCQVhaQkEyd2dBR29nQlNBS2RrRURjV29pQUNBTlR3MEJBbjhnQkNBTFN5QUNRUU4ySUFScUlnVWdCMHR4UlFSQUlBSkJCM0VoQWlBRkRBRUxJQVFnQjJ0QkEzUWdBbXBCSDNFaEFpQUhDeUlFS0FBQUlBSjJJUVVMSUFVZ0NFRUJhM0VpQmlBSVFRRjBRUUZySWdvZ0NXc2lFRWtFZnlBT1FRRnJCU0FGSUFweElnVWdFRUVBSUFVZ0NFNGJheUVHSUE0TElRVWdEeUFBUVFGMGFpQUdRUUZySWdvN0FRQWdBRUVCYWlFQUlBSWdCV29oQWlBSVFRRWdCbXNnQ2lBR1FRQktHeUFKYWlJSlNnUkFJQWxCQWtnTkFVRWdJQWxuSWdWcklRNUJBU0FGUVI5emRDRUlDeUFBSUExUERRQWdDa0VBUnlFR0FuOGdCQ0FMU3lBQ1FRTjFJQVJxSWdVZ0IwdHhSUVJBSUFKQkIzRWhBaUFGREFFTElBSWdCQ0FIYTBFRGRHcEJIM0VoQWlBSEN5SUVLQUFBSUFKMklRVU1BUXNMUVd3Z0NVRUJSdzBBR2tGUUlBQWdEVXNOQUJwQmJDQUNRU0JLRFFBYUlBRWdBRUVCYXpZQ0FDQUVJQUpCQjJwQkEzVnFJQU5yQ3lBTVFSQnFKQUFMOGdFQkFYOGdBa1VFUUNBQVFnQTNBZ0FnQUVFQU5nSVFJQUJDQURjQ0NFRzRmdzhMSUFBZ0FUWUNEQ0FBSUFGQkJHbzJBaEFnQWtFRVR3UkFJQUFnQVNBQ2FpSUJRUVJySWdNMkFnZ2dBQ0FES0FBQU5nSUFJQUZCQVdzdEFBQWlBUVJBSUFBZ0FXZEJGMnMyQWdRZ0FnOExJQUJCQURZQ0JFRi9Ed3NnQUNBQk5nSUlJQUFnQVMwQUFDSUROZ0lBQWtBQ1FBSkFJQUpCQW1zT0FnRUFBZ3NnQUNBQkxRQUNRUkIwSUFOeUlnTTJBZ0FMSUFBZ0FTMEFBVUVJZENBRGFqWUNBQXNnQVNBQ2FrRUJheTBBQUNJQlJRUkFJQUJCQURZQ0JFRnNEd3NnQUNBQlp5QUNRUU4wYTBFSmFqWUNCQ0FDQzBRQkFuOGdBU0FDTHdFQUlnTWdBU2dDQkdvaUJEWUNCQ0FBSUFOQkFuUkJvQjFxS0FJQUlBRW9BZ0JCQUNBRWEzWnhOZ0lBSUFFUUR4b2dBQ0FDUVFScU5nSUVDNThCQVFSL1FRTWhBU0FBS0FJRUlnSkJJRTBFUUNBQUtBSUlJZ0VnQUNnQ0VFOEVRQ0FBSUFKQkIzRTJBZ1FnQUNBQklBSkJBM1pySWdJMkFnZ2dBQ0FDS0FBQU5nSUFRUUFQQ3lBQUtBSU1JZ01nQVVZRVFFRUJRUUlnQWtFZ1NSc1BDeUFBSUFFZ0FTQURheUFDUVFOMklnUWdBU0FFYXlBRFNTSUJHeUlEYXlJRU5nSUlJQUFnQWlBRFFRTjBhellDQkNBQUlBUW9BQUEyQWdBTElBRUxTQUVFZnlBQUtBSUVJQUFvQWdCQkFuUnFJZ0l0QUFJZ0FpOEJBQ0VFSUFFZ0FTZ0NCQ0lGSUFJdEFBTWlBbW8yQWdRZ0FDQUVJQUVvQWdBZ0JYUkJBQ0FDYTNacU5nSUFDMUlCQkg4Z0FDZ0NCQ0FBS0FJQVFRSjBhaUlDTFFBQ0lBSXZBUUFoQkNBQklBSXRBQU1pQWlBQktBSUVhaUlGTmdJRUlBQWdCQ0FDUVFKMFFhQWRhaWdDQUNBQktBSUFRUUFnQld0MmNXbzJBZ0FMQ0FBZ0FFR0lmMHNMR2dBZ0FBUkFJQUVFUUNBQ0lBQWdBUkVDQUE4TElBQVFCZ3NMcGdnQ0RYOEJmaU1BUVJCcklna2tBQ0FKUVFBMkFnd2dDVUVBTmdJSUFuOENRQ0FEUWVnSmFpQURJQWxCQ0dvZ0NVRU1haUFCSUFJZ0EwR0FBV29RQ3lJUFFZaC9TdzBBUVZRZ0NTZ0NEQ0lFSUFBb0FnQWlBVUgvQVhGQkFXcExEUUVhSUFCQkJHb2hDeUFBSUFGQi80R0FlSEVnQkVFUWRFR0FnUHdIY1hJMkFnQkJmeUFFSUFSQkFFZ2JRUUZxSVFCQkFDRUJJQWtvQWdnaEJVRUFJUUlEUUNBQUlBSkdCRUFnQlVFRGF5RUJRUUFoQUFOQUFrQkJBQ0VDSUFBZ0FVNEVRQU5BSUFBZ0JVNE5BaUFESUFBZ0EycEI2QWxxTFFBQVFRSjBha0ZBYXlJQklBRW9BZ0FpQVVFQmFqWUNBQ0FCSUFOcUlBQTZBT2dISUFCQkFXb2hBQXdBQ3dBRkEwQWdBa0VFUmtVRVFDQURJQU1nQUNBQ2FpSUhha0hvQ1dvdEFBQkJBblJxUVVCcklnZ2dDQ2dDQUNJSVFRRnFOZ0lBSUFNZ0NHb2dCem9BNkFjZ0FrRUJhaUVDREFFTEN5QUFRUVJxSVFBTUFnc0FDd3NnQkVFQmFpRU9JQU1vQWdBaEIwRUFJUUJCQVNFSUEwQWdDQ0FPUmcwRElBNGdDR3NoQkNBRElBaEJBblJxS0FJQUlRVUNRQUpBQWtBQ1FBSkFBa0JCQVNBSWRFRUJkU0lOUVFGckRnZ0FBUVFDQkFRRUF3UUxRUUFoQWlBRlFRQWdCVUVBU2hzaEJpQUFJUUVEUUNBQ0lBWkdEUVVnQXlBQ0lBZHFhaTBBNkFjaENpQUxJQUZCQVhScUlnd2dCRG9BQVNBTUlBbzZBQUFnQWtFQmFpRUNJQUZCQVdvaEFRd0FDd0FMUVFBaEFpQUZRUUFnQlVFQVNoc2hDaUFBSVFFRFFDQUNJQXBHRFFRZ0N5QUJRUUYwYWlJR0lBTWdBaUFIYW1vdEFPZ0hJZ3c2QUFJZ0JpQUVPZ0FCSUFZZ0REb0FBQ0FHSUFRNkFBTWdBa0VCYWlFQ0lBRkJBbW9oQVF3QUN3QUxRUUFoQWlBRlFRQWdCVUVBU2hzaEJpQUVRUWgwUVlEK0EzRWhCQ0FBSVFFRFFDQUNJQVpHRFFNZ0N5QUJRUUYwYWlBRUlBTWdBaUFIYW1vdEFPZ0hjcTFDZ1lDRWdKQ0F3QUIrTndBQUlBSkJBV29oQWlBQlFRUnFJUUVNQUFzQUMwRUFJUUlnQlVFQUlBVkJBRW9iSVFZZ0JFRUlkRUdBL2dOeElRUWdBQ0VCQTBBZ0FpQUdSZzBDSUFzZ0FVRUJkR29pQ2lBRUlBTWdBaUFIYW1vdEFPZ0hjcTFDZ1lDRWdKQ0F3QUIrSWhFM0FBZ2dDaUFSTndBQUlBSkJBV29oQWlBQlFRaHFJUUVNQUFzQUMwRUFJUUVnQlVFQUlBVkJBRW9iSVFvZ0JFRUlkRUdBL2dOeElRd2dBQ0VFQTBBZ0FTQUtSZzBCSUFzZ0JFRUJkR29oRUNBTUlBTWdBU0FIYW1vdEFPZ0hjcTFDZ1lDRWdKQ0F3QUIrSVJGQkFDRUNBMEFnQWlBTlRrVUVRQ0FRSUFKQkFYUnFJZ1lnRVRjQUdDQUdJQkUzQUJBZ0JpQVJOd0FJSUFZZ0VUY0FBQ0FDUVJCcUlRSU1BUXNMSUFGQkFXb2hBU0FFSUExcUlRUU1BQXNBQ3lBSVFRRnFJUWdnQlNBSGFpRUhJQVVnRFd3Z0FHb2hBQXdBQ3dBRklBTWdBa0VDZEdvaUIwRkFheUFCTmdJQUlBSkJBV29oQWlBSEtBSUFJQUZxSVFFTUFRc0FDd0FMSUE4TElBbEJFR29rQUF2eUFnRUdmeU1BUVNCcklnVWtBQ0FFS0FJQUlRWWdCVUVNYWlBQ0lBTVFEU0lEUVloL1RRUkFJQVJCQkdvaEFpQUFJQUZxSWdsQkEyc2hCRUVBSUFaQkVIWnJRUjl4SVFNRFFDQUZRUXhxRUE4Z0FDQUVUM0pGQkVBZ0FpQUZLQUlNSWdZZ0JTZ0NFQ0lIZENBRGRrRUJkR29pQ0MwQUFTRUtJQUFnQ0MwQUFEb0FBQ0FDSUFZZ0J5QUthaUlHZENBRGRrRUJkR29pQnkwQUFDRUlJQVVnQmlBSExRQUJhallDRUNBQUlBZzZBQUVnQUVFQ2FpRUFEQUVMQ3dOQUlBVkJER29RRHlFSElBVW9BZ3doQmlBRktBSVFJUVFnQUNBSlR5QUhja1VFUUNBQ0lBWWdCSFFnQTNaQkFYUnFJZ1l0QUFBaEJ5QUZJQVFnQmkwQUFXbzJBaEFnQUNBSE9nQUFJQUJCQVdvaEFBd0JDd3NEUUNBQUlBbFBSUVJBSUFJZ0JpQUVkQ0FEZGtFQmRHb2lCeTBBQVNFSUlBQWdCeTBBQURvQUFDQUFRUUZxSVFBZ0JDQUlhaUVFREFFTEMwRnNRV3dnQVNBRktBSVVJQVVvQWhoSEd5QUVRU0JIR3lFREN5QUZRU0JxSkFBZ0F3dlBGQUVqZnlNQVFkQUFheUlGSkFCQmJDRUpBa0FnQTBFS1NRMEFBa0FnQXlBQ0x3QUVJZ2NnQWk4QUFDSUlJQUl2QUFJaURXcHFRUVpxSWd4SkRRQWdCQzhCQWlFR0lBVkJQR29nQWtFR2FpSUNJQWdRRFNJSlFZaC9TdzBCSUFWQktHb2dBaUFJYWlJQ0lBMFFEU0lKUVloL1N3MEJJQVZCRkdvZ0FpQU5haUlDSUFjUURTSUpRWWgvU3cwQklBVWdBaUFIYWlBRElBeHJFQTBpQ1VHSWYwc05BU0FFUVFScUlRb2dBQ0FCYWlJZlFRTnJJU0JCQUNBR2EwRWZjU0VMSUFVb0FnZ2hFU0FGS0FJY0lSSWdCU2dDTUNFVElBVW9Ba1FoRkNBRktBSUVJUWtnQlNnQ0dDRU5JQVVvQWl3aERDQUZLQUpBSVFZZ0JTZ0NFQ0VoSUFVb0FpUWhJaUFGS0FJNElTTWdCU2dDVENFa0lBVW9BZ0FoRlNBRktBSVVJUllnQlNnQ0tDRVhJQVVvQWp3aEdFRUJJUThnQUNBQlFRTnFRUUoySWdScUlnTWdCR29pQWlBRWFpSVpJUVFnQWlFSUlBTWhCd05BSUE5QkFYRkZJQVFnSUU5eVJRUkFJQUFnQ2lBWUlBWjBJQXQyUVFKMGFpSU9Md0VBT3dBQUlBNHRBQUloR2lBT0xRQURJUkFnQnlBS0lCY2dESFFnQzNaQkFuUnFJZzR2QVFBN0FBQWdEaTBBQWlFYklBNHRBQU1oRHlBSUlBb2dGaUFOZENBTGRrRUNkR29pRGk4QkFEc0FBQ0FPTFFBQ0lSd2dEaTBBQXlFZElBUWdDaUFWSUFsMElBdDJRUUowYWlJT0x3RUFPd0FBSUE0dEFBSWhIaUFPTFFBRElRNGdBQ0FRYWlJbElBb2dHQ0FHSUJwcUlnWjBJQXQyUVFKMGFpSVFMd0VBT3dBQUlCQXRBQUlnRUMwQUF5RW1JQWNnRDJvaUp5QUtJQmNnRENBYmFpSWFkQ0FMZGtFQ2RHb2lCeThCQURzQUFDQUhMUUFDSVF3Z0J5MEFBeUVRSUFnZ0hXb2lHeUFLSUJZZ0RTQWNhaUlQZENBTGRrRUNkR29pQ0M4QkFEc0FBQ0FJTFFBQ0lRMGdDQzBBQXlFY0lBUWdEbW9pSFNBS0lCVWdDU0FlYWlJT2RDQUxka0VDZEdvaUNTOEJBRHNBQUNBR2FpRUFRUU1oQndKL0lCUWdKRWtFUUNBQUlRWkJBd3dCQ3lBQVFRZHhJUVlnRkNBQVFRTjJheUlVS0FBQUlSaEJBQXNnQ1MwQUF5RWVJQWt0QUFJaENDQU1JQnBxSVFBZ0V5QWpTUVIvSUFBRklCTWdBRUVEZG1zaUV5Z0FBQ0VYUVFBaEJ5QUFRUWR4Q3lFTUlBMGdEMm9oQUNBSGNpRUpRUU1oRHdKL0lCSWdJa2tFUUNBQUlRMUJBd3dCQ3lBQVFRZHhJUTBnRWlBQVFRTjJheUlTS0FBQUlSWkJBQXNnQ0NBT2FpRUFJQWx5SUJFZ0lVa0VmeUFBQlNBUklBQkJBM1pySWhFb0FBQWhGVUVBSVE4Z0FFRUhjUXNoQ1NBbElDWnFJUUFnRUNBbmFpRUhJQnNnSEdvaENDQWRJQjVxSVFRZ0QzSkZJUThNQVFzTElBVWdERFlDTENBRklBWTJBa0FnQlNBTk5nSVlJQVVnQ1RZQ0JDQUZJQlEyQWtRZ0JTQVROZ0l3SUFVZ0VqWUNIQ0FGSUJFMkFnZ2dCU0FZTmdJOElBVWdGellDS0NBRklCWTJBaFFnQlNBVk5nSUFJQUlnQjBrZ0FDQURTM0lOQUVGc0lRa2dDQ0FaU3cwQklBTkJBMnNoQ1FOQUlBVkJQR29RRDBVZ0FDQUpTWEVFUUNBQUlBb2dCU2dDUENJTklBVW9Ba0FpREhRZ0MzWkJBblJxSWc0dkFRQTdBQUFnQUNBT0xRQURhaUlHSUFvZ0RTQU1JQTR0QUFKcUlnQjBJQXQyUVFKMGFpSU1Md0VBT3dBQUlBVWdBQ0FNTFFBQ2FqWUNRQ0FHSUF3dEFBTnFJUUFNQVFVZ0EwRUNheUVNQTBBZ0JVRThhaEFQSVFZZ0JTZ0NQQ0VOSUFVb0FrQWhDU0FBSUF4TElBWnlSUVJBSUFBZ0NpQU5JQWwwSUF0MlFRSjBhaUlHTHdFQU93QUFJQVVnQ1NBR0xRQUNhallDUUNBQUlBWXRBQU5xSVFBTUFRc0xBMEFnQUNBTVMwVUVRQ0FBSUFvZ0RTQUpkQ0FMZGtFQ2RHb2lCaThCQURzQUFDQUFJQVl0QUFOcUlRQWdDU0FHTFFBQ2FpRUpEQUVMQ3dKQUlBQWdBMDhOQUNBQUlBb2dEU0FKZENBTGRpSUFRUUowYWlJRExRQUFPZ0FBSUFNdEFBTkJBVVlFUUNBSklBTXRBQUpxSVFrTUFRc2dDVUVmU3cwQVFTQWdDU0FLSUFCQkFuUnFMUUFDYWlJQUlBQkJJRThiSVFrTElBSkJBMnNoREFOQUlBVkJLR29RRDBVZ0J5QU1TWEVFUUNBSElBb2dCU2dDS0NJR0lBVW9BaXdpQUhRZ0MzWkJBblJxSWcwdkFRQTdBQUFnQnlBTkxRQURhaUlESUFvZ0JpQUFJQTB0QUFKcUlnQjBJQXQyUVFKMGFpSUdMd0VBT3dBQUlBVWdBQ0FHTFFBQ2FqWUNMQ0FESUFZdEFBTnFJUWNNQVFVZ0FrRUNheUVHQTBBZ0JVRW9haEFQSVFNZ0JTZ0NLQ0VNSUFVb0Fpd2hBQ0FHSUFkSklBTnlSUVJBSUFjZ0NpQU1JQUIwSUF0MlFRSjBhaUlETHdFQU93QUFJQVVnQUNBRExRQUNhallDTENBSElBTXRBQU5xSVFjTUFRc0xBMEFnQmlBSFNVVUVRQ0FISUFvZ0RDQUFkQ0FMZGtFQ2RHb2lBeThCQURzQUFDQUhJQU10QUFOcUlRY2dBQ0FETFFBQ2FpRUFEQUVMQ3dKQUlBSWdCMDBOQUNBSElBb2dEQ0FBZENBTGRpSUNRUUowYWlJRExRQUFPZ0FBSUFNdEFBTkJBVVlFUUNBQUlBTXRBQUpxSVFBTUFRc2dBRUVmU3cwQVFTQWdBQ0FLSUFKQkFuUnFMUUFDYWlJQUlBQkJJRThiSVFBTElCbEJBMnNoREFOQUlBVkJGR29RRDBVZ0NDQU1TWEVFUUNBSUlBb2dCU2dDRkNJR0lBVW9BaGdpQW5RZ0MzWkJBblJxSWcwdkFRQTdBQUFnQ0NBTkxRQURhaUlESUFvZ0JpQUNJQTB0QUFKcUlnSjBJQXQyUVFKMGFpSUdMd0VBT3dBQUlBVWdBaUFHTFFBQ2FqWUNHQ0FESUFZdEFBTnFJUWdNQVFVZ0dVRUNheUVEQTBBZ0JVRVVhaEFQSVFJZ0JTZ0NGQ0VHSUFVb0FoZ2hCeUFESUFoSklBSnlSUVJBSUFnZ0NpQUdJQWQwSUF0MlFRSjBhaUlDTHdFQU93QUFJQVVnQnlBQ0xRQUNhallDR0NBSUlBSXRBQU5xSVFnTUFRc0xBMEFnQXlBSVNVVUVRQ0FJSUFvZ0JpQUhkQ0FMZGtFQ2RHb2lBaThCQURzQUFDQUlJQUl0QUFOcUlRZ2dCeUFDTFFBQ2FpRUhEQUVMQ3dKQUlBZ2dHVThOQUNBSUlBb2dCaUFIZENBTGRpSUNRUUowYWlJRExRQUFPZ0FBSUFNdEFBTkJBVVlFUUNBSElBTXRBQUpxSVFjTUFRc2dCMEVmU3cwQVFTQWdCeUFLSUFKQkFuUnFMUUFDYWlJQ0lBSkJJRThiSVFjTEEwQWdCUkFQUlNBRUlDQkpjUVJBSUFRZ0NpQUZLQUlBSWdZZ0JTZ0NCQ0lDZENBTGRrRUNkR29pREM4QkFEc0FBQ0FFSUF3dEFBTnFJZ01nQ2lBR0lBSWdEQzBBQW1vaUFuUWdDM1pCQW5ScUlnUXZBUUE3QUFBZ0JTQUNJQVF0QUFKcU5nSUVJQU1nQkMwQUEyb2hCQXdCQlNBZlFRSnJJUU1EUUNBRkVBOGhBaUFGS0FJQUlRWWdCU2dDQkNFSUlBTWdCRWtnQW5KRkJFQWdCQ0FLSUFZZ0NIUWdDM1pCQW5ScUlnSXZBUUE3QUFBZ0JTQUlJQUl0QUFKcU5nSUVJQVFnQWkwQUEyb2hCQXdCQ3dzRFFDQURJQVJKUlFSQUlBUWdDaUFHSUFoMElBdDJRUUowYWlJQ0x3RUFPd0FBSUFRZ0FpMEFBMm9oQkNBSUlBSXRBQUpxSVFnTUFRc0xBa0FnQkNBZlR3MEFJQVFnQ2lBR0lBaDBJQXQySWdKQkFuUnFJZ010QUFBNkFBQWdBeTBBQTBFQlJnUkFJQWdnQXkwQUFtb2hDQXdCQ3lBSVFSOUxEUUJCSUNBSUlBb2dBa0VDZEdvdEFBSnFJZ0lnQWtFZ1R4c2hDQXRCYkVGc1FXeEJiRUZzUVd4QmJFRnNJQUVnQ0VFZ1J4c2dCU2dDQ0NBRktBSU1SeHNnQjBFZ1J4c2dCU2dDSENBRktBSWdSeHNnQUVFZ1J4c2dCU2dDTUNBRktBSTBSeHNnQ1VFZ1J4c2dCU2dDUkNBRktBSklSeHNoQ1F3SkN3QUxBQXNBQ3dBTEFBc0FDd0FMQUF0QmJDRUpDeUFGUWRBQWFpUUFJQWtMN0JBQkhuOGpBRUhRQUdzaUJTUUFRV3doQ1FKQUlBTkJDa2tOQUFKQUlBTWdBaThBQkNJR0lBSXZBQUFpQnlBQ0x3QUNJZ2hxYWtFR2FpSU9TUTBBSUFRdkFRSWhEeUFGUVR4cUlBSkJCbW9pQWlBSEVBMGlDVUdJZjBzTkFTQUZRU2hxSUFJZ0Iyb2lBaUFJRUEwaUNVR0lmMHNOQVNBRlFSUnFJQUlnQ0dvaUFpQUdFQTBpQ1VHSWYwc05BU0FGSUFJZ0Jtb2dBeUFPYXhBTklnbEJpSDlMRFFFZ0JFRUVhaUVLSUFBZ0FXb2lIRUVEYXlFZFFRQWdEMnRCSDNFaEN5QUZLQUlJSVJFZ0JTZ0NIQ0VTSUFVb0FqQWhFeUFGS0FKRUlSUWdCU2dDQkNFSklBVW9BaGdoQmlBRktBSXNJUWNnQlNnQ1FDRUlJQVVvQWhBaEhpQUZLQUlrSVI4Z0JTZ0NPQ0VnSUFVb0Frd2hJU0FGS0FJQUlSVWdCU2dDRkNFV0lBVW9BaWdoRnlBRktBSThJUmhCQVNFTklBQWdBVUVEYWtFQ2RpSUNhaUlPSUFKcUlnOGdBbW9pR1NFRUlBOGhBaUFPSVFNRFFDQU5SU0FFSUIxUGNrVUVRQ0FLSUJnZ0NIUWdDM1pCQVhScUlnd3RBQUVoRFNBQUlBd3RBQUE2QUFBZ0NpQVhJQWQwSUF0MlFRRjBhaUlNTFFBQklSQWdBeUFNTFFBQU9nQUFJQW9nRmlBR2RDQUxka0VCZEdvaURDMEFBU0VhSUFJZ0RDMEFBRG9BQUNBS0lCVWdDWFFnQzNaQkFYUnFJZ3d0QUFFaEd5QUVJQXd0QUFBNkFBQWdDaUFZSUFnZ0RXb2lDSFFnQzNaQkFYUnFJZ3d0QUFFaERTQUFJQXd0QUFBNkFBRWdDaUFYSUFjZ0VHb2lCM1FnQzNaQkFYUnFJZ3d0QUFFaEVDQURJQXd0QUFBNkFBRWdDaUFXSUFZZ0dtb2lESFFnQzNaQkFYUnFJZ1l0QUFFaEdpQUNJQVl0QUFBNkFBRWdDaUFWSUFrZ0cyb2lHM1FnQzNaQkFYUnFJZ2t0QUFFaElpQUVJQWt0QUFBNkFBRWdDQ0FOYWlFR1FRTWhDUUovSUJRZ0lVa0VRRUVESVEwZ0Jnd0JDeUFVSUFaQkEzWnJJaFFvQUFBaEdFRUFJUTBnQmtFSGNRc2hDQ0FISUJCcUlRWWdFeUFnU1FSL0lBWUZJQk1nQmtFRGRtc2lFeWdBQUNFWFFRQWhDU0FHUVFkeEN5RUhJQXdnR21vaERDQUpJQTF5SVJCQkF5RU5BbjhnRWlBZlNRUkFJQXdoQmtFRERBRUxJQXhCQjNFaEJpQVNJQXhCQTNackloSW9BQUFoRmtFQUN5QWJJQ0pxSVF3Z0VISWhFQ0FSSUI1SkJIOGdEQVVnRVNBTVFRTjJheUlSS0FBQUlSVkJBQ0VOSUF4QkIzRUxJUWtnQkVFQ2FpRUVJQUpCQW1vaEFpQURRUUpxSVFNZ0FFRUNhaUVBSUEwZ0VISkZJUTBNQVFzTElBVWdCellDTENBRklBZzJBa0FnQlNBR05nSVlJQVVnQ1RZQ0JDQUZJQlEyQWtRZ0JTQVROZ0l3SUFVZ0VqWUNIQ0FGSUJFMkFnZ2dCU0FZTmdJOElBVWdGellDS0NBRklCWTJBaFFnQlNBVk5nSUFJQUFnRGtzZ0F5QVBTM0lOQUVGc0lRa2dBaUFaU3cwQklBNUJBMnNoQ1FOQUlBVkJQR29RRHlBQUlBbFBja1VFUUNBS0lBVW9BandpQmlBRktBSkFJZ2QwSUF0MlFRRjBhaUlJTFFBQklRd2dBQ0FJTFFBQU9nQUFJQW9nQmlBSElBeHFJZ1owSUF0MlFRRjBhaUlITFFBQUlRZ2dCU0FHSUFjdEFBRnFOZ0pBSUFBZ0NEb0FBU0FBUVFKcUlRQU1BUXNMQTBBZ0JVRThhaEFQSVFjZ0JTZ0NQQ0VHSUFVb0FrQWhDU0FBSUE1UElBZHlSUVJBSUFvZ0JpQUpkQ0FMZGtFQmRHb2lCaTBBQUNFSElBVWdDU0FHTFFBQmFqWUNRQ0FBSUFjNkFBQWdBRUVCYWlFQURBRUxDd05BSUFBZ0RrOUZCRUFnQ2lBR0lBbDBJQXQyUVFGMGFpSUhMUUFCSUFBZ0J5MEFBRG9BQUNBQVFRRnFJUUFnQ1dvaENRd0JDd3NnRDBFRGF5RUFBMEFnQlVFb2FoQVBJQUFnQTAxeVJRUkFJQW9nQlNnQ0tDSUdJQVVvQWl3aUIzUWdDM1pCQVhScUlnZ3RBQUVoRGlBRElBZ3RBQUE2QUFBZ0NpQUdJQWNnRG1vaUJuUWdDM1pCQVhScUlnY3RBQUFoQ0NBRklBWWdCeTBBQVdvMkFpd2dBeUFJT2dBQklBTkJBbW9oQXd3QkN3c0RRQ0FGUVNocUVBOGhCeUFGS0FJb0lRWWdCU2dDTENFQUlBTWdEMDhnQjNKRkJFQWdDaUFHSUFCMElBdDJRUUYwYWlJR0xRQUFJUWNnQlNBQUlBWXRBQUZxTmdJc0lBTWdCem9BQUNBRFFRRnFJUU1NQVFzTEEwQWdBeUFQVDBVRVFDQUtJQVlnQUhRZ0MzWkJBWFJxSWdjdEFBRWhDQ0FESUFjdEFBQTZBQUFnQTBFQmFpRURJQUFnQ0dvaEFBd0JDd3NnR1VFRGF5RURBMEFnQlVFVWFoQVBJQUlnQTA5eVJRUkFJQW9nQlNnQ0ZDSUdJQVVvQWhnaUIzUWdDM1pCQVhScUlnZ3RBQUVoRGlBQ0lBZ3RBQUE2QUFBZ0NpQUdJQWNnRG1vaUJuUWdDM1pCQVhScUlnY3RBQUFoQ0NBRklBWWdCeTBBQVdvMkFoZ2dBaUFJT2dBQklBSkJBbW9oQWd3QkN3c0RRQ0FGUVJScUVBOGhCeUFGS0FJVUlRWWdCU2dDR0NFRElBSWdHVThnQjNKRkJFQWdDaUFHSUFOMElBdDJRUUYwYWlJR0xRQUFJUWNnQlNBRElBWXRBQUZxTmdJWUlBSWdCem9BQUNBQ1FRRnFJUUlNQVFzTEEwQWdBaUFaVDBVRVFDQUtJQVlnQTNRZ0MzWkJBWFJxSWdjdEFBRWhDQ0FDSUFjdEFBQTZBQUFnQWtFQmFpRUNJQU1nQ0dvaEF3d0JDd3NEUUNBRkVBOGdCQ0FkVDNKRkJFQWdDaUFGS0FJQUlnSWdCU2dDQkNJR2RDQUxka0VCZEdvaUJ5MEFBU0VJSUFRZ0J5MEFBRG9BQUNBS0lBSWdCaUFJYWlJQ2RDQUxka0VCZEdvaUJpMEFBQ0VISUFVZ0FpQUdMUUFCYWpZQ0JDQUVJQWM2QUFFZ0JFRUNhaUVFREFFTEN3TkFJQVVRRHlFSElBVW9BZ0FoQmlBRktBSUVJUUlnQkNBY1R5QUhja1VFUUNBS0lBWWdBblFnQzNaQkFYUnFJZ1l0QUFBaEJ5QUZJQUlnQmkwQUFXbzJBZ1FnQkNBSE9nQUFJQVJCQVdvaEJBd0JDd3NEUUNBRUlCeFBSUVJBSUFvZ0JpQUNkQ0FMZGtFQmRHb2lCeTBBQVNFSUlBUWdCeTBBQURvQUFDQUVRUUZxSVFRZ0FpQUlhaUVDREFFTEMwRnNRV3hCYkVGc1FXeEJiRUZzUVd3Z0FTQUNRU0JIR3lBRktBSUlJQVVvQWd4SEd5QURRU0JIR3lBRktBSWNJQVVvQWlCSEd5QUFRU0JIR3lBRktBSXdJQVVvQWpSSEd5QUpRU0JIR3lBRktBSkVJQVVvQWtoSEd5RUpEQUVMUVd3aENRc2dCVUhRQUdva0FDQUpDMWdCQTM4Q1FDQUFLQUtRNndFaUFVVU5BQ0FCS0FJQUlBRkJ0TlVCYWlnQ0FDSUNJQUZCdU5VQmFpZ0NBQ0lERUJNZ0FnUkFJQU1nQVNBQ0VRSUFEQUVMSUFFUUJnc2dBRUVBTmdLZzZ3RWdBRUlBTndPUTZ3RUw2UU1DQkg4Q2ZpQUFRUUJCS0JBRElRUWdBa0VCUVFVZ0F4c2lBRWtFUUNBQUR3c2dBVVVFUUVGL0R3dEJBU0VHQWtBQ1FDQURRUUZHRFFBZ0F5RUdJQUVvQUFBaUJVR282cjVwUmcwQVFYWWhBeUFGUVhCeFFkRFV0TUlCUncwQlFRZ2hBeUFDUVFoSkRRRWdBVFVBQkNFSUlBUkJBVFlDRkNBRUlBZzNBd0JCQUE4TElBRWdBaUFHRUJvaUF5QUNTdzBBSUFRZ0F6WUNHRUZ5SVFNZ0FDQUJhaUlGUVFGckxRQUFJZ0pCQ0hFTkFDQUNRU0J4SWdaRkJFQkJjQ0VESUFVdEFBQWlCVUduQVVzTkFTQUZRUWR4clVJQklBVkJBM1pCQ21xdGhpSUlRZ09JZmlBSWZDRUpJQUJCQVdvaEFBc2dBa0VHZGlFRklBSkJBblpCQUNFREFrQUNRQUpBQWtBZ0FrRURjVUVCYXc0REFBRUNBd3NnQUNBQmFpMEFBQ0VESUFCQkFXb2hBQXdDQ3lBQUlBRnFMd0FBSVFNZ0FFRUNhaUVBREFFTElBQWdBV29vQUFBaEF5QUFRUVJxSVFBTFFRRnhJUUlDZmdKQUFrQUNRQUpBSUFWQkFXc09Bd0VDQXdBTFFuOGdCa1VOQXhvZ0FDQUJhakVBQUF3REN5QUFJQUZxTXdBQVFvQUNmQXdDQ3lBQUlBRnFOUUFBREFFTElBQWdBV29wQUFBTElRZ2dCQ0FDTmdJZ0lBUWdBellDSENBRUlBZzNBd0JCQUNFRElBUkJBRFlDRkNBRUlBZ2dDU0FHR3lJSU53TUlJQVJDZ0lBSUlBZ2dDRUtBZ0FoYUd6NENFQXNnQXd0ZkFRRi9RYmgvSVFNZ0FVRUJRUVVnQWhzaUFrOEVmeUFBSUFKcVFRRnJMUUFBSWdCQkEzRkJBblJCb0I1cUtBSUFJQUpxSUFCQkJIWkJESEZCc0I1cUtBSUFhaUFBUVNCeElnRkZhaUFCUVFWMklBQkJ3QUJKY1dvRlFiaC9Dd3NNQUNBQUlBRWdBa0VBRUJrTGx3TUNCWDhDZmlNQVFVQnFJZ1FrQUFKQUEwQWdBVUVGVHdSQUFrQWdBQ2dBQUVGd2NVSFExTFRDQVVZRVFFSitJUWNnQVVFSVNRMEVJQUFvQUFRaUFrRjNTdzBFSUFKQkNHb2lBeUFCU3cwRUlBSkJnWDlKRFFFTUJBc2dCRUVZYWlBQUlBRVFHeUVDUW40Z0JDa0RHRUlBSUFRb0FpeEJBVWNiSUFJYklnZENmVllOQXlBSElBaDhJZ2dnQjFSQ2ZpRUhEUU1DUUFKQUlBRkJDRWtOQUNBQUtBQUFRWEJ4UWREVXRNSUJSdzBBSUFBb0FBUWlBa0YzU3cwRlFiaC9JQUpCQ0dvaUFpQUJJQUpKR3lFRERBRUxJQVJCR0dvZ0FDQUJFQnNpQWtHSWYwc0VRQ0FDSVFNTUFRdEJ1SDhoQXlBQ0RRQWdBU0FFS0FJd0lnSnJJUVVnQUNBQ2FpRUdBMEFnQmlBRklBUkJER29RSFNJRFFZaC9TdzBCSUFOQkEyb2lBaUFGU3dSQVFiaC9JUU1NQWdzZ0JTQUNheUVGSUFJZ0Jtb2hCaUFFS0FJUVJRMEFDeUFFS0FJNEJIOUJ1SDhoQXlBRlFRUkpEUUVnQmtFRWFnVWdCZ3NnQUdzaEF3c2dBMEdJZjBzTkF3c2dBU0FEYXlFQklBQWdBMm9oQUF3QkN3dENmaUFJSUFFYklRY0xJQVJCUUdza0FDQUhDMlFCQVg5QnVIOGhBd0pBSUFGQkEwa05BQ0FBTFFBQ0lRRWdBaUFBTHdBQUlnQkJBWEUyQWdRZ0FpQUFRUUYyUVFOeElnTTJBZ0FnQWlBQUlBRkJFSFJ5UVFOMklnQTJBZ2dDUUFKQUlBTkJBV3NPQXdJQkFBRUxRV3dQQ3lBQUlRTUxJQU1MUkFFQ2Z5QUJJQUlvQWdRaUF5QUJLQUlFYWlJRU5nSUVJQUFnQTBFQ2RFR2dIV29vQWdBZ0FTZ0NBRUVBSUFScmRuRTJBZ0FnQVJBUEdpQUFJQUpCQ0dvMkFnUUx6Z0VCQm45QnVuOGhDZ0pBSUFJb0FnUWlDQ0FDS0FJQUlnbHFJZzBnQVNBQWEwc05BRUZzSVFvZ0NTQUVJQU1vQWdBaUMydExEUUFnQUNBSmFpSUVJQUlvQWdnaURHc2hBaUFBSUFGQklHc2lBQ0FMSUFsQkFCQWdJQU1nQ1NBTGFqWUNBQUpBQWtBZ0JDQUZheUFNVHdSQUlBSWhCUXdCQ3lBTUlBUWdCbXRMRFFJZ0J5QUhJQUlnQldzaUFtb2lBU0FJYWs4RVFDQUVJQUVnQ0JBS0dnd0NDeUFDSUFocUlRZ2dCQ0FCUVFBZ0Ftc1FDaUFDYXlFRUN5QUVJQUFnQlNBSVFRRVFJQXNnRFNFS0N5QUtDOGNFQVFKL0lBQWdBMm9oQmdKQUlBTkJCMHdFUUFOQUlBQWdCazhOQWlBQUlBSXRBQUE2QUFBZ0FFRUJhaUVBSUFKQkFXb2hBZ3dBQ3dBTElBUkJBVVlFUUFKQUlBQWdBbXNpQlVFSFRRUkFJQUFnQWkwQUFEb0FBQ0FBSUFJdEFBRTZBQUVnQUNBQ0xRQUNPZ0FDSUFBZ0FpMEFBem9BQXlBQUlBSWdCVUVDZENJRlFjQWVhaWdDQUdvaUFpZ0FBRFlBQkNBQ0lBVkI0QjVxS0FJQWF5RUNEQUVMSUFBZ0Fpa0FBRGNBQUFzZ0FrRUlhaUVDSUFCQkNHb2hBQXNnQVNBR1R3UkFJQUFnQTJvaEFTQUVRUUZISUFBZ0FtdEJEMHB5UlFSQUEwQWdBQ0FDS1FBQU53QUFJQUpCQ0dvaEFpQUFRUWhxSWdBZ0FVa05BQXdEQ3dBTElBQWdBaWtBQURjQUFDQUFJQUlwQUFnM0FBZ2dBMEVSU1EwQklBQkJFR29oQUFOQUlBQWdBaWtBRURjQUFDQUFJQUlwQUJnM0FBZ2dBQ0FDS1FBZ053QVFJQUFnQWlrQUtEY0FHQ0FDUVNCcUlRSWdBRUVnYWlJQUlBRkpEUUFMREFFTEFrQWdBQ0FCU3dSQUlBQWhBUXdCQ3lBQklBQnJJUVVDUUNBRVFRRkhJQUFnQW10QkQwcHlSUVJBSUFJaEF3TkFJQUFnQXlrQUFEY0FBQ0FEUVFocUlRTWdBRUVJYWlJQUlBRkpEUUFMREFFTElBQWdBaWtBQURjQUFDQUFJQUlwQUFnM0FBZ2dCVUVSU0EwQUlBQkJFR29oQUNBQ0lRTURRQ0FBSUFNcEFCQTNBQUFnQUNBREtRQVlOd0FJSUFBZ0F5a0FJRGNBRUNBQUlBTXBBQ2czQUJnZ0EwRWdhaUVESUFCQklHb2lBQ0FCU1EwQUN3c2dBaUFGYWlFQ0N3TkFJQUVnQms4TkFTQUJJQUl0QUFBNkFBQWdBVUVCYWlFQklBSkJBV29oQWd3QUN3QUxDNjRIQWdWL0FYNGpBRUdBQVdzaUVTUUFJQkVnQXpZQ2ZFRi9JUThDUUFKQUFrQUNRQUpBSUFJT0JBRUFBd0lFQ3lBR1JRUkFRYmgvSVE4TUJBdEJiQ0VQSUFVdEFBQWlBaUFEU3cwRElBZ2dBa0VDZENJQ2FpZ0NBQ0VESUFJZ0Iyb29BZ0FoQWlBQVFRQTZBQXNnQUVJQU53SUFJQUFnQWpZQ0RDQUFJQU02QUFvZ0FFRUFPd0VJSUFFZ0FEWUNBRUVCSVE4TUF3c2dBU0FKTmdJQVFRQWhEd3dDQ3lBS1JRUkFRV3doRHd3Q0MwRUFJUThnQzBVZ0RFRVpTSElOQVVFSUlBUjBRUWhxSVFCQkFDRURBMEFnQUNBRFRRMENJQU5CUUdzaEF3d0FDd0FMUVd3aER5QVJJQkZCL0FCcUlCRkIrQUJxSUFVZ0JoQU1JZ05CaUg5TERRQWdFU2dDZUNJQ0lBUkxEUUFnRVNnQ2ZFRUJhaUVKSUFCQkNHb2hDMEdBZ0FJZ0FuUkJFSFVoQlVFQklSQkJBU0FDZENJUFFRRnJJZ29oRWdOQUlBa2dEa2NFUUFKQUlCRWdEa0VCZENJRWFpOEJBQ0lNUWYvL0EwWUVRQ0FMSUJKQkEzUnFJQTQyQWdRZ0VrRUJheUVTUVFFaERBd0JDeUFRUVFBZ0JTQU13VW9iSVJBTElBUWdEV29nRERzQkFDQU9RUUZxSVE0TUFRc0xJQUFnQWpZQ0JDQUFJQkEyQWdBQ1FDQUtJQkpHQkVBZ0RVSHFBR29oQmtFQUlSQkJBQ0VNQTBBZ0NTQVFSZ1JBSUE5QkEzWWdEMEVCZG1wQkEyb2lCVUVCZENFRVFRQWhERUVBSVJJRFFFRUFJUTRnRHlBU1RRMEVBMEFnRGtFQ1J3UkFJQXNnQlNBT2JDQU1haUFLY1VFRGRHb2dCaUFPSUJKcWFpMEFBRFlDQkNBT1FRRnFJUTRNQVFzTElCSkJBbW9oRWlBRUlBeHFJQXB4SVF3TUFBc0FCU0FSSUJCQkFYUnFMZ0VBSVFVZ0JpQU1haUlFSUJNM0FBQkJDQ0VPQTBBZ0JTQU9TZ1JBSUFRZ0Rtb2dFemNBQUNBT1FRaHFJUTRNQVFzTElCTkNnWUtFaUpDZ3dJQUJmQ0VUSUJCQkFXb2hFQ0FGSUF4cUlRd01BUXNBQ3dBTElBOUJBM1lnRDBFQmRtcEJBMm9oQlVFQUlSQkJBQ0VPQTBBZ0NTQVFSZzBCUVFBaERDQVJJQkJCQVhScUxnRUFJZ1JCQUNBRVFRQktHeUVFQTBBZ0JDQU1Sd1JBSUFzZ0RrRURkR29nRURZQ0JBTkFJQVVnRG1vZ0NuRWlEaUFTU3cwQUN5QU1RUUZxSVF3TUFRc0xJQkJCQVdvaEVBd0FDd0FMSUFKQkFXb2hCVUVBSVF3RFFDQU1JQTlIQkVBZ0RTQUxJQXhCQTNScUlna29BZ1FpQkVFQmRHb2lBaUFDTHdFQUlnWkJBV283QVFBZ0NTQUZJQVpuUVdCemFpSUNPZ0FESUFrZ0JpQUNkQ0FQYXpzQkFDQUpJQWdnQkVFQ2RDSUNhaWdDQURvQUFpQUpJQUlnQjJvb0FnQTJBZ1FnREVFQmFpRU1EQUVMQ3lBQklBQTJBZ0FnQXlFUEN5QVJRWUFCYWlRQUlBOEw3Vm9DTzM4R2ZpTUFRZUFCYXlJRUpBQUNRRUd3N0FrUUJTSUZSUVJBUVVBaEJ3d0JDeUFGUWdBM0F2VHFBU0FGUVFBMkFzVHJBU0FGUVFBMkFyVHJBU0FGUWdBM0FwenJBU0FGUVFBMkFyanBBU0FGUVFBMkFxenNDU0FGUWdBM0F0VHJBU0FGUWdBM0FxenJBU0FGUWdBM0E0anJBU0FGUWdBM0F1VHFBU0FGUWdBM0F1VHJBU0FGUVlHQWdNQUFOZ0s4NndFZ0JVSUFOd0trNndFZ0JVSDg2Z0ZxUVFBMkFnQWdCVUdRNndGcVFnQTNBd0FnQlJBWUlBVkJyTlVCYWlFVUlBVkIrT3NCYWlFY0lBVkJzT29CYWlFaUlBVkJvREJxSVNvZ0JVR1lJR29oS3lBRlFhalFBR29oSGlBRlFSQnFJU3dnQlVFSWFpRW9JQVZCQkdvaExTQUZRY0RwQVdvaEtTQUZRWWpyQVdvZ0JFR1VBV29oTHlBRVFZd0JhaUV3SUFSQmhBRnFJVEVnQkVIY0FHb2hNaUFFUWRRQWFpRXpJQVJCekFCcUlUUWdBQ0VkQWtBQ1FBSkFBa0FDUUFOQVFRRkJCU0FGS0FMazZnRWJJUVlDUUFOQUlBTWdCa2tOQVNBQ0tBQUFRWEJ4UWREVXRNSUJSZ1JBUWJoL0lRY2dBMEVJU1EwSUlBSW9BQVFpRGtGM1N3UkFRWEloQnd3SkN5QURJQTVCQ0dvaUNVa05DQ0FPUVlCL1N3UkFJQWtoQnd3SkN5QURJQWxySVFNZ0FpQUphaUVDREFFTEN5QUZRZ0EzQXF6cEFTQUZRZ0EzQStqcEFTQUZRUUEyQXBqckFTQUZRZ0EzQTREcUFTQUZRZ00zQS9qcEFTQUZRYlRwQVdwQ0FEY0NBQ0FGUWZEcEFXcENBRGNEQUNBRlFhalFBR29pQ1VHTWdJRGdBRFlDQUNBRlFhelFBV3BCNEJJcEFnQTNBZ0FnQlVHMDBBRnFRZWdTS0FJQU5nSUFJQVVnQlVFUWFqWUNBQ0FGSUFWQm9EQnFOZ0lFSUFVZ0JVR1lJR28yQWdnZ0JTQUpOZ0lNSUFWQkFVRUZJQVVvQXVUcUFSczJBcnpwQVFKQUlBRkZEUUFnQlNnQ3JPa0JJZ2tnSFVZTkFDQUZJQWsyQXJqcEFTQUZJQjAyQXF6cEFTQUZLQUt3NlFFaERpQUZJQjAyQXJEcEFTQUZJQjBnRGlBSmEybzJBclRwQVF0QnVIOGhDU0FEUVFWQkNTQUZLQUxrNmdFaUJodEpEUVVnQWtFQlFRVWdCaHNnQmhBYUlnNUJpSDlMQkVBZ0RpRUpEQVVMSUFNZ0RrRURha2tOQlNBcElBSWdEaUFHRUJraUJrR0lmMHNFUUNBR0lRa01CUXNnQmcwRkFrQUNRQ0FGS0FLbzZ3RkJBVWNOQUNBRktBS2s2d0VpQ1VVTkFDQUZLQUtVNndGRkRRQWdDU2dDQkVFQmF5SUhJQVVvQXR6cEFTSUtyVUtIbGErdm1MYmVtNTUvZmtMSno5bXk4ZVc2NmllRlFoZUpRcy9XMDc3U3g2dlpRbjVDK2ZQZDhabjJtYXNXZkNJL1FpR0lJRCtGUXMvVzA3N1N4NnZaUW40aVAwSWRpQ0EvaFVMNTg5M3htZmFacXhaK0lqOUNJSWdnUDRXbmNTRUdJQWtvQWdBaEZRTkFRUUFoQ0FKQUlCVWdCa0VDZEdvb0FnQWlDVVVOQUNBSktBSUlRUWhKRFFBZ0NTZ0NCQ0lTS0FBQVFiZkl3dUYrUncwQUlCSW9BQVFoQ0FzZ0NDQUtSd1JBSUFZZ0IzRkJBV29oQmlBSURRRUxDeUFKUlEwQUlBVVFHQ0FGUVg4MkFxRHJBU0FGSUFrMkFwVHJBU0FGSUFVb0F0enBBU0lJTmdLWTZ3RU1BUXNnQlNnQzNPa0JJUWdMQWtBZ0NFVU5BQ0FGS0FLWTZ3RWdDRVlOQUVGZ0lRa01CZ3NDUUNBRktBTGc2UUVFUUNBRklBVW9BdWpxQVNJSlJUWUM3T29CSUFrTkFTQUZRdm5xME5EbnlhSGs0UUEzQTZqcUFTQUZRZ0EzQTZEcUFTQUZRcy9XMDc3U3g2dlpRamNEbU9vQklBVkMxdXVDN3VyOWlmWGdBRGNEa09vQklBVkNBRGNEaU9vQklDSkJBRUVvRUFNYURBRUxJQVZCQURZQzdPb0JDeUFCSUIxcUlTVWdCU0FGS1FQbzZRRWdEcTE4TndQbzZRRWdBeUFPYXlFRElBSWdEbW9oQWlBZElRNERRQ0FDSUFNZ0JFRXNhaEFkSWhWQmlIOUxCRUFnRlNFSkRBWUxJQU5CQTJzaU5TQVZTUTBFSUFKQkEyb2hHMEZzSVFrQ1FBSkFBa0FDUUFKQUFrQUNRQUpBQWtBQ1FBSkFBa0FDUUFKQUFrQUNRQ0FFS0FJc0RnTUNBUUFWQ3lBVlFmLy9CMHNORXlBVlFRTkpEUklnQlNrRHlPa0JJVDhDUUFKQUlCc3RBQUFpQ1VFRGNTSWFRUUZyRGdNR0FRQUhDeUFGS0FLQTZnRU5BRUZpSVFrTUZRc2dGVUVGU1EwU0lCc29BQUFoQXdKL0FrQUNRQUpBSUFsQkFuWkJBM0VpQ1VFQ2F3NENBUUlBQ3lBSlFRQkhJUWNnQTBFRWRrSC9CM0VoQzBFRElRWWdBMEVPZGtIL0IzRU1BZ3RCQkNFR0lBTkJCSFpCLy84QWNTRUxRUUVoQnlBRFFSSjJEQUVMSUFOQkJIWkIvLzhQY1NJTFFZQ0FDRXNORTBFQklRZEJCU0VHSUFJdEFBZEJDblFnQTBFV2RuSUxJZ2dnQm1vaUNTQVZTdzBTQWtBZ0MwR0JCa2tOQUNBRktBS2M2d0ZGRFFCQkFDRURBMEFnQTBHRGdBRkxEUUVnQTBGQWF5RUREQUFMQUFzZ0JpQWJhaUVQSUJwQkEwY05CaUFGS0FJTUlnSXRBQUZCQ0hRaEF5QUhEUWNnQTBVTkNDQUVRZkFBYWlBUElBZ1FEU0lEUVloL1N3MEpJQUpCQkdvaEJpQUxJQnhxSWhKQkEyc2hDa0VBSUFJdkFRSnJRUjl4SVFjZ0hDRURBMEFnQkVId0FHb1FEMFVnQXlBS1NYRUVRQ0FESUFZZ0JDZ0NjQ0lJSUFRb0FuUWlEM1FnQjNaQkFuUnFJZ0l2QVFBN0FBQWdBeUFDTFFBRGFpSURJQVlnQ0NBUElBSXRBQUpxSWdoMElBZDJRUUowYWlJQ0x3RUFPd0FBSUFRZ0NDQUNMUUFDYWpZQ2RDQURJQUl0QUFOcUlRTU1BUVVnRWtFQ2F5RUlBMEFnQkVId0FHb1FEeUVQSUFRb0FuQWhDaUFFS0FKMElRSWdBeUFJU3lBUGNrVUVRQ0FESUFZZ0NpQUNkQ0FIZGtFQ2RHb2lDaThCQURzQUFDQUVJQUlnQ2kwQUFtbzJBblFnQXlBS0xRQURhaUVEREFFTEN3TkFJQU1nQ0UwRVFDQURJQVlnQ2lBQ2RDQUhka0VDZEdvaUR5OEJBRHNBQUNBRElBOHRBQU5xSVFNZ0FpQVBMUUFDYWlFQ0RBRUxDd0pBSUFNZ0VrOE5BQ0FESUFZZ0NpQUNkQ0FIZGtFQ2RHb2lBeTBBQURvQUFDQURMUUFEUVFGR0JFQWdBaUFETFFBQ2FpRUNEQUVMSUFKQkgwc05BRUVnSUFJZ0F5MEFBbW9pQWlBQ1FTQlBHeUVDQzBGc1FXd2dDeUFFS0FKNElBUW9BbnhIR3lBQ1FTQkhHeUVEREFzTEFBc0FDeUFFS0FJMElnSWdKU0FPYTBzTkNpQU9SUVJBUVFBaENTQUNEUUlNRGdzZ0RpQWJMUUFBSUFJUUF4b2dBaUVKREF3TElCVWdKU0FPYTBzTkNTQU9EUUZCQUNFSklCVkZEUXdMUWJaL0lRa01FUXNnRGlBYklCVVFBaG9nRlNFSkRBb0xJQndnR3dKL0FrQUNRQUpBSUFsQkFuWkJBM0ZCQVdzT0F3RUFBZ0FMSUFsQkEzWWhBMEVCREFJTElCc3ZBQUJCQkhZaEEwRUNEQUVMSUJWQkJFa05EaUFDTHdBRElBSXRBQVZCRUhSeUlnSkJqNENBQVVzTkRpQUNRUVIySVFOQkF3c2lBbW90QUFBZ0EwRWdhaEFESVFrZ0JTQUROZ0tBNndFZ0JTQUpOZ0x3NmdFZ0FrRUJhaUVKREFVTElCVUNmd0pBQWtBQ1FDQUpRUUoyUVFOeFFRRnJEZ01CQUFJQUN5QUpRUU4ySVFOQkFRd0NDeUFiTHdBQVFRUjJJUU5CQWd3QkN5QUNMd0FESUFJdEFBVkJFSFJ5UVFSMklRTkJBd3NpQWlBRGFpSUpRU0JxU1FSQUlBa2dGVXNORFNBY0lBSWdHMm9nQXhBQ0lRSWdCU0FETmdLQTZ3RWdCU0FDTmdMdzZnRWdBaUFEYWlJQ1FnQTNBQmdnQWtJQU53QVFJQUpDQURjQUNDQUNRZ0EzQUFBTUJRc2dCU0FETmdLQTZ3RWdCU0FDSUJ0cU5nTHc2Z0VNQkFzZ0IwVUVRQ0FlSUE4Z0NDQVVFQlFpQWtHSWYwc2dBaUFJVDNJTkRDQWNJQXNnQWlBUGFpQUlJQUpySUI0UUZTRUREQU1MSUF0RklBaEZjZzBMSUF0QkNIWWlBeUFJSUF0SkJIOGdDRUVFZENBTGJnVkJEd3RCR0d3aUFrR01DR29vQWdCc0lBSkJpQWhxS0FJQWFpSUdRUU4ySUFacUlBSkJnQWhxS0FJQUlBSkJoQWhxS0FJQUlBTnNha2tFUUNNQVFSQnJJaEFrQUNBZUtBSUFJUU1nRkVId0JHcEJBRUhzQUJBRElRWkJWQ0VDQWtBZ0EwSC9BWEVpREVFTVN3MEFBa0FnRkVIY0NXb2dCaUFRUVFocUlCQkJER29nRHlBSUlCUkIzQXRxSWhjUUN5SVNRWWgvU3cwQUlCQW9BZ3dpQmlBTVN3MEJJQlJCcUFWcUlRMGdGRUdrQldvaE5pQWVRUVJxSVJFZ0EwR0FnSUI0Y1NFM0lBWkJBV29pRXlFQ0lBWWhBd05BSUFJaUIwRUJheUVDSUFNaUNrRUJheUVESUJRZ0NrRUNkR29vQXZBRVJRMEFDMEVCSUFjZ0IwRUJUUnNoRmtFQUlRZEJBU0VDQTBBZ0FpQVdSd1JBSUJRZ0FrRUNkQ0lEYWlnQzhBUWhHQ0FESUExcUlBYzJBZ0FnQWtFQmFpRUNJQWNnR0dvaEJ3d0JDd3NnRFNBSE5nSUFRUUFoQWlBUUtBSUlJUU1EUUNBQ0lBTkhCRUFnRFNBQ0lCUnFRZHdKYWkwQUFDSVlRUUowYWlJWklCa29BZ0FpR1VFQmFqWUNBQ0FVSUJsQkFYUnFJaGtnR0RvQTNRVWdHU0FDT2dEY0JTQUNRUUZxSVFJTUFRc0xRUUFoQXlBTlFRQTJBZ0FnRENBR1FYOXphaUVHUVFFaEFnTkFJQUlnRmtjRVFDQVVJQUpCQW5ScUlnMGdBellDQUNBTktBTHdCQ0FDSUFacWRDQURhaUVESUFKQkFXb2hBZ3dCQ3dzZ0RDQVRJQXBySWdaclFRRnFJUW9nQmlFREEwQWdBeUFLU1FSQUlCUWdBMEUwYkdvaERVRUJJUUlEUUNBQ0lCWkhCRUFnRFNBQ1FRSjBJaGhxSUJRZ0dHb29BZ0FnQTNZMkFnQWdBa0VCYWlFQ0RBRUxDeUFEUVFGcUlRTU1BUXNMSUJjZ0ZFRTBFQUloT0NBVVFaQU1haUU1SUJNZ0RHc2hPaUFVUWR3RmFpRVhRUUFoQ2dOQUFrQUNRQ0FISUFwSEJFQkJBU0FNSUJNZ0Z5QUtRUUYwYWlJQ0xRQUJJZzFySWdOckloaDBJUmtnQWkwQUFDRVdJRGdnRFVFQ2RHb2lIeWdDQUNFQ0lBWWdHRTBFUUNBMlFRRWdBeUE2YWlJTklBMUJBVXdiSWlCQkFuUWlKR29vQWdBaERTQTVJQlFnQTBFMGJHcEJOQkFDSVNFZ0RVRUJkQ0VtSUJFZ0FrRUNkR29oSXlBZ1FRRk5EUUlnQTBFUWRFR0FnUHdIY1NBV2NrR0FnSUFJY2lFZ0lDRWdKR29vQWdBaEpFRUFJUUlEUUNBQ0lDUkdEUU1nSXlBQ1FRSjBhaUFnTmdFQUlBSkJBV29oQWd3QUN3QUxJQUlnQWlBWmFpSU5JQUlnRFVzYklRMGdBMEVRZEVHQWdQd0hjU0FXY2tHQWdJQUljaUVEQTBBZ0FpQU5SZzBESUJFZ0FrRUNkR29nQXpZQkFDQUNRUUZxSVFJTUFBc0FDeUFlSUF4QkVIUWdOM0lnREhKQmdBSnlOZ0lBREFNTElBY2dEV3NoSkNBWElDWnFJU1pCQUNFTkEwQWdEU0FrUmcwQlFRRWdHQ0FUSUNZZ0RVRUJkR29pSnkwQUFTSUNheUk3YTNRaVBDQWhJQUpCQW5ScUlpQW9BZ0FpQW1vaFBTQURJRHRxUVJCMFFZQ0EvQWR4SUNjdEFBQkJDSFJ5SUJaeVFZQ0FnQkJ5SVNjRFFDQWpJQUpCQW5ScUlDYzJBUUFnQWtFQmFpSUNJRDFKRFFBTElDQWdJQ2dDQUNBOGFqWUNBQ0FOUVFGcUlRME1BQXNBQ3lBZklCOG9BZ0FnR1dvMkFnQWdDa0VCYWlFS0RBQUxBQXNnRWlFQ0N5QVFRUkJxSkFBZ0FrR0lmMHNnQWlBSVQzSU5EQ0FjSUFzZ0FpQVBhaUFJSUFKcklCNFFGaUVEREFNTElCNGdEeUFJSUJRUUZDSUNRWWgvU3lBQ0lBaFBjZzBMSUJ3Z0N5QUNJQTlxSUFnZ0Ftc2dIaEFYSVFNTUFnc2dBd1JBSUJ3Z0N5QVBJQWdnQWhBV0lRTU1BZ3NnSENBTElBOGdDQ0FDRUJjaEF3d0JDeUFjSUFzZ0R5QUlJQUlRRlNFREN5QURRWWgvU3cwSUlBVWdDellDZ09zQklBVWdIRFlDOE9vQklBVkJBVFlDZ09vQklCcEJBa1lFUUNBRklCNDJBZ3dMSUFzZ0hHb2lBa0lBTndBQUlBSkNBRGNBR0NBQ1FnQTNBQkFnQWtJQU53QUlJQWxCaUg5TERRb0xJQWtnRlVZTkNDQVZJQWxySVFZZ0JTZ0NuT3NCSVFvQ1FDQUpJQnRxSWdNdEFBQWlEMFVFUUVFQklRSkJBQ0VQUWJoL0lRa2dCa0VCUmcwQkRBc0xBbjhnQTBFQmFpQVB3Q0lDUVFCT0RRQWFJQUpCZjBZRVFDQUdRUU5JRFFzZ0F5OEFBVUdBL2dGcUlROGdBMEVEYWd3QkN5QUdRUUpJRFFvZ0F5MEFBU0FQUVFoMGNrR0FnQUpySVE4Z0EwRUNhZ3NoRWtHNGZ5RUpJQkpCQVdvaUFpQVZJQnRxSWdkTERRb2dMQ0FGSUJJdEFBQWlFa0VHZGtFalFRa2dBaUFISUFKclFjQVFRZEFSUWZBU0lBVW9Bb1RxQVNBS0lBOGdGQkFoSWdsQmlIOUxEUWdnS3lBb0lCSkJCSFpCQTNGQkgwRUlJQUlnQ1dvaUFpQUhJQUpyUVlBTFFZQU1RWUFYSUFVb0FvVHFBU0FGS0FLYzZ3RWdEeUFVRUNFaUNFR0lmMHNOQ0VGc0lRa2dLaUF0SUJKQkFuWkJBM0ZCTkVFSklBSWdDR29pQWlBSElBSnJRWUFOUWVBT1FaQVpJQVVvQW9UcUFTQUZLQUtjNndFZ0R5QVVFQ0VpQjBHSWYwc05DaUFDSUFkcUlBTnJJZ0loQ1NBQ1FZaC9TdzBLQ3lBT0lBOUJBRXh5RFFFTFFicC9JUWtNQ0FzZ0pTQU9heUVKSUFZZ0Ftc2hCaUFDSUFOcUlRY0NRQUpBQWtBZ0NrVUVRQ0FQUVFsSUlBVXBBOGpwQVVLQmdJQUlWSElOQWlBb0tBSUFJZ0pCQ0dvaEVpQUNLQUlFSVFwQkFDRURRUUFoQWdOQUlBTWdDblpGQkVBZ0FpQVNJQU5CQTNScUxRQUNRUlpMYWlFQ0lBTkJBV29oQXd3QkN3c2dCVUVBTmdLYzZ3RWdBa0VJSUFwcmRFRVVUdzBCREFNTElBVkJBRFlDbk9zQkN5QUVJQVVvQXZEcUFTSUROZ0xjQVNBSklBNXFJUllnQXlBRktBS0E2d0ZxSVJjQ1FDQVBSUVJBSUE0aEJ3d0JDeUFGS0FLNDZRRWhHaUFGS0FLMDZRRWhHQ0FGS0FLdzZRRWhFaUFGUVFFMkFvVHFBVUVBSVFNRFFDQURRUU5IQkVBZ0JDQURRUUowSWdKcUlBSWdCV3BCck5BQmFpZ0NBRFlDWkNBRFFRRnFJUU1NQVFzTFFXd2hDU0FFUVRocUlnSWdCeUFHRUExQmlIOUxEUU5CQ0NBUElBOUJDRTRiSVI4Z05DQUNJQVVvQWdBUUhpQXpJQUlnQlNnQ0NCQWVJRElnQWlBRktBSUVFQjRnRGlBU2F5RVpRUUFoQ0FOQUlBUkJPR29RRDBFRFJpQUlJQjlPY2tVRVFDQUVLQUpRSUFRb0FreEJBM1JxS1FJQUlrQ25JZ2RCRUhZaUVVSC9BWEVoQ3lBRUtBSmdJQVFvQWx4QkEzUnFLUUlBSWtHbklneEJFSFlpSVVIL0FYRWhFQ0FFS0FKWUlBUW9BbFJCQTNScUtRSUFJa0pDSUlpbklRWWdRVUlnaUNCQVFpQ0lweUVEQWtBZ1FrSVFpS2NpQ2tIL0FYRWlBa0VDVHdSQUFrQWdBa0VaU1NBL1FvR0FnQkJVY2tVRVFDQUVRU0FnQkNnQ1BDSUtheUlOSUFJZ0FpQU5TeHNpRXlBS2FqWUNQQ0FHSUFRb0FqZ2dDblJCQUNBVGEzWWdBaUFUYXlJVGRHb2hDaUFFUVRocUVBOGFJQUlnRFUwTkFTQUVJQVFvQWp3aUFpQVRhallDUENBRUtBSTRJQUowUVFBZ0UydDJJQXBxSVFvTUFRc2dCQ0FDSUFRb0Fqd2lEV28yQWp3Z0JDZ0NPQ0FOZEVFQUlBcHJkaUFHYWlFS0lBUkJPR29RRHhvTElBUXBBbVFoUkNBRUlBbzJBbVFnQkNCRU53Sm9EQUVMQWtBZ0FrVUVRQ0FEQkVBZ0JDZ0NaQ0VLREFNTElBUW9BbWdoQ2d3QkN5QUVJQVFvQWp3aUFrRUJhallDUEFKL0lBWWdBMFZxSUFRb0FqZ2dBblJCSDNacUlnSkJBMFlFUUNBRUtBSmtRUUZyREFFTElBSkJBblFnQkdvb0FtUUxJZ1pGSUFacUlRb2dBa0VCUndSQUlBUWdCQ2dDYURZQ2JBc0xJQVFnQkNnQ1pEWUNhQ0FFSUFvMkFtUUxweUVDSUVGQ2dJRDhCNE5RUlFSQUlBUWdCQ2dDUENJR0lCQnFOZ0k4SUFRb0FqZ2dCblJCQUNBaGEzWWdBbW9oQWdzZ0N5QVFha0VVVHdSQUlBUkJPR29RRHhvTElFQkNnSUQ4QjROUVJRUkFJQVFnQkNnQ1BDSUdJQXRxTmdJOElBUW9BamdnQm5SQkFDQVJhM1lnQTJvaEF3c2dCRUU0YWhBUEdpQUVJQVFvQWpnaUJrRUFJQWRCR0hZaUN5QUVLQUk4YWlJUWEzWWdDMEVDZEVHZ0hXb29BZ0J4SUFkQi8vOERjV28yQWt3Z0JDQVFJQXhCR0hZaUIyb2lDellDUENBRUlBZEJBblJCb0IxcUtBSUFJQVpCQUNBTGEzWnhJQXhCLy84RGNXbzJBbHdnQkVFNGFoQVBHaUFFSUVLbklnWkJHSFlpQnlBRUtBSThhaUlMTmdJOElBUWdCMEVDZEVHZ0hXb29BZ0FnQkNnQ09FRUFJQXRyZG5FZ0JrSC8vd054YWpZQ1ZDQUVRZkFBYWlBSVFReHNhaUlHSUFvMkFnZ2dCaUFDTmdJRUlBWWdBellDQUNBSVFRRnFJUWdnQXlBWmFpQUNhaUVaREFFTEN5QUlJQjlJRFFNZ0ZrRWdheUVoSUE0aEJ3TkFJQVJCT0dvUUQwRURSaUFJSUE5T2NrVUVRQ0FFS0FKUUlBUW9Ba3hCQTNScUtRSUFJa0NuSWdaQkVIWWlJMEgvQVhFaENpQUVLQUpnSUFRb0FseEJBM1JxS1FJQUlrR25JZzFCRUhZaUlFSC9BWEVoRXlBRUtBSllJQVFvQWxSQkEzUnFLUUlBSWtKQ0lJaW5JUU1nUVVJZ2lDQkFRaUNJcHlFTEFrQWdRa0lRaUtjaURFSC9BWEVpQWtFQ1R3UkFBa0FnQWtFWlNTQS9Rb0dBZ0JCVWNrVUVRQ0FFUVNBZ0JDZ0NQQ0lNYXlJUklBSWdBaUFSU3hzaUVDQU1hallDUENBRElBUW9BamdnREhSQkFDQVFhM1lnQWlBUWF5SU1kR29oRUNBRVFUaHFFQThhSUFJZ0VVME5BU0FFSUFRb0Fqd2lBaUFNYWpZQ1BDQUVLQUk0SUFKMFFRQWdER3QySUJCcUlSQU1BUXNnQkNBQ0lBUW9BandpRUdvMkFqd2dCQ2dDT0NBUWRFRUFJQXhyZGlBRGFpRVFJQVJCT0dvUUR4b0xJQVFwQW1RaFJDQUVJQkEyQW1RZ0JDQkVOd0pvREFFTEFrQWdBa1VFUUNBTEJFQWdCQ2dDWkNFUURBTUxJQVFvQW1naEVBd0JDeUFFSUFRb0Fqd2lBa0VCYWpZQ1BBSi9JQU1nQzBWcUlBUW9BamdnQW5SQkgzWnFJZ0pCQTBZRVFDQUVLQUprUVFGckRBRUxJQUpCQW5RZ0JHb29BbVFMSWdORklBTnFJUkFnQWtFQlJ3UkFJQVFnQkNnQ2FEWUNiQXNMSUFRZ0JDZ0NaRFlDYUNBRUlCQTJBbVFMcHlFTUlFRkNnSUQ4QjROUVJRUkFJQVFnQkNnQ1BDSUNJQk5xTmdJOElBUW9BamdnQW5SQkFDQWdhM1lnREdvaERBc2dDaUFUYWtFVVR3UkFJQVJCT0dvUUR4b0xJRUJDZ0lEOEI0TlFSUVJBSUFRZ0JDZ0NQQ0lDSUFwcU5nSThJQVFvQWpnZ0FuUkJBQ0FqYTNZZ0Myb2hDd3NnQkVFNGFoQVBHaUFFSUFRb0FqZ2lBa0VBSUFaQkdIWWlBeUFFS0FJOGFpSUthM1lnQTBFQ2RFR2dIV29vQWdCeElBWkIvLzhEY1dvMkFrd2dCQ0FLSUExQkdIWWlBMm9pQmpZQ1BDQUVJQU5CQW5SQm9CMXFLQUlBSUFKQkFDQUdhM1p4SUExQi8vOERjV28yQWx3Z0JFRTRhaEFQR2lBRUlFS25JZ0pCR0hZaUF5QUVLQUk4YWlJR05nSThJQVFnQTBFQ2RFR2dIV29vQWdBZ0JDZ0NPRUVBSUFacmRuRWdBa0gvL3dOeGFqWUNWQUpBQWtBQ1FDQUVLQUxjQVNJRElBUkI4QUJxSUFoQkIzRkJER3hxSWhNb0FnQWlFV29pSXlBWFN3MEFJQWNnRXlnQ0JDSU5JQkZxSWdwcUlDRkxEUUFnQ2tFZ2FpQVdJQWRyVFEwQkN5QUVJQk1vQWdnMkFoZ2dCQ0FUS1FJQU53TVFJQWNnRmlBRVFSQnFJQVJCM0FGcUlCY2dFaUFZSUJvUUh5RUtEQUVMSUFjZ0VXb2hBaUFUS0FJSUlRWWdCeUFES1FBQU53QUFJQWNnQXlrQUNEY0FDQUpBSUJGQkVVa05BQ0FISUFNcEFCQTNBQkFnQnlBREtRQVlOd0FZSUJGQkVHdEJFVWdOQUNBRFFSQnFJUU1nQjBFZ2FpRVJBMEFnRVNBREtRQVFOd0FBSUJFZ0F5a0FHRGNBQ0NBUklBTXBBQ0EzQUJBZ0VTQURLUUFvTndBWUlBTkJJR29oQXlBUlFTQnFJaEVnQWtrTkFBc0xJQUlnQm1zaEF5QUVJQ00yQXR3QklBSWdFbXNnQmtrRVFDQUdJQUlnR0d0TERRY2dHaUFhSUFNZ0Vtc2lBMm9pRVNBTmFrOEVRQ0FDSUJFZ0RSQUtHZ3dDQ3lBRElBMXFJUTBnQWlBUlFRQWdBMnNRQ2lBRGF5RUNJQkloQXdzZ0JrRVFUd1JBSUFJZ0F5a0FBRGNBQUNBQ0lBTXBBQWczQUFnZ0RVRVJTQTBCSUFJZ0RXb2hCaUFDUVJCcUlRSURRQ0FDSUFNcEFCQTNBQUFnQWlBREtRQVlOd0FJSUFJZ0F5a0FJRGNBRUNBQ0lBTXBBQ2czQUJnZ0EwRWdhaUVESUFKQklHb2lBaUFHU1EwQUN3d0JDd0pBSUFaQkIwMEVRQ0FDSUFNdEFBQTZBQUFnQWlBRExRQUJPZ0FCSUFJZ0F5MEFBam9BQWlBQ0lBTXRBQU02QUFNZ0FpQURJQVpCQW5RaUJrSEFIbW9vQWdCcUlnTW9BQUEyQUFRZ0F5QUdRZUFlYWlnQ0FHc2hBd3dCQ3lBQ0lBTXBBQUEzQUFBTElBMUJDVWtOQUNBQ0lBMXFJUkVnQWtFSWFpSUdJQU5CQ0dvaUEydEJEMHdFUUFOQUlBWWdBeWtBQURjQUFDQURRUWhxSVFNZ0JrRUlhaUlHSUJGSkRRQU1BZ3NBQ3lBR0lBTXBBQUEzQUFBZ0JpQURLUUFJTndBSUlBMUJHVWdOQUNBQ1FSaHFJUUlEUUNBQ0lBTXBBQkEzQUFBZ0FpQURLUUFZTndBSUlBSWdBeWtBSURjQUVDQUNJQU1wQUNnM0FCZ2dBMEVnYWlFRElBSkJJR29pQWlBUlNRMEFDd3NnQ2tHSWYwc0VRQ0FLSVFrTUJnVWdFeUFRTmdJSUlCTWdERFlDQkNBVElBczJBZ0FnQ0VFQmFpRUlJQWNnQ21vaEJ5QUxJQmxxSUF4cUlSa01BZ3NBQ3dzZ0NDQVBTQTBESUFnZ0gyc2hCZ05BQWtBZ0JpQVBUZ1JBUVFBaEF3TkFJQU5CQTBZTkFpQUZJQU5CQW5RaUFtcEJyTkFCYWlBQ0lBUnFLQUprTmdJQUlBTkJBV29oQXd3QUN3QUxBa0FDUUFKQUlBUW9BdHdCSWdNZ0JFSHdBR29nQmtFSGNVRU1iR29pQ0NnQ0FDSU1haUlRSUJkTERRQWdCeUFJS0FJRUlnc2dER29pQ21vZ0lVc05BQ0FLUVNCcUlCWWdCMnRORFFFTElBUWdDQ2dDQ0RZQ0tDQUVJQWdwQWdBM0F5QWdCeUFXSUFSQklHb2dCRUhjQVdvZ0Z5QVNJQmdnR2hBZklRb01BUXNnQnlBTWFpRUNJQWdvQWdnaENDQUhJQU1wQUFBM0FBQWdCeUFES1FBSU53QUlBa0FnREVFUlNRMEFJQWNnQXlrQUVEY0FFQ0FISUFNcEFCZzNBQmdnREVFUWEwRVJTQTBBSUFOQkVHb2hBeUFIUVNCcUlRd0RRQ0FNSUFNcEFCQTNBQUFnRENBREtRQVlOd0FJSUF3Z0F5a0FJRGNBRUNBTUlBTXBBQ2czQUJnZ0EwRWdhaUVESUF4QklHb2lEQ0FDU1EwQUN3c2dBaUFJYXlFRElBUWdFRFlDM0FFZ0FpQVNheUFJU1FSQUlBZ2dBaUFZYTBzTkJ5QWFJQm9nQXlBU2F5SURhaUlNSUF0cVR3UkFJQUlnRENBTEVBb2FEQUlMSUFNZ0Myb2hDeUFDSUF4QkFDQURheEFLSUFOcklRSWdFaUVEQ3lBSVFSQlBCRUFnQWlBREtRQUFOd0FBSUFJZ0F5a0FDRGNBQ0NBTFFSRklEUUVnQWlBTGFpRUlJQUpCRUdvaEFnTkFJQUlnQXlrQUVEY0FBQ0FDSUFNcEFCZzNBQWdnQWlBREtRQWdOd0FRSUFJZ0F5a0FLRGNBR0NBRFFTQnFJUU1nQWtFZ2FpSUNJQWhKRFFBTERBRUxBa0FnQ0VFSFRRUkFJQUlnQXkwQUFEb0FBQ0FDSUFNdEFBRTZBQUVnQWlBRExRQUNPZ0FDSUFJZ0F5MEFBem9BQXlBQ0lBTWdDRUVDZENJSVFjQWVhaWdDQUdvaUF5Z0FBRFlBQkNBRElBaEI0QjVxS0FJQWF5RUREQUVMSUFJZ0F5a0FBRGNBQUFzZ0MwRUpTUTBBSUFJZ0Myb2hEQ0FDUVFocUlnZ2dBMEVJYWlJRGEwRVBUQVJBQTBBZ0NDQURLUUFBTndBQUlBTkJDR29oQXlBSVFRaHFJZ2dnREVrTkFBd0NDd0FMSUFnZ0F5a0FBRGNBQUNBSUlBTXBBQWczQUFnZ0MwRVpTQTBBSUFKQkdHb2hBZ05BSUFJZ0F5a0FFRGNBQUNBQ0lBTXBBQmczQUFnZ0FpQURLUUFnTndBUUlBSWdBeWtBS0RjQUdDQURRU0JxSVFNZ0FrRWdhaUlDSUF4SkRRQUxDeUFLUVloL1N3UkFJQW9oQ1F3R0JTQUdRUUZxSVFZZ0J5QUthaUVIREFJTEFBc0xJQVFvQXR3QklRTUxRYnAvSVFrZ0Z5QURheUlDSUJZZ0IydExEUUlnQndSL0lBY2dBeUFDRUFJZ0Ftb0ZRUUFMSUE1cklRa01BZ3NnQlVFQU5nS2M2d0VMSUFRZ0JTZ0M4T29CSWdNMkF0d0JJQWtnRG1vaERDQURJQVVvQW9EckFXb2hFQUpBSUE5RkJFQWdEaUVHREFFTElBVW9BcmpwQVNFTklBVW9BclRwQVNFVElBVW9BckRwQVNFU0lBVkJBVFlDaE9vQlFRQWhBd05BSUFOQkEwY0VRQ0FFSUFOQkFuUWlBbW9nQWlBRmFrR3MwQUZxS0FJQU5nS2NBU0FEUVFGcUlRTU1BUXNMUVd3aENTQUVRZkFBYWlJQ0lBY2dCaEFOUVloL1N3MEJJREVnQWlBRktBSUFFQjRnTUNBQ0lBVW9BZ2dRSGlBdklBSWdCU2dDQkJBZUlBeEJJR3NoR0NBT0lRWURRQ0FFS0FLSUFTQUVLQUtFQVVFRGRHb3BBZ0FpUUtjaUNrRVFkaUlaUWY4QmNTRUxJQVFvQXBnQklBUW9BcFFCUVFOMGFpa0NBQ0pCcHlJV1FSQjJJaDlCL3dGeElSb2dCQ2dDa0FFZ0JDZ0NqQUZCQTNScUtRSUFJa0pDSUlpbklRY2dRVUlnaUNCQVFpQ0lweUVEQWtBZ1FrSVFpS2NpQ0VIL0FYRWlBa0VDVHdSQUFrQWdBa0VaU1NBL1FvR0FnQkJVY2tVRVFDQUVRU0FnQkNnQ2RDSUlheUlSSUFJZ0FpQVJTeHNpRnlBSWFqWUNkQ0FISUFRb0FuQWdDSFJCQUNBWGEzWWdBaUFYYXlJWGRHb2hDQ0FFUWZBQWFoQVBHaUFDSUJGTkRRRWdCQ0FFS0FKMElnSWdGMm8yQW5RZ0JDZ0NjQ0FDZEVFQUlCZHJkaUFJYWlFSURBRUxJQVFnQWlBRUtBSjBJaEZxTmdKMElBUW9BbkFnRVhSQkFDQUlhM1lnQjJvaENDQUVRZkFBYWhBUEdnc2dCQ2tDbkFFaFJDQUVJQWcyQXB3QklBUWdSRGNDb0FFTUFRc0NRQ0FDUlFSQUlBTUVRQ0FFS0FLY0FTRUlEQU1MSUFRb0FxQUJJUWdNQVFzZ0JDQUVLQUowSWdKQkFXbzJBblFDZnlBSElBTkZhaUFFS0FKd0lBSjBRUjkyYWlJQ1FRTkdCRUFnQkNnQ25BRkJBV3NNQVFzZ0FrRUNkQ0FFYWlnQ25BRUxJZ2RGSUFkcUlRZ2dBa0VCUndSQUlBUWdCQ2dDb0FFMkFxUUJDd3NnQkNBRUtBS2NBVFlDb0FFZ0JDQUlOZ0tjQVF1bklRSWdRVUtBZ1B3SGcxQkZCRUFnQkNBRUtBSjBJZ2NnR21vMkFuUWdCQ2dDY0NBSGRFRUFJQjlyZGlBQ2FpRUNDeUFMSUJwcVFSUlBCRUFnQkVId0FHb1FEeG9MSUVCQ2dJRDhCNE5RUlFSQUlBUWdCQ2dDZENJSElBdHFOZ0owSUFRb0FuQWdCM1JCQUNBWmEzWWdBMm9oQXdzZ0JFSHdBR29RRHhvZ0JDQUVLQUp3SWdkQkFDQUtRUmgySWdzZ0JDZ0NkR29pR210MklBdEJBblJCb0IxcUtBSUFjU0FLUWYvL0EzRnFOZ0tFQVNBRUlCb2dGa0VZZGlJS2FpSUxOZ0owSUFRZ0NrRUNkRUdnSFdvb0FnQWdCMEVBSUF0cmRuRWdGa0gvL3dOeGFqWUNsQUVnQkVId0FHb1FEeG9nQkNCQ3B5SUhRUmgySWdvZ0JDZ0NkR29pQ3pZQ2RDQUVJQXBCQW5SQm9CMXFLQUlBSUFRb0FuQkJBQ0FMYTNaeElBZEIvLzhEY1dvMkFvd0JJQVFnQXpZQ09DQUVJQUkyQWp3Z0JDQUlOZ0pBQWtBQ1FBSkFJQVFvQXR3Qklnc2dBMm9pRmlBUVN3MEFJQVlnQWlBRGFpSUthaUFZU3cwQUlBcEJJR29nRENBR2EwME5BUXNnQkNBRVFVQnJLQUlBTmdJSUlBUWdCQ2tET0RjREFDQUdJQXdnQkNBRVFkd0JhaUFRSUJJZ0V5QU5FQjhoQ2d3QkN5QURJQVpxSVFjZ0JpQUxLUUFBTndBQUlBWWdDeWtBQ0RjQUNBSkFJQU5CRVVrTkFDQUdJQXNwQUJBM0FCQWdCaUFMS1FBWU53QVlJQU5CRUd0QkVVZ05BQ0FMUVJCcUlRTWdCa0VnYWlFTEEwQWdDeUFES1FBUU53QUFJQXNnQXlrQUdEY0FDQ0FMSUFNcEFDQTNBQkFnQ3lBREtRQW9Od0FZSUFOQklHb2hBeUFMUVNCcUlnc2dCMGtOQUFzTElBY2dDR3NoQXlBRUlCWTJBdHdCSUFjZ0Vtc2dDRWtFUUNBSUlBY2dFMnRMRFFRZ0RTQU5JQU1nRW1zaUEyb2lDeUFDYWs4RVFDQUhJQXNnQWhBS0dnd0NDeUFISUF0QkFDQURheEFLSUFRZ0FpQURhaUlDTmdJOElBTnJJUWNnRWlFREN5QUlRUkJQQkVBZ0J5QURLUUFBTndBQUlBY2dBeWtBQ0RjQUNDQUNRUkZJRFFFZ0FpQUhhaUVJSUFkQkVHb2hBZ05BSUFJZ0F5a0FFRGNBQUNBQ0lBTXBBQmczQUFnZ0FpQURLUUFnTndBUUlBSWdBeWtBS0RjQUdDQURRU0JxSVFNZ0FrRWdhaUlDSUFoSkRRQUxEQUVMQWtBZ0NFRUhUUVJBSUFjZ0F5MEFBRG9BQUNBSElBTXRBQUU2QUFFZ0J5QURMUUFDT2dBQ0lBY2dBeTBBQXpvQUF5QUhJQU1nQ0VFQ2RDSUlRY0FlYWlnQ0FHb2lBeWdBQURZQUJDQURJQWhCNEI1cUtBSUFheUVEREFFTElBY2dBeWtBQURjQUFBc2dBa0VKU1EwQUlBSWdCMm9oQ3lBSFFRaHFJZ2dnQTBFSWFpSURhMEVQVEFSQUEwQWdDQ0FES1FBQU53QUFJQU5CQ0dvaEF5QUlRUWhxSWdnZ0Mwa05BQXdDQ3dBTElBZ2dBeWtBQURjQUFDQUlJQU1wQUFnM0FBZ2dBa0VaU0EwQUlBZEJHR29oQWdOQUlBSWdBeWtBRURjQUFDQUNJQU1wQUJnM0FBZ2dBaUFES1FBZ053QVFJQUlnQXlrQUtEY0FHQ0FEUVNCcUlRTWdBa0VnYWlJQ0lBdEpEUUFMQ3lBS1FZaC9Td1JBSUFvaENRd0RDeUFHSUFwcUlRWWdCRUh3QUdvUUR5RURJQTlCQVdzaUR3MEFDMEVBSVFJZ0EwRUNTUTBCQTBBZ0FrRURSd1JBSUFVZ0FrRUNkQ0lEYWtHczBBRnFJQU1nQkdvb0Fwd0JOZ0lBSUFKQkFXb2hBZ3dCQ3dzZ0JDZ0MzQUVoQXd0QnVuOGhDU0FRSUFOcklnSWdEQ0FHYTBzTkFDQUdCSDhnQmlBRElBSVFBaUFDYWdWQkFBc2dEbXNoQ1FzZ0NVR0lmMHNOQmdzQ1FDQUZLQUxzNmdGRkRRQWdCU0FGS1FPSTZnRWdDYTE4TndPSTZnRUNRQ0FGS0FMUTZnRWlBaUFKYWlJSVFSOU5CRUFnRGtVTkFTQUNJQ0pxSUE0Z0NSQUNHaUFGS0FMUTZnRWdDV29oQ0F3QkN5QU9JUU1nQWdSQUlBSWdJbW9nQTBFZ0lBSnJFQUlhSUFVb0F0RHFBU0VDSUFWQkFEWUMwT29CSUFVZ0JTa0RrT29CSUFVcEFMRHFBVUxQMXRPKzBzZXIyVUorZkVJZmlVS0hsYSt2bUxiZW01NS9mamNEa09vQklBVWdCU2tEbU9vQklBVXBBTGpxQVVMUDF0Tyswc2VyMlVKK2ZFSWZpVUtIbGErdm1MYmVtNTUvZmpjRG1Pb0JJQVVnQlNrRG9Pb0JJQVVwQU1EcUFVTFAxdE8rMHNlcjJVSitmRUlmaVVLSGxhK3ZtTGJlbTU1L2ZqY0RvT29CSUFVZ0JTa0RxT29CSUFVcEFNanFBVUxQMXRPKzBzZXIyVUorZkVJZmlVS0hsYSt2bUxiZW01NS9mamNEcU9vQklBTWdBbXRCSUdvaEF3c2dDU0FPYWlJQ0lBTkJJR3BQQkVBZ0FrRWdheUVHSUFVcEE2anFBU0UvSUFVcEE2RHFBU0ZBSUFVcEE1anFBU0ZCSUFVcEE1RHFBU0ZDQTBBZ0F5a0FHRUxQMXRPKzBzZXIyVUorSUQ5OFFoK0pRb2VWcjYrWXR0NmJubjkrSVQ4Z0F5a0FFRUxQMXRPKzBzZXIyVUorSUVCOFFoK0pRb2VWcjYrWXR0NmJubjkrSVVBZ0F5a0FDRUxQMXRPKzBzZXIyVUorSUVGOFFoK0pRb2VWcjYrWXR0NmJubjkrSVVFZ0F5a0FBRUxQMXRPKzBzZXIyVUorSUVKOFFoK0pRb2VWcjYrWXR0NmJubjkrSVVJZ0EwRWdhaUlESUFaTkRRQUxJQVVnUHpjRHFPb0JJQVVnUURjRG9Pb0JJQVVnUVRjRG1Pb0JJQVVnUWpjRGtPb0JDeUFDSUFOTkRRRWdJaUFESUFJZ0Eyc2lDQkFDR2dzZ0JTQUlOZ0xRNmdFTElEVWdGV3NoQXlBVklCdHFJUUlnQ1NBT2FpRU9JQVFvQWpCRkRRQUxJQ2twQXdBaVAwSi9VU0EvSUE0Z0hXdXNVWEpGQkVCQmJDRUpEQVlMSUFVb0F1RHBBUVJBUVdvaENTQURRUVJKRFFZZ0JTZ0M2T29CUlFSQUlDSWdCU2dDME9vQmFpRUtBbjRnQlNrRGlPb0JJajlDSUZvRVFDQUZLUU9ZNmdFaVFFSUhpU0FGS1FPUTZnRWlRVUlCaVh3Z0JTa0RvT29CSWtKQ0RJbDhJQVVwQTZqcUFTSkRRaEtKZkNCQlFzL1cwNzdTeDZ2WlFuNUNINGxDaDVXdnI1aTIzcHVlZjM2RlFvZVZyNitZdHQ2Ym5uOStRcDJqdGVxRHNZMksrZ0I5SUVCQ3o5YlR2dExIcTlsQ2ZrSWZpVUtIbGErdm1MYmVtNTUvZm9WQ2g1V3ZyNWkyM3B1ZWYzNUNuYU8xNm9PeGpZcjZBSDBnUWtMUDF0Tyswc2VyMlVKK1FoK0pRb2VWcjYrWXR0NmJubjkraFVLSGxhK3ZtTGJlbTU1L2ZrS2RvN1hxZzdHTml2b0FmU0JEUXMvVzA3N1N4NnZaUW41Q0g0bENoNVd2cjVpMjNwdWVmMzZGUW9lVnI2K1l0dDZibm45K1FwMmp0ZXFEc1kySytnQjlEQUVMSUFVcEE2RHFBVUxGejlteThlVzY2aWQ4Q3lBL2ZDRS9JQ0loQmdOQUlBb2dCa0VJYWlJSFR3UkFJQVlwQUFCQ3o5YlR2dExIcTlsQ2ZrSWZpVUtIbGErdm1MYmVtNTUvZmlBL2hVSWJpVUtIbGErdm1MYmVtNTUvZmtLZG83WHFnN0dOaXZvQWZTRS9JQWNoQmd3QkN3c0NRQ0FLSUFaQkJHb2lDRWtFUUNBR0lRZ01BUXNnQmpVQUFFS0hsYSt2bUxiZW01NS9maUEvaFVJWGlVTFAxdE8rMHNlcjJVSitRdm56M2ZHWjlwbXJGbndoUHdzRFFDQUlJQXBKQkVBZ0NERUFBRUxGejlteThlVzY2aWQrSUQrRlFndUpRb2VWcjYrWXR0NmJubjkrSVQ4Z0NFRUJhaUVJREFFTEN5QUNLQUFBSUQ5Q0lZZ2dQNFZDejliVHZ0TEhxOWxDZmlJL1FoMklJRCtGUXZuejNmR1o5cG1yRm40aVAwSWdpQ0EvaGFkSERRY0xJQU5CQkdzaEF5QUNRUVJxSVFJTElBNGdIV3NpQ1VHSmYwOE5CQ0FCSUFscklRRWdDU0FkYWlFZFFRRWhQZ3dCQ3d0QnVIOGhCeUFERFFRZ0hTQUFheUVIREFRTFFXd2hDUXdCQzBHNGZ5RUpDMEc0ZnlFSElBbEJka1lnUG5FTkFRc2dDU0VIQ3lnQ0FBMEFJQVZCL09vQmFpZ0NBQ0VCSUFWQitPb0JhaWdDQUNFQUlBVVFHQ0FGS0FLdzZ3RWdBQ0FCRUJNZ0JVRUFOZ0t3NndFZ0JTZ0NwT3NCSWdJRVFBSkFBa0FDUUFKQUlBSW9BZ0FpQXdSQUlBQkZEUUlnQVNBRElBQVJBZ0FNQVFzZ0FFVU5BZ3NnQVNBQ0lBQVJBZ0FNQWdzZ0F4QUdDeUFDRUFZTElBVkJBRFlDcE9zQkN5QUFCRUFnQVNBRklBQVJBZ0FNQVFzZ0JSQUdDeUFFUWVBQmFpUUFJQWNMQzZnVkNRQkJpQWdMRFFFQUFBQUJBQUFBQWdBQUFBSUFRYUFJQzdNR0FRQUFBQUVBQUFBQ0FBQUFBZ0FBQUNZQUFBQ0NBQUFBSVFVQUFFb0FBQUJuQ0FBQUpnQUFBTUFCQUFDQUFBQUFTUVVBQUVvQUFBQytDQUFBS1FBQUFDd0NBQUNBQUFBQVNRVUFBRW9BQUFDK0NBQUFMd0FBQU1vQ0FBQ0FBQUFBaWdVQUFFb0FBQUNFQ1FBQU5RQUFBSE1EQUFDQUFBQUFuUVVBQUVvQUFBQ2dDUUFBUFFBQUFJRURBQUNBQUFBQTZ3VUFBRXNBQUFBK0NnQUFSQUFBQUo0REFBQ0FBQUFBVFFZQUFFc0FBQUNxQ2dBQVN3QUFBTE1EQUFDQUFBQUF3UVlBQUUwQUFBQWZEUUFBVFFBQUFGTUVBQUNBQUFBQUl3Z0FBRkVBQUFDbUR3QUFWQUFBQUprRUFBQ0FBQUFBU3drQUFGY0FBQUN4RWdBQVdBQUFBTm9FQUFDQUFBQUFid2tBQUYwQUFBQWpGQUFBVkFBQUFFVUZBQUNBQUFBQVZBb0FBR29BQUFDTUZBQUFhZ0FBQUs4RkFBQ0FBQUFBZGdrQUFId0FBQUJPRUFBQWZBQUFBTklDQUFDQUFBQUFZd2NBQUpFQUFBQ1FCd0FBa2dBQUFBQUFBQUFCQUFBQUFRQUFBQVVBQUFBTkFBQUFIUUFBQUQwQUFBQjlBQUFBL1FBQUFQMEJBQUQ5QXdBQS9RY0FBUDBQQUFEOUh3QUEvVDhBQVAxL0FBRDkvd0FBL2Y4QkFQMy9Bd0Q5L3djQS9mOFBBUDMvSHdEOS96OEEvZjkvQVAzLy93RDkvLzhCL2YvL0EvMy8vd2Y5Ly84UC9mLy9ILzMvL3ovOS8vOS9BQUFBQUFFQUFBQUNBQUFBQXdBQUFBUUFBQUFGQUFBQUJnQUFBQWNBQUFBSUFBQUFDUUFBQUFvQUFBQUxBQUFBREFBQUFBMEFBQUFPQUFBQUR3QUFBQkFBQUFBUkFBQUFFZ0FBQUJNQUFBQVVBQUFBRlFBQUFCWUFBQUFYQUFBQUdBQUFBQmtBQUFBYUFBQUFHd0FBQUJ3QUFBQWRBQUFBSGdBQUFCOEFBQUFEQUFBQUJBQUFBQVVBQUFBR0FBQUFCd0FBQUFnQUFBQUpBQUFBQ2dBQUFBc0FBQUFNQUFBQURRQUFBQTRBQUFBUEFBQUFFQUFBQUJFQUFBQVNBQUFBRXdBQUFCUUFBQUFWQUFBQUZnQUFBQmNBQUFBWUFBQUFHUUFBQUJvQUFBQWJBQUFBSEFBQUFCMEFBQUFlQUFBQUh3QUFBQ0FBQUFBaEFBQUFJZ0FBQUNNQUFBQWxBQUFBSndBQUFDa0FBQUFyQUFBQUx3QUFBRE1BQUFBN0FBQUFRd0FBQUZNQUFBQmpBQUFBZ3dBQUFBTUJBQUFEQWdBQUF3UUFBQU1JQUFBREVBQUFBeUFBQUFOQUFBQURnQUFBQXdBQkFFSGdEd3RSQVFBQUFBRUFBQUFCQUFBQUFRQUFBQUlBQUFBQ0FBQUFBd0FBQUFNQUFBQUVBQUFBQkFBQUFBVUFBQUFIQUFBQUNBQUFBQWtBQUFBS0FBQUFDd0FBQUF3QUFBQU5BQUFBRGdBQUFBOEFBQUFRQUVIRUVBdUxBUUVBQUFBQ0FBQUFBd0FBQUFRQUFBQUZBQUFBQmdBQUFBY0FBQUFJQUFBQUNRQUFBQW9BQUFBTEFBQUFEQUFBQUEwQUFBQU9BQUFBRHdBQUFCQUFBQUFTQUFBQUZBQUFBQllBQUFBWUFBQUFIQUFBQUNBQUFBQW9BQUFBTUFBQUFFQUFBQUNBQUFBQUFBRUFBQUFDQUFBQUJBQUFBQWdBQUFBUUFBQUFJQUFBQUVBQUFBQ0FBQUFBQUFFQVFaQVNDK1lFQVFBQUFBRUFBQUFCQUFBQUFRQUFBQUlBQUFBQ0FBQUFBd0FBQUFNQUFBQUVBQUFBQmdBQUFBY0FBQUFJQUFBQUNRQUFBQW9BQUFBTEFBQUFEQUFBQUEwQUFBQU9BQUFBRHdBQUFCQUFBQUFCQUFBQUJBQUFBQWdBQUFBQUFBQUFBUUFCQVFZQUFBQUFBQUFFQUFBQUFCQUFBQVFBQUFBQUlBQUFCUUVBQUFBQUFBQUZBd0FBQUFBQUFBVUVBQUFBQUFBQUJRWUFBQUFBQUFBRkJ3QUFBQUFBQUFVSkFBQUFBQUFBQlFvQUFBQUFBQUFGREFBQUFBQUFBQVlPQUFBQUFBQUJCUkFBQUFBQUFBRUZGQUFBQUFBQUFRVVdBQUFBQUFBQ0JSd0FBQUFBQUFNRklBQUFBQUFBQkFVd0FBQUFJQUFHQlVBQUFBQUFBQWNGZ0FBQUFBQUFDQVlBQVFBQUFBQUtCZ0FFQUFBQUFBd0dBQkFBQUNBQUFBUUFBQUFBQUFBQUJBRUFBQUFBQUFBRkFnQUFBQ0FBQUFVRUFBQUFBQUFBQlFVQUFBQWdBQUFGQndBQUFBQUFBQVVJQUFBQUlBQUFCUW9BQUFBQUFBQUZDd0FBQUFBQUFBWU5BQUFBSUFBQkJSQUFBQUFBQUFFRkVnQUFBQ0FBQVFVV0FBQUFBQUFDQlJnQUFBQWdBQU1GSUFBQUFBQUFBd1VvQUFBQUFBQUdCRUFBQUFBUUFBWUVRQUFBQUNBQUJ3V0FBQUFBQUFBSkJnQUNBQUFBQUFzR0FBZ0FBREFBQUFRQUFBQUFFQUFBQkFFQUFBQWdBQUFGQWdBQUFDQUFBQVVEQUFBQUlBQUFCUVVBQUFBZ0FBQUZCZ0FBQUNBQUFBVUlBQUFBSUFBQUJRa0FBQUFnQUFBRkN3QUFBQ0FBQUFVTUFBQUFBQUFBQmc4QUFBQWdBQUVGRWdBQUFDQUFBUVVVQUFBQUlBQUNCUmdBQUFBZ0FBSUZIQUFBQUNBQUF3VW9BQUFBSUFBRUJUQUFBQUFBQUJBR0FBQUJBQUFBRHdZQWdBQUFBQUFPQmdCQUFBQUFBQTBHQUNBQVFZQVhDNGNDQVFBQkFRVUFBQUFBQUFBRkFBQUFBQUFBQmdROUFBQUFBQUFKQmYwQkFBQUFBQThGL1g4QUFBQUFGUVg5L3g4QUFBQURCUVVBQUFBQUFBY0VmUUFBQUFBQURBWDlEd0FBQUFBU0JmMy9Bd0FBQUJjRi9mOS9BQUFBQlFVZEFBQUFBQUFJQlAwQUFBQUFBQTRGL1Q4QUFBQUFGQVg5L3c4QUFBQUNCUUVBQUFBUUFBY0VmUUFBQUFBQUN3WDlCd0FBQUFBUkJmMy9BUUFBQUJZRi9mOC9BQUFBQkFVTkFBQUFFQUFJQlAwQUFBQUFBQTBGL1I4QUFBQUFFd1g5L3djQUFBQUJCUUVBQUFBUUFBWUVQUUFBQUFBQUNnWDlBd0FBQUFBUUJmMy9BQUFBQUJ3Ri9mLy9Ed0FBR3dYOS8vOEhBQUFhQmYzLy93TUFBQmtGL2YvL0FRQUFHQVg5Ly84QVFaQVpDNFlFQVFBQkFRWUFBQUFBQUFBR0F3QUFBQUFBQUFRRUFBQUFJQUFBQlFVQUFBQUFBQUFGQmdBQUFBQUFBQVVJQUFBQUFBQUFCUWtBQUFBQUFBQUZDd0FBQUFBQUFBWU5BQUFBQUFBQUJoQUFBQUFBQUFBR0V3QUFBQUFBQUFZV0FBQUFBQUFBQmhrQUFBQUFBQUFHSEFBQUFBQUFBQVlmQUFBQUFBQUFCaUlBQUFBQUFBRUdKUUFBQUFBQUFRWXBBQUFBQUFBQ0JpOEFBQUFBQUFNR093QUFBQUFBQkFaVEFBQUFBQUFIQm9NQUFBQUFBQWtHQXdJQUFCQUFBQVFFQUFBQUFBQUFCQVVBQUFBZ0FBQUZCZ0FBQUFBQUFBVUhBQUFBSUFBQUJRa0FBQUFBQUFBRkNnQUFBQUFBQUFZTUFBQUFBQUFBQmc4QUFBQUFBQUFHRWdBQUFBQUFBQVlWQUFBQUFBQUFCaGdBQUFBQUFBQUdHd0FBQUFBQUFBWWVBQUFBQUFBQUJpRUFBQUFBQUFFR0l3QUFBQUFBQVFZbkFBQUFBQUFDQmlzQUFBQUFBQU1HTXdBQUFBQUFCQVpEQUFBQUFBQUZCbU1BQUFBQUFBZ0dBd0VBQUNBQUFBUUVBQUFBTUFBQUJBUUFBQUFRQUFBRUJRQUFBQ0FBQUFVSEFBQUFJQUFBQlFnQUFBQWdBQUFGQ2dBQUFDQUFBQVVMQUFBQUFBQUFCZzRBQUFBQUFBQUdFUUFBQUFBQUFBWVVBQUFBQUFBQUJoY0FBQUFBQUFBR0dnQUFBQUFBQUFZZEFBQUFBQUFBQmlBQUFBQUFBQkFHQXdBQkFBQUFEd1lEZ0FBQUFBQU9CZ05BQUFBQUFBMEdBeUFBQUFBQURBWURFQUFBQUFBTEJnTUlBQUFBQUFvR0F3UUFRYVFkQzlrQkFRQUFBQU1BQUFBSEFBQUFEd0FBQUI4QUFBQS9BQUFBZndBQUFQOEFBQUQvQVFBQS93TUFBUDhIQUFEL0R3QUEveDhBQVA4L0FBRC9md0FBLy84QUFQLy9BUUQvL3dNQS8vOEhBUC8vRHdELy94OEEvLzgvQVAvL2Z3RC8vLzhBLy8vL0FmLy8vd1AvLy84SC8vLy9ELy8vL3gvLy8vOC8vLy8vZndBQUFBQUJBQUFBQWdBQUFBUUFBQUFBQUFBQUFnQUFBQVFBQUFBSUFBQUFBQUFBQUFFQUFBQUNBQUFBQVFBQUFBUUFBQUFFQUFBQUJBQUFBQVFBQUFBSUFBQUFDQUFBQUFnQUFBQUhBQUFBQ0FBQUFBa0FBQUFLQUFBQUN3QkJnQjhMQTRBUkFRPT0iO3ZhciBPdD1uZXcgd0EsVHQ9ITE7YXN5bmMgZnVuY3Rpb24gY2UoQSx0LEkpe2xldCBlPW51bGw7dHlwZW9mIEEhPSJzdHJpbmciP2U9QS5ocmVmOkEuc3RhcnRzV2l0aCgiaHR0cCIpP2U9QTplPWAke3R9LyR7QX1gLGUuZW5kc1dpdGgoIi5qcyIpJiYoZT1lLnN1YnN0cmluZygwLGUubGVuZ3RoLTMpKSxlLmVuZHNXaXRoKCIud2FzbSIpJiYoZT1lLnN1YnN0cmluZygwLGUubGVuZ3RoLTUpKTtsZXQgZz1gJHtlfS53YXNtYCxyPWF3YWl0IHlBLmdldChgJHtnfS56c3RgLHtyZXNwb25zZVR5cGU6ImFycmF5YnVmZmVyIixwYXJhbXM6SX0pO1R0fHwoYXdhaXQgT3QuaW5pdCgpLFR0PSEwKTtsZXQgbj1PdC5kZWNvZGUobmV3IFVpbnQ4QXJyYXkoci5kYXRhKSkuYnVmZmVyO3JldHVybihhd2FpdCBpbXBvcnQoYCR7ZX0uanNgKSkuZGVmYXVsdCh7d2FzbUJpbmFyeTpufSl9dmFyIFB0PWNlO3ZhciBtQT1uZXcgTWFwO2FzeW5jIGZ1bmN0aW9uIGZlKEEsdCxJKXtsZXQgZT1BLGc9QSxyPW51bGw7cmV0dXJuIHR5cGVvZiBBIT0ic3RyaW5nIiYmKGU9bmV3IFVSTChBLmhyZWYpLGc9ZS5ocmVmKSxtQS5oYXMoZyk/cj1hd2FpdCBtQS5nZXQoZyk6KG1BLnNldChnLFB0KGUsdCxJKSkscj1hd2FpdCBtQS5nZXQoZykpLHJ9dmFyIHh0PWZlO3ZhciBsZT17VGV4dEZpbGU6IlRleHRGaWxlIixCaW5hcnlGaWxlOiJCaW5hcnlGaWxlIixUZXh0U3RyZWFtOiJUZXh0U3RyZWFtIixCaW5hcnlTdHJlYW06IkJpbmFyeVN0cmVhbSIsSW1hZ2U6IkltYWdlIixQb2ludFNldDoiUG9pbnRTZXQiLE1lc2g6Ik1lc2giLFBvbHlEYXRhOiJQb2x5RGF0YSIsVHJhbnNmb3JtTGlzdDoiVHJhbnNmb3JtTGlzdCIsSnNvbkNvbXBhdGlibGU6Ikpzb25Db21wYXRpYmxlIn0sRD1sZTt2YXIgRGU9e0ludDg6ImludDgiLFVJbnQ4OiJ1aW50OCIsSW50MTY6ImludDE2IixVSW50MTY6InVpbnQxNiIsSW50MzI6ImludDMyIixVSW50MzI6InVpbnQzMiIsSW50NjQ6ImludDY0IixVSW50NjQ6InVpbnQ2NCIsU2l6ZVZhbHVlVHlwZToidWludDY0IixJZGVudGlmaWVyVHlwZToidWludDY0IixJbmRleFZhbHVlVHlwZToiaW50NjQiLE9mZnNldFZhbHVlVHlwZToiaW50NjQifSxTPURlO3ZhciB1ZT17RmxvYXQzMjoiZmxvYXQzMiIsRmxvYXQ2NDoiZmxvYXQ2NCIsU3BhY2VQcmVjaXNpb25UeXBlOiJmbG9hdDY0In0saj11ZTtmdW5jdGlvbiBoZShBLHQpe2xldCBJPW51bGw7c3dpdGNoKEEpe2Nhc2UgUy5VSW50ODp7ST1uZXcgVWludDhBcnJheSh0KTticmVha31jYXNlIFMuSW50ODp7ST1uZXcgSW50OEFycmF5KHQpO2JyZWFrfWNhc2UgUy5VSW50MTY6e0k9bmV3IFVpbnQxNkFycmF5KHQpO2JyZWFrfWNhc2UgUy5JbnQxNjp7ST1uZXcgSW50MTZBcnJheSh0KTticmVha31jYXNlIFMuVUludDMyOntJPW5ldyBVaW50MzJBcnJheSh0KTticmVha31jYXNlIFMuSW50MzI6e0k9bmV3IEludDMyQXJyYXkodCk7YnJlYWt9Y2FzZSBTLlVJbnQ2NDp7dHlwZW9mIGdsb2JhbFRoaXMuQmlnVWludDY0QXJyYXk9PSJmdW5jdGlvbiI/ST1uZXcgQmlnVWludDY0QXJyYXkodCk6ST1uZXcgVWludDhBcnJheSh0KTticmVha31jYXNlIFMuSW50NjQ6e3R5cGVvZiBnbG9iYWxUaGlzLkJpZ0ludDY0QXJyYXk9PSJmdW5jdGlvbiI/ST1uZXcgQmlnSW50NjRBcnJheSh0KTpJPW5ldyBVaW50OEFycmF5KHQpO2JyZWFrfWNhc2Ugai5GbG9hdDMyOntJPW5ldyBGbG9hdDMyQXJyYXkodCk7YnJlYWt9Y2FzZSBqLkZsb2F0NjQ6e0k9bmV3IEZsb2F0NjRBcnJheSh0KTticmVha31jYXNlIm51bGwiOntJPW51bGw7YnJlYWt9Y2FzZSBudWxsOntJPW51bGw7YnJlYWt9ZGVmYXVsdDp0aHJvdyBuZXcgRXJyb3IoIlR5cGUgaXMgbm90IHN1cHBvcnRlZCBhcyBhIFR5cGVkQXJyYXkiKX1yZXR1cm4gSX12YXIgRz1oZTt2YXIgWnQ9dHlwZW9mIGdsb2JhbFRoaXMuU2hhcmVkQXJyYXlCdWZmZXI9PSJmdW5jdGlvbiIsanQ9bmV3IFRleHRFbmNvZGVyLFd0PW5ldyBUZXh0RGVjb2RlcigidXRmLTgiKTtmdW5jdGlvbiBkZShBLHQpe2xldCBJPXtmbGFnczoiciIsZW5jb2Rpbmc6ImJpbmFyeSJ9LGU9QS5mc19vcGVuKHQsSS5mbGFncykscj1BLmZzX3N0YXQodCkuc2l6ZSxvPW51bGw7WnQ/bz1uZXcgU2hhcmVkQXJyYXlCdWZmZXIocik6bz1uZXcgQXJyYXlCdWZmZXIocik7bGV0IG49bmV3IFVpbnQ4QXJyYXkobyk7cmV0dXJuIEEuZnNfcmVhZChlLG4sMCxyLDApLEEuZnNfY2xvc2UoZSksbn1mdW5jdGlvbiBWdChBLHQsSSl7bGV0IGU9bnVsbDtadD9lPW5ldyBTaGFyZWRBcnJheUJ1ZmZlcihJKTplPW5ldyBBcnJheUJ1ZmZlcihJKTtsZXQgZz1uZXcgVWludDhBcnJheShlKSxyPW5ldyBVaW50OEFycmF5KEEuSEVBUFU4LmJ1ZmZlcix0LEkpO3JldHVybiBnLnNldChyKSxnfWZ1bmN0aW9uIGQoQSx0LEksZSl7bGV0IGc9MDtyZXR1cm4gdCE9PW51bGwmJihnPUEuY2NhbGwoIml0a193YXNtX2lucHV0X2FycmF5X2FsbG9jIiwibnVtYmVyIixbIm51bWJlciIsIm51bWJlciIsIm51bWJlciIsIm51bWJlciJdLFswLEksZSx0LmJ1ZmZlci5ieXRlTGVuZ3RoXSksQS5IRUFQVTguc2V0KG5ldyBVaW50OEFycmF5KHQuYnVmZmVyKSxnKSksZ31mdW5jdGlvbiBiKEEsdCxJKXtsZXQgZT1KU09OLnN0cmluZ2lmeSh0KSxnPUEubGVuZ3RoQnl0ZXNVVEY4KGUpKzEscj1BLmNjYWxsKCJpdGtfd2FzbV9pbnB1dF9qc29uX2FsbG9jIiwibnVtYmVyIixbIm51bWJlciIsIm51bWJlciIsIm51bWJlciJdLFswLEksZ10pO0Euc3RyaW5nVG9VVEY4KGUscixnKX1mdW5jdGlvbiB3KEEsdCxJLGUpe2xldCBnPUEuY2NhbGwoIml0a193YXNtX291dHB1dF9hcnJheV9hZGRyZXNzIiwibnVtYmVyIixbIm51bWJlciIsIm51bWJlciIsIm51bWJlciJdLFswLHQsSV0pLHI9QS5jY2FsbCgiaXRrX3dhc21fb3V0cHV0X2FycmF5X3NpemUiLCJudW1iZXIiLFsibnVtYmVyIiwibnVtYmVyIiwibnVtYmVyIl0sWzAsdCxJXSksbz1WdChBLGcscik7cmV0dXJuIEcoZSxvLmJ1ZmZlcil9ZnVuY3Rpb24gSUEoQSx0KXtsZXQgST1BLmNjYWxsKCJpdGtfd2FzbV9vdXRwdXRfanNvbl9hZGRyZXNzIiwibnVtYmVyIixbIm51bWJlciIsIm51bWJlciJdLFswLHRdKSxlPUEuVVRGOFRvU3RyaW5nKEkpO3JldHVybiBKU09OLnBhcnNlKGUpfWZ1bmN0aW9uIHllKEEsdCxJLGUpe2UhPW51bGwmJmUubGVuZ3RoPjAmJmUuZm9yRWFjaChmdW5jdGlvbihRLEIpe3N3aXRjaChRLnR5cGUpe2Nhc2UgRC5UZXh0U3RyZWFtOntsZXQgaT1qdC5lbmNvZGUoUS5kYXRhLmRhdGEpLGY9ZChBLGksQiwwKSxzPXtzaXplOmkuYnVmZmVyLmJ5dGVMZW5ndGgsZGF0YTpgZGF0YTphcHBsaWNhdGlvbi92bmQuaXRrLmFkZHJlc3MsMDoke2Z9YH07YihBLHMsQik7YnJlYWt9Y2FzZSBELkpzb25Db21wYXRpYmxlOntsZXQgaT1qdC5lbmNvZGUoSlNPTi5zdHJpbmdpZnkoUS5kYXRhKSksZj1kKEEsaSxCLDApLHM9e3NpemU6aS5idWZmZXIuYnl0ZUxlbmd0aCxkYXRhOmBkYXRhOmFwcGxpY2F0aW9uL3ZuZC5pdGsuYWRkcmVzcywwOiR7Zn1gfTtiKEEscyxCKTticmVha31jYXNlIEQuQmluYXJ5U3RyZWFtOntsZXQgaT1RLmRhdGEuZGF0YSxmPWQoQSxpLEIsMCkscz17c2l6ZTppLmJ1ZmZlci5ieXRlTGVuZ3RoLGRhdGE6YGRhdGE6YXBwbGljYXRpb24vdm5kLml0ay5hZGRyZXNzLDA6JHtmfWB9O2IoQSxzLEIpO2JyZWFrfWNhc2UgRC5UZXh0RmlsZTp7QS5mc193cml0ZUZpbGUoUS5kYXRhLnBhdGgsUS5kYXRhLmRhdGEpO2JyZWFrfWNhc2UgRC5CaW5hcnlGaWxlOntBLmZzX3dyaXRlRmlsZShRLmRhdGEucGF0aCxRLmRhdGEuZGF0YSk7YnJlYWt9Y2FzZSBELkltYWdlOntsZXQgaT1RLmRhdGEsZj1kKEEsaS5kYXRhLEIsMCkscz1kKEEsaS5kaXJlY3Rpb24sQiwxKSxhPXR5cGVvZiBpLm1ldGFkYXRhPy5lbnRyaWVzPCJ1Ij9BcnJheS5mcm9tKGkubWV0YWRhdGEuZW50cmllcygpKTpbXSxFPXtpbWFnZVR5cGU6aS5pbWFnZVR5cGUsbmFtZTppLm5hbWUsb3JpZ2luOmkub3JpZ2luLHNwYWNpbmc6aS5zcGFjaW5nLGRpcmVjdGlvbjpgZGF0YTphcHBsaWNhdGlvbi92bmQuaXRrLmFkZHJlc3MsMDoke3N9YCxzaXplOmkuc2l6ZSxkYXRhOmBkYXRhOmFwcGxpY2F0aW9uL3ZuZC5pdGsuYWRkcmVzcywwOiR7Zn1gLG1ldGFkYXRhOmF9O2IoQSxFLEIpO2JyZWFrfWNhc2UgRC5NZXNoOntsZXQgaT1RLmRhdGEsZj1kKEEsaS5wb2ludHMsQiwwKSxzPWQoQSxpLmNlbGxzLEIsMSksYT1kKEEsaS5wb2ludERhdGEsQiwyKSxFPWQoQSxpLmNlbGxEYXRhLEIsMyksdT17bWVzaFR5cGU6aS5tZXNoVHlwZSxuYW1lOmkubmFtZSxudW1iZXJPZlBvaW50czppLm51bWJlck9mUG9pbnRzLHBvaW50czpgZGF0YTphcHBsaWNhdGlvbi92bmQuaXRrLmFkZHJlc3MsMDoke2Z9YCxudW1iZXJPZkNlbGxzOmkubnVtYmVyT2ZDZWxscyxjZWxsczpgZGF0YTphcHBsaWNhdGlvbi92bmQuaXRrLmFkZHJlc3MsMDoke3N9YCxjZWxsQnVmZmVyU2l6ZTppLmNlbGxCdWZmZXJTaXplLG51bWJlck9mUG9pbnRQaXhlbHM6aS5udW1iZXJPZlBvaW50UGl4ZWxzLHBvaW50RGF0YTpgZGF0YTphcHBsaWNhdGlvbi92bmQuaXRrLmFkZHJlc3MsMDoke2F9YCxudW1iZXJPZkNlbGxQaXhlbHM6aS5udW1iZXJPZkNlbGxQaXhlbHMsY2VsbERhdGE6YGRhdGE6YXBwbGljYXRpb24vdm5kLml0ay5hZGRyZXNzLDA6JHtFfWB9O2IoQSx1LEIpO2JyZWFrfWNhc2UgRC5Qb2ludFNldDp7bGV0IGk9US5kYXRhLGY9ZChBLGkucG9pbnRzLEIsMCkscz1kKEEsaS5wb2ludERhdGEsQiwxKSxhPXtwb2ludFNldFR5cGU6aS5wb2ludFNldFR5cGUsbmFtZTppLm5hbWUsbnVtYmVyT2ZQb2ludHM6aS5udW1iZXJPZlBvaW50cyxwb2ludHM6YGRhdGE6YXBwbGljYXRpb24vdm5kLml0ay5hZGRyZXNzLDA6JHtmfWAsbnVtYmVyT2ZQb2ludFBpeGVsczppLm51bWJlck9mUG9pbnRQaXhlbHMscG9pbnREYXRhOmBkYXRhOmFwcGxpY2F0aW9uL3ZuZC5pdGsuYWRkcmVzcywwOiR7c31gfTtiKEEsYSxCKTticmVha31jYXNlIEQuVHJhbnNmb3JtTGlzdDp7bGV0IGk9US5kYXRhLGY9W107aS5mb3JFYWNoKChzLGEpPT57bGV0IHU9YGRhdGE6YXBwbGljYXRpb24vdm5kLml0ay5hZGRyZXNzLDA6JHtkKEEscy5maXhlZFBhcmFtZXRlcnMsQixhKjIpfWAsRj1gZGF0YTphcHBsaWNhdGlvbi92bmQuaXRrLmFkZHJlc3MsMDoke2QoQSxzLnBhcmFtZXRlcnMsQixhKjIrMSl9YCxSPXt0cmFuc2Zvcm1UeXBlOnMudHJhbnNmb3JtVHlwZSxudW1iZXJPZkZpeGVkUGFyYW1ldGVyczpzLm51bWJlck9mRml4ZWRQYXJhbWV0ZXJzLG51bWJlck9mUGFyYW1ldGVyczpzLm51bWJlck9mUGFyYW1ldGVycyxuYW1lOnMubmFtZSxpbnB1dFNwYWNlTmFtZTpzLmlucHV0U3BhY2VOYW1lLG91dHB1dFNwYWNlTmFtZTpzLm91dHB1dFNwYWNlTmFtZSxwYXJhbWV0ZXJzOkYsZml4ZWRQYXJhbWV0ZXJzOnV9O2YucHVzaChSKX0pLGIoQSxmLEIpO2JyZWFrfWNhc2UgRC5Qb2x5RGF0YTp7bGV0IGk9US5kYXRhLGY9ZChBLGkucG9pbnRzLEIsMCkscz1kKEEsaS52ZXJ0aWNlcyxCLDEpLGE9ZChBLGkubGluZXMsQiwyKSxFPWQoQSxpLnBvbHlnb25zLEIsMyksdT1kKEEsaS50cmlhbmdsZVN0cmlwcyxCLDQpLHk9ZChBLGkucG9pbnREYXRhLEIsNSksRj1kKEEsaS5wb2ludERhdGEsQiw2KSxSPXtwb2x5RGF0YVR5cGU6aS5wb2x5RGF0YVR5cGUsbmFtZTppLm5hbWUsbnVtYmVyT2ZQb2ludHM6aS5udW1iZXJPZlBvaW50cyxwb2ludHM6YGRhdGE6YXBwbGljYXRpb24vdm5kLml0ay5hZGRyZXNzLDA6JHtmfWAsdmVydGljZXNCdWZmZXJTaXplOmkudmVydGljZXNCdWZmZXJTaXplLHZlcnRpY2VzOmBkYXRhOmFwcGxpY2F0aW9uL3ZuZC5pdGsuYWRkcmVzcywwOiR7c31gLGxpbmVzQnVmZmVyU2l6ZTppLmxpbmVzQnVmZmVyU2l6ZSxsaW5lczpgZGF0YTphcHBsaWNhdGlvbi92bmQuaXRrLmFkZHJlc3MsMDoke2F9YCxwb2x5Z29uc0J1ZmZlclNpemU6aS5wb2x5Z29uc0J1ZmZlclNpemUscG9seWdvbnM6YGRhdGE6YXBwbGljYXRpb24vdm5kLml0ay5hZGRyZXNzLDA6JHtFfWAsdHJpYW5nbGVTdHJpcHNCdWZmZXJTaXplOmkudHJpYW5nbGVTdHJpcHNCdWZmZXJTaXplLHRyaWFuZ2xlU3RyaXBzOmBkYXRhOmFwcGxpY2F0aW9uL3ZuZC5pdGsuYWRkcmVzcywwOiR7dX1gLG51bWJlck9mUG9pbnRQaXhlbHM6aS5udW1iZXJPZlBvaW50UGl4ZWxzLHBvaW50RGF0YTpgZGF0YTphcHBsaWNhdGlvbi92bmQuaXRrLmFkZHJlc3MsMDoke3l9YCxudW1iZXJPZkNlbGxQaXhlbHM6aS5udW1iZXJPZkNlbGxQaXhlbHMsY2VsbERhdGE6YGRhdGE6YXBwbGljYXRpb24vdm5kLml0ay5hZGRyZXNzLDA6JHtGfWB9O2IoQSxSLEIpO2JyZWFrfWRlZmF1bHQ6dGhyb3cgRXJyb3IoIlVuc3VwcG9ydGVkIGlucHV0IEludGVyZmFjZVR5cGUiKX19KSxBLnJlc2V0TW9kdWxlU3Rkb3V0KCksQS5yZXNldE1vZHVsZVN0ZGVycigpO2xldCBnPUEuc3RhY2tTYXZlKCkscj0wO3RyeXtyPUEuY2FsbE1haW4odC5zbGljZSgpKX1jYXRjaChRKXt0aHJvdyB0eXBlb2YgUT09Im51bWJlciImJihjb25zb2xlLmxvZygiRXhjZXB0aW9uIHdoaWxlIHJ1bm5pbmcgcGlwZWxpbmU6IiksY29uc29sZS5sb2coInN0ZG91dDoiLEEuZ2V0TW9kdWxlU3Rkb3V0KCkpLGNvbnNvbGUuZXJyb3IoInN0ZGVycjoiLEEuZ2V0TW9kdWxlU3RkZXJyKCkpLHR5cGVvZiBBLmdldEV4Y2VwdGlvbk1lc3NhZ2U8InUiP2NvbnNvbGUuZXJyb3IoImV4Y2VwdGlvbjoiLEEuZ2V0RXhjZXB0aW9uTWVzc2FnZShRKSk6Y29uc29sZS5lcnJvcigiQnVpbGQgbW9kdWxlIGluIERlYnVnIG1vZGUgZm9yIGV4Y2VwdGlvbiBtZXNzYWdlIGluZm9ybWF0aW9uLiIpKSxRfWZpbmFsbHl7QS5zdGFja1Jlc3RvcmUoZyl9bGV0IG89QS5nZXRNb2R1bGVTdGRvdXQoKSxuPUEuZ2V0TW9kdWxlU3RkZXJyKCksYz1bXTtyZXR1cm4gSSE9bnVsbCYmSS5sZW5ndGg+MCYmcj09PTAmJkkuZm9yRWFjaChmdW5jdGlvbihRLEIpe2xldCBpPW51bGw7c3dpdGNoKFEudHlwZSl7Y2FzZSBELlRleHRTdHJlYW06e2xldCBzPUEuY2NhbGwoIml0a193YXNtX291dHB1dF9hcnJheV9hZGRyZXNzIiwibnVtYmVyIixbIm51bWJlciIsIm51bWJlciIsIm51bWJlciJdLFswLEIsMF0pLGE9QS5jY2FsbCgiaXRrX3dhc21fb3V0cHV0X2FycmF5X3NpemUiLCJudW1iZXIiLFsibnVtYmVyIiwibnVtYmVyIiwibnVtYmVyIl0sWzAsQiwwXSksRT1uZXcgVWludDhBcnJheShBLkhFQVBVOC5idWZmZXIscyxhKTtpPXtkYXRhOld0LmRlY29kZShFKX07YnJlYWt9Y2FzZSBELkpzb25Db21wYXRpYmxlOntsZXQgcz1BLmNjYWxsKCJpdGtfd2FzbV9vdXRwdXRfYXJyYXlfYWRkcmVzcyIsIm51bWJlciIsWyJudW1iZXIiLCJudW1iZXIiLCJudW1iZXIiXSxbMCxCLDBdKSxhPUEuY2NhbGwoIml0a193YXNtX291dHB1dF9hcnJheV9zaXplIiwibnVtYmVyIixbIm51bWJlciIsIm51bWJlciIsIm51bWJlciJdLFswLEIsMF0pLEU9bmV3IFVpbnQ4QXJyYXkoQS5IRUFQVTguYnVmZmVyLHMsYSk7aT1KU09OLnBhcnNlKFd0LmRlY29kZShFKSk7YnJlYWt9Y2FzZSBELkJpbmFyeVN0cmVhbTp7bGV0IHM9QS5jY2FsbCgiaXRrX3dhc21fb3V0cHV0X2FycmF5X2FkZHJlc3MiLCJudW1iZXIiLFsibnVtYmVyIiwibnVtYmVyIiwibnVtYmVyIl0sWzAsQiwwXSksYT1BLmNjYWxsKCJpdGtfd2FzbV9vdXRwdXRfYXJyYXlfc2l6ZSIsIm51bWJlciIsWyJudW1iZXIiLCJudW1iZXIiLCJudW1iZXIiXSxbMCxCLDBdKTtpPXtkYXRhOlZ0KEEscyxhKX07YnJlYWt9Y2FzZSBELlRleHRGaWxlOntpPXtwYXRoOlEuZGF0YS5wYXRoLGRhdGE6QS5mc19yZWFkRmlsZShRLmRhdGEucGF0aCx7ZW5jb2Rpbmc6InV0ZjgifSl9O2JyZWFrfWNhc2UgRC5CaW5hcnlGaWxlOntpPXtwYXRoOlEuZGF0YS5wYXRoLGRhdGE6ZGUoQSxRLmRhdGEucGF0aCl9O2JyZWFrfWNhc2UgRC5JbWFnZTp7bGV0IHM9SUEoQSxCKTtzLmRhdGE9dyhBLEIsMCxzLmltYWdlVHlwZS5jb21wb25lbnRUeXBlKSxzLmRpcmVjdGlvbj13KEEsQiwxLGouRmxvYXQ2NCkscy5tZXRhZGF0YT1uZXcgTWFwKHMubWV0YWRhdGEpLGk9czticmVha31jYXNlIEQuTWVzaDp7bGV0IHM9SUEoQSxCKTtzLm51bWJlck9mUG9pbnRzPjA/cy5wb2ludHM9dyhBLEIsMCxzLm1lc2hUeXBlLnBvaW50Q29tcG9uZW50VHlwZSk6cy5wb2ludHM9RyhzLm1lc2hUeXBlLnBvaW50Q29tcG9uZW50VHlwZSxuZXcgQXJyYXlCdWZmZXIoMCkpLHMubnVtYmVyT2ZDZWxscz4wP3MuY2VsbHM9dyhBLEIsMSxzLm1lc2hUeXBlLmNlbGxDb21wb25lbnRUeXBlKTpzLmNlbGxzPUcocy5tZXNoVHlwZS5jZWxsQ29tcG9uZW50VHlwZSxuZXcgQXJyYXlCdWZmZXIoMCkpLHMubnVtYmVyT2ZQb2ludFBpeGVscz4wP3MucG9pbnREYXRhPXcoQSxCLDIscy5tZXNoVHlwZS5wb2ludFBpeGVsQ29tcG9uZW50VHlwZSk6cy5wb2ludERhdGE9RyhzLm1lc2hUeXBlLnBvaW50UGl4ZWxDb21wb25lbnRUeXBlLG5ldyBBcnJheUJ1ZmZlcigwKSkscy5udW1iZXJPZkNlbGxQaXhlbHM+MD9zLmNlbGxEYXRhPXcoQSxCLDMscy5tZXNoVHlwZS5jZWxsUGl4ZWxDb21wb25lbnRUeXBlKTpzLmNlbGxEYXRhPUcocy5tZXNoVHlwZS5jZWxsUGl4ZWxDb21wb25lbnRUeXBlLG5ldyBBcnJheUJ1ZmZlcigwKSksaT1zO2JyZWFrfWNhc2UgRC5Qb2ludFNldDp7bGV0IHM9SUEoQSxCKTtzLm51bWJlck9mUG9pbnRzPjA/cy5wb2ludHM9dyhBLEIsMCxzLnBvaW50U2V0VHlwZS5wb2ludENvbXBvbmVudFR5cGUpOnMucG9pbnRzPUcocy5wb2ludFNldFR5cGUucG9pbnRDb21wb25lbnRUeXBlLG5ldyBBcnJheUJ1ZmZlcigwKSkscy5udW1iZXJPZlBvaW50UGl4ZWxzPjA/cy5wb2ludERhdGE9dyhBLEIsMSxzLnBvaW50U2V0VHlwZS5wb2ludFBpeGVsQ29tcG9uZW50VHlwZSk6cy5wb2ludERhdGE9RyhzLnBvaW50U2V0VHlwZS5wb2ludFBpeGVsQ29tcG9uZW50VHlwZSxuZXcgQXJyYXlCdWZmZXIoMCkpLGk9czticmVha31jYXNlIEQuVHJhbnNmb3JtTGlzdDp7bGV0IHM9SUEoQSxCKTtzLmZvckVhY2goKGEsRSk9PnthLm51bWJlck9mRml4ZWRQYXJhbWV0ZXJzPjAmJihzW0VdLmZpeGVkUGFyYW1ldGVycz13KEEsQixFKjIsYS50cmFuc2Zvcm1UeXBlLnBhcmFtZXRlcnNWYWx1ZVR5cGUpKSxhLm51bWJlck9mRml4ZWRQYXJhbWV0ZXJzPjAmJihzW0VdLnBhcmFtZXRlcnM9dyhBLEIsRSoyKzEsYS50cmFuc2Zvcm1UeXBlLnBhcmFtZXRlcnNWYWx1ZVR5cGUpKX0pLGk9czticmVha31jYXNlIEQuUG9seURhdGE6e2xldCBzPUlBKEEsQik7cy5udW1iZXJPZlBvaW50cz4wP3MucG9pbnRzPXcoQSxCLDAsai5GbG9hdDMyKTpzLnBvaW50cz1uZXcgRmxvYXQzMkFycmF5LHMudmVydGljZXNCdWZmZXJTaXplPjA/cy52ZXJ0aWNlcz13KEEsQiwxLFMuVUludDMyKTpzLnZlcnRpY2VzPW5ldyBVaW50MzJBcnJheSxzLmxpbmVzQnVmZmVyU2l6ZT4wP3MubGluZXM9dyhBLEIsMixTLlVJbnQzMik6cy5saW5lcz1uZXcgVWludDMyQXJyYXkscy5wb2x5Z29uc0J1ZmZlclNpemU+MD9zLnBvbHlnb25zPXcoQSxCLDMsUy5VSW50MzIpOnMucG9seWdvbnM9bmV3IFVpbnQzMkFycmF5LHMudHJpYW5nbGVTdHJpcHNCdWZmZXJTaXplPjA/cy50cmlhbmdsZVN0cmlwcz13KEEsQiw0LFMuVUludDMyKTpzLnRyaWFuZ2xlU3RyaXBzPW5ldyBVaW50MzJBcnJheSxzLm51bWJlck9mUG9pbnRQaXhlbHM+MD9zLnBvaW50RGF0YT13KEEsQiw1LHMucG9seURhdGFUeXBlLnBvaW50UGl4ZWxDb21wb25lbnRUeXBlKTpzLnBvaW50RGF0YT1HKHMucG9seURhdGFUeXBlLnBvaW50UGl4ZWxDb21wb25lbnRUeXBlLG5ldyBBcnJheUJ1ZmZlcigwKSkscy5udW1iZXJPZkNlbGxQaXhlbHM+MD9zLmNlbGxEYXRhPXcoQSxCLDYscy5wb2x5RGF0YVR5cGUuY2VsbFBpeGVsQ29tcG9uZW50VHlwZSk6cy5jZWxsRGF0YT1HKHMucG9seURhdGFUeXBlLmNlbGxQaXhlbENvbXBvbmVudFR5cGUsbmV3IEFycmF5QnVmZmVyKDApKSxpPXM7YnJlYWt9ZGVmYXVsdDp0aHJvdyBFcnJvcigiVW5zdXBwb3J0ZWQgb3V0cHV0IEludGVyZmFjZVR5cGUiKX1sZXQgZj17dHlwZTpRLnR5cGUsZGF0YTppfTtjLnB1c2goZil9KSx7cmV0dXJuVmFsdWU6cixzdGRvdXQ6byxzdGRlcnI6bixvdXRwdXRzOmN9fXZhciBYdD15ZTt2YXIgd2U9dHlwZW9mIGdsb2JhbFRoaXMuU2hhcmVkQXJyYXlCdWZmZXI8InUiO2Z1bmN0aW9uIG1lKEEsdCl7aWYoQT09bnVsbClyZXR1cm5bXTtsZXQgST1bXTtmb3IobGV0IGU9MDtlPEEubGVuZ3RoO2UrKyl7bGV0IGc9cGUoQVtlXSx0KTtnIT09bnVsbCYmSS5wdXNoKGcpfXJldHVybiBJfWZ1bmN0aW9uIHBlKEEsdCl7aWYoQT09bnVsbClyZXR1cm4gbnVsbDtsZXQgST1udWxsO3JldHVybiBBLmJ1ZmZlciE9PXZvaWQgMD9JPUEuYnVmZmVyOkEuYnl0ZUxlbmd0aCE9PXZvaWQgMCYmKEk9QSksd2UmJkkgaW5zdGFuY2VvZiBTaGFyZWRBcnJheUJ1ZmZlcj9udWxsOnQ/STpJLnNsaWNlKDApfXZhciB6dD1tZTtmdW5jdGlvbiBTZShBKXtyZXR1cm5bQS5kYXRhLEEuZGlyZWN0aW9uXX12YXIgX3Q9U2U7ZnVuY3Rpb24gRmUoQSl7cmV0dXJuW0EucG9pbnRzLEEucG9pbnREYXRhLEEuY2VsbHMsQS5jZWxsRGF0YV19dmFyIHZ0PUZlO2Z1bmN0aW9uIFJlKEEpe3JldHVybltBLnBvaW50cyxBLnZlcnRpY2VzLEEubGluZXMsQS5wb2x5Z29ucyxBLnRyaWFuZ2xlU3RyaXBzLEEucG9pbnREYXRhLEEuY2VsbERhdGFdfXZhciAkdD1SZTthc3luYyBmdW5jdGlvbiBOZShBLHQsSSxlKXtsZXQgZz1YdChBLHQsSSxlKSxyPVtdO3JldHVybiBnLm91dHB1dHMuZm9yRWFjaChmdW5jdGlvbihvKXtpZihvLnR5cGU9PT1ELkJpbmFyeVN0cmVhbXx8by50eXBlPT09RC5CaW5hcnlGaWxlKXtsZXQgbj1vLmRhdGE7ci5wdXNoKG4pfWVsc2UgaWYoby50eXBlPT09RC5JbWFnZSl7bGV0IG49by5kYXRhO3IucHVzaCguLi5fdChuKSl9ZWxzZSBpZihvLnR5cGU9PT1ELk1lc2gpe2xldCBuPW8uZGF0YTtyLnB1c2goLi4udnQobikpfWVsc2UgaWYoby50eXBlPT09RC5Qb2x5RGF0YSl7bGV0IG49by5kYXRhO3IucHVzaCguLi4kdChuKSl9fSksRkEoZyx6dChyLCEwKSl9dmFyIEFJPU5lO3ZhciBVZT17cnVuUGlwZWxpbmU6YXN5bmMgZnVuY3Rpb24oQSx0LEksZSxnLHIpe2xldCBvPWF3YWl0IHh0KEEsdCxyKTtyZXR1cm4gYXdhaXQgQUkobyxJLGUsZyl9fTtDQShVZSk7JTBBLyohIEJ1bmRsZWQgbGljZW5zZSBpbmZvcm1hdGlvbjolMEElMEFjb21saW5rL2Rpc3QvZXNtL2NvbWxpbmsubWpzOiUwQSAgKCoqJTBBICAgKiBAbGljZW5zZSUwQSAgICogQ29weXJpZ2h0IDIwMTkgR29vZ2xlIExMQyUwQSAgICogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjAlMEEgICAqKSUwQSovJTBBJztCdChsdCk7ZXhwb3J0e3cgYXMgZ2V0RGVmYXVsdFdlYldvcmtlcixkIGFzIGdldFBpcGVsaW5lV29ya2VyVXJsLGggYXMgZ2V0UGlwZWxpbmVzQmFzZVVybCxYciBhcyBoZGY1UmVhZFRyYW5zZm9ybSxBbyBhcyBoZGY1V3JpdGVUcmFuc2Zvcm0sdG8gYXMgbWF0UmVhZFRyYW5zZm9ybSxvbyBhcyBtYXRXcml0ZVRyYW5zZm9ybSxpbyBhcyBtbmNSZWFkVHJhbnNmb3JtLHNvIGFzIG1uY1dyaXRlVHJhbnNmb3JtLGhzIGFzIHNldERlZmF1bHRXZWJXb3JrZXIsQnQgYXMgc2V0UGlwZWxpbmVXb3JrZXJVcmwsdXMgYXMgc2V0UGlwZWxpbmVzQmFzZVVybCxnbyBhcyB0eHRSZWFkVHJhbnNmb3JtLENvIGFzIHR4dFdyaXRlVHJhbnNmb3JtLGtBIGFzIHZlcnNpb24sZm8gYXMgd2FzbVJlYWRUcmFuc2Zvcm0sdW8gYXMgd2FzbVdyaXRlVHJhbnNmb3JtLFFvIGFzIHdhc21ac3RkUmVhZFRyYW5zZm9ybSxtbyBhcyB3YXNtWnN0ZFdyaXRlVHJhbnNmb3JtfTsKLyohIEJ1bmRsZWQgbGljZW5zZSBpbmZvcm1hdGlvbjoKCmNvbWxpbmsvZGlzdC9lc20vY29tbGluay5tanM6CiAgKCoqCiAgICogQGxpY2Vuc2UKICAgKiBDb3B5cmlnaHQgMjAxOSBHb29nbGUgTExDCiAgICogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjAKICAgKikKKi8K""" +default_js_module = """data:text/javascript;base64,dmFyIFV0PU9iamVjdC5kZWZpbmVQcm9wZXJ0eTt2YXIgTnQ9KEEsZSk9Pntmb3IodmFyIHQgaW4gZSlVdChBLHQse2dldDplW3RdLGVudW1lcmFibGU6ITB9KX07dmFyIFR0PSIwLjEuMSIsVEE9VHQ7dmFyIEx0PXtJbnQ4OiJpbnQ4IixVSW50ODoidWludDgiLEludDE2OiJpbnQxNiIsVUludDE2OiJ1aW50MTYiLEludDMyOiJpbnQzMiIsVUludDMyOiJ1aW50MzIiLEludDY0OiJpbnQ2NCIsVUludDY0OiJ1aW50NjQiLFNpemVWYWx1ZVR5cGU6InVpbnQ2NCIsSWRlbnRpZmllclR5cGU6InVpbnQ2NCIsSW5kZXhWYWx1ZVR5cGU6ImludDY0IixPZmZzZXRWYWx1ZVR5cGU6ImludDY0In0sRj1MdDt2YXIgUHQ9e0Zsb2F0MzI6ImZsb2F0MzIiLEZsb2F0NjQ6ImZsb2F0NjQiLFNwYWNlUHJlY2lzaW9uVHlwZToiZmxvYXQ2NCJ9LEg9UHQ7ZnVuY3Rpb24gR3QoQSxlKXtsZXQgdD1udWxsO3N3aXRjaChBKXtjYXNlIEYuVUludDg6e3Q9bmV3IFVpbnQ4QXJyYXkoZSk7YnJlYWt9Y2FzZSBGLkludDg6e3Q9bmV3IEludDhBcnJheShlKTticmVha31jYXNlIEYuVUludDE2Ont0PW5ldyBVaW50MTZBcnJheShlKTticmVha31jYXNlIEYuSW50MTY6e3Q9bmV3IEludDE2QXJyYXkoZSk7YnJlYWt9Y2FzZSBGLlVJbnQzMjp7dD1uZXcgVWludDMyQXJyYXkoZSk7YnJlYWt9Y2FzZSBGLkludDMyOnt0PW5ldyBJbnQzMkFycmF5KGUpO2JyZWFrfWNhc2UgRi5VSW50NjQ6e3R5cGVvZiBnbG9iYWxUaGlzLkJpZ1VpbnQ2NEFycmF5PT0iZnVuY3Rpb24iP3Q9bmV3IEJpZ1VpbnQ2NEFycmF5KGUpOnQ9bmV3IFVpbnQ4QXJyYXkoZSk7YnJlYWt9Y2FzZSBGLkludDY0Ont0eXBlb2YgZ2xvYmFsVGhpcy5CaWdJbnQ2NEFycmF5PT0iZnVuY3Rpb24iP3Q9bmV3IEJpZ0ludDY0QXJyYXkoZSk6dD1uZXcgVWludDhBcnJheShlKTticmVha31jYXNlIEguRmxvYXQzMjp7dD1uZXcgRmxvYXQzMkFycmF5KGUpO2JyZWFrfWNhc2UgSC5GbG9hdDY0Ont0PW5ldyBGbG9hdDY0QXJyYXkoZSk7YnJlYWt9Y2FzZSJudWxsIjp7dD1udWxsO2JyZWFrfWNhc2UgbnVsbDp7dD1udWxsO2JyZWFrfWRlZmF1bHQ6dGhyb3cgbmV3IEVycm9yKCJUeXBlIGlzIG5vdCBzdXBwb3J0ZWQgYXMgYSBUeXBlZEFycmF5Iil9cmV0dXJuIHR9dmFyIEw9R3Q7ZnVuY3Rpb24gT3QoQSl7bGV0IGU9QS5zbGljZSgoQS5sYXN0SW5kZXhPZigiLiIpLTE+Pj4wKSsyKTtpZihlLnRvTG93ZXJDYXNlKCk9PT0iZ3oiKXtsZXQgdD1BLnNsaWNlKDAsLTMpLmxhc3RJbmRleE9mKCIuIik7ZT1BLnNsaWNlKCh0LTE+Pj4wKSsyKX1lbHNlIGlmKGUudG9Mb3dlckNhc2UoKT09PSJjYm9yIil7bGV0IHQ9QS5zbGljZSgwLC01KS5sYXN0SW5kZXhPZigiLiIpO2U9QS5zbGljZSgodC0xPj4+MCkrMil9ZWxzZSBpZihlLnRvTG93ZXJDYXNlKCk9PT0ienN0Iil7bGV0IHQ9QS5zbGljZSgwLC0xMCkubGFzdEluZGV4T2YoIi4iKTtlPUEuc2xpY2UoKHQtMT4+PjApKzIpfWVsc2UgaWYoZS50b0xvd2VyQ2FzZSgpPT09InppcCIpe2xldCB0PUEuc2xpY2UoMCwtNCkubGFzdEluZGV4T2YoIi4iKTtlPUEuc2xpY2UoKHQtMT4+PjApKzIpfXJldHVybiBlfXZhciBBQT1PdDt2YXIgeHQ9e1RleHRGaWxlOiJUZXh0RmlsZSIsQmluYXJ5RmlsZToiQmluYXJ5RmlsZSIsVGV4dFN0cmVhbToiVGV4dFN0cmVhbSIsQmluYXJ5U3RyZWFtOiJCaW5hcnlTdHJlYW0iLEltYWdlOiJJbWFnZSIsUG9pbnRTZXQ6IlBvaW50U2V0IixNZXNoOiJNZXNoIixQb2x5RGF0YToiUG9seURhdGEiLFRyYW5zZm9ybUxpc3Q6IlRyYW5zZm9ybUxpc3QiLEpzb25Db21wYXRpYmxlOiJKc29uQ29tcGF0aWJsZSJ9LEU9eHQ7dmFyIHllPVN5bWJvbCgiQ29tbGluay5wcm94eSIpLFd0PVN5bWJvbCgiQ29tbGluay5lbmRwb2ludCIpLEdBPVN5bWJvbCgiQ29tbGluay5yZWxlYXNlUHJveHkiKSxMQT1TeW1ib2woIkNvbWxpbmsuZmluYWxpemVyIiksQ0E9U3ltYm9sKCJDb21saW5rLnRocm93biIpLGhlPUE9PnR5cGVvZiBBPT0ib2JqZWN0IiYmQSE9PW51bGx8fHR5cGVvZiBBPT0iZnVuY3Rpb24iLEp0PXtjYW5IYW5kbGU6QT0+aGUoQSkmJkFbeWVdLHNlcmlhbGl6ZShBKXtsZXR7cG9ydDE6ZSxwb3J0Mjp0fT1uZXcgTWVzc2FnZUNoYW5uZWw7cmV0dXJuIERlKEEsZSksW3QsW3RdXX0sZGVzZXJpYWxpemUoQSl7cmV0dXJuIEEuc3RhcnQoKSxPQShBKX19LE10PXtjYW5IYW5kbGU6QT0+aGUoQSkmJkNBIGluIEEsc2VyaWFsaXplKHt2YWx1ZTpBfSl7bGV0IGU7cmV0dXJuIEEgaW5zdGFuY2VvZiBFcnJvcj9lPXtpc0Vycm9yOiEwLHZhbHVlOnttZXNzYWdlOkEubWVzc2FnZSxuYW1lOkEubmFtZSxzdGFjazpBLnN0YWNrfX06ZT17aXNFcnJvcjohMSx2YWx1ZTpBfSxbZSxbXV19LGRlc2VyaWFsaXplKEEpe3Rocm93IEEuaXNFcnJvcj9PYmplY3QuYXNzaWduKG5ldyBFcnJvcihBLnZhbHVlLm1lc3NhZ2UpLEEudmFsdWUpOkEudmFsdWV9fSx3ZT1uZXcgTWFwKFtbInByb3h5IixKdF0sWyJ0aHJvdyIsTXRdXSk7ZnVuY3Rpb24gSHQoQSxlKXtmb3IobGV0IHQgb2YgQSlpZihlPT09dHx8dD09PSIqInx8dCBpbnN0YW5jZW9mIFJlZ0V4cCYmdC50ZXN0KGUpKXJldHVybiEwO3JldHVybiExfWZ1bmN0aW9uIERlKEEsZT1nbG9iYWxUaGlzLHQ9WyIqIl0pe2UuYWRkRXZlbnRMaXN0ZW5lcigibWVzc2FnZSIsZnVuY3Rpb24gcihuKXtpZighbnx8IW4uZGF0YSlyZXR1cm47aWYoIUh0KHQsbi5vcmlnaW4pKXtjb25zb2xlLndhcm4oYEludmFsaWQgb3JpZ2luICcke24ub3JpZ2lufScgZm9yIGNvbWxpbmsgcHJveHlgKTtyZXR1cm59bGV0e2lkOm8sdHlwZTppLHBhdGg6bH09T2JqZWN0LmFzc2lnbih7cGF0aDpbXX0sbi5kYXRhKSx1PShuLmRhdGEuYXJndW1lbnRMaXN0fHxbXSkubWFwKE0pLEI7dHJ5e2xldCBzPWwuc2xpY2UoMCwtMSkucmVkdWNlKChjLEkpPT5jW0ldLEEpLGE9bC5yZWR1Y2UoKGMsSSk9PmNbSV0sQSk7c3dpdGNoKGkpe2Nhc2UiR0VUIjpCPWE7YnJlYWs7Y2FzZSJTRVQiOnNbbC5zbGljZSgtMSlbMF1dPU0obi5kYXRhLnZhbHVlKSxCPSEwO2JyZWFrO2Nhc2UiQVBQTFkiOkI9YS5hcHBseShzLHUpO2JyZWFrO2Nhc2UiQ09OU1RSVUNUIjp7bGV0IGM9bmV3IGEoLi4udSk7Qj12dChjKX1icmVhaztjYXNlIkVORFBPSU5UIjp7bGV0e3BvcnQxOmMscG9ydDI6SX09bmV3IE1lc3NhZ2VDaGFubmVsO0RlKEEsSSksQj14QShjLFtjXSl9YnJlYWs7Y2FzZSJSRUxFQVNFIjpCPXZvaWQgMDticmVhaztkZWZhdWx0OnJldHVybn19Y2F0Y2gocyl7Qj17dmFsdWU6cyxbQ0FdOjB9fVByb21pc2UucmVzb2x2ZShCKS5jYXRjaChzPT4oe3ZhbHVlOnMsW0NBXTowfSkpLnRoZW4ocz0+e2xldFthLGNdPXVBKHMpO2UucG9zdE1lc3NhZ2UoT2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LGEpLHtpZDpvfSksYyksaT09PSJSRUxFQVNFIiYmKGUucmVtb3ZlRXZlbnRMaXN0ZW5lcigibWVzc2FnZSIsciksU2UoZSksTEEgaW4gQSYmdHlwZW9mIEFbTEFdPT0iZnVuY3Rpb24iJiZBW0xBXSgpKX0pLmNhdGNoKHM9PntsZXRbYSxjXT11QSh7dmFsdWU6bmV3IFR5cGVFcnJvcigiVW5zZXJpYWxpemFibGUgcmV0dXJuIHZhbHVlIiksW0NBXTowfSk7ZS5wb3N0TWVzc2FnZShPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sYSkse2lkOm99KSxjKX0pfSksZS5zdGFydCYmZS5zdGFydCgpfWZ1bmN0aW9uIFl0KEEpe3JldHVybiBBLmNvbnN0cnVjdG9yLm5hbWU9PT0iTWVzc2FnZVBvcnQifWZ1bmN0aW9uIFNlKEEpe1l0KEEpJiZBLmNsb3NlKCl9ZnVuY3Rpb24gT0EoQSxlKXtyZXR1cm4gUEEoQSxbXSxlKX1mdW5jdGlvbiBCQShBKXtpZihBKXRocm93IG5ldyBFcnJvcigiUHJveHkgaGFzIGJlZW4gcmVsZWFzZWQgYW5kIGlzIG5vdCB1c2VhYmxlIil9ZnVuY3Rpb24gUmUoQSl7cmV0dXJuIFkoQSx7dHlwZToiUkVMRUFTRSJ9KS50aGVuKCgpPT57U2UoQSl9KX12YXIgZkE9bmV3IFdlYWtNYXAsY0E9IkZpbmFsaXphdGlvblJlZ2lzdHJ5ImluIGdsb2JhbFRoaXMmJm5ldyBGaW5hbGl6YXRpb25SZWdpc3RyeShBPT57bGV0IGU9KGZBLmdldChBKXx8MCktMTtmQS5zZXQoQSxlKSxlPT09MCYmUmUoQSl9KTtmdW5jdGlvbiBxdChBLGUpe2xldCB0PShmQS5nZXQoZSl8fDApKzE7ZkEuc2V0KGUsdCksY0EmJmNBLnJlZ2lzdGVyKEEsZSxBKX1mdW5jdGlvbiBLdChBKXtjQSYmY0EudW5yZWdpc3RlcihBKX1mdW5jdGlvbiBQQShBLGU9W10sdD1mdW5jdGlvbigpe30pe2xldCByPSExLG49bmV3IFByb3h5KHQse2dldChvLGkpe2lmKEJBKHIpLGk9PT1HQSlyZXR1cm4oKT0+e0t0KG4pLFJlKEEpLHI9ITB9O2lmKGk9PT0idGhlbiIpe2lmKGUubGVuZ3RoPT09MClyZXR1cm57dGhlbjooKT0+bn07bGV0IGw9WShBLHt0eXBlOiJHRVQiLHBhdGg6ZS5tYXAodT0+dS50b1N0cmluZygpKX0pLnRoZW4oTSk7cmV0dXJuIGwudGhlbi5iaW5kKGwpfXJldHVybiBQQShBLFsuLi5lLGldKX0sc2V0KG8saSxsKXtCQShyKTtsZXRbdSxCXT11QShsKTtyZXR1cm4gWShBLHt0eXBlOiJTRVQiLHBhdGg6Wy4uLmUsaV0ubWFwKHM9PnMudG9TdHJpbmcoKSksdmFsdWU6dX0sQikudGhlbihNKX0sYXBwbHkobyxpLGwpe0JBKHIpO2xldCB1PWVbZS5sZW5ndGgtMV07aWYodT09PVd0KXJldHVybiBZKEEse3R5cGU6IkVORFBPSU5UIn0pLnRoZW4oTSk7aWYodT09PSJiaW5kIilyZXR1cm4gUEEoQSxlLnNsaWNlKDAsLTEpKTtsZXRbQixzXT1kZShsKTtyZXR1cm4gWShBLHt0eXBlOiJBUFBMWSIscGF0aDplLm1hcChhPT5hLnRvU3RyaW5nKCkpLGFyZ3VtZW50TGlzdDpCfSxzKS50aGVuKE0pfSxjb25zdHJ1Y3QobyxpKXtCQShyKTtsZXRbbCx1XT1kZShpKTtyZXR1cm4gWShBLHt0eXBlOiJDT05TVFJVQ1QiLHBhdGg6ZS5tYXAoQj0+Qi50b1N0cmluZygpKSxhcmd1bWVudExpc3Q6bH0sdSkudGhlbihNKX19KTtyZXR1cm4gcXQobixBKSxufWZ1bmN0aW9uIGp0KEEpe3JldHVybiBBcnJheS5wcm90b3R5cGUuY29uY2F0LmFwcGx5KFtdLEEpfWZ1bmN0aW9uIGRlKEEpe2xldCBlPUEubWFwKHVBKTtyZXR1cm5bZS5tYXAodD0+dFswXSksanQoZS5tYXAodD0+dFsxXSkpXX12YXIgYmU9bmV3IFdlYWtNYXA7ZnVuY3Rpb24geEEoQSxlKXtyZXR1cm4gYmUuc2V0KEEsZSksQX1mdW5jdGlvbiB2dChBKXtyZXR1cm4gT2JqZWN0LmFzc2lnbihBLHtbeWVdOiEwfSl9ZnVuY3Rpb24gdUEoQSl7Zm9yKGxldFtlLHRdb2Ygd2UpaWYodC5jYW5IYW5kbGUoQSkpe2xldFtyLG5dPXQuc2VyaWFsaXplKEEpO3JldHVyblt7dHlwZToiSEFORExFUiIsbmFtZTplLHZhbHVlOnJ9LG5dfXJldHVyblt7dHlwZToiUkFXIix2YWx1ZTpBfSxiZS5nZXQoQSl8fFtdXX1mdW5jdGlvbiBNKEEpe3N3aXRjaChBLnR5cGUpe2Nhc2UiSEFORExFUiI6cmV0dXJuIHdlLmdldChBLm5hbWUpLmRlc2VyaWFsaXplKEEudmFsdWUpO2Nhc2UiUkFXIjpyZXR1cm4gQS52YWx1ZX19ZnVuY3Rpb24gWShBLGUsdCl7cmV0dXJuIG5ldyBQcm9taXNlKHI9PntsZXQgbj1fdCgpO0EuYWRkRXZlbnRMaXN0ZW5lcigibWVzc2FnZSIsZnVuY3Rpb24gbyhpKXshaS5kYXRhfHwhaS5kYXRhLmlkfHxpLmRhdGEuaWQhPT1ufHwoQS5yZW1vdmVFdmVudExpc3RlbmVyKCJtZXNzYWdlIixvKSxyKGkuZGF0YSkpfSksQS5zdGFydCYmQS5zdGFydCgpLEEucG9zdE1lc3NhZ2UoT2JqZWN0LmFzc2lnbih7aWQ6bn0sZSksdCl9KX1mdW5jdGlvbiBfdCgpe3JldHVybiBuZXcgQXJyYXkoNCkuZmlsbCgwKS5tYXAoKCk9Pk1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSpOdW1iZXIuTUFYX1NBRkVfSU5URUdFUikudG9TdHJpbmcoMTYpKS5qb2luKCItIil9ZnVuY3Rpb24gZUEoQSxlKXtyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gQS5hcHBseShlLGFyZ3VtZW50cyl9fXZhcnt0b1N0cmluZzp6dH09T2JqZWN0LnByb3RvdHlwZSx7Z2V0UHJvdG90eXBlT2Y6TUF9PU9iamVjdCxRQT0oQT0+ZT0+e2xldCB0PXp0LmNhbGwoZSk7cmV0dXJuIEFbdF18fChBW3RdPXQuc2xpY2UoOCwtMSkudG9Mb3dlckNhc2UoKSl9KShPYmplY3QuY3JlYXRlKG51bGwpKSxQPUE9PihBPUEudG9Mb3dlckNhc2UoKSxlPT5RQShlKT09PUEpLHBBPUE9PmU9PnR5cGVvZiBlPT09QSx7aXNBcnJheTpxfT1BcnJheSx0QT1wQSgidW5kZWZpbmVkIik7ZnVuY3Rpb24gWnQoQSl7cmV0dXJuIEEhPT1udWxsJiYhdEEoQSkmJkEuY29uc3RydWN0b3IhPT1udWxsJiYhdEEoQS5jb25zdHJ1Y3RvcikmJlQoQS5jb25zdHJ1Y3Rvci5pc0J1ZmZlcikmJkEuY29uc3RydWN0b3IuaXNCdWZmZXIoQSl9dmFyIE5lPVAoIkFycmF5QnVmZmVyIik7ZnVuY3Rpb24gVnQoQSl7bGV0IGU7cmV0dXJuIHR5cGVvZiBBcnJheUJ1ZmZlcjwidSImJkFycmF5QnVmZmVyLmlzVmlldz9lPUFycmF5QnVmZmVyLmlzVmlldyhBKTplPUEmJkEuYnVmZmVyJiZOZShBLmJ1ZmZlciksZX12YXIgWHQ9cEEoInN0cmluZyIpLFQ9cEEoImZ1bmN0aW9uIiksVGU9cEEoIm51bWJlciIpLG1BPUE9PkEhPT1udWxsJiZ0eXBlb2YgQT09Im9iamVjdCIsJHQ9QT0+QT09PSEwfHxBPT09ITEsRUE9QT0+e2lmKFFBKEEpIT09Im9iamVjdCIpcmV0dXJuITE7bGV0IGU9TUEoQSk7cmV0dXJuKGU9PT1udWxsfHxlPT09T2JqZWN0LnByb3RvdHlwZXx8T2JqZWN0LmdldFByb3RvdHlwZU9mKGUpPT09bnVsbCkmJiEoU3ltYm9sLnRvU3RyaW5nVGFnIGluIEEpJiYhKFN5bWJvbC5pdGVyYXRvciBpbiBBKX0sQXI9UCgiRGF0ZSIpLGVyPVAoIkZpbGUiKSx0cj1QKCJCbG9iIikscnI9UCgiRmlsZUxpc3QiKSxvcj1BPT5tQShBKSYmVChBLnBpcGUpLG5yPUE9PntsZXQgZTtyZXR1cm4gQSYmKHR5cGVvZiBGb3JtRGF0YT09ImZ1bmN0aW9uIiYmQSBpbnN0YW5jZW9mIEZvcm1EYXRhfHxUKEEuYXBwZW5kKSYmKChlPVFBKEEpKT09PSJmb3JtZGF0YSJ8fGU9PT0ib2JqZWN0IiYmVChBLnRvU3RyaW5nKSYmQS50b1N0cmluZygpPT09IltvYmplY3QgRm9ybURhdGFdIikpfSxpcj1QKCJVUkxTZWFyY2hQYXJhbXMiKSxhcj1BPT5BLnRyaW0/QS50cmltKCk6QS5yZXBsYWNlKC9eW1xzXHVGRUZGXHhBMF0rfFtcc1x1RkVGRlx4QTBdKyQvZywiIik7ZnVuY3Rpb24gckEoQSxlLHthbGxPd25LZXlzOnQ9ITF9PXt9KXtpZihBPT09bnVsbHx8dHlwZW9mIEE+InUiKXJldHVybjtsZXQgcixuO2lmKHR5cGVvZiBBIT0ib2JqZWN0IiYmKEE9W0FdKSxxKEEpKWZvcihyPTAsbj1BLmxlbmd0aDtyPG47cisrKWUuY2FsbChudWxsLEFbcl0scixBKTtlbHNle2xldCBvPXQ/T2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMoQSk6T2JqZWN0LmtleXMoQSksaT1vLmxlbmd0aCxsO2ZvcihyPTA7cjxpO3IrKylsPW9bcl0sZS5jYWxsKG51bGwsQVtsXSxsLEEpfX1mdW5jdGlvbiBMZShBLGUpe2U9ZS50b0xvd2VyQ2FzZSgpO2xldCB0PU9iamVjdC5rZXlzKEEpLHI9dC5sZW5ndGgsbjtmb3IoO3ItLSA+MDspaWYobj10W3JdLGU9PT1uLnRvTG93ZXJDYXNlKCkpcmV0dXJuIG47cmV0dXJuIG51bGx9dmFyIFBlPXR5cGVvZiBnbG9iYWxUaGlzPCJ1Ij9nbG9iYWxUaGlzOnR5cGVvZiBzZWxmPCJ1Ij9zZWxmOnR5cGVvZiB3aW5kb3c8InUiP3dpbmRvdzpnbG9iYWwsR2U9QT0+IXRBKEEpJiZBIT09UGU7ZnVuY3Rpb24gSkEoKXtsZXR7Y2FzZWxlc3M6QX09R2UodGhpcykmJnRoaXN8fHt9LGU9e30sdD0ocixuKT0+e2xldCBvPUEmJkxlKGUsbil8fG47RUEoZVtvXSkmJkVBKHIpP2Vbb109SkEoZVtvXSxyKTpFQShyKT9lW29dPUpBKHt9LHIpOnEocik/ZVtvXT1yLnNsaWNlKCk6ZVtvXT1yfTtmb3IobGV0IHI9MCxuPWFyZ3VtZW50cy5sZW5ndGg7cjxuO3IrKylhcmd1bWVudHNbcl0mJnJBKGFyZ3VtZW50c1tyXSx0KTtyZXR1cm4gZX12YXIgc3I9KEEsZSx0LHthbGxPd25LZXlzOnJ9PXt9KT0+KHJBKGUsKG4sbyk9Pnt0JiZUKG4pP0Fbb109ZUEobix0KTpBW29dPW59LHthbGxPd25LZXlzOnJ9KSxBKSxJcj1BPT4oQS5jaGFyQ29kZUF0KDApPT09NjUyNzkmJihBPUEuc2xpY2UoMSkpLEEpLGdyPShBLGUsdCxyKT0+e0EucHJvdG90eXBlPU9iamVjdC5jcmVhdGUoZS5wcm90b3R5cGUsciksQS5wcm90b3R5cGUuY29uc3RydWN0b3I9QSxPYmplY3QuZGVmaW5lUHJvcGVydHkoQSwic3VwZXIiLHt2YWx1ZTplLnByb3RvdHlwZX0pLHQmJk9iamVjdC5hc3NpZ24oQS5wcm90b3R5cGUsdCl9LGxyPShBLGUsdCxyKT0+e2xldCBuLG8saSxsPXt9O2lmKGU9ZXx8e30sQT09bnVsbClyZXR1cm4gZTtkb3tmb3Iobj1PYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhBKSxvPW4ubGVuZ3RoO28tLSA+MDspaT1uW29dLCghcnx8cihpLEEsZSkpJiYhbFtpXSYmKGVbaV09QVtpXSxsW2ldPSEwKTtBPXQhPT0hMSYmTUEoQSl9d2hpbGUoQSYmKCF0fHx0KEEsZSkpJiZBIT09T2JqZWN0LnByb3RvdHlwZSk7cmV0dXJuIGV9LEJyPShBLGUsdCk9PntBPVN0cmluZyhBKSwodD09PXZvaWQgMHx8dD5BLmxlbmd0aCkmJih0PUEubGVuZ3RoKSx0LT1lLmxlbmd0aDtsZXQgcj1BLmluZGV4T2YoZSx0KTtyZXR1cm4gciE9PS0xJiZyPT09dH0sQ3I9QT0+e2lmKCFBKXJldHVybiBudWxsO2lmKHEoQSkpcmV0dXJuIEE7bGV0IGU9QS5sZW5ndGg7aWYoIVRlKGUpKXJldHVybiBudWxsO2xldCB0PW5ldyBBcnJheShlKTtmb3IoO2UtLSA+MDspdFtlXT1BW2VdO3JldHVybiB0fSxmcj0oQT0+ZT0+QSYmZSBpbnN0YW5jZW9mIEEpKHR5cGVvZiBVaW50OEFycmF5PCJ1IiYmTUEoVWludDhBcnJheSkpLGNyPShBLGUpPT57bGV0IHI9KEEmJkFbU3ltYm9sLml0ZXJhdG9yXSkuY2FsbChBKSxuO2Zvcig7KG49ci5uZXh0KCkpJiYhbi5kb25lOyl7bGV0IG89bi52YWx1ZTtlLmNhbGwoQSxvWzBdLG9bMV0pfX0sdXI9KEEsZSk9PntsZXQgdCxyPVtdO2Zvcig7KHQ9QS5leGVjKGUpKSE9PW51bGw7KXIucHVzaCh0KTtyZXR1cm4gcn0sRXI9UCgiSFRNTEZvcm1FbGVtZW50IiksUXI9QT0+QS50b0xvd2VyQ2FzZSgpLnJlcGxhY2UoL1stX1xzXShbYS16XGRdKShcdyopL2csZnVuY3Rpb24odCxyLG4pe3JldHVybiByLnRvVXBwZXJDYXNlKCkrbn0pLEZlPSgoe2hhc093blByb3BlcnR5OkF9KT0+KGUsdCk9PkEuY2FsbChlLHQpKShPYmplY3QucHJvdG90eXBlKSxwcj1QKCJSZWdFeHAiKSxPZT0oQSxlKT0+e2xldCB0PU9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3JzKEEpLHI9e307ckEodCwobixvKT0+e2xldCBpOyhpPWUobixvLEEpKSE9PSExJiYocltvXT1pfHxuKX0pLE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKEEscil9LG1yPUE9PntPZShBLChlLHQpPT57aWYoVChBKSYmWyJhcmd1bWVudHMiLCJjYWxsZXIiLCJjYWxsZWUiXS5pbmRleE9mKHQpIT09LTEpcmV0dXJuITE7bGV0IHI9QVt0XTtpZihUKHIpKXtpZihlLmVudW1lcmFibGU9ITEsIndyaXRhYmxlImluIGUpe2Uud3JpdGFibGU9ITE7cmV0dXJufWUuc2V0fHwoZS5zZXQ9KCk9Pnt0aHJvdyBFcnJvcigiQ2FuIG5vdCByZXdyaXRlIHJlYWQtb25seSBtZXRob2QgJyIrdCsiJyIpfSl9fSl9LGRyPShBLGUpPT57bGV0IHQ9e30scj1uPT57bi5mb3JFYWNoKG89Pnt0W29dPSEwfSl9O3JldHVybiBxKEEpP3IoQSk6cihTdHJpbmcoQSkuc3BsaXQoZSkpLHR9LHlyPSgpPT57fSxocj0oQSxlKT0+KEE9K0EsTnVtYmVyLmlzRmluaXRlKEEpP0E6ZSksV0E9ImFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6IixVZT0iMDEyMzQ1Njc4OSIseGU9e0RJR0lUOlVlLEFMUEhBOldBLEFMUEhBX0RJR0lUOldBK1dBLnRvVXBwZXJDYXNlKCkrVWV9LHdyPShBPTE2LGU9eGUuQUxQSEFfRElHSVQpPT57bGV0IHQ9IiIse2xlbmd0aDpyfT1lO2Zvcig7QS0tOyl0Kz1lW01hdGgucmFuZG9tKCkqcnwwXTtyZXR1cm4gdH07ZnVuY3Rpb24gRHIoQSl7cmV0dXJuISEoQSYmVChBLmFwcGVuZCkmJkFbU3ltYm9sLnRvU3RyaW5nVGFnXT09PSJGb3JtRGF0YSImJkFbU3ltYm9sLml0ZXJhdG9yXSl9dmFyIFNyPUE9PntsZXQgZT1uZXcgQXJyYXkoMTApLHQ9KHIsbik9PntpZihtQShyKSl7aWYoZS5pbmRleE9mKHIpPj0wKXJldHVybjtpZighKCJ0b0pTT04iaW4gcikpe2Vbbl09cjtsZXQgbz1xKHIpP1tdOnt9O3JldHVybiByQShyLChpLGwpPT57bGV0IHU9dChpLG4rMSk7IXRBKHUpJiYob1tsXT11KX0pLGVbbl09dm9pZCAwLG99fXJldHVybiByfTtyZXR1cm4gdChBLDApfSxScj1QKCJBc3luY0Z1bmN0aW9uIiksYnI9QT0+QSYmKG1BKEEpfHxUKEEpKSYmVChBLnRoZW4pJiZUKEEuY2F0Y2gpLGc9e2lzQXJyYXk6cSxpc0FycmF5QnVmZmVyOk5lLGlzQnVmZmVyOlp0LGlzRm9ybURhdGE6bnIsaXNBcnJheUJ1ZmZlclZpZXc6VnQsaXNTdHJpbmc6WHQsaXNOdW1iZXI6VGUsaXNCb29sZWFuOiR0LGlzT2JqZWN0Om1BLGlzUGxhaW5PYmplY3Q6RUEsaXNVbmRlZmluZWQ6dEEsaXNEYXRlOkFyLGlzRmlsZTplcixpc0Jsb2I6dHIsaXNSZWdFeHA6cHIsaXNGdW5jdGlvbjpULGlzU3RyZWFtOm9yLGlzVVJMU2VhcmNoUGFyYW1zOmlyLGlzVHlwZWRBcnJheTpmcixpc0ZpbGVMaXN0OnJyLGZvckVhY2g6ckEsbWVyZ2U6SkEsZXh0ZW5kOnNyLHRyaW06YXIsc3RyaXBCT006SXIsaW5oZXJpdHM6Z3IsdG9GbGF0T2JqZWN0OmxyLGtpbmRPZjpRQSxraW5kT2ZUZXN0OlAsZW5kc1dpdGg6QnIsdG9BcnJheTpDcixmb3JFYWNoRW50cnk6Y3IsbWF0Y2hBbGw6dXIsaXNIVE1MRm9ybTpFcixoYXNPd25Qcm9wZXJ0eTpGZSxoYXNPd25Qcm9wOkZlLHJlZHVjZURlc2NyaXB0b3JzOk9lLGZyZWV6ZU1ldGhvZHM6bXIsdG9PYmplY3RTZXQ6ZHIsdG9DYW1lbENhc2U6UXIsbm9vcDp5cix0b0Zpbml0ZU51bWJlcjpocixmaW5kS2V5OkxlLGdsb2JhbDpQZSxpc0NvbnRleHREZWZpbmVkOkdlLEFMUEhBQkVUOnhlLGdlbmVyYXRlU3RyaW5nOndyLGlzU3BlY0NvbXBsaWFudEZvcm06RHIsdG9KU09OT2JqZWN0OlNyLGlzQXN5bmNGbjpScixpc1RoZW5hYmxlOmJyfTtmdW5jdGlvbiBLKEEsZSx0LHIsbil7RXJyb3IuY2FsbCh0aGlzKSxFcnJvci5jYXB0dXJlU3RhY2tUcmFjZT9FcnJvci5jYXB0dXJlU3RhY2tUcmFjZSh0aGlzLHRoaXMuY29uc3RydWN0b3IpOnRoaXMuc3RhY2s9bmV3IEVycm9yKCkuc3RhY2ssdGhpcy5tZXNzYWdlPUEsdGhpcy5uYW1lPSJBeGlvc0Vycm9yIixlJiYodGhpcy5jb2RlPWUpLHQmJih0aGlzLmNvbmZpZz10KSxyJiYodGhpcy5yZXF1ZXN0PXIpLG4mJih0aGlzLnJlc3BvbnNlPW4pfWcuaW5oZXJpdHMoSyxFcnJvcix7dG9KU09OOmZ1bmN0aW9uKCl7cmV0dXJue21lc3NhZ2U6dGhpcy5tZXNzYWdlLG5hbWU6dGhpcy5uYW1lLGRlc2NyaXB0aW9uOnRoaXMuZGVzY3JpcHRpb24sbnVtYmVyOnRoaXMubnVtYmVyLGZpbGVOYW1lOnRoaXMuZmlsZU5hbWUsbGluZU51bWJlcjp0aGlzLmxpbmVOdW1iZXIsY29sdW1uTnVtYmVyOnRoaXMuY29sdW1uTnVtYmVyLHN0YWNrOnRoaXMuc3RhY2ssY29uZmlnOmcudG9KU09OT2JqZWN0KHRoaXMuY29uZmlnKSxjb2RlOnRoaXMuY29kZSxzdGF0dXM6dGhpcy5yZXNwb25zZSYmdGhpcy5yZXNwb25zZS5zdGF0dXM/dGhpcy5yZXNwb25zZS5zdGF0dXM6bnVsbH19fSk7dmFyIFdlPUsucHJvdG90eXBlLEplPXt9O1siRVJSX0JBRF9PUFRJT05fVkFMVUUiLCJFUlJfQkFEX09QVElPTiIsIkVDT05OQUJPUlRFRCIsIkVUSU1FRE9VVCIsIkVSUl9ORVRXT1JLIiwiRVJSX0ZSX1RPT19NQU5ZX1JFRElSRUNUUyIsIkVSUl9ERVBSRUNBVEVEIiwiRVJSX0JBRF9SRVNQT05TRSIsIkVSUl9CQURfUkVRVUVTVCIsIkVSUl9DQU5DRUxFRCIsIkVSUl9OT1RfU1VQUE9SVCIsIkVSUl9JTlZBTElEX1VSTCJdLmZvckVhY2goQT0+e0plW0FdPXt2YWx1ZTpBfX0pO09iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKEssSmUpO09iamVjdC5kZWZpbmVQcm9wZXJ0eShXZSwiaXNBeGlvc0Vycm9yIix7dmFsdWU6ITB9KTtLLmZyb209KEEsZSx0LHIsbixvKT0+e2xldCBpPU9iamVjdC5jcmVhdGUoV2UpO3JldHVybiBnLnRvRmxhdE9iamVjdChBLGksZnVuY3Rpb24odSl7cmV0dXJuIHUhPT1FcnJvci5wcm90b3R5cGV9LGw9PmwhPT0iaXNBeGlvc0Vycm9yIiksSy5jYWxsKGksQS5tZXNzYWdlLGUsdCxyLG4pLGkuY2F1c2U9QSxpLm5hbWU9QS5uYW1lLG8mJk9iamVjdC5hc3NpZ24oaSxvKSxpfTt2YXIgcD1LO3ZhciBkQT1udWxsO2Z1bmN0aW9uIEhBKEEpe3JldHVybiBnLmlzUGxhaW5PYmplY3QoQSl8fGcuaXNBcnJheShBKX1mdW5jdGlvbiBIZShBKXtyZXR1cm4gZy5lbmRzV2l0aChBLCJbXSIpP0Euc2xpY2UoMCwtMik6QX1mdW5jdGlvbiBNZShBLGUsdCl7cmV0dXJuIEE/QS5jb25jYXQoZSkubWFwKGZ1bmN0aW9uKG4sbyl7cmV0dXJuIG49SGUobiksIXQmJm8/IlsiK24rIl0iOm59KS5qb2luKHQ/Ii4iOiIiKTplfWZ1bmN0aW9uIGtyKEEpe3JldHVybiBnLmlzQXJyYXkoQSkmJiFBLnNvbWUoSEEpfXZhciBGcj1nLnRvRmxhdE9iamVjdChnLHt9LG51bGwsZnVuY3Rpb24oZSl7cmV0dXJuL15pc1tBLVpdLy50ZXN0KGUpfSk7ZnVuY3Rpb24gVXIoQSxlLHQpe2lmKCFnLmlzT2JqZWN0KEEpKXRocm93IG5ldyBUeXBlRXJyb3IoInRhcmdldCBtdXN0IGJlIGFuIG9iamVjdCIpO2U9ZXx8bmV3KGRBfHxGb3JtRGF0YSksdD1nLnRvRmxhdE9iamVjdCh0LHttZXRhVG9rZW5zOiEwLGRvdHM6ITEsaW5kZXhlczohMX0sITEsZnVuY3Rpb24oZixRKXtyZXR1cm4hZy5pc1VuZGVmaW5lZChRW2ZdKX0pO2xldCByPXQubWV0YVRva2VucyxuPXQudmlzaXRvcnx8cyxvPXQuZG90cyxpPXQuaW5kZXhlcyx1PSh0LkJsb2J8fHR5cGVvZiBCbG9iPCJ1IiYmQmxvYikmJmcuaXNTcGVjQ29tcGxpYW50Rm9ybShlKTtpZighZy5pc0Z1bmN0aW9uKG4pKXRocm93IG5ldyBUeXBlRXJyb3IoInZpc2l0b3IgbXVzdCBiZSBhIGZ1bmN0aW9uIik7ZnVuY3Rpb24gQihDKXtpZihDPT09bnVsbClyZXR1cm4iIjtpZihnLmlzRGF0ZShDKSlyZXR1cm4gQy50b0lTT1N0cmluZygpO2lmKCF1JiZnLmlzQmxvYihDKSl0aHJvdyBuZXcgcCgiQmxvYiBpcyBub3Qgc3VwcG9ydGVkLiBVc2UgYSBCdWZmZXIgaW5zdGVhZC4iKTtyZXR1cm4gZy5pc0FycmF5QnVmZmVyKEMpfHxnLmlzVHlwZWRBcnJheShDKT91JiZ0eXBlb2YgQmxvYj09ImZ1bmN0aW9uIj9uZXcgQmxvYihbQ10pOkJ1ZmZlci5mcm9tKEMpOkN9ZnVuY3Rpb24gcyhDLGYsUSl7bGV0IG09QztpZihDJiYhUSYmdHlwZW9mIEM9PSJvYmplY3QiKXtpZihnLmVuZHNXaXRoKGYsInt9IikpZj1yP2Y6Zi5zbGljZSgwLC0yKSxDPUpTT04uc3RyaW5naWZ5KEMpO2Vsc2UgaWYoZy5pc0FycmF5KEMpJiZrcihDKXx8KGcuaXNGaWxlTGlzdChDKXx8Zy5lbmRzV2l0aChmLCJbXSIpKSYmKG09Zy50b0FycmF5KEMpKSlyZXR1cm4gZj1IZShmKSxtLmZvckVhY2goZnVuY3Rpb24oTixGdCl7IShnLmlzVW5kZWZpbmVkKE4pfHxOPT09bnVsbCkmJmUuYXBwZW5kKGk9PT0hMD9NZShbZl0sRnQsbyk6aT09PW51bGw/ZjpmKyJbXSIsQihOKSl9KSwhMX1yZXR1cm4gSEEoQyk/ITA6KGUuYXBwZW5kKE1lKFEsZixvKSxCKEMpKSwhMSl9bGV0IGE9W10sYz1PYmplY3QuYXNzaWduKEZyLHtkZWZhdWx0VmlzaXRvcjpzLGNvbnZlcnRWYWx1ZTpCLGlzVmlzaXRhYmxlOkhBfSk7ZnVuY3Rpb24gSShDLGYpe2lmKCFnLmlzVW5kZWZpbmVkKEMpKXtpZihhLmluZGV4T2YoQykhPT0tMSl0aHJvdyBFcnJvcigiQ2lyY3VsYXIgcmVmZXJlbmNlIGRldGVjdGVkIGluICIrZi5qb2luKCIuIikpO2EucHVzaChDKSxnLmZvckVhY2goQyxmdW5jdGlvbihtLFUpeyghKGcuaXNVbmRlZmluZWQobSl8fG09PT1udWxsKSYmbi5jYWxsKGUsbSxnLmlzU3RyaW5nKFUpP1UudHJpbSgpOlUsZixjKSk9PT0hMCYmSShtLGY/Zi5jb25jYXQoVSk6W1VdKX0pLGEucG9wKCl9fWlmKCFnLmlzT2JqZWN0KEEpKXRocm93IG5ldyBUeXBlRXJyb3IoImRhdGEgbXVzdCBiZSBhbiBvYmplY3QiKTtyZXR1cm4gSShBKSxlfXZhciBPPVVyO2Z1bmN0aW9uIFllKEEpe2xldCBlPXsiISI6IiUyMSIsIiciOiIlMjciLCIoIjoiJTI4IiwiKSI6IiUyOSIsIn4iOiIlN0UiLCIlMjAiOiIrIiwiJTAwIjoiXDAifTtyZXR1cm4gZW5jb2RlVVJJQ29tcG9uZW50KEEpLnJlcGxhY2UoL1shJygpfl18JTIwfCUwMC9nLGZ1bmN0aW9uKHIpe3JldHVybiBlW3JdfSl9ZnVuY3Rpb24gcWUoQSxlKXt0aGlzLl9wYWlycz1bXSxBJiZPKEEsdGhpcyxlKX12YXIgS2U9cWUucHJvdG90eXBlO0tlLmFwcGVuZD1mdW5jdGlvbihlLHQpe3RoaXMuX3BhaXJzLnB1c2goW2UsdF0pfTtLZS50b1N0cmluZz1mdW5jdGlvbihlKXtsZXQgdD1lP2Z1bmN0aW9uKHIpe3JldHVybiBlLmNhbGwodGhpcyxyLFllKX06WWU7cmV0dXJuIHRoaXMuX3BhaXJzLm1hcChmdW5jdGlvbihuKXtyZXR1cm4gdChuWzBdKSsiPSIrdChuWzFdKX0sIiIpLmpvaW4oIiYiKX07dmFyIHlBPXFlO2Z1bmN0aW9uIE5yKEEpe3JldHVybiBlbmNvZGVVUklDb21wb25lbnQoQSkucmVwbGFjZSgvJTNBL2dpLCI6IikucmVwbGFjZSgvJTI0L2csIiQiKS5yZXBsYWNlKC8lMkMvZ2ksIiwiKS5yZXBsYWNlKC8lMjAvZywiKyIpLnJlcGxhY2UoLyU1Qi9naSwiWyIpLnJlcGxhY2UoLyU1RC9naSwiXSIpfWZ1bmN0aW9uIG9BKEEsZSx0KXtpZighZSlyZXR1cm4gQTtsZXQgcj10JiZ0LmVuY29kZXx8TnIsbj10JiZ0LnNlcmlhbGl6ZSxvO2lmKG4/bz1uKGUsdCk6bz1nLmlzVVJMU2VhcmNoUGFyYW1zKGUpP2UudG9TdHJpbmcoKTpuZXcgeUEoZSx0KS50b1N0cmluZyhyKSxvKXtsZXQgaT1BLmluZGV4T2YoIiMiKTtpIT09LTEmJihBPUEuc2xpY2UoMCxpKSksQSs9KEEuaW5kZXhPZigiPyIpPT09LTE/Ij8iOiImIikrb31yZXR1cm4gQX12YXIgWUE9Y2xhc3N7Y29uc3RydWN0b3IoKXt0aGlzLmhhbmRsZXJzPVtdfXVzZShlLHQscil7cmV0dXJuIHRoaXMuaGFuZGxlcnMucHVzaCh7ZnVsZmlsbGVkOmUscmVqZWN0ZWQ6dCxzeW5jaHJvbm91czpyP3Iuc3luY2hyb25vdXM6ITEscnVuV2hlbjpyP3IucnVuV2hlbjpudWxsfSksdGhpcy5oYW5kbGVycy5sZW5ndGgtMX1lamVjdChlKXt0aGlzLmhhbmRsZXJzW2VdJiYodGhpcy5oYW5kbGVyc1tlXT1udWxsKX1jbGVhcigpe3RoaXMuaGFuZGxlcnMmJih0aGlzLmhhbmRsZXJzPVtdKX1mb3JFYWNoKGUpe2cuZm9yRWFjaCh0aGlzLmhhbmRsZXJzLGZ1bmN0aW9uKHIpe3IhPT1udWxsJiZlKHIpfSl9fSxxQT1ZQTt2YXIgaEE9e3NpbGVudEpTT05QYXJzaW5nOiEwLGZvcmNlZEpTT05QYXJzaW5nOiEwLGNsYXJpZnlUaW1lb3V0RXJyb3I6ITF9O3ZhciBqZT10eXBlb2YgVVJMU2VhcmNoUGFyYW1zPCJ1Ij9VUkxTZWFyY2hQYXJhbXM6eUE7dmFyIHZlPXR5cGVvZiBGb3JtRGF0YTwidSI/Rm9ybURhdGE6bnVsbDt2YXIgX2U9dHlwZW9mIEJsb2I8InUiP0Jsb2I6bnVsbDt2YXIgemU9e2lzQnJvd3NlcjohMCxjbGFzc2VzOntVUkxTZWFyY2hQYXJhbXM6amUsRm9ybURhdGE6dmUsQmxvYjpfZX0scHJvdG9jb2xzOlsiaHR0cCIsImh0dHBzIiwiZmlsZSIsImJsb2IiLCJ1cmwiLCJkYXRhIl19O3ZhciBLQT17fTtOdChLQSx7aGFzQnJvd3NlckVudjooKT0+WmUsaGFzU3RhbmRhcmRCcm93c2VyRW52OigpPT5UcixoYXNTdGFuZGFyZEJyb3dzZXJXZWJXb3JrZXJFbnY6KCk9PkxyfSk7dmFyIFplPXR5cGVvZiB3aW5kb3c8InUiJiZ0eXBlb2YgZG9jdW1lbnQ8InUiLFRyPShBPT5aZSYmWyJSZWFjdE5hdGl2ZSIsIk5hdGl2ZVNjcmlwdCIsIk5TIl0uaW5kZXhPZihBKTwwKSh0eXBlb2YgbmF2aWdhdG9yPCJ1IiYmbmF2aWdhdG9yLnByb2R1Y3QpLExyPXR5cGVvZiBXb3JrZXJHbG9iYWxTY29wZTwidSImJnNlbGYgaW5zdGFuY2VvZiBXb3JrZXJHbG9iYWxTY29wZSYmdHlwZW9mIHNlbGYuaW1wb3J0U2NyaXB0cz09ImZ1bmN0aW9uIjt2YXIgYj17Li4uS0EsLi4uemV9O2Z1bmN0aW9uIGpBKEEsZSl7cmV0dXJuIE8oQSxuZXcgYi5jbGFzc2VzLlVSTFNlYXJjaFBhcmFtcyxPYmplY3QuYXNzaWduKHt2aXNpdG9yOmZ1bmN0aW9uKHQscixuLG8pe3JldHVybiBiLmlzTm9kZSYmZy5pc0J1ZmZlcih0KT8odGhpcy5hcHBlbmQocix0LnRvU3RyaW5nKCJiYXNlNjQiKSksITEpOm8uZGVmYXVsdFZpc2l0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfX0sZSkpfWZ1bmN0aW9uIFByKEEpe3JldHVybiBnLm1hdGNoQWxsKC9cdyt8XFsoXHcqKV0vZyxBKS5tYXAoZT0+ZVswXT09PSJbXSI/IiI6ZVsxXXx8ZVswXSl9ZnVuY3Rpb24gR3IoQSl7bGV0IGU9e30sdD1PYmplY3Qua2V5cyhBKSxyLG49dC5sZW5ndGgsbztmb3Iocj0wO3I8bjtyKyspbz10W3JdLGVbb109QVtvXTtyZXR1cm4gZX1mdW5jdGlvbiBPcihBKXtmdW5jdGlvbiBlKHQscixuLG8pe2xldCBpPXRbbysrXTtpZihpPT09Il9fcHJvdG9fXyIpcmV0dXJuITA7bGV0IGw9TnVtYmVyLmlzRmluaXRlKCtpKSx1PW8+PXQubGVuZ3RoO3JldHVybiBpPSFpJiZnLmlzQXJyYXkobik/bi5sZW5ndGg6aSx1PyhnLmhhc093blByb3AobixpKT9uW2ldPVtuW2ldLHJdOm5baV09ciwhbCk6KCghbltpXXx8IWcuaXNPYmplY3QobltpXSkpJiYobltpXT1bXSksZSh0LHIsbltpXSxvKSYmZy5pc0FycmF5KG5baV0pJiYobltpXT1HcihuW2ldKSksIWwpfWlmKGcuaXNGb3JtRGF0YShBKSYmZy5pc0Z1bmN0aW9uKEEuZW50cmllcykpe2xldCB0PXt9O3JldHVybiBnLmZvckVhY2hFbnRyeShBLChyLG4pPT57ZShQcihyKSxuLHQsMCl9KSx0fXJldHVybiBudWxsfXZhciB3QT1PcjtmdW5jdGlvbiB4cihBLGUsdCl7aWYoZy5pc1N0cmluZyhBKSl0cnl7cmV0dXJuKGV8fEpTT04ucGFyc2UpKEEpLGcudHJpbShBKX1jYXRjaChyKXtpZihyLm5hbWUhPT0iU3ludGF4RXJyb3IiKXRocm93IHJ9cmV0dXJuKHR8fEpTT04uc3RyaW5naWZ5KShBKX12YXIgdkE9e3RyYW5zaXRpb25hbDpoQSxhZGFwdGVyOlsieGhyIiwiaHR0cCJdLHRyYW5zZm9ybVJlcXVlc3Q6W2Z1bmN0aW9uKGUsdCl7bGV0IHI9dC5nZXRDb250ZW50VHlwZSgpfHwiIixuPXIuaW5kZXhPZigiYXBwbGljYXRpb24vanNvbiIpPi0xLG89Zy5pc09iamVjdChlKTtpZihvJiZnLmlzSFRNTEZvcm0oZSkmJihlPW5ldyBGb3JtRGF0YShlKSksZy5pc0Zvcm1EYXRhKGUpKXJldHVybiBuP0pTT04uc3RyaW5naWZ5KHdBKGUpKTplO2lmKGcuaXNBcnJheUJ1ZmZlcihlKXx8Zy5pc0J1ZmZlcihlKXx8Zy5pc1N0cmVhbShlKXx8Zy5pc0ZpbGUoZSl8fGcuaXNCbG9iKGUpKXJldHVybiBlO2lmKGcuaXNBcnJheUJ1ZmZlclZpZXcoZSkpcmV0dXJuIGUuYnVmZmVyO2lmKGcuaXNVUkxTZWFyY2hQYXJhbXMoZSkpcmV0dXJuIHQuc2V0Q29udGVudFR5cGUoImFwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZDtjaGFyc2V0PXV0Zi04IiwhMSksZS50b1N0cmluZygpO2xldCBsO2lmKG8pe2lmKHIuaW5kZXhPZigiYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkIik+LTEpcmV0dXJuIGpBKGUsdGhpcy5mb3JtU2VyaWFsaXplcikudG9TdHJpbmcoKTtpZigobD1nLmlzRmlsZUxpc3QoZSkpfHxyLmluZGV4T2YoIm11bHRpcGFydC9mb3JtLWRhdGEiKT4tMSl7bGV0IHU9dGhpcy5lbnYmJnRoaXMuZW52LkZvcm1EYXRhO3JldHVybiBPKGw/eyJmaWxlc1tdIjplfTplLHUmJm5ldyB1LHRoaXMuZm9ybVNlcmlhbGl6ZXIpfX1yZXR1cm4gb3x8bj8odC5zZXRDb250ZW50VHlwZSgiYXBwbGljYXRpb24vanNvbiIsITEpLHhyKGUpKTplfV0sdHJhbnNmb3JtUmVzcG9uc2U6W2Z1bmN0aW9uKGUpe2xldCB0PXRoaXMudHJhbnNpdGlvbmFsfHx2QS50cmFuc2l0aW9uYWwscj10JiZ0LmZvcmNlZEpTT05QYXJzaW5nLG49dGhpcy5yZXNwb25zZVR5cGU9PT0ianNvbiI7aWYoZSYmZy5pc1N0cmluZyhlKSYmKHImJiF0aGlzLnJlc3BvbnNlVHlwZXx8bikpe2xldCBpPSEodCYmdC5zaWxlbnRKU09OUGFyc2luZykmJm47dHJ5e3JldHVybiBKU09OLnBhcnNlKGUpfWNhdGNoKGwpe2lmKGkpdGhyb3cgbC5uYW1lPT09IlN5bnRheEVycm9yIj9wLmZyb20obCxwLkVSUl9CQURfUkVTUE9OU0UsdGhpcyxudWxsLHRoaXMucmVzcG9uc2UpOmx9fXJldHVybiBlfV0sdGltZW91dDowLHhzcmZDb29raWVOYW1lOiJYU1JGLVRPS0VOIix4c3JmSGVhZGVyTmFtZToiWC1YU1JGLVRPS0VOIixtYXhDb250ZW50TGVuZ3RoOi0xLG1heEJvZHlMZW5ndGg6LTEsZW52OntGb3JtRGF0YTpiLmNsYXNzZXMuRm9ybURhdGEsQmxvYjpiLmNsYXNzZXMuQmxvYn0sdmFsaWRhdGVTdGF0dXM6ZnVuY3Rpb24oZSl7cmV0dXJuIGU+PTIwMCYmZTwzMDB9LGhlYWRlcnM6e2NvbW1vbjp7QWNjZXB0OiJhcHBsaWNhdGlvbi9qc29uLCB0ZXh0L3BsYWluLCAqLyoiLCJDb250ZW50LVR5cGUiOnZvaWQgMH19fTtnLmZvckVhY2goWyJkZWxldGUiLCJnZXQiLCJoZWFkIiwicG9zdCIsInB1dCIsInBhdGNoIl0sQT0+e3ZBLmhlYWRlcnNbQV09e319KTt2YXIgaj12QTt2YXIgV3I9Zy50b09iamVjdFNldChbImFnZSIsImF1dGhvcml6YXRpb24iLCJjb250ZW50LWxlbmd0aCIsImNvbnRlbnQtdHlwZSIsImV0YWciLCJleHBpcmVzIiwiZnJvbSIsImhvc3QiLCJpZi1tb2RpZmllZC1zaW5jZSIsImlmLXVubW9kaWZpZWQtc2luY2UiLCJsYXN0LW1vZGlmaWVkIiwibG9jYXRpb24iLCJtYXgtZm9yd2FyZHMiLCJwcm94eS1hdXRob3JpemF0aW9uIiwicmVmZXJlciIsInJldHJ5LWFmdGVyIiwidXNlci1hZ2VudCJdKSxWZT1BPT57bGV0IGU9e30sdCxyLG47cmV0dXJuIEEmJkEuc3BsaXQoYApgKS5mb3JFYWNoKGZ1bmN0aW9uKGkpe249aS5pbmRleE9mKCI6IiksdD1pLnN1YnN0cmluZygwLG4pLnRyaW0oKS50b0xvd2VyQ2FzZSgpLHI9aS5zdWJzdHJpbmcobisxKS50cmltKCksISghdHx8ZVt0XSYmV3JbdF0pJiYodD09PSJzZXQtY29va2llIj9lW3RdP2VbdF0ucHVzaChyKTplW3RdPVtyXTplW3RdPWVbdF0/ZVt0XSsiLCAiK3I6cil9KSxlfTt2YXIgWGU9U3ltYm9sKCJpbnRlcm5hbHMiKTtmdW5jdGlvbiBuQShBKXtyZXR1cm4gQSYmU3RyaW5nKEEpLnRyaW0oKS50b0xvd2VyQ2FzZSgpfWZ1bmN0aW9uIERBKEEpe3JldHVybiBBPT09ITF8fEE9PW51bGw/QTpnLmlzQXJyYXkoQSk/QS5tYXAoREEpOlN0cmluZyhBKX1mdW5jdGlvbiBKcihBKXtsZXQgZT1PYmplY3QuY3JlYXRlKG51bGwpLHQ9LyhbXlxzLDs9XSspXHMqKD86PVxzKihbXiw7XSspKT8vZyxyO2Zvcig7cj10LmV4ZWMoQSk7KWVbclsxXV09clsyXTtyZXR1cm4gZX12YXIgTXI9QT0+L15bLV9hLXpBLVowLTleYHx+LCEjJCUmJyorLl0rJC8udGVzdChBLnRyaW0oKSk7ZnVuY3Rpb24gX0EoQSxlLHQscixuKXtpZihnLmlzRnVuY3Rpb24ocikpcmV0dXJuIHIuY2FsbCh0aGlzLGUsdCk7aWYobiYmKGU9dCksISFnLmlzU3RyaW5nKGUpKXtpZihnLmlzU3RyaW5nKHIpKXJldHVybiBlLmluZGV4T2YocikhPT0tMTtpZihnLmlzUmVnRXhwKHIpKXJldHVybiByLnRlc3QoZSl9fWZ1bmN0aW9uIEhyKEEpe3JldHVybiBBLnRyaW0oKS50b0xvd2VyQ2FzZSgpLnJlcGxhY2UoLyhbYS16XGRdKShcdyopL2csKGUsdCxyKT0+dC50b1VwcGVyQ2FzZSgpK3IpfWZ1bmN0aW9uIFlyKEEsZSl7bGV0IHQ9Zy50b0NhbWVsQ2FzZSgiICIrZSk7WyJnZXQiLCJzZXQiLCJoYXMiXS5mb3JFYWNoKHI9PntPYmplY3QuZGVmaW5lUHJvcGVydHkoQSxyK3Qse3ZhbHVlOmZ1bmN0aW9uKG4sbyxpKXtyZXR1cm4gdGhpc1tyXS5jYWxsKHRoaXMsZSxuLG8saSl9LGNvbmZpZ3VyYWJsZTohMH0pfSl9dmFyIHY9Y2xhc3N7Y29uc3RydWN0b3IoZSl7ZSYmdGhpcy5zZXQoZSl9c2V0KGUsdCxyKXtsZXQgbj10aGlzO2Z1bmN0aW9uIG8obCx1LEIpe2xldCBzPW5BKHUpO2lmKCFzKXRocm93IG5ldyBFcnJvcigiaGVhZGVyIG5hbWUgbXVzdCBiZSBhIG5vbi1lbXB0eSBzdHJpbmciKTtsZXQgYT1nLmZpbmRLZXkobixzKTsoIWF8fG5bYV09PT12b2lkIDB8fEI9PT0hMHx8Qj09PXZvaWQgMCYmblthXSE9PSExKSYmKG5bYXx8dV09REEobCkpfWxldCBpPShsLHUpPT5nLmZvckVhY2gobCwoQixzKT0+byhCLHMsdSkpO3JldHVybiBnLmlzUGxhaW5PYmplY3QoZSl8fGUgaW5zdGFuY2VvZiB0aGlzLmNvbnN0cnVjdG9yP2koZSx0KTpnLmlzU3RyaW5nKGUpJiYoZT1lLnRyaW0oKSkmJiFNcihlKT9pKFZlKGUpLHQpOmUhPW51bGwmJm8odCxlLHIpLHRoaXN9Z2V0KGUsdCl7aWYoZT1uQShlKSxlKXtsZXQgcj1nLmZpbmRLZXkodGhpcyxlKTtpZihyKXtsZXQgbj10aGlzW3JdO2lmKCF0KXJldHVybiBuO2lmKHQ9PT0hMClyZXR1cm4gSnIobik7aWYoZy5pc0Z1bmN0aW9uKHQpKXJldHVybiB0LmNhbGwodGhpcyxuLHIpO2lmKGcuaXNSZWdFeHAodCkpcmV0dXJuIHQuZXhlYyhuKTt0aHJvdyBuZXcgVHlwZUVycm9yKCJwYXJzZXIgbXVzdCBiZSBib29sZWFufHJlZ2V4cHxmdW5jdGlvbiIpfX19aGFzKGUsdCl7aWYoZT1uQShlKSxlKXtsZXQgcj1nLmZpbmRLZXkodGhpcyxlKTtyZXR1cm4hIShyJiZ0aGlzW3JdIT09dm9pZCAwJiYoIXR8fF9BKHRoaXMsdGhpc1tyXSxyLHQpKSl9cmV0dXJuITF9ZGVsZXRlKGUsdCl7bGV0IHI9dGhpcyxuPSExO2Z1bmN0aW9uIG8oaSl7aWYoaT1uQShpKSxpKXtsZXQgbD1nLmZpbmRLZXkocixpKTtsJiYoIXR8fF9BKHIscltsXSxsLHQpKSYmKGRlbGV0ZSByW2xdLG49ITApfX1yZXR1cm4gZy5pc0FycmF5KGUpP2UuZm9yRWFjaChvKTpvKGUpLG59Y2xlYXIoZSl7bGV0IHQ9T2JqZWN0LmtleXModGhpcykscj10Lmxlbmd0aCxuPSExO2Zvcig7ci0tOyl7bGV0IG89dFtyXTsoIWV8fF9BKHRoaXMsdGhpc1tvXSxvLGUsITApKSYmKGRlbGV0ZSB0aGlzW29dLG49ITApfXJldHVybiBufW5vcm1hbGl6ZShlKXtsZXQgdD10aGlzLHI9e307cmV0dXJuIGcuZm9yRWFjaCh0aGlzLChuLG8pPT57bGV0IGk9Zy5maW5kS2V5KHIsbyk7aWYoaSl7dFtpXT1EQShuKSxkZWxldGUgdFtvXTtyZXR1cm59bGV0IGw9ZT9IcihvKTpTdHJpbmcobykudHJpbSgpO2whPT1vJiZkZWxldGUgdFtvXSx0W2xdPURBKG4pLHJbbF09ITB9KSx0aGlzfWNvbmNhdCguLi5lKXtyZXR1cm4gdGhpcy5jb25zdHJ1Y3Rvci5jb25jYXQodGhpcywuLi5lKX10b0pTT04oZSl7bGV0IHQ9T2JqZWN0LmNyZWF0ZShudWxsKTtyZXR1cm4gZy5mb3JFYWNoKHRoaXMsKHIsbik9PntyIT1udWxsJiZyIT09ITEmJih0W25dPWUmJmcuaXNBcnJheShyKT9yLmpvaW4oIiwgIik6cil9KSx0fVtTeW1ib2wuaXRlcmF0b3JdKCl7cmV0dXJuIE9iamVjdC5lbnRyaWVzKHRoaXMudG9KU09OKCkpW1N5bWJvbC5pdGVyYXRvcl0oKX10b1N0cmluZygpe3JldHVybiBPYmplY3QuZW50cmllcyh0aGlzLnRvSlNPTigpKS5tYXAoKFtlLHRdKT0+ZSsiOiAiK3QpLmpvaW4oYApgKX1nZXRbU3ltYm9sLnRvU3RyaW5nVGFnXSgpe3JldHVybiJBeGlvc0hlYWRlcnMifXN0YXRpYyBmcm9tKGUpe3JldHVybiBlIGluc3RhbmNlb2YgdGhpcz9lOm5ldyB0aGlzKGUpfXN0YXRpYyBjb25jYXQoZSwuLi50KXtsZXQgcj1uZXcgdGhpcyhlKTtyZXR1cm4gdC5mb3JFYWNoKG49PnIuc2V0KG4pKSxyfXN0YXRpYyBhY2Nlc3NvcihlKXtsZXQgcj0odGhpc1tYZV09dGhpc1tYZV09e2FjY2Vzc29yczp7fX0pLmFjY2Vzc29ycyxuPXRoaXMucHJvdG90eXBlO2Z1bmN0aW9uIG8oaSl7bGV0IGw9bkEoaSk7cltsXXx8KFlyKG4saSkscltsXT0hMCl9cmV0dXJuIGcuaXNBcnJheShlKT9lLmZvckVhY2gobyk6byhlKSx0aGlzfX07di5hY2Nlc3NvcihbIkNvbnRlbnQtVHlwZSIsIkNvbnRlbnQtTGVuZ3RoIiwiQWNjZXB0IiwiQWNjZXB0LUVuY29kaW5nIiwiVXNlci1BZ2VudCIsIkF1dGhvcml6YXRpb24iXSk7Zy5yZWR1Y2VEZXNjcmlwdG9ycyh2LnByb3RvdHlwZSwoe3ZhbHVlOkF9LGUpPT57bGV0IHQ9ZVswXS50b1VwcGVyQ2FzZSgpK2Uuc2xpY2UoMSk7cmV0dXJue2dldDooKT0+QSxzZXQocil7dGhpc1t0XT1yfX19KTtnLmZyZWV6ZU1ldGhvZHModik7dmFyIGs9djtmdW5jdGlvbiBpQShBLGUpe2xldCB0PXRoaXN8fGoscj1lfHx0LG49ay5mcm9tKHIuaGVhZGVycyksbz1yLmRhdGE7cmV0dXJuIGcuZm9yRWFjaChBLGZ1bmN0aW9uKGwpe289bC5jYWxsKHQsbyxuLm5vcm1hbGl6ZSgpLGU/ZS5zdGF0dXM6dm9pZCAwKX0pLG4ubm9ybWFsaXplKCksb31mdW5jdGlvbiBhQShBKXtyZXR1cm4hIShBJiZBLl9fQ0FOQ0VMX18pfWZ1bmN0aW9uICRlKEEsZSx0KXtwLmNhbGwodGhpcyxBPz8iY2FuY2VsZWQiLHAuRVJSX0NBTkNFTEVELGUsdCksdGhpcy5uYW1lPSJDYW5jZWxlZEVycm9yIn1nLmluaGVyaXRzKCRlLHAse19fQ0FOQ0VMX186ITB9KTt2YXIgeD0kZTtmdW5jdGlvbiB6QShBLGUsdCl7bGV0IHI9dC5jb25maWcudmFsaWRhdGVTdGF0dXM7IXQuc3RhdHVzfHwhcnx8cih0LnN0YXR1cyk/QSh0KTplKG5ldyBwKCJSZXF1ZXN0IGZhaWxlZCB3aXRoIHN0YXR1cyBjb2RlICIrdC5zdGF0dXMsW3AuRVJSX0JBRF9SRVFVRVNULHAuRVJSX0JBRF9SRVNQT05TRV1bTWF0aC5mbG9vcih0LnN0YXR1cy8xMDApLTRdLHQuY29uZmlnLHQucmVxdWVzdCx0KSl9dmFyIEF0PWIuaGFzU3RhbmRhcmRCcm93c2VyRW52P3t3cml0ZShBLGUsdCxyLG4sbyl7bGV0IGk9W0ErIj0iK2VuY29kZVVSSUNvbXBvbmVudChlKV07Zy5pc051bWJlcih0KSYmaS5wdXNoKCJleHBpcmVzPSIrbmV3IERhdGUodCkudG9HTVRTdHJpbmcoKSksZy5pc1N0cmluZyhyKSYmaS5wdXNoKCJwYXRoPSIrciksZy5pc1N0cmluZyhuKSYmaS5wdXNoKCJkb21haW49IituKSxvPT09ITAmJmkucHVzaCgic2VjdXJlIiksZG9jdW1lbnQuY29va2llPWkuam9pbigiOyAiKX0scmVhZChBKXtsZXQgZT1kb2N1bWVudC5jb29raWUubWF0Y2gobmV3IFJlZ0V4cCgiKF58O1xccyopKCIrQSsiKT0oW147XSopIikpO3JldHVybiBlP2RlY29kZVVSSUNvbXBvbmVudChlWzNdKTpudWxsfSxyZW1vdmUoQSl7dGhpcy53cml0ZShBLCIiLERhdGUubm93KCktODY0ZTUpfX06e3dyaXRlKCl7fSxyZWFkKCl7cmV0dXJuIG51bGx9LHJlbW92ZSgpe319O2Z1bmN0aW9uIFpBKEEpe3JldHVybi9eKFthLXpdW2EtelxkK1wtLl0qOik/XC9cLy9pLnRlc3QoQSl9ZnVuY3Rpb24gVkEoQSxlKXtyZXR1cm4gZT9BLnJlcGxhY2UoL1wvP1wvJC8sIiIpKyIvIitlLnJlcGxhY2UoL15cLysvLCIiKTpBfWZ1bmN0aW9uIHNBKEEsZSl7cmV0dXJuIEEmJiFaQShlKT9WQShBLGUpOmV9dmFyIGV0PWIuaGFzU3RhbmRhcmRCcm93c2VyRW52P2Z1bmN0aW9uKCl7bGV0IGU9Lyhtc2llfHRyaWRlbnQpL2kudGVzdChuYXZpZ2F0b3IudXNlckFnZW50KSx0PWRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImEiKSxyO2Z1bmN0aW9uIG4obyl7bGV0IGk9bztyZXR1cm4gZSYmKHQuc2V0QXR0cmlidXRlKCJocmVmIixpKSxpPXQuaHJlZiksdC5zZXRBdHRyaWJ1dGUoImhyZWYiLGkpLHtocmVmOnQuaHJlZixwcm90b2NvbDp0LnByb3RvY29sP3QucHJvdG9jb2wucmVwbGFjZSgvOiQvLCIiKToiIixob3N0OnQuaG9zdCxzZWFyY2g6dC5zZWFyY2g/dC5zZWFyY2gucmVwbGFjZSgvXlw/LywiIik6IiIsaGFzaDp0Lmhhc2g/dC5oYXNoLnJlcGxhY2UoL14jLywiIik6IiIsaG9zdG5hbWU6dC5ob3N0bmFtZSxwb3J0OnQucG9ydCxwYXRobmFtZTp0LnBhdGhuYW1lLmNoYXJBdCgwKT09PSIvIj90LnBhdGhuYW1lOiIvIit0LnBhdGhuYW1lfX1yZXR1cm4gcj1uKHdpbmRvdy5sb2NhdGlvbi5ocmVmKSxmdW5jdGlvbihpKXtsZXQgbD1nLmlzU3RyaW5nKGkpP24oaSk6aTtyZXR1cm4gbC5wcm90b2NvbD09PXIucHJvdG9jb2wmJmwuaG9zdD09PXIuaG9zdH19KCk6ZnVuY3Rpb24oKXtyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4hMH19KCk7ZnVuY3Rpb24gWEEoQSl7bGV0IGU9L14oWy0rXHddezEsMjV9KSg6P1wvXC98OikvLmV4ZWMoQSk7cmV0dXJuIGUmJmVbMV18fCIifWZ1bmN0aW9uIHFyKEEsZSl7QT1BfHwxMDtsZXQgdD1uZXcgQXJyYXkoQSkscj1uZXcgQXJyYXkoQSksbj0wLG89MCxpO3JldHVybiBlPWUhPT12b2lkIDA/ZToxZTMsZnVuY3Rpb24odSl7bGV0IEI9RGF0ZS5ub3coKSxzPXJbb107aXx8KGk9QiksdFtuXT11LHJbbl09QjtsZXQgYT1vLGM9MDtmb3IoO2EhPT1uOyljKz10W2ErK10sYT1hJUE7aWYobj0obisxKSVBLG49PT1vJiYobz0obysxKSVBKSxCLWk8ZSlyZXR1cm47bGV0IEk9cyYmQi1zO3JldHVybiBJP01hdGgucm91bmQoYyoxZTMvSSk6dm9pZCAwfX12YXIgdHQ9cXI7ZnVuY3Rpb24gcnQoQSxlKXtsZXQgdD0wLHI9dHQoNTAsMjUwKTtyZXR1cm4gbj0+e2xldCBvPW4ubG9hZGVkLGk9bi5sZW5ndGhDb21wdXRhYmxlP24udG90YWw6dm9pZCAwLGw9by10LHU9cihsKSxCPW88PWk7dD1vO2xldCBzPXtsb2FkZWQ6byx0b3RhbDppLHByb2dyZXNzOmk/by9pOnZvaWQgMCxieXRlczpsLHJhdGU6dXx8dm9pZCAwLGVzdGltYXRlZDp1JiZpJiZCPyhpLW8pL3U6dm9pZCAwLGV2ZW50Om59O3NbZT8iZG93bmxvYWQiOiJ1cGxvYWQiXT0hMCxBKHMpfX12YXIgS3I9dHlwZW9mIFhNTEh0dHBSZXF1ZXN0PCJ1IixvdD1LciYmZnVuY3Rpb24oQSl7cmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKHQscil7bGV0IG49QS5kYXRhLG89ay5mcm9tKEEuaGVhZGVycykubm9ybWFsaXplKCkse3Jlc3BvbnNlVHlwZTppLHdpdGhYU1JGVG9rZW46bH09QSx1O2Z1bmN0aW9uIEIoKXtBLmNhbmNlbFRva2VuJiZBLmNhbmNlbFRva2VuLnVuc3Vic2NyaWJlKHUpLEEuc2lnbmFsJiZBLnNpZ25hbC5yZW1vdmVFdmVudExpc3RlbmVyKCJhYm9ydCIsdSl9bGV0IHM7aWYoZy5pc0Zvcm1EYXRhKG4pKXtpZihiLmhhc1N0YW5kYXJkQnJvd3NlckVudnx8Yi5oYXNTdGFuZGFyZEJyb3dzZXJXZWJXb3JrZXJFbnYpby5zZXRDb250ZW50VHlwZSghMSk7ZWxzZSBpZigocz1vLmdldENvbnRlbnRUeXBlKCkpIT09ITEpe2xldFtmLC4uLlFdPXM/cy5zcGxpdCgiOyIpLm1hcChtPT5tLnRyaW0oKSkuZmlsdGVyKEJvb2xlYW4pOltdO28uc2V0Q29udGVudFR5cGUoW2Z8fCJtdWx0aXBhcnQvZm9ybS1kYXRhIiwuLi5RXS5qb2luKCI7ICIpKX19bGV0IGE9bmV3IFhNTEh0dHBSZXF1ZXN0O2lmKEEuYXV0aCl7bGV0IGY9QS5hdXRoLnVzZXJuYW1lfHwiIixRPUEuYXV0aC5wYXNzd29yZD91bmVzY2FwZShlbmNvZGVVUklDb21wb25lbnQoQS5hdXRoLnBhc3N3b3JkKSk6IiI7by5zZXQoIkF1dGhvcml6YXRpb24iLCJCYXNpYyAiK2J0b2EoZisiOiIrUSkpfWxldCBjPXNBKEEuYmFzZVVSTCxBLnVybCk7YS5vcGVuKEEubWV0aG9kLnRvVXBwZXJDYXNlKCksb0EoYyxBLnBhcmFtcyxBLnBhcmFtc1NlcmlhbGl6ZXIpLCEwKSxhLnRpbWVvdXQ9QS50aW1lb3V0O2Z1bmN0aW9uIEkoKXtpZighYSlyZXR1cm47bGV0IGY9ay5mcm9tKCJnZXRBbGxSZXNwb25zZUhlYWRlcnMiaW4gYSYmYS5nZXRBbGxSZXNwb25zZUhlYWRlcnMoKSksbT17ZGF0YTohaXx8aT09PSJ0ZXh0Inx8aT09PSJqc29uIj9hLnJlc3BvbnNlVGV4dDphLnJlc3BvbnNlLHN0YXR1czphLnN0YXR1cyxzdGF0dXNUZXh0OmEuc3RhdHVzVGV4dCxoZWFkZXJzOmYsY29uZmlnOkEscmVxdWVzdDphfTt6QShmdW5jdGlvbihOKXt0KE4pLEIoKX0sZnVuY3Rpb24oTil7cihOKSxCKCl9LG0pLGE9bnVsbH1pZigib25sb2FkZW5kImluIGE/YS5vbmxvYWRlbmQ9STphLm9ucmVhZHlzdGF0ZWNoYW5nZT1mdW5jdGlvbigpeyFhfHxhLnJlYWR5U3RhdGUhPT00fHxhLnN0YXR1cz09PTAmJiEoYS5yZXNwb25zZVVSTCYmYS5yZXNwb25zZVVSTC5pbmRleE9mKCJmaWxlOiIpPT09MCl8fHNldFRpbWVvdXQoSSl9LGEub25hYm9ydD1mdW5jdGlvbigpe2EmJihyKG5ldyBwKCJSZXF1ZXN0IGFib3J0ZWQiLHAuRUNPTk5BQk9SVEVELEEsYSkpLGE9bnVsbCl9LGEub25lcnJvcj1mdW5jdGlvbigpe3IobmV3IHAoIk5ldHdvcmsgRXJyb3IiLHAuRVJSX05FVFdPUkssQSxhKSksYT1udWxsfSxhLm9udGltZW91dD1mdW5jdGlvbigpe2xldCBRPUEudGltZW91dD8idGltZW91dCBvZiAiK0EudGltZW91dCsibXMgZXhjZWVkZWQiOiJ0aW1lb3V0IGV4Y2VlZGVkIixtPUEudHJhbnNpdGlvbmFsfHxoQTtBLnRpbWVvdXRFcnJvck1lc3NhZ2UmJihRPUEudGltZW91dEVycm9yTWVzc2FnZSkscihuZXcgcChRLG0uY2xhcmlmeVRpbWVvdXRFcnJvcj9wLkVUSU1FRE9VVDpwLkVDT05OQUJPUlRFRCxBLGEpKSxhPW51bGx9LGIuaGFzU3RhbmRhcmRCcm93c2VyRW52JiYobCYmZy5pc0Z1bmN0aW9uKGwpJiYobD1sKEEpKSxsfHxsIT09ITEmJmV0KGMpKSl7bGV0IGY9QS54c3JmSGVhZGVyTmFtZSYmQS54c3JmQ29va2llTmFtZSYmQXQucmVhZChBLnhzcmZDb29raWVOYW1lKTtmJiZvLnNldChBLnhzcmZIZWFkZXJOYW1lLGYpfW49PT12b2lkIDAmJm8uc2V0Q29udGVudFR5cGUobnVsbCksInNldFJlcXVlc3RIZWFkZXIiaW4gYSYmZy5mb3JFYWNoKG8udG9KU09OKCksZnVuY3Rpb24oUSxtKXthLnNldFJlcXVlc3RIZWFkZXIobSxRKX0pLGcuaXNVbmRlZmluZWQoQS53aXRoQ3JlZGVudGlhbHMpfHwoYS53aXRoQ3JlZGVudGlhbHM9ISFBLndpdGhDcmVkZW50aWFscyksaSYmaSE9PSJqc29uIiYmKGEucmVzcG9uc2VUeXBlPUEucmVzcG9uc2VUeXBlKSx0eXBlb2YgQS5vbkRvd25sb2FkUHJvZ3Jlc3M9PSJmdW5jdGlvbiImJmEuYWRkRXZlbnRMaXN0ZW5lcigicHJvZ3Jlc3MiLHJ0KEEub25Eb3dubG9hZFByb2dyZXNzLCEwKSksdHlwZW9mIEEub25VcGxvYWRQcm9ncmVzcz09ImZ1bmN0aW9uIiYmYS51cGxvYWQmJmEudXBsb2FkLmFkZEV2ZW50TGlzdGVuZXIoInByb2dyZXNzIixydChBLm9uVXBsb2FkUHJvZ3Jlc3MpKSwoQS5jYW5jZWxUb2tlbnx8QS5zaWduYWwpJiYodT1mPT57YSYmKHIoIWZ8fGYudHlwZT9uZXcgeChudWxsLEEsYSk6ZiksYS5hYm9ydCgpLGE9bnVsbCl9LEEuY2FuY2VsVG9rZW4mJkEuY2FuY2VsVG9rZW4uc3Vic2NyaWJlKHUpLEEuc2lnbmFsJiYoQS5zaWduYWwuYWJvcnRlZD91KCk6QS5zaWduYWwuYWRkRXZlbnRMaXN0ZW5lcigiYWJvcnQiLHUpKSk7bGV0IEM9WEEoYyk7aWYoQyYmYi5wcm90b2NvbHMuaW5kZXhPZihDKT09PS0xKXtyKG5ldyBwKCJVbnN1cHBvcnRlZCBwcm90b2NvbCAiK0MrIjoiLHAuRVJSX0JBRF9SRVFVRVNULEEpKTtyZXR1cm59YS5zZW5kKG58fG51bGwpfSl9O3ZhciAkQT17aHR0cDpkQSx4aHI6b3R9O2cuZm9yRWFjaCgkQSwoQSxlKT0+e2lmKEEpe3RyeXtPYmplY3QuZGVmaW5lUHJvcGVydHkoQSwibmFtZSIse3ZhbHVlOmV9KX1jYXRjaHt9T2JqZWN0LmRlZmluZVByb3BlcnR5KEEsImFkYXB0ZXJOYW1lIix7dmFsdWU6ZX0pfX0pO3ZhciBudD1BPT5gLSAke0F9YCxqcj1BPT5nLmlzRnVuY3Rpb24oQSl8fEE9PT1udWxsfHxBPT09ITEsU0E9e2dldEFkYXB0ZXI6QT0+e0E9Zy5pc0FycmF5KEEpP0E6W0FdO2xldHtsZW5ndGg6ZX09QSx0LHIsbj17fTtmb3IobGV0IG89MDtvPGU7bysrKXt0PUFbb107bGV0IGk7aWYocj10LCFqcih0KSYmKHI9JEFbKGk9U3RyaW5nKHQpKS50b0xvd2VyQ2FzZSgpXSxyPT09dm9pZCAwKSl0aHJvdyBuZXcgcChgVW5rbm93biBhZGFwdGVyICcke2l9J2ApO2lmKHIpYnJlYWs7bltpfHwiIyIrb109cn1pZighcil7bGV0IG89T2JqZWN0LmVudHJpZXMobikubWFwKChbbCx1XSk9PmBhZGFwdGVyICR7bH0gYCsodT09PSExPyJpcyBub3Qgc3VwcG9ydGVkIGJ5IHRoZSBlbnZpcm9ubWVudCI6ImlzIG5vdCBhdmFpbGFibGUgaW4gdGhlIGJ1aWxkIikpLGk9ZT9vLmxlbmd0aD4xP2BzaW5jZSA6CmArby5tYXAobnQpLmpvaW4oYApgKToiICIrbnQob1swXSk6ImFzIG5vIGFkYXB0ZXIgc3BlY2lmaWVkIjt0aHJvdyBuZXcgcCgiVGhlcmUgaXMgbm8gc3VpdGFibGUgYWRhcHRlciB0byBkaXNwYXRjaCB0aGUgcmVxdWVzdCAiK2ksIkVSUl9OT1RfU1VQUE9SVCIpfXJldHVybiByfSxhZGFwdGVyczokQX07ZnVuY3Rpb24gQWUoQSl7aWYoQS5jYW5jZWxUb2tlbiYmQS5jYW5jZWxUb2tlbi50aHJvd0lmUmVxdWVzdGVkKCksQS5zaWduYWwmJkEuc2lnbmFsLmFib3J0ZWQpdGhyb3cgbmV3IHgobnVsbCxBKX1mdW5jdGlvbiBSQShBKXtyZXR1cm4gQWUoQSksQS5oZWFkZXJzPWsuZnJvbShBLmhlYWRlcnMpLEEuZGF0YT1pQS5jYWxsKEEsQS50cmFuc2Zvcm1SZXF1ZXN0KSxbInBvc3QiLCJwdXQiLCJwYXRjaCJdLmluZGV4T2YoQS5tZXRob2QpIT09LTEmJkEuaGVhZGVycy5zZXRDb250ZW50VHlwZSgiYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkIiwhMSksU0EuZ2V0QWRhcHRlcihBLmFkYXB0ZXJ8fGouYWRhcHRlcikoQSkudGhlbihmdW5jdGlvbihyKXtyZXR1cm4gQWUoQSksci5kYXRhPWlBLmNhbGwoQSxBLnRyYW5zZm9ybVJlc3BvbnNlLHIpLHIuaGVhZGVycz1rLmZyb20oci5oZWFkZXJzKSxyfSxmdW5jdGlvbihyKXtyZXR1cm4gYUEocil8fChBZShBKSxyJiZyLnJlc3BvbnNlJiYoci5yZXNwb25zZS5kYXRhPWlBLmNhbGwoQSxBLnRyYW5zZm9ybVJlc3BvbnNlLHIucmVzcG9uc2UpLHIucmVzcG9uc2UuaGVhZGVycz1rLmZyb20oci5yZXNwb25zZS5oZWFkZXJzKSkpLFByb21pc2UucmVqZWN0KHIpfSl9dmFyIGl0PUE9PkEgaW5zdGFuY2VvZiBrP3suLi5BfTpBO2Z1bmN0aW9uIEcoQSxlKXtlPWV8fHt9O2xldCB0PXt9O2Z1bmN0aW9uIHIoQixzLGEpe3JldHVybiBnLmlzUGxhaW5PYmplY3QoQikmJmcuaXNQbGFpbk9iamVjdChzKT9nLm1lcmdlLmNhbGwoe2Nhc2VsZXNzOmF9LEIscyk6Zy5pc1BsYWluT2JqZWN0KHMpP2cubWVyZ2Uoe30scyk6Zy5pc0FycmF5KHMpP3Muc2xpY2UoKTpzfWZ1bmN0aW9uIG4oQixzLGEpe2lmKGcuaXNVbmRlZmluZWQocykpe2lmKCFnLmlzVW5kZWZpbmVkKEIpKXJldHVybiByKHZvaWQgMCxCLGEpfWVsc2UgcmV0dXJuIHIoQixzLGEpfWZ1bmN0aW9uIG8oQixzKXtpZighZy5pc1VuZGVmaW5lZChzKSlyZXR1cm4gcih2b2lkIDAscyl9ZnVuY3Rpb24gaShCLHMpe2lmKGcuaXNVbmRlZmluZWQocykpe2lmKCFnLmlzVW5kZWZpbmVkKEIpKXJldHVybiByKHZvaWQgMCxCKX1lbHNlIHJldHVybiByKHZvaWQgMCxzKX1mdW5jdGlvbiBsKEIscyxhKXtpZihhIGluIGUpcmV0dXJuIHIoQixzKTtpZihhIGluIEEpcmV0dXJuIHIodm9pZCAwLEIpfWxldCB1PXt1cmw6byxtZXRob2Q6byxkYXRhOm8sYmFzZVVSTDppLHRyYW5zZm9ybVJlcXVlc3Q6aSx0cmFuc2Zvcm1SZXNwb25zZTppLHBhcmFtc1NlcmlhbGl6ZXI6aSx0aW1lb3V0OmksdGltZW91dE1lc3NhZ2U6aSx3aXRoQ3JlZGVudGlhbHM6aSx3aXRoWFNSRlRva2VuOmksYWRhcHRlcjppLHJlc3BvbnNlVHlwZTppLHhzcmZDb29raWVOYW1lOmkseHNyZkhlYWRlck5hbWU6aSxvblVwbG9hZFByb2dyZXNzOmksb25Eb3dubG9hZFByb2dyZXNzOmksZGVjb21wcmVzczppLG1heENvbnRlbnRMZW5ndGg6aSxtYXhCb2R5TGVuZ3RoOmksYmVmb3JlUmVkaXJlY3Q6aSx0cmFuc3BvcnQ6aSxodHRwQWdlbnQ6aSxodHRwc0FnZW50OmksY2FuY2VsVG9rZW46aSxzb2NrZXRQYXRoOmkscmVzcG9uc2VFbmNvZGluZzppLHZhbGlkYXRlU3RhdHVzOmwsaGVhZGVyczooQixzKT0+bihpdChCKSxpdChzKSwhMCl9O3JldHVybiBnLmZvckVhY2goT2JqZWN0LmtleXMoT2JqZWN0LmFzc2lnbih7fSxBLGUpKSxmdW5jdGlvbihzKXtsZXQgYT11W3NdfHxuLGM9YShBW3NdLGVbc10scyk7Zy5pc1VuZGVmaW5lZChjKSYmYSE9PWx8fCh0W3NdPWMpfSksdH12YXIgYkE9IjEuNi44Ijt2YXIgZWU9e307WyJvYmplY3QiLCJib29sZWFuIiwibnVtYmVyIiwiZnVuY3Rpb24iLCJzdHJpbmciLCJzeW1ib2wiXS5mb3JFYWNoKChBLGUpPT57ZWVbQV09ZnVuY3Rpb24ocil7cmV0dXJuIHR5cGVvZiByPT09QXx8ImEiKyhlPDE/Im4gIjoiICIpK0F9fSk7dmFyIGF0PXt9O2VlLnRyYW5zaXRpb25hbD1mdW5jdGlvbihlLHQscil7ZnVuY3Rpb24gbihvLGkpe3JldHVybiJbQXhpb3MgdiIrYkErIl0gVHJhbnNpdGlvbmFsIG9wdGlvbiAnIitvKyInIitpKyhyPyIuICIrcjoiIil9cmV0dXJuKG8saSxsKT0+e2lmKGU9PT0hMSl0aHJvdyBuZXcgcChuKGksIiBoYXMgYmVlbiByZW1vdmVkIisodD8iIGluICIrdDoiIikpLHAuRVJSX0RFUFJFQ0FURUQpO3JldHVybiB0JiYhYXRbaV0mJihhdFtpXT0hMCxjb25zb2xlLndhcm4obihpLCIgaGFzIGJlZW4gZGVwcmVjYXRlZCBzaW5jZSB2Iit0KyIgYW5kIHdpbGwgYmUgcmVtb3ZlZCBpbiB0aGUgbmVhciBmdXR1cmUiKSkpLGU/ZShvLGksbCk6ITB9fTtmdW5jdGlvbiB2cihBLGUsdCl7aWYodHlwZW9mIEEhPSJvYmplY3QiKXRocm93IG5ldyBwKCJvcHRpb25zIG11c3QgYmUgYW4gb2JqZWN0IixwLkVSUl9CQURfT1BUSU9OX1ZBTFVFKTtsZXQgcj1PYmplY3Qua2V5cyhBKSxuPXIubGVuZ3RoO2Zvcig7bi0tID4wOyl7bGV0IG89cltuXSxpPWVbb107aWYoaSl7bGV0IGw9QVtvXSx1PWw9PT12b2lkIDB8fGkobCxvLEEpO2lmKHUhPT0hMCl0aHJvdyBuZXcgcCgib3B0aW9uICIrbysiIG11c3QgYmUgIit1LHAuRVJSX0JBRF9PUFRJT05fVkFMVUUpO2NvbnRpbnVlfWlmKHQhPT0hMCl0aHJvdyBuZXcgcCgiVW5rbm93biBvcHRpb24gIitvLHAuRVJSX0JBRF9PUFRJT04pfX12YXIga0E9e2Fzc2VydE9wdGlvbnM6dnIsdmFsaWRhdG9yczplZX07dmFyIFc9a0EudmFsaWRhdG9ycyxfPWNsYXNze2NvbnN0cnVjdG9yKGUpe3RoaXMuZGVmYXVsdHM9ZSx0aGlzLmludGVyY2VwdG9ycz17cmVxdWVzdDpuZXcgcUEscmVzcG9uc2U6bmV3IHFBfX1hc3luYyByZXF1ZXN0KGUsdCl7dHJ5e3JldHVybiBhd2FpdCB0aGlzLl9yZXF1ZXN0KGUsdCl9Y2F0Y2gocil7aWYociBpbnN0YW5jZW9mIEVycm9yKXtsZXQgbjtFcnJvci5jYXB0dXJlU3RhY2tUcmFjZT9FcnJvci5jYXB0dXJlU3RhY2tUcmFjZShuPXt9KTpuPW5ldyBFcnJvcjtsZXQgbz1uLnN0YWNrP24uc3RhY2sucmVwbGFjZSgvXi4rXG4vLCIiKToiIjtyLnN0YWNrP28mJiFTdHJpbmcoci5zdGFjaykuZW5kc1dpdGgoby5yZXBsYWNlKC9eLitcbi4rXG4vLCIiKSkmJihyLnN0YWNrKz1gCmArbyk6ci5zdGFjaz1vfXRocm93IHJ9fV9yZXF1ZXN0KGUsdCl7dHlwZW9mIGU9PSJzdHJpbmciPyh0PXR8fHt9LHQudXJsPWUpOnQ9ZXx8e30sdD1HKHRoaXMuZGVmYXVsdHMsdCk7bGV0e3RyYW5zaXRpb25hbDpyLHBhcmFtc1NlcmlhbGl6ZXI6bixoZWFkZXJzOm99PXQ7ciE9PXZvaWQgMCYma0EuYXNzZXJ0T3B0aW9ucyhyLHtzaWxlbnRKU09OUGFyc2luZzpXLnRyYW5zaXRpb25hbChXLmJvb2xlYW4pLGZvcmNlZEpTT05QYXJzaW5nOlcudHJhbnNpdGlvbmFsKFcuYm9vbGVhbiksY2xhcmlmeVRpbWVvdXRFcnJvcjpXLnRyYW5zaXRpb25hbChXLmJvb2xlYW4pfSwhMSksbiE9bnVsbCYmKGcuaXNGdW5jdGlvbihuKT90LnBhcmFtc1NlcmlhbGl6ZXI9e3NlcmlhbGl6ZTpufTprQS5hc3NlcnRPcHRpb25zKG4se2VuY29kZTpXLmZ1bmN0aW9uLHNlcmlhbGl6ZTpXLmZ1bmN0aW9ufSwhMCkpLHQubWV0aG9kPSh0Lm1ldGhvZHx8dGhpcy5kZWZhdWx0cy5tZXRob2R8fCJnZXQiKS50b0xvd2VyQ2FzZSgpO2xldCBpPW8mJmcubWVyZ2Uoby5jb21tb24sb1t0Lm1ldGhvZF0pO28mJmcuZm9yRWFjaChbImRlbGV0ZSIsImdldCIsImhlYWQiLCJwb3N0IiwicHV0IiwicGF0Y2giLCJjb21tb24iXSxDPT57ZGVsZXRlIG9bQ119KSx0LmhlYWRlcnM9ay5jb25jYXQoaSxvKTtsZXQgbD1bXSx1PSEwO3RoaXMuaW50ZXJjZXB0b3JzLnJlcXVlc3QuZm9yRWFjaChmdW5jdGlvbihmKXt0eXBlb2YgZi5ydW5XaGVuPT0iZnVuY3Rpb24iJiZmLnJ1bldoZW4odCk9PT0hMXx8KHU9dSYmZi5zeW5jaHJvbm91cyxsLnVuc2hpZnQoZi5mdWxmaWxsZWQsZi5yZWplY3RlZCkpfSk7bGV0IEI9W107dGhpcy5pbnRlcmNlcHRvcnMucmVzcG9uc2UuZm9yRWFjaChmdW5jdGlvbihmKXtCLnB1c2goZi5mdWxmaWxsZWQsZi5yZWplY3RlZCl9KTtsZXQgcyxhPTAsYztpZighdSl7bGV0IEM9W1JBLmJpbmQodGhpcyksdm9pZCAwXTtmb3IoQy51bnNoaWZ0LmFwcGx5KEMsbCksQy5wdXNoLmFwcGx5KEMsQiksYz1DLmxlbmd0aCxzPVByb21pc2UucmVzb2x2ZSh0KTthPGM7KXM9cy50aGVuKENbYSsrXSxDW2ErK10pO3JldHVybiBzfWM9bC5sZW5ndGg7bGV0IEk9dDtmb3IoYT0wO2E8Yzspe2xldCBDPWxbYSsrXSxmPWxbYSsrXTt0cnl7ST1DKEkpfWNhdGNoKFEpe2YuY2FsbCh0aGlzLFEpO2JyZWFrfX10cnl7cz1SQS5jYWxsKHRoaXMsSSl9Y2F0Y2goQyl7cmV0dXJuIFByb21pc2UucmVqZWN0KEMpfWZvcihhPTAsYz1CLmxlbmd0aDthPGM7KXM9cy50aGVuKEJbYSsrXSxCW2ErK10pO3JldHVybiBzfWdldFVyaShlKXtlPUcodGhpcy5kZWZhdWx0cyxlKTtsZXQgdD1zQShlLmJhc2VVUkwsZS51cmwpO3JldHVybiBvQSh0LGUucGFyYW1zLGUucGFyYW1zU2VyaWFsaXplcil9fTtnLmZvckVhY2goWyJkZWxldGUiLCJnZXQiLCJoZWFkIiwib3B0aW9ucyJdLGZ1bmN0aW9uKGUpe18ucHJvdG90eXBlW2VdPWZ1bmN0aW9uKHQscil7cmV0dXJuIHRoaXMucmVxdWVzdChHKHJ8fHt9LHttZXRob2Q6ZSx1cmw6dCxkYXRhOihyfHx7fSkuZGF0YX0pKX19KTtnLmZvckVhY2goWyJwb3N0IiwicHV0IiwicGF0Y2giXSxmdW5jdGlvbihlKXtmdW5jdGlvbiB0KHIpe3JldHVybiBmdW5jdGlvbihvLGksbCl7cmV0dXJuIHRoaXMucmVxdWVzdChHKGx8fHt9LHttZXRob2Q6ZSxoZWFkZXJzOnI/eyJDb250ZW50LVR5cGUiOiJtdWx0aXBhcnQvZm9ybS1kYXRhIn06e30sdXJsOm8sZGF0YTppfSkpfX1fLnByb3RvdHlwZVtlXT10KCksXy5wcm90b3R5cGVbZSsiRm9ybSJdPXQoITApfSk7dmFyIElBPV87dmFyIHRlPWNsYXNzIEF7Y29uc3RydWN0b3IoZSl7aWYodHlwZW9mIGUhPSJmdW5jdGlvbiIpdGhyb3cgbmV3IFR5cGVFcnJvcigiZXhlY3V0b3IgbXVzdCBiZSBhIGZ1bmN0aW9uLiIpO2xldCB0O3RoaXMucHJvbWlzZT1uZXcgUHJvbWlzZShmdW5jdGlvbihvKXt0PW99KTtsZXQgcj10aGlzO3RoaXMucHJvbWlzZS50aGVuKG49PntpZighci5fbGlzdGVuZXJzKXJldHVybjtsZXQgbz1yLl9saXN0ZW5lcnMubGVuZ3RoO2Zvcig7by0tID4wOylyLl9saXN0ZW5lcnNbb10obik7ci5fbGlzdGVuZXJzPW51bGx9KSx0aGlzLnByb21pc2UudGhlbj1uPT57bGV0IG8saT1uZXcgUHJvbWlzZShsPT57ci5zdWJzY3JpYmUobCksbz1sfSkudGhlbihuKTtyZXR1cm4gaS5jYW5jZWw9ZnVuY3Rpb24oKXtyLnVuc3Vic2NyaWJlKG8pfSxpfSxlKGZ1bmN0aW9uKG8saSxsKXtyLnJlYXNvbnx8KHIucmVhc29uPW5ldyB4KG8saSxsKSx0KHIucmVhc29uKSl9KX10aHJvd0lmUmVxdWVzdGVkKCl7aWYodGhpcy5yZWFzb24pdGhyb3cgdGhpcy5yZWFzb259c3Vic2NyaWJlKGUpe2lmKHRoaXMucmVhc29uKXtlKHRoaXMucmVhc29uKTtyZXR1cm59dGhpcy5fbGlzdGVuZXJzP3RoaXMuX2xpc3RlbmVycy5wdXNoKGUpOnRoaXMuX2xpc3RlbmVycz1bZV19dW5zdWJzY3JpYmUoZSl7aWYoIXRoaXMuX2xpc3RlbmVycylyZXR1cm47bGV0IHQ9dGhpcy5fbGlzdGVuZXJzLmluZGV4T2YoZSk7dCE9PS0xJiZ0aGlzLl9saXN0ZW5lcnMuc3BsaWNlKHQsMSl9c3RhdGljIHNvdXJjZSgpe2xldCBlO3JldHVybnt0b2tlbjpuZXcgQShmdW5jdGlvbihuKXtlPW59KSxjYW5jZWw6ZX19fSxzdD10ZTtmdW5jdGlvbiByZShBKXtyZXR1cm4gZnVuY3Rpb24odCl7cmV0dXJuIEEuYXBwbHkobnVsbCx0KX19ZnVuY3Rpb24gb2UoQSl7cmV0dXJuIGcuaXNPYmplY3QoQSkmJkEuaXNBeGlvc0Vycm9yPT09ITB9dmFyIG5lPXtDb250aW51ZToxMDAsU3dpdGNoaW5nUHJvdG9jb2xzOjEwMSxQcm9jZXNzaW5nOjEwMixFYXJseUhpbnRzOjEwMyxPazoyMDAsQ3JlYXRlZDoyMDEsQWNjZXB0ZWQ6MjAyLE5vbkF1dGhvcml0YXRpdmVJbmZvcm1hdGlvbjoyMDMsTm9Db250ZW50OjIwNCxSZXNldENvbnRlbnQ6MjA1LFBhcnRpYWxDb250ZW50OjIwNixNdWx0aVN0YXR1czoyMDcsQWxyZWFkeVJlcG9ydGVkOjIwOCxJbVVzZWQ6MjI2LE11bHRpcGxlQ2hvaWNlczozMDAsTW92ZWRQZXJtYW5lbnRseTozMDEsRm91bmQ6MzAyLFNlZU90aGVyOjMwMyxOb3RNb2RpZmllZDozMDQsVXNlUHJveHk6MzA1LFVudXNlZDozMDYsVGVtcG9yYXJ5UmVkaXJlY3Q6MzA3LFBlcm1hbmVudFJlZGlyZWN0OjMwOCxCYWRSZXF1ZXN0OjQwMCxVbmF1dGhvcml6ZWQ6NDAxLFBheW1lbnRSZXF1aXJlZDo0MDIsRm9yYmlkZGVuOjQwMyxOb3RGb3VuZDo0MDQsTWV0aG9kTm90QWxsb3dlZDo0MDUsTm90QWNjZXB0YWJsZTo0MDYsUHJveHlBdXRoZW50aWNhdGlvblJlcXVpcmVkOjQwNyxSZXF1ZXN0VGltZW91dDo0MDgsQ29uZmxpY3Q6NDA5LEdvbmU6NDEwLExlbmd0aFJlcXVpcmVkOjQxMSxQcmVjb25kaXRpb25GYWlsZWQ6NDEyLFBheWxvYWRUb29MYXJnZTo0MTMsVXJpVG9vTG9uZzo0MTQsVW5zdXBwb3J0ZWRNZWRpYVR5cGU6NDE1LFJhbmdlTm90U2F0aXNmaWFibGU6NDE2LEV4cGVjdGF0aW9uRmFpbGVkOjQxNyxJbUFUZWFwb3Q6NDE4LE1pc2RpcmVjdGVkUmVxdWVzdDo0MjEsVW5wcm9jZXNzYWJsZUVudGl0eTo0MjIsTG9ja2VkOjQyMyxGYWlsZWREZXBlbmRlbmN5OjQyNCxUb29FYXJseTo0MjUsVXBncmFkZVJlcXVpcmVkOjQyNixQcmVjb25kaXRpb25SZXF1aXJlZDo0MjgsVG9vTWFueVJlcXVlc3RzOjQyOSxSZXF1ZXN0SGVhZGVyRmllbGRzVG9vTGFyZ2U6NDMxLFVuYXZhaWxhYmxlRm9yTGVnYWxSZWFzb25zOjQ1MSxJbnRlcm5hbFNlcnZlckVycm9yOjUwMCxOb3RJbXBsZW1lbnRlZDo1MDEsQmFkR2F0ZXdheTo1MDIsU2VydmljZVVuYXZhaWxhYmxlOjUwMyxHYXRld2F5VGltZW91dDo1MDQsSHR0cFZlcnNpb25Ob3RTdXBwb3J0ZWQ6NTA1LFZhcmlhbnRBbHNvTmVnb3RpYXRlczo1MDYsSW5zdWZmaWNpZW50U3RvcmFnZTo1MDcsTG9vcERldGVjdGVkOjUwOCxOb3RFeHRlbmRlZDo1MTAsTmV0d29ya0F1dGhlbnRpY2F0aW9uUmVxdWlyZWQ6NTExfTtPYmplY3QuZW50cmllcyhuZSkuZm9yRWFjaCgoW0EsZV0pPT57bmVbZV09QX0pO3ZhciBJdD1uZTtmdW5jdGlvbiBndChBKXtsZXQgZT1uZXcgSUEoQSksdD1lQShJQS5wcm90b3R5cGUucmVxdWVzdCxlKTtyZXR1cm4gZy5leHRlbmQodCxJQS5wcm90b3R5cGUsZSx7YWxsT3duS2V5czohMH0pLGcuZXh0ZW5kKHQsZSxudWxsLHthbGxPd25LZXlzOiEwfSksdC5jcmVhdGU9ZnVuY3Rpb24obil7cmV0dXJuIGd0KEcoQSxuKSl9LHR9dmFyIEQ9Z3Qoaik7RC5BeGlvcz1JQTtELkNhbmNlbGVkRXJyb3I9eDtELkNhbmNlbFRva2VuPXN0O0QuaXNDYW5jZWw9YUE7RC5WRVJTSU9OPWJBO0QudG9Gb3JtRGF0YT1PO0QuQXhpb3NFcnJvcj1wO0QuQ2FuY2VsPUQuQ2FuY2VsZWRFcnJvcjtELmFsbD1mdW5jdGlvbihlKXtyZXR1cm4gUHJvbWlzZS5hbGwoZSl9O0Quc3ByZWFkPXJlO0QuaXNBeGlvc0Vycm9yPW9lO0QubWVyZ2VDb25maWc9RztELkF4aW9zSGVhZGVycz1rO0QuZm9ybVRvSlNPTj1BPT53QShnLmlzSFRNTEZvcm0oQSk/bmV3IEZvcm1EYXRhKEEpOkEpO0QuZ2V0QWRhcHRlcj1TQS5nZXRBZGFwdGVyO0QuSHR0cFN0YXR1c0NvZGU9SXQ7RC5kZWZhdWx0PUQ7dmFyIHo9RDt2YXJ7QXhpb3M6a2EsQXhpb3NFcnJvcjpGYSxDYW5jZWxlZEVycm9yOlVhLGlzQ2FuY2VsOk5hLENhbmNlbFRva2VuOlRhLFZFUlNJT046TGEsYWxsOlBhLENhbmNlbDpHYSxpc0F4aW9zRXJyb3I6T2Esc3ByZWFkOnhhLHRvRm9ybURhdGE6V2EsQXhpb3NIZWFkZXJzOkphLEh0dHBTdGF0dXNDb2RlOk1hLGZvcm1Ub0pTT046SGEsZ2V0QWRhcHRlcjpZYSxtZXJnZUNvbmZpZzpxYX09ejthc3luYyBmdW5jdGlvbiBfcihBLGUpe2xldCB0PUEscj1udWxsO2lmKHQ9PW51bGwpcj1uZXcgV29ya2VyKG5ldyBVUkwoIi4vd2ViLXdvcmtlcnMvaXRrLXdhc20tcGlwZWxpbmUud29ya2VyLmpzIixpbXBvcnQubWV0YS51cmwpLHt0eXBlOiJtb2R1bGUifSk7ZWxzZSBpZih0LnN0YXJ0c1dpdGgoImh0dHAiKSl7bGV0IG49YXdhaXQgei5nZXQodCx7cmVzcG9uc2VUeXBlOiJibG9iIixwYXJhbXM6ZX0pLG89VVJMLmNyZWF0ZU9iamVjdFVSTChuLmRhdGEpO3I9bmV3IFdvcmtlcihvLHt0eXBlOiJtb2R1bGUifSl9ZWxzZSByPW5ldyBXb3JrZXIodCx7dHlwZToibW9kdWxlIn0pO3JldHVybiByfXZhciBnQT1fcjtmdW5jdGlvbiBsdChBKXtsZXQgZT1PQShBKSx0PUE7cmV0dXJuIHQudGVybWluYXRlZD0hMSx0LndvcmtlclByb3h5PWUsdC5vcmlnaW5hbFRlcm1pbmF0ZT10LnRlcm1pbmF0ZSx0LnRlcm1pbmF0ZT0oKT0+e3QudGVybWluYXRlZD0hMCx0LndvcmtlclByb3h5W0dBXSgpLHQub3JpZ2luYWxUZXJtaW5hdGUoKX0se3dvcmtlclByb3h5OmUsd29ya2VyOnR9fWFzeW5jIGZ1bmN0aW9uIHpyKEEsZSx0KXtsZXQgcjtpZihBIT1udWxsKXtsZXQgbz1BO3JldHVybiBvLndvcmtlclByb3h5IT09dm9pZCAwPyhyPW8ud29ya2VyUHJveHkse3dvcmtlclByb3h5OnIsd29ya2VyOm99KTpsdChBKX1sZXQgbj1hd2FpdCBnQShlLHQpO3JldHVybiBsdChuKX12YXIgQnQ9enI7YXN5bmMgZnVuY3Rpb24gWnIoQSxlLHQpe2xldCByPSJ1bmtub3duIjt0eXBlb2YgQSE9InN0cmluZyI/cj1BLmhyZWY6QS5zdGFydHNXaXRoKCJodHRwIik/cj1BOnI9dHlwZW9mIGU8InUiP2Ake2V9LyR7QX1gOkEsci5lbmRzV2l0aCgiLmpzIikmJihyPXIuc3Vic3RyaW5nKDAsci5sZW5ndGgtMykpLHIuZW5kc1dpdGgoIi53YXNtIikmJihyPXIuc3Vic3RyaW5nKDAsci5sZW5ndGgtNSkpO2xldCBuPWAke3J9Lndhc21gLGk9KGF3YWl0IHouZ2V0KG4se3Jlc3BvbnNlVHlwZToiYXJyYXlidWZmZXIiLHBhcmFtczp0fSkpLmRhdGE7cmV0dXJuKGF3YWl0IGltcG9ydChgJHtyfS5qc2ApKS5kZWZhdWx0KHt3YXNtQmluYXJ5Oml9KX12YXIgQ3Q9WnI7dmFyIGZ0PWFzeW5jKCk9PldlYkFzc2VtYmx5LnZhbGlkYXRlKG5ldyBVaW50OEFycmF5KFswLDk3LDExNSwxMDksMSwwLDAsMCwxLDUsMSw5NiwwLDEsMTIzLDMsMiwxLDAsMTAsMTAsMSw4LDAsNjUsMCwyNTMsMTUsMjUzLDk4LDExXSkpO3ZhciBFdD10eXBlb2YgZ2xvYmFsVGhpcy5TaGFyZWRBcnJheUJ1ZmZlcj09ImZ1bmN0aW9uIixjdD1uZXcgVGV4dEVuY29kZXIsdXQ9bmV3IFRleHREZWNvZGVyKCJ1dGYtOCIpO2Z1bmN0aW9uIFZyKEEsZSl7bGV0IHQ9e2ZsYWdzOiJyIixlbmNvZGluZzoiYmluYXJ5In0scj1BLmZzX29wZW4oZSx0LmZsYWdzKSxvPUEuZnNfc3RhdChlKS5zaXplLGk9bnVsbDtFdD9pPW5ldyBTaGFyZWRBcnJheUJ1ZmZlcihvKTppPW5ldyBBcnJheUJ1ZmZlcihvKTtsZXQgbD1uZXcgVWludDhBcnJheShpKTtyZXR1cm4gQS5mc19yZWFkKHIsbCwwLG8sMCksQS5mc19jbG9zZShyKSxsfWZ1bmN0aW9uIFF0KEEsZSx0KXtsZXQgcj1udWxsO0V0P3I9bmV3IFNoYXJlZEFycmF5QnVmZmVyKHQpOnI9bmV3IEFycmF5QnVmZmVyKHQpO2xldCBuPW5ldyBVaW50OEFycmF5KHIpLG89bmV3IFVpbnQ4QXJyYXkoQS5IRUFQVTguYnVmZmVyLGUsdCk7cmV0dXJuIG4uc2V0KG8pLG59ZnVuY3Rpb24gUyhBLGUsdCxyKXtsZXQgbj0wO3JldHVybiBlIT09bnVsbCYmKG49QS5jY2FsbCgiaXRrX3dhc21faW5wdXRfYXJyYXlfYWxsb2MiLCJudW1iZXIiLFsibnVtYmVyIiwibnVtYmVyIiwibnVtYmVyIiwibnVtYmVyIl0sWzAsdCxyLGUuYnVmZmVyLmJ5dGVMZW5ndGhdKSxBLkhFQVBVOC5zZXQobmV3IFVpbnQ4QXJyYXkoZS5idWZmZXIpLG4pKSxufWZ1bmN0aW9uIEooQSxlLHQpe2xldCByPUpTT04uc3RyaW5naWZ5KGUpLG49QS5sZW5ndGhCeXRlc1VURjgocikrMSxvPUEuY2NhbGwoIml0a193YXNtX2lucHV0X2pzb25fYWxsb2MiLCJudW1iZXIiLFsibnVtYmVyIiwibnVtYmVyIiwibnVtYmVyIl0sWzAsdCxuXSk7QS5zdHJpbmdUb1VURjgocixvLG4pfWZ1bmN0aW9uIFIoQSxlLHQscil7bGV0IG49QS5jY2FsbCgiaXRrX3dhc21fb3V0cHV0X2FycmF5X2FkZHJlc3MiLCJudW1iZXIiLFsibnVtYmVyIiwibnVtYmVyIiwibnVtYmVyIl0sWzAsZSx0XSksbz1BLmNjYWxsKCJpdGtfd2FzbV9vdXRwdXRfYXJyYXlfc2l6ZSIsIm51bWJlciIsWyJudW1iZXIiLCJudW1iZXIiLCJudW1iZXIiXSxbMCxlLHRdKSxpPVF0KEEsbixvKTtyZXR1cm4gTChyLGkuYnVmZmVyKX1mdW5jdGlvbiBsQShBLGUpe2xldCB0PUEuY2NhbGwoIml0a193YXNtX291dHB1dF9qc29uX2FkZHJlc3MiLCJudW1iZXIiLFsibnVtYmVyIiwibnVtYmVyIl0sWzAsZV0pLHI9QS5VVEY4VG9TdHJpbmcodCk7cmV0dXJuIEpTT04ucGFyc2Uocil9ZnVuY3Rpb24gWHIoQSxlLHQscil7ciE9bnVsbCYmci5sZW5ndGg+MCYmci5mb3JFYWNoKGZ1bmN0aW9uKEIscyl7c3dpdGNoKEIudHlwZSl7Y2FzZSBFLlRleHRTdHJlYW06e2xldCBhPWN0LmVuY29kZShCLmRhdGEuZGF0YSksYz1TKEEsYSxzLDApLEk9e3NpemU6YS5idWZmZXIuYnl0ZUxlbmd0aCxkYXRhOmBkYXRhOmFwcGxpY2F0aW9uL3ZuZC5pdGsuYWRkcmVzcywwOiR7Y31gfTtKKEEsSSxzKTticmVha31jYXNlIEUuSnNvbkNvbXBhdGlibGU6e2xldCBhPWN0LmVuY29kZShKU09OLnN0cmluZ2lmeShCLmRhdGEpKSxjPVMoQSxhLHMsMCksST17c2l6ZTphLmJ1ZmZlci5ieXRlTGVuZ3RoLGRhdGE6YGRhdGE6YXBwbGljYXRpb24vdm5kLml0ay5hZGRyZXNzLDA6JHtjfWB9O0ooQSxJLHMpO2JyZWFrfWNhc2UgRS5CaW5hcnlTdHJlYW06e2xldCBhPUIuZGF0YS5kYXRhLGM9UyhBLGEscywwKSxJPXtzaXplOmEuYnVmZmVyLmJ5dGVMZW5ndGgsZGF0YTpgZGF0YTphcHBsaWNhdGlvbi92bmQuaXRrLmFkZHJlc3MsMDoke2N9YH07SihBLEkscyk7YnJlYWt9Y2FzZSBFLlRleHRGaWxlOntBLmZzX3dyaXRlRmlsZShCLmRhdGEucGF0aCxCLmRhdGEuZGF0YSk7YnJlYWt9Y2FzZSBFLkJpbmFyeUZpbGU6e0EuZnNfd3JpdGVGaWxlKEIuZGF0YS5wYXRoLEIuZGF0YS5kYXRhKTticmVha31jYXNlIEUuSW1hZ2U6e2xldCBhPUIuZGF0YSxjPVMoQSxhLmRhdGEscywwKSxJPVMoQSxhLmRpcmVjdGlvbixzLDEpLEM9dHlwZW9mIGEubWV0YWRhdGE/LmVudHJpZXM8InUiP0FycmF5LmZyb20oYS5tZXRhZGF0YS5lbnRyaWVzKCkpOltdLGY9e2ltYWdlVHlwZTphLmltYWdlVHlwZSxuYW1lOmEubmFtZSxvcmlnaW46YS5vcmlnaW4sc3BhY2luZzphLnNwYWNpbmcsZGlyZWN0aW9uOmBkYXRhOmFwcGxpY2F0aW9uL3ZuZC5pdGsuYWRkcmVzcywwOiR7SX1gLHNpemU6YS5zaXplLGRhdGE6YGRhdGE6YXBwbGljYXRpb24vdm5kLml0ay5hZGRyZXNzLDA6JHtjfWAsbWV0YWRhdGE6Q307SihBLGYscyk7YnJlYWt9Y2FzZSBFLk1lc2g6e2xldCBhPUIuZGF0YSxjPVMoQSxhLnBvaW50cyxzLDApLEk9UyhBLGEuY2VsbHMscywxKSxDPVMoQSxhLnBvaW50RGF0YSxzLDIpLGY9UyhBLGEuY2VsbERhdGEscywzKSxRPXttZXNoVHlwZTphLm1lc2hUeXBlLG5hbWU6YS5uYW1lLG51bWJlck9mUG9pbnRzOmEubnVtYmVyT2ZQb2ludHMscG9pbnRzOmBkYXRhOmFwcGxpY2F0aW9uL3ZuZC5pdGsuYWRkcmVzcywwOiR7Y31gLG51bWJlck9mQ2VsbHM6YS5udW1iZXJPZkNlbGxzLGNlbGxzOmBkYXRhOmFwcGxpY2F0aW9uL3ZuZC5pdGsuYWRkcmVzcywwOiR7SX1gLGNlbGxCdWZmZXJTaXplOmEuY2VsbEJ1ZmZlclNpemUsbnVtYmVyT2ZQb2ludFBpeGVsczphLm51bWJlck9mUG9pbnRQaXhlbHMscG9pbnREYXRhOmBkYXRhOmFwcGxpY2F0aW9uL3ZuZC5pdGsuYWRkcmVzcywwOiR7Q31gLG51bWJlck9mQ2VsbFBpeGVsczphLm51bWJlck9mQ2VsbFBpeGVscyxjZWxsRGF0YTpgZGF0YTphcHBsaWNhdGlvbi92bmQuaXRrLmFkZHJlc3MsMDoke2Z9YH07SihBLFEscyk7YnJlYWt9Y2FzZSBFLlBvaW50U2V0OntsZXQgYT1CLmRhdGEsYz1TKEEsYS5wb2ludHMscywwKSxJPVMoQSxhLnBvaW50RGF0YSxzLDEpLEM9e3BvaW50U2V0VHlwZTphLnBvaW50U2V0VHlwZSxuYW1lOmEubmFtZSxudW1iZXJPZlBvaW50czphLm51bWJlck9mUG9pbnRzLHBvaW50czpgZGF0YTphcHBsaWNhdGlvbi92bmQuaXRrLmFkZHJlc3MsMDoke2N9YCxudW1iZXJPZlBvaW50UGl4ZWxzOmEubnVtYmVyT2ZQb2ludFBpeGVscyxwb2ludERhdGE6YGRhdGE6YXBwbGljYXRpb24vdm5kLml0ay5hZGRyZXNzLDA6JHtJfWB9O0ooQSxDLHMpO2JyZWFrfWNhc2UgRS5UcmFuc2Zvcm1MaXN0OntsZXQgYT1CLmRhdGEsYz1bXTthLmZvckVhY2goKEksQyk9PntsZXQgUT1gZGF0YTphcHBsaWNhdGlvbi92bmQuaXRrLmFkZHJlc3MsMDoke1MoQSxJLmZpeGVkUGFyYW1ldGVycyxzLEMqMil9YCxVPWBkYXRhOmFwcGxpY2F0aW9uL3ZuZC5pdGsuYWRkcmVzcywwOiR7UyhBLEkucGFyYW1ldGVycyxzLEMqMisxKX1gLE49e3RyYW5zZm9ybVR5cGU6SS50cmFuc2Zvcm1UeXBlLG51bWJlck9mRml4ZWRQYXJhbWV0ZXJzOkkubnVtYmVyT2ZGaXhlZFBhcmFtZXRlcnMsbnVtYmVyT2ZQYXJhbWV0ZXJzOkkubnVtYmVyT2ZQYXJhbWV0ZXJzLG5hbWU6SS5uYW1lLGlucHV0U3BhY2VOYW1lOkkuaW5wdXRTcGFjZU5hbWUsb3V0cHV0U3BhY2VOYW1lOkkub3V0cHV0U3BhY2VOYW1lLHBhcmFtZXRlcnM6VSxmaXhlZFBhcmFtZXRlcnM6UX07Yy5wdXNoKE4pfSksSihBLGMscyk7YnJlYWt9Y2FzZSBFLlBvbHlEYXRhOntsZXQgYT1CLmRhdGEsYz1TKEEsYS5wb2ludHMscywwKSxJPVMoQSxhLnZlcnRpY2VzLHMsMSksQz1TKEEsYS5saW5lcyxzLDIpLGY9UyhBLGEucG9seWdvbnMscywzKSxRPVMoQSxhLnRyaWFuZ2xlU3RyaXBzLHMsNCksbT1TKEEsYS5wb2ludERhdGEscyw1KSxVPVMoQSxhLnBvaW50RGF0YSxzLDYpLE49e3BvbHlEYXRhVHlwZTphLnBvbHlEYXRhVHlwZSxuYW1lOmEubmFtZSxudW1iZXJPZlBvaW50czphLm51bWJlck9mUG9pbnRzLHBvaW50czpgZGF0YTphcHBsaWNhdGlvbi92bmQuaXRrLmFkZHJlc3MsMDoke2N9YCx2ZXJ0aWNlc0J1ZmZlclNpemU6YS52ZXJ0aWNlc0J1ZmZlclNpemUsdmVydGljZXM6YGRhdGE6YXBwbGljYXRpb24vdm5kLml0ay5hZGRyZXNzLDA6JHtJfWAsbGluZXNCdWZmZXJTaXplOmEubGluZXNCdWZmZXJTaXplLGxpbmVzOmBkYXRhOmFwcGxpY2F0aW9uL3ZuZC5pdGsuYWRkcmVzcywwOiR7Q31gLHBvbHlnb25zQnVmZmVyU2l6ZTphLnBvbHlnb25zQnVmZmVyU2l6ZSxwb2x5Z29uczpgZGF0YTphcHBsaWNhdGlvbi92bmQuaXRrLmFkZHJlc3MsMDoke2Z9YCx0cmlhbmdsZVN0cmlwc0J1ZmZlclNpemU6YS50cmlhbmdsZVN0cmlwc0J1ZmZlclNpemUsdHJpYW5nbGVTdHJpcHM6YGRhdGE6YXBwbGljYXRpb24vdm5kLml0ay5hZGRyZXNzLDA6JHtRfWAsbnVtYmVyT2ZQb2ludFBpeGVsczphLm51bWJlck9mUG9pbnRQaXhlbHMscG9pbnREYXRhOmBkYXRhOmFwcGxpY2F0aW9uL3ZuZC5pdGsuYWRkcmVzcywwOiR7bX1gLG51bWJlck9mQ2VsbFBpeGVsczphLm51bWJlck9mQ2VsbFBpeGVscyxjZWxsRGF0YTpgZGF0YTphcHBsaWNhdGlvbi92bmQuaXRrLmFkZHJlc3MsMDoke1V9YH07SihBLE4scyk7YnJlYWt9ZGVmYXVsdDp0aHJvdyBFcnJvcigiVW5zdXBwb3J0ZWQgaW5wdXQgSW50ZXJmYWNlVHlwZSIpfX0pLEEucmVzZXRNb2R1bGVTdGRvdXQoKSxBLnJlc2V0TW9kdWxlU3RkZXJyKCk7bGV0IG49QS5zdGFja1NhdmUoKSxvPTA7dHJ5e289QS5jYWxsTWFpbihlLnNsaWNlKCkpfWNhdGNoKEIpe3Rocm93IHR5cGVvZiBCPT0ibnVtYmVyIiYmKGNvbnNvbGUubG9nKCJFeGNlcHRpb24gd2hpbGUgcnVubmluZyBwaXBlbGluZToiKSxjb25zb2xlLmxvZygic3Rkb3V0OiIsQS5nZXRNb2R1bGVTdGRvdXQoKSksY29uc29sZS5lcnJvcigic3RkZXJyOiIsQS5nZXRNb2R1bGVTdGRlcnIoKSksdHlwZW9mIEEuZ2V0RXhjZXB0aW9uTWVzc2FnZTwidSI/Y29uc29sZS5lcnJvcigiZXhjZXB0aW9uOiIsQS5nZXRFeGNlcHRpb25NZXNzYWdlKEIpKTpjb25zb2xlLmVycm9yKCJCdWlsZCBtb2R1bGUgaW4gRGVidWcgbW9kZSBmb3IgZXhjZXB0aW9uIG1lc3NhZ2UgaW5mb3JtYXRpb24uIikpLEJ9ZmluYWxseXtBLnN0YWNrUmVzdG9yZShuKX1sZXQgaT1BLmdldE1vZHVsZVN0ZG91dCgpLGw9QS5nZXRNb2R1bGVTdGRlcnIoKSx1PVtdO3JldHVybiB0IT1udWxsJiZ0Lmxlbmd0aD4wJiZvPT09MCYmdC5mb3JFYWNoKGZ1bmN0aW9uKEIscyl7bGV0IGE9bnVsbDtzd2l0Y2goQi50eXBlKXtjYXNlIEUuVGV4dFN0cmVhbTp7bGV0IEk9QS5jY2FsbCgiaXRrX3dhc21fb3V0cHV0X2FycmF5X2FkZHJlc3MiLCJudW1iZXIiLFsibnVtYmVyIiwibnVtYmVyIiwibnVtYmVyIl0sWzAscywwXSksQz1BLmNjYWxsKCJpdGtfd2FzbV9vdXRwdXRfYXJyYXlfc2l6ZSIsIm51bWJlciIsWyJudW1iZXIiLCJudW1iZXIiLCJudW1iZXIiXSxbMCxzLDBdKSxmPW5ldyBVaW50OEFycmF5KEEuSEVBUFU4LmJ1ZmZlcixJLEMpO2E9e2RhdGE6dXQuZGVjb2RlKGYpfTticmVha31jYXNlIEUuSnNvbkNvbXBhdGlibGU6e2xldCBJPUEuY2NhbGwoIml0a193YXNtX291dHB1dF9hcnJheV9hZGRyZXNzIiwibnVtYmVyIixbIm51bWJlciIsIm51bWJlciIsIm51bWJlciJdLFswLHMsMF0pLEM9QS5jY2FsbCgiaXRrX3dhc21fb3V0cHV0X2FycmF5X3NpemUiLCJudW1iZXIiLFsibnVtYmVyIiwibnVtYmVyIiwibnVtYmVyIl0sWzAscywwXSksZj1uZXcgVWludDhBcnJheShBLkhFQVBVOC5idWZmZXIsSSxDKTthPUpTT04ucGFyc2UodXQuZGVjb2RlKGYpKTticmVha31jYXNlIEUuQmluYXJ5U3RyZWFtOntsZXQgST1BLmNjYWxsKCJpdGtfd2FzbV9vdXRwdXRfYXJyYXlfYWRkcmVzcyIsIm51bWJlciIsWyJudW1iZXIiLCJudW1iZXIiLCJudW1iZXIiXSxbMCxzLDBdKSxDPUEuY2NhbGwoIml0a193YXNtX291dHB1dF9hcnJheV9zaXplIiwibnVtYmVyIixbIm51bWJlciIsIm51bWJlciIsIm51bWJlciJdLFswLHMsMF0pO2E9e2RhdGE6UXQoQSxJLEMpfTticmVha31jYXNlIEUuVGV4dEZpbGU6e2E9e3BhdGg6Qi5kYXRhLnBhdGgsZGF0YTpBLmZzX3JlYWRGaWxlKEIuZGF0YS5wYXRoLHtlbmNvZGluZzoidXRmOCJ9KX07YnJlYWt9Y2FzZSBFLkJpbmFyeUZpbGU6e2E9e3BhdGg6Qi5kYXRhLnBhdGgsZGF0YTpWcihBLEIuZGF0YS5wYXRoKX07YnJlYWt9Y2FzZSBFLkltYWdlOntsZXQgST1sQShBLHMpO0kuZGF0YT1SKEEscywwLEkuaW1hZ2VUeXBlLmNvbXBvbmVudFR5cGUpLEkuZGlyZWN0aW9uPVIoQSxzLDEsSC5GbG9hdDY0KSxJLm1ldGFkYXRhPW5ldyBNYXAoSS5tZXRhZGF0YSksYT1JO2JyZWFrfWNhc2UgRS5NZXNoOntsZXQgST1sQShBLHMpO0kubnVtYmVyT2ZQb2ludHM+MD9JLnBvaW50cz1SKEEscywwLEkubWVzaFR5cGUucG9pbnRDb21wb25lbnRUeXBlKTpJLnBvaW50cz1MKEkubWVzaFR5cGUucG9pbnRDb21wb25lbnRUeXBlLG5ldyBBcnJheUJ1ZmZlcigwKSksSS5udW1iZXJPZkNlbGxzPjA/SS5jZWxscz1SKEEscywxLEkubWVzaFR5cGUuY2VsbENvbXBvbmVudFR5cGUpOkkuY2VsbHM9TChJLm1lc2hUeXBlLmNlbGxDb21wb25lbnRUeXBlLG5ldyBBcnJheUJ1ZmZlcigwKSksSS5udW1iZXJPZlBvaW50UGl4ZWxzPjA/SS5wb2ludERhdGE9UihBLHMsMixJLm1lc2hUeXBlLnBvaW50UGl4ZWxDb21wb25lbnRUeXBlKTpJLnBvaW50RGF0YT1MKEkubWVzaFR5cGUucG9pbnRQaXhlbENvbXBvbmVudFR5cGUsbmV3IEFycmF5QnVmZmVyKDApKSxJLm51bWJlck9mQ2VsbFBpeGVscz4wP0kuY2VsbERhdGE9UihBLHMsMyxJLm1lc2hUeXBlLmNlbGxQaXhlbENvbXBvbmVudFR5cGUpOkkuY2VsbERhdGE9TChJLm1lc2hUeXBlLmNlbGxQaXhlbENvbXBvbmVudFR5cGUsbmV3IEFycmF5QnVmZmVyKDApKSxhPUk7YnJlYWt9Y2FzZSBFLlBvaW50U2V0OntsZXQgST1sQShBLHMpO0kubnVtYmVyT2ZQb2ludHM+MD9JLnBvaW50cz1SKEEscywwLEkucG9pbnRTZXRUeXBlLnBvaW50Q29tcG9uZW50VHlwZSk6SS5wb2ludHM9TChJLnBvaW50U2V0VHlwZS5wb2ludENvbXBvbmVudFR5cGUsbmV3IEFycmF5QnVmZmVyKDApKSxJLm51bWJlck9mUG9pbnRQaXhlbHM+MD9JLnBvaW50RGF0YT1SKEEscywxLEkucG9pbnRTZXRUeXBlLnBvaW50UGl4ZWxDb21wb25lbnRUeXBlKTpJLnBvaW50RGF0YT1MKEkucG9pbnRTZXRUeXBlLnBvaW50UGl4ZWxDb21wb25lbnRUeXBlLG5ldyBBcnJheUJ1ZmZlcigwKSksYT1JO2JyZWFrfWNhc2UgRS5UcmFuc2Zvcm1MaXN0OntsZXQgST1sQShBLHMpO0kuZm9yRWFjaCgoQyxmKT0+e0MubnVtYmVyT2ZGaXhlZFBhcmFtZXRlcnM+MCYmKElbZl0uZml4ZWRQYXJhbWV0ZXJzPVIoQSxzLGYqMixDLnRyYW5zZm9ybVR5cGUucGFyYW1ldGVyc1ZhbHVlVHlwZSkpLEMubnVtYmVyT2ZGaXhlZFBhcmFtZXRlcnM+MCYmKElbZl0ucGFyYW1ldGVycz1SKEEscyxmKjIrMSxDLnRyYW5zZm9ybVR5cGUucGFyYW1ldGVyc1ZhbHVlVHlwZSkpfSksYT1JO2JyZWFrfWNhc2UgRS5Qb2x5RGF0YTp7bGV0IEk9bEEoQSxzKTtJLm51bWJlck9mUG9pbnRzPjA/SS5wb2ludHM9UihBLHMsMCxILkZsb2F0MzIpOkkucG9pbnRzPW5ldyBGbG9hdDMyQXJyYXksSS52ZXJ0aWNlc0J1ZmZlclNpemU+MD9JLnZlcnRpY2VzPVIoQSxzLDEsRi5VSW50MzIpOkkudmVydGljZXM9bmV3IFVpbnQzMkFycmF5LEkubGluZXNCdWZmZXJTaXplPjA/SS5saW5lcz1SKEEscywyLEYuVUludDMyKTpJLmxpbmVzPW5ldyBVaW50MzJBcnJheSxJLnBvbHlnb25zQnVmZmVyU2l6ZT4wP0kucG9seWdvbnM9UihBLHMsMyxGLlVJbnQzMik6SS5wb2x5Z29ucz1uZXcgVWludDMyQXJyYXksSS50cmlhbmdsZVN0cmlwc0J1ZmZlclNpemU+MD9JLnRyaWFuZ2xlU3RyaXBzPVIoQSxzLDQsRi5VSW50MzIpOkkudHJpYW5nbGVTdHJpcHM9bmV3IFVpbnQzMkFycmF5LEkubnVtYmVyT2ZQb2ludFBpeGVscz4wP0kucG9pbnREYXRhPVIoQSxzLDUsSS5wb2x5RGF0YVR5cGUucG9pbnRQaXhlbENvbXBvbmVudFR5cGUpOkkucG9pbnREYXRhPUwoSS5wb2x5RGF0YVR5cGUucG9pbnRQaXhlbENvbXBvbmVudFR5cGUsbmV3IEFycmF5QnVmZmVyKDApKSxJLm51bWJlck9mQ2VsbFBpeGVscz4wP0kuY2VsbERhdGE9UihBLHMsNixJLnBvbHlEYXRhVHlwZS5jZWxsUGl4ZWxDb21wb25lbnRUeXBlKTpJLmNlbGxEYXRhPUwoSS5wb2x5RGF0YVR5cGUuY2VsbFBpeGVsQ29tcG9uZW50VHlwZSxuZXcgQXJyYXlCdWZmZXIoMCkpLGE9STticmVha31kZWZhdWx0OnRocm93IEVycm9yKCJVbnN1cHBvcnRlZCBvdXRwdXQgSW50ZXJmYWNlVHlwZSIpfWxldCBjPXt0eXBlOkIudHlwZSxkYXRhOmF9O3UucHVzaChjKX0pLHtyZXR1cm5WYWx1ZTpvLHN0ZG91dDppLHN0ZGVycjpsLG91dHB1dHM6dX19dmFyIHB0PVhyO3ZhciAkcj10eXBlb2YgZ2xvYmFsVGhpcy5TaGFyZWRBcnJheUJ1ZmZlcjwidSI7ZnVuY3Rpb24gQW8oQSxlKXtpZihBPT1udWxsKXJldHVybltdO2xldCB0PVtdO2ZvcihsZXQgcj0wO3I8QS5sZW5ndGg7cisrKXtsZXQgbj1lbyhBW3JdLGUpO24hPT1udWxsJiZ0LnB1c2gobil9cmV0dXJuIHR9ZnVuY3Rpb24gZW8oQSxlKXtpZihBPT1udWxsKXJldHVybiBudWxsO2xldCB0PW51bGw7cmV0dXJuIEEuYnVmZmVyIT09dm9pZCAwP3Q9QS5idWZmZXI6QS5ieXRlTGVuZ3RoIT09dm9pZCAwJiYodD1BKSwkciYmdCBpbnN0YW5jZW9mIFNoYXJlZEFycmF5QnVmZmVyP251bGw6ZT90OnQuc2xpY2UoMCl9dmFyIG10PUFvO2Z1bmN0aW9uIHRvKEEpe3JldHVybltBLmRhdGEsQS5kaXJlY3Rpb25dfXZhciBkdD10bztmdW5jdGlvbiBybyhBKXtyZXR1cm5bQS5wb2ludHMsQS5wb2ludERhdGEsQS5jZWxscyxBLmNlbGxEYXRhXX12YXIgeXQ9cm87ZnVuY3Rpb24gb28oQSl7cmV0dXJuW0EucG9pbnRzLEEudmVydGljZXMsQS5saW5lcyxBLnBvbHlnb25zLEEudHJpYW5nbGVTdHJpcHMsQS5wb2ludERhdGEsQS5jZWxsRGF0YV19dmFyIGh0PW9vO3ZhciBubztmdW5jdGlvbiBGQSgpe3JldHVybiBub312YXIgaW87ZnVuY3Rpb24gd3QoKXtyZXR1cm4gaW99dmFyIGFvO2Z1bmN0aW9uIFVBKCl7cmV0dXJuIGFvfXZhciBpZT1uZXcgTWFwO2Z1bmN0aW9uIHNvKCl7bGV0IEE9VUEoKTtyZXR1cm4gdHlwZW9mIEE+InUiJiYoQT1udWxsKSxBfWZ1bmN0aW9uIER0KCl7bGV0IEE9RkEoKTtyZXR1cm4gdHlwZW9mIEE+InUiJiYoQT1uZXcgVVJMKCIvcGlwZWxpbmVzIixkb2N1bWVudC5sb2NhdGlvbi5vcmlnaW4pLmhyZWYpLEF9ZnVuY3Rpb24gTkEoKXtsZXQgQT13dCgpO3JldHVybiB0eXBlb2YgQT4idSImJihBPXt9KSxBfWFzeW5jIGZ1bmN0aW9uIElvKEEsZSx0KXtsZXQgcj1BLG49QTtpZih0eXBlb2YgQSE9InN0cmluZyImJihyPW5ldyBVUkwoQS5ocmVmKSxuPXIuaHJlZiksaWUuaGFzKG4pKXJldHVybiBpZS5nZXQobik7e2xldCBvPWF3YWl0IEN0KEEsZT8udG9TdHJpbmcoKT8/RHQoKSx0Pz9OQSgpKTtyZXR1cm4gaWUuc2V0KG4sbyksb319YXN5bmMgZnVuY3Rpb24gZ28oQSxlLHQscixuKXtpZighYXdhaXQgZnQoKSl7bGV0IFE9IldlYkFzc2VtYmx5IFNJTUQgc3VwcG9ydCBpcyByZXF1aXJlZCAtLSBwbGVhc2UgdXBkYXRlIHlvdXIgYnJvd3Nlci4iO3Rocm93IGFsZXJ0KFEpLG5ldyBFcnJvcihRKX1sZXQgbz1uPy53ZWJXb3JrZXI/P251bGw7aWYobz09PSExKXtsZXQgUT1hd2FpdCBJbyhBLnRvU3RyaW5nKCksbj8ucGlwZWxpbmVCYXNlVXJsLG4/LnBpcGVsaW5lUXVlcnlQYXJhbXM/P05BKCkpO3JldHVybiBwdChRLGUsdCxyKX1sZXQgaT1vLGw9bj8ucGlwZWxpbmVXb3JrZXJVcmw/P3NvKCksdT10eXBlb2YgbCE9InN0cmluZyImJnR5cGVvZiBsPy5ocmVmPCJ1Ij9sLmhyZWY6bCx7d29ya2VyUHJveHk6Qix3b3JrZXI6c309YXdhaXQgQnQoaSx1LG4/LnBpcGVsaW5lUXVlcnlQYXJhbXM/P05BKCkpO2k9cztsZXQgYT1bXTtyIT1udWxsJiZyLmxlbmd0aD4wJiZyLmZvckVhY2goZnVuY3Rpb24oUSl7aWYoUS50eXBlPT09RS5CaW5hcnlTdHJlYW0pe2xldCBtPVEuZGF0YS5kYXRhO2EucHVzaChtKX1lbHNlIGlmKFEudHlwZT09PUUuQmluYXJ5RmlsZSl7bGV0IG09US5kYXRhLmRhdGE7YS5wdXNoKG0pfWVsc2UgaWYoUS50eXBlPT09RS5JbWFnZSl7bGV0IG09US5kYXRhO20uZGF0YSE9PW51bGwmJmEucHVzaCguLi5kdChtKSl9ZWxzZSBpZihRLnR5cGU9PT1FLk1lc2gpe2xldCBtPVEuZGF0YTthLnB1c2goLi4ueXQobSkpfWVsc2UgaWYoUS50eXBlPT09RS5Qb2x5RGF0YSl7bGV0IG09US5kYXRhO2EucHVzaCguLi5odChtKSl9fSk7bGV0IGM9bj8ucGlwZWxpbmVCYXNlVXJsPz9EdCgpLEk9dHlwZW9mIGMhPSJzdHJpbmciJiZ0eXBlb2YgYz8uaHJlZjwidSI/Yy5ocmVmOmMsQz1yIT1udWxsP3hBKHIsbXQoYSxuPy5ub0NvcHkpKTpudWxsLGY9YXdhaXQgQi5ydW5QaXBlbGluZShBLnRvU3RyaW5nKCksSSxlLHQsQyxuPy5waXBlbGluZVF1ZXJ5UGFyYW1zPz9OQSgpKTtyZXR1cm57cmV0dXJuVmFsdWU6Zi5yZXR1cm5WYWx1ZSxzdGRvdXQ6Zi5zdGRvdXQsc3RkZXJyOmYuc3RkZXJyLG91dHB1dHM6Zi5vdXRwdXRzLHdlYldvcmtlcjppfX12YXIgeT1nbzt2YXIgbG89bnVsbDtmdW5jdGlvbiBTdCgpe3JldHVybiBsb312YXIgQm89bmV3IE1hcChbXSksWj1Cbzt2YXIgQ289bmV3IE1hcChbWyJoNSIsImhkZjUiXSxbImhkZjUiLCJoZGY1Il0sWyJ0eHQiLCJ0eHQiXSxbIm1hdCIsIm1hdCJdLFsieGZtIiwibW5jIl0sWyJpd3QiLCJ3YXNtIl0sWyJpd3QuY2JvciIsIndhc20iXSxbIml3dC5jYm9yLnpzdCIsIndhc20tenN0ZCJdXSksVj1Dbzt2YXIgYWUsZm89YGh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9ucG0vQGl0ay13YXNtL3RyYW5zZm9ybS1pb0Ake1RBfS9kaXN0L3BpcGVsaW5lc2A7ZnVuY3Rpb24gR3MoQSl7YWU9QX1mdW5jdGlvbiBoKCl7aWYodHlwZW9mIGFlPCJ1IilyZXR1cm4gYWU7bGV0IEE9RkEoKTtyZXR1cm4gdHlwZW9mIEE8InUiP0E6Zm99dmFyIHNlLGNvPW51bGw7ZnVuY3Rpb24gUnQoQSl7c2U9QX1mdW5jdGlvbiBkKCl7aWYodHlwZW9mIHNlPCJ1IilyZXR1cm4gc2U7bGV0IEE9VUEoKTtyZXR1cm4gdHlwZW9mIEE8InUiP0E6Y299dmFyIFg9bnVsbDthc3luYyBmdW5jdGlvbiBidCgpe2xldCBBPWQoKSxlPXR5cGVvZiBBIT0ic3RyaW5nIiYmdHlwZW9mIEE/LmhyZWY8InUiP0EuaHJlZjpBO1g9YXdhaXQgZ0EoZSl9ZnVuY3Rpb24gWXMoQSl7WD1BfWFzeW5jIGZ1bmN0aW9uIHcoKXtpZihYIT09bnVsbClyZXR1cm4gWC50ZXJtaW5hdGVkJiZhd2FpdCBidCgpLFg7bGV0IEE9U3QoKTtyZXR1cm4gQSE9PW51bGw/QTooYXdhaXQgYnQoKSxYKX1hc3luYyBmdW5jdGlvbiB1byhBLGU9e30pe2xldCB0PVt7dHlwZTpFLkpzb25Db21wYXRpYmxlfSx7dHlwZTpFLlRyYW5zZm9ybUxpc3R9XSxyPUE7aWYoQSBpbnN0YW5jZW9mIEZpbGUpe2xldCBRPWF3YWl0IEEuYXJyYXlCdWZmZXIoKTtyPXtwYXRoOkEubmFtZSxkYXRhOm5ldyBVaW50OEFycmF5KFEpfX1sZXQgbj1be3R5cGU6RS5CaW5hcnlGaWxlLGRhdGE6cn1dLG89W10saT1yLnBhdGg7by5wdXNoKGkpLG8ucHVzaCgiMCIpLG8ucHVzaCgiMSIpLG8ucHVzaCgiLS1tZW1vcnktaW8iKSxlLmZsb2F0UGFyYW1ldGVycyYmZS5mbG9hdFBhcmFtZXRlcnMmJm8ucHVzaCgiLS1mbG9hdC1wYXJhbWV0ZXJzIik7bGV0IEI9ImhkZjUtcmVhZC10cmFuc2Zvcm0iLHM9ZT8ud2ViV29ya2VyO3M9PT12b2lkIDAmJihzPWF3YWl0IHcoKSk7bGV0e3dlYldvcmtlcjphLHJldHVyblZhbHVlOmMsc3RkZXJyOkksb3V0cHV0czpDfT1hd2FpdCB5KEIsbyx0LG4se3BpcGVsaW5lQmFzZVVybDpoKCkscGlwZWxpbmVXb3JrZXJVcmw6ZCgpLHdlYldvcmtlcjpzLG5vQ29weTplPy5ub0NvcHl9KTtpZihjIT09MCYmSSE9PSIiKXRocm93IG5ldyBFcnJvcihJKTtyZXR1cm57d2ViV29ya2VyOmEsY291bGRSZWFkOkNbMF0/LmRhdGEsdHJhbnNmb3JtOkNbMV0/LmRhdGF9fXZhciBJZT11bzthc3luYyBmdW5jdGlvbiBFbyhBLGUsdD17fSl7bGV0IHI9W3t0eXBlOkUuSnNvbkNvbXBhdGlibGV9LHt0eXBlOkUuQmluYXJ5RmlsZSxkYXRhOntwYXRoOmUsZGF0YTpuZXcgVWludDhBcnJheX19XSxuPVt7dHlwZTpFLlRyYW5zZm9ybUxpc3QsZGF0YTpBfV0sbz1bXTtvLnB1c2goIjAiKSxvLnB1c2goIjAiKTtsZXQgdT1lO28ucHVzaCh1KSxvLnB1c2goIi0tbWVtb3J5LWlvIiksdC5mbG9hdFBhcmFtZXRlcnMmJnQuZmxvYXRQYXJhbWV0ZXJzJiZvLnB1c2goIi0tZmxvYXQtcGFyYW1ldGVycyIpLHQudXNlQ29tcHJlc3Npb24mJnQudXNlQ29tcHJlc3Npb24mJm8ucHVzaCgiLS11c2UtY29tcHJlc3Npb24iKTtsZXQgQj0iaGRmNS13cml0ZS10cmFuc2Zvcm0iLHM9dD8ud2ViV29ya2VyO3M9PT12b2lkIDAmJihzPWF3YWl0IHcoKSk7bGV0e3dlYldvcmtlcjphLHJldHVyblZhbHVlOmMsc3RkZXJyOkksb3V0cHV0czpDfT1hd2FpdCB5KEIsbyxyLG4se3BpcGVsaW5lQmFzZVVybDpoKCkscGlwZWxpbmVXb3JrZXJVcmw6ZCgpLHdlYldvcmtlcjpzLG5vQ29weTp0Py5ub0NvcHl9KTtpZihjIT09MCYmSSE9PSIiKXRocm93IG5ldyBFcnJvcihJKTtyZXR1cm57d2ViV29ya2VyOmEsY291bGRXcml0ZTpDWzBdPy5kYXRhLHNlcmlhbGl6ZWRUcmFuc2Zvcm06Q1sxXT8uZGF0YX19dmFyIGdlPUVvO2FzeW5jIGZ1bmN0aW9uIFFvKEEsZT17fSl7bGV0IHQ9W3t0eXBlOkUuSnNvbkNvbXBhdGlibGV9LHt0eXBlOkUuVHJhbnNmb3JtTGlzdH1dLHI9QTtpZihBIGluc3RhbmNlb2YgRmlsZSl7bGV0IFE9YXdhaXQgQS5hcnJheUJ1ZmZlcigpO3I9e3BhdGg6QS5uYW1lLGRhdGE6bmV3IFVpbnQ4QXJyYXkoUSl9fWxldCBuPVt7dHlwZTpFLkJpbmFyeUZpbGUsZGF0YTpyfV0sbz1bXSxpPXIucGF0aDtvLnB1c2goaSksby5wdXNoKCIwIiksby5wdXNoKCIxIiksby5wdXNoKCItLW1lbW9yeS1pbyIpLGUuZmxvYXRQYXJhbWV0ZXJzJiZlLmZsb2F0UGFyYW1ldGVycyYmby5wdXNoKCItLWZsb2F0LXBhcmFtZXRlcnMiKTtsZXQgQj0ibWF0LXJlYWQtdHJhbnNmb3JtIixzPWU/LndlYldvcmtlcjtzPT09dm9pZCAwJiYocz1hd2FpdCB3KCkpO2xldHt3ZWJXb3JrZXI6YSxyZXR1cm5WYWx1ZTpjLHN0ZGVycjpJLG91dHB1dHM6Q309YXdhaXQgeShCLG8sdCxuLHtwaXBlbGluZUJhc2VVcmw6aCgpLHBpcGVsaW5lV29ya2VyVXJsOmQoKSx3ZWJXb3JrZXI6cyxub0NvcHk6ZT8ubm9Db3B5fSk7aWYoYyE9PTAmJkkhPT0iIil0aHJvdyBuZXcgRXJyb3IoSSk7cmV0dXJue3dlYldvcmtlcjphLGNvdWxkUmVhZDpDWzBdPy5kYXRhLHRyYW5zZm9ybTpDWzFdPy5kYXRhfX12YXIgbGU9UW87YXN5bmMgZnVuY3Rpb24gcG8oQSxlLHQ9e30pe2xldCByPVt7dHlwZTpFLkpzb25Db21wYXRpYmxlfSx7dHlwZTpFLkJpbmFyeUZpbGUsZGF0YTp7cGF0aDplLGRhdGE6bmV3IFVpbnQ4QXJyYXl9fV0sbj1be3R5cGU6RS5UcmFuc2Zvcm1MaXN0LGRhdGE6QX1dLG89W107by5wdXNoKCIwIiksby5wdXNoKCIwIik7bGV0IHU9ZTtvLnB1c2godSksby5wdXNoKCItLW1lbW9yeS1pbyIpLHQuZmxvYXRQYXJhbWV0ZXJzJiZ0LmZsb2F0UGFyYW1ldGVycyYmby5wdXNoKCItLWZsb2F0LXBhcmFtZXRlcnMiKSx0LnVzZUNvbXByZXNzaW9uJiZ0LnVzZUNvbXByZXNzaW9uJiZvLnB1c2goIi0tdXNlLWNvbXByZXNzaW9uIik7bGV0IEI9Im1hdC13cml0ZS10cmFuc2Zvcm0iLHM9dD8ud2ViV29ya2VyO3M9PT12b2lkIDAmJihzPWF3YWl0IHcoKSk7bGV0e3dlYldvcmtlcjphLHJldHVyblZhbHVlOmMsc3RkZXJyOkksb3V0cHV0czpDfT1hd2FpdCB5KEIsbyxyLG4se3BpcGVsaW5lQmFzZVVybDpoKCkscGlwZWxpbmVXb3JrZXJVcmw6ZCgpLHdlYldvcmtlcjpzLG5vQ29weTp0Py5ub0NvcHl9KTtpZihjIT09MCYmSSE9PSIiKXRocm93IG5ldyBFcnJvcihJKTtyZXR1cm57d2ViV29ya2VyOmEsY291bGRXcml0ZTpDWzBdPy5kYXRhLHNlcmlhbGl6ZWRUcmFuc2Zvcm06Q1sxXT8uZGF0YX19dmFyIEJlPXBvO2FzeW5jIGZ1bmN0aW9uIG1vKEEsZT17fSl7bGV0IHQ9W3t0eXBlOkUuSnNvbkNvbXBhdGlibGV9LHt0eXBlOkUuVHJhbnNmb3JtTGlzdH1dLHI9QTtpZihBIGluc3RhbmNlb2YgRmlsZSl7bGV0IFE9YXdhaXQgQS5hcnJheUJ1ZmZlcigpO3I9e3BhdGg6QS5uYW1lLGRhdGE6bmV3IFVpbnQ4QXJyYXkoUSl9fWxldCBuPVt7dHlwZTpFLkJpbmFyeUZpbGUsZGF0YTpyfV0sbz1bXSxpPXIucGF0aDtvLnB1c2goaSksby5wdXNoKCIwIiksby5wdXNoKCIxIiksby5wdXNoKCItLW1lbW9yeS1pbyIpLGUuZmxvYXRQYXJhbWV0ZXJzJiZlLmZsb2F0UGFyYW1ldGVycyYmby5wdXNoKCItLWZsb2F0LXBhcmFtZXRlcnMiKTtsZXQgQj0ibW5jLXJlYWQtdHJhbnNmb3JtIixzPWU/LndlYldvcmtlcjtzPT09dm9pZCAwJiYocz1hd2FpdCB3KCkpO2xldHt3ZWJXb3JrZXI6YSxyZXR1cm5WYWx1ZTpjLHN0ZGVycjpJLG91dHB1dHM6Q309YXdhaXQgeShCLG8sdCxuLHtwaXBlbGluZUJhc2VVcmw6aCgpLHBpcGVsaW5lV29ya2VyVXJsOmQoKSx3ZWJXb3JrZXI6cyxub0NvcHk6ZT8ubm9Db3B5fSk7aWYoYyE9PTAmJkkhPT0iIil0aHJvdyBuZXcgRXJyb3IoSSk7cmV0dXJue3dlYldvcmtlcjphLGNvdWxkUmVhZDpDWzBdPy5kYXRhLHRyYW5zZm9ybTpDWzFdPy5kYXRhfX12YXIgQ2U9bW87YXN5bmMgZnVuY3Rpb24geW8oQSxlLHQ9e30pe2xldCByPVt7dHlwZTpFLkpzb25Db21wYXRpYmxlfSx7dHlwZTpFLkJpbmFyeUZpbGUsZGF0YTp7cGF0aDplLGRhdGE6bmV3IFVpbnQ4QXJyYXl9fV0sbj1be3R5cGU6RS5UcmFuc2Zvcm1MaXN0LGRhdGE6QX1dLG89W107by5wdXNoKCIwIiksby5wdXNoKCIwIik7bGV0IHU9ZTtvLnB1c2godSksby5wdXNoKCItLW1lbW9yeS1pbyIpLHQuZmxvYXRQYXJhbWV0ZXJzJiZ0LmZsb2F0UGFyYW1ldGVycyYmby5wdXNoKCItLWZsb2F0LXBhcmFtZXRlcnMiKSx0LnVzZUNvbXByZXNzaW9uJiZ0LnVzZUNvbXByZXNzaW9uJiZvLnB1c2goIi0tdXNlLWNvbXByZXNzaW9uIik7bGV0IEI9Im1uYy13cml0ZS10cmFuc2Zvcm0iLHM9dD8ud2ViV29ya2VyO3M9PT12b2lkIDAmJihzPWF3YWl0IHcoKSk7bGV0e3dlYldvcmtlcjphLHJldHVyblZhbHVlOmMsc3RkZXJyOkksb3V0cHV0czpDfT1hd2FpdCB5KEIsbyxyLG4se3BpcGVsaW5lQmFzZVVybDpoKCkscGlwZWxpbmVXb3JrZXJVcmw6ZCgpLHdlYldvcmtlcjpzLG5vQ29weTp0Py5ub0NvcHl9KTtpZihjIT09MCYmSSE9PSIiKXRocm93IG5ldyBFcnJvcihJKTtyZXR1cm57d2ViV29ya2VyOmEsY291bGRXcml0ZTpDWzBdPy5kYXRhLHNlcmlhbGl6ZWRUcmFuc2Zvcm06Q1sxXT8uZGF0YX19dmFyIGZlPXlvO2FzeW5jIGZ1bmN0aW9uIGhvKEEsZT17fSl7bGV0IHQ9W3t0eXBlOkUuSnNvbkNvbXBhdGlibGV9LHt0eXBlOkUuVHJhbnNmb3JtTGlzdH1dLHI9QTtpZihBIGluc3RhbmNlb2YgRmlsZSl7bGV0IFE9YXdhaXQgQS5hcnJheUJ1ZmZlcigpO3I9e3BhdGg6QS5uYW1lLGRhdGE6bmV3IFVpbnQ4QXJyYXkoUSl9fWxldCBuPVt7dHlwZTpFLkJpbmFyeUZpbGUsZGF0YTpyfV0sbz1bXSxpPXIucGF0aDtvLnB1c2goaSksby5wdXNoKCIwIiksby5wdXNoKCIxIiksby5wdXNoKCItLW1lbW9yeS1pbyIpLGUuZmxvYXRQYXJhbWV0ZXJzJiZlLmZsb2F0UGFyYW1ldGVycyYmby5wdXNoKCItLWZsb2F0LXBhcmFtZXRlcnMiKTtsZXQgQj0idHh0LXJlYWQtdHJhbnNmb3JtIixzPWU/LndlYldvcmtlcjtzPT09dm9pZCAwJiYocz1hd2FpdCB3KCkpO2xldHt3ZWJXb3JrZXI6YSxyZXR1cm5WYWx1ZTpjLHN0ZGVycjpJLG91dHB1dHM6Q309YXdhaXQgeShCLG8sdCxuLHtwaXBlbGluZUJhc2VVcmw6aCgpLHBpcGVsaW5lV29ya2VyVXJsOmQoKSx3ZWJXb3JrZXI6cyxub0NvcHk6ZT8ubm9Db3B5fSk7aWYoYyE9PTAmJkkhPT0iIil0aHJvdyBuZXcgRXJyb3IoSSk7cmV0dXJue3dlYldvcmtlcjphLGNvdWxkUmVhZDpDWzBdPy5kYXRhLHRyYW5zZm9ybTpDWzFdPy5kYXRhfX12YXIgY2U9aG87YXN5bmMgZnVuY3Rpb24gd28oQSxlLHQ9e30pe2xldCByPVt7dHlwZTpFLkpzb25Db21wYXRpYmxlfSx7dHlwZTpFLkJpbmFyeUZpbGUsZGF0YTp7cGF0aDplLGRhdGE6bmV3IFVpbnQ4QXJyYXl9fV0sbj1be3R5cGU6RS5UcmFuc2Zvcm1MaXN0LGRhdGE6QX1dLG89W107by5wdXNoKCIwIiksby5wdXNoKCIwIik7bGV0IHU9ZTtvLnB1c2godSksby5wdXNoKCItLW1lbW9yeS1pbyIpLHQuZmxvYXRQYXJhbWV0ZXJzJiZ0LmZsb2F0UGFyYW1ldGVycyYmby5wdXNoKCItLWZsb2F0LXBhcmFtZXRlcnMiKSx0LnVzZUNvbXByZXNzaW9uJiZ0LnVzZUNvbXByZXNzaW9uJiZvLnB1c2goIi0tdXNlLWNvbXByZXNzaW9uIik7bGV0IEI9InR4dC13cml0ZS10cmFuc2Zvcm0iLHM9dD8ud2ViV29ya2VyO3M9PT12b2lkIDAmJihzPWF3YWl0IHcoKSk7bGV0e3dlYldvcmtlcjphLHJldHVyblZhbHVlOmMsc3RkZXJyOkksb3V0cHV0czpDfT1hd2FpdCB5KEIsbyxyLG4se3BpcGVsaW5lQmFzZVVybDpoKCkscGlwZWxpbmVXb3JrZXJVcmw6ZCgpLHdlYldvcmtlcjpzLG5vQ29weTp0Py5ub0NvcHl9KTtpZihjIT09MCYmSSE9PSIiKXRocm93IG5ldyBFcnJvcihJKTtyZXR1cm57d2ViV29ya2VyOmEsY291bGRXcml0ZTpDWzBdPy5kYXRhLHNlcmlhbGl6ZWRUcmFuc2Zvcm06Q1sxXT8uZGF0YX19dmFyIHVlPXdvO2FzeW5jIGZ1bmN0aW9uIERvKEEsZT17fSl7bGV0IHQ9W3t0eXBlOkUuSnNvbkNvbXBhdGlibGV9LHt0eXBlOkUuVHJhbnNmb3JtTGlzdH1dLHI9QTtpZihBIGluc3RhbmNlb2YgRmlsZSl7bGV0IFE9YXdhaXQgQS5hcnJheUJ1ZmZlcigpO3I9e3BhdGg6QS5uYW1lLGRhdGE6bmV3IFVpbnQ4QXJyYXkoUSl9fWxldCBuPVt7dHlwZTpFLkJpbmFyeUZpbGUsZGF0YTpyfV0sbz1bXSxpPXIucGF0aDtvLnB1c2goaSksby5wdXNoKCIwIiksby5wdXNoKCIxIiksby5wdXNoKCItLW1lbW9yeS1pbyIpLGUuZmxvYXRQYXJhbWV0ZXJzJiZlLmZsb2F0UGFyYW1ldGVycyYmby5wdXNoKCItLWZsb2F0LXBhcmFtZXRlcnMiKTtsZXQgQj0id2FzbS1yZWFkLXRyYW5zZm9ybSIscz1lPy53ZWJXb3JrZXI7cz09PXZvaWQgMCYmKHM9YXdhaXQgdygpKTtsZXR7d2ViV29ya2VyOmEscmV0dXJuVmFsdWU6YyxzdGRlcnI6SSxvdXRwdXRzOkN9PWF3YWl0IHkoQixvLHQsbix7cGlwZWxpbmVCYXNlVXJsOmgoKSxwaXBlbGluZVdvcmtlclVybDpkKCksd2ViV29ya2VyOnMsbm9Db3B5OmU/Lm5vQ29weX0pO2lmKGMhPT0wJiZJIT09IiIpdGhyb3cgbmV3IEVycm9yKEkpO3JldHVybnt3ZWJXb3JrZXI6YSxjb3VsZFJlYWQ6Q1swXT8uZGF0YSx0cmFuc2Zvcm06Q1sxXT8uZGF0YX19dmFyIEVlPURvO2FzeW5jIGZ1bmN0aW9uIFNvKEEsZSx0PXt9KXtsZXQgcj1be3R5cGU6RS5Kc29uQ29tcGF0aWJsZX0se3R5cGU6RS5CaW5hcnlGaWxlLGRhdGE6e3BhdGg6ZSxkYXRhOm5ldyBVaW50OEFycmF5fX1dLG49W3t0eXBlOkUuVHJhbnNmb3JtTGlzdCxkYXRhOkF9XSxvPVtdO28ucHVzaCgiMCIpLG8ucHVzaCgiMCIpO2xldCB1PWU7by5wdXNoKHUpLG8ucHVzaCgiLS1tZW1vcnktaW8iKSx0LmZsb2F0UGFyYW1ldGVycyYmdC5mbG9hdFBhcmFtZXRlcnMmJm8ucHVzaCgiLS1mbG9hdC1wYXJhbWV0ZXJzIiksdC51c2VDb21wcmVzc2lvbiYmdC51c2VDb21wcmVzc2lvbiYmby5wdXNoKCItLXVzZS1jb21wcmVzc2lvbiIpO2xldCBCPSJ3YXNtLXdyaXRlLXRyYW5zZm9ybSIscz10Py53ZWJXb3JrZXI7cz09PXZvaWQgMCYmKHM9YXdhaXQgdygpKTtsZXR7d2ViV29ya2VyOmEscmV0dXJuVmFsdWU6YyxzdGRlcnI6SSxvdXRwdXRzOkN9PWF3YWl0IHkoQixvLHIsbix7cGlwZWxpbmVCYXNlVXJsOmgoKSxwaXBlbGluZVdvcmtlclVybDpkKCksd2ViV29ya2VyOnMsbm9Db3B5OnQ/Lm5vQ29weX0pO2lmKGMhPT0wJiZJIT09IiIpdGhyb3cgbmV3IEVycm9yKEkpO3JldHVybnt3ZWJXb3JrZXI6YSxjb3VsZFdyaXRlOkNbMF0/LmRhdGEsc2VyaWFsaXplZFRyYW5zZm9ybTpDWzFdPy5kYXRhfX12YXIgUWU9U287YXN5bmMgZnVuY3Rpb24gUm8oQSxlPXt9KXtsZXQgdD1be3R5cGU6RS5Kc29uQ29tcGF0aWJsZX0se3R5cGU6RS5UcmFuc2Zvcm1MaXN0fV0scj1BO2lmKEEgaW5zdGFuY2VvZiBGaWxlKXtsZXQgUT1hd2FpdCBBLmFycmF5QnVmZmVyKCk7cj17cGF0aDpBLm5hbWUsZGF0YTpuZXcgVWludDhBcnJheShRKX19bGV0IG49W3t0eXBlOkUuQmluYXJ5RmlsZSxkYXRhOnJ9XSxvPVtdLGk9ci5wYXRoO28ucHVzaChpKSxvLnB1c2goIjAiKSxvLnB1c2goIjEiKSxvLnB1c2goIi0tbWVtb3J5LWlvIiksZS5mbG9hdFBhcmFtZXRlcnMmJmUuZmxvYXRQYXJhbWV0ZXJzJiZvLnB1c2goIi0tZmxvYXQtcGFyYW1ldGVycyIpO2xldCBCPSJ3YXNtLXpzdGQtcmVhZC10cmFuc2Zvcm0iLHM9ZT8ud2ViV29ya2VyO3M9PT12b2lkIDAmJihzPWF3YWl0IHcoKSk7bGV0e3dlYldvcmtlcjphLHJldHVyblZhbHVlOmMsc3RkZXJyOkksb3V0cHV0czpDfT1hd2FpdCB5KEIsbyx0LG4se3BpcGVsaW5lQmFzZVVybDpoKCkscGlwZWxpbmVXb3JrZXJVcmw6ZCgpLHdlYldvcmtlcjpzLG5vQ29weTplPy5ub0NvcHl9KTtpZihjIT09MCYmSSE9PSIiKXRocm93IG5ldyBFcnJvcihJKTtyZXR1cm57d2ViV29ya2VyOmEsY291bGRSZWFkOkNbMF0/LmRhdGEsdHJhbnNmb3JtOkNbMV0/LmRhdGF9fXZhciBwZT1Sbzthc3luYyBmdW5jdGlvbiBibyhBLGUsdD17fSl7bGV0IHI9W3t0eXBlOkUuSnNvbkNvbXBhdGlibGV9LHt0eXBlOkUuQmluYXJ5RmlsZSxkYXRhOntwYXRoOmUsZGF0YTpuZXcgVWludDhBcnJheX19XSxuPVt7dHlwZTpFLlRyYW5zZm9ybUxpc3QsZGF0YTpBfV0sbz1bXTtvLnB1c2goIjAiKSxvLnB1c2goIjAiKTtsZXQgdT1lO28ucHVzaCh1KSxvLnB1c2goIi0tbWVtb3J5LWlvIiksdC5mbG9hdFBhcmFtZXRlcnMmJnQuZmxvYXRQYXJhbWV0ZXJzJiZvLnB1c2goIi0tZmxvYXQtcGFyYW1ldGVycyIpLHQudXNlQ29tcHJlc3Npb24mJnQudXNlQ29tcHJlc3Npb24mJm8ucHVzaCgiLS11c2UtY29tcHJlc3Npb24iKTtsZXQgQj0id2FzbS16c3RkLXdyaXRlLXRyYW5zZm9ybSIscz10Py53ZWJXb3JrZXI7cz09PXZvaWQgMCYmKHM9YXdhaXQgdygpKTtsZXR7d2ViV29ya2VyOmEscmV0dXJuVmFsdWU6YyxzdGRlcnI6SSxvdXRwdXRzOkN9PWF3YWl0IHkoQixvLHIsbix7cGlwZWxpbmVCYXNlVXJsOmgoKSxwaXBlbGluZVdvcmtlclVybDpkKCksd2ViV29ya2VyOnMsbm9Db3B5OnQ/Lm5vQ29weX0pO2lmKGMhPT0wJiZJIT09IiIpdGhyb3cgbmV3IEVycm9yKEkpO3JldHVybnt3ZWJXb3JrZXI6YSxjb3VsZFdyaXRlOkNbMF0/LmRhdGEsc2VyaWFsaXplZFRyYW5zZm9ybTpDWzFdPy5kYXRhfX12YXIgbWU9Ym87dmFyIGtvPW5ldyBNYXAoW1siaGRmNSIsW0llLGdlXV0sWyJtYXQiLFtsZSxCZV1dLFsibW5jIixbQ2UsZmVdXSxbInR4dCIsW2NlLHVlXV0sWyJ3YXNtIixbRWUsUWVdXSxbIndhc21ac3RkIixbcGUsbWVdXV0pLCQ9a287YXN5bmMgZnVuY3Rpb24gRm8oQSxlPXt9KXtsZXQgdD1BLnR5cGU/PyIiLHI9QS5uYW1lPz9BLnBhdGg/PyJmaWxlTmFtZSIsbj1BQShyKS50b0xvd2VyQ2FzZSgpLG89ZT8ud2ViV29ya2VyLGk9QTtpZihBIGluc3RhbmNlb2YgQmxvYil7bGV0IEk9YXdhaXQgQS5hcnJheUJ1ZmZlcigpO2k9e3BhdGg6QS5uYW1lLGRhdGE6bmV3IFVpbnQ4QXJyYXkoSSl9fWxldCBsPW51bGw7aWYodCYmWi5oYXModCkpbD1aLmdldCh0KTtlbHNlIGlmKFYuaGFzKG4pKWw9Vi5nZXQobik7ZWxzZSBmb3IobGV0IEkgb2YgJC52YWx1ZXMoKSlpZihJWzBdIT09bnVsbCl7bGV0e3dlYldvcmtlcjpDLGNvdWxkUmVhZDpmLHRyYW5zZm9ybTpRfT1hd2FpdCBJWzBdKHtwYXRoOmkucGF0aCxkYXRhOmkuZGF0YS5zbGljZSgpfSx7ZmxvYXRQYXJhbWV0ZXJzOmUuZmxvYXRQYXJhbWV0ZXJzLHdlYldvcmtlcjpvLG5vQ29weTplPy5ub0NvcHl9KTtpZihvPUMsZilyZXR1cm57d2ViV29ya2VyOm8sdHJhbnNmb3JtOlF9fWlmKCFsKXRocm93IEVycm9yKCJDb3VsZCBub3QgZmluZCBJTyBmb3I6ICIrcik7bGV0IEI9JC5nZXQobClbMF0se3dlYldvcmtlcjpzLGNvdWxkUmVhZDphLHRyYW5zZm9ybTpjfT1hd2FpdCBCKGkse2Zsb2F0UGFyYW1ldGVyczplLmZsb2F0UGFyYW1ldGVycyx3ZWJXb3JrZXI6byxub0NvcHk6ZT8ubm9Db3B5fSk7aWYobz1zLCFhKXRocm93IEVycm9yKCJDb3VsZCBub3QgcmVhZDogIityKTtyZXR1cm57d2ViV29ya2VyOm8sdHJhbnNmb3JtOmN9fXZhciBVbz1Gbzthc3luYyBmdW5jdGlvbiBObyhBLGUsdD17fSl7bGV0IHI9QSxuPXQubWltZVR5cGUsbz1BQShlKS50b0xvd2VyQ2FzZSgpLGk9dC53ZWJXb3JrZXIsbD1udWxsO2lmKHR5cGVvZiBuPCJ1IiYmWi5oYXMobikpbD1aLmdldChuKTtlbHNlIGlmKFYuaGFzKG8pKWw9Vi5nZXQobyk7ZWxzZSBmb3IobGV0IEMgb2YgJC52YWx1ZXMoKSlpZihDWzFdIT09bnVsbCl7bGV0e3dlYldvcmtlcjpmLGNvdWxkV3JpdGU6USxzZXJpYWxpemVkVHJhbnNmb3JtOm19PWF3YWl0IENbMV0ocixlLHQpO2lmKGk9ZixRKXJldHVybnt3ZWJXb3JrZXI6aSxzZXJpYWxpemVkVHJhbnNmb3JtOm19fWlmKCFsKXRocm93IEVycm9yKCJDb3VsZCBub3QgZmluZCBJTyBmb3I6ICIrZSk7bGV0IEI9JC5nZXQobClbMV0se3dlYldvcmtlcjpzLGNvdWxkV3JpdGU6YSxzZXJpYWxpemVkVHJhbnNmb3JtOmN9PWF3YWl0IEIocixlLHQpO2lmKGk9cywhYSl0aHJvdyBFcnJvcigiQ291bGQgbm90IHdyaXRlOiAiK2UpO3JldHVybnt3ZWJXb3JrZXI6aSxzZXJpYWxpemVkVHJhbnNmb3JtOmN9fXZhciBUbz1Obzt2YXIga3Q9J2RhdGE6dGV4dC9qYXZhc2NyaXB0O2NoYXJzZXQ9dXRmLTgsdmFyIElJPU9iamVjdC5kZWZpbmVQcm9wZXJ0eTt2YXIgZUk9KEEsdCk9Pntmb3IodmFyIEkgaW4gdClJSShBLEkse2dldDp0W0ldLGVudW1lcmFibGU6ITB9KX07dmFyIHZBPVN5bWJvbCgiQ29tbGluay5wcm94eSIpLGdJPVN5bWJvbCgiQ29tbGluay5lbmRwb2ludCIpLHJJPVN5bWJvbCgiQ29tbGluay5yZWxlYXNlUHJveHkiKSxwQT1TeW1ib2woIkNvbWxpbmsuZmluYWxpemVyIiksZ0E9U3ltYm9sKCJDb21saW5rLnRocm93biIpLCRBPUE9PnR5cGVvZiBBPT0ib2JqZWN0IiYmQSE9PW51bGx8fHR5cGVvZiBBPT0iZnVuY3Rpb24iLG9JPXtjYW5IYW5kbGU6QT0+JEEoQSkmJkFbdkFdLHNlcmlhbGl6ZShBKXtsZXR7cG9ydDE6dCxwb3J0MjpJfT1uZXcgTWVzc2FnZUNoYW5uZWw7cmV0dXJuIENBKEEsdCksW0ksW0ldXX0sZGVzZXJpYWxpemUoQSl7cmV0dXJuIEEuc3RhcnQoKSxzSShBKX19LGlJPXtjYW5IYW5kbGU6QT0+JEEoQSkmJmdBIGluIEEsc2VyaWFsaXplKHt2YWx1ZTpBfSl7bGV0IHQ7cmV0dXJuIEEgaW5zdGFuY2VvZiBFcnJvcj90PXtpc0Vycm9yOiEwLHZhbHVlOnttZXNzYWdlOkEubWVzc2FnZSxuYW1lOkEubmFtZSxzdGFjazpBLnN0YWNrfX06dD17aXNFcnJvcjohMSx2YWx1ZTpBfSxbdCxbXV19LGRlc2VyaWFsaXplKEEpe3Rocm93IEEuaXNFcnJvcj9PYmplY3QuYXNzaWduKG5ldyBFcnJvcihBLnZhbHVlLm1lc3NhZ2UpLEEudmFsdWUpOkEudmFsdWV9fSxBdD1uZXcgTWFwKFtbInByb3h5IixvSV0sWyJ0aHJvdyIsaUldXSk7ZnVuY3Rpb24gQ0koQSx0KXtmb3IobGV0IEkgb2YgQSlpZih0PT09SXx8ST09PSIqInx8SSBpbnN0YW5jZW9mIFJlZ0V4cCYmSS50ZXN0KHQpKXJldHVybiEwO3JldHVybiExfWZ1bmN0aW9uIENBKEEsdD1nbG9iYWxUaGlzLEk9WyIqIl0pe3QuYWRkRXZlbnRMaXN0ZW5lcigibWVzc2FnZSIsZnVuY3Rpb24gZShnKXtpZighZ3x8IWcuZGF0YSlyZXR1cm47aWYoIUNJKEksZy5vcmlnaW4pKXtjb25zb2xlLndhcm4oYEludmFsaWQgb3JpZ2luIFwnJHtnLm9yaWdpbn1cJyBmb3IgY29tbGluayBwcm94eWApO3JldHVybn1sZXR7aWQ6cix0eXBlOm8scGF0aDpufT1PYmplY3QuYXNzaWduKHtwYXRoOltdfSxnLmRhdGEpLGM9KGcuZGF0YS5hcmd1bWVudExpc3R8fFtdKS5tYXAoTSksUTt0cnl7bGV0IEI9bi5zbGljZSgwLC0xKS5yZWR1Y2UoKGYscyk9PmZbc10sQSksaT1uLnJlZHVjZSgoZixzKT0+ZltzXSxBKTtzd2l0Y2gobyl7Y2FzZSJHRVQiOlE9aTticmVhaztjYXNlIlNFVCI6QltuLnNsaWNlKC0xKVswXV09TShnLmRhdGEudmFsdWUpLFE9ITA7YnJlYWs7Y2FzZSJBUFBMWSI6UT1pLmFwcGx5KEIsYyk7YnJlYWs7Y2FzZSJDT05TVFJVQ1QiOntsZXQgZj1uZXcgaSguLi5jKTtRPUVJKGYpfWJyZWFrO2Nhc2UiRU5EUE9JTlQiOntsZXR7cG9ydDE6Zixwb3J0MjpzfT1uZXcgTWVzc2FnZUNoYW5uZWw7Q0EoQSxzKSxRPUZBKGYsW2ZdKX1icmVhaztjYXNlIlJFTEVBU0UiOlE9dm9pZCAwO2JyZWFrO2RlZmF1bHQ6cmV0dXJufX1jYXRjaChCKXtRPXt2YWx1ZTpCLFtnQV06MH19UHJvbWlzZS5yZXNvbHZlKFEpLmNhdGNoKEI9Pih7dmFsdWU6QixbZ0FdOjB9KSkudGhlbihCPT57bGV0W2ksZl09aUEoQik7dC5wb3N0TWVzc2FnZShPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30saSkse2lkOnJ9KSxmKSxvPT09IlJFTEVBU0UiJiYodC5yZW1vdmVFdmVudExpc3RlbmVyKCJtZXNzYWdlIixlKSx0dCh0KSxwQSBpbiBBJiZ0eXBlb2YgQVtwQV09PSJmdW5jdGlvbiImJkFbcEFdKCkpfSkuY2F0Y2goQj0+e2xldFtpLGZdPWlBKHt2YWx1ZTpuZXcgVHlwZUVycm9yKCJVbnNlcmlhbGl6YWJsZSByZXR1cm4gdmFsdWUiKSxbZ0FdOjB9KTt0LnBvc3RNZXNzYWdlKE9iamVjdC5hc3NpZ24oT2JqZWN0LmFzc2lnbih7fSxpKSx7aWQ6cn0pLGYpfSl9KSx0LnN0YXJ0JiZ0LnN0YXJ0KCl9ZnVuY3Rpb24gQkkoQSl7cmV0dXJuIEEuY29uc3RydWN0b3IubmFtZT09PSJNZXNzYWdlUG9ydCJ9ZnVuY3Rpb24gdHQoQSl7QkkoQSkmJkEuY2xvc2UoKX1mdW5jdGlvbiBzSShBLHQpe3JldHVybiBTQShBLFtdLHQpfWZ1bmN0aW9uIGVBKEEpe2lmKEEpdGhyb3cgbmV3IEVycm9yKCJQcm94eSBoYXMgYmVlbiByZWxlYXNlZCBhbmQgaXMgbm90IHVzZWFibGUiKX1mdW5jdGlvbiBJdChBKXtyZXR1cm4gcShBLHt0eXBlOiJSRUxFQVNFIn0pLnRoZW4oKCk9Pnt0dChBKX0pfXZhciByQT1uZXcgV2Vha01hcCxvQT0iRmluYWxpemF0aW9uUmVnaXN0cnkiaW4gZ2xvYmFsVGhpcyYmbmV3IEZpbmFsaXphdGlvblJlZ2lzdHJ5KEE9PntsZXQgdD0ockEuZ2V0KEEpfHwwKS0xO3JBLnNldChBLHQpLHQ9PT0wJiZJdChBKX0pO2Z1bmN0aW9uIG5JKEEsdCl7bGV0IEk9KHJBLmdldCh0KXx8MCkrMTtyQS5zZXQodCxJKSxvQSYmb0EucmVnaXN0ZXIoQSx0LEEpfWZ1bmN0aW9uIFFJKEEpe29BJiZvQS51bnJlZ2lzdGVyKEEpfWZ1bmN0aW9uIFNBKEEsdD1bXSxJPWZ1bmN0aW9uKCl7fSl7bGV0IGU9ITEsZz1uZXcgUHJveHkoSSx7Z2V0KHIsbyl7aWYoZUEoZSksbz09PXJJKXJldHVybigpPT57UUkoZyksSXQoQSksZT0hMH07aWYobz09PSJ0aGVuIil7aWYodC5sZW5ndGg9PT0wKXJldHVybnt0aGVuOigpPT5nfTtsZXQgbj1xKEEse3R5cGU6IkdFVCIscGF0aDp0Lm1hcChjPT5jLnRvU3RyaW5nKCkpfSkudGhlbihNKTtyZXR1cm4gbi50aGVuLmJpbmQobil9cmV0dXJuIFNBKEEsWy4uLnQsb10pfSxzZXQocixvLG4pe2VBKGUpO2xldFtjLFFdPWlBKG4pO3JldHVybiBxKEEse3R5cGU6IlNFVCIscGF0aDpbLi4udCxvXS5tYXAoQj0+Qi50b1N0cmluZygpKSx2YWx1ZTpjfSxRKS50aGVuKE0pfSxhcHBseShyLG8sbil7ZUEoZSk7bGV0IGM9dFt0Lmxlbmd0aC0xXTtpZihjPT09Z0kpcmV0dXJuIHEoQSx7dHlwZToiRU5EUE9JTlQifSkudGhlbihNKTtpZihjPT09ImJpbmQiKXJldHVybiBTQShBLHQuc2xpY2UoMCwtMSkpO2xldFtRLEJdPV9BKG4pO3JldHVybiBxKEEse3R5cGU6IkFQUExZIixwYXRoOnQubWFwKGk9PmkudG9TdHJpbmcoKSksYXJndW1lbnRMaXN0OlF9LEIpLnRoZW4oTSl9LGNvbnN0cnVjdChyLG8pe2VBKGUpO2xldFtuLGNdPV9BKG8pO3JldHVybiBxKEEse3R5cGU6IkNPTlNUUlVDVCIscGF0aDp0Lm1hcChRPT5RLnRvU3RyaW5nKCkpLGFyZ3VtZW50TGlzdDpufSxjKS50aGVuKE0pfX0pO3JldHVybiBuSShnLEEpLGd9ZnVuY3Rpb24gYUkoQSl7cmV0dXJuIEFycmF5LnByb3RvdHlwZS5jb25jYXQuYXBwbHkoW10sQSl9ZnVuY3Rpb24gX0EoQSl7bGV0IHQ9QS5tYXAoaUEpO3JldHVyblt0Lm1hcChJPT5JWzBdKSxhSSh0Lm1hcChJPT5JWzFdKSldfXZhciBldD1uZXcgV2Vha01hcDtmdW5jdGlvbiBGQShBLHQpe3JldHVybiBldC5zZXQoQSx0KSxBfWZ1bmN0aW9uIEVJKEEpe3JldHVybiBPYmplY3QuYXNzaWduKEEse1t2QV06ITB9KX1mdW5jdGlvbiBpQShBKXtmb3IobGV0W3QsSV1vZiBBdClpZihJLmNhbkhhbmRsZShBKSl7bGV0W2UsZ109SS5zZXJpYWxpemUoQSk7cmV0dXJuW3t0eXBlOiJIQU5ETEVSIixuYW1lOnQsdmFsdWU6ZX0sZ119cmV0dXJuW3t0eXBlOiJSQVciLHZhbHVlOkF9LGV0LmdldChBKXx8W11dfWZ1bmN0aW9uIE0oQSl7c3dpdGNoKEEudHlwZSl7Y2FzZSJIQU5ETEVSIjpyZXR1cm4gQXQuZ2V0KEEubmFtZSkuZGVzZXJpYWxpemUoQS52YWx1ZSk7Y2FzZSJSQVciOnJldHVybiBBLnZhbHVlfX1mdW5jdGlvbiBxKEEsdCxJKXtyZXR1cm4gbmV3IFByb21pc2UoZT0+e2xldCBnPWNJKCk7QS5hZGRFdmVudExpc3RlbmVyKCJtZXNzYWdlIixmdW5jdGlvbiByKG8peyFvLmRhdGF8fCFvLmRhdGEuaWR8fG8uZGF0YS5pZCE9PWd8fChBLnJlbW92ZUV2ZW50TGlzdGVuZXIoIm1lc3NhZ2UiLHIpLGUoby5kYXRhKSl9KSxBLnN0YXJ0JiZBLnN0YXJ0KCksQS5wb3N0TWVzc2FnZShPYmplY3QuYXNzaWduKHtpZDpnfSx0KSxJKX0pfWZ1bmN0aW9uIGNJKCl7cmV0dXJuIG5ldyBBcnJheSg0KS5maWxsKDApLm1hcCgoKT0+TWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpKk51bWJlci5NQVhfU0FGRV9JTlRFR0VSKS50b1N0cmluZygxNikpLmpvaW4oIi0iKX1mdW5jdGlvbiBXKEEsdCl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIEEuYXBwbHkodCxhcmd1bWVudHMpfX12YXJ7dG9TdHJpbmc6Zkl9PU9iamVjdC5wcm90b3R5cGUse2dldFByb3RvdHlwZU9mOlVBfT1PYmplY3Qsc0E9KEE9PnQ9PntsZXQgST1mSS5jYWxsKHQpO3JldHVybiBBW0ldfHwoQVtJXT1JLnNsaWNlKDgsLTEpLnRvTG93ZXJDYXNlKCkpfSkoT2JqZWN0LmNyZWF0ZShudWxsKSksVT1BPT4oQT1BLnRvTG93ZXJDYXNlKCksdD0+c0EodCk9PT1BKSxuQT1BPT50PT50eXBlb2YgdD09PUEse2lzQXJyYXk6S309QXJyYXksWj1uQSgidW5kZWZpbmVkIik7ZnVuY3Rpb24gbEkoQSl7cmV0dXJuIEEhPT1udWxsJiYhWihBKSYmQS5jb25zdHJ1Y3RvciE9PW51bGwmJiFaKEEuY29uc3RydWN0b3IpJiZOKEEuY29uc3RydWN0b3IuaXNCdWZmZXIpJiZBLmNvbnN0cnVjdG9yLmlzQnVmZmVyKEEpfXZhciBpdD1VKCJBcnJheUJ1ZmZlciIpO2Z1bmN0aW9uIERJKEEpe2xldCB0O3JldHVybiB0eXBlb2YgQXJyYXlCdWZmZXI8InUiJiZBcnJheUJ1ZmZlci5pc1ZpZXc/dD1BcnJheUJ1ZmZlci5pc1ZpZXcoQSk6dD1BJiZBLmJ1ZmZlciYmaXQoQS5idWZmZXIpLHR9dmFyIHVJPW5BKCJzdHJpbmciKSxOPW5BKCJmdW5jdGlvbiIpLEN0PW5BKCJudW1iZXIiKSxRQT1BPT5BIT09bnVsbCYmdHlwZW9mIEE9PSJvYmplY3QiLGhJPUE9PkE9PT0hMHx8QT09PSExLEJBPUE9PntpZihzQShBKSE9PSJvYmplY3QiKXJldHVybiExO2xldCB0PVVBKEEpO3JldHVybih0PT09bnVsbHx8dD09PU9iamVjdC5wcm90b3R5cGV8fE9iamVjdC5nZXRQcm90b3R5cGVPZih0KT09PW51bGwpJiYhKFN5bWJvbC50b1N0cmluZ1RhZyBpbiBBKSYmIShTeW1ib2wuaXRlcmF0b3IgaW4gQSl9LGRJPVUoIkRhdGUiKSx5ST1VKCJGaWxlIiksd0k9VSgiQmxvYiIpLG1JPVUoIkZpbGVMaXN0IikscEk9QT0+UUEoQSkmJk4oQS5waXBlKSxTST1BPT57bGV0IHQ7cmV0dXJuIEEmJih0eXBlb2YgRm9ybURhdGE9PSJmdW5jdGlvbiImJkEgaW5zdGFuY2VvZiBGb3JtRGF0YXx8TihBLmFwcGVuZCkmJigodD1zQShBKSk9PT0iZm9ybWRhdGEifHx0PT09Im9iamVjdCImJk4oQS50b1N0cmluZykmJkEudG9TdHJpbmcoKT09PSJbb2JqZWN0IEZvcm1EYXRhXSIpKX0sRkk9VSgiVVJMU2VhcmNoUGFyYW1zIiksUkk9QT0+QS50cmltP0EudHJpbSgpOkEucmVwbGFjZSgvXltcXHNcXHVGRUZGXFx4QTBdK3xbXFxzXFx1RkVGRlxceEEwXSskL2csIiIpO2Z1bmN0aW9uIFYoQSx0LHthbGxPd25LZXlzOkk9ITF9PXt9KXtpZihBPT09bnVsbHx8dHlwZW9mIEE+InUiKXJldHVybjtsZXQgZSxnO2lmKHR5cGVvZiBBIT0ib2JqZWN0IiYmKEE9W0FdKSxLKEEpKWZvcihlPTAsZz1BLmxlbmd0aDtlPGc7ZSsrKXQuY2FsbChudWxsLEFbZV0sZSxBKTtlbHNle2xldCByPUk/T2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMoQSk6T2JqZWN0LmtleXMoQSksbz1yLmxlbmd0aCxuO2ZvcihlPTA7ZTxvO2UrKyluPXJbZV0sdC5jYWxsKG51bGwsQVtuXSxuLEEpfX1mdW5jdGlvbiBCdChBLHQpe3Q9dC50b0xvd2VyQ2FzZSgpO2xldCBJPU9iamVjdC5rZXlzKEEpLGU9SS5sZW5ndGgsZztmb3IoO2UtLSA+MDspaWYoZz1JW2VdLHQ9PT1nLnRvTG93ZXJDYXNlKCkpcmV0dXJuIGc7cmV0dXJuIG51bGx9dmFyIHN0PXR5cGVvZiBnbG9iYWxUaGlzPCJ1Ij9nbG9iYWxUaGlzOnR5cGVvZiBzZWxmPCJ1Ij9zZWxmOnR5cGVvZiB3aW5kb3c8InUiP3dpbmRvdzpnbG9iYWwsbnQ9QT0+IVooQSkmJkEhPT1zdDtmdW5jdGlvbiBOQSgpe2xldHtjYXNlbGVzczpBfT1udCh0aGlzKSYmdGhpc3x8e30sdD17fSxJPShlLGcpPT57bGV0IHI9QSYmQnQodCxnKXx8ZztCQSh0W3JdKSYmQkEoZSk/dFtyXT1OQSh0W3JdLGUpOkJBKGUpP3Rbcl09TkEoe30sZSk6SyhlKT90W3JdPWUuc2xpY2UoKTp0W3JdPWV9O2ZvcihsZXQgZT0wLGc9YXJndW1lbnRzLmxlbmd0aDtlPGc7ZSsrKWFyZ3VtZW50c1tlXSYmVihhcmd1bWVudHNbZV0sSSk7cmV0dXJuIHR9dmFyIE5JPShBLHQsSSx7YWxsT3duS2V5czplfT17fSk9PihWKHQsKGcscik9PntJJiZOKGcpP0Fbcl09VyhnLEkpOkFbcl09Z30se2FsbE93bktleXM6ZX0pLEEpLFVJPUE9PihBLmNoYXJDb2RlQXQoMCk9PT02NTI3OSYmKEE9QS5zbGljZSgxKSksQSksR0k9KEEsdCxJLGUpPT57QS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0LnByb3RvdHlwZSxlKSxBLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1BLE9iamVjdC5kZWZpbmVQcm9wZXJ0eShBLCJzdXBlciIse3ZhbHVlOnQucHJvdG90eXBlfSksSSYmT2JqZWN0LmFzc2lnbihBLnByb3RvdHlwZSxJKX0sa0k9KEEsdCxJLGUpPT57bGV0IGcscixvLG49e307aWYodD10fHx7fSxBPT1udWxsKXJldHVybiB0O2Rve2ZvcihnPU9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKEEpLHI9Zy5sZW5ndGg7ci0tID4wOylvPWdbcl0sKCFlfHxlKG8sQSx0KSkmJiFuW29dJiYodFtvXT1BW29dLG5bb109ITApO0E9SSE9PSExJiZVQShBKX13aGlsZShBJiYoIUl8fEkoQSx0KSkmJkEhPT1PYmplY3QucHJvdG90eXBlKTtyZXR1cm4gdH0sTEk9KEEsdCxJKT0+e0E9U3RyaW5nKEEpLChJPT09dm9pZCAwfHxJPkEubGVuZ3RoKSYmKEk9QS5sZW5ndGgpLEktPXQubGVuZ3RoO2xldCBlPUEuaW5kZXhPZih0LEkpO3JldHVybiBlIT09LTEmJmU9PT1JfSxKST1BPT57aWYoIUEpcmV0dXJuIG51bGw7aWYoSyhBKSlyZXR1cm4gQTtsZXQgdD1BLmxlbmd0aDtpZighQ3QodCkpcmV0dXJuIG51bGw7bGV0IEk9bmV3IEFycmF5KHQpO2Zvcig7dC0tID4wOylJW3RdPUFbdF07cmV0dXJuIEl9LEhJPShBPT50PT5BJiZ0IGluc3RhbmNlb2YgQSkodHlwZW9mIFVpbnQ4QXJyYXk8InUiJiZVQShVaW50OEFycmF5KSksWUk9KEEsdCk9PntsZXQgZT0oQSYmQVtTeW1ib2wuaXRlcmF0b3JdKS5jYWxsKEEpLGc7Zm9yKDsoZz1lLm5leHQoKSkmJiFnLmRvbmU7KXtsZXQgcj1nLnZhbHVlO3QuY2FsbChBLHJbMF0sclsxXSl9fSxiST0oQSx0KT0+e2xldCBJLGU9W107Zm9yKDsoST1BLmV4ZWModCkpIT09bnVsbDspZS5wdXNoKEkpO3JldHVybiBlfSxNST1VKCJIVE1MRm9ybUVsZW1lbnQiKSxxST1BPT5BLnRvTG93ZXJDYXNlKCkucmVwbGFjZSgvWy1fXFxzXShbYS16XFxkXSkoXFx3KikvZyxmdW5jdGlvbihJLGUsZyl7cmV0dXJuIGUudG9VcHBlckNhc2UoKStnfSkscnQ9KCh7aGFzT3duUHJvcGVydHk6QX0pPT4odCxJKT0+QS5jYWxsKHQsSSkpKE9iamVjdC5wcm90b3R5cGUpLEtJPVUoIlJlZ0V4cCIpLFF0PShBLHQpPT57bGV0IEk9T2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcnMoQSksZT17fTtWKEksKGcscik9PntsZXQgbzsobz10KGcscixBKSkhPT0hMSYmKGVbcl09b3x8Zyl9KSxPYmplY3QuZGVmaW5lUHJvcGVydGllcyhBLGUpfSxPST1BPT57UXQoQSwodCxJKT0+e2lmKE4oQSkmJlsiYXJndW1lbnRzIiwiY2FsbGVyIiwiY2FsbGVlIl0uaW5kZXhPZihJKSE9PS0xKXJldHVybiExO2xldCBlPUFbSV07aWYoTihlKSl7aWYodC5lbnVtZXJhYmxlPSExLCJ3cml0YWJsZSJpbiB0KXt0LndyaXRhYmxlPSExO3JldHVybn10LnNldHx8KHQuc2V0PSgpPT57dGhyb3cgRXJyb3IoIkNhbiBub3QgcmV3cml0ZSByZWFkLW9ubHkgbWV0aG9kIFwnIitJKyJcJyIpfSl9fSl9LFRJPShBLHQpPT57bGV0IEk9e30sZT1nPT57Zy5mb3JFYWNoKHI9PntJW3JdPSEwfSl9O3JldHVybiBLKEEpP2UoQSk6ZShTdHJpbmcoQSkuc3BsaXQodCkpLEl9LFBJPSgpPT57fSx4ST0oQSx0KT0+KEE9K0EsTnVtYmVyLmlzRmluaXRlKEEpP0E6dCksUkE9ImFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6IixvdD0iMDEyMzQ1Njc4OSIsYXQ9e0RJR0lUOm90LEFMUEhBOlJBLEFMUEhBX0RJR0lUOlJBK1JBLnRvVXBwZXJDYXNlKCkrb3R9LGpJPShBPTE2LHQ9YXQuQUxQSEFfRElHSVQpPT57bGV0IEk9IiIse2xlbmd0aDplfT10O2Zvcig7QS0tOylJKz10W01hdGgucmFuZG9tKCkqZXwwXTtyZXR1cm4gSX07ZnVuY3Rpb24gV0koQSl7cmV0dXJuISEoQSYmTihBLmFwcGVuZCkmJkFbU3ltYm9sLnRvU3RyaW5nVGFnXT09PSJGb3JtRGF0YSImJkFbU3ltYm9sLml0ZXJhdG9yXSl9dmFyIFpJPUE9PntsZXQgdD1uZXcgQXJyYXkoMTApLEk9KGUsZyk9PntpZihRQShlKSl7aWYodC5pbmRleE9mKGUpPj0wKXJldHVybjtpZighKCJ0b0pTT04iaW4gZSkpe3RbZ109ZTtsZXQgcj1LKGUpP1tdOnt9O3JldHVybiBWKGUsKG8sbik9PntsZXQgYz1JKG8sZysxKTshWihjKSYmKHJbbl09Yyl9KSx0W2ddPXZvaWQgMCxyfX1yZXR1cm4gZX07cmV0dXJuIEkoQSwwKX0sVkk9VSgiQXN5bmNGdW5jdGlvbiIpLFhJPUE9PkEmJihRQShBKXx8TihBKSkmJk4oQS50aGVuKSYmTihBLmNhdGNoKSxDPXtpc0FycmF5OkssaXNBcnJheUJ1ZmZlcjppdCxpc0J1ZmZlcjpsSSxpc0Zvcm1EYXRhOlNJLGlzQXJyYXlCdWZmZXJWaWV3OkRJLGlzU3RyaW5nOnVJLGlzTnVtYmVyOkN0LGlzQm9vbGVhbjpoSSxpc09iamVjdDpRQSxpc1BsYWluT2JqZWN0OkJBLGlzVW5kZWZpbmVkOlosaXNEYXRlOmRJLGlzRmlsZTp5SSxpc0Jsb2I6d0ksaXNSZWdFeHA6S0ksaXNGdW5jdGlvbjpOLGlzU3RyZWFtOnBJLGlzVVJMU2VhcmNoUGFyYW1zOkZJLGlzVHlwZWRBcnJheTpISSxpc0ZpbGVMaXN0Om1JLGZvckVhY2g6VixtZXJnZTpOQSxleHRlbmQ6TkksdHJpbTpSSSxzdHJpcEJPTTpVSSxpbmhlcml0czpHSSx0b0ZsYXRPYmplY3Q6a0ksa2luZE9mOnNBLGtpbmRPZlRlc3Q6VSxlbmRzV2l0aDpMSSx0b0FycmF5OkpJLGZvckVhY2hFbnRyeTpZSSxtYXRjaEFsbDpiSSxpc0hUTUxGb3JtOk1JLGhhc093blByb3BlcnR5OnJ0LGhhc093blByb3A6cnQscmVkdWNlRGVzY3JpcHRvcnM6UXQsZnJlZXplTWV0aG9kczpPSSx0b09iamVjdFNldDpUSSx0b0NhbWVsQ2FzZTpxSSxub29wOlBJLHRvRmluaXRlTnVtYmVyOnhJLGZpbmRLZXk6QnQsZ2xvYmFsOnN0LGlzQ29udGV4dERlZmluZWQ6bnQsQUxQSEFCRVQ6YXQsZ2VuZXJhdGVTdHJpbmc6akksaXNTcGVjQ29tcGxpYW50Rm9ybTpXSSx0b0pTT05PYmplY3Q6WkksaXNBc3luY0ZuOlZJLGlzVGhlbmFibGU6WEl9O2Z1bmN0aW9uIE8oQSx0LEksZSxnKXtFcnJvci5jYWxsKHRoaXMpLEVycm9yLmNhcHR1cmVTdGFja1RyYWNlP0Vycm9yLmNhcHR1cmVTdGFja1RyYWNlKHRoaXMsdGhpcy5jb25zdHJ1Y3Rvcik6dGhpcy5zdGFjaz1uZXcgRXJyb3IoKS5zdGFjayx0aGlzLm1lc3NhZ2U9QSx0aGlzLm5hbWU9IkF4aW9zRXJyb3IiLHQmJih0aGlzLmNvZGU9dCksSSYmKHRoaXMuY29uZmlnPUkpLGUmJih0aGlzLnJlcXVlc3Q9ZSksZyYmKHRoaXMucmVzcG9uc2U9Zyl9Qy5pbmhlcml0cyhPLEVycm9yLHt0b0pTT046ZnVuY3Rpb24oKXtyZXR1cm57bWVzc2FnZTp0aGlzLm1lc3NhZ2UsbmFtZTp0aGlzLm5hbWUsZGVzY3JpcHRpb246dGhpcy5kZXNjcmlwdGlvbixudW1iZXI6dGhpcy5udW1iZXIsZmlsZU5hbWU6dGhpcy5maWxlTmFtZSxsaW5lTnVtYmVyOnRoaXMubGluZU51bWJlcixjb2x1bW5OdW1iZXI6dGhpcy5jb2x1bW5OdW1iZXIsc3RhY2s6dGhpcy5zdGFjayxjb25maWc6Qy50b0pTT05PYmplY3QodGhpcy5jb25maWcpLGNvZGU6dGhpcy5jb2RlLHN0YXR1czp0aGlzLnJlc3BvbnNlJiZ0aGlzLnJlc3BvbnNlLnN0YXR1cz90aGlzLnJlc3BvbnNlLnN0YXR1czpudWxsfX19KTt2YXIgRXQ9Ty5wcm90b3R5cGUsY3Q9e307WyJFUlJfQkFEX09QVElPTl9WQUxVRSIsIkVSUl9CQURfT1BUSU9OIiwiRUNPTk5BQk9SVEVEIiwiRVRJTUVET1VUIiwiRVJSX05FVFdPUksiLCJFUlJfRlJfVE9PX01BTllfUkVESVJFQ1RTIiwiRVJSX0RFUFJFQ0FURUQiLCJFUlJfQkFEX1JFU1BPTlNFIiwiRVJSX0JBRF9SRVFVRVNUIiwiRVJSX0NBTkNFTEVEIiwiRVJSX05PVF9TVVBQT1JUIiwiRVJSX0lOVkFMSURfVVJMIl0uZm9yRWFjaChBPT57Y3RbQV09e3ZhbHVlOkF9fSk7T2JqZWN0LmRlZmluZVByb3BlcnRpZXMoTyxjdCk7T2JqZWN0LmRlZmluZVByb3BlcnR5KEV0LCJpc0F4aW9zRXJyb3IiLHt2YWx1ZTohMH0pO08uZnJvbT0oQSx0LEksZSxnLHIpPT57bGV0IG89T2JqZWN0LmNyZWF0ZShFdCk7cmV0dXJuIEMudG9GbGF0T2JqZWN0KEEsbyxmdW5jdGlvbihjKXtyZXR1cm4gYyE9PUVycm9yLnByb3RvdHlwZX0sbj0+biE9PSJpc0F4aW9zRXJyb3IiKSxPLmNhbGwobyxBLm1lc3NhZ2UsdCxJLGUsZyksby5jYXVzZT1BLG8ubmFtZT1BLm5hbWUsciYmT2JqZWN0LmFzc2lnbihvLHIpLG99O3ZhciBsPU87dmFyIGFBPW51bGw7ZnVuY3Rpb24gR0EoQSl7cmV0dXJuIEMuaXNQbGFpbk9iamVjdChBKXx8Qy5pc0FycmF5KEEpfWZ1bmN0aW9uIGx0KEEpe3JldHVybiBDLmVuZHNXaXRoKEEsIltdIik/QS5zbGljZSgwLC0yKTpBfWZ1bmN0aW9uIGZ0KEEsdCxJKXtyZXR1cm4gQT9BLmNvbmNhdCh0KS5tYXAoZnVuY3Rpb24oZyxyKXtyZXR1cm4gZz1sdChnKSwhSSYmcj8iWyIrZysiXSI6Z30pLmpvaW4oST8iLiI6IiIpOnR9ZnVuY3Rpb24gekkoQSl7cmV0dXJuIEMuaXNBcnJheShBKSYmIUEuc29tZShHQSl9dmFyIF9JPUMudG9GbGF0T2JqZWN0KEMse30sbnVsbCxmdW5jdGlvbih0KXtyZXR1cm4vXmlzW0EtWl0vLnRlc3QodCl9KTtmdW5jdGlvbiB2SShBLHQsSSl7aWYoIUMuaXNPYmplY3QoQSkpdGhyb3cgbmV3IFR5cGVFcnJvcigidGFyZ2V0IG11c3QgYmUgYW4gb2JqZWN0Iik7dD10fHxuZXcoYUF8fEZvcm1EYXRhKSxJPUMudG9GbGF0T2JqZWN0KEkse21ldGFUb2tlbnM6ITAsZG90czohMSxpbmRleGVzOiExfSwhMSxmdW5jdGlvbihFLHUpe3JldHVybiFDLmlzVW5kZWZpbmVkKHVbRV0pfSk7bGV0IGU9SS5tZXRhVG9rZW5zLGc9SS52aXNpdG9yfHxCLHI9SS5kb3RzLG89SS5pbmRleGVzLGM9KEkuQmxvYnx8dHlwZW9mIEJsb2I8InUiJiZCbG9iKSYmQy5pc1NwZWNDb21wbGlhbnRGb3JtKHQpO2lmKCFDLmlzRnVuY3Rpb24oZykpdGhyb3cgbmV3IFR5cGVFcnJvcigidmlzaXRvciBtdXN0IGJlIGEgZnVuY3Rpb24iKTtmdW5jdGlvbiBRKGEpe2lmKGE9PT1udWxsKXJldHVybiIiO2lmKEMuaXNEYXRlKGEpKXJldHVybiBhLnRvSVNPU3RyaW5nKCk7aWYoIWMmJkMuaXNCbG9iKGEpKXRocm93IG5ldyBsKCJCbG9iIGlzIG5vdCBzdXBwb3J0ZWQuIFVzZSBhIEJ1ZmZlciBpbnN0ZWFkLiIpO3JldHVybiBDLmlzQXJyYXlCdWZmZXIoYSl8fEMuaXNUeXBlZEFycmF5KGEpP2MmJnR5cGVvZiBCbG9iPT0iZnVuY3Rpb24iP25ldyBCbG9iKFthXSk6QnVmZmVyLmZyb20oYSk6YX1mdW5jdGlvbiBCKGEsRSx1KXtsZXQgeT1hO2lmKGEmJiF1JiZ0eXBlb2YgYT09Im9iamVjdCIpe2lmKEMuZW5kc1dpdGgoRSwie30iKSlFPWU/RTpFLnNsaWNlKDAsLTIpLGE9SlNPTi5zdHJpbmdpZnkoYSk7ZWxzZSBpZihDLmlzQXJyYXkoYSkmJnpJKGEpfHwoQy5pc0ZpbGVMaXN0KGEpfHxDLmVuZHNXaXRoKEUsIltdIikpJiYoeT1DLnRvQXJyYXkoYSkpKXJldHVybiBFPWx0KEUpLHkuZm9yRWFjaChmdW5jdGlvbihSLHRJKXshKEMuaXNVbmRlZmluZWQoUil8fFI9PT1udWxsKSYmdC5hcHBlbmQobz09PSEwP2Z0KFtFXSx0SSxyKTpvPT09bnVsbD9FOkUrIltdIixRKFIpKX0pLCExfXJldHVybiBHQShhKT8hMDoodC5hcHBlbmQoZnQodSxFLHIpLFEoYSkpLCExKX1sZXQgaT1bXSxmPU9iamVjdC5hc3NpZ24oX0kse2RlZmF1bHRWaXNpdG9yOkIsY29udmVydFZhbHVlOlEsaXNWaXNpdGFibGU6R0F9KTtmdW5jdGlvbiBzKGEsRSl7aWYoIUMuaXNVbmRlZmluZWQoYSkpe2lmKGkuaW5kZXhPZihhKSE9PS0xKXRocm93IEVycm9yKCJDaXJjdWxhciByZWZlcmVuY2UgZGV0ZWN0ZWQgaW4gIitFLmpvaW4oIi4iKSk7aS5wdXNoKGEpLEMuZm9yRWFjaChhLGZ1bmN0aW9uKHksRil7KCEoQy5pc1VuZGVmaW5lZCh5KXx8eT09PW51bGwpJiZnLmNhbGwodCx5LEMuaXNTdHJpbmcoRik/Ri50cmltKCk6RixFLGYpKT09PSEwJiZzKHksRT9FLmNvbmNhdChGKTpbRl0pfSksaS5wb3AoKX19aWYoIUMuaXNPYmplY3QoQSkpdGhyb3cgbmV3IFR5cGVFcnJvcigiZGF0YSBtdXN0IGJlIGFuIG9iamVjdCIpO3JldHVybiBzKEEpLHR9dmFyIEo9dkk7ZnVuY3Rpb24gRHQoQSl7bGV0IHQ9eyIhIjoiJTI1MjEiLCJcJyI6IiUyNTI3IiwiKCI6IiUyNTI4IiwiKSI6IiUyNTI5IiwifiI6IiUyNTdFIiwiJTI1MjAiOiIrIiwiJTI1MDAiOiJcXDAifTtyZXR1cm4gZW5jb2RlVVJJQ29tcG9uZW50KEEpLnJlcGxhY2UoL1shXCcoKX5dfCUyNTIwfCUyNTAwL2csZnVuY3Rpb24oZSl7cmV0dXJuIHRbZV19KX1mdW5jdGlvbiB1dChBLHQpe3RoaXMuX3BhaXJzPVtdLEEmJkooQSx0aGlzLHQpfXZhciBodD11dC5wcm90b3R5cGU7aHQuYXBwZW5kPWZ1bmN0aW9uKHQsSSl7dGhpcy5fcGFpcnMucHVzaChbdCxJXSl9O2h0LnRvU3RyaW5nPWZ1bmN0aW9uKHQpe2xldCBJPXQ/ZnVuY3Rpb24oZSl7cmV0dXJuIHQuY2FsbCh0aGlzLGUsRHQpfTpEdDtyZXR1cm4gdGhpcy5fcGFpcnMubWFwKGZ1bmN0aW9uKGcpe3JldHVybiBJKGdbMF0pKyI9IitJKGdbMV0pfSwiIikuam9pbigiJiIpfTt2YXIgRUE9dXQ7ZnVuY3Rpb24gJEkoQSl7cmV0dXJuIGVuY29kZVVSSUNvbXBvbmVudChBKS5yZXBsYWNlKC8lMjUzQS9naSwiOiIpLnJlcGxhY2UoLyUyNTI0L2csIiQiKS5yZXBsYWNlKC8lMjUyQy9naSwiLCIpLnJlcGxhY2UoLyUyNTIwL2csIisiKS5yZXBsYWNlKC8lMjU1Qi9naSwiWyIpLnJlcGxhY2UoLyUyNTVEL2dpLCJdIil9ZnVuY3Rpb24gWChBLHQsSSl7aWYoIXQpcmV0dXJuIEE7bGV0IGU9SSYmSS5lbmNvZGV8fCRJLGc9SSYmSS5zZXJpYWxpemUscjtpZihnP3I9Zyh0LEkpOnI9Qy5pc1VSTFNlYXJjaFBhcmFtcyh0KT90LnRvU3RyaW5nKCk6bmV3IEVBKHQsSSkudG9TdHJpbmcoZSkscil7bGV0IG89QS5pbmRleE9mKCIlMjMiKTtvIT09LTEmJihBPUEuc2xpY2UoMCxvKSksQSs9KEEuaW5kZXhPZigiPyIpPT09LTE/Ij8iOiImIikrcn1yZXR1cm4gQX12YXIga0E9Y2xhc3N7Y29uc3RydWN0b3IoKXt0aGlzLmhhbmRsZXJzPVtdfXVzZSh0LEksZSl7cmV0dXJuIHRoaXMuaGFuZGxlcnMucHVzaCh7ZnVsZmlsbGVkOnQscmVqZWN0ZWQ6SSxzeW5jaHJvbm91czplP2Uuc3luY2hyb25vdXM6ITEscnVuV2hlbjplP2UucnVuV2hlbjpudWxsfSksdGhpcy5oYW5kbGVycy5sZW5ndGgtMX1lamVjdCh0KXt0aGlzLmhhbmRsZXJzW3RdJiYodGhpcy5oYW5kbGVyc1t0XT1udWxsKX1jbGVhcigpe3RoaXMuaGFuZGxlcnMmJih0aGlzLmhhbmRsZXJzPVtdKX1mb3JFYWNoKHQpe0MuZm9yRWFjaCh0aGlzLmhhbmRsZXJzLGZ1bmN0aW9uKGUpe2UhPT1udWxsJiZ0KGUpfSl9fSxMQT1rQTt2YXIgY0E9e3NpbGVudEpTT05QYXJzaW5nOiEwLGZvcmNlZEpTT05QYXJzaW5nOiEwLGNsYXJpZnlUaW1lb3V0RXJyb3I6ITF9O3ZhciBkdD10eXBlb2YgVVJMU2VhcmNoUGFyYW1zPCJ1Ij9VUkxTZWFyY2hQYXJhbXM6RUE7dmFyIHl0PXR5cGVvZiBGb3JtRGF0YTwidSI/Rm9ybURhdGE6bnVsbDt2YXIgd3Q9dHlwZW9mIEJsb2I8InUiP0Jsb2I6bnVsbDt2YXIgbXQ9e2lzQnJvd3NlcjohMCxjbGFzc2VzOntVUkxTZWFyY2hQYXJhbXM6ZHQsRm9ybURhdGE6eXQsQmxvYjp3dH0scHJvdG9jb2xzOlsiaHR0cCIsImh0dHBzIiwiZmlsZSIsImJsb2IiLCJ1cmwiLCJkYXRhIl19O3ZhciBKQT17fTtlSShKQSx7aGFzQnJvd3NlckVudjooKT0+cHQsaGFzU3RhbmRhcmRCcm93c2VyRW52OigpPT5BZSxoYXNTdGFuZGFyZEJyb3dzZXJXZWJXb3JrZXJFbnY6KCk9PnRlfSk7dmFyIHB0PXR5cGVvZiB3aW5kb3c8InUiJiZ0eXBlb2YgZG9jdW1lbnQ8InUiLEFlPShBPT5wdCYmWyJSZWFjdE5hdGl2ZSIsIk5hdGl2ZVNjcmlwdCIsIk5TIl0uaW5kZXhPZihBKTwwKSh0eXBlb2YgbmF2aWdhdG9yPCJ1IiYmbmF2aWdhdG9yLnByb2R1Y3QpLHRlPXR5cGVvZiBXb3JrZXJHbG9iYWxTY29wZTwidSImJnNlbGYgaW5zdGFuY2VvZiBXb3JrZXJHbG9iYWxTY29wZSYmdHlwZW9mIHNlbGYuaW1wb3J0U2NyaXB0cz09ImZ1bmN0aW9uIjt2YXIgbT17Li4uSkEsLi4ubXR9O2Z1bmN0aW9uIEhBKEEsdCl7cmV0dXJuIEooQSxuZXcgbS5jbGFzc2VzLlVSTFNlYXJjaFBhcmFtcyxPYmplY3QuYXNzaWduKHt2aXNpdG9yOmZ1bmN0aW9uKEksZSxnLHIpe3JldHVybiBtLmlzTm9kZSYmQy5pc0J1ZmZlcihJKT8odGhpcy5hcHBlbmQoZSxJLnRvU3RyaW5nKCJiYXNlNjQiKSksITEpOnIuZGVmYXVsdFZpc2l0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfX0sdCkpfWZ1bmN0aW9uIEllKEEpe3JldHVybiBDLm1hdGNoQWxsKC9cXHcrfFxcWyhcXHcqKV0vZyxBKS5tYXAodD0+dFswXT09PSJbXSI/IiI6dFsxXXx8dFswXSl9ZnVuY3Rpb24gZWUoQSl7bGV0IHQ9e30sST1PYmplY3Qua2V5cyhBKSxlLGc9SS5sZW5ndGgscjtmb3IoZT0wO2U8ZztlKyspcj1JW2VdLHRbcl09QVtyXTtyZXR1cm4gdH1mdW5jdGlvbiBnZShBKXtmdW5jdGlvbiB0KEksZSxnLHIpe2xldCBvPUlbcisrXTtpZihvPT09Il9fcHJvdG9fXyIpcmV0dXJuITA7bGV0IG49TnVtYmVyLmlzRmluaXRlKCtvKSxjPXI+PUkubGVuZ3RoO3JldHVybiBvPSFvJiZDLmlzQXJyYXkoZyk/Zy5sZW5ndGg6byxjPyhDLmhhc093blByb3AoZyxvKT9nW29dPVtnW29dLGVdOmdbb109ZSwhbik6KCghZ1tvXXx8IUMuaXNPYmplY3QoZ1tvXSkpJiYoZ1tvXT1bXSksdChJLGUsZ1tvXSxyKSYmQy5pc0FycmF5KGdbb10pJiYoZ1tvXT1lZShnW29dKSksIW4pfWlmKEMuaXNGb3JtRGF0YShBKSYmQy5pc0Z1bmN0aW9uKEEuZW50cmllcykpe2xldCBJPXt9O3JldHVybiBDLmZvckVhY2hFbnRyeShBLChlLGcpPT57dChJZShlKSxnLEksMCl9KSxJfXJldHVybiBudWxsfXZhciBmQT1nZTtmdW5jdGlvbiByZShBLHQsSSl7aWYoQy5pc1N0cmluZyhBKSl0cnl7cmV0dXJuKHR8fEpTT04ucGFyc2UpKEEpLEMudHJpbShBKX1jYXRjaChlKXtpZihlLm5hbWUhPT0iU3ludGF4RXJyb3IiKXRocm93IGV9cmV0dXJuKEl8fEpTT04uc3RyaW5naWZ5KShBKX12YXIgWUE9e3RyYW5zaXRpb25hbDpjQSxhZGFwdGVyOlsieGhyIiwiaHR0cCJdLHRyYW5zZm9ybVJlcXVlc3Q6W2Z1bmN0aW9uKHQsSSl7bGV0IGU9SS5nZXRDb250ZW50VHlwZSgpfHwiIixnPWUuaW5kZXhPZigiYXBwbGljYXRpb24vanNvbiIpPi0xLHI9Qy5pc09iamVjdCh0KTtpZihyJiZDLmlzSFRNTEZvcm0odCkmJih0PW5ldyBGb3JtRGF0YSh0KSksQy5pc0Zvcm1EYXRhKHQpKXJldHVybiBnP0pTT04uc3RyaW5naWZ5KGZBKHQpKTp0O2lmKEMuaXNBcnJheUJ1ZmZlcih0KXx8Qy5pc0J1ZmZlcih0KXx8Qy5pc1N0cmVhbSh0KXx8Qy5pc0ZpbGUodCl8fEMuaXNCbG9iKHQpKXJldHVybiB0O2lmKEMuaXNBcnJheUJ1ZmZlclZpZXcodCkpcmV0dXJuIHQuYnVmZmVyO2lmKEMuaXNVUkxTZWFyY2hQYXJhbXModCkpcmV0dXJuIEkuc2V0Q29udGVudFR5cGUoImFwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZDtjaGFyc2V0PXV0Zi04IiwhMSksdC50b1N0cmluZygpO2xldCBuO2lmKHIpe2lmKGUuaW5kZXhPZigiYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkIik+LTEpcmV0dXJuIEhBKHQsdGhpcy5mb3JtU2VyaWFsaXplcikudG9TdHJpbmcoKTtpZigobj1DLmlzRmlsZUxpc3QodCkpfHxlLmluZGV4T2YoIm11bHRpcGFydC9mb3JtLWRhdGEiKT4tMSl7bGV0IGM9dGhpcy5lbnYmJnRoaXMuZW52LkZvcm1EYXRhO3JldHVybiBKKG4/eyJmaWxlc1tdIjp0fTp0LGMmJm5ldyBjLHRoaXMuZm9ybVNlcmlhbGl6ZXIpfX1yZXR1cm4gcnx8Zz8oSS5zZXRDb250ZW50VHlwZSgiYXBwbGljYXRpb24vanNvbiIsITEpLHJlKHQpKTp0fV0sdHJhbnNmb3JtUmVzcG9uc2U6W2Z1bmN0aW9uKHQpe2xldCBJPXRoaXMudHJhbnNpdGlvbmFsfHxZQS50cmFuc2l0aW9uYWwsZT1JJiZJLmZvcmNlZEpTT05QYXJzaW5nLGc9dGhpcy5yZXNwb25zZVR5cGU9PT0ianNvbiI7aWYodCYmQy5pc1N0cmluZyh0KSYmKGUmJiF0aGlzLnJlc3BvbnNlVHlwZXx8Zykpe2xldCBvPSEoSSYmSS5zaWxlbnRKU09OUGFyc2luZykmJmc7dHJ5e3JldHVybiBKU09OLnBhcnNlKHQpfWNhdGNoKG4pe2lmKG8pdGhyb3cgbi5uYW1lPT09IlN5bnRheEVycm9yIj9sLmZyb20obixsLkVSUl9CQURfUkVTUE9OU0UsdGhpcyxudWxsLHRoaXMucmVzcG9uc2UpOm59fXJldHVybiB0fV0sdGltZW91dDowLHhzcmZDb29raWVOYW1lOiJYU1JGLVRPS0VOIix4c3JmSGVhZGVyTmFtZToiWC1YU1JGLVRPS0VOIixtYXhDb250ZW50TGVuZ3RoOi0xLG1heEJvZHlMZW5ndGg6LTEsZW52OntGb3JtRGF0YTptLmNsYXNzZXMuRm9ybURhdGEsQmxvYjptLmNsYXNzZXMuQmxvYn0sdmFsaWRhdGVTdGF0dXM6ZnVuY3Rpb24odCl7cmV0dXJuIHQ+PTIwMCYmdDwzMDB9LGhlYWRlcnM6e2NvbW1vbjp7QWNjZXB0OiJhcHBsaWNhdGlvbi9qc29uLCB0ZXh0L3BsYWluLCAqLyoiLCJDb250ZW50LVR5cGUiOnZvaWQgMH19fTtDLmZvckVhY2goWyJkZWxldGUiLCJnZXQiLCJoZWFkIiwicG9zdCIsInB1dCIsInBhdGNoIl0sQT0+e1lBLmhlYWRlcnNbQV09e319KTt2YXIgVD1ZQTt2YXIgb2U9Qy50b09iamVjdFNldChbImFnZSIsImF1dGhvcml6YXRpb24iLCJjb250ZW50LWxlbmd0aCIsImNvbnRlbnQtdHlwZSIsImV0YWciLCJleHBpcmVzIiwiZnJvbSIsImhvc3QiLCJpZi1tb2RpZmllZC1zaW5jZSIsImlmLXVubW9kaWZpZWQtc2luY2UiLCJsYXN0LW1vZGlmaWVkIiwibG9jYXRpb24iLCJtYXgtZm9yd2FyZHMiLCJwcm94eS1hdXRob3JpemF0aW9uIiwicmVmZXJlciIsInJldHJ5LWFmdGVyIiwidXNlci1hZ2VudCJdKSxTdD1BPT57bGV0IHQ9e30sSSxlLGc7cmV0dXJuIEEmJkEuc3BsaXQoYCUwQWApLmZvckVhY2goZnVuY3Rpb24obyl7Zz1vLmluZGV4T2YoIjoiKSxJPW8uc3Vic3RyaW5nKDAsZykudHJpbSgpLnRvTG93ZXJDYXNlKCksZT1vLnN1YnN0cmluZyhnKzEpLnRyaW0oKSwhKCFJfHx0W0ldJiZvZVtJXSkmJihJPT09InNldC1jb29raWUiP3RbSV0/dFtJXS5wdXNoKGUpOnRbSV09W2VdOnRbSV09dFtJXT90W0ldKyIsICIrZTplKX0pLHR9O3ZhciBGdD1TeW1ib2woImludGVybmFscyIpO2Z1bmN0aW9uIHooQSl7cmV0dXJuIEEmJlN0cmluZyhBKS50cmltKCkudG9Mb3dlckNhc2UoKX1mdW5jdGlvbiBsQShBKXtyZXR1cm4gQT09PSExfHxBPT1udWxsP0E6Qy5pc0FycmF5KEEpP0EubWFwKGxBKTpTdHJpbmcoQSl9ZnVuY3Rpb24gaWUoQSl7bGV0IHQ9T2JqZWN0LmNyZWF0ZShudWxsKSxJPS8oW15cXHMsOz1dKylcXHMqKD86PVxccyooW14sO10rKSk/L2csZTtmb3IoO2U9SS5leGVjKEEpOyl0W2VbMV1dPWVbMl07cmV0dXJuIHR9dmFyIENlPUE9Pi9eWy1fYS16QS1aMC05XmB8fiwhJTIzJCUmXCcqKy5dKyQvLnRlc3QoQS50cmltKCkpO2Z1bmN0aW9uIGJBKEEsdCxJLGUsZyl7aWYoQy5pc0Z1bmN0aW9uKGUpKXJldHVybiBlLmNhbGwodGhpcyx0LEkpO2lmKGcmJih0PUkpLCEhQy5pc1N0cmluZyh0KSl7aWYoQy5pc1N0cmluZyhlKSlyZXR1cm4gdC5pbmRleE9mKGUpIT09LTE7aWYoQy5pc1JlZ0V4cChlKSlyZXR1cm4gZS50ZXN0KHQpfX1mdW5jdGlvbiBCZShBKXtyZXR1cm4gQS50cmltKCkudG9Mb3dlckNhc2UoKS5yZXBsYWNlKC8oW2EtelxcZF0pKFxcdyopL2csKHQsSSxlKT0+SS50b1VwcGVyQ2FzZSgpK2UpfWZ1bmN0aW9uIHNlKEEsdCl7bGV0IEk9Qy50b0NhbWVsQ2FzZSgiICIrdCk7WyJnZXQiLCJzZXQiLCJoYXMiXS5mb3JFYWNoKGU9PntPYmplY3QuZGVmaW5lUHJvcGVydHkoQSxlK0kse3ZhbHVlOmZ1bmN0aW9uKGcscixvKXtyZXR1cm4gdGhpc1tlXS5jYWxsKHRoaXMsdCxnLHIsbyl9LGNvbmZpZ3VyYWJsZTohMH0pfSl9dmFyIFA9Y2xhc3N7Y29uc3RydWN0b3IodCl7dCYmdGhpcy5zZXQodCl9c2V0KHQsSSxlKXtsZXQgZz10aGlzO2Z1bmN0aW9uIHIobixjLFEpe2xldCBCPXooYyk7aWYoIUIpdGhyb3cgbmV3IEVycm9yKCJoZWFkZXIgbmFtZSBtdXN0IGJlIGEgbm9uLWVtcHR5IHN0cmluZyIpO2xldCBpPUMuZmluZEtleShnLEIpOyghaXx8Z1tpXT09PXZvaWQgMHx8UT09PSEwfHxRPT09dm9pZCAwJiZnW2ldIT09ITEpJiYoZ1tpfHxjXT1sQShuKSl9bGV0IG89KG4sYyk9PkMuZm9yRWFjaChuLChRLEIpPT5yKFEsQixjKSk7cmV0dXJuIEMuaXNQbGFpbk9iamVjdCh0KXx8dCBpbnN0YW5jZW9mIHRoaXMuY29uc3RydWN0b3I/byh0LEkpOkMuaXNTdHJpbmcodCkmJih0PXQudHJpbSgpKSYmIUNlKHQpP28oU3QodCksSSk6dCE9bnVsbCYmcihJLHQsZSksdGhpc31nZXQodCxJKXtpZih0PXoodCksdCl7bGV0IGU9Qy5maW5kS2V5KHRoaXMsdCk7aWYoZSl7bGV0IGc9dGhpc1tlXTtpZighSSlyZXR1cm4gZztpZihJPT09ITApcmV0dXJuIGllKGcpO2lmKEMuaXNGdW5jdGlvbihJKSlyZXR1cm4gSS5jYWxsKHRoaXMsZyxlKTtpZihDLmlzUmVnRXhwKEkpKXJldHVybiBJLmV4ZWMoZyk7dGhyb3cgbmV3IFR5cGVFcnJvcigicGFyc2VyIG11c3QgYmUgYm9vbGVhbnxyZWdleHB8ZnVuY3Rpb24iKX19fWhhcyh0LEkpe2lmKHQ9eih0KSx0KXtsZXQgZT1DLmZpbmRLZXkodGhpcyx0KTtyZXR1cm4hIShlJiZ0aGlzW2VdIT09dm9pZCAwJiYoIUl8fGJBKHRoaXMsdGhpc1tlXSxlLEkpKSl9cmV0dXJuITF9ZGVsZXRlKHQsSSl7bGV0IGU9dGhpcyxnPSExO2Z1bmN0aW9uIHIobyl7aWYobz16KG8pLG8pe2xldCBuPUMuZmluZEtleShlLG8pO24mJighSXx8YkEoZSxlW25dLG4sSSkpJiYoZGVsZXRlIGVbbl0sZz0hMCl9fXJldHVybiBDLmlzQXJyYXkodCk/dC5mb3JFYWNoKHIpOnIodCksZ31jbGVhcih0KXtsZXQgST1PYmplY3Qua2V5cyh0aGlzKSxlPUkubGVuZ3RoLGc9ITE7Zm9yKDtlLS07KXtsZXQgcj1JW2VdOyghdHx8YkEodGhpcyx0aGlzW3JdLHIsdCwhMCkpJiYoZGVsZXRlIHRoaXNbcl0sZz0hMCl9cmV0dXJuIGd9bm9ybWFsaXplKHQpe2xldCBJPXRoaXMsZT17fTtyZXR1cm4gQy5mb3JFYWNoKHRoaXMsKGcscik9PntsZXQgbz1DLmZpbmRLZXkoZSxyKTtpZihvKXtJW29dPWxBKGcpLGRlbGV0ZSBJW3JdO3JldHVybn1sZXQgbj10P0JlKHIpOlN0cmluZyhyKS50cmltKCk7biE9PXImJmRlbGV0ZSBJW3JdLElbbl09bEEoZyksZVtuXT0hMH0pLHRoaXN9Y29uY2F0KC4uLnQpe3JldHVybiB0aGlzLmNvbnN0cnVjdG9yLmNvbmNhdCh0aGlzLC4uLnQpfXRvSlNPTih0KXtsZXQgST1PYmplY3QuY3JlYXRlKG51bGwpO3JldHVybiBDLmZvckVhY2godGhpcywoZSxnKT0+e2UhPW51bGwmJmUhPT0hMSYmKElbZ109dCYmQy5pc0FycmF5KGUpP2Uuam9pbigiLCAiKTplKX0pLEl9W1N5bWJvbC5pdGVyYXRvcl0oKXtyZXR1cm4gT2JqZWN0LmVudHJpZXModGhpcy50b0pTT04oKSlbU3ltYm9sLml0ZXJhdG9yXSgpfXRvU3RyaW5nKCl7cmV0dXJuIE9iamVjdC5lbnRyaWVzKHRoaXMudG9KU09OKCkpLm1hcCgoW3QsSV0pPT50KyI6ICIrSSkuam9pbihgJTBBYCl9Z2V0W1N5bWJvbC50b1N0cmluZ1RhZ10oKXtyZXR1cm4iQXhpb3NIZWFkZXJzIn1zdGF0aWMgZnJvbSh0KXtyZXR1cm4gdCBpbnN0YW5jZW9mIHRoaXM/dDpuZXcgdGhpcyh0KX1zdGF0aWMgY29uY2F0KHQsLi4uSSl7bGV0IGU9bmV3IHRoaXModCk7cmV0dXJuIEkuZm9yRWFjaChnPT5lLnNldChnKSksZX1zdGF0aWMgYWNjZXNzb3IodCl7bGV0IGU9KHRoaXNbRnRdPXRoaXNbRnRdPXthY2Nlc3NvcnM6e319KS5hY2Nlc3NvcnMsZz10aGlzLnByb3RvdHlwZTtmdW5jdGlvbiByKG8pe2xldCBuPXoobyk7ZVtuXXx8KHNlKGcsbyksZVtuXT0hMCl9cmV0dXJuIEMuaXNBcnJheSh0KT90LmZvckVhY2gocik6cih0KSx0aGlzfX07UC5hY2Nlc3NvcihbIkNvbnRlbnQtVHlwZSIsIkNvbnRlbnQtTGVuZ3RoIiwiQWNjZXB0IiwiQWNjZXB0LUVuY29kaW5nIiwiVXNlci1BZ2VudCIsIkF1dGhvcml6YXRpb24iXSk7Qy5yZWR1Y2VEZXNjcmlwdG9ycyhQLnByb3RvdHlwZSwoe3ZhbHVlOkF9LHQpPT57bGV0IEk9dFswXS50b1VwcGVyQ2FzZSgpK3Quc2xpY2UoMSk7cmV0dXJue2dldDooKT0+QSxzZXQoZSl7dGhpc1tJXT1lfX19KTtDLmZyZWV6ZU1ldGhvZHMoUCk7dmFyIHA9UDtmdW5jdGlvbiBfKEEsdCl7bGV0IEk9dGhpc3x8VCxlPXR8fEksZz1wLmZyb20oZS5oZWFkZXJzKSxyPWUuZGF0YTtyZXR1cm4gQy5mb3JFYWNoKEEsZnVuY3Rpb24obil7cj1uLmNhbGwoSSxyLGcubm9ybWFsaXplKCksdD90LnN0YXR1czp2b2lkIDApfSksZy5ub3JtYWxpemUoKSxyfWZ1bmN0aW9uIHYoQSl7cmV0dXJuISEoQSYmQS5fX0NBTkNFTF9fKX1mdW5jdGlvbiBSdChBLHQsSSl7bC5jYWxsKHRoaXMsQT8/ImNhbmNlbGVkIixsLkVSUl9DQU5DRUxFRCx0LEkpLHRoaXMubmFtZT0iQ2FuY2VsZWRFcnJvciJ9Qy5pbmhlcml0cyhSdCxsLHtfX0NBTkNFTF9fOiEwfSk7dmFyIEg9UnQ7ZnVuY3Rpb24gTUEoQSx0LEkpe2xldCBlPUkuY29uZmlnLnZhbGlkYXRlU3RhdHVzOyFJLnN0YXR1c3x8IWV8fGUoSS5zdGF0dXMpP0EoSSk6dChuZXcgbCgiUmVxdWVzdCBmYWlsZWQgd2l0aCBzdGF0dXMgY29kZSAiK0kuc3RhdHVzLFtsLkVSUl9CQURfUkVRVUVTVCxsLkVSUl9CQURfUkVTUE9OU0VdW01hdGguZmxvb3IoSS5zdGF0dXMvMTAwKS00XSxJLmNvbmZpZyxJLnJlcXVlc3QsSSkpfXZhciBOdD1tLmhhc1N0YW5kYXJkQnJvd3NlckVudj97d3JpdGUoQSx0LEksZSxnLHIpe2xldCBvPVtBKyI9IitlbmNvZGVVUklDb21wb25lbnQodCldO0MuaXNOdW1iZXIoSSkmJm8ucHVzaCgiZXhwaXJlcz0iK25ldyBEYXRlKEkpLnRvR01UU3RyaW5nKCkpLEMuaXNTdHJpbmcoZSkmJm8ucHVzaCgicGF0aD0iK2UpLEMuaXNTdHJpbmcoZykmJm8ucHVzaCgiZG9tYWluPSIrZykscj09PSEwJiZvLnB1c2goInNlY3VyZSIpLGRvY3VtZW50LmNvb2tpZT1vLmpvaW4oIjsgIil9LHJlYWQoQSl7bGV0IHQ9ZG9jdW1lbnQuY29va2llLm1hdGNoKG5ldyBSZWdFeHAoIihefDtcXFxccyopKCIrQSsiKT0oW147XSopIikpO3JldHVybiB0P2RlY29kZVVSSUNvbXBvbmVudCh0WzNdKTpudWxsfSxyZW1vdmUoQSl7dGhpcy53cml0ZShBLCIiLERhdGUubm93KCktODY0ZTUpfX06e3dyaXRlKCl7fSxyZWFkKCl7cmV0dXJuIG51bGx9LHJlbW92ZSgpe319O2Z1bmN0aW9uIHFBKEEpe3JldHVybi9eKFthLXpdW2EtelxcZCtcXC0uXSo6KT9cXC9cXC8vaS50ZXN0KEEpfWZ1bmN0aW9uIEtBKEEsdCl7cmV0dXJuIHQ/QS5yZXBsYWNlKC9cXC8/XFwvJC8sIiIpKyIvIit0LnJlcGxhY2UoL15cXC8rLywiIik6QX1mdW5jdGlvbiAkKEEsdCl7cmV0dXJuIEEmJiFxQSh0KT9LQShBLHQpOnR9dmFyIFV0PW0uaGFzU3RhbmRhcmRCcm93c2VyRW52P2Z1bmN0aW9uKCl7bGV0IHQ9Lyhtc2llfHRyaWRlbnQpL2kudGVzdChuYXZpZ2F0b3IudXNlckFnZW50KSxJPWRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImEiKSxlO2Z1bmN0aW9uIGcocil7bGV0IG89cjtyZXR1cm4gdCYmKEkuc2V0QXR0cmlidXRlKCJocmVmIixvKSxvPUkuaHJlZiksSS5zZXRBdHRyaWJ1dGUoImhyZWYiLG8pLHtocmVmOkkuaHJlZixwcm90b2NvbDpJLnByb3RvY29sP0kucHJvdG9jb2wucmVwbGFjZSgvOiQvLCIiKToiIixob3N0OkkuaG9zdCxzZWFyY2g6SS5zZWFyY2g/SS5zZWFyY2gucmVwbGFjZSgvXlxcPy8sIiIpOiIiLGhhc2g6SS5oYXNoP0kuaGFzaC5yZXBsYWNlKC9eJTIzLywiIik6IiIsaG9zdG5hbWU6SS5ob3N0bmFtZSxwb3J0OkkucG9ydCxwYXRobmFtZTpJLnBhdGhuYW1lLmNoYXJBdCgwKT09PSIvIj9JLnBhdGhuYW1lOiIvIitJLnBhdGhuYW1lfX1yZXR1cm4gZT1nKHdpbmRvdy5sb2NhdGlvbi5ocmVmKSxmdW5jdGlvbihvKXtsZXQgbj1DLmlzU3RyaW5nKG8pP2cobyk6bztyZXR1cm4gbi5wcm90b2NvbD09PWUucHJvdG9jb2wmJm4uaG9zdD09PWUuaG9zdH19KCk6ZnVuY3Rpb24oKXtyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4hMH19KCk7ZnVuY3Rpb24gT0EoQSl7bGV0IHQ9L14oWy0rXFx3XXsxLDI1fSkoOj9cXC9cXC98OikvLmV4ZWMoQSk7cmV0dXJuIHQmJnRbMV18fCIifWZ1bmN0aW9uIG5lKEEsdCl7QT1BfHwxMDtsZXQgST1uZXcgQXJyYXkoQSksZT1uZXcgQXJyYXkoQSksZz0wLHI9MCxvO3JldHVybiB0PXQhPT12b2lkIDA/dDoxZTMsZnVuY3Rpb24oYyl7bGV0IFE9RGF0ZS5ub3coKSxCPWVbcl07b3x8KG89USksSVtnXT1jLGVbZ109UTtsZXQgaT1yLGY9MDtmb3IoO2khPT1nOylmKz1JW2krK10saT1pJUE7aWYoZz0oZysxKSVBLGc9PT1yJiYocj0ocisxKSVBKSxRLW88dClyZXR1cm47bGV0IHM9QiYmUS1CO3JldHVybiBzP01hdGgucm91bmQoZioxZTMvcyk6dm9pZCAwfX12YXIgR3Q9bmU7ZnVuY3Rpb24ga3QoQSx0KXtsZXQgST0wLGU9R3QoNTAsMjUwKTtyZXR1cm4gZz0+e2xldCByPWcubG9hZGVkLG89Zy5sZW5ndGhDb21wdXRhYmxlP2cudG90YWw6dm9pZCAwLG49ci1JLGM9ZShuKSxRPXI8PW87ST1yO2xldCBCPXtsb2FkZWQ6cix0b3RhbDpvLHByb2dyZXNzOm8/ci9vOnZvaWQgMCxieXRlczpuLHJhdGU6Y3x8dm9pZCAwLGVzdGltYXRlZDpjJiZvJiZRPyhvLXIpL2M6dm9pZCAwLGV2ZW50Omd9O0JbdD8iZG93bmxvYWQiOiJ1cGxvYWQiXT0hMCxBKEIpfX12YXIgUWU9dHlwZW9mIFhNTEh0dHBSZXF1ZXN0PCJ1IixMdD1RZSYmZnVuY3Rpb24oQSl7cmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKEksZSl7bGV0IGc9QS5kYXRhLHI9cC5mcm9tKEEuaGVhZGVycykubm9ybWFsaXplKCkse3Jlc3BvbnNlVHlwZTpvLHdpdGhYU1JGVG9rZW46bn09QSxjO2Z1bmN0aW9uIFEoKXtBLmNhbmNlbFRva2VuJiZBLmNhbmNlbFRva2VuLnVuc3Vic2NyaWJlKGMpLEEuc2lnbmFsJiZBLnNpZ25hbC5yZW1vdmVFdmVudExpc3RlbmVyKCJhYm9ydCIsYyl9bGV0IEI7aWYoQy5pc0Zvcm1EYXRhKGcpKXtpZihtLmhhc1N0YW5kYXJkQnJvd3NlckVudnx8bS5oYXNTdGFuZGFyZEJyb3dzZXJXZWJXb3JrZXJFbnYpci5zZXRDb250ZW50VHlwZSghMSk7ZWxzZSBpZigoQj1yLmdldENvbnRlbnRUeXBlKCkpIT09ITEpe2xldFtFLC4uLnVdPUI/Qi5zcGxpdCgiOyIpLm1hcCh5PT55LnRyaW0oKSkuZmlsdGVyKEJvb2xlYW4pOltdO3Iuc2V0Q29udGVudFR5cGUoW0V8fCJtdWx0aXBhcnQvZm9ybS1kYXRhIiwuLi51XS5qb2luKCI7ICIpKX19bGV0IGk9bmV3IFhNTEh0dHBSZXF1ZXN0O2lmKEEuYXV0aCl7bGV0IEU9QS5hdXRoLnVzZXJuYW1lfHwiIix1PUEuYXV0aC5wYXNzd29yZD91bmVzY2FwZShlbmNvZGVVUklDb21wb25lbnQoQS5hdXRoLnBhc3N3b3JkKSk6IiI7ci5zZXQoIkF1dGhvcml6YXRpb24iLCJCYXNpYyAiK2J0b2EoRSsiOiIrdSkpfWxldCBmPSQoQS5iYXNlVVJMLEEudXJsKTtpLm9wZW4oQS5tZXRob2QudG9VcHBlckNhc2UoKSxYKGYsQS5wYXJhbXMsQS5wYXJhbXNTZXJpYWxpemVyKSwhMCksaS50aW1lb3V0PUEudGltZW91dDtmdW5jdGlvbiBzKCl7aWYoIWkpcmV0dXJuO2xldCBFPXAuZnJvbSgiZ2V0QWxsUmVzcG9uc2VIZWFkZXJzImluIGkmJmkuZ2V0QWxsUmVzcG9uc2VIZWFkZXJzKCkpLHk9e2RhdGE6IW98fG89PT0idGV4dCJ8fG89PT0ianNvbiI/aS5yZXNwb25zZVRleHQ6aS5yZXNwb25zZSxzdGF0dXM6aS5zdGF0dXMsc3RhdHVzVGV4dDppLnN0YXR1c1RleHQsaGVhZGVyczpFLGNvbmZpZzpBLHJlcXVlc3Q6aX07TUEoZnVuY3Rpb24oUil7SShSKSxRKCl9LGZ1bmN0aW9uKFIpe2UoUiksUSgpfSx5KSxpPW51bGx9aWYoIm9ubG9hZGVuZCJpbiBpP2kub25sb2FkZW5kPXM6aS5vbnJlYWR5c3RhdGVjaGFuZ2U9ZnVuY3Rpb24oKXshaXx8aS5yZWFkeVN0YXRlIT09NHx8aS5zdGF0dXM9PT0wJiYhKGkucmVzcG9uc2VVUkwmJmkucmVzcG9uc2VVUkwuaW5kZXhPZigiZmlsZToiKT09PTApfHxzZXRUaW1lb3V0KHMpfSxpLm9uYWJvcnQ9ZnVuY3Rpb24oKXtpJiYoZShuZXcgbCgiUmVxdWVzdCBhYm9ydGVkIixsLkVDT05OQUJPUlRFRCxBLGkpKSxpPW51bGwpfSxpLm9uZXJyb3I9ZnVuY3Rpb24oKXtlKG5ldyBsKCJOZXR3b3JrIEVycm9yIixsLkVSUl9ORVRXT1JLLEEsaSkpLGk9bnVsbH0saS5vbnRpbWVvdXQ9ZnVuY3Rpb24oKXtsZXQgdT1BLnRpbWVvdXQ/InRpbWVvdXQgb2YgIitBLnRpbWVvdXQrIm1zIGV4Y2VlZGVkIjoidGltZW91dCBleGNlZWRlZCIseT1BLnRyYW5zaXRpb25hbHx8Y0E7QS50aW1lb3V0RXJyb3JNZXNzYWdlJiYodT1BLnRpbWVvdXRFcnJvck1lc3NhZ2UpLGUobmV3IGwodSx5LmNsYXJpZnlUaW1lb3V0RXJyb3I/bC5FVElNRURPVVQ6bC5FQ09OTkFCT1JURUQsQSxpKSksaT1udWxsfSxtLmhhc1N0YW5kYXJkQnJvd3NlckVudiYmKG4mJkMuaXNGdW5jdGlvbihuKSYmKG49bihBKSksbnx8biE9PSExJiZVdChmKSkpe2xldCBFPUEueHNyZkhlYWRlck5hbWUmJkEueHNyZkNvb2tpZU5hbWUmJk50LnJlYWQoQS54c3JmQ29va2llTmFtZSk7RSYmci5zZXQoQS54c3JmSGVhZGVyTmFtZSxFKX1nPT09dm9pZCAwJiZyLnNldENvbnRlbnRUeXBlKG51bGwpLCJzZXRSZXF1ZXN0SGVhZGVyImluIGkmJkMuZm9yRWFjaChyLnRvSlNPTigpLGZ1bmN0aW9uKHUseSl7aS5zZXRSZXF1ZXN0SGVhZGVyKHksdSl9KSxDLmlzVW5kZWZpbmVkKEEud2l0aENyZWRlbnRpYWxzKXx8KGkud2l0aENyZWRlbnRpYWxzPSEhQS53aXRoQ3JlZGVudGlhbHMpLG8mJm8hPT0ianNvbiImJihpLnJlc3BvbnNlVHlwZT1BLnJlc3BvbnNlVHlwZSksdHlwZW9mIEEub25Eb3dubG9hZFByb2dyZXNzPT0iZnVuY3Rpb24iJiZpLmFkZEV2ZW50TGlzdGVuZXIoInByb2dyZXNzIixrdChBLm9uRG93bmxvYWRQcm9ncmVzcywhMCkpLHR5cGVvZiBBLm9uVXBsb2FkUHJvZ3Jlc3M9PSJmdW5jdGlvbiImJmkudXBsb2FkJiZpLnVwbG9hZC5hZGRFdmVudExpc3RlbmVyKCJwcm9ncmVzcyIsa3QoQS5vblVwbG9hZFByb2dyZXNzKSksKEEuY2FuY2VsVG9rZW58fEEuc2lnbmFsKSYmKGM9RT0+e2kmJihlKCFFfHxFLnR5cGU/bmV3IEgobnVsbCxBLGkpOkUpLGkuYWJvcnQoKSxpPW51bGwpfSxBLmNhbmNlbFRva2VuJiZBLmNhbmNlbFRva2VuLnN1YnNjcmliZShjKSxBLnNpZ25hbCYmKEEuc2lnbmFsLmFib3J0ZWQ/YygpOkEuc2lnbmFsLmFkZEV2ZW50TGlzdGVuZXIoImFib3J0IixjKSkpO2xldCBhPU9BKGYpO2lmKGEmJm0ucHJvdG9jb2xzLmluZGV4T2YoYSk9PT0tMSl7ZShuZXcgbCgiVW5zdXBwb3J0ZWQgcHJvdG9jb2wgIithKyI6IixsLkVSUl9CQURfUkVRVUVTVCxBKSk7cmV0dXJufWkuc2VuZChnfHxudWxsKX0pfTt2YXIgVEE9e2h0dHA6YUEseGhyOkx0fTtDLmZvckVhY2goVEEsKEEsdCk9PntpZihBKXt0cnl7T2JqZWN0LmRlZmluZVByb3BlcnR5KEEsIm5hbWUiLHt2YWx1ZTp0fSl9Y2F0Y2h7fU9iamVjdC5kZWZpbmVQcm9wZXJ0eShBLCJhZGFwdGVyTmFtZSIse3ZhbHVlOnR9KX19KTt2YXIgSnQ9QT0+YC0gJHtBfWAsYWU9QT0+Qy5pc0Z1bmN0aW9uKEEpfHxBPT09bnVsbHx8QT09PSExLERBPXtnZXRBZGFwdGVyOkE9PntBPUMuaXNBcnJheShBKT9BOltBXTtsZXR7bGVuZ3RoOnR9PUEsSSxlLGc9e307Zm9yKGxldCByPTA7cjx0O3IrKyl7ST1BW3JdO2xldCBvO2lmKGU9SSwhYWUoSSkmJihlPVRBWyhvPVN0cmluZyhJKSkudG9Mb3dlckNhc2UoKV0sZT09PXZvaWQgMCkpdGhyb3cgbmV3IGwoYFVua25vd24gYWRhcHRlciBcJyR7b31cJ2ApO2lmKGUpYnJlYWs7Z1tvfHwiJTIzIityXT1lfWlmKCFlKXtsZXQgcj1PYmplY3QuZW50cmllcyhnKS5tYXAoKFtuLGNdKT0+YGFkYXB0ZXIgJHtufSBgKyhjPT09ITE/ImlzIG5vdCBzdXBwb3J0ZWQgYnkgdGhlIGVudmlyb25tZW50IjoiaXMgbm90IGF2YWlsYWJsZSBpbiB0aGUgYnVpbGQiKSksbz10P3IubGVuZ3RoPjE/YHNpbmNlIDolMEFgK3IubWFwKEp0KS5qb2luKGAlMEFgKToiICIrSnQoclswXSk6ImFzIG5vIGFkYXB0ZXIgc3BlY2lmaWVkIjt0aHJvdyBuZXcgbCgiVGhlcmUgaXMgbm8gc3VpdGFibGUgYWRhcHRlciB0byBkaXNwYXRjaCB0aGUgcmVxdWVzdCAiK28sIkVSUl9OT1RfU1VQUE9SVCIpfXJldHVybiBlfSxhZGFwdGVyczpUQX07ZnVuY3Rpb24gUEEoQSl7aWYoQS5jYW5jZWxUb2tlbiYmQS5jYW5jZWxUb2tlbi50aHJvd0lmUmVxdWVzdGVkKCksQS5zaWduYWwmJkEuc2lnbmFsLmFib3J0ZWQpdGhyb3cgbmV3IEgobnVsbCxBKX1mdW5jdGlvbiB1QShBKXtyZXR1cm4gUEEoQSksQS5oZWFkZXJzPXAuZnJvbShBLmhlYWRlcnMpLEEuZGF0YT1fLmNhbGwoQSxBLnRyYW5zZm9ybVJlcXVlc3QpLFsicG9zdCIsInB1dCIsInBhdGNoIl0uaW5kZXhPZihBLm1ldGhvZCkhPT0tMSYmQS5oZWFkZXJzLnNldENvbnRlbnRUeXBlKCJhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQiLCExKSxEQS5nZXRBZGFwdGVyKEEuYWRhcHRlcnx8VC5hZGFwdGVyKShBKS50aGVuKGZ1bmN0aW9uKGUpe3JldHVybiBQQShBKSxlLmRhdGE9Xy5jYWxsKEEsQS50cmFuc2Zvcm1SZXNwb25zZSxlKSxlLmhlYWRlcnM9cC5mcm9tKGUuaGVhZGVycyksZX0sZnVuY3Rpb24oZSl7cmV0dXJuIHYoZSl8fChQQShBKSxlJiZlLnJlc3BvbnNlJiYoZS5yZXNwb25zZS5kYXRhPV8uY2FsbChBLEEudHJhbnNmb3JtUmVzcG9uc2UsZS5yZXNwb25zZSksZS5yZXNwb25zZS5oZWFkZXJzPXAuZnJvbShlLnJlc3BvbnNlLmhlYWRlcnMpKSksUHJvbWlzZS5yZWplY3QoZSl9KX12YXIgSHQ9QT0+QSBpbnN0YW5jZW9mIHA/ey4uLkF9OkE7ZnVuY3Rpb24gayhBLHQpe3Q9dHx8e307bGV0IEk9e307ZnVuY3Rpb24gZShRLEIsaSl7cmV0dXJuIEMuaXNQbGFpbk9iamVjdChRKSYmQy5pc1BsYWluT2JqZWN0KEIpP0MubWVyZ2UuY2FsbCh7Y2FzZWxlc3M6aX0sUSxCKTpDLmlzUGxhaW5PYmplY3QoQik/Qy5tZXJnZSh7fSxCKTpDLmlzQXJyYXkoQik/Qi5zbGljZSgpOkJ9ZnVuY3Rpb24gZyhRLEIsaSl7aWYoQy5pc1VuZGVmaW5lZChCKSl7aWYoIUMuaXNVbmRlZmluZWQoUSkpcmV0dXJuIGUodm9pZCAwLFEsaSl9ZWxzZSByZXR1cm4gZShRLEIsaSl9ZnVuY3Rpb24gcihRLEIpe2lmKCFDLmlzVW5kZWZpbmVkKEIpKXJldHVybiBlKHZvaWQgMCxCKX1mdW5jdGlvbiBvKFEsQil7aWYoQy5pc1VuZGVmaW5lZChCKSl7aWYoIUMuaXNVbmRlZmluZWQoUSkpcmV0dXJuIGUodm9pZCAwLFEpfWVsc2UgcmV0dXJuIGUodm9pZCAwLEIpfWZ1bmN0aW9uIG4oUSxCLGkpe2lmKGkgaW4gdClyZXR1cm4gZShRLEIpO2lmKGkgaW4gQSlyZXR1cm4gZSh2b2lkIDAsUSl9bGV0IGM9e3VybDpyLG1ldGhvZDpyLGRhdGE6cixiYXNlVVJMOm8sdHJhbnNmb3JtUmVxdWVzdDpvLHRyYW5zZm9ybVJlc3BvbnNlOm8scGFyYW1zU2VyaWFsaXplcjpvLHRpbWVvdXQ6byx0aW1lb3V0TWVzc2FnZTpvLHdpdGhDcmVkZW50aWFsczpvLHdpdGhYU1JGVG9rZW46byxhZGFwdGVyOm8scmVzcG9uc2VUeXBlOm8seHNyZkNvb2tpZU5hbWU6byx4c3JmSGVhZGVyTmFtZTpvLG9uVXBsb2FkUHJvZ3Jlc3M6byxvbkRvd25sb2FkUHJvZ3Jlc3M6byxkZWNvbXByZXNzOm8sbWF4Q29udGVudExlbmd0aDpvLG1heEJvZHlMZW5ndGg6byxiZWZvcmVSZWRpcmVjdDpvLHRyYW5zcG9ydDpvLGh0dHBBZ2VudDpvLGh0dHBzQWdlbnQ6byxjYW5jZWxUb2tlbjpvLHNvY2tldFBhdGg6byxyZXNwb25zZUVuY29kaW5nOm8sdmFsaWRhdGVTdGF0dXM6bixoZWFkZXJzOihRLEIpPT5nKEh0KFEpLEh0KEIpLCEwKX07cmV0dXJuIEMuZm9yRWFjaChPYmplY3Qua2V5cyhPYmplY3QuYXNzaWduKHt9LEEsdCkpLGZ1bmN0aW9uKEIpe2xldCBpPWNbQl18fGcsZj1pKEFbQl0sdFtCXSxCKTtDLmlzVW5kZWZpbmVkKGYpJiZpIT09bnx8KElbQl09Zil9KSxJfXZhciBoQT0iMS42LjgiO3ZhciB4QT17fTtbIm9iamVjdCIsImJvb2xlYW4iLCJudW1iZXIiLCJmdW5jdGlvbiIsInN0cmluZyIsInN5bWJvbCJdLmZvckVhY2goKEEsdCk9Pnt4QVtBXT1mdW5jdGlvbihlKXtyZXR1cm4gdHlwZW9mIGU9PT1BfHwiYSIrKHQ8MT8ibiAiOiIgIikrQX19KTt2YXIgWXQ9e307eEEudHJhbnNpdGlvbmFsPWZ1bmN0aW9uKHQsSSxlKXtmdW5jdGlvbiBnKHIsbyl7cmV0dXJuIltBeGlvcyB2IitoQSsiXSBUcmFuc2l0aW9uYWwgb3B0aW9uIFwnIityKyJcJyIrbysoZT8iLiAiK2U6IiIpfXJldHVybihyLG8sbik9PntpZih0PT09ITEpdGhyb3cgbmV3IGwoZyhvLCIgaGFzIGJlZW4gcmVtb3ZlZCIrKEk/IiBpbiAiK0k6IiIpKSxsLkVSUl9ERVBSRUNBVEVEKTtyZXR1cm4gSSYmIVl0W29dJiYoWXRbb109ITAsY29uc29sZS53YXJuKGcobywiIGhhcyBiZWVuIGRlcHJlY2F0ZWQgc2luY2UgdiIrSSsiIGFuZCB3aWxsIGJlIHJlbW92ZWQgaW4gdGhlIG5lYXIgZnV0dXJlIikpKSx0P3QocixvLG4pOiEwfX07ZnVuY3Rpb24gRWUoQSx0LEkpe2lmKHR5cGVvZiBBIT0ib2JqZWN0Iil0aHJvdyBuZXcgbCgib3B0aW9ucyBtdXN0IGJlIGFuIG9iamVjdCIsbC5FUlJfQkFEX09QVElPTl9WQUxVRSk7bGV0IGU9T2JqZWN0LmtleXMoQSksZz1lLmxlbmd0aDtmb3IoO2ctLSA+MDspe2xldCByPWVbZ10sbz10W3JdO2lmKG8pe2xldCBuPUFbcl0sYz1uPT09dm9pZCAwfHxvKG4scixBKTtpZihjIT09ITApdGhyb3cgbmV3IGwoIm9wdGlvbiAiK3IrIiBtdXN0IGJlICIrYyxsLkVSUl9CQURfT1BUSU9OX1ZBTFVFKTtjb250aW51ZX1pZihJIT09ITApdGhyb3cgbmV3IGwoIlVua25vd24gb3B0aW9uICIrcixsLkVSUl9CQURfT1BUSU9OKX19dmFyIGRBPXthc3NlcnRPcHRpb25zOkVlLHZhbGlkYXRvcnM6eEF9O3ZhciBZPWRBLnZhbGlkYXRvcnMseD1jbGFzc3tjb25zdHJ1Y3Rvcih0KXt0aGlzLmRlZmF1bHRzPXQsdGhpcy5pbnRlcmNlcHRvcnM9e3JlcXVlc3Q6bmV3IExBLHJlc3BvbnNlOm5ldyBMQX19YXN5bmMgcmVxdWVzdCh0LEkpe3RyeXtyZXR1cm4gYXdhaXQgdGhpcy5fcmVxdWVzdCh0LEkpfWNhdGNoKGUpe2lmKGUgaW5zdGFuY2VvZiBFcnJvcil7bGV0IGc7RXJyb3IuY2FwdHVyZVN0YWNrVHJhY2U/RXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UoZz17fSk6Zz1uZXcgRXJyb3I7bGV0IHI9Zy5zdGFjaz9nLnN0YWNrLnJlcGxhY2UoL14uK1xcbi8sIiIpOiIiO2Uuc3RhY2s/ciYmIVN0cmluZyhlLnN0YWNrKS5lbmRzV2l0aChyLnJlcGxhY2UoL14uK1xcbi4rXFxuLywiIikpJiYoZS5zdGFjays9YCUwQWArcik6ZS5zdGFjaz1yfXRocm93IGV9fV9yZXF1ZXN0KHQsSSl7dHlwZW9mIHQ9PSJzdHJpbmciPyhJPUl8fHt9LEkudXJsPXQpOkk9dHx8e30sST1rKHRoaXMuZGVmYXVsdHMsSSk7bGV0e3RyYW5zaXRpb25hbDplLHBhcmFtc1NlcmlhbGl6ZXI6ZyxoZWFkZXJzOnJ9PUk7ZSE9PXZvaWQgMCYmZEEuYXNzZXJ0T3B0aW9ucyhlLHtzaWxlbnRKU09OUGFyc2luZzpZLnRyYW5zaXRpb25hbChZLmJvb2xlYW4pLGZvcmNlZEpTT05QYXJzaW5nOlkudHJhbnNpdGlvbmFsKFkuYm9vbGVhbiksY2xhcmlmeVRpbWVvdXRFcnJvcjpZLnRyYW5zaXRpb25hbChZLmJvb2xlYW4pfSwhMSksZyE9bnVsbCYmKEMuaXNGdW5jdGlvbihnKT9JLnBhcmFtc1NlcmlhbGl6ZXI9e3NlcmlhbGl6ZTpnfTpkQS5hc3NlcnRPcHRpb25zKGcse2VuY29kZTpZLmZ1bmN0aW9uLHNlcmlhbGl6ZTpZLmZ1bmN0aW9ufSwhMCkpLEkubWV0aG9kPShJLm1ldGhvZHx8dGhpcy5kZWZhdWx0cy5tZXRob2R8fCJnZXQiKS50b0xvd2VyQ2FzZSgpO2xldCBvPXImJkMubWVyZ2Uoci5jb21tb24scltJLm1ldGhvZF0pO3ImJkMuZm9yRWFjaChbImRlbGV0ZSIsImdldCIsImhlYWQiLCJwb3N0IiwicHV0IiwicGF0Y2giLCJjb21tb24iXSxhPT57ZGVsZXRlIHJbYV19KSxJLmhlYWRlcnM9cC5jb25jYXQobyxyKTtsZXQgbj1bXSxjPSEwO3RoaXMuaW50ZXJjZXB0b3JzLnJlcXVlc3QuZm9yRWFjaChmdW5jdGlvbihFKXt0eXBlb2YgRS5ydW5XaGVuPT0iZnVuY3Rpb24iJiZFLnJ1bldoZW4oSSk9PT0hMXx8KGM9YyYmRS5zeW5jaHJvbm91cyxuLnVuc2hpZnQoRS5mdWxmaWxsZWQsRS5yZWplY3RlZCkpfSk7bGV0IFE9W107dGhpcy5pbnRlcmNlcHRvcnMucmVzcG9uc2UuZm9yRWFjaChmdW5jdGlvbihFKXtRLnB1c2goRS5mdWxmaWxsZWQsRS5yZWplY3RlZCl9KTtsZXQgQixpPTAsZjtpZighYyl7bGV0IGE9W3VBLmJpbmQodGhpcyksdm9pZCAwXTtmb3IoYS51bnNoaWZ0LmFwcGx5KGEsbiksYS5wdXNoLmFwcGx5KGEsUSksZj1hLmxlbmd0aCxCPVByb21pc2UucmVzb2x2ZShJKTtpPGY7KUI9Qi50aGVuKGFbaSsrXSxhW2krK10pO3JldHVybiBCfWY9bi5sZW5ndGg7bGV0IHM9STtmb3IoaT0wO2k8Zjspe2xldCBhPW5baSsrXSxFPW5baSsrXTt0cnl7cz1hKHMpfWNhdGNoKHUpe0UuY2FsbCh0aGlzLHUpO2JyZWFrfX10cnl7Qj11QS5jYWxsKHRoaXMscyl9Y2F0Y2goYSl7cmV0dXJuIFByb21pc2UucmVqZWN0KGEpfWZvcihpPTAsZj1RLmxlbmd0aDtpPGY7KUI9Qi50aGVuKFFbaSsrXSxRW2krK10pO3JldHVybiBCfWdldFVyaSh0KXt0PWsodGhpcy5kZWZhdWx0cyx0KTtsZXQgST0kKHQuYmFzZVVSTCx0LnVybCk7cmV0dXJuIFgoSSx0LnBhcmFtcyx0LnBhcmFtc1NlcmlhbGl6ZXIpfX07Qy5mb3JFYWNoKFsiZGVsZXRlIiwiZ2V0IiwiaGVhZCIsIm9wdGlvbnMiXSxmdW5jdGlvbih0KXt4LnByb3RvdHlwZVt0XT1mdW5jdGlvbihJLGUpe3JldHVybiB0aGlzLnJlcXVlc3QoayhlfHx7fSx7bWV0aG9kOnQsdXJsOkksZGF0YTooZXx8e30pLmRhdGF9KSl9fSk7Qy5mb3JFYWNoKFsicG9zdCIsInB1dCIsInBhdGNoIl0sZnVuY3Rpb24odCl7ZnVuY3Rpb24gSShlKXtyZXR1cm4gZnVuY3Rpb24ocixvLG4pe3JldHVybiB0aGlzLnJlcXVlc3QoayhufHx7fSx7bWV0aG9kOnQsaGVhZGVyczplP3siQ29udGVudC1UeXBlIjoibXVsdGlwYXJ0L2Zvcm0tZGF0YSJ9Ont9LHVybDpyLGRhdGE6b30pKX19eC5wcm90b3R5cGVbdF09SSgpLHgucHJvdG90eXBlW3QrIkZvcm0iXT1JKCEwKX0pO3ZhciBBQT14O3ZhciBqQT1jbGFzcyBBe2NvbnN0cnVjdG9yKHQpe2lmKHR5cGVvZiB0IT0iZnVuY3Rpb24iKXRocm93IG5ldyBUeXBlRXJyb3IoImV4ZWN1dG9yIG11c3QgYmUgYSBmdW5jdGlvbi4iKTtsZXQgSTt0aGlzLnByb21pc2U9bmV3IFByb21pc2UoZnVuY3Rpb24ocil7ST1yfSk7bGV0IGU9dGhpczt0aGlzLnByb21pc2UudGhlbihnPT57aWYoIWUuX2xpc3RlbmVycylyZXR1cm47bGV0IHI9ZS5fbGlzdGVuZXJzLmxlbmd0aDtmb3IoO3ItLSA+MDspZS5fbGlzdGVuZXJzW3JdKGcpO2UuX2xpc3RlbmVycz1udWxsfSksdGhpcy5wcm9taXNlLnRoZW49Zz0+e2xldCByLG89bmV3IFByb21pc2Uobj0+e2Uuc3Vic2NyaWJlKG4pLHI9bn0pLnRoZW4oZyk7cmV0dXJuIG8uY2FuY2VsPWZ1bmN0aW9uKCl7ZS51bnN1YnNjcmliZShyKX0sb30sdChmdW5jdGlvbihyLG8sbil7ZS5yZWFzb258fChlLnJlYXNvbj1uZXcgSChyLG8sbiksSShlLnJlYXNvbikpfSl9dGhyb3dJZlJlcXVlc3RlZCgpe2lmKHRoaXMucmVhc29uKXRocm93IHRoaXMucmVhc29ufXN1YnNjcmliZSh0KXtpZih0aGlzLnJlYXNvbil7dCh0aGlzLnJlYXNvbik7cmV0dXJufXRoaXMuX2xpc3RlbmVycz90aGlzLl9saXN0ZW5lcnMucHVzaCh0KTp0aGlzLl9saXN0ZW5lcnM9W3RdfXVuc3Vic2NyaWJlKHQpe2lmKCF0aGlzLl9saXN0ZW5lcnMpcmV0dXJuO2xldCBJPXRoaXMuX2xpc3RlbmVycy5pbmRleE9mKHQpO0khPT0tMSYmdGhpcy5fbGlzdGVuZXJzLnNwbGljZShJLDEpfXN0YXRpYyBzb3VyY2UoKXtsZXQgdDtyZXR1cm57dG9rZW46bmV3IEEoZnVuY3Rpb24oZyl7dD1nfSksY2FuY2VsOnR9fX0sYnQ9akE7ZnVuY3Rpb24gV0EoQSl7cmV0dXJuIGZ1bmN0aW9uKEkpe3JldHVybiBBLmFwcGx5KG51bGwsSSl9fWZ1bmN0aW9uIFpBKEEpe3JldHVybiBDLmlzT2JqZWN0KEEpJiZBLmlzQXhpb3NFcnJvcj09PSEwfXZhciBWQT17Q29udGludWU6MTAwLFN3aXRjaGluZ1Byb3RvY29sczoxMDEsUHJvY2Vzc2luZzoxMDIsRWFybHlIaW50czoxMDMsT2s6MjAwLENyZWF0ZWQ6MjAxLEFjY2VwdGVkOjIwMixOb25BdXRob3JpdGF0aXZlSW5mb3JtYXRpb246MjAzLE5vQ29udGVudDoyMDQsUmVzZXRDb250ZW50OjIwNSxQYXJ0aWFsQ29udGVudDoyMDYsTXVsdGlTdGF0dXM6MjA3LEFscmVhZHlSZXBvcnRlZDoyMDgsSW1Vc2VkOjIyNixNdWx0aXBsZUNob2ljZXM6MzAwLE1vdmVkUGVybWFuZW50bHk6MzAxLEZvdW5kOjMwMixTZWVPdGhlcjozMDMsTm90TW9kaWZpZWQ6MzA0LFVzZVByb3h5OjMwNSxVbnVzZWQ6MzA2LFRlbXBvcmFyeVJlZGlyZWN0OjMwNyxQZXJtYW5lbnRSZWRpcmVjdDozMDgsQmFkUmVxdWVzdDo0MDAsVW5hdXRob3JpemVkOjQwMSxQYXltZW50UmVxdWlyZWQ6NDAyLEZvcmJpZGRlbjo0MDMsTm90Rm91bmQ6NDA0LE1ldGhvZE5vdEFsbG93ZWQ6NDA1LE5vdEFjY2VwdGFibGU6NDA2LFByb3h5QXV0aGVudGljYXRpb25SZXF1aXJlZDo0MDcsUmVxdWVzdFRpbWVvdXQ6NDA4LENvbmZsaWN0OjQwOSxHb25lOjQxMCxMZW5ndGhSZXF1aXJlZDo0MTEsUHJlY29uZGl0aW9uRmFpbGVkOjQxMixQYXlsb2FkVG9vTGFyZ2U6NDEzLFVyaVRvb0xvbmc6NDE0LFVuc3VwcG9ydGVkTWVkaWFUeXBlOjQxNSxSYW5nZU5vdFNhdGlzZmlhYmxlOjQxNixFeHBlY3RhdGlvbkZhaWxlZDo0MTcsSW1BVGVhcG90OjQxOCxNaXNkaXJlY3RlZFJlcXVlc3Q6NDIxLFVucHJvY2Vzc2FibGVFbnRpdHk6NDIyLExvY2tlZDo0MjMsRmFpbGVkRGVwZW5kZW5jeTo0MjQsVG9vRWFybHk6NDI1LFVwZ3JhZGVSZXF1aXJlZDo0MjYsUHJlY29uZGl0aW9uUmVxdWlyZWQ6NDI4LFRvb01hbnlSZXF1ZXN0czo0MjksUmVxdWVzdEhlYWRlckZpZWxkc1Rvb0xhcmdlOjQzMSxVbmF2YWlsYWJsZUZvckxlZ2FsUmVhc29uczo0NTEsSW50ZXJuYWxTZXJ2ZXJFcnJvcjo1MDAsTm90SW1wbGVtZW50ZWQ6NTAxLEJhZEdhdGV3YXk6NTAyLFNlcnZpY2VVbmF2YWlsYWJsZTo1MDMsR2F0ZXdheVRpbWVvdXQ6NTA0LEh0dHBWZXJzaW9uTm90U3VwcG9ydGVkOjUwNSxWYXJpYW50QWxzb05lZ290aWF0ZXM6NTA2LEluc3VmZmljaWVudFN0b3JhZ2U6NTA3LExvb3BEZXRlY3RlZDo1MDgsTm90RXh0ZW5kZWQ6NTEwLE5ldHdvcmtBdXRoZW50aWNhdGlvblJlcXVpcmVkOjUxMX07T2JqZWN0LmVudHJpZXMoVkEpLmZvckVhY2goKFtBLHRdKT0+e1ZBW3RdPUF9KTt2YXIgTXQ9VkE7ZnVuY3Rpb24gcXQoQSl7bGV0IHQ9bmV3IEFBKEEpLEk9VyhBQS5wcm90b3R5cGUucmVxdWVzdCx0KTtyZXR1cm4gQy5leHRlbmQoSSxBQS5wcm90b3R5cGUsdCx7YWxsT3duS2V5czohMH0pLEMuZXh0ZW5kKEksdCxudWxsLHthbGxPd25LZXlzOiEwfSksSS5jcmVhdGU9ZnVuY3Rpb24oZyl7cmV0dXJuIHF0KGsoQSxnKSl9LEl9dmFyIGg9cXQoVCk7aC5BeGlvcz1BQTtoLkNhbmNlbGVkRXJyb3I9SDtoLkNhbmNlbFRva2VuPWJ0O2guaXNDYW5jZWw9djtoLlZFUlNJT049aEE7aC50b0Zvcm1EYXRhPUo7aC5BeGlvc0Vycm9yPWw7aC5DYW5jZWw9aC5DYW5jZWxlZEVycm9yO2guYWxsPWZ1bmN0aW9uKHQpe3JldHVybiBQcm9taXNlLmFsbCh0KX07aC5zcHJlYWQ9V0E7aC5pc0F4aW9zRXJyb3I9WkE7aC5tZXJnZUNvbmZpZz1rO2guQXhpb3NIZWFkZXJzPXA7aC5mb3JtVG9KU09OPUE9PmZBKEMuaXNIVE1MRm9ybShBKT9uZXcgRm9ybURhdGEoQSk6QSk7aC5nZXRBZGFwdGVyPURBLmdldEFkYXB0ZXI7aC5IdHRwU3RhdHVzQ29kZT1NdDtoLmRlZmF1bHQ9aDt2YXIgeUE9aDt2YXJ7QXhpb3M6aW8sQXhpb3NFcnJvcjpDbyxDYW5jZWxlZEVycm9yOkJvLGlzQ2FuY2VsOnNvLENhbmNlbFRva2VuOm5vLFZFUlNJT046UW8sYWxsOmFvLENhbmNlbDpFbyxpc0F4aW9zRXJyb3I6Y28sc3ByZWFkOmZvLHRvRm9ybURhdGE6bG8sQXhpb3NIZWFkZXJzOkRvLEh0dHBTdGF0dXNDb2RlOnVvLGZvcm1Ub0pTT046aG8sZ2V0QWRhcHRlcjp5byxtZXJnZUNvbmZpZzp3b309eUE7dmFyIHRBLEwsekEsWEE9e2Vudjp7ZW1zY3JpcHRlbl9ub3RpZnlfbWVtb3J5X2dyb3d0aDpmdW5jdGlvbihBKXt6QT1uZXcgVWludDhBcnJheShMLmV4cG9ydHMubWVtb3J5LmJ1ZmZlcil9fX0sd0E9Y2xhc3N7aW5pdCgpe3JldHVybiB0QXx8KHR5cGVvZiBmZXRjaDwidSI/dEE9ZmV0Y2goImRhdGE6YXBwbGljYXRpb24vd2FzbTtiYXNlNjQsIitLdCkudGhlbih0PT50LmFycmF5QnVmZmVyKCkpLnRoZW4odD0+V2ViQXNzZW1ibHkuaW5zdGFudGlhdGUodCxYQSkpLnRoZW4odGhpcy5faW5pdCk6dEE9V2ViQXNzZW1ibHkuaW5zdGFudGlhdGUoQnVmZmVyLmZyb20oS3QsImJhc2U2NCIpLFhBKS50aGVuKHRoaXMuX2luaXQpLHRBKX1faW5pdCh0KXtMPXQuaW5zdGFuY2UsWEEuZW52LmVtc2NyaXB0ZW5fbm90aWZ5X21lbW9yeV9ncm93dGgoMCl9ZGVjb2RlKHQsST0wKXtpZighTCl0aHJvdyBuZXcgRXJyb3IoIlpTVEREZWNvZGVyOiBBd2FpdCAuaW5pdCgpIGJlZm9yZSBkZWNvZGluZy4iKTtsZXQgZT10LmJ5dGVMZW5ndGgsZz1MLmV4cG9ydHMubWFsbG9jKGUpO3pBLnNldCh0LGcpLEk9SXx8TnVtYmVyKEwuZXhwb3J0cy5aU1REX2ZpbmREZWNvbXByZXNzZWRTaXplKGcsZSkpO2xldCByPUwuZXhwb3J0cy5tYWxsb2MoSSksbz1MLmV4cG9ydHMuWlNURF9kZWNvbXByZXNzKHIsSSxnLGUpLG49ekEuc2xpY2UocixyK28pO3JldHVybiBMLmV4cG9ydHMuZnJlZShnKSxMLmV4cG9ydHMuZnJlZShyKSxufX0sS3Q9IkFHRnpiUUVBQUFBQmJnNWdBMzkvZndGL1lBRi9BWDlnQW45L0FHQUJmd0JnQlg5L2YzOS9BWDlnQTM5L2Z3QmdCSDkvZjM4QmYyQUFBWDlnQW45L0FYOWdCMzkvZjM5L2YzOEJmMkFDZjM4QmZtQUlmMzkvZjM5L2YzOEJmMkFGZjM5L2YzOEFZQTUvZjM5L2YzOS9mMzkvZjM5L2Z3Ri9BaWNCQTJWdWRoOWxiWE5qY21sd2RHVnVYMjV2ZEdsbWVWOXRaVzF2Y25sZlozSnZkM1JvQUFNREl5SUhBQUFCQVFNSEF3RUFDUVFBQlFFSUNBRUZCZ1FFQkFNR0FBQUtBQVVMREEwR0JBVUJjQUVCQVFVSEFRR0FBb0NBQWdZSUFYOEJRWUNqQkFzSHJnRUxCbTFsYlc5eWVRSUFCbTFoYkd4dll3QUZCR1p5WldVQUJneGFVMVJFWDJselJYSnliM0lBRWhsYVUxUkVYMlpwYm1SRVpXTnZiWEJ5WlhOelpXUlRhWHBsQUJ3UFdsTlVSRjlrWldOdmJYQnlaWE56QUNJWlgxOXBibVJwY21WamRGOW1kVzVqZEdsdmJsOTBZV0pzWlFFQUVGOWZaWEp5Ym05ZmJHOWpZWFJwYjI0QUFRbHpkR0ZqYTFOaGRtVUFCd3h6ZEdGamExSmxjM1J2Y21VQUNBcHpkR0ZqYTBGc2JHOWpBQWtLaS9JQklnVUFRWVFmQ3pNQkFYOGdBZ1JBSUFBaEF3TkFJQU1nQVMwQUFEb0FBQ0FEUVFGcUlRTWdBVUVCYWlFQklBSkJBV3NpQWcwQUN3c2dBQXNwQVFGL0lBSUVRQ0FBSVFNRFFDQURJQUU2QUFBZ0EwRUJhaUVESUFKQkFXc2lBZzBBQ3dzZ0FBdHNBUUovUVlBZktBSUFJZ0VnQUVFSGFrRjRjU0lDYWlFQUFrQWdBa0VBSUFBZ0FVMGJEUUFnQUQ4QVFSQjBTd1JBSUFBL0FFRVFkR3RCLy84RGFrRVFka0FBUVg5R0JIOUJBQVZCQUJBQVFRRUxSUTBCQzBHQUh5QUFOZ0lBSUFFUEMwR0VIMEV3TmdJQVFYOEx1U2NCQzM4akFFRVFheUlLSkFBQ1FBSkFBa0FDUUFKQUFrQUNRQUpBQWtBQ1FBSkFBa0FDUUFKQUlBQkI5QUZOQkVCQmlCOG9BZ0FpQmtFUUlBQkJDMnBCZUhFZ0FFRUxTUnNpQlVFRGRpSUFkaUlCUVFOeEJFQUNRQ0FCUVg5elFRRnhJQUJxSWdKQkEzUWlBVUd3SDJvaUFDQUJRYmdmYWlnQ0FDSUJLQUlJSWdSR0JFQkJpQjhnQmtGK0lBSjNjVFlDQUF3QkN5QUVJQUEyQWd3Z0FDQUVOZ0lJQ3lBQlFRaHFJUUFnQVNBQ1FRTjBJZ0pCQTNJMkFnUWdBU0FDYWlJQklBRW9BZ1JCQVhJMkFnUU1Ed3NnQlVHUUh5Z0NBQ0lIVFEwQklBRUVRQUpBUVFJZ0FIUWlBa0VBSUFKcmNpQUJJQUIwY1dnaUFVRURkQ0lBUWJBZmFpSUNJQUJCdUI5cUtBSUFJZ0FvQWdnaUJFWUVRRUdJSHlBR1FYNGdBWGR4SWdZMkFnQU1BUXNnQkNBQ05nSU1JQUlnQkRZQ0NBc2dBQ0FGUVFOeU5nSUVJQUFnQldvaUNDQUJRUU4wSWdFZ0JXc2lCRUVCY2pZQ0JDQUFJQUZxSUFRMkFnQWdCd1JBSUFkQmVIRkJzQjlxSVFGQm5COG9BZ0FoQWdKL0lBWkJBU0FIUVFOMmRDSURjVVVFUUVHSUh5QURJQVp5TmdJQUlBRU1BUXNnQVNnQ0NBc2hBeUFCSUFJMkFnZ2dBeUFDTmdJTUlBSWdBVFlDRENBQ0lBTTJBZ2dMSUFCQkNHb2hBRUdjSHlBSU5nSUFRWkFmSUFRMkFnQU1Ed3RCakI4b0FnQWlDMFVOQVNBTGFFRUNkRUc0SVdvb0FnQWlBaWdDQkVGNGNTQUZheUVESUFJaEFRTkFBa0FnQVNnQ0VDSUFSUVJBSUFFb0FoUWlBRVVOQVFzZ0FDZ0NCRUY0Y1NBRmF5SUJJQU1nQVNBRFNTSUJHeUVESUFBZ0FpQUJHeUVDSUFBaEFRd0JDd3NnQWlnQ0dDRUpJQUlnQWlnQ0RDSUVSd1JBUVpnZktBSUFHaUFDS0FJSUlnQWdCRFlDRENBRUlBQTJBZ2dNRGdzZ0FrRVVhaUlCS0FJQUlnQkZCRUFnQWlnQ0VDSUFSUTBESUFKQkVHb2hBUXNEUUNBQklRZ2dBQ0lFUVJScUlnRW9BZ0FpQUEwQUlBUkJFR29oQVNBRUtBSVFJZ0FOQUFzZ0NFRUFOZ0lBREEwTFFYOGhCU0FBUWI5L1N3MEFJQUJCQzJvaUFFRjRjU0VGUVl3ZktBSUFJZ2hGRFFCQkFDQUZheUVEQWtBQ1FBSkFBbjlCQUNBRlFZQUNTUTBBR2tFZklBVkIvLy8vQjBzTkFCb2dCVUVtSUFCQkNIWm5JZ0JyZGtFQmNTQUFRUUYwYTBFK2Fnc2lCMEVDZEVHNElXb29BZ0FpQVVVRVFFRUFJUUFNQVF0QkFDRUFJQVZCR1NBSFFRRjJhMEVBSUFkQkgwY2JkQ0VDQTBBQ1FDQUJLQUlFUVhoeElBVnJJZ1lnQTA4TkFDQUJJUVFnQmlJRERRQkJBQ0VESUFFaEFBd0RDeUFBSUFFb0FoUWlCaUFHSUFFZ0FrRWRka0VFY1dvb0FoQWlBVVliSUFBZ0Joc2hBQ0FDUVFGMElRSWdBUTBBQ3dzZ0FDQUVja1VFUUVFQUlRUkJBaUFIZENJQVFRQWdBR3R5SUFoeElnQkZEUU1nQUdoQkFuUkJ1Q0ZxS0FJQUlRQUxJQUJGRFFFTEEwQWdBQ2dDQkVGNGNTQUZheUlDSUFOSklRRWdBaUFESUFFYklRTWdBQ0FFSUFFYklRUWdBQ2dDRUNJQkJIOGdBUVVnQUNnQ0ZBc2lBQTBBQ3dzZ0JFVU5BQ0FEUVpBZktBSUFJQVZyVHcwQUlBUW9BaGdoQnlBRUlBUW9BZ3dpQWtjRVFFR1lIeWdDQUJvZ0JDZ0NDQ0lBSUFJMkFnd2dBaUFBTmdJSURBd0xJQVJCRkdvaUFTZ0NBQ0lBUlFSQUlBUW9BaEFpQUVVTkF5QUVRUkJxSVFFTEEwQWdBU0VHSUFBaUFrRVVhaUlCS0FJQUlnQU5BQ0FDUVJCcUlRRWdBaWdDRUNJQURRQUxJQVpCQURZQ0FBd0xDeUFGUVpBZktBSUFJZ1JOQkVCQm5COG9BZ0FoQUFKQUlBUWdCV3NpQVVFUVR3UkFJQUFnQldvaUFpQUJRUUZ5TmdJRUlBQWdCR29nQVRZQ0FDQUFJQVZCQTNJMkFnUU1BUXNnQUNBRVFRTnlOZ0lFSUFBZ0JHb2lBU0FCS0FJRVFRRnlOZ0lFUVFBaEFrRUFJUUVMUVpBZklBRTJBZ0JCbkI4Z0FqWUNBQ0FBUVFocUlRQU1EUXNnQlVHVUh5Z0NBQ0lDU1FSQVFaUWZJQUlnQldzaUFUWUNBRUdnSDBHZ0h5Z0NBQ0lBSUFWcUlnSTJBZ0FnQWlBQlFRRnlOZ0lFSUFBZ0JVRURjallDQkNBQVFRaHFJUUFNRFF0QkFDRUFJQVZCTDJvaUF3Si9RZUFpS0FJQUJFQkI2Q0lvQWdBTUFRdEI3Q0pDZnpjQ0FFSGtJa0tBb0lDQWdJQUVOd0lBUWVBaUlBcEJER3BCY0hGQjJLclZxZ1Z6TmdJQVFmUWlRUUEyQWdCQnhDSkJBRFlDQUVHQUlBc2lBV29pQmtFQUlBRnJJZ2h4SWdFZ0JVME5ERUhBSWlnQ0FDSUVCRUJCdUNJb0FnQWlCeUFCYWlJSklBZE5JQVFnQ1VseURRMExBa0JCeENJdEFBQkJCSEZGQkVBQ1FBSkFBa0FDUUVHZ0h5Z0NBQ0lFQkVCQnlDSWhBQU5BSUFRZ0FDZ0NBQ0lIVHdSQUlBY2dBQ2dDQkdvZ0JFc05Bd3NnQUNnQ0NDSUFEUUFMQzBFQUVBUWlBa0YvUmcwRElBRWhCa0hrSWlnQ0FDSUFRUUZySWdRZ0FuRUVRQ0FCSUFKcklBSWdCR3BCQUNBQWEzRnFJUVlMSUFVZ0JrOE5BMEhBSWlnQ0FDSUFCRUJCdUNJb0FnQWlCQ0FHYWlJSUlBUk5JQUFnQ0VseURRUUxJQVlRQkNJQUlBSkhEUUVNQlFzZ0JpQUNheUFJY1NJR0VBUWlBaUFBS0FJQUlBQW9BZ1JxUmcwQklBSWhBQXNnQUVGL1JnMEJJQVZCTUdvZ0JrMEVRQ0FBSVFJTUJBdEI2Q0lvQWdBaUFpQURJQVpyYWtFQUlBSnJjU0lDRUFSQmYwWU5BU0FDSUFacUlRWWdBQ0VDREFNTElBSkJmMGNOQWd0QnhDSkJ4Q0lvQWdCQkJISTJBZ0FMSUFFUUJDSUNRWDlHUVFBUUJDSUFRWDlHY2lBQUlBSk5jZzBGSUFBZ0Ftc2lCaUFGUVNocVRRMEZDMEc0SWtHNElpZ0NBQ0FHYWlJQU5nSUFRYndpS0FJQUlBQkpCRUJCdkNJZ0FEWUNBQXNDUUVHZ0h5Z0NBQ0lEQkVCQnlDSWhBQU5BSUFJZ0FDZ0NBQ0lCSUFBb0FnUWlCR3BHRFFJZ0FDZ0NDQ0lBRFFBTERBUUxRWmdmS0FJQUlnQkJBQ0FBSUFKTkcwVUVRRUdZSHlBQ05nSUFDMEVBSVFCQnpDSWdCallDQUVISUlpQUNOZ0lBUWFnZlFYODJBZ0JCckI5QjRDSW9BZ0EyQWdCQjFDSkJBRFlDQUFOQUlBQkJBM1FpQVVHNEgyb2dBVUd3SDJvaUJEWUNBQ0FCUWJ3ZmFpQUVOZ0lBSUFCQkFXb2lBRUVnUncwQUMwR1VIeUFHUVNocklnQkJlQ0FDYTBFSGNTSUJheUlFTmdJQVFhQWZJQUVnQW1vaUFUWUNBQ0FCSUFSQkFYSTJBZ1FnQUNBQ2FrRW9OZ0lFUWFRZlFmQWlLQUlBTmdJQURBUUxJQUlnQTAwZ0FTQURTM0lOQWlBQUtBSU1RUWh4RFFJZ0FDQUVJQVpxTmdJRVFhQWZJQU5CZUNBRGEwRUhjU0lBYWlJQk5nSUFRWlFmUVpRZktBSUFJQVpxSWdJZ0FHc2lBRFlDQUNBQklBQkJBWEkyQWdRZ0FpQURha0VvTmdJRVFhUWZRZkFpS0FJQU5nSUFEQU1MUVFBaEJBd0tDMEVBSVFJTUNBdEJtQjhvQWdBZ0Frc0VRRUdZSHlBQ05nSUFDeUFDSUFacUlRRkJ5Q0loQUFKQUFrQUNRQU5BSUFFZ0FDZ0NBRWNFUUNBQUtBSUlJZ0FOQVF3Q0N3c2dBQzBBREVFSWNVVU5BUXRCeUNJaEFBTkFJQU1nQUNnQ0FDSUJUd1JBSUFFZ0FDZ0NCR29pQkNBRFN3MERDeUFBS0FJSUlRQU1BQXNBQ3lBQUlBSTJBZ0FnQUNBQUtBSUVJQVpxTmdJRUlBSkJlQ0FDYTBFSGNXb2lCeUFGUVFOeU5nSUVJQUZCZUNBQmEwRUhjV29pQmlBRklBZHFJZ1ZySVFBZ0F5QUdSZ1JBUWFBZklBVTJBZ0JCbEI5QmxCOG9BZ0FnQUdvaUFEWUNBQ0FGSUFCQkFYSTJBZ1FNQ0F0Qm5COG9BZ0FnQmtZRVFFR2NIeUFGTmdJQVFaQWZRWkFmS0FJQUlBQnFJZ0EyQWdBZ0JTQUFRUUZ5TmdJRUlBQWdCV29nQURZQ0FBd0lDeUFHS0FJRUlnTkJBM0ZCQVVjTkJpQURRWGh4SVFrZ0EwSC9BVTBFUUNBR0tBSU1JZ0VnQmlnQ0NDSUNSZ1JBUVlnZlFZZ2ZLQUlBUVg0Z0EwRURkbmR4TmdJQURBY0xJQUlnQVRZQ0RDQUJJQUkyQWdnTUJnc2dCaWdDR0NFSUlBWWdCaWdDRENJQ1J3UkFJQVlvQWdnaUFTQUNOZ0lNSUFJZ0FUWUNDQXdGQ3lBR1FSUnFJZ0VvQWdBaUEwVUVRQ0FHS0FJUUlnTkZEUVFnQmtFUWFpRUJDd05BSUFFaEJDQURJZ0pCRkdvaUFTZ0NBQ0lERFFBZ0FrRVFhaUVCSUFJb0FoQWlBdzBBQ3lBRVFRQTJBZ0FNQkF0QmxCOGdCa0VvYXlJQVFYZ2dBbXRCQjNFaUFXc2lDRFlDQUVHZ0h5QUJJQUpxSWdFMkFnQWdBU0FJUVFGeU5nSUVJQUFnQW1wQktEWUNCRUdrSDBId0lpZ0NBRFlDQUNBRElBUkJKeUFFYTBFSGNXcEJMMnNpQUNBQUlBTkJFR3BKR3lJQlFSczJBZ1FnQVVIUUlpa0NBRGNDRUNBQlFjZ2lLUUlBTndJSVFkQWlJQUZCQ0dvMkFnQkJ6Q0lnQmpZQ0FFSElJaUFDTmdJQVFkUWlRUUEyQWdBZ0FVRVlhaUVBQTBBZ0FFRUhOZ0lFSUFCQkNHb2dBRUVFYWlFQUlBUkpEUUFMSUFFZ0EwWU5BQ0FCSUFFb0FnUkJmbkUyQWdRZ0F5QUJJQU5ySWdKQkFYSTJBZ1FnQVNBQ05nSUFJQUpCL3dGTkJFQWdBa0Y0Y1VHd0gyb2hBQUovUVlnZktBSUFJZ0ZCQVNBQ1FRTjJkQ0lDY1VVRVFFR0lIeUFCSUFKeU5nSUFJQUFNQVFzZ0FDZ0NDQXNoQVNBQUlBTTJBZ2dnQVNBRE5nSU1JQU1nQURZQ0RDQURJQUUyQWdnTUFRdEJIeUVBSUFKQi8vLy9CMDBFUUNBQ1FTWWdBa0VJZG1jaUFHdDJRUUZ4SUFCQkFYUnJRVDVxSVFBTElBTWdBRFlDSENBRFFnQTNBaEFnQUVFQ2RFRzRJV29oQVFKQUFrQkJqQjhvQWdBaUJFRUJJQUIwSWdaeFJRUkFRWXdmSUFRZ0JuSTJBZ0FnQVNBRE5nSUFEQUVMSUFKQkdTQUFRUUYyYTBFQUlBQkJIMGNiZENFQUlBRW9BZ0FoQkFOQUlBUWlBU2dDQkVGNGNTQUNSZzBDSUFCQkhYWWhCQ0FBUVFGMElRQWdBU0FFUVFSeGFpSUdLQUlRSWdRTkFBc2dCaUFETmdJUUN5QURJQUUyQWhnZ0F5QUROZ0lNSUFNZ0F6WUNDQXdCQ3lBQktBSUlJZ0FnQXpZQ0RDQUJJQU0yQWdnZ0EwRUFOZ0lZSUFNZ0FUWUNEQ0FESUFBMkFnZ0xRWlFmS0FJQUlnQWdCVTBOQUVHVUh5QUFJQVZySWdFMkFnQkJvQjlCb0I4b0FnQWlBQ0FGYWlJQ05nSUFJQUlnQVVFQmNqWUNCQ0FBSUFWQkEzSTJBZ1FnQUVFSWFpRUFEQWdMUVlRZlFUQTJBZ0JCQUNFQURBY0xRUUFoQWdzZ0NFVU5BQUpBSUFZb0Fod2lBVUVDZEVHNElXb2lCQ2dDQUNBR1JnUkFJQVFnQWpZQ0FDQUNEUUZCakI5QmpCOG9BZ0JCZmlBQmQzRTJBZ0FNQWdzZ0NFRVFRUlFnQ0NnQ0VDQUdSaHRxSUFJMkFnQWdBa1VOQVFzZ0FpQUlOZ0lZSUFZb0FoQWlBUVJBSUFJZ0FUWUNFQ0FCSUFJMkFoZ0xJQVlvQWhRaUFVVU5BQ0FDSUFFMkFoUWdBU0FDTmdJWUN5QUFJQWxxSVFBZ0JpQUphaUlHS0FJRUlRTUxJQVlnQTBGK2NUWUNCQ0FGSUFCQkFYSTJBZ1FnQUNBRmFpQUFOZ0lBSUFCQi93Rk5CRUFnQUVGNGNVR3dIMm9oQVFKL1FZZ2ZLQUlBSWdKQkFTQUFRUU4yZENJQWNVVUVRRUdJSHlBQUlBSnlOZ0lBSUFFTUFRc2dBU2dDQ0FzaEFDQUJJQVUyQWdnZ0FDQUZOZ0lNSUFVZ0FUWUNEQ0FGSUFBMkFnZ01BUXRCSHlFRElBQkIvLy8vQjAwRVFDQUFRU1lnQUVFSWRtY2lBV3QyUVFGeElBRkJBWFJyUVQ1cUlRTUxJQVVnQXpZQ0hDQUZRZ0EzQWhBZ0EwRUNkRUc0SVdvaEFRSkFBa0JCakI4b0FnQWlBa0VCSUFOMElnUnhSUVJBUVl3ZklBSWdCSEkyQWdBZ0FTQUZOZ0lBREFFTElBQkJHU0FEUVFGMmEwRUFJQU5CSDBjYmRDRURJQUVvQWdBaEFnTkFJQUlpQVNnQ0JFRjRjU0FBUmcwQ0lBTkJIWFloQWlBRFFRRjBJUU1nQVNBQ1FRUnhhaUlFS0FJUUlnSU5BQXNnQkNBRk5nSVFDeUFGSUFFMkFoZ2dCU0FGTmdJTUlBVWdCVFlDQ0F3QkN5QUJLQUlJSWdBZ0JUWUNEQ0FCSUFVMkFnZ2dCVUVBTmdJWUlBVWdBVFlDRENBRklBQTJBZ2dMSUFkQkNHb2hBQXdDQ3dKQUlBZEZEUUFDUUNBRUtBSWNJZ0JCQW5SQnVDRnFJZ0VvQWdBZ0JFWUVRQ0FCSUFJMkFnQWdBZzBCUVl3ZklBaEJmaUFBZDNFaUNEWUNBQXdDQ3lBSFFSQkJGQ0FIS0FJUUlBUkdHMm9nQWpZQ0FDQUNSUTBCQ3lBQ0lBYzJBaGdnQkNnQ0VDSUFCRUFnQWlBQU5nSVFJQUFnQWpZQ0dBc2dCQ2dDRkNJQVJRMEFJQUlnQURZQ0ZDQUFJQUkyQWhnTEFrQWdBMEVQVFFSQUlBUWdBeUFGYWlJQVFRTnlOZ0lFSUFBZ0JHb2lBQ0FBS0FJRVFRRnlOZ0lFREFFTElBUWdCVUVEY2pZQ0JDQUVJQVZxSWdJZ0EwRUJjallDQkNBQ0lBTnFJQU0yQWdBZ0EwSC9BVTBFUUNBRFFYaHhRYkFmYWlFQUFuOUJpQjhvQWdBaUFVRUJJQU5CQTNaMElnTnhSUVJBUVlnZklBRWdBM0kyQWdBZ0FBd0JDeUFBS0FJSUN5RUJJQUFnQWpZQ0NDQUJJQUkyQWd3Z0FpQUFOZ0lNSUFJZ0FUWUNDQXdCQzBFZklRQWdBMEgvLy84SFRRUkFJQU5CSmlBRFFRaDJaeUlBYTNaQkFYRWdBRUVCZEd0QlBtb2hBQXNnQWlBQU5nSWNJQUpDQURjQ0VDQUFRUUowUWJnaGFpRUJBa0FDUUNBSVFRRWdBSFFpQm5GRkJFQkJqQjhnQmlBSWNqWUNBQ0FCSUFJMkFnQU1BUXNnQTBFWklBQkJBWFpyUVFBZ0FFRWZSeHQwSVFBZ0FTZ0NBQ0VGQTBBZ0JTSUJLQUlFUVhoeElBTkdEUUlnQUVFZGRpRUdJQUJCQVhRaEFDQUJJQVpCQkhGcUlnWW9BaEFpQlEwQUN5QUdJQUkyQWhBTElBSWdBVFlDR0NBQ0lBSTJBZ3dnQWlBQ05nSUlEQUVMSUFFb0FnZ2lBQ0FDTmdJTUlBRWdBallDQ0NBQ1FRQTJBaGdnQWlBQk5nSU1JQUlnQURZQ0NBc2dCRUVJYWlFQURBRUxBa0FnQ1VVTkFBSkFJQUlvQWh3aUFFRUNkRUc0SVdvaUFTZ0NBQ0FDUmdSQUlBRWdCRFlDQUNBRURRRkJqQjhnQzBGK0lBQjNjVFlDQUF3Q0N5QUpRUkJCRkNBSktBSVFJQUpHRzJvZ0JEWUNBQ0FFUlEwQkN5QUVJQWsyQWhnZ0FpZ0NFQ0lBQkVBZ0JDQUFOZ0lRSUFBZ0JEWUNHQXNnQWlnQ0ZDSUFSUTBBSUFRZ0FEWUNGQ0FBSUFRMkFoZ0xBa0FnQTBFUFRRUkFJQUlnQXlBRmFpSUFRUU55TmdJRUlBQWdBbW9pQUNBQUtBSUVRUUZ5TmdJRURBRUxJQUlnQlVFRGNqWUNCQ0FDSUFWcUlnUWdBMEVCY2pZQ0JDQURJQVJxSUFNMkFnQWdCd1JBSUFkQmVIRkJzQjlxSVFCQm5COG9BZ0FoQVFKL1FRRWdCMEVEZG5RaUJTQUdjVVVFUUVHSUh5QUZJQVp5TmdJQUlBQU1BUXNnQUNnQ0NBc2hCaUFBSUFFMkFnZ2dCaUFCTmdJTUlBRWdBRFlDRENBQklBWTJBZ2dMUVp3ZklBUTJBZ0JCa0I4Z0F6WUNBQXNnQWtFSWFpRUFDeUFLUVJCcUpBQWdBQXZTQ3dFSGZ3SkFJQUJGRFFBZ0FFRUlheUlDSUFCQkJHc29BZ0FpQVVGNGNTSUFhaUVGQWtBZ0FVRUJjUTBBSUFGQkEzRkZEUUVnQWlBQ0tBSUFJZ0ZySWdKQm1COG9BZ0JKRFFFZ0FDQUJhaUVBQWtBQ1FFR2NIeWdDQUNBQ1J3UkFJQUZCL3dGTkJFQWdBVUVEZGlFRUlBSW9BZ3dpQVNBQ0tBSUlJZ05HQkVCQmlCOUJpQjhvQWdCQmZpQUVkM0UyQWdBTUJRc2dBeUFCTmdJTUlBRWdBellDQ0F3RUN5QUNLQUlZSVFZZ0FpQUNLQUlNSWdGSEJFQWdBaWdDQ0NJRElBRTJBZ3dnQVNBRE5nSUlEQU1MSUFKQkZHb2lCQ2dDQUNJRFJRUkFJQUlvQWhBaUEwVU5BaUFDUVJCcUlRUUxBMEFnQkNFSElBTWlBVUVVYWlJRUtBSUFJZ01OQUNBQlFSQnFJUVFnQVNnQ0VDSUREUUFMSUFkQkFEWUNBQXdDQ3lBRktBSUVJZ0ZCQTNGQkEwY05Ba0dRSHlBQU5nSUFJQVVnQVVGK2NUWUNCQ0FDSUFCQkFYSTJBZ1FnQlNBQU5nSUFEd3RCQUNFQkN5QUdSUTBBQWtBZ0FpZ0NIQ0lEUVFKMFFiZ2hhaUlFS0FJQUlBSkdCRUFnQkNBQk5nSUFJQUVOQVVHTUgwR01IeWdDQUVGK0lBTjNjVFlDQUF3Q0N5QUdRUkJCRkNBR0tBSVFJQUpHRzJvZ0FUWUNBQ0FCUlEwQkN5QUJJQVkyQWhnZ0FpZ0NFQ0lEQkVBZ0FTQUROZ0lRSUFNZ0FUWUNHQXNnQWlnQ0ZDSURSUTBBSUFFZ0F6WUNGQ0FESUFFMkFoZ0xJQUlnQlU4TkFDQUZLQUlFSWdGQkFYRkZEUUFDUUFKQUFrQUNRQ0FCUVFKeFJRUkFRYUFmS0FJQUlBVkdCRUJCb0I4Z0FqWUNBRUdVSDBHVUh5Z0NBQ0FBYWlJQU5nSUFJQUlnQUVFQmNqWUNCQ0FDUVp3ZktBSUFSdzBHUVpBZlFRQTJBZ0JCbkI5QkFEWUNBQThMUVp3ZktBSUFJQVZHQkVCQm5COGdBallDQUVHUUgwR1FIeWdDQUNBQWFpSUFOZ0lBSUFJZ0FFRUJjallDQkNBQUlBSnFJQUEyQWdBUEN5QUJRWGh4SUFCcUlRQWdBVUgvQVUwRVFDQUJRUU4ySVFRZ0JTZ0NEQ0lCSUFVb0FnZ2lBMFlFUUVHSUgwR0lIeWdDQUVGK0lBUjNjVFlDQUF3RkN5QURJQUUyQWd3Z0FTQUROZ0lJREFRTElBVW9BaGdoQmlBRklBVW9BZ3dpQVVjRVFFR1lIeWdDQUJvZ0JTZ0NDQ0lESUFFMkFnd2dBU0FETmdJSURBTUxJQVZCRkdvaUJDZ0NBQ0lEUlFSQUlBVW9BaEFpQTBVTkFpQUZRUkJxSVFRTEEwQWdCQ0VISUFNaUFVRVVhaUlFS0FJQUlnTU5BQ0FCUVJCcUlRUWdBU2dDRUNJRERRQUxJQWRCQURZQ0FBd0NDeUFGSUFGQmZuRTJBZ1FnQWlBQVFRRnlOZ0lFSUFBZ0Ftb2dBRFlDQUF3REMwRUFJUUVMSUFaRkRRQUNRQ0FGS0FJY0lnTkJBblJCdUNGcUlnUW9BZ0FnQlVZRVFDQUVJQUUyQWdBZ0FRMEJRWXdmUVl3ZktBSUFRWDRnQTNkeE5nSUFEQUlMSUFaQkVFRVVJQVlvQWhBZ0JVWWJhaUFCTmdJQUlBRkZEUUVMSUFFZ0JqWUNHQ0FGS0FJUUlnTUVRQ0FCSUFNMkFoQWdBeUFCTmdJWUN5QUZLQUlVSWdORkRRQWdBU0FETmdJVUlBTWdBVFlDR0FzZ0FpQUFRUUZ5TmdJRUlBQWdBbW9nQURZQ0FDQUNRWndmS0FJQVJ3MEFRWkFmSUFBMkFnQVBDeUFBUWY4QlRRUkFJQUJCZUhGQnNCOXFJUUVDZjBHSUh5Z0NBQ0lEUVFFZ0FFRURkblFpQUhGRkJFQkJpQjhnQUNBRGNqWUNBQ0FCREFFTElBRW9BZ2dMSVFBZ0FTQUNOZ0lJSUFBZ0FqWUNEQ0FDSUFFMkFnd2dBaUFBTmdJSUR3dEJIeUVESUFCQi8vLy9CMDBFUUNBQVFTWWdBRUVJZG1jaUFXdDJRUUZ4SUFGQkFYUnJRVDVxSVFNTElBSWdBellDSENBQ1FnQTNBaEFnQTBFQ2RFRzRJV29oQVFKQUFrQUNRRUdNSHlnQ0FDSUVRUUVnQTNRaUIzRkZCRUJCakI4Z0JDQUhjallDQUNBQklBSTJBZ0FnQWlBQk5nSVlEQUVMSUFCQkdTQURRUUYyYTBFQUlBTkJIMGNiZENFRElBRW9BZ0FoQVFOQUlBRWlCQ2dDQkVGNGNTQUFSZzBDSUFOQkhYWWhBU0FEUVFGMElRTWdCQ0FCUVFSeGFpSUhRUkJxS0FJQUlnRU5BQXNnQnlBQ05nSVFJQUlnQkRZQ0dBc2dBaUFDTmdJTUlBSWdBallDQ0F3QkN5QUVLQUlJSWdBZ0FqWUNEQ0FFSUFJMkFnZ2dBa0VBTmdJWUlBSWdCRFlDRENBQ0lBQTJBZ2dMUWFnZlFhZ2ZLQUlBUVFGcklnQkJmeUFBR3pZQ0FBc0xCQUFqQUFzR0FDQUFKQUFMRUFBakFDQUFhMEZ3Y1NJQUpBQWdBQXRLQVFGL0lBQWdBVWtFUUNBQUlBRWdBaEFDRHdzZ0FnUkFJQUFnQW1vaEF5QUJJQUpxSVFFRFFDQURRUUZySWdNZ0FVRUJheUlCTFFBQU9nQUFJQUpCQVdzaUFnMEFDd3NnQUF2OURnSVJmd0YrSXdCQk1Hc2lCeVFBUWJoL0lRZ0NRQ0FGUlEwQUlBUXNBQUFpQ1VIL0FYRWhDd0pBSUFsQkFFZ0VRQ0FMUWY0QWEwRUJkaUlHSUFWUERRSkJiQ0VJSUF0Qi93QnJJZ3RCL3dGTERRSWdCRUVCYWlFSVFRQWhCUU5BSUFVZ0MwOEVRQ0FMSVFnZ0JpRUxEQU1GSUFBZ0JXb2dDQ0FGUVFGMmFpSUVMUUFBUVFSMk9nQUFJQUFnQlVFQmNtb2dCQzBBQUVFUGNUb0FBQ0FGUVFKcUlRVU1BUXNBQ3dBTElBVWdDMDBOQVNBSFFmOEJOZ0lFSUFZZ0IwRUVhaUFIUVFocUlBUkJBV29pRGlBTEVBd2lCRUdJZjBzRVFDQUVJUWdNQWd0QlZDRUlJQWNvQWdnaUVFRUdTdzBCSUFjb0FnUWlFVUVCZENJSlFRSnFyVUlCSUJDdGhpSVlRUUVnRUhRaURVRUJhaUlGclVJQ2hueDhRZ3Q4UXZ6Ly8vLy8vLy8vL3dDRFF1UUNWZzBCUVZJaENDQVJRZjhCU3cwQklBMUJmM05CQW5SQjVBSnFyU0FSUVFGcUloVkJBWFN0SUJoOFFnaDhWQTBCSUFzZ0JHc2hGaUFFSUE1cUlSY2dCa0dBQkdvaUVpQUZRUUowYWlJUklBbHFRUUpxSVE0Z0JrR0VCR29oRTBHQWdBSWdFSFJCRUhZaENVRUFJUVZCQVNFUElBMUJBV3NpRkNFS0EwQWdCU0FWUmtVRVFBSkFJQVlnQlVFQmRDSUlhaThCQUNJRVFmLy9BMFlFUUNBVElBcEJBblJxSUFVNkFBSWdDa0VCYXlFS1FRRWhCQXdCQ3lBUFFRQWdDU0FFd1VvYklROExJQWdnRVdvZ0JEc0JBQ0FGUVFGcUlRVU1BUXNMSUFZZ0R6c0JnZ1FnQmlBUU93R0FCQUpBSUFvZ0ZFWUVRQ0FOUVFOMklRaENBQ0VZUVFBaER3TkFJQXdnRlVZRVFDQUlJQTFCQVhacVFRTnFJZ2xCQVhRaENFRUFJUVJCQUNFS0EwQkJBQ0VGSUFvZ0RVOE5CQU5BSUFWQkFrWkZCRUFnRXlBRklBbHNJQVJxSUJSeFFRSjBhaUFPSUFVZ0NtcHFMUUFBT2dBQ0lBVkJBV29oQlF3QkN3c2dDa0VDYWlFS0lBUWdDR29nRkhFaEJBd0FDd0FGSUFZZ0RFRUJkR291QVFBaENTQU9JQTlxSWdRZ0dEY0FBRUVJSVFVRFFDQUZJQWxPUlFSQUlBUWdCV29nR0RjQUFDQUZRUWhxSVFVTUFRc0xJQmhDZ1lLRWlKQ2d3SUFCZkNFWUlBeEJBV29oRENBSklBOXFJUThNQVFzQUN3QUxJQTFCQTNZZ0RVRUJkbXBCQTJvaENFRUFJUVVEUUNBTUlCVkdSUVJBUVFBaENTQUdJQXhCQVhScUxnRUFJZ1JCQUNBRVFRQktHeUVFQTBBZ0JDQUpSa1VFUUNBVElBVkJBblJxSUF3NkFBSURRQ0FGSUFocUlCUnhJZ1VnQ2tzTkFBc2dDVUVCYWlFSkRBRUxDeUFNUVFGcUlRd01BUXNMUVg4aENDQUZEUUlMSUJCQkFXb2hDRUVBSVFVRFFDQUZJQTFHUlFSQUlCRWdFeUFGUVFKMGFpSU9MUUFDUVFGMGFpSUVJQVF2QVFBaUNVRUJhanNCQUNBT0lBZ2dDV2RCWUhOcUlnUTZBQU1nRGlBSklBUjBJQTFyT3dFQUlBVkJBV29oQlF3QkN3c0NRQUpBSUFZdkFZSUVCRUFnQjBFY2FpSUVJQmNnRmhBTklnaEJpSDlMRFFJZ0IwRVVhaUFFSUJJUURpQUhRUXhxSUFRZ0VoQU9RUUFoQlFOQUlBZEJIR29pQkJBUElBVkIrd0ZMY2cwQ0lBQWdCV29pQmlBSFFSUnFJQVFRRURvQUFDQUdJQWRCREdvZ0JCQVFPZ0FCSUFWQkFuSWhCQ0FIUVJ4cUVBOEVRQ0FFSVFVTUF3VWdBQ0FFYWlBSFFSUnFJQWRCSEdvaUJCQVFPZ0FBSUFZZ0IwRU1haUFFRUJBNkFBTWdCVUVFYWlFRkRBRUxBQXNBQ3lBSFFSeHFJZ1FnRnlBV0VBMGlDRUdJZjBzTkFTQUhRUlJxSUFRZ0VoQU9JQWRCREdvZ0JDQVNFQTVCQUNFRkEwQWdCMEVjYWlJRUVBOGdCVUg3QVV0eVJRUkFJQUFnQldvaUJpQUhRUlJxSUFRUUVUb0FBQ0FHSUFkQkRHb2dCQkFST2dBQklBVkJBbkloQkNBSFFSeHFFQThFUUNBRUlRVUZJQUFnQkdvZ0IwRVVhaUFIUVJ4cUlnUVFFVG9BQUNBR0lBZEJER29nQkJBUk9nQURJQVZCQkdvaEJRd0NDd3NMQW44RFFFRzZmeUVJSUFWQi9RRkxEUU1nQUNBRmFpSUdJQWRCRkdvZ0IwRWNhaUlKRUJFNkFBQWdCa0VCYWlFRUlBa1FEMEVEUmdSQUlBZEJER29oQ0VFQ0RBSUxJQVZCL0FGTERRTWdCaUFIUVF4cUlBZEJIR29pQkJBUk9nQUJJQVZCQW1vaEJTQUVFQTlCQTBjTkFBc2dBQ0FGYWlFRUlBZEJGR29oQ0VFREN5QUVJQWdnQjBFY2FoQVJPZ0FBSUFacUlBQnJJUWdNQVFzQ2Z3TkFRYnAvSVFnZ0JVSDlBVXNOQWlBQUlBVnFJZ1lnQjBFVWFpQUhRUnhxSWdrUUVEb0FBQ0FHUVFGcUlRUWdDUkFQUVFOR0JFQWdCMEVNYWlFSVFRSU1BZ3NnQlVIOEFVc05BaUFHSUFkQkRHb2dCMEVjYWlJRUVCQTZBQUVnQlVFQ2FpRUZJQVFRRDBFRFJ3MEFDeUFBSUFWcUlRUWdCMEVVYWlFSVFRTUxJQVFnQ0NBSFFSeHFFQkE2QUFBZ0Jtb2dBR3NoQ0FzZ0NFR0lmMHNOQVFzZ0NDRUVRUUFoQlNBQlFRQkJOQkFESVFsQkFDRUtBMEFnQkNBRlJ3UkFJQUFnQldvaUJpMEFBQ0lCUVF0TEJFQkJiQ0VJREFNRklBa2dBVUVDZEdvaUFTQUJLQUlBUVFGcU5nSUFJQVZCQVdvaEJVRUJJQVl0QUFCMFFRRjFJQXBxSVFvTUFnc0FDd3RCYkNFSUlBcEZEUUFnQ21jaUJVRWZjeUlCUVF0TERRQWdBMEVnSUFWck5nSUFRUUZCQWlBQmRDQUtheUlEWjBFZmN5SUJkQ0FEUncwQUlBQWdCR29nQVVFQmFpSUFPZ0FBSUFrZ0FFRUNkR29pQUNBQUtBSUFRUUZxTmdJQUlBa29BZ1FpQUVFQ1NTQUFRUUZ4Y2cwQUlBSWdCRUVCYWpZQ0FDQUxRUUZxSVFnTElBZEJNR29rQUNBSUM2QUZBUXgvSXdCQkVHc2lEQ1FBQW44Z0JFRUhUUVJBSUF4Q0FEY0RDQ0FNUVFocUlnVWdBeUFFRUFJYVFXd2dBQ0FCSUFJZ0JVRUlFQXdpQUNBQUlBUkxHeUFBSUFCQmlYOUpHd3dCQ3lBQVFRQWdBU2dDQUVFQmFpSU5RUUYwRUFNaEQwRlVJQU1vQUFBaUJrRVBjU0lBUVFwTERRQWFJQUlnQUVFRmFqWUNBQ0FESUFScUlnSkJCR3NoQnlBQ1FRZHJJUXNnQUVFR2FpRU9RUVFoQWlBR1FRUjJJUVZCSUNBQWRDSUlRUUZ5SVFsQkFDRUFRUUVoQmlBRElRUURRQUpBSUFaQkFYRkZCRUFEUUNBRlFYOXpRWUNBZ0lCNGNtZ2lCa0VZU1VVRVFDQUFRU1JxSVFBZ0JDQUxUUVIvSUFSQkEyb0ZJQVFnQzJ0QkEzUWdBbXBCSDNFaEFpQUhDeUlFS0FBQUlBSjJJUVVNQVFzTElBSWdCa0VlY1NJS2FrRUNhaUVDSUFaQkFYWkJBMndnQUdvZ0JTQUtka0VEY1dvaUFDQU5UdzBCQW44Z0JDQUxTeUFDUVFOMklBUnFJZ1VnQjB0eFJRUkFJQUpCQjNFaEFpQUZEQUVMSUFRZ0IydEJBM1FnQW1wQkgzRWhBaUFIQ3lJRUtBQUFJQUoySVFVTElBVWdDRUVCYTNFaUJpQUlRUUYwUVFGcklnb2dDV3NpRUVrRWZ5QU9RUUZyQlNBRklBcHhJZ1VnRUVFQUlBVWdDRTRiYXlFR0lBNExJUVVnRHlBQVFRRjBhaUFHUVFGcklnbzdBUUFnQUVFQmFpRUFJQUlnQldvaEFpQUlRUUVnQm1zZ0NpQUdRUUJLR3lBSmFpSUpTZ1JBSUFsQkFrZ05BVUVnSUFsbklnVnJJUTVCQVNBRlFSOXpkQ0VJQ3lBQUlBMVBEUUFnQ2tFQVJ5RUdBbjhnQkNBTFN5QUNRUU4xSUFScUlnVWdCMHR4UlFSQUlBSkJCM0VoQWlBRkRBRUxJQUlnQkNBSGEwRURkR3BCSDNFaEFpQUhDeUlFS0FBQUlBSjJJUVVNQVFzTFFXd2dDVUVCUncwQUdrRlFJQUFnRFVzTkFCcEJiQ0FDUVNCS0RRQWFJQUVnQUVFQmF6WUNBQ0FFSUFKQkIycEJBM1ZxSUFOckN5QU1RUkJxSkFBTDhnRUJBWDhnQWtVRVFDQUFRZ0EzQWdBZ0FFRUFOZ0lRSUFCQ0FEY0NDRUc0Znc4TElBQWdBVFlDRENBQUlBRkJCR28yQWhBZ0FrRUVUd1JBSUFBZ0FTQUNhaUlCUVFScklnTTJBZ2dnQUNBREtBQUFOZ0lBSUFGQkFXc3RBQUFpQVFSQUlBQWdBV2RCRjJzMkFnUWdBZzhMSUFCQkFEWUNCRUYvRHdzZ0FDQUJOZ0lJSUFBZ0FTMEFBQ0lETmdJQUFrQUNRQUpBSUFKQkFtc09BZ0VBQWdzZ0FDQUJMUUFDUVJCMElBTnlJZ00yQWdBTElBQWdBUzBBQVVFSWRDQURhallDQUFzZ0FTQUNha0VCYXkwQUFDSUJSUVJBSUFCQkFEWUNCRUZzRHdzZ0FDQUJaeUFDUVFOMGEwRUphallDQkNBQ0MwUUJBbjhnQVNBQ0x3RUFJZ01nQVNnQ0JHb2lCRFlDQkNBQUlBTkJBblJCb0IxcUtBSUFJQUVvQWdCQkFDQUVhM1p4TmdJQUlBRVFEeG9nQUNBQ1FRUnFOZ0lFQzU4QkFRUi9RUU1oQVNBQUtBSUVJZ0pCSUUwRVFDQUFLQUlJSWdFZ0FDZ0NFRThFUUNBQUlBSkJCM0UyQWdRZ0FDQUJJQUpCQTNacklnSTJBZ2dnQUNBQ0tBQUFOZ0lBUVFBUEN5QUFLQUlNSWdNZ0FVWUVRRUVCUVFJZ0FrRWdTUnNQQ3lBQUlBRWdBU0FEYXlBQ1FRTjJJZ1FnQVNBRWF5QURTU0lCR3lJRGF5SUVOZ0lJSUFBZ0FpQURRUU4wYXpZQ0JDQUFJQVFvQUFBMkFnQUxJQUVMU0FFRWZ5QUFLQUlFSUFBb0FnQkJBblJxSWdJdEFBSWdBaThCQUNFRUlBRWdBU2dDQkNJRklBSXRBQU1pQW1vMkFnUWdBQ0FFSUFFb0FnQWdCWFJCQUNBQ2EzWnFOZ0lBQzFJQkJIOGdBQ2dDQkNBQUtBSUFRUUowYWlJQ0xRQUNJQUl2QVFBaEJDQUJJQUl0QUFNaUFpQUJLQUlFYWlJRk5nSUVJQUFnQkNBQ1FRSjBRYUFkYWlnQ0FDQUJLQUlBUVFBZ0JXdDJjV28yQWdBTENBQWdBRUdJZjBzTEdnQWdBQVJBSUFFRVFDQUNJQUFnQVJFQ0FBOExJQUFRQmdzTHBnZ0NEWDhCZmlNQVFSQnJJZ2trQUNBSlFRQTJBZ3dnQ1VFQU5nSUlBbjhDUUNBRFFlZ0phaUFESUFsQkNHb2dDVUVNYWlBQklBSWdBMEdBQVdvUUN5SVBRWWgvU3cwQVFWUWdDU2dDRENJRUlBQW9BZ0FpQVVIL0FYRkJBV3BMRFFFYUlBQkJCR29oQ3lBQUlBRkIvNEdBZUhFZ0JFRVFkRUdBZ1B3SGNYSTJBZ0JCZnlBRUlBUkJBRWdiUVFGcUlRQkJBQ0VCSUFrb0FnZ2hCVUVBSVFJRFFDQUFJQUpHQkVBZ0JVRURheUVCUVFBaEFBTkFBa0JCQUNFQ0lBQWdBVTRFUUFOQUlBQWdCVTROQWlBRElBQWdBMnBCNkFscUxRQUFRUUowYWtGQWF5SUJJQUVvQWdBaUFVRUJhallDQUNBQklBTnFJQUE2QU9nSElBQkJBV29oQUF3QUN3QUZBMEFnQWtFRVJrVUVRQ0FESUFNZ0FDQUNhaUlIYWtIb0NXb3RBQUJCQW5ScVFVQnJJZ2dnQ0NnQ0FDSUlRUUZxTmdJQUlBTWdDR29nQnpvQTZBY2dBa0VCYWlFQ0RBRUxDeUFBUVFScUlRQU1BZ3NBQ3dzZ0JFRUJhaUVPSUFNb0FnQWhCMEVBSVFCQkFTRUlBMEFnQ0NBT1JnMERJQTRnQ0dzaEJDQURJQWhCQW5ScUtBSUFJUVVDUUFKQUFrQUNRQUpBQWtCQkFTQUlkRUVCZFNJTlFRRnJEZ2dBQVFRQ0JBUUVBd1FMUVFBaEFpQUZRUUFnQlVFQVNoc2hCaUFBSVFFRFFDQUNJQVpHRFFVZ0F5QUNJQWRxYWkwQTZBY2hDaUFMSUFGQkFYUnFJZ3dnQkRvQUFTQU1JQW82QUFBZ0FrRUJhaUVDSUFGQkFXb2hBUXdBQ3dBTFFRQWhBaUFGUVFBZ0JVRUFTaHNoQ2lBQUlRRURRQ0FDSUFwR0RRUWdDeUFCUVFGMGFpSUdJQU1nQWlBSGFtb3RBT2dISWd3NkFBSWdCaUFFT2dBQklBWWdERG9BQUNBR0lBUTZBQU1nQWtFQmFpRUNJQUZCQW1vaEFRd0FDd0FMUVFBaEFpQUZRUUFnQlVFQVNoc2hCaUFFUVFoMFFZRCtBM0VoQkNBQUlRRURRQ0FDSUFaR0RRTWdDeUFCUVFGMGFpQUVJQU1nQWlBSGFtb3RBT2dIY3ExQ2dZQ0VnSkNBd0FCK053QUFJQUpCQVdvaEFpQUJRUVJxSVFFTUFBc0FDMEVBSVFJZ0JVRUFJQVZCQUVvYklRWWdCRUVJZEVHQS9nTnhJUVFnQUNFQkEwQWdBaUFHUmcwQ0lBc2dBVUVCZEdvaUNpQUVJQU1nQWlBSGFtb3RBT2dIY3ExQ2dZQ0VnSkNBd0FCK0loRTNBQWdnQ2lBUk53QUFJQUpCQVdvaEFpQUJRUWhxSVFFTUFBc0FDMEVBSVFFZ0JVRUFJQVZCQUVvYklRb2dCRUVJZEVHQS9nTnhJUXdnQUNFRUEwQWdBU0FLUmcwQklBc2dCRUVCZEdvaEVDQU1JQU1nQVNBSGFtb3RBT2dIY3ExQ2dZQ0VnSkNBd0FCK0lSRkJBQ0VDQTBBZ0FpQU5Ua1VFUUNBUUlBSkJBWFJxSWdZZ0VUY0FHQ0FHSUJFM0FCQWdCaUFSTndBSUlBWWdFVGNBQUNBQ1FSQnFJUUlNQVFzTElBRkJBV29oQVNBRUlBMXFJUVFNQUFzQUN5QUlRUUZxSVFnZ0JTQUhhaUVISUFVZ0RXd2dBR29oQUF3QUN3QUZJQU1nQWtFQ2RHb2lCMEZBYXlBQk5nSUFJQUpCQVdvaEFpQUhLQUlBSUFGcUlRRU1BUXNBQ3dBTElBOExJQWxCRUdva0FBdnlBZ0VHZnlNQVFTQnJJZ1VrQUNBRUtBSUFJUVlnQlVFTWFpQUNJQU1RRFNJRFFZaC9UUVJBSUFSQkJHb2hBaUFBSUFGcUlnbEJBMnNoQkVFQUlBWkJFSFpyUVI5eElRTURRQ0FGUVF4cUVBOGdBQ0FFVDNKRkJFQWdBaUFGS0FJTUlnWWdCU2dDRUNJSGRDQURka0VCZEdvaUNDMEFBU0VLSUFBZ0NDMEFBRG9BQUNBQ0lBWWdCeUFLYWlJR2RDQURka0VCZEdvaUJ5MEFBQ0VJSUFVZ0JpQUhMUUFCYWpZQ0VDQUFJQWc2QUFFZ0FFRUNhaUVBREFFTEN3TkFJQVZCREdvUUR5RUhJQVVvQWd3aEJpQUZLQUlRSVFRZ0FDQUpUeUFIY2tVRVFDQUNJQVlnQkhRZ0EzWkJBWFJxSWdZdEFBQWhCeUFGSUFRZ0JpMEFBV28yQWhBZ0FDQUhPZ0FBSUFCQkFXb2hBQXdCQ3dzRFFDQUFJQWxQUlFSQUlBSWdCaUFFZENBRGRrRUJkR29pQnkwQUFTRUlJQUFnQnkwQUFEb0FBQ0FBUVFGcUlRQWdCQ0FJYWlFRURBRUxDMEZzUVd3Z0FTQUZLQUlVSUFVb0FoaEhHeUFFUVNCSEd5RURDeUFGUVNCcUpBQWdBd3ZQRkFFamZ5TUFRZEFBYXlJRkpBQkJiQ0VKQWtBZ0EwRUtTUTBBQWtBZ0F5QUNMd0FFSWdjZ0FpOEFBQ0lJSUFJdkFBSWlEV3BxUVFacUlneEpEUUFnQkM4QkFpRUdJQVZCUEdvZ0FrRUdhaUlDSUFnUURTSUpRWWgvU3cwQklBVkJLR29nQWlBSWFpSUNJQTBRRFNJSlFZaC9TdzBCSUFWQkZHb2dBaUFOYWlJQ0lBY1FEU0lKUVloL1N3MEJJQVVnQWlBSGFpQURJQXhyRUEwaUNVR0lmMHNOQVNBRVFRUnFJUW9nQUNBQmFpSWZRUU5ySVNCQkFDQUdhMEVmY1NFTElBVW9BZ2doRVNBRktBSWNJUklnQlNnQ01DRVRJQVVvQWtRaEZDQUZLQUlFSVFrZ0JTZ0NHQ0VOSUFVb0Fpd2hEQ0FGS0FKQUlRWWdCU2dDRUNFaElBVW9BaVFoSWlBRktBSTRJU01nQlNnQ1RDRWtJQVVvQWdBaEZTQUZLQUlVSVJZZ0JTZ0NLQ0VYSUFVb0Fqd2hHRUVCSVE4Z0FDQUJRUU5xUVFKMklnUnFJZ01nQkdvaUFpQUVhaUlaSVFRZ0FpRUlJQU1oQndOQUlBOUJBWEZGSUFRZ0lFOXlSUVJBSUFBZ0NpQVlJQVowSUF0MlFRSjBhaUlPTHdFQU93QUFJQTR0QUFJaEdpQU9MUUFESVJBZ0J5QUtJQmNnREhRZ0MzWkJBblJxSWc0dkFRQTdBQUFnRGkwQUFpRWJJQTR0QUFNaER5QUlJQW9nRmlBTmRDQUxka0VDZEdvaURpOEJBRHNBQUNBT0xRQUNJUndnRGkwQUF5RWRJQVFnQ2lBVklBbDBJQXQyUVFKMGFpSU9Md0VBT3dBQUlBNHRBQUloSGlBT0xRQURJUTRnQUNBUWFpSWxJQW9nR0NBR0lCcHFJZ1owSUF0MlFRSjBhaUlRTHdFQU93QUFJQkF0QUFJZ0VDMEFBeUVtSUFjZ0Qyb2lKeUFLSUJjZ0RDQWJhaUlhZENBTGRrRUNkR29pQnk4QkFEc0FBQ0FITFFBQ0lRd2dCeTBBQXlFUUlBZ2dIV29pR3lBS0lCWWdEU0FjYWlJUGRDQUxka0VDZEdvaUNDOEJBRHNBQUNBSUxRQUNJUTBnQ0MwQUF5RWNJQVFnRG1vaUhTQUtJQlVnQ1NBZWFpSU9kQ0FMZGtFQ2RHb2lDUzhCQURzQUFDQUdhaUVBUVFNaEJ3Si9JQlFnSkVrRVFDQUFJUVpCQXd3QkN5QUFRUWR4SVFZZ0ZDQUFRUU4yYXlJVUtBQUFJUmhCQUFzZ0NTMEFBeUVlSUFrdEFBSWhDQ0FNSUJwcUlRQWdFeUFqU1FSL0lBQUZJQk1nQUVFRGRtc2lFeWdBQUNFWFFRQWhCeUFBUVFkeEN5RU1JQTBnRDJvaEFDQUhjaUVKUVFNaER3Si9JQklnSWtrRVFDQUFJUTFCQXd3QkN5QUFRUWR4SVEwZ0VpQUFRUU4yYXlJU0tBQUFJUlpCQUFzZ0NDQU9haUVBSUFseUlCRWdJVWtFZnlBQUJTQVJJQUJCQTNackloRW9BQUFoRlVFQUlROGdBRUVIY1FzaENTQWxJQ1pxSVFBZ0VDQW5haUVISUJzZ0hHb2hDQ0FkSUI1cUlRUWdEM0pGSVE4TUFRc0xJQVVnRERZQ0xDQUZJQVkyQWtBZ0JTQU5OZ0lZSUFVZ0NUWUNCQ0FGSUJRMkFrUWdCU0FUTmdJd0lBVWdFallDSENBRklCRTJBZ2dnQlNBWU5nSThJQVVnRnpZQ0tDQUZJQlkyQWhRZ0JTQVZOZ0lBSUFJZ0Iwa2dBQ0FEUzNJTkFFRnNJUWtnQ0NBWlN3MEJJQU5CQTJzaENRTkFJQVZCUEdvUUQwVWdBQ0FKU1hFRVFDQUFJQW9nQlNnQ1BDSU5JQVVvQWtBaURIUWdDM1pCQW5ScUlnNHZBUUE3QUFBZ0FDQU9MUUFEYWlJR0lBb2dEU0FNSUE0dEFBSnFJZ0IwSUF0MlFRSjBhaUlNTHdFQU93QUFJQVVnQUNBTUxRQUNhallDUUNBR0lBd3RBQU5xSVFBTUFRVWdBMEVDYXlFTUEwQWdCVUU4YWhBUElRWWdCU2dDUENFTklBVW9Ba0FoQ1NBQUlBeExJQVp5UlFSQUlBQWdDaUFOSUFsMElBdDJRUUowYWlJR0x3RUFPd0FBSUFVZ0NTQUdMUUFDYWpZQ1FDQUFJQVl0QUFOcUlRQU1BUXNMQTBBZ0FDQU1TMFVFUUNBQUlBb2dEU0FKZENBTGRrRUNkR29pQmk4QkFEc0FBQ0FBSUFZdEFBTnFJUUFnQ1NBR0xRQUNhaUVKREFFTEN3SkFJQUFnQTA4TkFDQUFJQW9nRFNBSmRDQUxkaUlBUVFKMGFpSURMUUFBT2dBQUlBTXRBQU5CQVVZRVFDQUpJQU10QUFKcUlRa01BUXNnQ1VFZlN3MEFRU0FnQ1NBS0lBQkJBblJxTFFBQ2FpSUFJQUJCSUU4YklRa0xJQUpCQTJzaERBTkFJQVZCS0dvUUQwVWdCeUFNU1hFRVFDQUhJQW9nQlNnQ0tDSUdJQVVvQWl3aUFIUWdDM1pCQW5ScUlnMHZBUUE3QUFBZ0J5QU5MUUFEYWlJRElBb2dCaUFBSUEwdEFBSnFJZ0IwSUF0MlFRSjBhaUlHTHdFQU93QUFJQVVnQUNBR0xRQUNhallDTENBRElBWXRBQU5xSVFjTUFRVWdBa0VDYXlFR0EwQWdCVUVvYWhBUElRTWdCU2dDS0NFTUlBVW9BaXdoQUNBR0lBZEpJQU55UlFSQUlBY2dDaUFNSUFCMElBdDJRUUowYWlJREx3RUFPd0FBSUFVZ0FDQURMUUFDYWpZQ0xDQUhJQU10QUFOcUlRY01BUXNMQTBBZ0JpQUhTVVVFUUNBSElBb2dEQ0FBZENBTGRrRUNkR29pQXk4QkFEc0FBQ0FISUFNdEFBTnFJUWNnQUNBRExRQUNhaUVBREFFTEN3SkFJQUlnQjAwTkFDQUhJQW9nRENBQWRDQUxkaUlDUVFKMGFpSURMUUFBT2dBQUlBTXRBQU5CQVVZRVFDQUFJQU10QUFKcUlRQU1BUXNnQUVFZlN3MEFRU0FnQUNBS0lBSkJBblJxTFFBQ2FpSUFJQUJCSUU4YklRQUxJQmxCQTJzaERBTkFJQVZCRkdvUUQwVWdDQ0FNU1hFRVFDQUlJQW9nQlNnQ0ZDSUdJQVVvQWhnaUFuUWdDM1pCQW5ScUlnMHZBUUE3QUFBZ0NDQU5MUUFEYWlJRElBb2dCaUFDSUEwdEFBSnFJZ0owSUF0MlFRSjBhaUlHTHdFQU93QUFJQVVnQWlBR0xRQUNhallDR0NBRElBWXRBQU5xSVFnTUFRVWdHVUVDYXlFREEwQWdCVUVVYWhBUElRSWdCU2dDRkNFR0lBVW9BaGdoQnlBRElBaEpJQUp5UlFSQUlBZ2dDaUFHSUFkMElBdDJRUUowYWlJQ0x3RUFPd0FBSUFVZ0J5QUNMUUFDYWpZQ0dDQUlJQUl0QUFOcUlRZ01BUXNMQTBBZ0F5QUlTVVVFUUNBSUlBb2dCaUFIZENBTGRrRUNkR29pQWk4QkFEc0FBQ0FJSUFJdEFBTnFJUWdnQnlBQ0xRQUNhaUVIREFFTEN3SkFJQWdnR1U4TkFDQUlJQW9nQmlBSGRDQUxkaUlDUVFKMGFpSURMUUFBT2dBQUlBTXRBQU5CQVVZRVFDQUhJQU10QUFKcUlRY01BUXNnQjBFZlN3MEFRU0FnQnlBS0lBSkJBblJxTFFBQ2FpSUNJQUpCSUU4YklRY0xBMEFnQlJBUFJTQUVJQ0JKY1FSQUlBUWdDaUFGS0FJQUlnWWdCU2dDQkNJQ2RDQUxka0VDZEdvaURDOEJBRHNBQUNBRUlBd3RBQU5xSWdNZ0NpQUdJQUlnREMwQUFtb2lBblFnQzNaQkFuUnFJZ1F2QVFBN0FBQWdCU0FDSUFRdEFBSnFOZ0lFSUFNZ0JDMEFBMm9oQkF3QkJTQWZRUUpySVFNRFFDQUZFQThoQWlBRktBSUFJUVlnQlNnQ0JDRUlJQU1nQkVrZ0FuSkZCRUFnQkNBS0lBWWdDSFFnQzNaQkFuUnFJZ0l2QVFBN0FBQWdCU0FJSUFJdEFBSnFOZ0lFSUFRZ0FpMEFBMm9oQkF3QkN3c0RRQ0FESUFSSlJRUkFJQVFnQ2lBR0lBaDBJQXQyUVFKMGFpSUNMd0VBT3dBQUlBUWdBaTBBQTJvaEJDQUlJQUl0QUFKcUlRZ01BUXNMQWtBZ0JDQWZUdzBBSUFRZ0NpQUdJQWgwSUF0MklnSkJBblJxSWdNdEFBQTZBQUFnQXkwQUEwRUJSZ1JBSUFnZ0F5MEFBbW9oQ0F3QkN5QUlRUjlMRFFCQklDQUlJQW9nQWtFQ2RHb3RBQUpxSWdJZ0FrRWdUeHNoQ0F0QmJFRnNRV3hCYkVGc1FXeEJiRUZzSUFFZ0NFRWdSeHNnQlNnQ0NDQUZLQUlNUnhzZ0IwRWdSeHNnQlNnQ0hDQUZLQUlnUnhzZ0FFRWdSeHNnQlNnQ01DQUZLQUkwUnhzZ0NVRWdSeHNnQlNnQ1JDQUZLQUpJUnhzaENRd0pDd0FMQUFzQUN3QUxBQXNBQ3dBTEFBdEJiQ0VKQ3lBRlFkQUFhaVFBSUFrTDdCQUJIbjhqQUVIUUFHc2lCU1FBUVd3aENRSkFJQU5CQ2trTkFBSkFJQU1nQWk4QUJDSUdJQUl2QUFBaUJ5QUNMd0FDSWdocWFrRUdhaUlPU1EwQUlBUXZBUUloRHlBRlFUeHFJQUpCQm1vaUFpQUhFQTBpQ1VHSWYwc05BU0FGUVNocUlBSWdCMm9pQWlBSUVBMGlDVUdJZjBzTkFTQUZRUlJxSUFJZ0NHb2lBaUFHRUEwaUNVR0lmMHNOQVNBRklBSWdCbW9nQXlBT2F4QU5JZ2xCaUg5TERRRWdCRUVFYWlFS0lBQWdBV29pSEVFRGF5RWRRUUFnRDJ0QkgzRWhDeUFGS0FJSUlSRWdCU2dDSENFU0lBVW9BakFoRXlBRktBSkVJUlFnQlNnQ0JDRUpJQVVvQWhnaEJpQUZLQUlzSVFjZ0JTZ0NRQ0VJSUFVb0FoQWhIaUFGS0FJa0lSOGdCU2dDT0NFZ0lBVW9Ba3doSVNBRktBSUFJUlVnQlNnQ0ZDRVdJQVVvQWlnaEZ5QUZLQUk4SVJoQkFTRU5JQUFnQVVFRGFrRUNkaUlDYWlJT0lBSnFJZzhnQW1vaUdTRUVJQThoQWlBT0lRTURRQ0FOUlNBRUlCMVBja1VFUUNBS0lCZ2dDSFFnQzNaQkFYUnFJZ3d0QUFFaERTQUFJQXd0QUFBNkFBQWdDaUFYSUFkMElBdDJRUUYwYWlJTUxRQUJJUkFnQXlBTUxRQUFPZ0FBSUFvZ0ZpQUdkQ0FMZGtFQmRHb2lEQzBBQVNFYUlBSWdEQzBBQURvQUFDQUtJQlVnQ1hRZ0MzWkJBWFJxSWd3dEFBRWhHeUFFSUF3dEFBQTZBQUFnQ2lBWUlBZ2dEV29pQ0hRZ0MzWkJBWFJxSWd3dEFBRWhEU0FBSUF3dEFBQTZBQUVnQ2lBWElBY2dFR29pQjNRZ0MzWkJBWFJxSWd3dEFBRWhFQ0FESUF3dEFBQTZBQUVnQ2lBV0lBWWdHbW9pREhRZ0MzWkJBWFJxSWdZdEFBRWhHaUFDSUFZdEFBQTZBQUVnQ2lBVklBa2dHMm9pRzNRZ0MzWkJBWFJxSWdrdEFBRWhJaUFFSUFrdEFBQTZBQUVnQ0NBTmFpRUdRUU1oQ1FKL0lCUWdJVWtFUUVFRElRMGdCZ3dCQ3lBVUlBWkJBM1pySWhRb0FBQWhHRUVBSVEwZ0JrRUhjUXNoQ0NBSElCQnFJUVlnRXlBZ1NRUi9JQVlGSUJNZ0JrRURkbXNpRXlnQUFDRVhRUUFoQ1NBR1FRZHhDeUVISUF3Z0dtb2hEQ0FKSUExeUlSQkJBeUVOQW44Z0VpQWZTUVJBSUF3aEJrRUREQUVMSUF4QkIzRWhCaUFTSUF4QkEzWnJJaElvQUFBaEZrRUFDeUFiSUNKcUlRd2dFSEloRUNBUklCNUpCSDhnREFVZ0VTQU1RUU4yYXlJUktBQUFJUlZCQUNFTklBeEJCM0VMSVFrZ0JFRUNhaUVFSUFKQkFtb2hBaUFEUVFKcUlRTWdBRUVDYWlFQUlBMGdFSEpGSVEwTUFRc0xJQVVnQnpZQ0xDQUZJQWcyQWtBZ0JTQUdOZ0lZSUFVZ0NUWUNCQ0FGSUJRMkFrUWdCU0FUTmdJd0lBVWdFallDSENBRklCRTJBZ2dnQlNBWU5nSThJQVVnRnpZQ0tDQUZJQlkyQWhRZ0JTQVZOZ0lBSUFBZ0Rrc2dBeUFQUzNJTkFFRnNJUWtnQWlBWlN3MEJJQTVCQTJzaENRTkFJQVZCUEdvUUR5QUFJQWxQY2tVRVFDQUtJQVVvQWp3aUJpQUZLQUpBSWdkMElBdDJRUUYwYWlJSUxRQUJJUXdnQUNBSUxRQUFPZ0FBSUFvZ0JpQUhJQXhxSWdaMElBdDJRUUYwYWlJSExRQUFJUWdnQlNBR0lBY3RBQUZxTmdKQUlBQWdDRG9BQVNBQVFRSnFJUUFNQVFzTEEwQWdCVUU4YWhBUElRY2dCU2dDUENFR0lBVW9Ba0FoQ1NBQUlBNVBJQWR5UlFSQUlBb2dCaUFKZENBTGRrRUJkR29pQmkwQUFDRUhJQVVnQ1NBR0xRQUJhallDUUNBQUlBYzZBQUFnQUVFQmFpRUFEQUVMQ3dOQUlBQWdEazlGQkVBZ0NpQUdJQWwwSUF0MlFRRjBhaUlITFFBQklBQWdCeTBBQURvQUFDQUFRUUZxSVFBZ0NXb2hDUXdCQ3dzZ0QwRURheUVBQTBBZ0JVRW9haEFQSUFBZ0EwMXlSUVJBSUFvZ0JTZ0NLQ0lHSUFVb0Fpd2lCM1FnQzNaQkFYUnFJZ2d0QUFFaERpQURJQWd0QUFBNkFBQWdDaUFHSUFjZ0Rtb2lCblFnQzNaQkFYUnFJZ2N0QUFBaENDQUZJQVlnQnkwQUFXbzJBaXdnQXlBSU9nQUJJQU5CQW1vaEF3d0JDd3NEUUNBRlFTaHFFQThoQnlBRktBSW9JUVlnQlNnQ0xDRUFJQU1nRDA4Z0IzSkZCRUFnQ2lBR0lBQjBJQXQyUVFGMGFpSUdMUUFBSVFjZ0JTQUFJQVl0QUFGcU5nSXNJQU1nQnpvQUFDQURRUUZxSVFNTUFRc0xBMEFnQXlBUFQwVUVRQ0FLSUFZZ0FIUWdDM1pCQVhScUlnY3RBQUVoQ0NBRElBY3RBQUE2QUFBZ0EwRUJhaUVESUFBZ0NHb2hBQXdCQ3dzZ0dVRURheUVEQTBBZ0JVRVVhaEFQSUFJZ0EwOXlSUVJBSUFvZ0JTZ0NGQ0lHSUFVb0FoZ2lCM1FnQzNaQkFYUnFJZ2d0QUFFaERpQUNJQWd0QUFBNkFBQWdDaUFHSUFjZ0Rtb2lCblFnQzNaQkFYUnFJZ2N0QUFBaENDQUZJQVlnQnkwQUFXbzJBaGdnQWlBSU9nQUJJQUpCQW1vaEFnd0JDd3NEUUNBRlFSUnFFQThoQnlBRktBSVVJUVlnQlNnQ0dDRURJQUlnR1U4Z0IzSkZCRUFnQ2lBR0lBTjBJQXQyUVFGMGFpSUdMUUFBSVFjZ0JTQURJQVl0QUFGcU5nSVlJQUlnQnpvQUFDQUNRUUZxSVFJTUFRc0xBMEFnQWlBWlQwVUVRQ0FLSUFZZ0EzUWdDM1pCQVhScUlnY3RBQUVoQ0NBQ0lBY3RBQUE2QUFBZ0FrRUJhaUVDSUFNZ0NHb2hBd3dCQ3dzRFFDQUZFQThnQkNBZFQzSkZCRUFnQ2lBRktBSUFJZ0lnQlNnQ0JDSUdkQ0FMZGtFQmRHb2lCeTBBQVNFSUlBUWdCeTBBQURvQUFDQUtJQUlnQmlBSWFpSUNkQ0FMZGtFQmRHb2lCaTBBQUNFSElBVWdBaUFHTFFBQmFqWUNCQ0FFSUFjNkFBRWdCRUVDYWlFRURBRUxDd05BSUFVUUR5RUhJQVVvQWdBaEJpQUZLQUlFSVFJZ0JDQWNUeUFIY2tVRVFDQUtJQVlnQW5RZ0MzWkJBWFJxSWdZdEFBQWhCeUFGSUFJZ0JpMEFBV28yQWdRZ0JDQUhPZ0FBSUFSQkFXb2hCQXdCQ3dzRFFDQUVJQnhQUlFSQUlBb2dCaUFDZENBTGRrRUJkR29pQnkwQUFTRUlJQVFnQnkwQUFEb0FBQ0FFUVFGcUlRUWdBaUFJYWlFQ0RBRUxDMEZzUVd4QmJFRnNRV3hCYkVGc1FXd2dBU0FDUVNCSEd5QUZLQUlJSUFVb0FneEhHeUFEUVNCSEd5QUZLQUljSUFVb0FpQkhHeUFBUVNCSEd5QUZLQUl3SUFVb0FqUkhHeUFKUVNCSEd5QUZLQUpFSUFVb0FraEhHeUVKREFFTFFXd2hDUXNnQlVIUUFHb2tBQ0FKQzFnQkEzOENRQ0FBS0FLUTZ3RWlBVVVOQUNBQktBSUFJQUZCdE5VQmFpZ0NBQ0lDSUFGQnVOVUJhaWdDQUNJREVCTWdBZ1JBSUFNZ0FTQUNFUUlBREFFTElBRVFCZ3NnQUVFQU5nS2c2d0VnQUVJQU53T1E2d0VMNlFNQ0JIOENmaUFBUVFCQktCQURJUVFnQWtFQlFRVWdBeHNpQUVrRVFDQUFEd3NnQVVVRVFFRi9Ed3RCQVNFR0FrQUNRQ0FEUVFGR0RRQWdBeUVHSUFFb0FBQWlCVUdvNnI1cFJnMEFRWFloQXlBRlFYQnhRZERVdE1JQlJ3MEJRUWdoQXlBQ1FRaEpEUUVnQVRVQUJDRUlJQVJCQVRZQ0ZDQUVJQWczQXdCQkFBOExJQUVnQWlBR0VCb2lBeUFDU3cwQUlBUWdBellDR0VGeUlRTWdBQ0FCYWlJRlFRRnJMUUFBSWdKQkNIRU5BQ0FDUVNCeElnWkZCRUJCY0NFRElBVXRBQUFpQlVHbkFVc05BU0FGUVFkeHJVSUJJQVZCQTNaQkNtcXRoaUlJUWdPSWZpQUlmQ0VKSUFCQkFXb2hBQXNnQWtFR2RpRUZJQUpCQW5aQkFDRURBa0FDUUFKQUFrQWdBa0VEY1VFQmF3NERBQUVDQXdzZ0FDQUJhaTBBQUNFRElBQkJBV29oQUF3Q0N5QUFJQUZxTHdBQUlRTWdBRUVDYWlFQURBRUxJQUFnQVdvb0FBQWhBeUFBUVFScUlRQUxRUUZ4SVFJQ2ZnSkFBa0FDUUFKQUlBVkJBV3NPQXdFQ0F3QUxRbjhnQmtVTkF4b2dBQ0FCYWpFQUFBd0RDeUFBSUFGcU13QUFRb0FDZkF3Q0N5QUFJQUZxTlFBQURBRUxJQUFnQVdvcEFBQUxJUWdnQkNBQ05nSWdJQVFnQXpZQ0hDQUVJQWczQXdCQkFDRURJQVJCQURZQ0ZDQUVJQWdnQ1NBR0d5SUlOd01JSUFSQ2dJQUlJQWdnQ0VLQWdBaGFHejRDRUFzZ0F3dGZBUUYvUWJoL0lRTWdBVUVCUVFVZ0Foc2lBazhFZnlBQUlBSnFRUUZyTFFBQUlnQkJBM0ZCQW5SQm9CNXFLQUlBSUFKcUlBQkJCSFpCREhGQnNCNXFLQUlBYWlBQVFTQnhJZ0ZGYWlBQlFRVjJJQUJCd0FCSmNXb0ZRYmgvQ3dzTUFDQUFJQUVnQWtFQUVCa0xsd01DQlg4Q2ZpTUFRVUJxSWdRa0FBSkFBMEFnQVVFRlR3UkFBa0FnQUNnQUFFRndjVUhRMUxUQ0FVWUVRRUorSVFjZ0FVRUlTUTBFSUFBb0FBUWlBa0YzU3cwRUlBSkJDR29pQXlBQlN3MEVJQUpCZ1g5SkRRRU1CQXNnQkVFWWFpQUFJQUVRR3lFQ1FuNGdCQ2tER0VJQUlBUW9BaXhCQVVjYklBSWJJZ2RDZlZZTkF5QUhJQWg4SWdnZ0IxUkNmaUVIRFFNQ1FBSkFJQUZCQ0VrTkFDQUFLQUFBUVhCeFFkRFV0TUlCUncwQUlBQW9BQVFpQWtGM1N3MEZRYmgvSUFKQkNHb2lBaUFCSUFKSkd5RUREQUVMSUFSQkdHb2dBQ0FCRUJzaUFrR0lmMHNFUUNBQ0lRTU1BUXRCdUg4aEF5QUNEUUFnQVNBRUtBSXdJZ0pySVFVZ0FDQUNhaUVHQTBBZ0JpQUZJQVJCREdvUUhTSURRWWgvU3cwQklBTkJBMm9pQWlBRlN3UkFRYmgvSVFNTUFnc2dCU0FDYXlFRklBSWdCbW9oQmlBRUtBSVFSUTBBQ3lBRUtBSTRCSDlCdUg4aEF5QUZRUVJKRFFFZ0JrRUVhZ1VnQmdzZ0FHc2hBd3NnQTBHSWYwc05Bd3NnQVNBRGF5RUJJQUFnQTJvaEFBd0JDd3RDZmlBSUlBRWJJUWNMSUFSQlFHc2tBQ0FIQzJRQkFYOUJ1SDhoQXdKQUlBRkJBMGtOQUNBQUxRQUNJUUVnQWlBQUx3QUFJZ0JCQVhFMkFnUWdBaUFBUVFGMlFRTnhJZ00yQWdBZ0FpQUFJQUZCRUhSeVFRTjJJZ0EyQWdnQ1FBSkFJQU5CQVdzT0F3SUJBQUVMUVd3UEN5QUFJUU1MSUFNTFJBRUNmeUFCSUFJb0FnUWlBeUFCS0FJRWFpSUVOZ0lFSUFBZ0EwRUNkRUdnSFdvb0FnQWdBU2dDQUVFQUlBUnJkbkUyQWdBZ0FSQVBHaUFBSUFKQkNHbzJBZ1FMemdFQkJuOUJ1bjhoQ2dKQUlBSW9BZ1FpQ0NBQ0tBSUFJZ2xxSWcwZ0FTQUFhMHNOQUVGc0lRb2dDU0FFSUFNb0FnQWlDMnRMRFFBZ0FDQUphaUlFSUFJb0FnZ2lER3NoQWlBQUlBRkJJR3NpQUNBTElBbEJBQkFnSUFNZ0NTQUxhallDQUFKQUFrQWdCQ0FGYXlBTVR3UkFJQUloQlF3QkN5QU1JQVFnQm10TERRSWdCeUFISUFJZ0JXc2lBbW9pQVNBSWFrOEVRQ0FFSUFFZ0NCQUtHZ3dDQ3lBQ0lBaHFJUWdnQkNBQlFRQWdBbXNRQ2lBQ2F5RUVDeUFFSUFBZ0JTQUlRUUVRSUFzZ0RTRUtDeUFLQzhjRUFRSi9JQUFnQTJvaEJnSkFJQU5CQjB3RVFBTkFJQUFnQms4TkFpQUFJQUl0QUFBNkFBQWdBRUVCYWlFQUlBSkJBV29oQWd3QUN3QUxJQVJCQVVZRVFBSkFJQUFnQW1zaUJVRUhUUVJBSUFBZ0FpMEFBRG9BQUNBQUlBSXRBQUU2QUFFZ0FDQUNMUUFDT2dBQ0lBQWdBaTBBQXpvQUF5QUFJQUlnQlVFQ2RDSUZRY0FlYWlnQ0FHb2lBaWdBQURZQUJDQUNJQVZCNEI1cUtBSUFheUVDREFFTElBQWdBaWtBQURjQUFBc2dBa0VJYWlFQ0lBQkJDR29oQUFzZ0FTQUdUd1JBSUFBZ0Eyb2hBU0FFUVFGSElBQWdBbXRCRDBweVJRUkFBMEFnQUNBQ0tRQUFOd0FBSUFKQkNHb2hBaUFBUVFocUlnQWdBVWtOQUF3REN3QUxJQUFnQWlrQUFEY0FBQ0FBSUFJcEFBZzNBQWdnQTBFUlNRMEJJQUJCRUdvaEFBTkFJQUFnQWlrQUVEY0FBQ0FBSUFJcEFCZzNBQWdnQUNBQ0tRQWdOd0FRSUFBZ0Fpa0FLRGNBR0NBQ1FTQnFJUUlnQUVFZ2FpSUFJQUZKRFFBTERBRUxBa0FnQUNBQlN3UkFJQUFoQVF3QkN5QUJJQUJySVFVQ1FDQUVRUUZISUFBZ0FtdEJEMHB5UlFSQUlBSWhBd05BSUFBZ0F5a0FBRGNBQUNBRFFRaHFJUU1nQUVFSWFpSUFJQUZKRFFBTERBRUxJQUFnQWlrQUFEY0FBQ0FBSUFJcEFBZzNBQWdnQlVFUlNBMEFJQUJCRUdvaEFDQUNJUU1EUUNBQUlBTXBBQkEzQUFBZ0FDQURLUUFZTndBSUlBQWdBeWtBSURjQUVDQUFJQU1wQUNnM0FCZ2dBMEVnYWlFRElBQkJJR29pQUNBQlNRMEFDd3NnQWlBRmFpRUNDd05BSUFFZ0JrOE5BU0FCSUFJdEFBQTZBQUFnQVVFQmFpRUJJQUpCQVdvaEFnd0FDd0FMQzY0SEFnVi9BWDRqQUVHQUFXc2lFU1FBSUJFZ0F6WUNmRUYvSVE4Q1FBSkFBa0FDUUFKQUlBSU9CQUVBQXdJRUN5QUdSUVJBUWJoL0lROE1CQXRCYkNFUElBVXRBQUFpQWlBRFN3MERJQWdnQWtFQ2RDSUNhaWdDQUNFRElBSWdCMm9vQWdBaEFpQUFRUUE2QUFzZ0FFSUFOd0lBSUFBZ0FqWUNEQ0FBSUFNNkFBb2dBRUVBT3dFSUlBRWdBRFlDQUVFQklROE1Bd3NnQVNBSk5nSUFRUUFoRHd3Q0N5QUtSUVJBUVd3aER3d0NDMEVBSVE4Z0MwVWdERUVaU0hJTkFVRUlJQVIwUVFocUlRQkJBQ0VEQTBBZ0FDQURUUTBDSUFOQlFHc2hBd3dBQ3dBTFFXd2hEeUFSSUJGQi9BQnFJQkZCK0FCcUlBVWdCaEFNSWdOQmlIOUxEUUFnRVNnQ2VDSUNJQVJMRFFBZ0VTZ0NmRUVCYWlFSklBQkJDR29oQzBHQWdBSWdBblJCRUhVaEJVRUJJUkJCQVNBQ2RDSVBRUUZySWdvaEVnTkFJQWtnRGtjRVFBSkFJQkVnRGtFQmRDSUVhaThCQUNJTVFmLy9BMFlFUUNBTElCSkJBM1JxSUE0MkFnUWdFa0VCYXlFU1FRRWhEQXdCQ3lBUVFRQWdCU0FNd1VvYklSQUxJQVFnRFdvZ0REc0JBQ0FPUVFGcUlRNE1BUXNMSUFBZ0FqWUNCQ0FBSUJBMkFnQUNRQ0FLSUJKR0JFQWdEVUhxQUdvaEJrRUFJUkJCQUNFTUEwQWdDU0FRUmdSQUlBOUJBM1lnRDBFQmRtcEJBMm9pQlVFQmRDRUVRUUFoREVFQUlSSURRRUVBSVE0Z0R5QVNUUTBFQTBBZ0RrRUNSd1JBSUFzZ0JTQU9iQ0FNYWlBS2NVRURkR29nQmlBT0lCSnFhaTBBQURZQ0JDQU9RUUZxSVE0TUFRc0xJQkpCQW1vaEVpQUVJQXhxSUFweElRd01BQXNBQlNBUklCQkJBWFJxTGdFQUlRVWdCaUFNYWlJRUlCTTNBQUJCQ0NFT0EwQWdCU0FPU2dSQUlBUWdEbW9nRXpjQUFDQU9RUWhxSVE0TUFRc0xJQk5DZ1lLRWlKQ2d3SUFCZkNFVElCQkJBV29oRUNBRklBeHFJUXdNQVFzQUN3QUxJQTlCQTNZZ0QwRUJkbXBCQTJvaEJVRUFJUkJCQUNFT0EwQWdDU0FRUmcwQlFRQWhEQ0FSSUJCQkFYUnFMZ0VBSWdSQkFDQUVRUUJLR3lFRUEwQWdCQ0FNUndSQUlBc2dEa0VEZEdvZ0VEWUNCQU5BSUFVZ0Rtb2dDbkVpRGlBU1N3MEFDeUFNUVFGcUlRd01BUXNMSUJCQkFXb2hFQXdBQ3dBTElBSkJBV29oQlVFQUlRd0RRQ0FNSUE5SEJFQWdEU0FMSUF4QkEzUnFJZ2tvQWdRaUJFRUJkR29pQWlBQ0x3RUFJZ1pCQVdvN0FRQWdDU0FGSUFablFXQnphaUlDT2dBRElBa2dCaUFDZENBUGF6c0JBQ0FKSUFnZ0JFRUNkQ0lDYWlnQ0FEb0FBaUFKSUFJZ0Iyb29BZ0EyQWdRZ0RFRUJhaUVNREFFTEN5QUJJQUEyQWdBZ0F5RVBDeUFSUVlBQmFpUUFJQThMN1ZvQ08zOEdmaU1BUWVBQmF5SUVKQUFDUUVHdzdBa1FCU0lGUlFSQVFVQWhCd3dCQ3lBRlFnQTNBdlRxQVNBRlFRQTJBc1RyQVNBRlFRQTJBclRyQVNBRlFnQTNBcHpyQVNBRlFRQTJBcmpwQVNBRlFRQTJBcXpzQ1NBRlFnQTNBdFRyQVNBRlFnQTNBcXpyQVNBRlFnQTNBNGpyQVNBRlFnQTNBdVRxQVNBRlFnQTNBdVRyQVNBRlFZR0FnTUFBTmdLODZ3RWdCVUlBTndLazZ3RWdCVUg4NmdGcVFRQTJBZ0FnQlVHUTZ3RnFRZ0EzQXdBZ0JSQVlJQVZCck5VQmFpRVVJQVZCK09zQmFpRWNJQVZCc09vQmFpRWlJQVZCb0RCcUlTb2dCVUdZSUdvaEt5QUZRYWpRQUdvaEhpQUZRUkJxSVN3Z0JVRUlhaUVvSUFWQkJHb2hMU0FGUWNEcEFXb2hLU0FGUVlqckFXb2dCRUdVQVdvaEx5QUVRWXdCYWlFd0lBUkJoQUZxSVRFZ0JFSGNBR29oTWlBRVFkUUFhaUV6SUFSQnpBQnFJVFFnQUNFZEFrQUNRQUpBQWtBQ1FBTkFRUUZCQlNBRktBTGs2Z0ViSVFZQ1FBTkFJQU1nQmtrTkFTQUNLQUFBUVhCeFFkRFV0TUlCUmdSQVFiaC9JUWNnQTBFSVNRMElJQUlvQUFRaURrRjNTd1JBUVhJaEJ3d0pDeUFESUE1QkNHb2lDVWtOQ0NBT1FZQi9Td1JBSUFraEJ3d0pDeUFESUFscklRTWdBaUFKYWlFQ0RBRUxDeUFGUWdBM0FxenBBU0FGUWdBM0EranBBU0FGUVFBMkFwanJBU0FGUWdBM0E0RHFBU0FGUWdNM0EvanBBU0FGUWJUcEFXcENBRGNDQUNBRlFmRHBBV3BDQURjREFDQUZRYWpRQUdvaUNVR01nSURnQURZQ0FDQUZRYXpRQVdwQjRCSXBBZ0EzQWdBZ0JVRzAwQUZxUWVnU0tBSUFOZ0lBSUFVZ0JVRVFhallDQUNBRklBVkJvREJxTmdJRUlBVWdCVUdZSUdvMkFnZ2dCU0FKTmdJTUlBVkJBVUVGSUFVb0F1VHFBUnMyQXJ6cEFRSkFJQUZGRFFBZ0JTZ0NyT2tCSWdrZ0hVWU5BQ0FGSUFrMkFyanBBU0FGSUIwMkFxenBBU0FGS0FLdzZRRWhEaUFGSUIwMkFyRHBBU0FGSUIwZ0RpQUphMm8yQXJUcEFRdEJ1SDhoQ1NBRFFRVkJDU0FGS0FMazZnRWlCaHRKRFFVZ0FrRUJRUVVnQmhzZ0JoQWFJZzVCaUg5TEJFQWdEaUVKREFVTElBTWdEa0VEYWtrTkJTQXBJQUlnRGlBR0VCa2lCa0dJZjBzRVFDQUdJUWtNQlFzZ0JnMEZBa0FDUUNBRktBS282d0ZCQVVjTkFDQUZLQUtrNndFaUNVVU5BQ0FGS0FLVTZ3RkZEUUFnQ1NnQ0JFRUJheUlISUFVb0F0enBBU0lLclVLSGxhK3ZtTGJlbTU1L2ZrTEp6OW15OGVXNjZpZUZRaGVKUXMvVzA3N1N4NnZaUW41QytmUGQ4Wm4ybWFzV2ZDSS9RaUdJSUQrRlFzL1cwNzdTeDZ2WlFuNGlQMElkaUNBL2hVTDU4OTN4bWZhWnF4WitJajlDSUlnZ1A0V25jU0VHSUFrb0FnQWhGUU5BUVFBaENBSkFJQlVnQmtFQ2RHb29BZ0FpQ1VVTkFDQUpLQUlJUVFoSkRRQWdDU2dDQkNJU0tBQUFRYmZJd3VGK1J3MEFJQklvQUFRaENBc2dDQ0FLUndSQUlBWWdCM0ZCQVdvaEJpQUlEUUVMQ3lBSlJRMEFJQVVRR0NBRlFYODJBcURyQVNBRklBazJBcFRyQVNBRklBVW9BdHpwQVNJSU5nS1k2d0VNQVFzZ0JTZ0MzT2tCSVFnTEFrQWdDRVVOQUNBRktBS1k2d0VnQ0VZTkFFRmdJUWtNQmdzQ1FDQUZLQUxnNlFFRVFDQUZJQVVvQXVqcUFTSUpSVFlDN09vQklBa05BU0FGUXZucTBORG55YUhrNFFBM0E2anFBU0FGUWdBM0E2RHFBU0FGUXMvVzA3N1N4NnZaUWpjRG1Pb0JJQVZDMXV1Qzd1cjlpZlhnQURjRGtPb0JJQVZDQURjRGlPb0JJQ0pCQUVFb0VBTWFEQUVMSUFWQkFEWUM3T29CQ3lBQklCMXFJU1VnQlNBRktRUG82UUVnRHExOE53UG82UUVnQXlBT2F5RURJQUlnRG1vaEFpQWRJUTREUUNBQ0lBTWdCRUVzYWhBZEloVkJpSDlMQkVBZ0ZTRUpEQVlMSUFOQkEyc2lOU0FWU1EwRUlBSkJBMm9oRzBGc0lRa0NRQUpBQWtBQ1FBSkFBa0FDUUFKQUFrQUNRQUpBQWtBQ1FBSkFBa0FDUUNBRUtBSXNEZ01DQVFBVkN5QVZRZi8vQjBzTkV5QVZRUU5KRFJJZ0JTa0R5T2tCSVQ4Q1FBSkFJQnN0QUFBaUNVRURjU0lhUVFGckRnTUdBUUFIQ3lBRktBS0E2Z0VOQUVGaUlRa01GUXNnRlVFRlNRMFNJQnNvQUFBaEF3Si9Ba0FDUUFKQUlBbEJBblpCQTNFaUNVRUNhdzRDQVFJQUN5QUpRUUJISVFjZ0EwRUVka0gvQjNFaEMwRURJUVlnQTBFT2RrSC9CM0VNQWd0QkJDRUdJQU5CQkhaQi8vOEFjU0VMUVFFaEJ5QURRUkoyREFFTElBTkJCSFpCLy84UGNTSUxRWUNBQ0VzTkUwRUJJUWRCQlNFR0lBSXRBQWRCQ25RZ0EwRVdkbklMSWdnZ0Jtb2lDU0FWU3cwU0FrQWdDMEdCQmtrTkFDQUZLQUtjNndGRkRRQkJBQ0VEQTBBZ0EwR0RnQUZMRFFFZ0EwRkFheUVEREFBTEFBc2dCaUFiYWlFUElCcEJBMGNOQmlBRktBSU1JZ0l0QUFGQkNIUWhBeUFIRFFjZ0EwVU5DQ0FFUWZBQWFpQVBJQWdRRFNJRFFZaC9TdzBKSUFKQkJHb2hCaUFMSUJ4cUloSkJBMnNoQ2tFQUlBSXZBUUpyUVI5eElRY2dIQ0VEQTBBZ0JFSHdBR29RRDBVZ0F5QUtTWEVFUUNBRElBWWdCQ2dDY0NJSUlBUW9BblFpRDNRZ0IzWkJBblJxSWdJdkFRQTdBQUFnQXlBQ0xRQURhaUlESUFZZ0NDQVBJQUl0QUFKcUlnaDBJQWQyUVFKMGFpSUNMd0VBT3dBQUlBUWdDQ0FDTFFBQ2FqWUNkQ0FESUFJdEFBTnFJUU1NQVFVZ0VrRUNheUVJQTBBZ0JFSHdBR29RRHlFUElBUW9BbkFoQ2lBRUtBSjBJUUlnQXlBSVN5QVBja1VFUUNBRElBWWdDaUFDZENBSGRrRUNkR29pQ2k4QkFEc0FBQ0FFSUFJZ0NpMEFBbW8yQW5RZ0F5QUtMUUFEYWlFRERBRUxDd05BSUFNZ0NFMEVRQ0FESUFZZ0NpQUNkQ0FIZGtFQ2RHb2lEeThCQURzQUFDQURJQTh0QUFOcUlRTWdBaUFQTFFBQ2FpRUNEQUVMQ3dKQUlBTWdFazhOQUNBRElBWWdDaUFDZENBSGRrRUNkR29pQXkwQUFEb0FBQ0FETFFBRFFRRkdCRUFnQWlBRExRQUNhaUVDREFFTElBSkJIMHNOQUVFZ0lBSWdBeTBBQW1vaUFpQUNRU0JQR3lFQ0MwRnNRV3dnQ3lBRUtBSjRJQVFvQW54SEd5QUNRU0JIR3lFRERBc0xBQXNBQ3lBRUtBSTBJZ0lnSlNBT2Ewc05DaUFPUlFSQVFRQWhDU0FDRFFJTURnc2dEaUFiTFFBQUlBSVFBeG9nQWlFSkRBd0xJQlVnSlNBT2Ewc05DU0FPRFFGQkFDRUpJQlZGRFF3TFFiWi9JUWtNRVFzZ0RpQWJJQlVRQWhvZ0ZTRUpEQW9MSUJ3Z0d3Si9Ba0FDUUFKQUlBbEJBblpCQTNGQkFXc09Bd0VBQWdBTElBbEJBM1loQTBFQkRBSUxJQnN2QUFCQkJIWWhBMEVDREFFTElCVkJCRWtORGlBQ0x3QURJQUl0QUFWQkVIUnlJZ0pCajRDQUFVc05EaUFDUVFSMklRTkJBd3NpQW1vdEFBQWdBMEVnYWhBRElRa2dCU0FETmdLQTZ3RWdCU0FKTmdMdzZnRWdBa0VCYWlFSkRBVUxJQlVDZndKQUFrQUNRQ0FKUVFKMlFRTnhRUUZyRGdNQkFBSUFDeUFKUVFOMklRTkJBUXdDQ3lBYkx3QUFRUVIySVFOQkFnd0JDeUFDTHdBRElBSXRBQVZCRUhSeVFRUjJJUU5CQXdzaUFpQURhaUlKUVNCcVNRUkFJQWtnRlVzTkRTQWNJQUlnRzJvZ0F4QUNJUUlnQlNBRE5nS0E2d0VnQlNBQ05nTHc2Z0VnQWlBRGFpSUNRZ0EzQUJnZ0FrSUFOd0FRSUFKQ0FEY0FDQ0FDUWdBM0FBQU1CUXNnQlNBRE5nS0E2d0VnQlNBQ0lCdHFOZ0x3NmdFTUJBc2dCMFVFUUNBZUlBOGdDQ0FVRUJRaUFrR0lmMHNnQWlBSVQzSU5EQ0FjSUFzZ0FpQVBhaUFJSUFKcklCNFFGU0VEREFNTElBdEZJQWhGY2cwTElBdEJDSFlpQXlBSUlBdEpCSDhnQ0VFRWRDQUxiZ1ZCRHd0QkdHd2lBa0dNQ0dvb0FnQnNJQUpCaUFocUtBSUFhaUlHUVFOMklBWnFJQUpCZ0FocUtBSUFJQUpCaEFocUtBSUFJQU5zYWtrRVFDTUFRUkJySWhBa0FDQWVLQUlBSVFNZ0ZFSHdCR3BCQUVIc0FCQURJUVpCVkNFQ0FrQWdBMEgvQVhFaURFRU1TdzBBQWtBZ0ZFSGNDV29nQmlBUVFRaHFJQkJCREdvZ0R5QUlJQlJCM0F0cUloY1FDeUlTUVloL1N3MEFJQkFvQWd3aUJpQU1TdzBCSUJSQnFBVnFJUTBnRkVHa0JXb2hOaUFlUVFScUlSRWdBMEdBZ0lCNGNTRTNJQVpCQVdvaUV5RUNJQVloQXdOQUlBSWlCMEVCYXlFQ0lBTWlDa0VCYXlFRElCUWdDa0VDZEdvb0F2QUVSUTBBQzBFQklBY2dCMEVCVFJzaEZrRUFJUWRCQVNFQ0EwQWdBaUFXUndSQUlCUWdBa0VDZENJRGFpZ0M4QVFoR0NBRElBMXFJQWMyQWdBZ0FrRUJhaUVDSUFjZ0dHb2hCd3dCQ3dzZ0RTQUhOZ0lBUVFBaEFpQVFLQUlJSVFNRFFDQUNJQU5IQkVBZ0RTQUNJQlJxUWR3SmFpMEFBQ0lZUVFKMGFpSVpJQmtvQWdBaUdVRUJhallDQUNBVUlCbEJBWFJxSWhrZ0dEb0EzUVVnR1NBQ09nRGNCU0FDUVFGcUlRSU1BUXNMUVFBaEF5QU5RUUEyQWdBZ0RDQUdRWDl6YWlFR1FRRWhBZ05BSUFJZ0ZrY0VRQ0FVSUFKQkFuUnFJZzBnQXpZQ0FDQU5LQUx3QkNBQ0lBWnFkQ0FEYWlFRElBSkJBV29oQWd3QkN3c2dEQ0FUSUFwcklnWnJRUUZxSVFvZ0JpRURBMEFnQXlBS1NRUkFJQlFnQTBFMGJHb2hEVUVCSVFJRFFDQUNJQlpIQkVBZ0RTQUNRUUowSWhocUlCUWdHR29vQWdBZ0EzWTJBZ0FnQWtFQmFpRUNEQUVMQ3lBRFFRRnFJUU1NQVFzTElCY2dGRUUwRUFJaE9DQVVRWkFNYWlFNUlCTWdER3NoT2lBVVFkd0ZhaUVYUVFBaENnTkFBa0FDUUNBSElBcEhCRUJCQVNBTUlCTWdGeUFLUVFGMGFpSUNMUUFCSWcxcklnTnJJaGgwSVJrZ0FpMEFBQ0VXSURnZ0RVRUNkR29pSHlnQ0FDRUNJQVlnR0UwRVFDQTJRUUVnQXlBNmFpSU5JQTFCQVV3YklpQkJBblFpSkdvb0FnQWhEU0E1SUJRZ0EwRTBiR3BCTkJBQ0lTRWdEVUVCZENFbUlCRWdBa0VDZEdvaEl5QWdRUUZORFFJZ0EwRVFkRUdBZ1B3SGNTQVdja0dBZ0lBSWNpRWdJQ0VnSkdvb0FnQWhKRUVBSVFJRFFDQUNJQ1JHRFFNZ0l5QUNRUUowYWlBZ05nRUFJQUpCQVdvaEFnd0FDd0FMSUFJZ0FpQVphaUlOSUFJZ0RVc2JJUTBnQTBFUWRFR0FnUHdIY1NBV2NrR0FnSUFJY2lFREEwQWdBaUFOUmcwRElCRWdBa0VDZEdvZ0F6WUJBQ0FDUVFGcUlRSU1BQXNBQ3lBZUlBeEJFSFFnTjNJZ0RISkJnQUp5TmdJQURBTUxJQWNnRFdzaEpDQVhJQ1pxSVNaQkFDRU5BMEFnRFNBa1JnMEJRUUVnR0NBVElDWWdEVUVCZEdvaUp5MEFBU0lDYXlJN2EzUWlQQ0FoSUFKQkFuUnFJaUFvQWdBaUFtb2hQU0FESUR0cVFSQjBRWUNBL0FkeElDY3RBQUJCQ0hSeUlCWnlRWUNBZ0JCeUlTY0RRQ0FqSUFKQkFuUnFJQ2MyQVFBZ0FrRUJhaUlDSUQxSkRRQUxJQ0FnSUNnQ0FDQThhallDQUNBTlFRRnFJUTBNQUFzQUN5QWZJQjhvQWdBZ0dXbzJBZ0FnQ2tFQmFpRUtEQUFMQUFzZ0VpRUNDeUFRUVJCcUpBQWdBa0dJZjBzZ0FpQUlUM0lORENBY0lBc2dBaUFQYWlBSUlBSnJJQjRRRmlFRERBTUxJQjRnRHlBSUlCUVFGQ0lDUVloL1N5QUNJQWhQY2cwTElCd2dDeUFDSUE5cUlBZ2dBbXNnSGhBWElRTU1BZ3NnQXdSQUlCd2dDeUFQSUFnZ0FoQVdJUU1NQWdzZ0hDQUxJQThnQ0NBQ0VCY2hBd3dCQ3lBY0lBc2dEeUFJSUFJUUZTRURDeUFEUVloL1N3MElJQVVnQ3pZQ2dPc0JJQVVnSERZQzhPb0JJQVZCQVRZQ2dPb0JJQnBCQWtZRVFDQUZJQjQyQWd3TElBc2dIR29pQWtJQU53QUFJQUpDQURjQUdDQUNRZ0EzQUJBZ0FrSUFOd0FJSUFsQmlIOUxEUW9MSUFrZ0ZVWU5DQ0FWSUFscklRWWdCU2dDbk9zQklRb0NRQ0FKSUJ0cUlnTXRBQUFpRDBVRVFFRUJJUUpCQUNFUFFiaC9JUWtnQmtFQlJnMEJEQXNMQW44Z0EwRUJhaUFQd0NJQ1FRQk9EUUFhSUFKQmYwWUVRQ0FHUVFOSURRc2dBeThBQVVHQS9nRnFJUThnQTBFRGFnd0JDeUFHUVFKSURRb2dBeTBBQVNBUFFRaDBja0dBZ0FKcklROGdBMEVDYWdzaEVrRzRmeUVKSUJKQkFXb2lBaUFWSUJ0cUlnZExEUW9nTENBRklCSXRBQUFpRWtFR2RrRWpRUWtnQWlBSElBSnJRY0FRUWRBUlFmQVNJQVVvQW9UcUFTQUtJQThnRkJBaElnbEJpSDlMRFFnZ0t5QW9JQkpCQkhaQkEzRkJIMEVJSUFJZ0NXb2lBaUFISUFKclFZQUxRWUFNUVlBWElBVW9Bb1RxQVNBRktBS2M2d0VnRHlBVUVDRWlDRUdJZjBzTkNFRnNJUWtnS2lBdElCSkJBblpCQTNGQk5FRUpJQUlnQ0dvaUFpQUhJQUpyUVlBTlFlQU9RWkFaSUFVb0FvVHFBU0FGS0FLYzZ3RWdEeUFVRUNFaUIwR0lmMHNOQ2lBQ0lBZHFJQU5ySWdJaENTQUNRWWgvU3cwS0N5QU9JQTlCQUV4eURRRUxRYnAvSVFrTUNBc2dKU0FPYXlFSklBWWdBbXNoQmlBQ0lBTnFJUWNDUUFKQUFrQWdDa1VFUUNBUFFRbElJQVVwQThqcEFVS0JnSUFJVkhJTkFpQW9LQUlBSWdKQkNHb2hFaUFDS0FJRUlRcEJBQ0VEUVFBaEFnTkFJQU1nQ25aRkJFQWdBaUFTSUFOQkEzUnFMUUFDUVJaTGFpRUNJQU5CQVdvaEF3d0JDd3NnQlVFQU5nS2M2d0VnQWtFSUlBcHJkRUVVVHcwQkRBTUxJQVZCQURZQ25Pc0JDeUFFSUFVb0F2RHFBU0lETmdMY0FTQUpJQTVxSVJZZ0F5QUZLQUtBNndGcUlSY0NRQ0FQUlFSQUlBNGhCd3dCQ3lBRktBSzQ2UUVoR2lBRktBSzA2UUVoR0NBRktBS3c2UUVoRWlBRlFRRTJBb1RxQVVFQUlRTURRQ0FEUVFOSEJFQWdCQ0FEUVFKMElnSnFJQUlnQldwQnJOQUJhaWdDQURZQ1pDQURRUUZxSVFNTUFRc0xRV3doQ1NBRVFUaHFJZ0lnQnlBR0VBMUJpSDlMRFFOQkNDQVBJQTlCQ0U0YklSOGdOQ0FDSUFVb0FnQVFIaUF6SUFJZ0JTZ0NDQkFlSURJZ0FpQUZLQUlFRUI0Z0RpQVNheUVaUVFBaENBTkFJQVJCT0dvUUQwRURSaUFJSUI5T2NrVUVRQ0FFS0FKUUlBUW9Ba3hCQTNScUtRSUFJa0NuSWdkQkVIWWlFVUgvQVhFaEN5QUVLQUpnSUFRb0FseEJBM1JxS1FJQUlrR25JZ3hCRUhZaUlVSC9BWEVoRUNBRUtBSllJQVFvQWxSQkEzUnFLUUlBSWtKQ0lJaW5JUVlnUVVJZ2lDQkFRaUNJcHlFREFrQWdRa0lRaUtjaUNrSC9BWEVpQWtFQ1R3UkFBa0FnQWtFWlNTQS9Rb0dBZ0JCVWNrVUVRQ0FFUVNBZ0JDZ0NQQ0lLYXlJTklBSWdBaUFOU3hzaUV5QUthallDUENBR0lBUW9BamdnQ25SQkFDQVRhM1lnQWlBVGF5SVRkR29oQ2lBRVFUaHFFQThhSUFJZ0RVME5BU0FFSUFRb0Fqd2lBaUFUYWpZQ1BDQUVLQUk0SUFKMFFRQWdFMnQySUFwcUlRb01BUXNnQkNBQ0lBUW9BandpRFdvMkFqd2dCQ2dDT0NBTmRFRUFJQXByZGlBR2FpRUtJQVJCT0dvUUR4b0xJQVFwQW1RaFJDQUVJQW8yQW1RZ0JDQkVOd0pvREFFTEFrQWdBa1VFUUNBREJFQWdCQ2dDWkNFS0RBTUxJQVFvQW1naENnd0JDeUFFSUFRb0Fqd2lBa0VCYWpZQ1BBSi9JQVlnQTBWcUlBUW9BamdnQW5SQkgzWnFJZ0pCQTBZRVFDQUVLQUprUVFGckRBRUxJQUpCQW5RZ0JHb29BbVFMSWdaRklBWnFJUW9nQWtFQlJ3UkFJQVFnQkNnQ2FEWUNiQXNMSUFRZ0JDZ0NaRFlDYUNBRUlBbzJBbVFMcHlFQ0lFRkNnSUQ4QjROUVJRUkFJQVFnQkNnQ1BDSUdJQkJxTmdJOElBUW9BamdnQm5SQkFDQWhhM1lnQW1vaEFnc2dDeUFRYWtFVVR3UkFJQVJCT0dvUUR4b0xJRUJDZ0lEOEI0TlFSUVJBSUFRZ0JDZ0NQQ0lHSUF0cU5nSThJQVFvQWpnZ0JuUkJBQ0FSYTNZZ0Eyb2hBd3NnQkVFNGFoQVBHaUFFSUFRb0FqZ2lCa0VBSUFkQkdIWWlDeUFFS0FJOGFpSVFhM1lnQzBFQ2RFR2dIV29vQWdCeElBZEIvLzhEY1dvMkFrd2dCQ0FRSUF4QkdIWWlCMm9pQ3pZQ1BDQUVJQWRCQW5SQm9CMXFLQUlBSUFaQkFDQUxhM1p4SUF4Qi8vOERjV28yQWx3Z0JFRTRhaEFQR2lBRUlFS25JZ1pCR0hZaUJ5QUVLQUk4YWlJTE5nSThJQVFnQjBFQ2RFR2dIV29vQWdBZ0JDZ0NPRUVBSUF0cmRuRWdCa0gvL3dOeGFqWUNWQ0FFUWZBQWFpQUlRUXhzYWlJR0lBbzJBZ2dnQmlBQ05nSUVJQVlnQXpZQ0FDQUlRUUZxSVFnZ0F5QVphaUFDYWlFWkRBRUxDeUFJSUI5SURRTWdGa0VnYXlFaElBNGhCd05BSUFSQk9Hb1FEMEVEUmlBSUlBOU9ja1VFUUNBRUtBSlFJQVFvQWt4QkEzUnFLUUlBSWtDbklnWkJFSFlpSTBIL0FYRWhDaUFFS0FKZ0lBUW9BbHhCQTNScUtRSUFJa0duSWcxQkVIWWlJRUgvQVhFaEV5QUVLQUpZSUFRb0FsUkJBM1JxS1FJQUlrSkNJSWluSVFNZ1FVSWdpQ0JBUWlDSXB5RUxBa0FnUWtJUWlLY2lERUgvQVhFaUFrRUNUd1JBQWtBZ0FrRVpTU0EvUW9HQWdCQlVja1VFUUNBRVFTQWdCQ2dDUENJTWF5SVJJQUlnQWlBUlN4c2lFQ0FNYWpZQ1BDQURJQVFvQWpnZ0RIUkJBQ0FRYTNZZ0FpQVFheUlNZEdvaEVDQUVRVGhxRUE4YUlBSWdFVTBOQVNBRUlBUW9BandpQWlBTWFqWUNQQ0FFS0FJNElBSjBRUUFnREd0MklCQnFJUkFNQVFzZ0JDQUNJQVFvQWp3aUVHbzJBandnQkNnQ09DQVFkRUVBSUF4cmRpQURhaUVRSUFSQk9Hb1FEeG9MSUFRcEFtUWhSQ0FFSUJBMkFtUWdCQ0JFTndKb0RBRUxBa0FnQWtVRVFDQUxCRUFnQkNnQ1pDRVFEQU1MSUFRb0FtZ2hFQXdCQ3lBRUlBUW9BandpQWtFQmFqWUNQQUovSUFNZ0MwVnFJQVFvQWpnZ0FuUkJIM1pxSWdKQkEwWUVRQ0FFS0FKa1FRRnJEQUVMSUFKQkFuUWdCR29vQW1RTElnTkZJQU5xSVJBZ0FrRUJSd1JBSUFRZ0JDZ0NhRFlDYkFzTElBUWdCQ2dDWkRZQ2FDQUVJQkEyQW1RTHB5RU1JRUZDZ0lEOEI0TlFSUVJBSUFRZ0JDZ0NQQ0lDSUJOcU5nSThJQVFvQWpnZ0FuUkJBQ0FnYTNZZ0RHb2hEQXNnQ2lBVGFrRVVUd1JBSUFSQk9Hb1FEeG9MSUVCQ2dJRDhCNE5RUlFSQUlBUWdCQ2dDUENJQ0lBcHFOZ0k4SUFRb0FqZ2dBblJCQUNBamEzWWdDMm9oQ3dzZ0JFRTRhaEFQR2lBRUlBUW9BamdpQWtFQUlBWkJHSFlpQXlBRUtBSThhaUlLYTNZZ0EwRUNkRUdnSFdvb0FnQnhJQVpCLy84RGNXbzJBa3dnQkNBS0lBMUJHSFlpQTJvaUJqWUNQQ0FFSUFOQkFuUkJvQjFxS0FJQUlBSkJBQ0FHYTNaeElBMUIvLzhEY1dvMkFsd2dCRUU0YWhBUEdpQUVJRUtuSWdKQkdIWWlBeUFFS0FJOGFpSUdOZ0k4SUFRZ0EwRUNkRUdnSFdvb0FnQWdCQ2dDT0VFQUlBWnJkbkVnQWtILy93TnhhallDVkFKQUFrQUNRQ0FFS0FMY0FTSURJQVJCOEFCcUlBaEJCM0ZCREd4cUloTW9BZ0FpRVdvaUl5QVhTdzBBSUFjZ0V5Z0NCQ0lOSUJGcUlncHFJQ0ZMRFFBZ0NrRWdhaUFXSUFkclRRMEJDeUFFSUJNb0FnZzJBaGdnQkNBVEtRSUFOd01RSUFjZ0ZpQUVRUkJxSUFSQjNBRnFJQmNnRWlBWUlCb1FIeUVLREFFTElBY2dFV29oQWlBVEtBSUlJUVlnQnlBREtRQUFOd0FBSUFjZ0F5a0FDRGNBQ0FKQUlCRkJFVWtOQUNBSElBTXBBQkEzQUJBZ0J5QURLUUFZTndBWUlCRkJFR3RCRVVnTkFDQURRUkJxSVFNZ0IwRWdhaUVSQTBBZ0VTQURLUUFRTndBQUlCRWdBeWtBR0RjQUNDQVJJQU1wQUNBM0FCQWdFU0FES1FBb053QVlJQU5CSUdvaEF5QVJRU0JxSWhFZ0Fra05BQXNMSUFJZ0Jtc2hBeUFFSUNNMkF0d0JJQUlnRW1zZ0Jra0VRQ0FHSUFJZ0dHdExEUWNnR2lBYUlBTWdFbXNpQTJvaUVTQU5hazhFUUNBQ0lCRWdEUkFLR2d3Q0N5QURJQTFxSVEwZ0FpQVJRUUFnQTJzUUNpQURheUVDSUJJaEF3c2dCa0VRVHdSQUlBSWdBeWtBQURjQUFDQUNJQU1wQUFnM0FBZ2dEVUVSU0EwQklBSWdEV29oQmlBQ1FSQnFJUUlEUUNBQ0lBTXBBQkEzQUFBZ0FpQURLUUFZTndBSUlBSWdBeWtBSURjQUVDQUNJQU1wQUNnM0FCZ2dBMEVnYWlFRElBSkJJR29pQWlBR1NRMEFDd3dCQ3dKQUlBWkJCMDBFUUNBQ0lBTXRBQUE2QUFBZ0FpQURMUUFCT2dBQklBSWdBeTBBQWpvQUFpQUNJQU10QUFNNkFBTWdBaUFESUFaQkFuUWlCa0hBSG1vb0FnQnFJZ01vQUFBMkFBUWdBeUFHUWVBZWFpZ0NBR3NoQXd3QkN5QUNJQU1wQUFBM0FBQUxJQTFCQ1VrTkFDQUNJQTFxSVJFZ0FrRUlhaUlHSUFOQkNHb2lBMnRCRDB3RVFBTkFJQVlnQXlrQUFEY0FBQ0FEUVFocUlRTWdCa0VJYWlJR0lCRkpEUUFNQWdzQUN5QUdJQU1wQUFBM0FBQWdCaUFES1FBSU53QUlJQTFCR1VnTkFDQUNRUmhxSVFJRFFDQUNJQU1wQUJBM0FBQWdBaUFES1FBWU53QUlJQUlnQXlrQUlEY0FFQ0FDSUFNcEFDZzNBQmdnQTBFZ2FpRURJQUpCSUdvaUFpQVJTUTBBQ3dzZ0NrR0lmMHNFUUNBS0lRa01CZ1VnRXlBUU5nSUlJQk1nRERZQ0JDQVRJQXMyQWdBZ0NFRUJhaUVJSUFjZ0Ntb2hCeUFMSUJscUlBeHFJUmtNQWdzQUN3c2dDQ0FQU0EwRElBZ2dIMnNoQmdOQUFrQWdCaUFQVGdSQVFRQWhBd05BSUFOQkEwWU5BaUFGSUFOQkFuUWlBbXBCck5BQmFpQUNJQVJxS0FKa05nSUFJQU5CQVdvaEF3d0FDd0FMQWtBQ1FBSkFJQVFvQXR3QklnTWdCRUh3QUdvZ0JrRUhjVUVNYkdvaUNDZ0NBQ0lNYWlJUUlCZExEUUFnQnlBSUtBSUVJZ3NnREdvaUNtb2dJVXNOQUNBS1FTQnFJQllnQjJ0TkRRRUxJQVFnQ0NnQ0NEWUNLQ0FFSUFncEFnQTNBeUFnQnlBV0lBUkJJR29nQkVIY0FXb2dGeUFTSUJnZ0doQWZJUW9NQVFzZ0J5QU1haUVDSUFnb0FnZ2hDQ0FISUFNcEFBQTNBQUFnQnlBREtRQUlOd0FJQWtBZ0RFRVJTUTBBSUFjZ0F5a0FFRGNBRUNBSElBTXBBQmczQUJnZ0RFRVFhMEVSU0EwQUlBTkJFR29oQXlBSFFTQnFJUXdEUUNBTUlBTXBBQkEzQUFBZ0RDQURLUUFZTndBSUlBd2dBeWtBSURjQUVDQU1JQU1wQUNnM0FCZ2dBMEVnYWlFRElBeEJJR29pRENBQ1NRMEFDd3NnQWlBSWF5RURJQVFnRURZQzNBRWdBaUFTYXlBSVNRUkFJQWdnQWlBWWEwc05CeUFhSUJvZ0F5QVNheUlEYWlJTUlBdHFUd1JBSUFJZ0RDQUxFQW9hREFJTElBTWdDMm9oQ3lBQ0lBeEJBQ0FEYXhBS0lBTnJJUUlnRWlFREN5QUlRUkJQQkVBZ0FpQURLUUFBTndBQUlBSWdBeWtBQ0RjQUNDQUxRUkZJRFFFZ0FpQUxhaUVJSUFKQkVHb2hBZ05BSUFJZ0F5a0FFRGNBQUNBQ0lBTXBBQmczQUFnZ0FpQURLUUFnTndBUUlBSWdBeWtBS0RjQUdDQURRU0JxSVFNZ0FrRWdhaUlDSUFoSkRRQUxEQUVMQWtBZ0NFRUhUUVJBSUFJZ0F5MEFBRG9BQUNBQ0lBTXRBQUU2QUFFZ0FpQURMUUFDT2dBQ0lBSWdBeTBBQXpvQUF5QUNJQU1nQ0VFQ2RDSUlRY0FlYWlnQ0FHb2lBeWdBQURZQUJDQURJQWhCNEI1cUtBSUFheUVEREFFTElBSWdBeWtBQURjQUFBc2dDMEVKU1EwQUlBSWdDMm9oRENBQ1FRaHFJZ2dnQTBFSWFpSURhMEVQVEFSQUEwQWdDQ0FES1FBQU53QUFJQU5CQ0dvaEF5QUlRUWhxSWdnZ0RFa05BQXdDQ3dBTElBZ2dBeWtBQURjQUFDQUlJQU1wQUFnM0FBZ2dDMEVaU0EwQUlBSkJHR29oQWdOQUlBSWdBeWtBRURjQUFDQUNJQU1wQUJnM0FBZ2dBaUFES1FBZ053QVFJQUlnQXlrQUtEY0FHQ0FEUVNCcUlRTWdBa0VnYWlJQ0lBeEpEUUFMQ3lBS1FZaC9Td1JBSUFvaENRd0dCU0FHUVFGcUlRWWdCeUFLYWlFSERBSUxBQXNMSUFRb0F0d0JJUU1MUWJwL0lRa2dGeUFEYXlJQ0lCWWdCMnRMRFFJZ0J3Ui9JQWNnQXlBQ0VBSWdBbW9GUVFBTElBNXJJUWtNQWdzZ0JVRUFOZ0tjNndFTElBUWdCU2dDOE9vQklnTTJBdHdCSUFrZ0Rtb2hEQ0FESUFVb0FvRHJBV29oRUFKQUlBOUZCRUFnRGlFR0RBRUxJQVVvQXJqcEFTRU5JQVVvQXJUcEFTRVRJQVVvQXJEcEFTRVNJQVZCQVRZQ2hPb0JRUUFoQXdOQUlBTkJBMGNFUUNBRUlBTkJBblFpQW1vZ0FpQUZha0dzMEFGcUtBSUFOZ0tjQVNBRFFRRnFJUU1NQVFzTFFXd2hDU0FFUWZBQWFpSUNJQWNnQmhBTlFZaC9TdzBCSURFZ0FpQUZLQUlBRUI0Z01DQUNJQVVvQWdnUUhpQXZJQUlnQlNnQ0JCQWVJQXhCSUdzaEdDQU9JUVlEUUNBRUtBS0lBU0FFS0FLRUFVRURkR29wQWdBaVFLY2lDa0VRZGlJWlFmOEJjU0VMSUFRb0FwZ0JJQVFvQXBRQlFRTjBhaWtDQUNKQnB5SVdRUkIySWg5Qi93RnhJUm9nQkNnQ2tBRWdCQ2dDakFGQkEzUnFLUUlBSWtKQ0lJaW5JUWNnUVVJZ2lDQkFRaUNJcHlFREFrQWdRa0lRaUtjaUNFSC9BWEVpQWtFQ1R3UkFBa0FnQWtFWlNTQS9Rb0dBZ0JCVWNrVUVRQ0FFUVNBZ0JDZ0NkQ0lJYXlJUklBSWdBaUFSU3hzaUZ5QUlhallDZENBSElBUW9BbkFnQ0hSQkFDQVhhM1lnQWlBWGF5SVhkR29oQ0NBRVFmQUFhaEFQR2lBQ0lCRk5EUUVnQkNBRUtBSjBJZ0lnRjJvMkFuUWdCQ2dDY0NBQ2RFRUFJQmRyZGlBSWFpRUlEQUVMSUFRZ0FpQUVLQUowSWhGcU5nSjBJQVFvQW5BZ0VYUkJBQ0FJYTNZZ0Iyb2hDQ0FFUWZBQWFoQVBHZ3NnQkNrQ25BRWhSQ0FFSUFnMkFwd0JJQVFnUkRjQ29BRU1BUXNDUUNBQ1JRUkFJQU1FUUNBRUtBS2NBU0VJREFNTElBUW9BcUFCSVFnTUFRc2dCQ0FFS0FKMElnSkJBV28yQW5RQ2Z5QUhJQU5GYWlBRUtBSndJQUowUVI5MmFpSUNRUU5HQkVBZ0JDZ0NuQUZCQVdzTUFRc2dBa0VDZENBRWFpZ0NuQUVMSWdkRklBZHFJUWdnQWtFQlJ3UkFJQVFnQkNnQ29BRTJBcVFCQ3dzZ0JDQUVLQUtjQVRZQ29BRWdCQ0FJTmdLY0FRdW5JUUlnUVVLQWdQd0hnMUJGQkVBZ0JDQUVLQUowSWdjZ0dtbzJBblFnQkNnQ2NDQUhkRUVBSUI5cmRpQUNhaUVDQ3lBTElCcHFRUlJQQkVBZ0JFSHdBR29RRHhvTElFQkNnSUQ4QjROUVJRUkFJQVFnQkNnQ2RDSUhJQXRxTmdKMElBUW9BbkFnQjNSQkFDQVphM1lnQTJvaEF3c2dCRUh3QUdvUUR4b2dCQ0FFS0FKd0lnZEJBQ0FLUVJoMklnc2dCQ2dDZEdvaUdtdDJJQXRCQW5SQm9CMXFLQUlBY1NBS1FmLy9BM0ZxTmdLRUFTQUVJQm9nRmtFWWRpSUthaUlMTmdKMElBUWdDa0VDZEVHZ0hXb29BZ0FnQjBFQUlBdHJkbkVnRmtILy93TnhhallDbEFFZ0JFSHdBR29RRHhvZ0JDQkNweUlIUVJoMklnb2dCQ2dDZEdvaUN6WUNkQ0FFSUFwQkFuUkJvQjFxS0FJQUlBUW9BbkJCQUNBTGEzWnhJQWRCLy84RGNXbzJBb3dCSUFRZ0F6WUNPQ0FFSUFJMkFqd2dCQ0FJTmdKQUFrQUNRQUpBSUFRb0F0d0JJZ3NnQTJvaUZpQVFTdzBBSUFZZ0FpQURhaUlLYWlBWVN3MEFJQXBCSUdvZ0RDQUdhMDBOQVFzZ0JDQUVRVUJyS0FJQU5nSUlJQVFnQkNrRE9EY0RBQ0FHSUF3Z0JDQUVRZHdCYWlBUUlCSWdFeUFORUI4aENnd0JDeUFESUFacUlRY2dCaUFMS1FBQU53QUFJQVlnQ3lrQUNEY0FDQUpBSUFOQkVVa05BQ0FHSUFzcEFCQTNBQkFnQmlBTEtRQVlOd0FZSUFOQkVHdEJFVWdOQUNBTFFSQnFJUU1nQmtFZ2FpRUxBMEFnQ3lBREtRQVFOd0FBSUFzZ0F5a0FHRGNBQ0NBTElBTXBBQ0EzQUJBZ0N5QURLUUFvTndBWUlBTkJJR29oQXlBTFFTQnFJZ3NnQjBrTkFBc0xJQWNnQ0dzaEF5QUVJQlkyQXR3QklBY2dFbXNnQ0VrRVFDQUlJQWNnRTJ0TERRUWdEU0FOSUFNZ0Vtc2lBMm9pQ3lBQ2FrOEVRQ0FISUFzZ0FoQUtHZ3dDQ3lBSElBdEJBQ0FEYXhBS0lBUWdBaUFEYWlJQ05nSThJQU5ySVFjZ0VpRURDeUFJUVJCUEJFQWdCeUFES1FBQU53QUFJQWNnQXlrQUNEY0FDQ0FDUVJGSURRRWdBaUFIYWlFSUlBZEJFR29oQWdOQUlBSWdBeWtBRURjQUFDQUNJQU1wQUJnM0FBZ2dBaUFES1FBZ053QVFJQUlnQXlrQUtEY0FHQ0FEUVNCcUlRTWdBa0VnYWlJQ0lBaEpEUUFMREFFTEFrQWdDRUVIVFFSQUlBY2dBeTBBQURvQUFDQUhJQU10QUFFNkFBRWdCeUFETFFBQ09nQUNJQWNnQXkwQUF6b0FBeUFISUFNZ0NFRUNkQ0lJUWNBZWFpZ0NBR29pQXlnQUFEWUFCQ0FESUFoQjRCNXFLQUlBYXlFRERBRUxJQWNnQXlrQUFEY0FBQXNnQWtFSlNRMEFJQUlnQjJvaEN5QUhRUWhxSWdnZ0EwRUlhaUlEYTBFUFRBUkFBMEFnQ0NBREtRQUFOd0FBSUFOQkNHb2hBeUFJUVFocUlnZ2dDMGtOQUF3Q0N3QUxJQWdnQXlrQUFEY0FBQ0FJSUFNcEFBZzNBQWdnQWtFWlNBMEFJQWRCR0dvaEFnTkFJQUlnQXlrQUVEY0FBQ0FDSUFNcEFCZzNBQWdnQWlBREtRQWdOd0FRSUFJZ0F5a0FLRGNBR0NBRFFTQnFJUU1nQWtFZ2FpSUNJQXRKRFFBTEN5QUtRWWgvU3dSQUlBb2hDUXdEQ3lBR0lBcHFJUVlnQkVId0FHb1FEeUVESUE5QkFXc2lEdzBBQzBFQUlRSWdBMEVDU1EwQkEwQWdBa0VEUndSQUlBVWdBa0VDZENJRGFrR3MwQUZxSUFNZ0JHb29BcHdCTmdJQUlBSkJBV29oQWd3QkN3c2dCQ2dDM0FFaEF3dEJ1bjhoQ1NBUUlBTnJJZ0lnRENBR2Ewc05BQ0FHQkg4Z0JpQURJQUlRQWlBQ2FnVkJBQXNnRG1zaENRc2dDVUdJZjBzTkJnc0NRQ0FGS0FMczZnRkZEUUFnQlNBRktRT0k2Z0VnQ2ExOE53T0k2Z0VDUUNBRktBTFE2Z0VpQWlBSmFpSUlRUjlOQkVBZ0RrVU5BU0FDSUNKcUlBNGdDUkFDR2lBRktBTFE2Z0VnQ1dvaENBd0JDeUFPSVFNZ0FnUkFJQUlnSW1vZ0EwRWdJQUpyRUFJYUlBVW9BdERxQVNFQ0lBVkJBRFlDME9vQklBVWdCU2tEa09vQklBVXBBTERxQVVMUDF0Tyswc2VyMlVKK2ZFSWZpVUtIbGErdm1MYmVtNTUvZmpjRGtPb0JJQVVnQlNrRG1Pb0JJQVVwQUxqcUFVTFAxdE8rMHNlcjJVSitmRUlmaVVLSGxhK3ZtTGJlbTU1L2ZqY0RtT29CSUFVZ0JTa0RvT29CSUFVcEFNRHFBVUxQMXRPKzBzZXIyVUorZkVJZmlVS0hsYSt2bUxiZW01NS9mamNEb09vQklBVWdCU2tEcU9vQklBVXBBTWpxQVVMUDF0Tyswc2VyMlVKK2ZFSWZpVUtIbGErdm1MYmVtNTUvZmpjRHFPb0JJQU1nQW10QklHb2hBd3NnQ1NBT2FpSUNJQU5CSUdwUEJFQWdBa0VnYXlFR0lBVXBBNmpxQVNFL0lBVXBBNkRxQVNGQUlBVXBBNWpxQVNGQklBVXBBNURxQVNGQ0EwQWdBeWtBR0VMUDF0Tyswc2VyMlVKK0lEOThRaCtKUW9lVnI2K1l0dDZibm45K0lUOGdBeWtBRUVMUDF0Tyswc2VyMlVKK0lFQjhRaCtKUW9lVnI2K1l0dDZibm45K0lVQWdBeWtBQ0VMUDF0Tyswc2VyMlVKK0lFRjhRaCtKUW9lVnI2K1l0dDZibm45K0lVRWdBeWtBQUVMUDF0Tyswc2VyMlVKK0lFSjhRaCtKUW9lVnI2K1l0dDZibm45K0lVSWdBMEVnYWlJRElBWk5EUUFMSUFVZ1B6Y0RxT29CSUFVZ1FEY0RvT29CSUFVZ1FUY0RtT29CSUFVZ1FqY0RrT29CQ3lBQ0lBTk5EUUVnSWlBRElBSWdBMnNpQ0JBQ0dnc2dCU0FJTmdMUTZnRUxJRFVnRldzaEF5QVZJQnRxSVFJZ0NTQU9haUVPSUFRb0FqQkZEUUFMSUNrcEF3QWlQMEovVVNBL0lBNGdIV3VzVVhKRkJFQkJiQ0VKREFZTElBVW9BdURwQVFSQVFXb2hDU0FEUVFSSkRRWWdCU2dDNk9vQlJRUkFJQ0lnQlNnQzBPb0JhaUVLQW40Z0JTa0RpT29CSWo5Q0lGb0VRQ0FGS1FPWTZnRWlRRUlIaVNBRktRT1E2Z0VpUVVJQmlYd2dCU2tEb09vQklrSkNESWw4SUFVcEE2anFBU0pEUWhLSmZDQkJRcy9XMDc3U3g2dlpRbjVDSDRsQ2g1V3ZyNWkyM3B1ZWYzNkZRb2VWcjYrWXR0NmJubjkrUXAyanRlcURzWTJLK2dCOUlFQkN6OWJUdnRMSHE5bENma0lmaVVLSGxhK3ZtTGJlbTU1L2ZvVkNoNVd2cjVpMjNwdWVmMzVDbmFPMTZvT3hqWXI2QUgwZ1FrTFAxdE8rMHNlcjJVSitRaCtKUW9lVnI2K1l0dDZibm45K2hVS0hsYSt2bUxiZW01NS9ma0tkbzdYcWc3R05pdm9BZlNCRFFzL1cwNzdTeDZ2WlFuNUNINGxDaDVXdnI1aTIzcHVlZjM2RlFvZVZyNitZdHQ2Ym5uOStRcDJqdGVxRHNZMksrZ0I5REFFTElBVXBBNkRxQVVMRno5bXk4ZVc2NmlkOEN5QS9mQ0UvSUNJaEJnTkFJQW9nQmtFSWFpSUhUd1JBSUFZcEFBQkN6OWJUdnRMSHE5bENma0lmaVVLSGxhK3ZtTGJlbTU1L2ZpQS9oVUliaVVLSGxhK3ZtTGJlbTU1L2ZrS2RvN1hxZzdHTml2b0FmU0UvSUFjaEJnd0JDd3NDUUNBS0lBWkJCR29pQ0VrRVFDQUdJUWdNQVFzZ0JqVUFBRUtIbGErdm1MYmVtNTUvZmlBL2hVSVhpVUxQMXRPKzBzZXIyVUorUXZuejNmR1o5cG1yRm53aFB3c0RRQ0FJSUFwSkJFQWdDREVBQUVMRno5bXk4ZVc2NmlkK0lEK0ZRZ3VKUW9lVnI2K1l0dDZibm45K0lUOGdDRUVCYWlFSURBRUxDeUFDS0FBQUlEOUNJWWdnUDRWQ3o5YlR2dExIcTlsQ2ZpSS9RaDJJSUQrRlF2bnozZkdaOXBtckZuNGlQMElnaUNBL2hhZEhEUWNMSUFOQkJHc2hBeUFDUVFScUlRSUxJQTRnSFdzaUNVR0pmMDhOQkNBQklBbHJJUUVnQ1NBZGFpRWRRUUVoUGd3QkN3dEJ1SDhoQnlBRERRUWdIU0FBYXlFSERBUUxRV3doQ1F3QkMwRzRmeUVKQzBHNGZ5RUhJQWxCZGtZZ1BuRU5BUXNnQ1NFSEN5Z0NBQTBBSUFWQi9Pb0JhaWdDQUNFQklBVkIrT29CYWlnQ0FDRUFJQVVRR0NBRktBS3c2d0VnQUNBQkVCTWdCVUVBTmdLdzZ3RWdCU2dDcE9zQklnSUVRQUpBQWtBQ1FBSkFJQUlvQWdBaUF3UkFJQUJGRFFJZ0FTQURJQUFSQWdBTUFRc2dBRVVOQWdzZ0FTQUNJQUFSQWdBTUFnc2dBeEFHQ3lBQ0VBWUxJQVZCQURZQ3BPc0JDeUFBQkVBZ0FTQUZJQUFSQWdBTUFRc2dCUkFHQ3lBRVFlQUJhaVFBSUFjTEM2Z1ZDUUJCaUFnTERRRUFBQUFCQUFBQUFnQUFBQUlBUWFBSUM3TUdBUUFBQUFFQUFBQUNBQUFBQWdBQUFDWUFBQUNDQUFBQUlRVUFBRW9BQUFCbkNBQUFKZ0FBQU1BQkFBQ0FBQUFBU1FVQUFFb0FBQUMrQ0FBQUtRQUFBQ3dDQUFDQUFBQUFTUVVBQUVvQUFBQytDQUFBTHdBQUFNb0NBQUNBQUFBQWlnVUFBRW9BQUFDRUNRQUFOUUFBQUhNREFBQ0FBQUFBblFVQUFFb0FBQUNnQ1FBQVBRQUFBSUVEQUFDQUFBQUE2d1VBQUVzQUFBQStDZ0FBUkFBQUFKNERBQUNBQUFBQVRRWUFBRXNBQUFDcUNnQUFTd0FBQUxNREFBQ0FBQUFBd1FZQUFFMEFBQUFmRFFBQVRRQUFBRk1FQUFDQUFBQUFJd2dBQUZFQUFBQ21Ed0FBVkFBQUFKa0VBQUNBQUFBQVN3a0FBRmNBQUFDeEVnQUFXQUFBQU5vRUFBQ0FBQUFBYndrQUFGMEFBQUFqRkFBQVZBQUFBRVVGQUFDQUFBQUFWQW9BQUdvQUFBQ01GQUFBYWdBQUFLOEZBQUNBQUFBQWRna0FBSHdBQUFCT0VBQUFmQUFBQU5JQ0FBQ0FBQUFBWXdjQUFKRUFBQUNRQndBQWtnQUFBQUFBQUFBQkFBQUFBUUFBQUFVQUFBQU5BQUFBSFFBQUFEMEFBQUI5QUFBQS9RQUFBUDBCQUFEOUF3QUEvUWNBQVAwUEFBRDlId0FBL1Q4QUFQMS9BQUQ5L3dBQS9mOEJBUDMvQXdEOS93Y0EvZjhQQVAzL0h3RDkvejhBL2Y5L0FQMy8vd0Q5Ly84Qi9mLy9BLzMvL3dmOS8vOFAvZi8vSC8zLy96LzkvLzkvQUFBQUFBRUFBQUFDQUFBQUF3QUFBQVFBQUFBRkFBQUFCZ0FBQUFjQUFBQUlBQUFBQ1FBQUFBb0FBQUFMQUFBQURBQUFBQTBBQUFBT0FBQUFEd0FBQUJBQUFBQVJBQUFBRWdBQUFCTUFBQUFVQUFBQUZRQUFBQllBQUFBWEFBQUFHQUFBQUJrQUFBQWFBQUFBR3dBQUFCd0FBQUFkQUFBQUhnQUFBQjhBQUFBREFBQUFCQUFBQUFVQUFBQUdBQUFBQndBQUFBZ0FBQUFKQUFBQUNnQUFBQXNBQUFBTUFBQUFEUUFBQUE0QUFBQVBBQUFBRUFBQUFCRUFBQUFTQUFBQUV3QUFBQlFBQUFBVkFBQUFGZ0FBQUJjQUFBQVlBQUFBR1FBQUFCb0FBQUFiQUFBQUhBQUFBQjBBQUFBZUFBQUFId0FBQUNBQUFBQWhBQUFBSWdBQUFDTUFBQUFsQUFBQUp3QUFBQ2tBQUFBckFBQUFMd0FBQURNQUFBQTdBQUFBUXdBQUFGTUFBQUJqQUFBQWd3QUFBQU1CQUFBREFnQUFBd1FBQUFNSUFBQURFQUFBQXlBQUFBTkFBQUFEZ0FBQUF3QUJBRUhnRHd0UkFRQUFBQUVBQUFBQkFBQUFBUUFBQUFJQUFBQUNBQUFBQXdBQUFBTUFBQUFFQUFBQUJBQUFBQVVBQUFBSEFBQUFDQUFBQUFrQUFBQUtBQUFBQ3dBQUFBd0FBQUFOQUFBQURnQUFBQThBQUFBUUFFSEVFQXVMQVFFQUFBQUNBQUFBQXdBQUFBUUFBQUFGQUFBQUJnQUFBQWNBQUFBSUFBQUFDUUFBQUFvQUFBQUxBQUFBREFBQUFBMEFBQUFPQUFBQUR3QUFBQkFBQUFBU0FBQUFGQUFBQUJZQUFBQVlBQUFBSEFBQUFDQUFBQUFvQUFBQU1BQUFBRUFBQUFDQUFBQUFBQUVBQUFBQ0FBQUFCQUFBQUFnQUFBQVFBQUFBSUFBQUFFQUFBQUNBQUFBQUFBRUFRWkFTQytZRUFRQUFBQUVBQUFBQkFBQUFBUUFBQUFJQUFBQUNBQUFBQXdBQUFBTUFBQUFFQUFBQUJnQUFBQWNBQUFBSUFBQUFDUUFBQUFvQUFBQUxBQUFBREFBQUFBMEFBQUFPQUFBQUR3QUFBQkFBQUFBQkFBQUFCQUFBQUFnQUFBQUFBQUFBQVFBQkFRWUFBQUFBQUFBRUFBQUFBQkFBQUFRQUFBQUFJQUFBQlFFQUFBQUFBQUFGQXdBQUFBQUFBQVVFQUFBQUFBQUFCUVlBQUFBQUFBQUZCd0FBQUFBQUFBVUpBQUFBQUFBQUJRb0FBQUFBQUFBRkRBQUFBQUFBQUFZT0FBQUFBQUFCQlJBQUFBQUFBQUVGRkFBQUFBQUFBUVVXQUFBQUFBQUNCUndBQUFBQUFBTUZJQUFBQUFBQUJBVXdBQUFBSUFBR0JVQUFBQUFBQUFjRmdBQUFBQUFBQ0FZQUFRQUFBQUFLQmdBRUFBQUFBQXdHQUJBQUFDQUFBQVFBQUFBQUFBQUFCQUVBQUFBQUFBQUZBZ0FBQUNBQUFBVUVBQUFBQUFBQUJRVUFBQUFnQUFBRkJ3QUFBQUFBQUFVSUFBQUFJQUFBQlFvQUFBQUFBQUFGQ3dBQUFBQUFBQVlOQUFBQUlBQUJCUkFBQUFBQUFBRUZFZ0FBQUNBQUFRVVdBQUFBQUFBQ0JSZ0FBQUFnQUFNRklBQUFBQUFBQXdVb0FBQUFBQUFHQkVBQUFBQVFBQVlFUUFBQUFDQUFCd1dBQUFBQUFBQUpCZ0FDQUFBQUFBc0dBQWdBQURBQUFBUUFBQUFBRUFBQUJBRUFBQUFnQUFBRkFnQUFBQ0FBQUFVREFBQUFJQUFBQlFVQUFBQWdBQUFGQmdBQUFDQUFBQVVJQUFBQUlBQUFCUWtBQUFBZ0FBQUZDd0FBQUNBQUFBVU1BQUFBQUFBQUJnOEFBQUFnQUFFRkVnQUFBQ0FBQVFVVUFBQUFJQUFDQlJnQUFBQWdBQUlGSEFBQUFDQUFBd1VvQUFBQUlBQUVCVEFBQUFBQUFCQUdBQUFCQUFBQUR3WUFnQUFBQUFBT0JnQkFBQUFBQUEwR0FDQUFRWUFYQzRjQ0FRQUJBUVVBQUFBQUFBQUZBQUFBQUFBQUJnUTlBQUFBQUFBSkJmMEJBQUFBQUE4Ri9YOEFBQUFBRlFYOS94OEFBQUFEQlFVQUFBQUFBQWNFZlFBQUFBQUFEQVg5RHdBQUFBQVNCZjMvQXdBQUFCY0YvZjkvQUFBQUJRVWRBQUFBQUFBSUJQMEFBQUFBQUE0Ri9UOEFBQUFBRkFYOS93OEFBQUFDQlFFQUFBQVFBQWNFZlFBQUFBQUFDd1g5QndBQUFBQVJCZjMvQVFBQUFCWUYvZjgvQUFBQUJBVU5BQUFBRUFBSUJQMEFBQUFBQUEwRi9SOEFBQUFBRXdYOS93Y0FBQUFCQlFFQUFBQVFBQVlFUFFBQUFBQUFDZ1g5QXdBQUFBQVFCZjMvQUFBQUFCd0YvZi8vRHdBQUd3WDkvLzhIQUFBYUJmMy8vd01BQUJrRi9mLy9BUUFBR0FYOS8vOEFRWkFaQzRZRUFRQUJBUVlBQUFBQUFBQUdBd0FBQUFBQUFBUUVBQUFBSUFBQUJRVUFBQUFBQUFBRkJnQUFBQUFBQUFVSUFBQUFBQUFBQlFrQUFBQUFBQUFGQ3dBQUFBQUFBQVlOQUFBQUFBQUFCaEFBQUFBQUFBQUdFd0FBQUFBQUFBWVdBQUFBQUFBQUJoa0FBQUFBQUFBR0hBQUFBQUFBQUFZZkFBQUFBQUFBQmlJQUFBQUFBQUVHSlFBQUFBQUFBUVlwQUFBQUFBQUNCaThBQUFBQUFBTUdPd0FBQUFBQUJBWlRBQUFBQUFBSEJvTUFBQUFBQUFrR0F3SUFBQkFBQUFRRUFBQUFBQUFBQkFVQUFBQWdBQUFGQmdBQUFBQUFBQVVIQUFBQUlBQUFCUWtBQUFBQUFBQUZDZ0FBQUFBQUFBWU1BQUFBQUFBQUJnOEFBQUFBQUFBR0VnQUFBQUFBQUFZVkFBQUFBQUFBQmhnQUFBQUFBQUFHR3dBQUFBQUFBQVllQUFBQUFBQUFCaUVBQUFBQUFBRUdJd0FBQUFBQUFRWW5BQUFBQUFBQ0Jpc0FBQUFBQUFNR013QUFBQUFBQkFaREFBQUFBQUFGQm1NQUFBQUFBQWdHQXdFQUFDQUFBQVFFQUFBQU1BQUFCQVFBQUFBUUFBQUVCUUFBQUNBQUFBVUhBQUFBSUFBQUJRZ0FBQUFnQUFBRkNnQUFBQ0FBQUFVTEFBQUFBQUFBQmc0QUFBQUFBQUFHRVFBQUFBQUFBQVlVQUFBQUFBQUFCaGNBQUFBQUFBQUdHZ0FBQUFBQUFBWWRBQUFBQUFBQUJpQUFBQUFBQUJBR0F3QUJBQUFBRHdZRGdBQUFBQUFPQmdOQUFBQUFBQTBHQXlBQUFBQUFEQVlERUFBQUFBQUxCZ01JQUFBQUFBb0dBd1FBUWFRZEM5a0JBUUFBQUFNQUFBQUhBQUFBRHdBQUFCOEFBQUEvQUFBQWZ3QUFBUDhBQUFEL0FRQUEvd01BQVA4SEFBRC9Ed0FBL3g4QUFQOC9BQUQvZndBQS8vOEFBUC8vQVFELy93TUEvLzhIQVAvL0R3RC8veDhBLy84L0FQLy9md0QvLy84QS8vLy9BZi8vL3dQLy8vOEgvLy8vRC8vLy94Ly8vLzgvLy8vL2Z3QUFBQUFCQUFBQUFnQUFBQVFBQUFBQUFBQUFBZ0FBQUFRQUFBQUlBQUFBQUFBQUFBRUFBQUFDQUFBQUFRQUFBQVFBQUFBRUFBQUFCQUFBQUFRQUFBQUlBQUFBQ0FBQUFBZ0FBQUFIQUFBQUNBQUFBQWtBQUFBS0FBQUFDd0JCZ0I4TEE0QVJBUT09Ijt2YXIgT3Q9bmV3IHdBLFR0PSExO2FzeW5jIGZ1bmN0aW9uIGNlKEEsdCxJKXtsZXQgZT1udWxsO3R5cGVvZiBBIT0ic3RyaW5nIj9lPUEuaHJlZjpBLnN0YXJ0c1dpdGgoImh0dHAiKT9lPUE6ZT1gJHt0fS8ke0F9YCxlLmVuZHNXaXRoKCIuanMiKSYmKGU9ZS5zdWJzdHJpbmcoMCxlLmxlbmd0aC0zKSksZS5lbmRzV2l0aCgiLndhc20iKSYmKGU9ZS5zdWJzdHJpbmcoMCxlLmxlbmd0aC01KSk7bGV0IGc9YCR7ZX0ud2FzbWAscj1hd2FpdCB5QS5nZXQoYCR7Z30uenN0YCx7cmVzcG9uc2VUeXBlOiJhcnJheWJ1ZmZlciIscGFyYW1zOkl9KTtUdHx8KGF3YWl0IE90LmluaXQoKSxUdD0hMCk7bGV0IG49T3QuZGVjb2RlKG5ldyBVaW50OEFycmF5KHIuZGF0YSkpLmJ1ZmZlcjtyZXR1cm4oYXdhaXQgaW1wb3J0KGAke2V9LmpzYCkpLmRlZmF1bHQoe3dhc21CaW5hcnk6bn0pfXZhciBQdD1jZTt2YXIgbUE9bmV3IE1hcDthc3luYyBmdW5jdGlvbiBmZShBLHQsSSl7bGV0IGU9QSxnPUEscj1udWxsO3JldHVybiB0eXBlb2YgQSE9InN0cmluZyImJihlPW5ldyBVUkwoQS5ocmVmKSxnPWUuaHJlZiksbUEuaGFzKGcpP3I9YXdhaXQgbUEuZ2V0KGcpOihtQS5zZXQoZyxQdChlLHQsSSkpLHI9YXdhaXQgbUEuZ2V0KGcpKSxyfXZhciB4dD1mZTt2YXIgbGU9e1RleHRGaWxlOiJUZXh0RmlsZSIsQmluYXJ5RmlsZToiQmluYXJ5RmlsZSIsVGV4dFN0cmVhbToiVGV4dFN0cmVhbSIsQmluYXJ5U3RyZWFtOiJCaW5hcnlTdHJlYW0iLEltYWdlOiJJbWFnZSIsUG9pbnRTZXQ6IlBvaW50U2V0IixNZXNoOiJNZXNoIixQb2x5RGF0YToiUG9seURhdGEiLFRyYW5zZm9ybUxpc3Q6IlRyYW5zZm9ybUxpc3QiLEpzb25Db21wYXRpYmxlOiJKc29uQ29tcGF0aWJsZSJ9LEQ9bGU7dmFyIERlPXtJbnQ4OiJpbnQ4IixVSW50ODoidWludDgiLEludDE2OiJpbnQxNiIsVUludDE2OiJ1aW50MTYiLEludDMyOiJpbnQzMiIsVUludDMyOiJ1aW50MzIiLEludDY0OiJpbnQ2NCIsVUludDY0OiJ1aW50NjQiLFNpemVWYWx1ZVR5cGU6InVpbnQ2NCIsSWRlbnRpZmllclR5cGU6InVpbnQ2NCIsSW5kZXhWYWx1ZVR5cGU6ImludDY0IixPZmZzZXRWYWx1ZVR5cGU6ImludDY0In0sUz1EZTt2YXIgdWU9e0Zsb2F0MzI6ImZsb2F0MzIiLEZsb2F0NjQ6ImZsb2F0NjQiLFNwYWNlUHJlY2lzaW9uVHlwZToiZmxvYXQ2NCJ9LGo9dWU7ZnVuY3Rpb24gaGUoQSx0KXtsZXQgST1udWxsO3N3aXRjaChBKXtjYXNlIFMuVUludDg6e0k9bmV3IFVpbnQ4QXJyYXkodCk7YnJlYWt9Y2FzZSBTLkludDg6e0k9bmV3IEludDhBcnJheSh0KTticmVha31jYXNlIFMuVUludDE2OntJPW5ldyBVaW50MTZBcnJheSh0KTticmVha31jYXNlIFMuSW50MTY6e0k9bmV3IEludDE2QXJyYXkodCk7YnJlYWt9Y2FzZSBTLlVJbnQzMjp7ST1uZXcgVWludDMyQXJyYXkodCk7YnJlYWt9Y2FzZSBTLkludDMyOntJPW5ldyBJbnQzMkFycmF5KHQpO2JyZWFrfWNhc2UgUy5VSW50NjQ6e3R5cGVvZiBnbG9iYWxUaGlzLkJpZ1VpbnQ2NEFycmF5PT0iZnVuY3Rpb24iP0k9bmV3IEJpZ1VpbnQ2NEFycmF5KHQpOkk9bmV3IFVpbnQ4QXJyYXkodCk7YnJlYWt9Y2FzZSBTLkludDY0Ont0eXBlb2YgZ2xvYmFsVGhpcy5CaWdJbnQ2NEFycmF5PT0iZnVuY3Rpb24iP0k9bmV3IEJpZ0ludDY0QXJyYXkodCk6ST1uZXcgVWludDhBcnJheSh0KTticmVha31jYXNlIGouRmxvYXQzMjp7ST1uZXcgRmxvYXQzMkFycmF5KHQpO2JyZWFrfWNhc2Ugai5GbG9hdDY0OntJPW5ldyBGbG9hdDY0QXJyYXkodCk7YnJlYWt9Y2FzZSJudWxsIjp7ST1udWxsO2JyZWFrfWNhc2UgbnVsbDp7ST1udWxsO2JyZWFrfWRlZmF1bHQ6dGhyb3cgbmV3IEVycm9yKCJUeXBlIGlzIG5vdCBzdXBwb3J0ZWQgYXMgYSBUeXBlZEFycmF5Iil9cmV0dXJuIEl9dmFyIEc9aGU7dmFyIFp0PXR5cGVvZiBnbG9iYWxUaGlzLlNoYXJlZEFycmF5QnVmZmVyPT0iZnVuY3Rpb24iLGp0PW5ldyBUZXh0RW5jb2RlcixXdD1uZXcgVGV4dERlY29kZXIoInV0Zi04Iik7ZnVuY3Rpb24gZGUoQSx0KXtsZXQgST17ZmxhZ3M6InIiLGVuY29kaW5nOiJiaW5hcnkifSxlPUEuZnNfb3Blbih0LEkuZmxhZ3MpLHI9QS5mc19zdGF0KHQpLnNpemUsbz1udWxsO1p0P289bmV3IFNoYXJlZEFycmF5QnVmZmVyKHIpOm89bmV3IEFycmF5QnVmZmVyKHIpO2xldCBuPW5ldyBVaW50OEFycmF5KG8pO3JldHVybiBBLmZzX3JlYWQoZSxuLDAsciwwKSxBLmZzX2Nsb3NlKGUpLG59ZnVuY3Rpb24gVnQoQSx0LEkpe2xldCBlPW51bGw7WnQ/ZT1uZXcgU2hhcmVkQXJyYXlCdWZmZXIoSSk6ZT1uZXcgQXJyYXlCdWZmZXIoSSk7bGV0IGc9bmV3IFVpbnQ4QXJyYXkoZSkscj1uZXcgVWludDhBcnJheShBLkhFQVBVOC5idWZmZXIsdCxJKTtyZXR1cm4gZy5zZXQociksZ31mdW5jdGlvbiBkKEEsdCxJLGUpe2xldCBnPTA7cmV0dXJuIHQhPT1udWxsJiYoZz1BLmNjYWxsKCJpdGtfd2FzbV9pbnB1dF9hcnJheV9hbGxvYyIsIm51bWJlciIsWyJudW1iZXIiLCJudW1iZXIiLCJudW1iZXIiLCJudW1iZXIiXSxbMCxJLGUsdC5idWZmZXIuYnl0ZUxlbmd0aF0pLEEuSEVBUFU4LnNldChuZXcgVWludDhBcnJheSh0LmJ1ZmZlciksZykpLGd9ZnVuY3Rpb24gYihBLHQsSSl7bGV0IGU9SlNPTi5zdHJpbmdpZnkodCksZz1BLmxlbmd0aEJ5dGVzVVRGOChlKSsxLHI9QS5jY2FsbCgiaXRrX3dhc21faW5wdXRfanNvbl9hbGxvYyIsIm51bWJlciIsWyJudW1iZXIiLCJudW1iZXIiLCJudW1iZXIiXSxbMCxJLGddKTtBLnN0cmluZ1RvVVRGOChlLHIsZyl9ZnVuY3Rpb24gdyhBLHQsSSxlKXtsZXQgZz1BLmNjYWxsKCJpdGtfd2FzbV9vdXRwdXRfYXJyYXlfYWRkcmVzcyIsIm51bWJlciIsWyJudW1iZXIiLCJudW1iZXIiLCJudW1iZXIiXSxbMCx0LEldKSxyPUEuY2NhbGwoIml0a193YXNtX291dHB1dF9hcnJheV9zaXplIiwibnVtYmVyIixbIm51bWJlciIsIm51bWJlciIsIm51bWJlciJdLFswLHQsSV0pLG89VnQoQSxnLHIpO3JldHVybiBHKGUsby5idWZmZXIpfWZ1bmN0aW9uIElBKEEsdCl7bGV0IEk9QS5jY2FsbCgiaXRrX3dhc21fb3V0cHV0X2pzb25fYWRkcmVzcyIsIm51bWJlciIsWyJudW1iZXIiLCJudW1iZXIiXSxbMCx0XSksZT1BLlVURjhUb1N0cmluZyhJKTtyZXR1cm4gSlNPTi5wYXJzZShlKX1mdW5jdGlvbiB5ZShBLHQsSSxlKXtlIT1udWxsJiZlLmxlbmd0aD4wJiZlLmZvckVhY2goZnVuY3Rpb24oUSxCKXtzd2l0Y2goUS50eXBlKXtjYXNlIEQuVGV4dFN0cmVhbTp7bGV0IGk9anQuZW5jb2RlKFEuZGF0YS5kYXRhKSxmPWQoQSxpLEIsMCkscz17c2l6ZTppLmJ1ZmZlci5ieXRlTGVuZ3RoLGRhdGE6YGRhdGE6YXBwbGljYXRpb24vdm5kLml0ay5hZGRyZXNzLDA6JHtmfWB9O2IoQSxzLEIpO2JyZWFrfWNhc2UgRC5Kc29uQ29tcGF0aWJsZTp7bGV0IGk9anQuZW5jb2RlKEpTT04uc3RyaW5naWZ5KFEuZGF0YSkpLGY9ZChBLGksQiwwKSxzPXtzaXplOmkuYnVmZmVyLmJ5dGVMZW5ndGgsZGF0YTpgZGF0YTphcHBsaWNhdGlvbi92bmQuaXRrLmFkZHJlc3MsMDoke2Z9YH07YihBLHMsQik7YnJlYWt9Y2FzZSBELkJpbmFyeVN0cmVhbTp7bGV0IGk9US5kYXRhLmRhdGEsZj1kKEEsaSxCLDApLHM9e3NpemU6aS5idWZmZXIuYnl0ZUxlbmd0aCxkYXRhOmBkYXRhOmFwcGxpY2F0aW9uL3ZuZC5pdGsuYWRkcmVzcywwOiR7Zn1gfTtiKEEscyxCKTticmVha31jYXNlIEQuVGV4dEZpbGU6e0EuZnNfd3JpdGVGaWxlKFEuZGF0YS5wYXRoLFEuZGF0YS5kYXRhKTticmVha31jYXNlIEQuQmluYXJ5RmlsZTp7QS5mc193cml0ZUZpbGUoUS5kYXRhLnBhdGgsUS5kYXRhLmRhdGEpO2JyZWFrfWNhc2UgRC5JbWFnZTp7bGV0IGk9US5kYXRhLGY9ZChBLGkuZGF0YSxCLDApLHM9ZChBLGkuZGlyZWN0aW9uLEIsMSksYT10eXBlb2YgaS5tZXRhZGF0YT8uZW50cmllczwidSI/QXJyYXkuZnJvbShpLm1ldGFkYXRhLmVudHJpZXMoKSk6W10sRT17aW1hZ2VUeXBlOmkuaW1hZ2VUeXBlLG5hbWU6aS5uYW1lLG9yaWdpbjppLm9yaWdpbixzcGFjaW5nOmkuc3BhY2luZyxkaXJlY3Rpb246YGRhdGE6YXBwbGljYXRpb24vdm5kLml0ay5hZGRyZXNzLDA6JHtzfWAsc2l6ZTppLnNpemUsZGF0YTpgZGF0YTphcHBsaWNhdGlvbi92bmQuaXRrLmFkZHJlc3MsMDoke2Z9YCxtZXRhZGF0YTphfTtiKEEsRSxCKTticmVha31jYXNlIEQuTWVzaDp7bGV0IGk9US5kYXRhLGY9ZChBLGkucG9pbnRzLEIsMCkscz1kKEEsaS5jZWxscyxCLDEpLGE9ZChBLGkucG9pbnREYXRhLEIsMiksRT1kKEEsaS5jZWxsRGF0YSxCLDMpLHU9e21lc2hUeXBlOmkubWVzaFR5cGUsbmFtZTppLm5hbWUsbnVtYmVyT2ZQb2ludHM6aS5udW1iZXJPZlBvaW50cyxwb2ludHM6YGRhdGE6YXBwbGljYXRpb24vdm5kLml0ay5hZGRyZXNzLDA6JHtmfWAsbnVtYmVyT2ZDZWxsczppLm51bWJlck9mQ2VsbHMsY2VsbHM6YGRhdGE6YXBwbGljYXRpb24vdm5kLml0ay5hZGRyZXNzLDA6JHtzfWAsY2VsbEJ1ZmZlclNpemU6aS5jZWxsQnVmZmVyU2l6ZSxudW1iZXJPZlBvaW50UGl4ZWxzOmkubnVtYmVyT2ZQb2ludFBpeGVscyxwb2ludERhdGE6YGRhdGE6YXBwbGljYXRpb24vdm5kLml0ay5hZGRyZXNzLDA6JHthfWAsbnVtYmVyT2ZDZWxsUGl4ZWxzOmkubnVtYmVyT2ZDZWxsUGl4ZWxzLGNlbGxEYXRhOmBkYXRhOmFwcGxpY2F0aW9uL3ZuZC5pdGsuYWRkcmVzcywwOiR7RX1gfTtiKEEsdSxCKTticmVha31jYXNlIEQuUG9pbnRTZXQ6e2xldCBpPVEuZGF0YSxmPWQoQSxpLnBvaW50cyxCLDApLHM9ZChBLGkucG9pbnREYXRhLEIsMSksYT17cG9pbnRTZXRUeXBlOmkucG9pbnRTZXRUeXBlLG5hbWU6aS5uYW1lLG51bWJlck9mUG9pbnRzOmkubnVtYmVyT2ZQb2ludHMscG9pbnRzOmBkYXRhOmFwcGxpY2F0aW9uL3ZuZC5pdGsuYWRkcmVzcywwOiR7Zn1gLG51bWJlck9mUG9pbnRQaXhlbHM6aS5udW1iZXJPZlBvaW50UGl4ZWxzLHBvaW50RGF0YTpgZGF0YTphcHBsaWNhdGlvbi92bmQuaXRrLmFkZHJlc3MsMDoke3N9YH07YihBLGEsQik7YnJlYWt9Y2FzZSBELlRyYW5zZm9ybUxpc3Q6e2xldCBpPVEuZGF0YSxmPVtdO2kuZm9yRWFjaCgocyxhKT0+e2xldCB1PWBkYXRhOmFwcGxpY2F0aW9uL3ZuZC5pdGsuYWRkcmVzcywwOiR7ZChBLHMuZml4ZWRQYXJhbWV0ZXJzLEIsYSoyKX1gLEY9YGRhdGE6YXBwbGljYXRpb24vdm5kLml0ay5hZGRyZXNzLDA6JHtkKEEscy5wYXJhbWV0ZXJzLEIsYSoyKzEpfWAsUj17dHJhbnNmb3JtVHlwZTpzLnRyYW5zZm9ybVR5cGUsbnVtYmVyT2ZGaXhlZFBhcmFtZXRlcnM6cy5udW1iZXJPZkZpeGVkUGFyYW1ldGVycyxudW1iZXJPZlBhcmFtZXRlcnM6cy5udW1iZXJPZlBhcmFtZXRlcnMsbmFtZTpzLm5hbWUsaW5wdXRTcGFjZU5hbWU6cy5pbnB1dFNwYWNlTmFtZSxvdXRwdXRTcGFjZU5hbWU6cy5vdXRwdXRTcGFjZU5hbWUscGFyYW1ldGVyczpGLGZpeGVkUGFyYW1ldGVyczp1fTtmLnB1c2goUil9KSxiKEEsZixCKTticmVha31jYXNlIEQuUG9seURhdGE6e2xldCBpPVEuZGF0YSxmPWQoQSxpLnBvaW50cyxCLDApLHM9ZChBLGkudmVydGljZXMsQiwxKSxhPWQoQSxpLmxpbmVzLEIsMiksRT1kKEEsaS5wb2x5Z29ucyxCLDMpLHU9ZChBLGkudHJpYW5nbGVTdHJpcHMsQiw0KSx5PWQoQSxpLnBvaW50RGF0YSxCLDUpLEY9ZChBLGkucG9pbnREYXRhLEIsNiksUj17cG9seURhdGFUeXBlOmkucG9seURhdGFUeXBlLG5hbWU6aS5uYW1lLG51bWJlck9mUG9pbnRzOmkubnVtYmVyT2ZQb2ludHMscG9pbnRzOmBkYXRhOmFwcGxpY2F0aW9uL3ZuZC5pdGsuYWRkcmVzcywwOiR7Zn1gLHZlcnRpY2VzQnVmZmVyU2l6ZTppLnZlcnRpY2VzQnVmZmVyU2l6ZSx2ZXJ0aWNlczpgZGF0YTphcHBsaWNhdGlvbi92bmQuaXRrLmFkZHJlc3MsMDoke3N9YCxsaW5lc0J1ZmZlclNpemU6aS5saW5lc0J1ZmZlclNpemUsbGluZXM6YGRhdGE6YXBwbGljYXRpb24vdm5kLml0ay5hZGRyZXNzLDA6JHthfWAscG9seWdvbnNCdWZmZXJTaXplOmkucG9seWdvbnNCdWZmZXJTaXplLHBvbHlnb25zOmBkYXRhOmFwcGxpY2F0aW9uL3ZuZC5pdGsuYWRkcmVzcywwOiR7RX1gLHRyaWFuZ2xlU3RyaXBzQnVmZmVyU2l6ZTppLnRyaWFuZ2xlU3RyaXBzQnVmZmVyU2l6ZSx0cmlhbmdsZVN0cmlwczpgZGF0YTphcHBsaWNhdGlvbi92bmQuaXRrLmFkZHJlc3MsMDoke3V9YCxudW1iZXJPZlBvaW50UGl4ZWxzOmkubnVtYmVyT2ZQb2ludFBpeGVscyxwb2ludERhdGE6YGRhdGE6YXBwbGljYXRpb24vdm5kLml0ay5hZGRyZXNzLDA6JHt5fWAsbnVtYmVyT2ZDZWxsUGl4ZWxzOmkubnVtYmVyT2ZDZWxsUGl4ZWxzLGNlbGxEYXRhOmBkYXRhOmFwcGxpY2F0aW9uL3ZuZC5pdGsuYWRkcmVzcywwOiR7Rn1gfTtiKEEsUixCKTticmVha31kZWZhdWx0OnRocm93IEVycm9yKCJVbnN1cHBvcnRlZCBpbnB1dCBJbnRlcmZhY2VUeXBlIil9fSksQS5yZXNldE1vZHVsZVN0ZG91dCgpLEEucmVzZXRNb2R1bGVTdGRlcnIoKTtsZXQgZz1BLnN0YWNrU2F2ZSgpLHI9MDt0cnl7cj1BLmNhbGxNYWluKHQuc2xpY2UoKSl9Y2F0Y2goUSl7dGhyb3cgdHlwZW9mIFE9PSJudW1iZXIiJiYoY29uc29sZS5sb2coIkV4Y2VwdGlvbiB3aGlsZSBydW5uaW5nIHBpcGVsaW5lOiIpLGNvbnNvbGUubG9nKCJzdGRvdXQ6IixBLmdldE1vZHVsZVN0ZG91dCgpKSxjb25zb2xlLmVycm9yKCJzdGRlcnI6IixBLmdldE1vZHVsZVN0ZGVycigpKSx0eXBlb2YgQS5nZXRFeGNlcHRpb25NZXNzYWdlPCJ1Ij9jb25zb2xlLmVycm9yKCJleGNlcHRpb246IixBLmdldEV4Y2VwdGlvbk1lc3NhZ2UoUSkpOmNvbnNvbGUuZXJyb3IoIkJ1aWxkIG1vZHVsZSBpbiBEZWJ1ZyBtb2RlIGZvciBleGNlcHRpb24gbWVzc2FnZSBpbmZvcm1hdGlvbi4iKSksUX1maW5hbGx5e0Euc3RhY2tSZXN0b3JlKGcpfWxldCBvPUEuZ2V0TW9kdWxlU3Rkb3V0KCksbj1BLmdldE1vZHVsZVN0ZGVycigpLGM9W107cmV0dXJuIEkhPW51bGwmJkkubGVuZ3RoPjAmJnI9PT0wJiZJLmZvckVhY2goZnVuY3Rpb24oUSxCKXtsZXQgaT1udWxsO3N3aXRjaChRLnR5cGUpe2Nhc2UgRC5UZXh0U3RyZWFtOntsZXQgcz1BLmNjYWxsKCJpdGtfd2FzbV9vdXRwdXRfYXJyYXlfYWRkcmVzcyIsIm51bWJlciIsWyJudW1iZXIiLCJudW1iZXIiLCJudW1iZXIiXSxbMCxCLDBdKSxhPUEuY2NhbGwoIml0a193YXNtX291dHB1dF9hcnJheV9zaXplIiwibnVtYmVyIixbIm51bWJlciIsIm51bWJlciIsIm51bWJlciJdLFswLEIsMF0pLEU9bmV3IFVpbnQ4QXJyYXkoQS5IRUFQVTguYnVmZmVyLHMsYSk7aT17ZGF0YTpXdC5kZWNvZGUoRSl9O2JyZWFrfWNhc2UgRC5Kc29uQ29tcGF0aWJsZTp7bGV0IHM9QS5jY2FsbCgiaXRrX3dhc21fb3V0cHV0X2FycmF5X2FkZHJlc3MiLCJudW1iZXIiLFsibnVtYmVyIiwibnVtYmVyIiwibnVtYmVyIl0sWzAsQiwwXSksYT1BLmNjYWxsKCJpdGtfd2FzbV9vdXRwdXRfYXJyYXlfc2l6ZSIsIm51bWJlciIsWyJudW1iZXIiLCJudW1iZXIiLCJudW1iZXIiXSxbMCxCLDBdKSxFPW5ldyBVaW50OEFycmF5KEEuSEVBUFU4LmJ1ZmZlcixzLGEpO2k9SlNPTi5wYXJzZShXdC5kZWNvZGUoRSkpO2JyZWFrfWNhc2UgRC5CaW5hcnlTdHJlYW06e2xldCBzPUEuY2NhbGwoIml0a193YXNtX291dHB1dF9hcnJheV9hZGRyZXNzIiwibnVtYmVyIixbIm51bWJlciIsIm51bWJlciIsIm51bWJlciJdLFswLEIsMF0pLGE9QS5jY2FsbCgiaXRrX3dhc21fb3V0cHV0X2FycmF5X3NpemUiLCJudW1iZXIiLFsibnVtYmVyIiwibnVtYmVyIiwibnVtYmVyIl0sWzAsQiwwXSk7aT17ZGF0YTpWdChBLHMsYSl9O2JyZWFrfWNhc2UgRC5UZXh0RmlsZTp7aT17cGF0aDpRLmRhdGEucGF0aCxkYXRhOkEuZnNfcmVhZEZpbGUoUS5kYXRhLnBhdGgse2VuY29kaW5nOiJ1dGY4In0pfTticmVha31jYXNlIEQuQmluYXJ5RmlsZTp7aT17cGF0aDpRLmRhdGEucGF0aCxkYXRhOmRlKEEsUS5kYXRhLnBhdGgpfTticmVha31jYXNlIEQuSW1hZ2U6e2xldCBzPUlBKEEsQik7cy5kYXRhPXcoQSxCLDAscy5pbWFnZVR5cGUuY29tcG9uZW50VHlwZSkscy5kaXJlY3Rpb249dyhBLEIsMSxqLkZsb2F0NjQpLHMubWV0YWRhdGE9bmV3IE1hcChzLm1ldGFkYXRhKSxpPXM7YnJlYWt9Y2FzZSBELk1lc2g6e2xldCBzPUlBKEEsQik7cy5udW1iZXJPZlBvaW50cz4wP3MucG9pbnRzPXcoQSxCLDAscy5tZXNoVHlwZS5wb2ludENvbXBvbmVudFR5cGUpOnMucG9pbnRzPUcocy5tZXNoVHlwZS5wb2ludENvbXBvbmVudFR5cGUsbmV3IEFycmF5QnVmZmVyKDApKSxzLm51bWJlck9mQ2VsbHM+MD9zLmNlbGxzPXcoQSxCLDEscy5tZXNoVHlwZS5jZWxsQ29tcG9uZW50VHlwZSk6cy5jZWxscz1HKHMubWVzaFR5cGUuY2VsbENvbXBvbmVudFR5cGUsbmV3IEFycmF5QnVmZmVyKDApKSxzLm51bWJlck9mUG9pbnRQaXhlbHM+MD9zLnBvaW50RGF0YT13KEEsQiwyLHMubWVzaFR5cGUucG9pbnRQaXhlbENvbXBvbmVudFR5cGUpOnMucG9pbnREYXRhPUcocy5tZXNoVHlwZS5wb2ludFBpeGVsQ29tcG9uZW50VHlwZSxuZXcgQXJyYXlCdWZmZXIoMCkpLHMubnVtYmVyT2ZDZWxsUGl4ZWxzPjA/cy5jZWxsRGF0YT13KEEsQiwzLHMubWVzaFR5cGUuY2VsbFBpeGVsQ29tcG9uZW50VHlwZSk6cy5jZWxsRGF0YT1HKHMubWVzaFR5cGUuY2VsbFBpeGVsQ29tcG9uZW50VHlwZSxuZXcgQXJyYXlCdWZmZXIoMCkpLGk9czticmVha31jYXNlIEQuUG9pbnRTZXQ6e2xldCBzPUlBKEEsQik7cy5udW1iZXJPZlBvaW50cz4wP3MucG9pbnRzPXcoQSxCLDAscy5wb2ludFNldFR5cGUucG9pbnRDb21wb25lbnRUeXBlKTpzLnBvaW50cz1HKHMucG9pbnRTZXRUeXBlLnBvaW50Q29tcG9uZW50VHlwZSxuZXcgQXJyYXlCdWZmZXIoMCkpLHMubnVtYmVyT2ZQb2ludFBpeGVscz4wP3MucG9pbnREYXRhPXcoQSxCLDEscy5wb2ludFNldFR5cGUucG9pbnRQaXhlbENvbXBvbmVudFR5cGUpOnMucG9pbnREYXRhPUcocy5wb2ludFNldFR5cGUucG9pbnRQaXhlbENvbXBvbmVudFR5cGUsbmV3IEFycmF5QnVmZmVyKDApKSxpPXM7YnJlYWt9Y2FzZSBELlRyYW5zZm9ybUxpc3Q6e2xldCBzPUlBKEEsQik7cy5mb3JFYWNoKChhLEUpPT57YS5udW1iZXJPZkZpeGVkUGFyYW1ldGVycz4wJiYoc1tFXS5maXhlZFBhcmFtZXRlcnM9dyhBLEIsRSoyLGEudHJhbnNmb3JtVHlwZS5wYXJhbWV0ZXJzVmFsdWVUeXBlKSksYS5udW1iZXJPZkZpeGVkUGFyYW1ldGVycz4wJiYoc1tFXS5wYXJhbWV0ZXJzPXcoQSxCLEUqMisxLGEudHJhbnNmb3JtVHlwZS5wYXJhbWV0ZXJzVmFsdWVUeXBlKSl9KSxpPXM7YnJlYWt9Y2FzZSBELlBvbHlEYXRhOntsZXQgcz1JQShBLEIpO3MubnVtYmVyT2ZQb2ludHM+MD9zLnBvaW50cz13KEEsQiwwLGouRmxvYXQzMik6cy5wb2ludHM9bmV3IEZsb2F0MzJBcnJheSxzLnZlcnRpY2VzQnVmZmVyU2l6ZT4wP3MudmVydGljZXM9dyhBLEIsMSxTLlVJbnQzMik6cy52ZXJ0aWNlcz1uZXcgVWludDMyQXJyYXkscy5saW5lc0J1ZmZlclNpemU+MD9zLmxpbmVzPXcoQSxCLDIsUy5VSW50MzIpOnMubGluZXM9bmV3IFVpbnQzMkFycmF5LHMucG9seWdvbnNCdWZmZXJTaXplPjA/cy5wb2x5Z29ucz13KEEsQiwzLFMuVUludDMyKTpzLnBvbHlnb25zPW5ldyBVaW50MzJBcnJheSxzLnRyaWFuZ2xlU3RyaXBzQnVmZmVyU2l6ZT4wP3MudHJpYW5nbGVTdHJpcHM9dyhBLEIsNCxTLlVJbnQzMik6cy50cmlhbmdsZVN0cmlwcz1uZXcgVWludDMyQXJyYXkscy5udW1iZXJPZlBvaW50UGl4ZWxzPjA/cy5wb2ludERhdGE9dyhBLEIsNSxzLnBvbHlEYXRhVHlwZS5wb2ludFBpeGVsQ29tcG9uZW50VHlwZSk6cy5wb2ludERhdGE9RyhzLnBvbHlEYXRhVHlwZS5wb2ludFBpeGVsQ29tcG9uZW50VHlwZSxuZXcgQXJyYXlCdWZmZXIoMCkpLHMubnVtYmVyT2ZDZWxsUGl4ZWxzPjA/cy5jZWxsRGF0YT13KEEsQiw2LHMucG9seURhdGFUeXBlLmNlbGxQaXhlbENvbXBvbmVudFR5cGUpOnMuY2VsbERhdGE9RyhzLnBvbHlEYXRhVHlwZS5jZWxsUGl4ZWxDb21wb25lbnRUeXBlLG5ldyBBcnJheUJ1ZmZlcigwKSksaT1zO2JyZWFrfWRlZmF1bHQ6dGhyb3cgRXJyb3IoIlVuc3VwcG9ydGVkIG91dHB1dCBJbnRlcmZhY2VUeXBlIil9bGV0IGY9e3R5cGU6US50eXBlLGRhdGE6aX07Yy5wdXNoKGYpfSkse3JldHVyblZhbHVlOnIsc3Rkb3V0Om8sc3RkZXJyOm4sb3V0cHV0czpjfX12YXIgWHQ9eWU7dmFyIHdlPXR5cGVvZiBnbG9iYWxUaGlzLlNoYXJlZEFycmF5QnVmZmVyPCJ1IjtmdW5jdGlvbiBtZShBLHQpe2lmKEE9PW51bGwpcmV0dXJuW107bGV0IEk9W107Zm9yKGxldCBlPTA7ZTxBLmxlbmd0aDtlKyspe2xldCBnPXBlKEFbZV0sdCk7ZyE9PW51bGwmJkkucHVzaChnKX1yZXR1cm4gSX1mdW5jdGlvbiBwZShBLHQpe2lmKEE9PW51bGwpcmV0dXJuIG51bGw7bGV0IEk9bnVsbDtyZXR1cm4gQS5idWZmZXIhPT12b2lkIDA/ST1BLmJ1ZmZlcjpBLmJ5dGVMZW5ndGghPT12b2lkIDAmJihJPUEpLHdlJiZJIGluc3RhbmNlb2YgU2hhcmVkQXJyYXlCdWZmZXI/bnVsbDp0P0k6SS5zbGljZSgwKX12YXIgenQ9bWU7ZnVuY3Rpb24gU2UoQSl7cmV0dXJuW0EuZGF0YSxBLmRpcmVjdGlvbl19dmFyIF90PVNlO2Z1bmN0aW9uIEZlKEEpe3JldHVybltBLnBvaW50cyxBLnBvaW50RGF0YSxBLmNlbGxzLEEuY2VsbERhdGFdfXZhciB2dD1GZTtmdW5jdGlvbiBSZShBKXtyZXR1cm5bQS5wb2ludHMsQS52ZXJ0aWNlcyxBLmxpbmVzLEEucG9seWdvbnMsQS50cmlhbmdsZVN0cmlwcyxBLnBvaW50RGF0YSxBLmNlbGxEYXRhXX12YXIgJHQ9UmU7YXN5bmMgZnVuY3Rpb24gTmUoQSx0LEksZSl7bGV0IGc9WHQoQSx0LEksZSkscj1bXTtyZXR1cm4gZy5vdXRwdXRzLmZvckVhY2goZnVuY3Rpb24obyl7aWYoby50eXBlPT09RC5CaW5hcnlTdHJlYW18fG8udHlwZT09PUQuQmluYXJ5RmlsZSl7bGV0IG49by5kYXRhO3IucHVzaChuKX1lbHNlIGlmKG8udHlwZT09PUQuSW1hZ2Upe2xldCBuPW8uZGF0YTtyLnB1c2goLi4uX3QobikpfWVsc2UgaWYoby50eXBlPT09RC5NZXNoKXtsZXQgbj1vLmRhdGE7ci5wdXNoKC4uLnZ0KG4pKX1lbHNlIGlmKG8udHlwZT09PUQuUG9seURhdGEpe2xldCBuPW8uZGF0YTtyLnB1c2goLi4uJHQobikpfX0pLEZBKGcsenQociwhMCkpfXZhciBBST1OZTt2YXIgVWU9e3J1blBpcGVsaW5lOmFzeW5jIGZ1bmN0aW9uKEEsdCxJLGUsZyxyKXtsZXQgbz1hd2FpdCB4dChBLHQscik7cmV0dXJuIGF3YWl0IEFJKG8sSSxlLGcpfX07Q0EoVWUpOyUwQS8qISBCdW5kbGVkIGxpY2Vuc2UgaW5mb3JtYXRpb246JTBBJTBBY29tbGluay9kaXN0L2VzbS9jb21saW5rLm1qczolMEEgICgqKiUwQSAgICogQGxpY2Vuc2UlMEEgICAqIENvcHlyaWdodCAyMDE5IEdvb2dsZSBMTEMlMEEgICAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wJTBBICAgKiklMEEqLyUwQSc7UnQoa3QpO2V4cG9ydHt3IGFzIGdldERlZmF1bHRXZWJXb3JrZXIsZCBhcyBnZXRQaXBlbGluZVdvcmtlclVybCxoIGFzIGdldFBpcGVsaW5lc0Jhc2VVcmwsSWUgYXMgaGRmNVJlYWRUcmFuc2Zvcm0sZ2UgYXMgaGRmNVdyaXRlVHJhbnNmb3JtLGxlIGFzIG1hdFJlYWRUcmFuc2Zvcm0sQmUgYXMgbWF0V3JpdGVUcmFuc2Zvcm0sQ2UgYXMgbW5jUmVhZFRyYW5zZm9ybSxmZSBhcyBtbmNXcml0ZVRyYW5zZm9ybSxVbyBhcyByZWFkVHJhbnNmb3JtLFlzIGFzIHNldERlZmF1bHRXZWJXb3JrZXIsUnQgYXMgc2V0UGlwZWxpbmVXb3JrZXJVcmwsR3MgYXMgc2V0UGlwZWxpbmVzQmFzZVVybCxjZSBhcyB0eHRSZWFkVHJhbnNmb3JtLHVlIGFzIHR4dFdyaXRlVHJhbnNmb3JtLFRBIGFzIHZlcnNpb24sRWUgYXMgd2FzbVJlYWRUcmFuc2Zvcm0sUWUgYXMgd2FzbVdyaXRlVHJhbnNmb3JtLHBlIGFzIHdhc21ac3RkUmVhZFRyYW5zZm9ybSxtZSBhcyB3YXNtWnN0ZFdyaXRlVHJhbnNmb3JtLFRvIGFzIHdyaXRlVHJhbnNmb3JtfTsKLyohIEJ1bmRsZWQgbGljZW5zZSBpbmZvcm1hdGlvbjoKCmNvbWxpbmsvZGlzdC9lc20vY29tbGluay5tanM6CiAgKCoqCiAgICogQGxpY2Vuc2UKICAgKiBDb3B5cmlnaHQgMjAxOSBHb29nbGUgTExDCiAgICogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjAKICAgKikKKi8K""" default_config = JsPackageConfig(default_js_module) js_package = JsPackage(default_config) diff --git a/packages/transform-io/python/itkwasm-transform-io-emscripten/itkwasm_transform_io_emscripten/read_transform_async.py b/packages/transform-io/python/itkwasm-transform-io-emscripten/itkwasm_transform_io_emscripten/read_transform_async.py new file mode 100644 index 000000000..235c874b7 --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io-emscripten/itkwasm_transform_io_emscripten/read_transform_async.py @@ -0,0 +1,87 @@ +import os +from typing import Optional, Union +from pathlib import Path + +from itkwasm import ( + TransformList, + BinaryFile, +) + +from .js_package import js_package + +from itkwasm.pyodide import ( + to_js, + to_py, + js_resources +) + +from .extension_to_transform_io import extension_to_transform_io +from .transform_io_index import transform_io_index + +async def read_transform_async( + serialized_transform: os.PathLike, + float_parameters: bool = False, +) -> TransformList: + """Read an transform file format and convert it to the itk-wasm file format + + :param serialized_transform: Input transform serialized in the file format + :type serialized_transform: os.PathLike + + :param float_parameters: Use float for the parameter value type. The default is double. + :type float_parameters: bool + + :return: Output transform + :rtype: TransformList + """ + js_module = await js_package.js_module + web_worker = js_resources.web_worker + + kwargs = {} + if float_parameters: + kwargs["floatParameters"] = to_js(float_parameters) + + extension = ''.join(Path(serialized_transform).suffixes) + + io = None + if extension in extension_to_transform_io: + func = f"{extension_to_transform_io[extension]}ReadTransform" + io = getattr(js_module, func) + else: + for ioname in transform_io_index: + func = f"{ioname}ReadTransform" + io = getattr(js_module, func) + outputs = await io(to_js(BinaryFile(serialized_transform)), webWorker=web_worker, noCopy=True, **kwargs) + outputs_object_map = outputs.as_object_map() + web_worker = outputs_object_map['webWorker'] + js_resources.web_worker = web_worker + could_read = to_py(outputs_object_map['couldRead']) + if could_read: + transform = to_py(outputs_object_map['transform']) + return transform + + if io is None: + raise RuntimeError(f"Could not find an transform reader for {extension}") + + outputs = await io(to_js(BinaryFile(serialized_transform)), webWorker=web_worker, noCopy=True, **kwargs) + outputs_object_map = outputs.as_object_map() + web_worker = outputs_object_map['webWorker'] + could_read = to_py(outputs_object_map['couldRead']) + + if not could_read: + raise RuntimeError(f"Could not read {serialized_transform}") + + js_resources.web_worker = web_worker + + transform = to_py(outputs_object_map['transform']) + + return transform + +async def transformread_async( + serialized_transform: os.PathLike, + float_parameters: bool = False, +) -> TransformList: + return await read_transform_async(serialized_transform, float_parameters=float_parameters) + +transformread_async.__doc__ = f"""{read_transform_async.__doc__} + Alias for read_transform_async. + """ diff --git a/packages/transform-io/python/itkwasm-transform-io-emscripten/itkwasm_transform_io_emscripten/transform_io_index.py b/packages/transform-io/python/itkwasm-transform-io-emscripten/itkwasm_transform_io_emscripten/transform_io_index.py new file mode 100644 index 000000000..1f186a8dc --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io-emscripten/itkwasm_transform_io_emscripten/transform_io_index.py @@ -0,0 +1,9 @@ +transform_io_index = [ + 'hdf5', + 'mat', + 'mnc', + 'txt', + 'wasm', + 'wasm_ztd', +] + diff --git a/packages/transform-io/python/itkwasm-transform-io-emscripten/itkwasm_transform_io_emscripten/write_transform_async.py b/packages/transform-io/python/itkwasm-transform-io-emscripten/itkwasm_transform_io_emscripten/write_transform_async.py new file mode 100644 index 000000000..296d4c952 --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io-emscripten/itkwasm_transform_io_emscripten/write_transform_async.py @@ -0,0 +1,94 @@ +import os +import importlib +from pathlib import Path +from typing import Optional, Union + +from itkwasm import TransformList, PixelTypes, IntTypes, FloatTypes, BinaryFile + +from itkwasm.pyodide import ( + to_js, + to_py, + js_resources +) + +from .js_package import js_package + +from .extension_to_transform_io import extension_to_transform_io +from .transform_io_index import transform_io_index + +async def write_transform_async( + transform: TransformList, + serialized_transform: os.PathLike, + float_parameters: bool = False, + use_compression: bool = False, +) -> None: + """Write an itk-wasm TransformList to an transform file format. + + :param transform: Input transform + :type transform: TransformList + + :param serialized_transform: Output transform serialized in the file format. + :type serialized_transform: str + + :param float_parameters: Use float for the parameter value type. The default is double. + :type float_parameters: bool + + :param use_compression: Use compression in the written file + :type use_compression: bool + + :param serialized_transform: Input transform serialized in the file format + :type serialized_transform: os.PathLike + """ + js_module = await js_package.js_module + web_worker = js_resources.web_worker + + kwargs = {} + if float_parameters: + kwargs["floatParameters"] = to_js(float_parameters) + if use_compression: + kwargs["useCompression"] = to_js(use_compression) + + extension = ''.join(Path(serialized_transform).suffixes) + + io = None + if extension in extension_to_transform_io: + func = f"{extension_to_transform_io[extension]}WriteTransform" + io = getattr(js_module, func) + else: + for ioname in transform_io_index: + func = f"{ioname}WriteTransform" + io = getattr(js_module, func) + outputs = await io(to_js(transform), to_js(serialized_transform), webWorker=web_worker, noCopy=True, **kwargs) + outputs_object_map = outputs.as_object_map() + web_worker = outputs_object_map['webWorker'] + js_resources.web_worker = web_worker + could_write = to_py(outputs_object_map['couldWrite']) + if could_write: + to_py(outputs_object_map['serializedTransform']) + return + + if io is None: + raise RuntimeError(f"Could not find an transform writer for {extension}") + + outputs = await io(to_js(transform), to_js(serialized_transform), webWorker=web_worker, noCopy=True, **kwargs) + outputs_object_map = outputs.as_object_map() + web_worker = outputs_object_map['webWorker'] + js_resources.web_worker = web_worker + could_write = to_py(outputs_object_map['couldWrite']) + + if not could_write: + raise RuntimeError(f"Could not write {serialized_transform}") + + to_py(outputs_object_map['serializedTransform']) + +async def transformwrite_async( + transform: TransformList, + serialized_transform: os.PathLike, + float_parameters: bool = False, + use_compression: bool = False, +) -> None: + return write_transform_async(transform, serialized_transform, float_parameters=float_parameters, use_compression=use_compression) + +transformwrite_async.__doc__ = f"""{write_transform_async.__doc__} + Alias for write_transform. + """ diff --git a/packages/transform-io/python/itkwasm-transform-io-emscripten/pyproject.toml b/packages/transform-io/python/itkwasm-transform-io-emscripten/pyproject.toml index 772c2d9ee..204c9960a 100644 --- a/packages/transform-io/python/itkwasm-transform-io-emscripten/pyproject.toml +++ b/packages/transform-io/python/itkwasm-transform-io-emscripten/pyproject.toml @@ -5,7 +5,7 @@ build-backend = "hatchling.build" [project] name = "itkwasm-transform-io-emscripten" readme = "README.md" -license = "Apache-2.0" +license-expression = "Apache-2.0" dynamic = ["version"] description = "Input and output for scientific and medical coordinate transform file formats." classifiers = [ @@ -19,11 +19,11 @@ classifiers = [ "Intended Audience :: Developers", "Intended Audience :: Science/Research", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", ] keywords = [ "itkwasm", @@ -31,9 +31,9 @@ keywords = [ "emscripten", ] -requires-python = ">=3.8" +requires-python = ">=3.9" dependencies = [ - "itkwasm >= 1.0.b171", + "itkwasm >= 1.0.b185", ] [tool.hatch.version] diff --git a/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/__init__.py b/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/fixtures.py b/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/fixtures.py new file mode 100644 index 000000000..597cf189a --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/fixtures.py @@ -0,0 +1,25 @@ +import pytest +import sys +import glob + +if sys.version_info < (3,10): + pytest.skip("Skipping pyodide tests on older Python", allow_module_level=True) + +from pytest_pyodide import run_in_pyodide + +from itkwasm_transform_io_emscripten import __version__ as test_package_version + +@pytest.fixture +def package_wheel(): + return f"itkwasm_transform_io_emscripten-{test_package_version}-py3-none-any.whl" + +@pytest.fixture +def input_data(): + from pathlib import Path + input_base_path = Path(__file__).parent.parent.parent.parent / 'test' / 'data' / 'input' + test_files = list(input_base_path.glob('*')) + data = {} + for test_file in test_files: + with open(test_file, 'rb') as f: + data[test_file.name] = f.read() + return data \ No newline at end of file diff --git a/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_hdf5_read_transform_async.py b/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_hdf5_read_transform_async.py new file mode 100644 index 000000000..0650fbe42 --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_hdf5_read_transform_async.py @@ -0,0 +1,58 @@ +import pytest +import sys + +if sys.version_info < (3,10): + pytest.skip("Skipping pyodide tests on older Python", allow_module_level=True) + +from pytest_pyodide import run_in_pyodide + +from .fixtures import package_wheel, input_data + +@run_in_pyodide(packages=['micropip']) +async def test_hdf5_read_transform_async(selenium, package_wheel, input_data): + import micropip + await micropip.install(package_wheel) + + from pathlib import Path + + import numpy as np + from itkwasm import TransformParameterizations, FloatTypes + + from itkwasm_transform_io_emscripten import hdf5_read_transform_async, hdf5_write_transform_async + + def write_input_data_to_fs(input_data, filename): + with open(filename, 'wb') as fp: + fp.write(input_data[filename]) + + def verify_test_linear_transform(transform_list): + assert len(transform_list) == 1 + transform = transform_list[0] + assert transform.transformType.transformParameterization == TransformParameterizations.Affine + assert transform.transformType.parametersValueType == FloatTypes.Float64 + assert transform.numberOfParameters == 12 + assert transform.numberOfFixedParameters == 3 + np.testing.assert_allclose(transform.fixedParameters, np.array([0.0, 0.0, 0.0])) + np.testing.assert_allclose(transform.parameters, np.array([ + 0.65631490118447, 0.5806583745824385, -0.4817536741017158, + -0.7407986817430222, 0.37486398378429736, -0.5573995934598175, + -0.14306664045479867, 0.7227121458012518, 0.676179776908723, + -65.99999999999997, 69.00000000000004, 32.000000000000036])) + + test_file_path = 'LinearTransform.h5' + write_input_data_to_fs(input_data, test_file_path) + + assert Path(test_file_path).exists() + + could_read, transform = await hdf5_read_transform_async(test_file_path) + assert could_read + verify_test_linear_transform(transform) + + test_output_file_path = 'out-LinearTransform.h5' + + use_compression = False + could_write = await hdf5_write_transform_async(transform, test_output_file_path, use_compression) + assert could_write + + could_read, transform = await hdf5_read_transform_async(test_output_file_path) + assert could_read + verify_test_linear_transform(transform) diff --git a/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_hdf5_write_transform_async.py b/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_hdf5_write_transform_async.py new file mode 100644 index 000000000..2e71e02a9 --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_hdf5_write_transform_async.py @@ -0,0 +1,18 @@ +import pytest +import sys + +if sys.version_info < (3,10): + pytest.skip("Skipping pyodide tests on older Python", allow_module_level=True) + +from pytest_pyodide import run_in_pyodide + +from .fixtures import package_wheel, input_data + +@run_in_pyodide(packages=['micropip']) +async def test_hdf5_write_transform_async(selenium, package_wheel): + import micropip + await micropip.install(package_wheel) + + from itkwasm_transform_io_emscripten import hdf5_write_transform_async + + # Write your test code here diff --git a/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_mat_read_transform_async.py b/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_mat_read_transform_async.py new file mode 100644 index 000000000..6077969a9 --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_mat_read_transform_async.py @@ -0,0 +1,18 @@ +import pytest +import sys + +if sys.version_info < (3,10): + pytest.skip("Skipping pyodide tests on older Python", allow_module_level=True) + +from pytest_pyodide import run_in_pyodide + +from .fixtures import package_wheel, input_data + +@run_in_pyodide(packages=['micropip']) +async def test_mat_read_transform_async(selenium, package_wheel): + import micropip + await micropip.install(package_wheel) + + from itkwasm_transform_io_emscripten import mat_read_transform_async + + # Write your test code here diff --git a/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_mat_write_transform_async.py b/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_mat_write_transform_async.py new file mode 100644 index 000000000..8ea910537 --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_mat_write_transform_async.py @@ -0,0 +1,18 @@ +import pytest +import sys + +if sys.version_info < (3,10): + pytest.skip("Skipping pyodide tests on older Python", allow_module_level=True) + +from pytest_pyodide import run_in_pyodide + +from .fixtures import package_wheel, input_data + +@run_in_pyodide(packages=['micropip']) +async def test_mat_write_transform_async(selenium, package_wheel): + import micropip + await micropip.install(package_wheel) + + from itkwasm_transform_io_emscripten import mat_write_transform_async + + # Write your test code here diff --git a/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_mnc_read_transform_async.py b/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_mnc_read_transform_async.py new file mode 100644 index 000000000..3cb4e29df --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_mnc_read_transform_async.py @@ -0,0 +1,18 @@ +import pytest +import sys + +if sys.version_info < (3,10): + pytest.skip("Skipping pyodide tests on older Python", allow_module_level=True) + +from pytest_pyodide import run_in_pyodide + +from .fixtures import package_wheel, input_data + +@run_in_pyodide(packages=['micropip']) +async def test_mnc_read_transform_async(selenium, package_wheel): + import micropip + await micropip.install(package_wheel) + + from itkwasm_transform_io_emscripten import mnc_read_transform_async + + # Write your test code here diff --git a/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_mnc_write_transform_async.py b/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_mnc_write_transform_async.py new file mode 100644 index 000000000..0a2276375 --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_mnc_write_transform_async.py @@ -0,0 +1,18 @@ +import pytest +import sys + +if sys.version_info < (3,10): + pytest.skip("Skipping pyodide tests on older Python", allow_module_level=True) + +from pytest_pyodide import run_in_pyodide + +from .fixtures import package_wheel, input_data + +@run_in_pyodide(packages=['micropip']) +async def test_mnc_write_transform_async(selenium, package_wheel): + import micropip + await micropip.install(package_wheel) + + from itkwasm_transform_io_emscripten import mnc_write_transform_async + + # Write your test code here diff --git a/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_read_write_transform_async.py b/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_read_write_transform_async.py new file mode 100644 index 000000000..cd9f9622d --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_read_write_transform_async.py @@ -0,0 +1,58 @@ +import sys + +if sys.version_info < (3,10): + pytest.skip("Skipping pyodide tests on older Python", allow_module_level=True) + +import pytest +from pytest_pyodide import run_in_pyodide +from .fixtures import package_wheel, input_data + +@pytest.mark.driver_timeout(30) +@run_in_pyodide(packages=['micropip', 'numpy']) +async def test_read_write_mesh_async(selenium, package_wheel, input_data): + import micropip + await micropip.install(package_wheel) + def write_input_data_to_fs(input_data, filename): + with open(filename, 'wb') as fp: + fp.write(input_data[filename]) + + from pathlib import Path + + from itkwasm import TransformParameterizations, FloatTypes + import numpy as np + + from itkwasm_transform_io_emscripten import read_transform_async, write_transform_async + + def write_input_data_to_fs(input_data, filename): + with open(filename, 'wb') as fp: + fp.write(input_data[filename]) + + def verify_test_linear_transform(transform_list): + assert len(transform_list) == 1 + transform = transform_list[0] + assert transform.transformType.transformParameterization == TransformParameterizations.Affine + assert transform.transformType.parametersValueType == FloatTypes.Float64 + assert transform.numberOfParameters == 12 + assert transform.numberOfFixedParameters == 3 + np.testing.assert_allclose(transform.fixedParameters, np.array([0.0, 0.0, 0.0])) + np.testing.assert_allclose(transform.parameters, np.array([ + 0.65631490118447, 0.5806583745824385, -0.4817536741017158, + -0.7407986817430222, 0.37486398378429736, -0.5573995934598175, + -0.14306664045479867, 0.7227121458012518, 0.676179776908723, + -65.99999999999997, 69.00000000000004, 32.000000000000036])) + + test_file_path = 'LinearTransform.h5' + write_input_data_to_fs(input_data, test_file_path) + + assert Path(test_file_path).exists() + + transform = await read_transform_async(test_file_path) + verify_test_linear_transform(transform) + + test_output_file_path = 'out-LinearTransform.h5' + + use_compression = False + await write_transform_async(transform, test_output_file_path, use_compression) + + transform = await read_transform_async(test_output_file_path) + verify_test_linear_transform(transform) diff --git a/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_txt_read_transform_async.py b/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_txt_read_transform_async.py new file mode 100644 index 000000000..d2adba9d9 --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_txt_read_transform_async.py @@ -0,0 +1,18 @@ +import pytest +import sys + +if sys.version_info < (3,10): + pytest.skip("Skipping pyodide tests on older Python", allow_module_level=True) + +from pytest_pyodide import run_in_pyodide + +from .fixtures import package_wheel, input_data + +@run_in_pyodide(packages=['micropip']) +async def test_txt_read_transform_async(selenium, package_wheel): + import micropip + await micropip.install(package_wheel) + + from itkwasm_transform_io_emscripten import txt_read_transform_async + + # Write your test code here diff --git a/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_txt_write_transform_async.py b/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_txt_write_transform_async.py new file mode 100644 index 000000000..3da486d23 --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_txt_write_transform_async.py @@ -0,0 +1,18 @@ +import pytest +import sys + +if sys.version_info < (3,10): + pytest.skip("Skipping pyodide tests on older Python", allow_module_level=True) + +from pytest_pyodide import run_in_pyodide + +from .fixtures import package_wheel, input_data + +@run_in_pyodide(packages=['micropip']) +async def test_txt_write_transform_async(selenium, package_wheel): + import micropip + await micropip.install(package_wheel) + + from itkwasm_transform_io_emscripten import txt_write_transform_async + + # Write your test code here diff --git a/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_wasm_read_transform_async.py b/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_wasm_read_transform_async.py new file mode 100644 index 000000000..2ce4fb8d7 --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_wasm_read_transform_async.py @@ -0,0 +1,18 @@ +import pytest +import sys + +if sys.version_info < (3,10): + pytest.skip("Skipping pyodide tests on older Python", allow_module_level=True) + +from pytest_pyodide import run_in_pyodide + +from .fixtures import package_wheel, input_data + +@run_in_pyodide(packages=['micropip']) +async def test_wasm_read_transform_async(selenium, package_wheel): + import micropip + await micropip.install(package_wheel) + + from itkwasm_transform_io_emscripten import wasm_read_transform_async + + # Write your test code here diff --git a/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_wasm_write_transform_async.py b/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_wasm_write_transform_async.py new file mode 100644 index 000000000..46006152d --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_wasm_write_transform_async.py @@ -0,0 +1,18 @@ +import pytest +import sys + +if sys.version_info < (3,10): + pytest.skip("Skipping pyodide tests on older Python", allow_module_level=True) + +from pytest_pyodide import run_in_pyodide + +from .fixtures import package_wheel, input_data + +@run_in_pyodide(packages=['micropip']) +async def test_wasm_write_transform_async(selenium, package_wheel): + import micropip + await micropip.install(package_wheel) + + from itkwasm_transform_io_emscripten import wasm_write_transform_async + + # Write your test code here diff --git a/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_wasm_zstd_read_transform_async.py b/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_wasm_zstd_read_transform_async.py new file mode 100644 index 000000000..be9b399b7 --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_wasm_zstd_read_transform_async.py @@ -0,0 +1,18 @@ +import pytest +import sys + +if sys.version_info < (3,10): + pytest.skip("Skipping pyodide tests on older Python", allow_module_level=True) + +from pytest_pyodide import run_in_pyodide + +from .fixtures import package_wheel, input_data + +@run_in_pyodide(packages=['micropip']) +async def test_wasm_zstd_read_transform_async(selenium, package_wheel): + import micropip + await micropip.install(package_wheel) + + from itkwasm_transform_io_emscripten import wasm_zstd_read_transform_async + + # Write your test code here diff --git a/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_wasm_zstd_write_transform_async.py b/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_wasm_zstd_write_transform_async.py new file mode 100644 index 000000000..3314dcf08 --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io-emscripten/tests/test_wasm_zstd_write_transform_async.py @@ -0,0 +1,18 @@ +import pytest +import sys + +if sys.version_info < (3,10): + pytest.skip("Skipping pyodide tests on older Python", allow_module_level=True) + +from pytest_pyodide import run_in_pyodide + +from .fixtures import package_wheel, input_data + +@run_in_pyodide(packages=['micropip']) +async def test_wasm_zstd_write_transform_async(selenium, package_wheel): + import micropip + await micropip.install(package_wheel) + + from itkwasm_transform_io_emscripten import wasm_zstd_write_transform_async + + # Write your test code here diff --git a/packages/transform-io/python/itkwasm-transform-io-wasi/itkwasm_transform_io_wasi/__init__.py b/packages/transform-io/python/itkwasm-transform-io-wasi/itkwasm_transform_io_wasi/__init__.py index 443124ad4..070a258ed 100644 --- a/packages/transform-io/python/itkwasm-transform-io-wasi/itkwasm_transform_io_wasi/__init__.py +++ b/packages/transform-io/python/itkwasm-transform-io-wasi/itkwasm_transform_io_wasi/__init__.py @@ -1,7 +1,8 @@ -# Generated file. To retain edits, remove this comment. - """itkwasm-transform-io-wasi: Input and output for scientific and medical coordinate transform file formats. WASI implementation.""" +from .read_transform import read_transform, transformread +from .write_transform import write_transform, transformwrite + from .hdf5_read_transform import hdf5_read_transform from .hdf5_write_transform import hdf5_write_transform from .mat_read_transform import mat_read_transform diff --git a/packages/transform-io/python/itkwasm-transform-io-wasi/itkwasm_transform_io_wasi/_version.py b/packages/transform-io/python/itkwasm-transform-io-wasi/itkwasm_transform_io_wasi/_version.py index 3dc1f76bc..485f44ac2 100644 --- a/packages/transform-io/python/itkwasm-transform-io-wasi/itkwasm_transform_io_wasi/_version.py +++ b/packages/transform-io/python/itkwasm-transform-io-wasi/itkwasm_transform_io_wasi/_version.py @@ -1 +1 @@ -__version__ = "0.1.0" +__version__ = "0.1.1" diff --git a/packages/transform-io/python/itkwasm-transform-io-wasi/itkwasm_transform_io_wasi/extension_to_transform_io.py b/packages/transform-io/python/itkwasm-transform-io-wasi/itkwasm_transform_io_wasi/extension_to_transform_io.py new file mode 100644 index 000000000..f90774811 --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io-wasi/itkwasm_transform_io_wasi/extension_to_transform_io.py @@ -0,0 +1,12 @@ +from collections import OrderedDict + +extension_to_transform_io = OrderedDict([ + ("h5", "hdf5"), + ("hdf5", "hdf5"), + ("txt", "txt"), + ("mat", "mat"), + ("xfm", "mnc"), + ("iwt", "wasm"), + ("iwt.cbor", "wasm"), + ("iwt.cbor.zst", "wasm-zstd"), +]) diff --git a/packages/transform-io/python/itkwasm-transform-io-wasi/itkwasm_transform_io_wasi/read_transform.py b/packages/transform-io/python/itkwasm-transform-io-wasi/itkwasm_transform_io_wasi/read_transform.py new file mode 100644 index 000000000..c921515b7 --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io-wasi/itkwasm_transform_io_wasi/read_transform.py @@ -0,0 +1,61 @@ +import os +import importlib +from pathlib import Path + +from itkwasm import TransformList + +from .extension_to_transform_io import extension_to_transform_io +from .transform_io_index import transform_io_index + +def read_transform( + serialized_transform: os.PathLike, + float_parameters: bool = False, +) -> TransformList: + """Read a transform file format and convert it to the ITK-Wasm file format. + + :param serialized_transform: Input transform serialized in the file format + :type serialized_transform: os.PathLike + + :param float_parameters: Use float for the parameter value type. The default is double. + :type float_parameters: bool + + :return: Output transform + :rtype: TransformList + """ + extension = ''.join(Path(serialized_transform).suffixes) + + io = None + if extension in extension_to_transform_io: + func = f"{extension_to_transform_io[extension]}_read_transform" + mod_name = f"itkwasm_transform_io_wasi.{func}" + mod = importlib.import_module(mod_name) + io = getattr(mod, func) + else: + for ioname in transform_io_index: + func = f"{ioname}_read_transform" + mod_name = f"itkwasm_transform_io_wasi.{func}" + mod = importlib.import_module(mod_name) + io = getattr(mod, func) + could_read, transform = io(serialized_transform, float_parameters=float_parameters) + if could_read: + return transform + + if io is None: + raise RuntimeError(f"Could not find an transform reader for {extension}") + + could_read, transform = io(serialized_transform, float_parameters=float_parameters) + if not could_read: + raise RuntimeError(f"Could not read {serialized_transform}") + + return transform + + +def transformread( + serialized_transform: os.PathLike, + float_parameters: bool = False, +) -> TransformList: + return read_transform(serialized_transform, float_parameters=float_parameters) + +transformread.__doc__ = f"""{read_transform.__doc__} + Alias for read_transform. + """ \ No newline at end of file diff --git a/packages/transform-io/python/itkwasm-transform-io-wasi/itkwasm_transform_io_wasi/transform_io_index.py b/packages/transform-io/python/itkwasm-transform-io-wasi/itkwasm_transform_io_wasi/transform_io_index.py new file mode 100644 index 000000000..1f186a8dc --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io-wasi/itkwasm_transform_io_wasi/transform_io_index.py @@ -0,0 +1,9 @@ +transform_io_index = [ + 'hdf5', + 'mat', + 'mnc', + 'txt', + 'wasm', + 'wasm_ztd', +] + diff --git a/packages/transform-io/python/itkwasm-transform-io-wasi/itkwasm_transform_io_wasi/write_transform.py b/packages/transform-io/python/itkwasm-transform-io-wasi/itkwasm_transform_io_wasi/write_transform.py new file mode 100644 index 000000000..23782dedc --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io-wasi/itkwasm_transform_io_wasi/write_transform.py @@ -0,0 +1,68 @@ +import os +import importlib +from pathlib import Path + +from itkwasm import TransformList + +from .extension_to_transform_io import extension_to_transform_io +from .transform_io_index import transform_io_index + +def write_transform( + transform: TransformList, + serialized_transform: os.PathLike, + float_parameters: bool = False, + use_compression: bool = False, +) -> None: + """Write an itk-wasm TransformList to an transform file format. + + :param transform: Input transform + :type transform: TransformList + + :param serialized_transform: Output transform serialized in the file format. + :type serialized_transform: str + + :param float_parameters: Use float for the parameter value type. The default is double. + :type float_parameters: bool + + :param use_compression: Use compression in the written file + :type use_compression: bool + + :param serialized_transform: Input transform serialized in the file format + :type serialized_transform: os.PathLike + """ + extension = ''.join(Path(serialized_transform).suffixes) + + io = None + if extension in extension_to_transform_io: + func = f"{extension_to_transform_io[extension]}_write_transform" + mod_name = f"itkwasm_transform_io_wasi.{func}" + mod = importlib.import_module(mod_name) + io = getattr(mod, func) + else: + for ioname in transform_io_index: + func = f"{ioname}_write_transform" + mod_name = f"itkwasm_transform_io_wasi.{func}" + mod = importlib.import_module(mod_name) + io = getattr(mod, func) + could_write = io(transform, serialized_transform, float_parameters=float_parameters, use_compression=use_compression) + if could_write: + return + + if io is None: + raise RuntimeError(f"Could not find an transform writer for {extension}") + + could_write = io(transform, serialized_transform, float_parameters=float_parameters, use_compression=use_compression) + if not could_write: + raise RuntimeError(f"Could not write {serialized_transform}") + +def transformwrite( + transform: TransformList, + serialized_transform: os.PathLike, + float_parameters: bool = False, + use_compression: bool = False, +) -> None: + return write_transform(transform, serialized_transform, float_parameters=float_parameters, use_compression=use_compression) + +transformwrite.__doc__ = f"""{write_transform.__doc__} + Alias for write_transform. + """ \ No newline at end of file diff --git a/packages/transform-io/python/itkwasm-transform-io-wasi/pyproject.toml b/packages/transform-io/python/itkwasm-transform-io-wasi/pyproject.toml index 956bef031..638af7acb 100644 --- a/packages/transform-io/python/itkwasm-transform-io-wasi/pyproject.toml +++ b/packages/transform-io/python/itkwasm-transform-io-wasi/pyproject.toml @@ -5,7 +5,7 @@ build-backend = "hatchling.build" [project] name = "itkwasm-transform-io-wasi" readme = "README.md" -license = "Apache-2.0" +license-expression = "Apache-2.0" dynamic = ["version"] description = "Input and output for scientific and medical coordinate transform file formats." classifiers = [ @@ -19,11 +19,11 @@ classifiers = [ "Intended Audience :: Developers", "Intended Audience :: Science/Research", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", ] keywords = [ "itkwasm", @@ -31,9 +31,9 @@ keywords = [ "wasi", ] -requires-python = ">=3.8" +requires-python = ">=3.9" dependencies = [ - "itkwasm >= 1.0.b171", + "itkwasm >= 1.0.b185", "importlib_resources", ] diff --git a/packages/transform-io/python/itkwasm-transform-io-wasi/tests/common.py b/packages/transform-io/python/itkwasm-transform-io-wasi/tests/common.py index 3a182e694..11ebafc53 100644 --- a/packages/transform-io/python/itkwasm-transform-io-wasi/tests/common.py +++ b/packages/transform-io/python/itkwasm-transform-io-wasi/tests/common.py @@ -1,6 +1,23 @@ from pathlib import Path +import numpy as np + +from itkwasm import TransformList, TransformParameterizations, FloatTypes test_input_path = Path(__file__).parent / ".." / ".." / ".." / "test" / "data" / "input" test_baseline_path = Path(__file__).parent / ".." / ".." / ".." / "test" / "data" / "baseline" -test_output_path = Path(__file__).parent / ".." / ".." / ".." / "test" / "data" / "output" / "python" -test_output_path.mkdir(parents=True, exist_ok=True) \ No newline at end of file +test_output_path = Path(__file__).parent / ".." / ".." / ".." / "test" / "data" / "output" / "python-wasi" +test_output_path.mkdir(parents=True, exist_ok=True) + +def verify_test_linear_transform(transform_list: TransformList): + assert len(transform_list) == 1 + transform = transform_list[0] + assert transform.transformType.transformParameterization == TransformParameterizations.Affine + assert transform.transformType.parametersValueType == FloatTypes.Float64 + assert transform.numberOfParameters == 12 + assert transform.numberOfFixedParameters == 3 + np.testing.assert_allclose(transform.fixedParameters, np.array([0.0, 0.0, 0.0])) + np.testing.assert_allclose(transform.parameters, np.array([ + 0.65631490118447, 0.5806583745824385, -0.4817536741017158, + -0.7407986817430222, 0.37486398378429736, -0.5573995934598175, + -0.14306664045479867, 0.7227121458012518, 0.676179776908723, + -65.99999999999997, 69.00000000000004, 32.000000000000036])) diff --git a/packages/transform-io/python/itkwasm-transform-io-wasi/tests/test_hdf5_read_transform.py b/packages/transform-io/python/itkwasm-transform-io-wasi/tests/test_hdf5_read_transform.py index be2fc2f9f..b7b01c621 100644 --- a/packages/transform-io/python/itkwasm-transform-io-wasi/tests/test_hdf5_read_transform.py +++ b/packages/transform-io/python/itkwasm-transform-io-wasi/tests/test_hdf5_read_transform.py @@ -1,8 +1,12 @@ -# Generated file. To retain edits, remove this comment. +from pathlib import Path from itkwasm_transform_io_wasi import hdf5_read_transform -from .common import test_input_path, test_output_path +from .common import test_input_path, test_output_path, verify_test_linear_transform + +test_input_file_path = test_input_path / "LinearTransform.h5" def test_hdf5_read_transform(): - pass + could_read, transform_list = hdf5_read_transform(test_input_file_path) + assert could_read + verify_test_linear_transform(transform_list) diff --git a/packages/transform-io/python/itkwasm-transform-io-wasi/tests/test_hdf5_write_transform.py b/packages/transform-io/python/itkwasm-transform-io-wasi/tests/test_hdf5_write_transform.py index 9768c6f47..34fcb2e76 100644 --- a/packages/transform-io/python/itkwasm-transform-io-wasi/tests/test_hdf5_write_transform.py +++ b/packages/transform-io/python/itkwasm-transform-io-wasi/tests/test_hdf5_write_transform.py @@ -1,8 +1,14 @@ -# Generated file. To retain edits, remove this comment. +from itkwasm_transform_io_wasi import hdf5_read_transform, hdf5_write_transform -from itkwasm_transform_io_wasi import hdf5_write_transform +from .common import test_input_path, test_output_path, verify_test_linear_transform -from .common import test_input_path, test_output_path +test_input_file_path = test_input_path / "LinearTransform.h5" +test_output_file_path = test_output_path / "hdf5-test-write-LinearTransform.h5" def test_hdf5_write_transform(): - pass + could_read, transform_list = hdf5_read_transform(test_input_file_path) + assert could_read + could_write = hdf5_write_transform(transform_list, test_output_file_path) + assert could_write + could_read, transform_list = hdf5_read_transform(test_output_file_path) + verify_test_linear_transform(transform_list) diff --git a/packages/transform-io/python/itkwasm-transform-io-wasi/tests/test_mat_read_transform.py b/packages/transform-io/python/itkwasm-transform-io-wasi/tests/test_mat_read_transform.py index bdd4db8fa..887441605 100644 --- a/packages/transform-io/python/itkwasm-transform-io-wasi/tests/test_mat_read_transform.py +++ b/packages/transform-io/python/itkwasm-transform-io-wasi/tests/test_mat_read_transform.py @@ -1,8 +1,10 @@ -# Generated file. To retain edits, remove this comment. - from itkwasm_transform_io_wasi import mat_read_transform -from .common import test_input_path, test_output_path +from .common import test_input_path, verify_test_linear_transform + +test_input_file_path = test_input_path / "LinearTransform.mat" def test_mat_read_transform(): - pass + could_read, transform_list = mat_read_transform(test_input_file_path) + assert could_read + verify_test_linear_transform(transform_list) diff --git a/packages/transform-io/python/itkwasm-transform-io-wasi/tests/test_mat_write_transform.py b/packages/transform-io/python/itkwasm-transform-io-wasi/tests/test_mat_write_transform.py index bf9368a22..5f4116efc 100644 --- a/packages/transform-io/python/itkwasm-transform-io-wasi/tests/test_mat_write_transform.py +++ b/packages/transform-io/python/itkwasm-transform-io-wasi/tests/test_mat_write_transform.py @@ -1,8 +1,14 @@ -# Generated file. To retain edits, remove this comment. +from itkwasm_transform_io_wasi import mat_read_transform, mat_write_transform -from itkwasm_transform_io_wasi import mat_write_transform +from .common import test_input_path, test_output_path, verify_test_linear_transform -from .common import test_input_path, test_output_path +test_input_file_path = test_input_path / "LinearTransform.mat" +test_output_file_path = test_output_path / "mat-test-write-LinearTransform.mat" def test_mat_write_transform(): - pass + could_read, transform_list = mat_read_transform(test_input_file_path) + assert could_read + could_write = mat_write_transform(transform_list, test_output_file_path) + assert could_write + could_read, transform_list = mat_read_transform(test_output_file_path) + verify_test_linear_transform(transform_list) \ No newline at end of file diff --git a/packages/transform-io/python/itkwasm-transform-io-wasi/tests/test_read_write_transform.py b/packages/transform-io/python/itkwasm-transform-io-wasi/tests/test_read_write_transform.py new file mode 100644 index 000000000..ef8ec0a93 --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io-wasi/tests/test_read_write_transform.py @@ -0,0 +1,36 @@ +from itkwasm import IntTypes, FloatTypes +import numpy as np + +from itkwasm_transform_io_wasi import read_transform, transformread, write_transform, transformwrite + +from .common import test_input_path, test_output_path, verify_test_linear_transform +verify_transform = verify_test_linear_transform + +test_input_file_path = test_input_path / "LinearTransform.h5" +test_output_file_path = test_output_path / "read-write-LinearTransform.h5" + +def test_read_transform(): + transform = read_transform(test_input_file_path) + verify_transform(transform) + +def test_transformread(): + transform = transformread(test_input_file_path) + verify_transform(transform) + +def test_write_transform(): + transform = read_transform(test_input_file_path) + + use_compression = False + write_transform(transform, test_output_file_path, use_compression=use_compression) + + transform = read_transform(test_output_file_path) + verify_transform(transform) + +def test_transformwrite(): + transform = transformread(test_input_file_path) + + use_compression = False + transformwrite(transform, test_output_file_path, use_compression=use_compression) + + transform = transformread(test_output_file_path) + verify_transform(transform) diff --git a/packages/transform-io/python/itkwasm-transform-io-wasi/tests/test_txt_read_transform.py b/packages/transform-io/python/itkwasm-transform-io-wasi/tests/test_txt_read_transform.py index 29bd598ea..b3c78baf9 100644 --- a/packages/transform-io/python/itkwasm-transform-io-wasi/tests/test_txt_read_transform.py +++ b/packages/transform-io/python/itkwasm-transform-io-wasi/tests/test_txt_read_transform.py @@ -1,8 +1,10 @@ -# Generated file. To retain edits, remove this comment. - from itkwasm_transform_io_wasi import txt_read_transform -from .common import test_input_path, test_output_path +from .common import test_input_path, verify_test_linear_transform + +test_input_file_path = test_input_path / "LinearTransform.txt" def test_txt_read_transform(): - pass + could_read, transform_list = txt_read_transform(test_input_file_path) + assert could_read + verify_test_linear_transform(transform_list) \ No newline at end of file diff --git a/packages/transform-io/python/itkwasm-transform-io-wasi/tests/test_txt_write_transform.py b/packages/transform-io/python/itkwasm-transform-io-wasi/tests/test_txt_write_transform.py index c4428dca8..3f75b63db 100644 --- a/packages/transform-io/python/itkwasm-transform-io-wasi/tests/test_txt_write_transform.py +++ b/packages/transform-io/python/itkwasm-transform-io-wasi/tests/test_txt_write_transform.py @@ -1,8 +1,14 @@ -# Generated file. To retain edits, remove this comment. +from itkwasm_transform_io_wasi import txt_read_transform, txt_write_transform -from itkwasm_transform_io_wasi import txt_write_transform +from .common import test_input_path, test_output_path, verify_test_linear_transform -from .common import test_input_path, test_output_path +test_input_file_path = test_input_path / "LinearTransform.txt" +test_output_file_path = test_output_path / "txt-test-write-LinearTransform.txt" def test_txt_write_transform(): - pass + could_read, transform_list = txt_read_transform(test_input_file_path) + assert could_read + could_write = txt_write_transform(transform_list, test_output_file_path) + assert could_write + could_read, transform_list = txt_read_transform(test_output_file_path) + verify_test_linear_transform(transform_list) \ No newline at end of file diff --git a/packages/transform-io/python/itkwasm-transform-io-wasi/tests/test_wasm_read_transform.py b/packages/transform-io/python/itkwasm-transform-io-wasi/tests/test_wasm_read_transform.py index 3d185a5c9..028475f9a 100644 --- a/packages/transform-io/python/itkwasm-transform-io-wasi/tests/test_wasm_read_transform.py +++ b/packages/transform-io/python/itkwasm-transform-io-wasi/tests/test_wasm_read_transform.py @@ -1,8 +1,10 @@ -# Generated file. To retain edits, remove this comment. - from itkwasm_transform_io_wasi import wasm_read_transform -from .common import test_input_path, test_output_path +from .common import test_input_path, verify_test_linear_transform + +test_input_file_path = test_input_path / "LinearTransform.iwt.cbor" def test_wasm_read_transform(): - pass + could_read, transform_list = wasm_read_transform(test_input_file_path) + assert could_read + verify_test_linear_transform(transform_list) \ No newline at end of file diff --git a/packages/transform-io/python/itkwasm-transform-io-wasi/tests/test_wasm_write_transform.py b/packages/transform-io/python/itkwasm-transform-io-wasi/tests/test_wasm_write_transform.py index ae66c2406..90e69f070 100644 --- a/packages/transform-io/python/itkwasm-transform-io-wasi/tests/test_wasm_write_transform.py +++ b/packages/transform-io/python/itkwasm-transform-io-wasi/tests/test_wasm_write_transform.py @@ -1,8 +1,14 @@ -# Generated file. To retain edits, remove this comment. +from itkwasm_transform_io_wasi import wasm_read_transform, wasm_write_transform -from itkwasm_transform_io_wasi import wasm_write_transform +from .common import test_input_path, test_output_path, verify_test_linear_transform -from .common import test_input_path, test_output_path +test_input_file_path = test_input_path / "LinearTransform.iwt.cbor" +test_output_file_path = test_output_path / "wasm-test-write-LinearTransform.iwt.cbor" def test_wasm_write_transform(): - pass + could_read, transform_list = wasm_read_transform(test_input_file_path) + assert could_read + could_write = wasm_write_transform(transform_list, test_output_file_path) + assert could_write + could_read, transform_list = wasm_read_transform(test_output_file_path) + verify_test_linear_transform(transform_list) \ No newline at end of file diff --git a/packages/transform-io/python/itkwasm-transform-io/itkwasm_transform_io/__init__.py b/packages/transform-io/python/itkwasm-transform-io/itkwasm_transform_io/__init__.py index 2d82258a2..d733ccf6b 100644 --- a/packages/transform-io/python/itkwasm-transform-io/itkwasm_transform_io/__init__.py +++ b/packages/transform-io/python/itkwasm-transform-io/itkwasm_transform_io/__init__.py @@ -1,7 +1,10 @@ -# Generated file. To retain edits, remove this comment. - """itkwasm-transform-io: Input and output for scientific and medical coordinate transform file formats.""" +from .read_transform_async import read_transform_async, transformread_async +from .read_transform import read_transform, transformread +from .write_transform_async import write_transform_async, transformwrite_async +from .write_transform import write_transform, transformwrite + from .hdf5_read_transform_async import hdf5_read_transform_async from .hdf5_read_transform import hdf5_read_transform from .hdf5_write_transform_async import hdf5_write_transform_async diff --git a/packages/transform-io/python/itkwasm-transform-io/itkwasm_transform_io/_version.py b/packages/transform-io/python/itkwasm-transform-io/itkwasm_transform_io/_version.py index 3dc1f76bc..485f44ac2 100644 --- a/packages/transform-io/python/itkwasm-transform-io/itkwasm_transform_io/_version.py +++ b/packages/transform-io/python/itkwasm-transform-io/itkwasm_transform_io/_version.py @@ -1 +1 @@ -__version__ = "0.1.0" +__version__ = "0.1.1" diff --git a/packages/transform-io/python/itkwasm-transform-io/itkwasm_transform_io/read_transform.py b/packages/transform-io/python/itkwasm-transform-io/itkwasm_transform_io/read_transform.py new file mode 100644 index 000000000..68f6731fc --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io/itkwasm_transform_io/read_transform.py @@ -0,0 +1,36 @@ +import os +from typing import Optional, Union + +from itkwasm import ( + environment_dispatch, + TransformList, +) + +def read_transform( + serialized_transform: os.PathLike, + float_parameters: bool = False, +) -> TransformList: + """Read a transform file format and convert it to the ITK-Wasm file format + + :param serialized_transform: Input transform serialized in the file format + :type serialized_transform: os.PathLike + + :param float_parameters: Use float for the parameter value type. The default is double. + :type float_parameters: bool + + :return: Output transform + :rtype: TransformList + """ + func = environment_dispatch("itkwasm_transform_io", "read_transform") + output = func(serialized_transform, float_parameters=float_parameters) + return output + +def transformread( + serialized_transform: os.PathLike, + float_parameters: bool = False, +) -> TransformList: + return read_transform(serialized_transform, float_parameters=float_parameters) + +transformread.__doc__ = f"""{read_transform.__doc__} + Alias for read_transform. + """ \ No newline at end of file diff --git a/packages/transform-io/python/itkwasm-transform-io/itkwasm_transform_io/read_transform_async.py b/packages/transform-io/python/itkwasm-transform-io/itkwasm_transform_io/read_transform_async.py new file mode 100644 index 000000000..2cffceb92 --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io/itkwasm_transform_io/read_transform_async.py @@ -0,0 +1,36 @@ +import os +from typing import Optional, Union + +from itkwasm import ( + environment_dispatch, + TransformList, +) + +async def read_transform_async( + serialized_transform: os.PathLike, + float_parameters: bool = False, +) -> TransformList: + """Read an transform file format and convert it to the ITK-Wasm file format. + + :param serialized_transform: Input transform serialized in the file format + :type serialized_transform: os.PathLike + + :param float_parameters: Use float for the parameter value type. The default is double. + :type float_parameters: bool + + :return: Output transform + :rtype: TransformList + """ + func = environment_dispatch("itkwasm_transform_io", "read_transform_async") + output = await func(serialized_transform, float_parameters=float_parameters) + return output + +async def transformread_async( + serialized_transform: os.PathLike, + float_parameters: bool = False, +) -> TransformList: + return await read_transform_async(serialized_transform, float_parameters=float_parameters) + +transformread_async.__doc__ = f"""{read_transform_async.__doc__} + Alias for read_transform. + """ \ No newline at end of file diff --git a/packages/transform-io/python/itkwasm-transform-io/itkwasm_transform_io/write_transform.py b/packages/transform-io/python/itkwasm-transform-io/itkwasm_transform_io/write_transform.py new file mode 100644 index 000000000..20ce71cd0 --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io/itkwasm_transform_io/write_transform.py @@ -0,0 +1,43 @@ +import os +from typing import Dict, Tuple, Optional, List, Any + +from itkwasm import ( + environment_dispatch, + TransformList, +) + +def write_transform( + transform: TransformList, + serialized_transform: str, + float_parameters: bool = False, + use_compression: bool = False, +) -> None: + """Write an ITK-Wasm file format converted to a transform file format + + :param transform: Input transform + :type transform: TransformList + + :param serialized_transform: Output transform serialized in the file format. + :type serialized_transform: str + + :param float_parameters: Use float for the parameter value type. The default is double. + :type float_parameters: bool + + :param use_compression: Use compression in the written file + :type use_compression: bool + """ + func = environment_dispatch("itkwasm_transform_io", "write_transform") + func(transform, serialized_transform, float_parameters=float_parameters, use_compression=use_compression) + return + +def transformwrite( + transform: TransformList, + serialized_transform: os.PathLike, + float_parameters: bool = False, + use_compression: bool = False, +) -> None: + return write_transform(transform, serialized_transform, float_parameters=float_parameters, use_compression=use_compression) + +transformwrite.__doc__ = f"""{write_transform.__doc__} + Alias for write_transform. + """ \ No newline at end of file diff --git a/packages/transform-io/python/itkwasm-transform-io/itkwasm_transform_io/write_transform_async.py b/packages/transform-io/python/itkwasm-transform-io/itkwasm_transform_io/write_transform_async.py new file mode 100644 index 000000000..0a2e96ad2 --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io/itkwasm_transform_io/write_transform_async.py @@ -0,0 +1,43 @@ +import os +from typing import Dict, Tuple, Optional, List, Any + +from itkwasm import ( + environment_dispatch, + TransformList, +) + +async def write_transform_async( + transform: TransformList, + serialized_transform: str, + float_parameters: bool = False, + use_compression: bool = False, +) -> None: + """Write an ITK-Wasm file format converted to a transform file format. + + :param transform: Input transform + :type transform: TransformList + + :param serialized_transform: Output transform serialized in the file format. + :type serialized_transform: str + + :param float_parameters: Only write transform metadata -- do not write pixel data. + :type float_parameters: bool + + :param use_compression: Use compression in the written file + :type use_compression: bool + """ + func = environment_dispatch("itkwasm_transform_io", "write_transform_async") + await func(transform, serialized_transform, float_parameters=float_parameters, use_compression=use_compression) + return + +async def transformwrite_async( + transform: TransformList, + serialized_transform: os.PathLike, + float_parameters: bool = False, + use_compression: bool = False, +) -> None: + return await write_transform_async(transform, serialized_transform, float_parameters=float_parameters, use_compression=use_compression) + +transformwrite_async.__doc__ = f"""{write_transform_async.__doc__} + Alias for write_transform. + """ \ No newline at end of file diff --git a/packages/transform-io/python/itkwasm-transform-io/pyproject.toml b/packages/transform-io/python/itkwasm-transform-io/pyproject.toml index e8e4d26ab..f84172e65 100644 --- a/packages/transform-io/python/itkwasm-transform-io/pyproject.toml +++ b/packages/transform-io/python/itkwasm-transform-io/pyproject.toml @@ -5,7 +5,7 @@ build-backend = "hatchling.build" [project] name = "itkwasm-transform-io" readme = "README.md" -license = "Apache-2.0" +license-expression = "Apache-2.0" dynamic = ["version"] description = "Input and output for scientific and medical coordinate transform file formats." classifiers = [ @@ -19,11 +19,11 @@ classifiers = [ "Intended Audience :: Developers", "Intended Audience :: Science/Research", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", ] keywords = [ "itkwasm", @@ -32,9 +32,9 @@ keywords = [ "emscripten", ] -requires-python = ">=3.8" +requires-python = ">=3.9" dependencies = [ - "itkwasm >= 1.0.b171", + "itkwasm >= 1.0.b185", "itkwasm-transform-io-wasi; sys_platform != \"emscripten\"", "itkwasm-transform-io-emscripten; sys_platform == \"emscripten\"", diff --git a/packages/transform-io/python/itkwasm-transform-io/tests/__init__.py b/packages/transform-io/python/itkwasm-transform-io/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/packages/transform-io/python/itkwasm-transform-io/tests/common.py b/packages/transform-io/python/itkwasm-transform-io/tests/common.py new file mode 100644 index 000000000..95b199562 --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io/tests/common.py @@ -0,0 +1,23 @@ +from pathlib import Path +import numpy as np + +from itkwasm import TransformList, TransformParameterizations, FloatTypes + +test_input_path = Path(__file__).parent / ".." / ".." / ".." / "test" / "data" / "input" +test_baseline_path = Path(__file__).parent / ".." / ".." / ".." / "test" / "data" / "baseline" +test_output_path = Path(__file__).parent / ".." / ".." / ".." / "test" / "data" / "output" / "python-dispatch" +test_output_path.mkdir(parents=True, exist_ok=True) + +def verify_test_linear_transform(transform_list: TransformList): + assert len(transform_list) == 1 + transform = transform_list[0] + assert transform.transformType.transformParameterization == TransformParameterizations.Affine + assert transform.transformType.parametersValueType == FloatTypes.Float64 + assert transform.numberOfParameters == 12 + assert transform.numberOfFixedParameters == 3 + np.testing.assert_allclose(transform.fixedParameters, np.array([0.0, 0.0, 0.0])) + np.testing.assert_allclose(transform.parameters, np.array([ + 0.65631490118447, 0.5806583745824385, -0.4817536741017158, + -0.7407986817430222, 0.37486398378429736, -0.5573995934598175, + -0.14306664045479867, 0.7227121458012518, 0.676179776908723, + -65.99999999999997, 69.00000000000004, 32.000000000000036])) diff --git a/packages/transform-io/python/itkwasm-transform-io/tests/fixtures.py b/packages/transform-io/python/itkwasm-transform-io/tests/fixtures.py new file mode 100644 index 000000000..cda5dbaf3 --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io/tests/fixtures.py @@ -0,0 +1,29 @@ +import pytest +import sys +import glob + +if sys.version_info < (3,10): + pytest.skip("Skipping pyodide tests on older Python", allow_module_level=True) + +from pytest_pyodide import run_in_pyodide + +from itkwasm_transform_io import __version__ as test_package_version + +@pytest.fixture +def package_wheel(): + return f"itkwasm_transform_io-{test_package_version}-py3-none-any.whl" + +@pytest.fixture +def emscripten_package_wheel(): + return f"itkwasm_transform_io_emscripten-{test_package_version}-py3-none-any.whl" + +@pytest.fixture +def input_data(): + from pathlib import Path + input_base_path = Path(__file__).parent.parent.parent.parent / 'test' / 'data' / 'input' + test_files = list(input_base_path.glob('*')) + data = {} + for test_file in test_files: + with open(test_file, 'rb') as f: + data[test_file.name] = f.read() + return data diff --git a/packages/transform-io/python/itkwasm-transform-io/tests/test_hdf5_read_transform.py b/packages/transform-io/python/itkwasm-transform-io/tests/test_hdf5_read_transform.py new file mode 100644 index 000000000..c4ec0fc4b --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io/tests/test_hdf5_read_transform.py @@ -0,0 +1,12 @@ +from pathlib import Path + +from itkwasm_transform_io import hdf5_read_transform + +from .common import test_input_path, test_output_path, verify_test_linear_transform + +test_input_file_path = test_input_path / "LinearTransform.h5" + +def test_hdf5_read_transform(): + could_read, transform_list = hdf5_read_transform(test_input_file_path) + assert could_read + verify_test_linear_transform(transform_list) diff --git a/packages/transform-io/python/itkwasm-transform-io/tests/test_hdf5_read_transform_async.py b/packages/transform-io/python/itkwasm-transform-io/tests/test_hdf5_read_transform_async.py new file mode 100644 index 000000000..9d6e0c66d --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io/tests/test_hdf5_read_transform_async.py @@ -0,0 +1,59 @@ +import pytest +import sys + +if sys.version_info < (3,10): + pytest.skip("Skipping pyodide tests on older Python", allow_module_level=True) + +from pytest_pyodide import run_in_pyodide + +from .fixtures import package_wheel, input_data, emscripten_package_wheel + +@run_in_pyodide(packages=['micropip']) +async def test_hdf5_read_transform_async(selenium, package_wheel, emscripten_package_wheel, input_data): + import micropip + await micropip.install(emscripten_package_wheel) + await micropip.install(package_wheel) + + from pathlib import Path + + import numpy as np + from itkwasm import TransformParameterizations, FloatTypes + + from itkwasm_transform_io import hdf5_read_transform_async, hdf5_write_transform_async + + def write_input_data_to_fs(input_data, filename): + with open(filename, 'wb') as fp: + fp.write(input_data[filename]) + + def verify_test_linear_transform(transform_list): + assert len(transform_list) == 1 + transform = transform_list[0] + assert transform.transformType.transformParameterization == TransformParameterizations.Affine + assert transform.transformType.parametersValueType == FloatTypes.Float64 + assert transform.numberOfParameters == 12 + assert transform.numberOfFixedParameters == 3 + np.testing.assert_allclose(transform.fixedParameters, np.array([0.0, 0.0, 0.0])) + np.testing.assert_allclose(transform.parameters, np.array([ + 0.65631490118447, 0.5806583745824385, -0.4817536741017158, + -0.7407986817430222, 0.37486398378429736, -0.5573995934598175, + -0.14306664045479867, 0.7227121458012518, 0.676179776908723, + -65.99999999999997, 69.00000000000004, 32.000000000000036])) + + test_file_path = 'LinearTransform.h5' + write_input_data_to_fs(input_data, test_file_path) + + assert Path(test_file_path).exists() + + could_read, transform = await hdf5_read_transform_async(test_file_path) + assert could_read + verify_test_linear_transform(transform) + + test_output_file_path = 'out-LinearTransform.h5' + + use_compression = False + could_write = await hdf5_write_transform_async(transform, test_output_file_path, use_compression) + assert could_write + + could_read, transform = await hdf5_read_transform_async(test_output_file_path) + assert could_read + verify_test_linear_transform(transform) diff --git a/packages/transform-io/python/itkwasm-transform-io/tests/test_hdf5_write_transform.py b/packages/transform-io/python/itkwasm-transform-io/tests/test_hdf5_write_transform.py new file mode 100644 index 000000000..a86b38c8e --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io/tests/test_hdf5_write_transform.py @@ -0,0 +1,14 @@ +from itkwasm_transform_io import hdf5_read_transform, hdf5_write_transform + +from .common import test_input_path, test_output_path, verify_test_linear_transform + +test_input_file_path = test_input_path / "LinearTransform.h5" +test_output_file_path = test_output_path / "hdf5-test-write-LinearTransform.h5" + +def test_hdf5_write_transform(): + could_read, transform_list = hdf5_read_transform(test_input_file_path) + assert could_read + could_write = hdf5_write_transform(transform_list, test_output_file_path) + assert could_write + could_read, transform_list = hdf5_read_transform(test_output_file_path) + verify_test_linear_transform(transform_list) diff --git a/packages/transform-io/python/itkwasm-transform-io/tests/test_mat_read_transform.py b/packages/transform-io/python/itkwasm-transform-io/tests/test_mat_read_transform.py new file mode 100644 index 000000000..9994ba7fb --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io/tests/test_mat_read_transform.py @@ -0,0 +1,19 @@ +import pytest +import sys + +if sys.version_info < (3,10): + pytest.skip("Skipping pyodide tests on older Python", allow_module_level=True) + +from pytest_pyodide import run_in_pyodide + +from .fixtures import emscripten_package_wheel, package_wheel, input_data + +@run_in_pyodide(packages=['micropip']) +async def test_mat_read_transform(selenium, package_wheel, emscripten_package_wheel): + import micropip + await micropip.install(emscripten_package_wheel) + await micropip.install(package_wheel) + + from itkwasm_transform_io import mat_read_transform + + # Write your test code here diff --git a/packages/transform-io/python/itkwasm-transform-io/tests/test_mat_write_transform.py b/packages/transform-io/python/itkwasm-transform-io/tests/test_mat_write_transform.py new file mode 100644 index 000000000..a35eee18d --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io/tests/test_mat_write_transform.py @@ -0,0 +1,19 @@ +import pytest +import sys + +if sys.version_info < (3,10): + pytest.skip("Skipping pyodide tests on older Python", allow_module_level=True) + +from pytest_pyodide import run_in_pyodide + +from .fixtures import emscripten_package_wheel, package_wheel, input_data + +@run_in_pyodide(packages=['micropip']) +async def test_mat_write_transform(selenium, package_wheel, emscripten_package_wheel): + import micropip + await micropip.install(emscripten_package_wheel) + await micropip.install(package_wheel) + + from itkwasm_transform_io import mat_write_transform + + # Write your test code here diff --git a/packages/transform-io/python/itkwasm-transform-io/tests/test_mnc_read_transform.py b/packages/transform-io/python/itkwasm-transform-io/tests/test_mnc_read_transform.py new file mode 100644 index 000000000..3f140fdbd --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io/tests/test_mnc_read_transform.py @@ -0,0 +1,19 @@ +import pytest +import sys + +if sys.version_info < (3,10): + pytest.skip("Skipping pyodide tests on older Python", allow_module_level=True) + +from pytest_pyodide import run_in_pyodide + +from .fixtures import emscripten_package_wheel, package_wheel, input_data + +@run_in_pyodide(packages=['micropip']) +async def test_mnc_read_transform(selenium, package_wheel, emscripten_package_wheel): + import micropip + await micropip.install(emscripten_package_wheel) + await micropip.install(package_wheel) + + from itkwasm_transform_io import mnc_read_transform + + # Write your test code here diff --git a/packages/transform-io/python/itkwasm-transform-io/tests/test_mnc_write_transform.py b/packages/transform-io/python/itkwasm-transform-io/tests/test_mnc_write_transform.py new file mode 100644 index 000000000..e48b67705 --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io/tests/test_mnc_write_transform.py @@ -0,0 +1,19 @@ +import pytest +import sys + +if sys.version_info < (3,10): + pytest.skip("Skipping pyodide tests on older Python", allow_module_level=True) + +from pytest_pyodide import run_in_pyodide + +from .fixtures import emscripten_package_wheel, package_wheel, input_data + +@run_in_pyodide(packages=['micropip']) +async def test_mnc_write_transform(selenium, package_wheel, emscripten_package_wheel): + import micropip + await micropip.install(emscripten_package_wheel) + await micropip.install(package_wheel) + + from itkwasm_transform_io import mnc_write_transform + + # Write your test code here diff --git a/packages/transform-io/python/itkwasm-transform-io/tests/test_read_write_transform.py b/packages/transform-io/python/itkwasm-transform-io/tests/test_read_write_transform.py new file mode 100644 index 000000000..bfd006a7e --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io/tests/test_read_write_transform.py @@ -0,0 +1,36 @@ +from itkwasm import IntTypes, FloatTypes +import numpy as np + +from itkwasm_transform_io import read_transform, transformread, write_transform, transformwrite + +from .common import test_input_path, test_output_path, verify_test_linear_transform +verify_transform = verify_test_linear_transform + +test_input_file_path = test_input_path / "LinearTransform.h5" +test_output_file_path = test_output_path / "read-write-LinearTransform.h5" + +def test_read_transform(): + transform = read_transform(test_input_file_path) + verify_transform(transform) + +def test_transformread(): + transform = transformread(test_input_file_path) + verify_transform(transform) + +def test_write_transform(): + transform = read_transform(test_input_file_path) + + use_compression = False + write_transform(transform, test_output_file_path, use_compression=use_compression) + + transform = read_transform(test_output_file_path) + verify_transform(transform) + +def test_transformwrite(): + transform = transformread(test_input_file_path) + + use_compression = False + transformwrite(transform, test_output_file_path, use_compression=use_compression) + + transform = transformread(test_output_file_path) + verify_transform(transform) diff --git a/packages/transform-io/python/itkwasm-transform-io/tests/test_read_write_transform_async.py b/packages/transform-io/python/itkwasm-transform-io/tests/test_read_write_transform_async.py new file mode 100644 index 000000000..4cd1443ce --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io/tests/test_read_write_transform_async.py @@ -0,0 +1,59 @@ +import sys + +if sys.version_info < (3,10): + pytest.skip("Skipping pyodide tests on older Python", allow_module_level=True) + +import pytest +from pytest_pyodide import run_in_pyodide +from .fixtures import package_wheel, input_data, emscripten_package_wheel + +@pytest.mark.driver_timeout(30) +@run_in_pyodide(packages=['micropip', 'numpy']) +async def test_read_write_mesh_async(selenium, package_wheel, emscripten_package_wheel, input_data): + import micropip + await micropip.install(emscripten_package_wheel) + await micropip.install(package_wheel) + def write_input_data_to_fs(input_data, filename): + with open(filename, 'wb') as fp: + fp.write(input_data[filename]) + + from pathlib import Path + + from itkwasm import TransformParameterizations, FloatTypes + import numpy as np + + from itkwasm_transform_io import read_transform_async, write_transform_async + + def write_input_data_to_fs(input_data, filename): + with open(filename, 'wb') as fp: + fp.write(input_data[filename]) + + def verify_test_linear_transform(transform_list): + assert len(transform_list) == 1 + transform = transform_list[0] + assert transform.transformType.transformParameterization == TransformParameterizations.Affine + assert transform.transformType.parametersValueType == FloatTypes.Float64 + assert transform.numberOfParameters == 12 + assert transform.numberOfFixedParameters == 3 + np.testing.assert_allclose(transform.fixedParameters, np.array([0.0, 0.0, 0.0])) + np.testing.assert_allclose(transform.parameters, np.array([ + 0.65631490118447, 0.5806583745824385, -0.4817536741017158, + -0.7407986817430222, 0.37486398378429736, -0.5573995934598175, + -0.14306664045479867, 0.7227121458012518, 0.676179776908723, + -65.99999999999997, 69.00000000000004, 32.000000000000036])) + + test_file_path = 'LinearTransform.h5' + write_input_data_to_fs(input_data, test_file_path) + + assert Path(test_file_path).exists() + + transform = await read_transform_async(test_file_path) + verify_test_linear_transform(transform) + + test_output_file_path = 'out-LinearTransform.h5' + + use_compression = False + await write_transform_async(transform, test_output_file_path, use_compression) + + transform = await read_transform_async(test_output_file_path) + verify_test_linear_transform(transform) diff --git a/packages/transform-io/python/itkwasm-transform-io/tests/test_txt_read_transform.py b/packages/transform-io/python/itkwasm-transform-io/tests/test_txt_read_transform.py new file mode 100644 index 000000000..73cf1e646 --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io/tests/test_txt_read_transform.py @@ -0,0 +1,19 @@ +import pytest +import sys + +if sys.version_info < (3,10): + pytest.skip("Skipping pyodide tests on older Python", allow_module_level=True) + +from pytest_pyodide import run_in_pyodide + +from .fixtures import emscripten_package_wheel, package_wheel, input_data + +@run_in_pyodide(packages=['micropip']) +async def test_txt_read_transform(selenium, package_wheel, emscripten_package_wheel): + import micropip + await micropip.install(emscripten_package_wheel) + await micropip.install(package_wheel) + + from itkwasm_transform_io import txt_read_transform + + # Write your test code here diff --git a/packages/transform-io/python/itkwasm-transform-io/tests/test_txt_write_transform.py b/packages/transform-io/python/itkwasm-transform-io/tests/test_txt_write_transform.py new file mode 100644 index 000000000..980dccfea --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io/tests/test_txt_write_transform.py @@ -0,0 +1,19 @@ +import pytest +import sys + +if sys.version_info < (3,10): + pytest.skip("Skipping pyodide tests on older Python", allow_module_level=True) + +from pytest_pyodide import run_in_pyodide + +from .fixtures import emscripten_package_wheel, package_wheel, input_data + +@run_in_pyodide(packages=['micropip']) +async def test_txt_write_transform(selenium, package_wheel, emscripten_package_wheel): + import micropip + await micropip.install(emscripten_package_wheel) + await micropip.install(package_wheel) + + from itkwasm_transform_io import txt_write_transform + + # Write your test code here diff --git a/packages/transform-io/python/itkwasm-transform-io/tests/test_wasm_read_transform.py b/packages/transform-io/python/itkwasm-transform-io/tests/test_wasm_read_transform.py new file mode 100644 index 000000000..f4d825e23 --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io/tests/test_wasm_read_transform.py @@ -0,0 +1,19 @@ +import pytest +import sys + +if sys.version_info < (3,10): + pytest.skip("Skipping pyodide tests on older Python", allow_module_level=True) + +from pytest_pyodide import run_in_pyodide + +from .fixtures import emscripten_package_wheel, package_wheel, input_data + +@run_in_pyodide(packages=['micropip']) +async def test_wasm_read_transform(selenium, package_wheel, emscripten_package_wheel): + import micropip + await micropip.install(emscripten_package_wheel) + await micropip.install(package_wheel) + + from itkwasm_transform_io import wasm_read_transform + + # Write your test code here diff --git a/packages/transform-io/python/itkwasm-transform-io/tests/test_wasm_write_transform.py b/packages/transform-io/python/itkwasm-transform-io/tests/test_wasm_write_transform.py new file mode 100644 index 000000000..8e0458262 --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io/tests/test_wasm_write_transform.py @@ -0,0 +1,19 @@ +import pytest +import sys + +if sys.version_info < (3,10): + pytest.skip("Skipping pyodide tests on older Python", allow_module_level=True) + +from pytest_pyodide import run_in_pyodide + +from .fixtures import emscripten_package_wheel, package_wheel, input_data + +@run_in_pyodide(packages=['micropip']) +async def test_wasm_write_transform(selenium, package_wheel, emscripten_package_wheel): + import micropip + await micropip.install(emscripten_package_wheel) + await micropip.install(package_wheel) + + from itkwasm_transform_io import wasm_write_transform + + # Write your test code here diff --git a/packages/transform-io/python/itkwasm-transform-io/tests/test_wasm_zstd_read_transform.py b/packages/transform-io/python/itkwasm-transform-io/tests/test_wasm_zstd_read_transform.py new file mode 100644 index 000000000..50466c5c7 --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io/tests/test_wasm_zstd_read_transform.py @@ -0,0 +1,19 @@ +import pytest +import sys + +if sys.version_info < (3,10): + pytest.skip("Skipping pyodide tests on older Python", allow_module_level=True) + +from pytest_pyodide import run_in_pyodide + +from .fixtures import emscripten_package_wheel, package_wheel, input_data + +@run_in_pyodide(packages=['micropip']) +async def test_wasm_zstd_read_transform(selenium, package_wheel, emscripten_package_wheel): + import micropip + await micropip.install(emscripten_package_wheel) + await micropip.install(package_wheel) + + from itkwasm_transform_io import wasm_zstd_read_transform + + # Write your test code here diff --git a/packages/transform-io/python/itkwasm-transform-io/tests/test_wasm_zstd_write_transform.py b/packages/transform-io/python/itkwasm-transform-io/tests/test_wasm_zstd_write_transform.py new file mode 100644 index 000000000..2e5c5e133 --- /dev/null +++ b/packages/transform-io/python/itkwasm-transform-io/tests/test_wasm_zstd_write_transform.py @@ -0,0 +1,19 @@ +import pytest +import sys + +if sys.version_info < (3,10): + pytest.skip("Skipping pyodide tests on older Python", allow_module_level=True) + +from pytest_pyodide import run_in_pyodide + +from .fixtures import emscripten_package_wheel, package_wheel, input_data + +@run_in_pyodide(packages=['micropip']) +async def test_wasm_zstd_write_transform(selenium, package_wheel, emscripten_package_wheel): + import micropip + await micropip.install(emscripten_package_wheel) + await micropip.install(package_wheel) + + from itkwasm_transform_io import wasm_zstd_write_transform + + # Write your test code here