diff --git a/.github/scripts/cmd/cmd.py b/.github/scripts/cmd/cmd.py index 2c017b7d0c3ef59c37cd2b43b3dd9184933dcdc4..e65f10a97b4e8ee56d73dd8fa34613bdaa927a2e 100755 --- a/.github/scripts/cmd/cmd.py +++ b/.github/scripts/cmd/cmd.py @@ -44,34 +44,6 @@ setup_logging() BENCH """ -bench_example = '''**Examples**: - Runs all benchmarks - %(prog)s - - Runs benchmarks for pallet_balances and pallet_multisig for all runtimes which have these pallets. **--quiet** makes it to output nothing to PR but reactions - %(prog)s --pallet pallet_balances pallet_xcm_benchmarks::generic --quiet - - Runs bench for all pallets for westend runtime and fails fast on first failed benchmark - %(prog)s --runtime westend --fail-fast - - Does not output anything and cleans up the previous bot's & author command triggering comments in PR - %(prog)s --runtime westend rococo --pallet pallet_balances pallet_multisig --quiet --clean -''' - -parser_bench = subparsers.add_parser('bench', help='Runs benchmarks (old CLI)', epilog=bench_example, formatter_class=argparse.RawDescriptionHelpFormatter) - -for arg, config in common_args.items(): - parser_bench.add_argument(arg, **config) - -parser_bench.add_argument('--runtime', help='Runtime(s) space separated', choices=runtimeNames, nargs='*', default=runtimeNames) -parser_bench.add_argument('--pallet', help='Pallet(s) space separated', nargs='*', default=[]) -parser_bench.add_argument('--fail-fast', help='Fail fast on first failed benchmark', action='store_true') - - -""" -BENCH OMNI -""" - bench_example = '''**Examples**: Runs all benchmarks %(prog)s @@ -86,14 +58,14 @@ bench_example = '''**Examples**: %(prog)s --runtime westend rococo --pallet pallet_balances pallet_multisig --quiet --clean ''' -parser_bench_old = subparsers.add_parser('bench-omni', help='Runs benchmarks (frame omni bencher)', epilog=bench_example, formatter_class=argparse.RawDescriptionHelpFormatter) +parser_bench = subparsers.add_parser('bench', aliases=['bench-omni'], help='Runs benchmarks (frame omni bencher)', epilog=bench_example, formatter_class=argparse.RawDescriptionHelpFormatter) for arg, config in common_args.items(): - parser_bench_old.add_argument(arg, **config) + parser_bench.add_argument(arg, **config) -parser_bench_old.add_argument('--runtime', help='Runtime(s) space separated', choices=runtimeNames, nargs='*', default=runtimeNames) -parser_bench_old.add_argument('--pallet', help='Pallet(s) space separated', nargs='*', default=[]) -parser_bench_old.add_argument('--fail-fast', help='Fail fast on first failed benchmark', action='store_true') +parser_bench.add_argument('--runtime', help='Runtime(s) space separated', choices=runtimeNames, nargs='*', default=runtimeNames) +parser_bench.add_argument('--pallet', help='Pallet(s) space separated', nargs='*', default=[]) +parser_bench.add_argument('--fail-fast', help='Fail fast on first failed benchmark', action='store_true') """ @@ -127,7 +99,7 @@ def main(): print(f'args: {args}') - if args.command == 'bench-omni': + if args.command == 'bench' or args.command == 'bench-omni': runtime_pallets_map = {} failed_benchmarks = {} successful_benchmarks = {} @@ -140,11 +112,23 @@ def main(): runtimesMatrix = {x['name']: x for x in runtimesMatrix} print(f'Filtered out runtimes: {runtimesMatrix}') + compile_bencher = os.system(f"cargo install --path substrate/utils/frame/omni-bencher --locked --profile {profile}") + if compile_bencher != 0: + print_and_log('⌠Failed to compile frame-omni-bencher') + sys.exit(1) + # loop over remaining runtimes to collect available pallets for runtime in runtimesMatrix.values(): build_command = f"forklift cargo build -p {runtime['package']} --profile {profile} --features={runtime['bench_features']}" print(f'-- building "{runtime["name"]}" with `{build_command}`') - os.system(build_command) + build_status = os.system(build_command) + if build_status != 0: + print_and_log(f'⌠Failed to build {runtime["name"]}') + if args.fail_fast: + sys.exit(1) + else: + continue + print(f'-- listing pallets for benchmark for {runtime["name"]}') wasm_file = f"target/{profile}/wbuild/{runtime['package']}/{runtime['package'].replace('-', '_')}.wasm" list_command = f"frame-omni-bencher v1 benchmark pallet " \ @@ -219,12 +203,15 @@ def main(): # TODO: we can remove once all pallets in dev runtime are migrated to polkadot-sdk-frame try: uses_polkadot_sdk_frame = "true" in os.popen(f"cargo metadata --locked --format-version 1 --no-deps | jq -r '.packages[] | select(.name == \"{pallet.replace('_', '-')}\") | .dependencies | any(.name == \"polkadot-sdk-frame\")'").read() + print(f'uses_polkadot_sdk_frame: {uses_polkadot_sdk_frame}') # Empty output from the previous os.popen command except StopIteration: + print(f'Error: {pallet} not found in dev runtime') uses_polkadot_sdk_frame = False template = config['template'] if uses_polkadot_sdk_frame and re.match(r"frame-(:?umbrella-)?weight-template\.hbs", os.path.normpath(template).split(os.path.sep)[-1]): template = "substrate/.maintain/frame-umbrella-weight-template.hbs" + print(f'template: {template}') else: default_path = f"./{config['path']}/src/weights" xcm_path = f"./{config['path']}/src/weights/xcm" @@ -270,149 +257,6 @@ def main(): print_and_log('✅ Successful benchmarks of runtimes/pallets:') for runtime, pallets in successful_benchmarks.items(): print_and_log(f'-- {runtime}: {pallets}') - - if args.command == 'bench': - runtime_pallets_map = {} - failed_benchmarks = {} - successful_benchmarks = {} - - profile = "production" - - print(f'Provided runtimes: {args.runtime}') - # convert to mapped dict - runtimesMatrix = list(filter(lambda x: x['name'] in args.runtime, runtimesMatrix)) - runtimesMatrix = {x['name']: x for x in runtimesMatrix} - print(f'Filtered out runtimes: {runtimesMatrix}') - - # loop over remaining runtimes to collect available pallets - for runtime in runtimesMatrix.values(): - build_command = f"forklift cargo build -p {runtime['old_package']} --profile {profile} --features={runtime['bench_features']} --locked" - print(f'-- building {runtime["name"]} with `{build_command}`') - os.system(build_command) - - chain = runtime['name'] if runtime['name'] == 'dev' else f"{runtime['name']}-dev" - - machine_test = f"target/{profile}/{runtime['old_bin']} benchmark machine --chain={chain}" - print(f"Running machine test for `{machine_test}`") - os.system(machine_test) - - print(f'-- listing pallets for benchmark for {chain}') - list_command = f"target/{profile}/{runtime['old_bin']} " \ - f"benchmark pallet " \ - f"--no-csv-header " \ - f"--no-storage-info " \ - f"--no-min-squares " \ - f"--no-median-slopes " \ - f"--all " \ - f"--list " \ - f"--chain={chain}" - print(f'-- running: {list_command}') - output = os.popen(list_command).read() - raw_pallets = output.strip().split('\n') - - all_pallets = set() - for pallet in raw_pallets: - if pallet: - all_pallets.add(pallet.split(',')[0].strip()) - - pallets = list(all_pallets) - print(f'Pallets in {runtime["name"]}: {pallets}') - runtime_pallets_map[runtime['name']] = pallets - - print(f'\n') - - # filter out only the specified pallets from collected runtimes/pallets - if args.pallet: - print(f'Pallets: {args.pallet}') - new_pallets_map = {} - # keep only specified pallets if they exist in the runtime - for runtime in runtime_pallets_map: - if set(args.pallet).issubset(set(runtime_pallets_map[runtime])): - new_pallets_map[runtime] = args.pallet - - runtime_pallets_map = new_pallets_map - - print(f'Filtered out runtimes & pallets: {runtime_pallets_map}\n') - - if not runtime_pallets_map: - if args.pallet and not args.runtime: - print(f"No pallets {args.pallet} found in any runtime") - elif args.runtime and not args.pallet: - print(f"{args.runtime} runtime does not have any pallets") - elif args.runtime and args.pallet: - print(f"No pallets {args.pallet} found in {args.runtime}") - else: - print('No runtimes found') - sys.exit(1) - - for runtime in runtime_pallets_map: - for pallet in runtime_pallets_map[runtime]: - config = runtimesMatrix[runtime] - header_path = os.path.abspath(config['header']) - template = None - - chain = config['name'] if runtime == 'dev' else f"{config['name']}-dev" - - print(f'-- config: {config}') - if runtime == 'dev': - # to support sub-modules (https://github.com/paritytech/command-bot/issues/275) - search_manifest_path = f"cargo metadata --locked --format-version 1 --no-deps | jq -r '.packages[] | select(.name == \"{pallet.replace('_', '-')}\") | .manifest_path'" - print(f'-- running: {search_manifest_path}') - manifest_path = os.popen(search_manifest_path).read() - if not manifest_path: - print(f'-- pallet {pallet} not found in dev runtime') - if args.fail_fast: - print_and_log(f'Error: {pallet} not found in dev runtime') - sys.exit(1) - package_dir = os.path.dirname(manifest_path) - print(f'-- package_dir: {package_dir}') - print(f'-- manifest_path: {manifest_path}') - output_path = os.path.join(package_dir, "src", "weights.rs") - template = config['template'] - else: - default_path = f"./{config['path']}/src/weights" - xcm_path = f"./{config['path']}/src/weights/xcm" - output_path = default_path - if pallet.startswith("pallet_xcm_benchmarks"): - template = config['template'] - output_path = xcm_path - - print(f'-- benchmarking {pallet} in {runtime} into {output_path}') - cmd = f"target/{profile}/{config['old_bin']} benchmark pallet " \ - f"--extrinsic=* " \ - f"--chain={chain} " \ - f"--pallet={pallet} " \ - f"--header={header_path} " \ - f"--output={output_path} " \ - f"--wasm-execution=compiled " \ - f"--steps=50 " \ - f"--repeat=20 " \ - f"--heap-pages=4096 " \ - f"{f'--template={template} ' if template else ''}" \ - f"--no-storage-info --no-min-squares --no-median-slopes " - print(f'-- Running: {cmd} \n') - status = os.system(cmd) - - if status != 0 and args.fail_fast: - print_and_log(f'⌠Failed to benchmark {pallet} in {runtime}') - sys.exit(1) - - # Otherwise collect failed benchmarks and print them at the end - # push failed pallets to failed_benchmarks - if status != 0: - failed_benchmarks[f'{runtime}'] = failed_benchmarks.get(f'{runtime}', []) + [pallet] - else: - successful_benchmarks[f'{runtime}'] = successful_benchmarks.get(f'{runtime}', []) + [pallet] - - if failed_benchmarks: - print_and_log('⌠Failed benchmarks of runtimes/pallets:') - for runtime, pallets in failed_benchmarks.items(): - print_and_log(f'-- {runtime}: {pallets}') - - if successful_benchmarks: - print_and_log('✅ Successful benchmarks of runtimes/pallets:') - for runtime, pallets in successful_benchmarks.items(): - print_and_log(f'-- {runtime}: {pallets}') elif args.command == 'fmt': command = f"cargo +nightly fmt" diff --git a/.github/workflows/bench-all-runtimes.yml b/.github/workflows/bench-all-runtimes.yml new file mode 100644 index 0000000000000000000000000000000000000000..fa36a6c249776e152c1df82884f864b1ba62a9cc --- /dev/null +++ b/.github/workflows/bench-all-runtimes.yml @@ -0,0 +1,214 @@ +name: Bench all runtimes + +on: + # schedule: + # - cron: '0 1 * * 0' # weekly on Sunday night 01:00 UTC + workflow_dispatch: + inputs: + draft: + type: boolean + default: false + description: "Whether to create a draft PR" + +permissions: # allow the action to create a PR + contents: write + issues: write + pull-requests: write + actions: read + +jobs: + preflight: + uses: ./.github/workflows/reusable-preflight.yml + + runtime-matrix: + runs-on: ubuntu-latest + needs: [preflight] + timeout-minutes: 30 + outputs: + runtime: ${{ steps.runtime.outputs.runtime }} + branch: ${{ steps.branch.outputs.branch }} + date: ${{ steps.branch.outputs.date }} + container: + image: ${{ needs.preflight.outputs.IMAGE }} + name: Extract runtimes from matrix + steps: + - uses: actions/checkout@v4 + with: + ref: master + + - name: Extract runtimes + id: runtime + run: | + RUNTIMES=$(jq '[.[] | select(.package != null)]' .github/workflows/runtimes-matrix.json) + + RUNTIMES=$(echo $RUNTIMES | jq -c .) + echo "runtime=$RUNTIMES" + echo "runtime=$RUNTIMES" >> $GITHUB_OUTPUT + + - name: Create branch + id: branch + run: | + DATE=$(date +'%Y-%m-%d-%s') + BRANCH="update-weights-weekly-$DATE" + # Fixes "detected dubious ownership" error in the ci + git config --global --add safe.directory $GITHUB_WORKSPACE + + git checkout -b $BRANCH + git push --set-upstream origin $BRANCH + + echo "date=$DATE" >> $GITHUB_OUTPUT + echo "branch=$BRANCH" >> $GITHUB_OUTPUT + + run-frame-omni-bencher: + needs: [preflight, runtime-matrix] + runs-on: ${{ needs.preflight.outputs.RUNNER_WEIGHTS }} + # 24 hours per runtime. + # Max it takes 14hr for westend to recalculate, but due to limited runners, + # sometimes it can take longer. + timeout-minutes: 1440 + strategy: + fail-fast: false # keep running other workflows even if one fails, to see the logs of all possible failures + matrix: + runtime: ${{ fromJSON(needs.runtime-matrix.outputs.runtime) }} + container: + image: ${{ needs.preflight.outputs.IMAGE }} + env: + PACKAGE_NAME: ${{ matrix.runtime.package }} + FLAGS: ${{ matrix.runtime.bench_flags }} + RUST_LOG: "frame_omni_bencher=info,polkadot_sdk_frame=info" + steps: + + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: ${{ needs.runtime-matrix.outputs.branch }} # checkout always from the initially created branch to avoid conflicts + + - name: script + id: required + run: | + git --version + # Fixes "detected dubious ownership" error in the ci + git config --global --add safe.directory $GITHUB_WORKSPACE + git remote -v + python3 -m pip install -r .github/scripts/generate-prdoc.requirements.txt + python3 .github/scripts/cmd/cmd.py bench --runtime ${{ matrix.runtime.name }} + git add . + git status + + if [ -f /tmp/cmd/command_output.log ]; then + CMD_OUTPUT=$(cat /tmp/cmd/command_output.log) + # export to summary to display in the PR + echo "$CMD_OUTPUT" >> $GITHUB_STEP_SUMMARY + # should be multiline, otherwise it captures the first line only + echo 'cmd_output<<EOF' >> $GITHUB_OUTPUT + echo "$CMD_OUTPUT" >> $GITHUB_OUTPUT + echo 'EOF' >> $GITHUB_OUTPUT + fi + + # Create patch that includes both modifications and new files + git add -A + git diff --staged > diff-${{ matrix.runtime.name }}.patch -U0 + git reset + + - name: Upload diff + uses: actions/upload-artifact@v4 + with: + name: diff-${{ matrix.runtime.name }} + path: diff-${{ matrix.runtime.name }}.patch + + apply-diff-commit: + runs-on: ubuntu-latest + needs: [runtime-matrix, run-frame-omni-bencher] + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: ${{ needs.runtime-matrix.outputs.branch }} + + - name: Download all artifacts + uses: actions/download-artifact@v4 + with: + path: patches + + # needs to be able to trigger CI + - uses: actions/create-github-app-token@v1 + id: generate_token + with: + app-id: ${{ secrets.CMD_BOT_APP_ID }} + private-key: ${{ secrets.CMD_BOT_APP_KEY }} + + - name: Apply diff and create PR + env: + GH_TOKEN: ${{ steps.generate_token.outputs.token }} + BRANCH: ${{ needs.runtime-matrix.outputs.branch }} + DATE: ${{ needs.runtime-matrix.outputs.date }} + run: | + git --version + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + + git status + + # Apply all patches + for file in patches/diff-*/diff-*.patch; do + if [ -f "$file" ] && [ -s "$file" ]; then + echo "Applying $file" + # using --3way and --ours for conflicts resolution. Requires git 2.47+ + git apply "$file" --unidiff-zero --allow-empty --3way --ours || echo "Failed to apply $file" + else + echo "Skipping empty or non-existent patch file: $file" + fi + done + + rm -rf patches + + # Get release tags from 1 and 3 months ago + ONE_MONTH_AGO=$(date -d "1 month ago" +%Y-%m-%d) + THREE_MONTHS_AGO=$(date -d "3 months ago" +%Y-%m-%d) + + # Get tags with their dates + ONE_MONTH_INFO=$(git for-each-ref --sort=-creatordate --format '%(refname:short)|%(creatordate:iso-strict-local)' 'refs/tags/polkadot-v*' | awk -v date="$ONE_MONTH_AGO" -F'|' '$2 <= date {print $0; exit}') + THREE_MONTHS_INFO=$(git for-each-ref --sort=-creatordate --format '%(refname:short)|%(creatordate:iso-strict-local)' 'refs/tags/polkadot-v*' | awk -v date="$THREE_MONTHS_AGO" -F'|' '$2 <= date {print $0; exit}') + + # Split into tag and date + ONE_MONTH_TAG=$(echo "$ONE_MONTH_INFO" | cut -d'|' -f1) + ONE_MONTH_DATE=$(echo "$ONE_MONTH_INFO" | cut -d'|' -f2 | cut -d'T' -f1) + THREE_MONTHS_TAG=$(echo "$THREE_MONTHS_INFO" | cut -d'|' -f1) + THREE_MONTHS_DATE=$(echo "$THREE_MONTHS_INFO" | cut -d'|' -f2 | cut -d'T' -f1) + + # Base URL for Subweight comparisons + BASE_URL="https://weights.tasty.limo/compare?repo=polkadot-sdk&threshold=5&path_pattern=.%2F**%2Fweights%2F**%2F*.rs%2C.%2F**%2Fweights.rs&method=asymptotic&ignore_errors=true&unit=time" + + # Generate comparison links + MASTER_LINK="${BASE_URL}&old=master&new=${BRANCH}" + ONE_MONTH_LINK="${BASE_URL}&old=${ONE_MONTH_TAG}&new=${BRANCH}" + THREE_MONTHS_LINK="${BASE_URL}&old=${THREE_MONTHS_TAG}&new=${BRANCH}" + + # Create PR body with all links in a temporary file + cat > /tmp/pr_body.md << EOF + Auto-update of all weights for ${DATE}. + + Subweight results: + - [now vs master](${MASTER_LINK}) + - [now vs ${ONE_MONTH_TAG} (${ONE_MONTH_DATE})](${ONE_MONTH_LINK}) + - [now vs ${THREE_MONTHS_TAG} (${THREE_MONTHS_DATE})](${THREE_MONTHS_LINK}) + EOF + + git add . + git commit -m "Update all weights weekly for $DATE" + git push --set-upstream origin "$BRANCH" + + MAYBE_DRAFT=${{ inputs.draft && '--draft' || '' }} + + PR_TITLE="Auto-update of all weights for $DATE" + gh pr create \ + --title "$PR_TITLE" \ + --head "$BRANCH" \ + --base "master" \ + --reviewer paritytech/ci \ + --reviewer paritytech/release-engineering \ + $MAYBE_DRAFT \ + --label "R0-silent" \ + --body "$(cat /tmp/pr_body.md)" \ No newline at end of file diff --git a/.github/workflows/build-misc.yml b/.github/workflows/build-misc.yml index 335c26282027e6eaeb5d172f0a55a618711bafd8..e1ef29f305d0f1e97866d84a83a960a04734b76c 100644 --- a/.github/workflows/build-misc.yml +++ b/.github/workflows/build-misc.yml @@ -46,6 +46,34 @@ jobs: app-id: ${{ secrets.WORKFLOW_STOPPER_RUNNER_APP_ID }} app-key: ${{ secrets.WORKFLOW_STOPPER_RUNNER_APP_KEY }} + # As part of our test fixtures we build the revive-uapi crate always with the `unstable-hostfn` feature. + # To make sure that it won't break for users downstream which are not setting this feature + # It doesn't need to produce working code so we just use a similar enough RISC-V target + check-revive-stable-uapi-polkavm: + timeout-minutes: 30 + needs: [preflight] + runs-on: ${{ needs.preflight.outputs.RUNNER }} + container: + image: ${{ needs.preflight.outputs.IMAGE }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Check Rust + run: | + rustup show + rustup +nightly show + + - name: Build + id: required + run: forklift cargo +nightly check -p pallet-revive-uapi --no-default-features --target riscv64imac-unknown-none-elf -Zbuild-std=core + - name: Stop all workflows if failed + if: ${{ failure() && steps.required.conclusion == 'failure' && !github.event.pull_request.head.repo.fork }} + uses: ./.github/actions/workflow-stopper + with: + app-id: ${{ secrets.WORKFLOW_STOPPER_RUNNER_APP_ID }} + app-key: ${{ secrets.WORKFLOW_STOPPER_RUNNER_APP_KEY }} + build-subkey: timeout-minutes: 20 needs: [preflight] diff --git a/.github/workflows/check-runtime-migration.yml b/.github/workflows/check-runtime-migration.yml index 9866ae18b98ac7dac962ec823873988c6e1cffad..e935f1cb44981e07f06cfeb74811fec29e9f41a3 100644 --- a/.github/workflows/check-runtime-migration.yml +++ b/.github/workflows/check-runtime-migration.yml @@ -16,6 +16,8 @@ concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true +permissions: {} + jobs: preflight: uses: ./.github/workflows/reusable-preflight.yml diff --git a/.github/workflows/check-semver.yml b/.github/workflows/check-semver.yml index 43c70d6abc78b0aca6fe0738617632a9b33b809a..df1a1c8be6038c3cbd996d1fa0dceb46aeb87b07 100644 --- a/.github/workflows/check-semver.yml +++ b/.github/workflows/check-semver.yml @@ -76,6 +76,7 @@ jobs: if: ${{ !contains(github.event.pull_request.labels.*.name, 'R0-silent') }} run: | rustup default $TOOLCHAIN + rustup target add wasm32-unknown-unknown --toolchain $TOOLCHAIN rustup component add rust-src --toolchain $TOOLCHAIN - name: install parity-publish diff --git a/.github/workflows/cmd.yml b/.github/workflows/cmd.yml index 3d4779064a44fa5244fe1d4ac7bcd06a3696b7fd..44a9a9f0611934d9ed59ba12cb8a98f571859c49 100644 --- a/.github/workflows/cmd.yml +++ b/.github/workflows/cmd.yml @@ -344,11 +344,6 @@ jobs: else echo "arg=" >> $GITHUB_OUTPUT fi - - - name: Install dependencies for bench - if: startsWith(needs.get-pr-info.outputs.CMD, 'bench') - run: | - cargo install --path substrate/utils/frame/omni-bencher --locked - name: Run cmd id: cmd diff --git a/.github/workflows/misc-sync-templates.yml b/.github/workflows/misc-sync-templates.yml index ac66e697562b3f90a6412fdb5c862aee0278c042..71f49b62fbbead4a2a95da776e1fbd4337b20666 100644 --- a/.github/workflows/misc-sync-templates.yml +++ b/.github/workflows/misc-sync-templates.yml @@ -25,9 +25,72 @@ on: description: Enable runner debug logging required: false default: false + patch: + description: 'Patch number of the stable release we want to sync with' + required: false + default: "" jobs: + prepare-chain-spec-artifacts: + runs-on: ubuntu-latest + strategy: + matrix: + include: + - template: minimal + package_name: 'minimal-template-runtime' + runtime_path: './templates/minimal/runtime' + runtime_wasm_path: minimal-template-runtime/minimal_template_runtime.compact.compressed.wasm + relay_chain: 'dev' + - template: parachain + package_name: 'parachain-template-runtime' + runtime_path: './templates/parachain/runtime' + runtime_wasm_path: parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm + relay_chain: 'rococo-local' + steps: + - uses: actions/checkout@v4 + with: + ref: "${{ github.event.inputs.stable_release_branch }}" + + - name: Setup build environment + run: | + sudo apt-get update + sudo apt-get install -y protobuf-compiler + cargo install --git https://github.com/chevdor/srtool-cli --locked + cargo install --path substrate/bin/utils/chain-spec-builder --locked + srtool pull + + - name: Build runtime and generate chain spec + run: | + # Prepare directories + sudo mkdir -p ${{ matrix.runtime_path }}/target + sudo chmod -R 777 ${{ matrix.runtime_path }}/target + + # Build runtime + srtool build --package ${{ matrix.package_name }} --runtime-dir ${{ matrix.runtime_path }} --root + + # Generate chain spec + # Note that para-id is set to 1000 for both minimal/parachain templates. + # `parachain-runtime` is hardcoded to use this parachain id. + # `minimal` template isn't using it, but when started with Omni Node, this para id is required (any number can do it, so setting it to 1000 for convenience). + chain-spec-builder -c dev_chain_spec.json create \ + --relay-chain "${{ matrix.relay_chain }}" \ + --para-id 1000 \ + --runtime "${{ matrix.runtime_path }}/target/srtool/release/wbuild/${{ matrix.runtime_wasm_path }}" \ + named-preset development + + - name: Prepare upload directory + run: | + mkdir -p artifacts-${{ matrix.template }} + cp dev_chain_spec.json artifacts-${{ matrix.template }}/dev_chain_spec.json + + - name: Upload template directory + uses: actions/upload-artifact@v4 + with: + name: artifacts-${{ matrix.template }} + path: artifacts-${{ matrix.template }}/dev_chain_spec.json + sync-templates: + needs: prepare-chain-spec-artifacts runs-on: ubuntu-latest environment: master strategy: @@ -48,6 +111,12 @@ jobs: with: path: polkadot-sdk ref: "${{ github.event.inputs.stable_release_branch }}" + - name: Download template artifacts + uses: actions/download-artifact@v4 + with: + name: artifacts-${{ matrix.template }} + path: templates/${{ matrix.template }}/ + if: matrix.template != 'solochain' - name: Generate a token for the template repository id: app_token uses: actions/create-github-app-token@v1.9.3 @@ -80,6 +149,10 @@ jobs: working-directory: polkadot-sdk/templates/${{ matrix.template }}/ - name: Create a new workspace Cargo.toml run: | + # This replaces the existing Cargo.toml for parachain-template, + # corresponding to the `parachain-template-docs` crate, so no need + # to delete that `Cargo.toml` after copying the `polkadot-sdk/templates/parachain/*` + # to the `polkadot-sdk-parachain-template` repo. cat << EOF > Cargo.toml [workspace.package] license = "MIT-0" @@ -135,11 +208,17 @@ jobs: if: ${{ matrix.template == 'parachain' }} run: | rm -f "${{ env.template-path }}/README.docify.md" - rm -f "${{ env.template-path }}/Cargo.toml" rm -f "${{ env.template-path }}/src/lib.rs" - name: Run psvm on monorepo workspace dependencies - run: psvm -o -v ${{ github.event.inputs.stable_release_branch }} -p ./Cargo.toml + run: | + patch_input="${{ github.event.inputs.patch }}" + if [[ -n "$patch_input" ]]; then + patch="-$patch_input" + else + patch="" + fi + psvm -o -v "${{ github.event.inputs.stable_release_branch }}$patch" -p ./Cargo.toml working-directory: polkadot-sdk/ - name: Copy over required workspace dependencies run: | diff --git a/.github/workflows/release-10_branchoff-stable.yml b/.github/workflows/release-10_branchoff-stable.yml index adce1b261b71f7f7ee6795403c4651cfab889f23..cfe135ac7299e9e0bc53eda6f2c333d58f994bdd 100644 --- a/.github/workflows/release-10_branchoff-stable.yml +++ b/.github/workflows/release-10_branchoff-stable.yml @@ -92,8 +92,11 @@ jobs: . ./.github/scripts/release/release_lib.sh NODE_VERSION="${{ needs.prepare-tooling.outputs.node_version }}" - set_version "\(NODE_VERSION[^=]*= \)\".*\"" $NODE_VERSION "polkadot/node/primitives/src/lib.rs" + NODE_VERSION_PATTERN="\(NODE_VERSION[^=]*= \)\".*\"" + set_version $NODE_VERSION_PATTERN $NODE_VERSION "polkadot/node/primitives/src/lib.rs" commit_with_message "Bump node version to $NODE_VERSION in polkadot-cli" + set_version $NODE_VERSION_PATTERN $NODE_VERSION "cumulus/polkadot-omni-node/lib/src/nodes/mod.rs" + commit_with_message "Bump node version to $NODE_VERSION in polkadot-omni-node-lib" SPEC_VERSION=$(get_spec_version $NODE_VERSION) runtimes_list=$(get_filtered_runtimes_list) diff --git a/.github/workflows/runtimes-matrix.json b/.github/workflows/runtimes-matrix.json index ff16b7397247fdfaab8d6e95d9ab96da4a6c2fbe..747b2bb4ac8fb7c4e083b6f1c7915f4cb8399895 100644 --- a/.github/workflows/runtimes-matrix.json +++ b/.github/workflows/runtimes-matrix.json @@ -8,8 +8,6 @@ "bench_features": "runtime-benchmarks", "bench_flags": "--genesis-builder-policy=none --exclude-pallets=pallet_xcm,pallet_xcm_benchmarks::fungible,pallet_xcm_benchmarks::generic,pallet_nomination_pools,pallet_remark,pallet_transaction_storage", "uri": null, - "old_package": "staging-node-cli", - "old_bin": "substrate-node", "is_relay": false }, { @@ -21,8 +19,6 @@ "bench_flags": "", "bench_features": "runtime-benchmarks", "uri": "wss://try-runtime-westend.polkadot.io:443", - "old_package": "polkadot", - "old_bin": "polkadot", "is_relay": true }, { @@ -34,8 +30,6 @@ "bench_features": "runtime-benchmarks", "bench_flags": "", "uri": "wss://try-runtime-rococo.polkadot.io:443", - "old_package": "polkadot", - "old_bin": "polkadot", "is_relay": true }, { @@ -47,8 +41,6 @@ "bench_features": "runtime-benchmarks", "bench_flags": "", "uri": "wss://westend-asset-hub-rpc.polkadot.io:443", - "old_package": "polkadot-parachain-bin", - "old_bin": "polkadot-parachain", "is_relay": false }, { @@ -60,8 +52,6 @@ "bench_features": "runtime-benchmarks", "bench_flags": "", "uri": "wss://rococo-asset-hub-rpc.polkadot.io:443", - "old_package": "polkadot-parachain-bin", - "old_bin": "polkadot-parachain", "is_relay": false }, { @@ -73,8 +63,6 @@ "bench_features": "runtime-benchmarks", "bench_flags": "", "uri": "wss://rococo-bridge-hub-rpc.polkadot.io:443", - "old_package": "polkadot-parachain-bin", - "old_bin": "polkadot-parachain", "is_relay": false }, { @@ -86,8 +74,6 @@ "bench_features": "runtime-benchmarks", "bench_flags": "", "uri": "wss://westend-bridge-hub-rpc.polkadot.io:443", - "old_package": "polkadot-parachain-bin", - "old_bin": "polkadot-parachain", "is_relay": false }, { @@ -99,8 +85,6 @@ "bench_features": "runtime-benchmarks", "bench_flags": "", "uri": "wss://westend-collectives-rpc.polkadot.io:443", - "old_package": "polkadot-parachain-bin", - "old_bin": "polkadot-parachain", "is_relay": false }, { @@ -112,8 +96,6 @@ "bench_features": "runtime-benchmarks", "bench_flags": "--genesis-builder-policy=none --exclude-pallets=pallet_xcm", "uri": "wss://rococo-contracts-rpc.polkadot.io:443", - "old_package": "polkadot-parachain-bin", - "old_bin": "polkadot-parachain", "is_relay": false }, { @@ -125,8 +107,6 @@ "bench_features": "runtime-benchmarks", "bench_flags": "--genesis-builder-policy=none --exclude-pallets=pallet_xcm,pallet_xcm_benchmarks::fungible,pallet_xcm_benchmarks::generic", "uri": "wss://rococo-coretime-rpc.polkadot.io:443", - "old_package": "polkadot-parachain-bin", - "old_bin": "polkadot-parachain", "is_relay": false }, { @@ -138,8 +118,6 @@ "bench_features": "runtime-benchmarks", "bench_flags": "--genesis-builder-policy=none --exclude-pallets=pallet_xcm,pallet_xcm_benchmarks::fungible,pallet_xcm_benchmarks::generic", "uri": "wss://westend-coretime-rpc.polkadot.io:443", - "old_package": "polkadot-parachain-bin", - "old_bin": "polkadot-parachain", "is_relay": false }, { @@ -151,8 +129,6 @@ "bench_features": "runtime-benchmarks", "bench_flags": "--genesis-builder-policy=none", "uri": null, - "old_package": "polkadot-parachain-bin", - "old_bin": "polkadot-parachain", "is_relay": false }, { @@ -164,8 +140,6 @@ "bench_features": "runtime-benchmarks", "bench_flags": "--genesis-builder-policy=none --exclude-pallets=pallet_xcm,pallet_xcm_benchmarks::fungible,pallet_xcm_benchmarks::generic", "uri": "wss://rococo-people-rpc.polkadot.io:443", - "old_package": "polkadot-parachain-bin", - "old_bin": "polkadot-parachain", "is_relay": false }, { @@ -177,8 +151,6 @@ "bench_features": "runtime-benchmarks", "bench_flags": "--genesis-builder-policy=none --exclude-pallets=pallet_xcm,pallet_xcm_benchmarks::fungible,pallet_xcm_benchmarks::generic", "uri": "wss://westend-people-rpc.polkadot.io:443", - "old_package": "polkadot-parachain-bin", - "old_bin": "polkadot-parachain", "is_relay": false } ] diff --git a/.gitlab/pipeline/zombienet/polkadot.yml b/.gitlab/pipeline/zombienet/polkadot.yml index 878f241317a42a102e08e7267a9b5d09c1fc1771..4d8d4947daa5ca627c146779e91769e4b104dc5d 100644 --- a/.gitlab/pipeline/zombienet/polkadot.yml +++ b/.gitlab/pipeline/zombienet/polkadot.yml @@ -379,6 +379,23 @@ zombienet-polkadot-elastic-scaling-slot-based-3cores: - unset NEXTEST_SUCCESS_OUTPUT - cargo nextest run --archive-file ./artifacts/polkadot-zombienet-tests.tar.zst --no-capture -- elastic_scaling::slot_based_3cores::slot_based_3cores_test +zombienet-polkadot-elastic-scaling-slot-based-12cores: + extends: + - .zombienet-polkadot-common + needs: + - job: build-polkadot-zombienet-tests + artifacts: true + before_script: + - !reference [ ".zombienet-polkadot-common", "before_script" ] + - export POLKADOT_IMAGE="${ZOMBIENET_INTEGRATION_TEST_IMAGE}" + - export CUMULUS_IMAGE="docker.io/paritypr/test-parachain:${PIPELINE_IMAGE_TAG}" + - export X_INFRA_INSTANCE=spot # use spot by default + script: + # we want to use `--no-capture` in zombienet tests. + - unset NEXTEST_FAILURE_OUTPUT + - unset NEXTEST_SUCCESS_OUTPUT + - cargo nextest run --archive-file ./artifacts/polkadot-zombienet-tests.tar.zst --no-capture -- elastic_scaling::slot_based_12cores::slot_based_12cores_test + zombienet-polkadot-elastic-scaling-doesnt-break-parachains: extends: - .zombienet-polkadot-common @@ -447,3 +464,19 @@ zombienet-polkadot-functional-async-backing-6-seconds-rate: - unset NEXTEST_FAILURE_OUTPUT - unset NEXTEST_SUCCESS_OUTPUT - cargo nextest run --archive-file ./artifacts/polkadot-zombienet-tests.tar.zst --no-capture -- functional::async_backing_6_seconds_rate::async_backing_6_seconds_rate_test + +zombienet-polkadot-functional-duplicate-collations: + extends: + - .zombienet-polkadot-common + needs: + - job: build-polkadot-zombienet-tests + artifacts: true + before_script: + - !reference [ ".zombienet-polkadot-common", "before_script" ] + - export POLKADOT_IMAGE="${ZOMBIENET_INTEGRATION_TEST_IMAGE}" + - export X_INFRA_INSTANCE=spot # use spot by default + script: + # we want to use `--no-capture` in zombienet tests. + - unset NEXTEST_FAILURE_OUTPUT + - unset NEXTEST_SUCCESS_OUTPUT + - cargo nextest run --archive-file ./artifacts/polkadot-zombienet-tests.tar.zst --no-capture -- functional::duplicate_collations::duplicate_collations_test diff --git a/Cargo.lock b/Cargo.lock index c80a852e03ed78293f64bf3f5532d044aee3b943..470759e590a99f534f64bdc59d476fea832c16c9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -36,12 +36,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" -[[package]] -name = "adler2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" - [[package]] name = "adler32" version = "1.2.0" @@ -118,9 +112,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "6748e8def348ed4d14996fa801f4122cd763fff530258cdc03f64b25f89d3a5a" dependencies = [ "memchr", ] @@ -369,24 +363,23 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.18" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", - "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.10" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" [[package]] name = "anstyle-parse" @@ -408,12 +401,12 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "3.0.6" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" dependencies = [ "anstyle", - "windows-sys 0.59.0", + "windows-sys 0.48.0", ] [[package]] @@ -998,7 +991,6 @@ dependencies = [ "pallet-multisig 28.0.0", "pallet-nft-fractionalization 10.0.0", "pallet-nfts 22.0.0", - "pallet-nfts-runtime-api 14.0.0", "pallet-proxy 28.0.0", "pallet-session 28.0.0", "pallet-timestamp 27.0.0", @@ -1133,6 +1125,7 @@ dependencies = [ "pallet-balances 28.0.0", "pallet-collator-selection 9.0.0", "pallet-message-queue 31.0.0", + "pallet-migrations 1.0.0", "pallet-multisig 28.0.0", "pallet-nft-fractionalization 10.0.0", "pallet-nfts 22.0.0", @@ -1686,7 +1679,7 @@ dependencies = [ "cc", "cfg-if", "libc", - "miniz_oxide 0.7.1", + "miniz_oxide", "object 0.32.2", "rustc-demangle", ] @@ -2596,6 +2589,8 @@ dependencies = [ "sp-runtime 31.0.1", "sp-std 14.0.0", "staging-xcm 7.0.0", + "staging-xcm-builder 7.0.0", + "staging-xcm-executor 7.0.0", ] [[package]] @@ -2646,7 +2641,6 @@ dependencies = [ "pallet-bridge-messages 0.7.0", "pallet-message-queue 31.0.0", "pallet-xcm 7.0.0", - "pallet-xcm-bridge-hub 0.2.0", "parachains-common 7.0.0", "parity-scale-codec", "rococo-system-emulated-network", @@ -2779,8 +2773,6 @@ dependencies = [ "bp-relayers 0.7.0", "bp-runtime 0.7.0", "bp-test-utils 0.7.0", - "bp-xcm-bridge-hub 0.2.0", - "bridge-runtime-common 0.7.0", "cumulus-pallet-parachain-system 0.7.0", "cumulus-pallet-xcmp-queue 0.7.0", "frame-support 28.0.0", @@ -2803,6 +2795,7 @@ dependencies = [ "sp-io 30.0.0", "sp-keyring 31.0.0", "sp-runtime 31.0.1", + "sp-std 14.0.0", "sp-tracing 16.0.0", "staging-xcm 7.0.0", "staging-xcm-builder 7.0.0", @@ -2886,7 +2879,6 @@ dependencies = [ "pallet-bridge-messages 0.7.0", "pallet-message-queue 31.0.0", "pallet-xcm 7.0.0", - "pallet-xcm-bridge-hub 0.2.0", "parachains-common 7.0.0", "parity-scale-codec", "rococo-westend-system-emulated-network", @@ -3084,12 +3076,12 @@ dependencies = [ [[package]] name = "bstr" -version = "1.11.3" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "531a9155a481e2ee699d4f98f43c0ca4ff8ee1bfd55c31e9e98fb29d2b176fe0" +checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05" dependencies = [ "memchr", - "regex-automata 0.4.8", + "regex-automata 0.3.6", "serde", ] @@ -3192,9 +3184,9 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.1.9" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" +checksum = "2cfa25e60aea747ec7e1124f238816749faa93759c6ff5b31f1ccdda137f4479" dependencies = [ "serde", ] @@ -3207,7 +3199,7 @@ checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a" dependencies = [ "camino", "cargo-platform", - "semver 1.0.24", + "semver 1.0.18", "serde", "serde_json", "thiserror", @@ -3492,12 +3484,12 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.26" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8eb5e908ef3a6efbe1ed62520fb7287959888c88485abe072543190ecc66783" +checksum = "0fbb260a053428790f3de475e304ff84cdbc4face759ea7a3e64c1edd938a7fc" dependencies = [ "clap_builder", - "clap_derive 4.5.24", + "clap_derive 4.5.13", ] [[package]] @@ -3511,24 +3503,24 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.26" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b01801b5fc6a0a232407abc821660c9c6d25a1cafc0d4f85f29fb8d9afc121" +checksum = "64b17d7ea74e9f833c7dbf2cbe4fb12ff26783eda4782a8975b72f895c9b4d99" dependencies = [ "anstream", "anstyle", - "clap_lex 0.7.4", + "clap_lex 0.7.0", "strsim 0.11.1", "terminal_size", ] [[package]] name = "clap_complete" -version = "4.5.42" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33a7e468e750fa4b6be660e8b5651ad47372e8fb114030b594c2d75d48c5ffd0" +checksum = "aa3c596da3cf0983427b0df0dba359df9182c13bd5b519b585a482b0c351f4e8" dependencies = [ - "clap 4.5.26", + "clap 4.5.13", ] [[package]] @@ -3546,9 +3538,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.24" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c" +checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" dependencies = [ "heck 0.5.0", "proc-macro2 1.0.86", @@ -3567,9 +3559,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.4" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" [[package]] name = "cmd_lib" @@ -3707,6 +3699,7 @@ dependencies = [ "pallet-treasury 27.0.0", "pallet-utility 28.0.0", "pallet-xcm 7.0.0", + "pallet-xcm-benchmarks 7.0.0", "parachains-common 7.0.0", "parachains-runtimes-test-utils 7.0.0", "parity-scale-codec", @@ -3755,23 +3748,23 @@ dependencies = [ [[package]] name = "color-print" -version = "0.3.7" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3aa954171903797d5623e047d9ab69d91b493657917bdfb8c2c80ecaf9cdb6f4" +checksum = "f2a5e6504ed8648554968650feecea00557a3476bc040d0ffc33080e66b646d0" dependencies = [ "color-print-proc-macro", ] [[package]] name = "color-print-proc-macro" -version = "0.3.7" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692186b5ebe54007e45a59aea47ece9eb4108e141326c304cdc91699a7118a22" +checksum = "d51beaa537d73d2d1ff34ee70bc095f170420ab2ec5d687ecd3ec2b0d092514b" dependencies = [ "nom", "proc-macro2 1.0.86", "quote 1.0.37", - "syn 2.0.87", + "syn 1.0.109", ] [[package]] @@ -3892,16 +3885,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "console_error_panic_hook" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" -dependencies = [ - "cfg-if", - "wasm-bindgen", -] - [[package]] name = "const-hex" version = "1.14.0" @@ -4446,7 +4429,7 @@ dependencies = [ "anes", "cast", "ciborium", - "clap 4.5.26", + "clap 4.5.13", "criterion-plot", "futures", "is-terminal", @@ -4591,7 +4574,7 @@ dependencies = [ name = "cumulus-client-cli" version = "0.7.0" dependencies = [ - "clap 4.5.26", + "clap 4.5.13", "parity-scale-codec", "sc-chain-spec", "sc-cli", @@ -4769,7 +4752,6 @@ dependencies = [ "polkadot-parachain-primitives 6.0.0", "polkadot-primitives 7.0.0", "polkadot-test-client", - "portpicker", "rstest", "sc-cli", "sc-client-api", @@ -4782,7 +4764,6 @@ dependencies = [ "sp-runtime 31.0.1", "sp-state-machine 0.35.0", "sp-version 29.0.0", - "substrate-test-utils", "tokio", "tracing", "url", @@ -4826,7 +4807,6 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-overseer", "polkadot-primitives 7.0.0", - "portpicker", "rand", "rstest", "sc-cli", @@ -4840,7 +4820,6 @@ dependencies = [ "sp-runtime 31.0.1", "sp-tracing 16.0.0", "sp-version 29.0.0", - "substrate-test-utils", "tokio", "tracing", ] @@ -5125,7 +5104,7 @@ version = "1.0.0" dependencies = [ "cumulus-primitives-proof-size-hostfunction 0.2.0", "cumulus-primitives-storage-weight-reclaim 1.0.0", - "derivative", + "derive-where", "docify", "frame-benchmarking 28.0.0", "frame-support 28.0.0", @@ -5255,7 +5234,7 @@ name = "cumulus-pov-validator" version = "0.1.0" dependencies = [ "anyhow", - "clap 4.5.26", + "clap 4.5.13", "parity-scale-codec", "polkadot-node-primitives", "polkadot-parachain-primitives 6.0.0", @@ -5470,7 +5449,6 @@ dependencies = [ "async-trait", "cumulus-primitives-core 0.7.0", "cumulus-relay-chain-interface", - "cumulus-test-service", "futures", "futures-timer", "polkadot-cli", @@ -5663,7 +5641,6 @@ dependencies = [ "pallet-aura 27.0.0", "pallet-authorship 28.0.0", "pallet-balances 28.0.0", - "pallet-collator-selection 9.0.0", "pallet-glutton 14.0.0", "pallet-message-queue 31.0.0", "pallet-session 28.0.0", @@ -5695,14 +5672,13 @@ name = "cumulus-test-service" version = "0.1.0" dependencies = [ "async-trait", - "clap 4.5.26", + "clap 4.5.13", "criterion", "cumulus-client-cli", "cumulus-client-collator", "cumulus-client-consensus-aura", "cumulus-client-consensus-common", "cumulus-client-consensus-proposer", - "cumulus-client-consensus-relay-chain", "cumulus-client-parachain-inherent", "cumulus-client-pov-recovery", "cumulus-client-service", @@ -5721,7 +5697,6 @@ dependencies = [ "jsonrpsee", "pallet-timestamp 27.0.0", "pallet-transaction-payment 28.0.0", - "parachains-common 7.0.0", "parity-scale-codec", "polkadot-cli", "polkadot-node-subsystem", @@ -5729,7 +5704,6 @@ dependencies = [ "polkadot-primitives 7.0.0", "polkadot-service", "polkadot-test-service", - "portpicker", "prometheus", "rand", "sc-basic-authorship", @@ -5765,7 +5739,6 @@ dependencies = [ "sp-timestamp 26.0.0", "sp-tracing 16.0.0", "substrate-test-client", - "substrate-test-utils", "tempfile", "tokio", "tracing", @@ -5789,9 +5762,9 @@ dependencies = [ [[package]] name = "curl-sys" -version = "0.4.78+curl-8.11.0" +version = "0.4.72+curl-8.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eec768341c5c7789611ae51cf6c459099f22e64a5d5d0ce4892434e33821eaf" +checksum = "29cbdc8314c447d11e8fd156dcdd031d9e02a7a976163e396b548c03153bc9ea" dependencies = [ "cc", "libc", @@ -6942,14 +6915,14 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.25" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" +checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" dependencies = [ "cfg-if", "libc", - "libredox", - "windows-sys 0.59.0", + "redox_syscall 0.3.5", + "windows-sys 0.48.0", ] [[package]] @@ -7026,12 +6999,12 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.35" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" +checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010" dependencies = [ "crc32fast", - "miniz_oxide 0.8.2", + "miniz_oxide", ] [[package]] @@ -7184,7 +7157,7 @@ dependencies = [ "Inflector", "array-bytes", "chrono", - "clap 4.5.26", + "clap 4.5.13", "comfy-table", "cumulus-client-parachain-inherent", "cumulus-primitives-proof-size-hostfunction 0.2.0", @@ -7350,7 +7323,7 @@ dependencies = [ name = "frame-election-solution-type-fuzzer" version = "2.0.0-alpha.5" dependencies = [ - "clap 4.5.26", + "clap 4.5.13", "frame-election-provider-solution-type 13.0.0", "frame-election-provider-support 28.0.0", "frame-support 28.0.0", @@ -7483,7 +7456,7 @@ name = "frame-omni-bencher" version = "0.1.0" dependencies = [ "assert_cmd", - "clap 4.5.26", + "clap 4.5.13", "cumulus-primitives-proof-size-hostfunction 0.2.0", "cumulus-test-runtime", "frame-benchmarking-cli", @@ -9198,12 +9171,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "is_terminal_polyfill" -version = "1.70.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" - [[package]] name = "isahc" version = "1.7.2" @@ -10295,17 +10262,6 @@ dependencies = [ "yamux 0.13.3", ] -[[package]] -name = "libredox" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" -dependencies = [ - "bitflags 2.6.0", - "libc", - "redox_syscall 0.5.8", -] - [[package]] name = "librocksdb-sys" version = "0.11.0+8.1.1" @@ -10382,9 +10338,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.21" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df9b68e50e6e0b26f672573834882eb57759f6db9b3be2ea3c35c91188bb4eaa" +checksum = "d97137b25e321a73eef1418d1d5d2eda4d77e12813f8e6dead84bc52c5870a7b" dependencies = [ "cc", "libc", @@ -10853,7 +10809,7 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" name = "minimal-template-node" version = "0.0.0" dependencies = [ - "clap 4.5.26", + "clap 4.5.13", "docify", "futures", "futures-timer", @@ -10883,15 +10839,6 @@ dependencies = [ "adler", ] -[[package]] -name = "miniz_oxide" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394" -dependencies = [ - "adler2", -] - [[package]] name = "mio" version = "1.0.2" @@ -11369,7 +11316,7 @@ version = "0.9.0-dev" dependencies = [ "array-bytes", "async-trait", - "clap 4.5.26", + "clap 4.5.13", "derive_more 0.99.17", "fs_extra", "futures", @@ -11445,7 +11392,7 @@ dependencies = [ name = "node-runtime-generate-bags" version = "3.0.0" dependencies = [ - "clap 4.5.26", + "clap 4.5.13", "generate-bags", "kitchensink-runtime", ] @@ -11454,7 +11401,7 @@ dependencies = [ name = "node-template-release" version = "3.0.0" dependencies = [ - "clap 4.5.26", + "clap 4.5.13", "flate2", "fs_extra", "glob", @@ -13003,13 +12950,11 @@ dependencies = [ "frame-system 28.0.0", "impl-trait-for-tuples", "log", - "pallet-assets 29.1.0", "pallet-balances 28.0.0", "pallet-contracts-fixtures", "pallet-contracts-proc-macro 18.0.0", "pallet-contracts-uapi 5.0.0", "pallet-insecure-randomness-collective-flip 16.0.0", - "pallet-message-queue 31.0.0", "pallet-proxy 28.0.0", "pallet-timestamp 27.0.0", "pallet-utility 28.0.0", @@ -13084,7 +13029,6 @@ dependencies = [ name = "pallet-contracts-mock-network" version = "3.0.0" dependencies = [ - "assert_matches", "frame-support 28.0.0", "frame-system 28.0.0", "pallet-assets 29.1.0", @@ -13093,17 +13037,13 @@ dependencies = [ "pallet-contracts-fixtures", "pallet-contracts-proc-macro 18.0.0", "pallet-contracts-uapi 5.0.0", - "pallet-insecure-randomness-collective-flip 16.0.0", "pallet-message-queue 31.0.0", - "pallet-proxy 28.0.0", "pallet-timestamp 27.0.0", - "pallet-utility 28.0.0", "pallet-xcm 7.0.0", "parity-scale-codec", "polkadot-parachain-primitives 6.0.0", "polkadot-primitives 7.0.0", "polkadot-runtime-parachains 7.0.0", - "pretty_assertions", "scale-info", "sp-api 26.0.0", "sp-core 28.0.0", @@ -13205,7 +13145,6 @@ dependencies = [ "frame-support 28.0.0", "frame-system 28.0.0", "pallet-balances 28.0.0", - "pallet-scheduler 29.0.0", "parity-scale-codec", "scale-info", "serde", @@ -13300,7 +13239,6 @@ dependencies = [ "sp-runtime 31.0.1", "sp-staking 26.0.0", "sp-tracing 16.0.0", - "substrate-test-utils", ] [[package]] @@ -13663,6 +13601,24 @@ dependencies = [ "sp-runtime 31.0.1", ] +[[package]] +name = "pallet-example-view-functions" +version = "1.0.0" +dependencies = [ + "frame-benchmarking 28.0.0", + "frame-metadata 18.0.0", + "frame-support 28.0.0", + "frame-system 28.0.0", + "log", + "parity-scale-codec", + "pretty_assertions", + "scale-info", + "sp-core 28.0.0", + "sp-io 30.0.0", + "sp-metadata-ir 0.6.0", + "sp-runtime 31.0.1", +] + [[package]] name = "pallet-examples" version = "4.0.0-dev" @@ -13677,6 +13633,7 @@ dependencies = [ "pallet-example-single-block-migrations", "pallet-example-split", "pallet-example-tasks", + "pallet-example-view-functions", ] [[package]] @@ -13700,7 +13657,6 @@ dependencies = [ "sp-runtime 31.0.1", "sp-staking 26.0.0", "sp-tracing 16.0.0", - "substrate-test-utils", ] [[package]] @@ -13731,7 +13687,6 @@ dependencies = [ "frame-support 28.0.0", "frame-system 28.0.0", "log", - "pallet-balances 28.0.0", "parity-scale-codec", "scale-info", "sp-core 28.0.0", @@ -13897,7 +13852,6 @@ dependencies = [ "scale-info", "sp-core 28.0.0", "sp-io 30.0.0", - "sp-keyring 31.0.0", "sp-runtime 31.0.1", ] @@ -14060,6 +14014,7 @@ dependencies = [ "impl-trait-for-tuples", "log", "parity-scale-codec", + "polkadot-sdk-frame 0.1.0", "pretty_assertions", "scale-info", "sp-api 26.0.0", @@ -14264,7 +14219,6 @@ dependencies = [ name = "pallet-nfts-runtime-api" version = "14.0.0" dependencies = [ - "pallet-nfts 22.0.0", "parity-scale-codec", "sp-api 26.0.0", ] @@ -14480,7 +14434,6 @@ dependencies = [ "frame-support 28.0.0", "frame-system 28.0.0", "log", - "pallet-balances 28.0.0", "parity-scale-codec", "scale-info", "serde", @@ -14562,7 +14515,6 @@ name = "pallet-paged-list" version = "0.6.0" dependencies = [ "docify", - "frame-benchmarking 28.0.0", "frame-support 28.0.0", "frame-system 28.0.0", "parity-scale-codec", @@ -14879,6 +14831,9 @@ dependencies = [ "serde_json", "sp-api 26.0.0", "sp-arithmetic 23.0.0", + "sp-consensus-aura 0.32.0", + "sp-consensus-babe 0.32.0", + "sp-consensus-slots 0.32.0", "sp-core 28.0.0", "sp-io 30.0.0", "sp-keystore 0.34.0", @@ -14925,7 +14880,7 @@ name = "pallet-revive-eth-rpc" version = "0.1.0" dependencies = [ "anyhow", - "clap 4.5.26", + "clap 4.5.13", "env_logger 0.11.3", "ethabi", "futures", @@ -16006,10 +15961,6 @@ dependencies = [ "frame-benchmarking 28.0.0", "frame-support 28.0.0", "frame-system 28.0.0", - "pallet-balances 28.0.0", - "pallet-collective 28.0.0", - "pallet-root-testing 4.0.0", - "pallet-timestamp 27.0.0", "parity-scale-codec", "scale-info", "sp-core 28.0.0", @@ -16272,7 +16223,7 @@ dependencies = [ name = "parachain-template-node" version = "0.0.0" dependencies = [ - "clap 4.5.26", + "clap 4.5.13", "color-print", "docify", "futures", @@ -17066,12 +17017,6 @@ version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" -[[package]] -name = "platforms" -version = "3.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4c7666f2019727f9e8e14bf14456e99c707d780922869f1ba473eee101fa49" - [[package]] name = "plotters" version = "0.3.5" @@ -17266,7 +17211,7 @@ name = "polkadot-cli" version = "7.0.0" dependencies = [ "cfg-if", - "clap 4.5.26", + "clap 4.5.13", "frame-benchmarking-cli", "futures", "log", @@ -17949,7 +17894,6 @@ dependencies = [ name = "polkadot-node-metrics" version = "7.0.0" dependencies = [ - "assert_cmd", "bs58", "futures", "futures-timer", @@ -17967,7 +17911,6 @@ dependencies = [ "sc-tracing", "sp-keyring 31.0.0", "substrate-prometheus-endpoint", - "substrate-test-utils", "tempfile", "tokio", "tracing-gum", @@ -18137,7 +18080,7 @@ version = "0.1.0" dependencies = [ "assert_cmd", "async-trait", - "clap 4.5.26", + "clap 4.5.13", "color-print", "cumulus-client-cli", "cumulus-client-collator", @@ -18178,6 +18121,7 @@ dependencies = [ "sc-consensus-manual-seal", "sc-executor 0.32.0", "sc-network", + "sc-offchain", "sc-rpc", "sc-runtime-utilities", "sc-service", @@ -18185,6 +18129,7 @@ dependencies = [ "sc-telemetry", "sc-tracing", "sc-transaction-pool", + "sc-transaction-pool-api", "scale-info", "serde", "serde_json", @@ -18197,6 +18142,7 @@ dependencies = [ "sp-genesis-builder 0.8.0", "sp-inherents 26.0.0", "sp-keystore 0.34.0", + "sp-offchain 26.0.0", "sp-runtime 31.0.1", "sp-session 27.0.0", "sp-storage 19.0.0", @@ -18248,7 +18194,6 @@ dependencies = [ "bridge-hub-westend-runtime", "collectives-westend-runtime", "color-eyre", - "contracts-rococo-runtime", "coretime-rococo-runtime", "coretime-westend-runtime", "cumulus-primitives-core 0.7.0", @@ -18588,7 +18533,6 @@ dependencies = [ "pallet-session 28.0.0", "pallet-staking 28.0.0", "pallet-timestamp 27.0.0", - "pallet-vesting 28.0.0", "parity-scale-codec", "polkadot-core-primitives 7.0.0", "polkadot-parachain-primitives 6.0.0", @@ -19655,7 +19599,7 @@ dependencies = [ "async-trait", "bincode", "bitvec", - "clap 4.5.26", + "clap 4.5.13", "clap-num", "color-eyre", "colored", @@ -19757,7 +19701,7 @@ version = "1.0.0" dependencies = [ "assert_matches", "async-trait", - "clap 4.5.26", + "clap 4.5.13", "color-eyre", "futures", "futures-timer", @@ -19840,7 +19784,6 @@ dependencies = [ "staging-xcm-executor 7.0.0", "substrate-wasm-builder 17.0.0", "test-runtime-constants", - "tiny-keccak", ] [[package]] @@ -19888,7 +19831,6 @@ dependencies = [ "sp-runtime 31.0.1", "sp-state-machine 0.35.0", "substrate-test-client", - "substrate-test-utils", "tempfile", "test-runtime-constants", "tokio", @@ -19899,7 +19841,7 @@ dependencies = [ name = "polkadot-voter-bags" version = "7.0.0" dependencies = [ - "clap 4.5.26", + "clap 4.5.13", "generate-bags", "sp-io 30.0.0", "westend-runtime", @@ -21223,6 +21165,12 @@ dependencies = [ "regex-syntax 0.6.29", ] +[[package]] +name = "regex-automata" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69" + [[package]] name = "regex-automata" version = "0.4.8" @@ -21301,7 +21249,6 @@ dependencies = [ "async-trait", "backoff", "bp-runtime 0.7.0", - "console", "futures", "isahc", "jsonpath_lib", @@ -21322,7 +21269,7 @@ dependencies = [ name = "remote-ext-tests-bags-list" version = "1.0.0" dependencies = [ - "clap 4.5.26", + "clap 4.5.13", "frame-system 28.0.0", "log", "pallet-bags-list-remote-tests", @@ -21626,14 +21573,12 @@ dependencies = [ "pallet-beefy-mmr 28.0.0", "pallet-bounties 27.0.0", "pallet-child-bounties 27.0.0", - "pallet-collective 28.0.0", "pallet-conviction-voting 28.0.0", "pallet-democracy 28.0.0", "pallet-elections-phragmen 29.0.0", "pallet-grandpa 28.0.0", "pallet-identity 29.0.0", "pallet-indices 28.0.0", - "pallet-membership 28.0.0", "pallet-message-queue 31.0.0", "pallet-migrations 1.0.0", "pallet-mmr 27.0.0", @@ -21670,7 +21615,6 @@ dependencies = [ "polkadot-runtime-parachains 7.0.0", "rococo-runtime-constants 7.0.0", "scale-info", - "separator", "serde", "serde_derive", "serde_json", @@ -21702,7 +21646,6 @@ dependencies = [ "staging-xcm-executor 7.0.0", "static_assertions", "substrate-wasm-builder 17.0.0", - "tiny-keccak", "tokio", "xcm-runtime-apis 0.1.0", ] @@ -21935,7 +21878,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.24", + "semver 1.0.18", ] [[package]] @@ -22354,7 +22297,7 @@ name = "sc-chain-spec" version = "28.0.0" dependencies = [ "array-bytes", - "clap 4.5.26", + "clap 4.5.13", "docify", "log", "memmap2 0.9.3", @@ -22397,7 +22340,7 @@ version = "0.36.0" dependencies = [ "array-bytes", "chrono", - "clap 4.5.26", + "clap 4.5.13", "fdlimit", "futures", "futures-timer", @@ -22457,7 +22400,6 @@ dependencies = [ "sp-state-machine 0.35.0", "sp-statement-store 10.0.0", "sp-storage 19.0.0", - "sp-test-primitives", "sp-trie 29.0.0", "substrate-prometheus-endpoint", "substrate-test-runtime", @@ -22480,7 +22422,6 @@ dependencies = [ "parity-db", "parity-scale-codec", "parking_lot 0.12.3", - "quickcheck", "rand", "sc-client-api", "sc-state-db", @@ -23217,16 +23158,10 @@ dependencies = [ name = "sc-network-common" version = "0.33.0" dependencies = [ - "async-trait", "bitflags 1.3.2", "futures", - "libp2p-identity", "parity-scale-codec", "prost-build", - "sc-consensus", - "sc-network-types", - "sp-consensus", - "sp-consensus-grandpa 13.0.0", "sp-runtime 31.0.1", "tempfile", ] @@ -23745,7 +23680,7 @@ dependencies = [ name = "sc-storage-monitor" version = "0.16.0" dependencies = [ - "clap 4.5.26", + "clap 4.5.13", "fs4", "log", "sp-core 28.0.0", @@ -23802,7 +23737,6 @@ dependencies = [ "parking_lot 0.12.3", "pin-project", "rand", - "sc-network", "sc-utils", "serde", "serde_json", @@ -23885,6 +23819,7 @@ dependencies = [ "thiserror", "tokio", "tokio-stream", + "tracing", ] [[package]] @@ -24145,12 +24080,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - [[package]] name = "scopeguard" version = "1.2.0" @@ -24319,9 +24248,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.24" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" +checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" dependencies = [ "serde", ] @@ -24347,12 +24276,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f638d531eccd6e23b980caf34876660d38e265409d8e99b397ab71eb3612fad0" -[[package]] -name = "separator" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f97841a747eef040fcd2e7b3b9a220a7205926e60488e673d9e4926d27772ce5" - [[package]] name = "serde" version = "1.0.214" @@ -25081,7 +25004,6 @@ dependencies = [ "sp-io 30.0.0", "sp-runtime 31.0.1", "sp-std 14.0.0", - "wasm-bindgen-test", ] [[package]] @@ -25194,7 +25116,6 @@ dependencies = [ "snowbridge-pallet-ethereum-client-fixtures 0.9.0", "sp-core 28.0.0", "sp-io 30.0.0", - "sp-keyring 31.0.0", "sp-runtime 31.0.1", "sp-std 14.0.0", "static_assertions", @@ -25347,7 +25268,6 @@ dependencies = [ "sp-arithmetic 23.0.0", "sp-core 28.0.0", "sp-io 30.0.0", - "sp-keyring 31.0.0", "sp-runtime 31.0.1", "sp-std 14.0.0", ] @@ -25394,7 +25314,6 @@ dependencies = [ "snowbridge-pallet-outbound-queue 0.2.0", "sp-core 28.0.0", "sp-io 30.0.0", - "sp-keyring 31.0.0", "sp-runtime 31.0.1", "sp-std 14.0.0", "staging-xcm 7.0.0", @@ -25633,7 +25552,7 @@ dependencies = [ name = "solochain-template-node" version = "0.0.0" dependencies = [ - "clap 4.5.26", + "clap 4.5.13", "frame-benchmarking-cli", "frame-metadata-hash-extension 0.1.0", "frame-system 28.0.0", @@ -27016,7 +26935,7 @@ dependencies = [ name = "sp-npos-elections-fuzzer" version = "2.0.0-alpha.5" dependencies = [ - "clap 4.5.26", + "clap 4.5.13", "honggfuzz", "rand", "sp-npos-elections 26.0.0", @@ -28240,7 +28159,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" name = "staging-chain-spec-builder" version = "1.6.1" dependencies = [ - "clap 4.5.26", + "clap 4.5.13", "cmd_lib", "docify", "log", @@ -28257,7 +28176,7 @@ version = "3.0.0-dev" dependencies = [ "array-bytes", "assert_cmd", - "clap 4.5.26", + "clap 4.5.13", "clap_complete", "criterion", "futures", @@ -28269,7 +28188,6 @@ dependencies = [ "node-rpc", "node-testing", "parity-scale-codec", - "platforms", "polkadot-sdk 0.1.0", "pretty_assertions", "rand", @@ -28294,7 +28212,7 @@ dependencies = [ name = "staging-node-inspect" version = "0.12.0" dependencies = [ - "clap 4.5.26", + "clap 4.5.13", "parity-scale-codec", "sc-cli", "sc-client-api", @@ -28343,7 +28261,7 @@ version = "7.0.0" dependencies = [ "array-bytes", "bounded-collections", - "derivative", + "derive-where", "environmental", "frame-support 28.0.0", "hex", @@ -28384,7 +28302,6 @@ dependencies = [ name = "staging-xcm-builder" version = "7.0.0" dependencies = [ - "assert_matches", "frame-support 28.0.0", "frame-system 28.0.0", "impl-trait-for-tuples", @@ -28639,7 +28556,7 @@ dependencies = [ name = "subkey" version = "9.0.0" dependencies = [ - "clap 4.5.26", + "clap 4.5.13", "sc-cli", ] @@ -28874,7 +28791,6 @@ dependencies = [ "sc-client-db", "sc-consensus", "sc-executor 0.32.0", - "sc-offchain", "sc-service", "serde", "serde_json", @@ -28976,12 +28892,6 @@ dependencies = [ [[package]] name = "substrate-test-utils" version = "4.0.0-dev" -dependencies = [ - "futures", - "sc-service", - "tokio", - "trybuild", -] [[package]] name = "substrate-wasm-builder" @@ -29065,7 +28975,7 @@ dependencies = [ "rand", "reqwest 0.12.9", "scale-info", - "semver 1.0.24", + "semver 1.0.18", "serde", "serde_json", "sp-version 35.0.0", @@ -29478,9 +29388,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tar" -version = "0.4.43" +version = "0.4.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c65998313f8e17d0d553d28f91a0df93e4dbbbf770279c7bc21ca0f09ea1a1f6" +checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" dependencies = [ "filetime", "libc", @@ -29528,12 +29438,12 @@ dependencies = [ [[package]] name = "terminal_size" -version = "0.4.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5352447f921fda68cf61b4101566c0bdb5104eff6804d0678e5227580ab6a4e9" +checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" dependencies = [ "rustix 0.38.42", - "windows-sys 0.59.0", + "windows-sys 0.48.0", ] [[package]] @@ -29580,7 +29490,7 @@ dependencies = [ name = "test-parachain-adder-collator" version = "1.0.0" dependencies = [ - "clap 4.5.26", + "clap 4.5.13", "futures", "futures-timer", "log", @@ -29597,7 +29507,6 @@ dependencies = [ "sc-service", "sp-core 28.0.0", "sp-keyring 31.0.0", - "substrate-test-utils", "test-parachain-adder", "tokio", ] @@ -29618,6 +29527,7 @@ dependencies = [ "log", "parity-scale-codec", "polkadot-parachain-primitives 6.0.0", + "polkadot-primitives 7.0.0", "sp-io 30.0.0", "substrate-wasm-builder 17.0.0", "tiny-keccak", @@ -29627,12 +29537,13 @@ dependencies = [ name = "test-parachain-undying-collator" version = "1.0.0" dependencies = [ - "clap 4.5.26", + "clap 4.5.13", "futures", "futures-timer", "log", "parity-scale-codec", "polkadot-cli", + "polkadot-erasure-coding", "polkadot-node-core-pvf", "polkadot-node-primitives", "polkadot-node-subsystem", @@ -29641,10 +29552,10 @@ dependencies = [ "polkadot-service", "polkadot-test-service", "sc-cli", + "sc-client-api", "sc-service", "sp-core 28.0.0", "sp-keyring 31.0.0", - "substrate-test-utils", "test-parachain-undying", "tokio", ] @@ -30837,30 +30748,6 @@ version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" -[[package]] -name = "wasm-bindgen-test" -version = "0.3.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e6e302a7ea94f83a6d09e78e7dc7d9ca7b186bc2829c24a22d0753efd680671" -dependencies = [ - "console_error_panic_hook", - "js-sys", - "scoped-tls", - "wasm-bindgen", - "wasm-bindgen-futures", - "wasm-bindgen-test-macro", -] - -[[package]] -name = "wasm-bindgen-test-macro" -version = "0.3.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecb993dd8c836930ed130e020e77d9b2e65dd0fbab1b67c790b0f5d80b11a575" -dependencies = [ - "proc-macro2 1.0.86", - "quote 1.0.37", -] - [[package]] name = "wasm-encoder" version = "0.31.1" @@ -31374,10 +31261,8 @@ dependencies = [ "pallet-balances 28.0.0", "pallet-beefy 28.0.0", "pallet-beefy-mmr 28.0.0", - "pallet-collective 28.0.0", "pallet-conviction-voting 28.0.0", "pallet-delegated-staking 1.0.0", - "pallet-democracy 28.0.0", "pallet-election-provider-multi-phase 27.0.0", "pallet-election-provider-support-benchmarking 27.0.0", "pallet-elections-phragmen 29.0.0", @@ -31923,13 +31808,11 @@ dependencies = [ [[package]] name = "xattr" -version = "1.4.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e105d177a3871454f754b33bb0ee637ecaaac997446375fd3e5d43a2ed00c909" +checksum = "f4686009f71ff3e5c4dbcf1a282d0a44db3f021ba69350cd42086b3e5f1c6985" dependencies = [ "libc", - "linux-raw-sys 0.4.14", - "rustix 0.38.42", ] [[package]] @@ -31963,7 +31846,6 @@ version = "0.5.0" dependencies = [ "array-bytes", "cumulus-pallet-parachain-system 0.7.0", - "cumulus-pallet-xcmp-queue 0.7.0", "cumulus-primitives-core 0.7.0", "cumulus-primitives-parachain-inherent 0.7.0", "cumulus-test-relay-sproof-builder 0.7.0", diff --git a/Cargo.toml b/Cargo.toml index 18c1dd2c68d2f09fec08aec3cc5961be8ecf2959..0d415fe4fdbd46d86394d73060197e12119b16e6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -363,6 +363,7 @@ members = [ "substrate/frame/examples/single-block-migrations", "substrate/frame/examples/split", "substrate/frame/examples/tasks", + "substrate/frame/examples/view-functions", "substrate/frame/executive", "substrate/frame/fast-unstake", "substrate/frame/glutton", @@ -739,8 +740,8 @@ cumulus-test-relay-sproof-builder = { path = "cumulus/test/relay-sproof-builder" cumulus-test-runtime = { path = "cumulus/test/runtime" } cumulus-test-service = { path = "cumulus/test/service" } curve25519-dalek = { version = "4.1.3" } -derivative = { version = "2.2.0", default-features = false } derive-syn-parse = { version = "0.2.0" } +derive-where = { version = "1.2.7" } derive_more = { version = "0.99.17", default-features = false } digest = { version = "0.10.3", default-features = false } directories = { version = "5.0.1" } @@ -941,6 +942,7 @@ pallet-example-offchain-worker = { path = "substrate/frame/examples/offchain-wor pallet-example-single-block-migrations = { path = "substrate/frame/examples/single-block-migrations", default-features = false } pallet-example-split = { path = "substrate/frame/examples/split", default-features = false } pallet-example-tasks = { path = "substrate/frame/examples/tasks", default-features = false } +pallet-example-view-functions = { path = "substrate/frame/examples/view-functions", default-features = false } pallet-examples = { path = "substrate/frame/examples" } pallet-fast-unstake = { path = "substrate/frame/fast-unstake", default-features = false } pallet-glutton = { path = "substrate/frame/glutton", default-features = false } @@ -1036,7 +1038,6 @@ people-rococo-runtime = { path = "cumulus/parachains/runtimes/people/people-roco people-westend-emulated-chain = { path = "cumulus/parachains/integration-tests/emulated/chains/parachains/people/people-westend" } people-westend-runtime = { path = "cumulus/parachains/runtimes/people/people-westend" } pin-project = { version = "1.1.3" } -platforms = { version = "3.4" } polkadot-approval-distribution = { path = "polkadot/node/network/approval-distribution", default-features = false } polkadot-availability-bitfield-distribution = { path = "polkadot/node/network/bitfield-distribution", default-features = false } polkadot-availability-distribution = { path = "polkadot/node/network/availability-distribution", default-features = false } @@ -1209,7 +1210,6 @@ schnorrkel = { version = "0.11.4", default-features = false } seccompiler = { version = "0.4.0" } secp256k1 = { version = "0.28.0", default-features = false } secrecy = { version = "0.8.0", default-features = false } -separator = { version = "0.4.1" } serde = { version = "1.0.214", default-features = false } serde-big-array = { version = "0.3.2" } serde_derive = { version = "1.0.117" } @@ -1372,7 +1372,6 @@ void = { version = "1.0.2" } w3f-bls = { version = "0.1.3", default-features = false } wait-timeout = { version = "0.2" } walkdir = { version = "2.5.0" } -wasm-bindgen-test = { version = "0.3.19" } wasm-instrument = { version = "0.4", default-features = false } wasm-opt = { version = "0.116" } wasm-timer = { version = "0.2.5" } diff --git a/bridges/modules/xcm-bridge-hub/src/lib.rs b/bridges/modules/xcm-bridge-hub/src/lib.rs index 682db811efa77367d1cb54a14641c4ad8cd93e4c..1633e99d7f303abe0e16c12a42d7e98be4fe23ff 100644 --- a/bridges/modules/xcm-bridge-hub/src/lib.rs +++ b/bridges/modules/xcm-bridge-hub/src/lib.rs @@ -145,8 +145,10 @@ use bp_messages::{LaneState, MessageNonce}; use bp_runtime::{AccountIdOf, BalanceOf, RangeInclusiveExt}; -pub use bp_xcm_bridge_hub::{Bridge, BridgeId, BridgeState, LocalXcmChannelManager}; -use bp_xcm_bridge_hub::{BridgeLocations, BridgeLocationsError}; +use bp_xcm_bridge_hub::BridgeLocationsError; +pub use bp_xcm_bridge_hub::{ + Bridge, BridgeId, BridgeLocations, BridgeState, LocalXcmChannelManager, +}; use frame_support::{traits::fungible::MutateHold, DefaultNoBound}; use frame_system::Config as SystemConfig; use pallet_bridge_messages::{Config as BridgeMessagesConfig, LanesManagerError}; diff --git a/bridges/relays/utils/Cargo.toml b/bridges/relays/utils/Cargo.toml index 8592ca780eaa896e187e08aa68f05d0e607b3510..6d28789daaec26e321e038026dfe5ebeb8bbe74c 100644 --- a/bridges/relays/utils/Cargo.toml +++ b/bridges/relays/utils/Cargo.toml @@ -15,7 +15,6 @@ anyhow = { workspace = true, default-features = true } async-std = { workspace = true } async-trait = { workspace = true } backoff = { workspace = true } -console = { workspace = true } futures = { workspace = true } isahc = { workspace = true } jsonpath_lib = { workspace = true } diff --git a/bridges/snowbridge/pallets/ethereum-client/Cargo.toml b/bridges/snowbridge/pallets/ethereum-client/Cargo.toml index ebd8a1c6ed11db000d9f71c33dc244bf01d77eb0..87b4c66d77535e4452acafb63a2ff5cd402890ac 100644 --- a/bridges/snowbridge/pallets/ethereum-client/Cargo.toml +++ b/bridges/snowbridge/pallets/ethereum-client/Cargo.toml @@ -45,7 +45,6 @@ serde = { workspace = true, default-features = true } serde_json = { workspace = true, default-features = true } snowbridge-pallet-ethereum-client-fixtures = { workspace = true, default-features = true } sp-io = { workspace = true, default-features = true } -sp-keyring = { workspace = true, default-features = true } [features] default = ["std"] diff --git a/bridges/snowbridge/pallets/outbound-queue/Cargo.toml b/bridges/snowbridge/pallets/outbound-queue/Cargo.toml index f4910e6e645716338e1e7293d610c5dc84b550a9..e343d4c684ab9feaf3e6901c4a56edd2e2dbf439 100644 --- a/bridges/snowbridge/pallets/outbound-queue/Cargo.toml +++ b/bridges/snowbridge/pallets/outbound-queue/Cargo.toml @@ -36,7 +36,6 @@ snowbridge-outbound-queue-merkle-tree = { workspace = true } [dev-dependencies] pallet-message-queue = { workspace = true } -sp-keyring = { workspace = true, default-features = true } [features] default = ["std"] diff --git a/bridges/snowbridge/pallets/system/Cargo.toml b/bridges/snowbridge/pallets/system/Cargo.toml index 3544925956b41dc3ad3c734a00dc81e1f94ba952..c695b1034f6981e38d11947f6df998976130ec7b 100644 --- a/bridges/snowbridge/pallets/system/Cargo.toml +++ b/bridges/snowbridge/pallets/system/Cargo.toml @@ -41,7 +41,6 @@ pallet-balances = { workspace = true, default-features = true } pallet-message-queue = { workspace = true, default-features = true } polkadot-primitives = { workspace = true, default-features = true } snowbridge-pallet-outbound-queue = { workspace = true, default-features = true } -sp-keyring = { workspace = true, default-features = true } [features] default = ["std"] diff --git a/bridges/snowbridge/primitives/ethereum/Cargo.toml b/bridges/snowbridge/primitives/ethereum/Cargo.toml index 44ea2d0d222ba4820b256f5e58a96778f07a532b..5c249354a53a6ee14cc1729df667cbcc91e6cd5e 100644 --- a/bridges/snowbridge/primitives/ethereum/Cargo.toml +++ b/bridges/snowbridge/primitives/ethereum/Cargo.toml @@ -31,7 +31,6 @@ ethabi = { workspace = true } [dev-dependencies] rand = { workspace = true, default-features = true } serde_json = { workspace = true, default-features = true } -wasm-bindgen-test = { workspace = true } [features] default = ["std"] diff --git a/cumulus/client/consensus/aura/src/collators/mod.rs b/cumulus/client/consensus/aura/src/collators/mod.rs index 66c6086eaf9ee3b2410ad389ae67a603b9311a6d..4c191c7d8a1a0882905fd77ec1ab0af90b213413 100644 --- a/cumulus/client/consensus/aura/src/collators/mod.rs +++ b/cumulus/client/consensus/aura/src/collators/mod.rs @@ -22,19 +22,18 @@ use crate::collator::SlotClaim; use codec::Codec; -use cumulus_client_consensus_common::{ - self as consensus_common, load_abridged_host_configuration, ParentSearchParams, -}; +use cumulus_client_consensus_common::{self as consensus_common, ParentSearchParams}; use cumulus_primitives_aura::{AuraUnincludedSegmentApi, Slot}; use cumulus_primitives_core::{relay_chain::Hash as ParaHash, BlockT, ClaimQueueOffset}; use cumulus_relay_chain_interface::RelayChainInterface; +use polkadot_node_subsystem::messages::RuntimeApiRequest; use polkadot_node_subsystem_util::runtime::ClaimQueueSnapshot; use polkadot_primitives::{ - AsyncBackingParams, CoreIndex, Hash as RelayHash, Id as ParaId, OccupiedCoreAssumption, - ValidationCodeHash, + CoreIndex, Hash as RelayHash, Id as ParaId, OccupiedCoreAssumption, ValidationCodeHash, + DEFAULT_SCHEDULING_LOOKAHEAD, }; use sc_consensus_aura::{standalone as aura_internal, AuraApi}; -use sp_api::{ApiExt, ProvideRuntimeApi}; +use sp_api::{ApiExt, ProvideRuntimeApi, RuntimeApiInfo}; use sp_core::Pair; use sp_keystore::KeystorePtr; use sp_timestamp::Timestamp; @@ -44,12 +43,13 @@ pub mod lookahead; pub mod slot_based; // This is an arbitrary value which is likely guaranteed to exceed any reasonable -// limit, as it would correspond to 10 non-included blocks. +// limit, as it would correspond to 30 non-included blocks. // // Since we only search for parent blocks which have already been imported, // we can guarantee that all imported blocks respect the unincluded segment -// rules specified by the parachain's runtime and thus will never be too deep. -const PARENT_SEARCH_DEPTH: usize = 10; +// rules specified by the parachain's runtime and thus will never be too deep. This is just an extra +// sanity check. +const PARENT_SEARCH_DEPTH: usize = 30; /// Check the `local_validation_code_hash` against the validation code hash in the relay chain /// state. @@ -101,26 +101,43 @@ async fn check_validation_code_or_log( } } -/// Reads async backing parameters from the relay chain storage at the given relay parent. -async fn async_backing_params( +/// Fetch scheduling lookahead at given relay parent. +async fn scheduling_lookahead( relay_parent: RelayHash, relay_client: &impl RelayChainInterface, -) -> Option<AsyncBackingParams> { - match load_abridged_host_configuration(relay_parent, relay_client).await { - Ok(Some(config)) => Some(config.async_backing_params), - Ok(None) => { +) -> Option<u32> { + let runtime_api_version = relay_client + .version(relay_parent) + .await + .map_err(|e| { tracing::error!( - target: crate::LOG_TARGET, - "Active config is missing in relay chain storage", - ); - None - }, + target: super::LOG_TARGET, + error = ?e, + "Failed to fetch relay chain runtime version.", + ) + }) + .ok()?; + + let parachain_host_runtime_api_version = runtime_api_version + .api_version( + &<dyn polkadot_primitives::runtime_api::ParachainHost<polkadot_primitives::Block>>::ID, + ) + .unwrap_or_default(); + + if parachain_host_runtime_api_version < + RuntimeApiRequest::SCHEDULING_LOOKAHEAD_RUNTIME_REQUIREMENT + { + return None + } + + match relay_client.scheduling_lookahead(relay_parent).await { + Ok(scheduling_lookahead) => Some(scheduling_lookahead), Err(err) => { tracing::error!( target: crate::LOG_TARGET, ?err, ?relay_parent, - "Failed to read active config from relay chain client", + "Failed to fetch scheduling lookahead from relay chain", ); None }, @@ -216,9 +233,10 @@ where let parent_search_params = ParentSearchParams { relay_parent, para_id, - ancestry_lookback: crate::collators::async_backing_params(relay_parent, relay_client) + ancestry_lookback: scheduling_lookahead(relay_parent, relay_client) .await - .map_or(0, |params| params.allowed_ancestry_len as usize), + .unwrap_or(DEFAULT_SCHEDULING_LOOKAHEAD) + .saturating_sub(1) as usize, max_depth: PARENT_SEARCH_DEPTH, ignore_alternative_branches: true, }; diff --git a/cumulus/client/consensus/common/src/tests.rs b/cumulus/client/consensus/common/src/tests.rs index 79e620db3bfa0c82860fa5fcce28a8c5fea5b975..2eff183fc47375e7cff8633798c2d33384b2060e 100644 --- a/cumulus/client/consensus/common/src/tests.rs +++ b/cumulus/client/consensus/common/src/tests.rs @@ -284,6 +284,10 @@ impl RelayChainInterface for Relaychain { ) -> RelayChainResult<Vec<u8>> { unimplemented!("Not needed for test") } + + async fn scheduling_lookahead(&self, _: PHash) -> RelayChainResult<u32> { + unimplemented!("Not needed for test") + } } fn sproof_with_best_parent(client: &Client) -> RelayStateSproofBuilder { diff --git a/cumulus/client/network/Cargo.toml b/cumulus/client/network/Cargo.toml index 11025f8f62e6d542c979d561061ffe1b12f16af4..3fb7eac591aaeb1ed1ae043adbd5979bb754a6c0 100644 --- a/cumulus/client/network/Cargo.toml +++ b/cumulus/client/network/Cargo.toml @@ -39,7 +39,6 @@ polkadot-primitives = { workspace = true, default-features = true } cumulus-relay-chain-interface = { workspace = true, default-features = true } [dev-dependencies] -portpicker = { workspace = true } rstest = { workspace = true } tokio = { features = ["macros"], workspace = true, default-features = true } url = { workspace = true } @@ -51,7 +50,6 @@ sp-consensus = { workspace = true, default-features = true } sp-core = { workspace = true, default-features = true } sp-keyring = { workspace = true, default-features = true } sp-keystore = { workspace = true, default-features = true } -substrate-test-utils = { workspace = true } # Polkadot polkadot-test-client = { workspace = true } diff --git a/cumulus/client/network/src/tests.rs b/cumulus/client/network/src/tests.rs index cccb710bf18f1122d8675ee0bfca23e2075b3d47..3bdcdaae4ef67e679b1655149383e78c8ec03c36 100644 --- a/cumulus/client/network/src/tests.rs +++ b/cumulus/client/network/src/tests.rs @@ -347,6 +347,10 @@ impl RelayChainInterface for DummyRelayChainInterface { ) -> RelayChainResult<Vec<u8>> { unimplemented!("Not needed for test") } + + async fn scheduling_lookahead(&self, _: PHash) -> RelayChainResult<u32> { + unimplemented!("Not needed for test") + } } fn make_validator_and_api() -> ( diff --git a/cumulus/client/pov-recovery/Cargo.toml b/cumulus/client/pov-recovery/Cargo.toml index 7e7da7244a86ee4e56ad6dbc7145dc9fad287221..7c85318bdde3cee1ab74252cfa56fdb021d35d70 100644 --- a/cumulus/client/pov-recovery/Cargo.toml +++ b/cumulus/client/pov-recovery/Cargo.toml @@ -41,7 +41,6 @@ cumulus-relay-chain-interface = { workspace = true, default-features = true } [dev-dependencies] assert_matches = { workspace = true } cumulus-test-client = { workspace = true } -portpicker = { workspace = true } rstest = { workspace = true } sc-utils = { workspace = true, default-features = true } sp-blockchain = { workspace = true, default-features = true } @@ -54,4 +53,3 @@ cumulus-test-service = { workspace = true } # Substrate sc-cli = { workspace = true, default-features = true } sc-client-api = { workspace = true, default-features = true } -substrate-test-utils = { workspace = true } diff --git a/cumulus/client/pov-recovery/src/tests.rs b/cumulus/client/pov-recovery/src/tests.rs index 91b462e06bf87bf9fb264e638daa77547b8ce660..be890d01dd96721402e00d5eaa07fd763e03079c 100644 --- a/cumulus/client/pov-recovery/src/tests.rs +++ b/cumulus/client/pov-recovery/src/tests.rs @@ -503,6 +503,10 @@ impl RelayChainInterface for Relaychain { ) -> RelayChainResult<Vec<u8>> { unimplemented!("Not needed for test") } + + async fn scheduling_lookahead(&self, _: PHash) -> RelayChainResult<u32> { + unimplemented!("Not needed for test") + } } fn make_candidate_chain(candidate_number_range: Range<u32>) -> Vec<CommittedCandidateReceipt> { diff --git a/cumulus/client/relay-chain-inprocess-interface/Cargo.toml b/cumulus/client/relay-chain-inprocess-interface/Cargo.toml index 2a590bbca5628eed2bbb2cabc22c06b4ecc12331..1307ec76de85ccbe2d36f2ba31b776205165fa8f 100644 --- a/cumulus/client/relay-chain-inprocess-interface/Cargo.toml +++ b/cumulus/client/relay-chain-inprocess-interface/Cargo.toml @@ -45,6 +45,3 @@ sp-keyring = { workspace = true, default-features = true } metered = { features = ["futures_channel"], workspace = true } polkadot-primitives = { workspace = true, default-features = true } polkadot-test-client = { workspace = true } - -# Cumulus -cumulus-test-service = { workspace = true } diff --git a/cumulus/client/relay-chain-inprocess-interface/src/lib.rs b/cumulus/client/relay-chain-inprocess-interface/src/lib.rs index f29e7f3ed7c7c5eb55cbe80a2c428c112e58cd60..e5daf8ee7b5878b5dbae3401b3688f916434ebbe 100644 --- a/cumulus/client/relay-chain-inprocess-interface/src/lib.rs +++ b/cumulus/client/relay-chain-inprocess-interface/src/lib.rs @@ -316,6 +316,10 @@ impl RelayChainInterface for RelayChainInProcessInterface { ) -> RelayChainResult<BTreeMap<CoreIndex, VecDeque<ParaId>>> { Ok(self.full_client.runtime_api().claim_queue(hash)?) } + + async fn scheduling_lookahead(&self, hash: PHash) -> RelayChainResult<u32> { + Ok(self.full_client.runtime_api().scheduling_lookahead(hash)?) + } } pub enum BlockCheckStatus { diff --git a/cumulus/client/relay-chain-interface/src/lib.rs b/cumulus/client/relay-chain-interface/src/lib.rs index 4a49eada292ac83ff489e4a8f12d2aa60e7ef300..f1d5e013ba6a21a9f267ef05ea101fddaa973003 100644 --- a/cumulus/client/relay-chain-interface/src/lib.rs +++ b/cumulus/client/relay-chain-interface/src/lib.rs @@ -244,6 +244,9 @@ pub trait RelayChainInterface: Send + Sync { &self, relay_parent: PHash, ) -> RelayChainResult<BTreeMap<CoreIndex, VecDeque<ParaId>>>; + + /// Fetch the scheduling lookahead value. + async fn scheduling_lookahead(&self, relay_parent: PHash) -> RelayChainResult<u32>; } #[async_trait] @@ -398,6 +401,10 @@ where ) -> RelayChainResult<BTreeMap<CoreIndex, VecDeque<ParaId>>> { (**self).claim_queue(relay_parent).await } + + async fn scheduling_lookahead(&self, relay_parent: PHash) -> RelayChainResult<u32> { + (**self).scheduling_lookahead(relay_parent).await + } } /// Helper function to call an arbitrary runtime API using a `RelayChainInterface` client. diff --git a/cumulus/client/relay-chain-minimal-node/src/blockchain_rpc_client.rs b/cumulus/client/relay-chain-minimal-node/src/blockchain_rpc_client.rs index 862cf6af97956802ce4dd871094db38c57851b74..cfd5bd951333dc5436d90ad9c83033a75628debe 100644 --- a/cumulus/client/relay-chain-minimal-node/src/blockchain_rpc_client.rs +++ b/cumulus/client/relay-chain-minimal-node/src/blockchain_rpc_client.rs @@ -464,6 +464,10 @@ impl RuntimeApiSubsystemClient for BlockChainRpcClient { ) -> Result<Option<Constraints>, ApiError> { Ok(self.rpc_client.parachain_host_backing_constraints(at, para_id).await?) } + + async fn scheduling_lookahead(&self, at: Hash) -> Result<u32, sp_api::ApiError> { + Ok(self.rpc_client.parachain_host_scheduling_lookahead(at).await?) + } } #[async_trait::async_trait] diff --git a/cumulus/client/relay-chain-rpc-interface/src/lib.rs b/cumulus/client/relay-chain-rpc-interface/src/lib.rs index 0e2f6c054c403607754e494a3ce6b595ad2bcd6b..a895d8f3e5f26239eafc40db45d85d5e86a807d7 100644 --- a/cumulus/client/relay-chain-rpc-interface/src/lib.rs +++ b/cumulus/client/relay-chain-rpc-interface/src/lib.rs @@ -282,4 +282,8 @@ impl RelayChainInterface for RelayChainRpcInterface { > { self.rpc_client.parachain_host_claim_queue(relay_parent).await } + + async fn scheduling_lookahead(&self, relay_parent: RelayHash) -> RelayChainResult<u32> { + self.rpc_client.parachain_host_scheduling_lookahead(relay_parent).await + } } diff --git a/cumulus/client/relay-chain-rpc-interface/src/rpc_client.rs b/cumulus/client/relay-chain-rpc-interface/src/rpc_client.rs index 0467b7085ca020f43dd4ab8442135e443850b96a..1cd9d0c11eeddbca8b02831c89016ac869479073 100644 --- a/cumulus/client/relay-chain-rpc-interface/src/rpc_client.rs +++ b/cumulus/client/relay-chain-rpc-interface/src/rpc_client.rs @@ -706,6 +706,14 @@ impl RelayChainRpcClient { .await } + pub async fn parachain_host_scheduling_lookahead( + &self, + at: RelayHash, + ) -> Result<u32, RelayChainError> { + self.call_remote_runtime_function("ParachainHost_scheduling_lookahead", at, None::<()>) + .await + } + pub async fn validation_code_hash( &self, at: RelayHash, diff --git a/cumulus/pallets/parachain-system/src/lib.rs b/cumulus/pallets/parachain-system/src/lib.rs index 6857b08e66b7d78a2c3dbb1ad6e4c65e88b536b7..624f91e7fdfb3c03164b1d7e6246df14266ea65e 100644 --- a/cumulus/pallets/parachain-system/src/lib.rs +++ b/cumulus/pallets/parachain-system/src/lib.rs @@ -45,7 +45,7 @@ use cumulus_primitives_core::{ use cumulus_primitives_parachain_inherent::{MessageQueueChain, ParachainInherentData}; use frame_support::{ defensive, - dispatch::{DispatchResult, Pays, PostDispatchInfo}, + dispatch::DispatchResult, ensure, inherent::{InherentData, InherentIdentifier, ProvideInherent}, traits::{Get, HandleMessage}, @@ -309,8 +309,12 @@ pub mod pallet { <UpgradeRestrictionSignal<T>>::kill(); let relay_upgrade_go_ahead = <UpgradeGoAhead<T>>::take(); - let vfp = <ValidationData<T>>::get() - .expect("set_validation_data inherent needs to be present in every block!"); + let vfp = <ValidationData<T>>::get().expect( + r"Missing required set_validation_data inherent. This inherent must be + present in every block. This error typically occurs when the set_validation_data + execution failed and was rejected by the block builder. Check earlier log entries + for the specific cause of the failure.", + ); LastRelayChainBlockNumber::<T>::put(vfp.relay_parent_number); @@ -567,11 +571,12 @@ pub mod pallet { /// if the appropriate time has come. #[pallet::call_index(0)] #[pallet::weight((0, DispatchClass::Mandatory))] - // TODO: This weight should be corrected. + // TODO: This weight should be corrected. Currently the weight is registered manually in the + // call with `register_extra_weight_unchecked`. pub fn set_validation_data( origin: OriginFor<T>, data: ParachainInherentData, - ) -> DispatchResultWithPostInfo { + ) -> DispatchResult { ensure_none(origin)?; assert!( !<ValidationData<T>>::exists(), @@ -692,7 +697,12 @@ pub mod pallet { vfp.relay_parent_number, )); - Ok(PostDispatchInfo { actual_weight: Some(total_weight), pays_fee: Pays::No }) + frame_system::Pallet::<T>::register_extra_weight_unchecked( + total_weight, + DispatchClass::Mandatory, + ); + + Ok(()) } #[pallet::call_index(1)] diff --git a/cumulus/pallets/session-benchmarking/src/inner.rs b/cumulus/pallets/session-benchmarking/src/inner.rs index 8d5954304878dfd5ff4c4bf912168d70e4e5e53f..6c5188921362efd9a60fa3a30693943b618379e7 100644 --- a/cumulus/pallets/session-benchmarking/src/inner.rs +++ b/cumulus/pallets/session-benchmarking/src/inner.rs @@ -14,29 +14,49 @@ // limitations under the License. //! Benchmarking setup for pallet-session. +#![cfg(feature = "runtime-benchmarks")] use alloc::{vec, vec::Vec}; use codec::Decode; -use frame_benchmarking::{benchmarks, whitelisted_caller}; +use frame_benchmarking::v2::*; use frame_system::RawOrigin; use pallet_session::*; pub struct Pallet<T: Config>(pallet_session::Pallet<T>); pub trait Config: pallet_session::Config {} -benchmarks! { - set_keys { +#[benchmarks] +mod benchmarks { + use super::*; + + #[benchmark] + fn set_keys() -> Result<(), BenchmarkError> { let caller: T::AccountId = whitelisted_caller(); frame_system::Pallet::<T>::inc_providers(&caller); let keys = T::Keys::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()).unwrap(); - let proof: Vec<u8> = vec![0,1,2,3]; - }: _(RawOrigin::Signed(caller), keys, proof) + let proof: Vec<u8> = vec![0, 1, 2, 3]; + + #[extrinsic_call] + _(RawOrigin::Signed(caller), keys, proof); + + Ok(()) + } - purge_keys { + #[benchmark] + fn purge_keys() -> Result<(), BenchmarkError> { let caller: T::AccountId = whitelisted_caller(); frame_system::Pallet::<T>::inc_providers(&caller); let keys = T::Keys::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()).unwrap(); - let proof: Vec<u8> = vec![0,1,2,3]; - let _t = pallet_session::Pallet::<T>::set_keys(RawOrigin::Signed(caller.clone()).into(), keys, proof); - }: _(RawOrigin::Signed(caller)) + let proof: Vec<u8> = vec![0, 1, 2, 3]; + let _t = pallet_session::Pallet::<T>::set_keys( + RawOrigin::Signed(caller.clone()).into(), + keys, + proof, + ); + + #[extrinsic_call] + _(RawOrigin::Signed(caller)); + + Ok(()) + } } diff --git a/cumulus/pallets/weight-reclaim/Cargo.toml b/cumulus/pallets/weight-reclaim/Cargo.toml index 8bde6abaff6a1a9e53f0e7048d94b18cc43c5325..d412a9b105d989156771a6a0a5fc24e0a3ac59ae 100644 --- a/cumulus/pallets/weight-reclaim/Cargo.toml +++ b/cumulus/pallets/weight-reclaim/Cargo.toml @@ -27,7 +27,7 @@ frame-system = { workspace = true } # Other dependencies codec = { features = ["derive"], workspace = true } -derivative = { features = ["use_core"], workspace = true } +derive-where = { workspace = true } docify = { workspace = true } log = { workspace = true, default-features = true } scale-info = { features = ["derive"], workspace = true } diff --git a/cumulus/pallets/weight-reclaim/src/lib.rs b/cumulus/pallets/weight-reclaim/src/lib.rs index bd9929033af14e43614ea1cd70bdd1b3232a6cfe..7bbd2cf29d831942520dd680eee8ddc9da853b50 100644 --- a/cumulus/pallets/weight-reclaim/src/lib.rs +++ b/cumulus/pallets/weight-reclaim/src/lib.rs @@ -29,7 +29,7 @@ extern crate alloc; use alloc::vec::Vec; use codec::{Decode, Encode}; use cumulus_primitives_storage_weight_reclaim::get_proof_size; -use derivative::Derivative; +use derive_where::derive_where; use frame_support::{ dispatch::{DispatchInfo, PostDispatchInfo}, pallet_prelude::Weight, @@ -83,13 +83,8 @@ pub mod pallet { /// calculates the unused weight using the post information and reclaim the unused weight. /// So this extension can be used as a drop-in replacement for `WeightReclaim` extension for /// parachains. -#[derive(Encode, Decode, TypeInfo, Derivative)] -#[derivative( - Clone(bound = "S: Clone"), - Eq(bound = "S: Eq"), - PartialEq(bound = "S: PartialEq"), - Default(bound = "S: Default") -)] +#[derive(Encode, Decode, TypeInfo)] +#[derive_where(Clone, Eq, PartialEq, Default; S)] #[scale_info(skip_type_params(T))] pub struct StorageWeightReclaim<T, S>(pub S, core::marker::PhantomData<T>); diff --git a/cumulus/pallets/weight-reclaim/src/tests.rs b/cumulus/pallets/weight-reclaim/src/tests.rs index b87c107c7ec71ce8dea8b04b702f673373dfd16f..ce647445b33272b71929ad1ac51042f079e75c4e 100644 --- a/cumulus/pallets/weight-reclaim/src/tests.rs +++ b/cumulus/pallets/weight-reclaim/src/tests.rs @@ -89,7 +89,8 @@ mod runtime { RuntimeHoldReason, RuntimeSlashReason, RuntimeLockId, - RuntimeTask + RuntimeTask, + RuntimeViewFunction )] pub struct Test; diff --git a/cumulus/pallets/xcmp-queue/src/bridging.rs b/cumulus/pallets/xcmp-queue/src/bridging.rs index 8ed11505a27a991cf2f6e2ff2097bf886fca1ddb..355691a41659d4f60d6f4dd98e752ae209077798 100644 --- a/cumulus/pallets/xcmp-queue/src/bridging.rs +++ b/cumulus/pallets/xcmp-queue/src/bridging.rs @@ -45,12 +45,11 @@ impl<Runtime: crate::Config> bp_xcm_bridge_hub_router::XcmChannelStatusProvider } } -/// Adapter implementation for `bp_xcm_bridge_hub_router::XcmChannelStatusProvider` which checks -/// only `OutboundXcmpStatus` for defined `SiblingParaId` if is suspended. +/// Adapter implementation for `bp_xcm_bridge::ChannelStatusProvider` and/or +/// `bp_xcm_bridge_hub_router::XcmChannelStatusProvider` which checks only `OutboundXcmpStatus` +/// for defined `Location` if is suspended. pub struct OutXcmpChannelStatusProvider<Runtime>(core::marker::PhantomData<Runtime>); -impl<Runtime: crate::Config> bp_xcm_bridge_hub_router::XcmChannelStatusProvider - for OutXcmpChannelStatusProvider<Runtime> -{ +impl<Runtime: crate::Config> OutXcmpChannelStatusProvider<Runtime> { fn is_congested(with: &Location) -> bool { // handle congestion only for a sibling parachain locations. let sibling_para_id: ParaId = match with.unpack() { @@ -88,6 +87,14 @@ impl<Runtime: crate::Config> bp_xcm_bridge_hub_router::XcmChannelStatusProvider } } +impl<Runtime: crate::Config> bp_xcm_bridge_hub_router::XcmChannelStatusProvider + for OutXcmpChannelStatusProvider<Runtime> +{ + fn is_congested(with: &Location) -> bool { + Self::is_congested(with) + } +} + #[cfg(feature = "runtime-benchmarks")] pub fn suspend_channel_for_benchmarks<T: crate::Config>(target: ParaId) { pallet::Pallet::<T>::suspend_channel(target) diff --git a/cumulus/parachains/integration-tests/emulated/common/src/macros.rs b/cumulus/parachains/integration-tests/emulated/common/src/macros.rs index cd2b41e5198f8de43b332b4bd404739206ff364b..983ac626177ee60ed14ea4cae75a8096b2191361 100644 --- a/cumulus/parachains/integration-tests/emulated/common/src/macros.rs +++ b/cumulus/parachains/integration-tests/emulated/common/src/macros.rs @@ -644,9 +644,8 @@ macro_rules! test_dry_run_transfer_across_pk_bridge { let transfer_amount = 10_000_000_000_000u128; let initial_balance = transfer_amount * 10; - // Bridge setup. + // AssetHub setup. $sender_asset_hub::force_xcm_version($destination, XCM_VERSION); - open_bridge_between_asset_hub_rococo_and_asset_hub_westend(); <$sender_asset_hub as TestExt>::execute_with(|| { type Runtime = <$sender_asset_hub as Chain>::Runtime; diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/Cargo.toml b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/Cargo.toml index 7bb7277df45c0055ae59c5c586c7a3bbb7e08661..35ceffe4c6953a84165987a330a1d806b248e33f 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/Cargo.toml @@ -32,7 +32,6 @@ xcm-runtime-apis = { workspace = true } # Bridges pallet-bridge-messages = { workspace = true } -pallet-xcm-bridge-hub = { workspace = true } # Cumulus cumulus-pallet-xcmp-queue = { workspace = true } diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/asset_transfers.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/asset_transfers.rs index a2a61660afff07419032492f8083408b7c0b6c4e..d1fe94962f184846e6b5b7f1d8efbf01b7c69c66 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/asset_transfers.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/asset_transfers.rs @@ -25,9 +25,6 @@ fn send_assets_over_bridge<F: FnOnce()>(send_fn: F) { AssetHubRococo::force_xcm_version(asset_hub_westend_location(), XCM_VERSION); BridgeHubRococo::force_xcm_version(bridge_hub_westend_location(), XCM_VERSION); - // open bridge - open_bridge_between_asset_hub_rococo_and_asset_hub_westend(); - // send message over bridge send_fn(); diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/mod.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/mod.rs index 8aff877559616ccb24b2f3de1a3a00492404d907..265002897ac5fead8b9b47e8fc0a7ff962572e6f 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/mod.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/mod.rs @@ -51,9 +51,6 @@ pub(crate) fn bridged_roc_at_ah_westend() -> Location { } // WND and wWND -pub(crate) fn wnd_at_ah_westend() -> Location { - Parent.into() -} pub(crate) fn bridged_wnd_at_ah_rococo() -> Location { Location::new(2, [GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH))]) } @@ -240,43 +237,3 @@ pub(crate) fn assert_bridge_hub_westend_message_received() { ); }) } - -pub(crate) fn open_bridge_between_asset_hub_rococo_and_asset_hub_westend() { - use testnet_parachains_constants::{ - rococo::currency::UNITS as ROC, westend::currency::UNITS as WND, - }; - - // open AHR -> AHW - BridgeHubRococo::fund_para_sovereign(AssetHubRococo::para_id(), ROC * 5); - AssetHubRococo::open_bridge( - AssetHubRococo::sibling_location_of(BridgeHubRococo::para_id()), - [ - GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)), - Parachain(AssetHubWestend::para_id().into()), - ] - .into(), - Some(( - (roc_at_ah_rococo(), ROC * 1).into(), - BridgeHubRococo::sovereign_account_id_of(BridgeHubRococo::sibling_location_of( - AssetHubRococo::para_id(), - )), - )), - ); - - // open AHW -> AHR - BridgeHubWestend::fund_para_sovereign(AssetHubWestend::para_id(), WND * 5); - AssetHubWestend::open_bridge( - AssetHubWestend::sibling_location_of(BridgeHubWestend::para_id()), - [ - GlobalConsensus(ByGenesis(ROCOCO_GENESIS_HASH)), - Parachain(AssetHubRococo::para_id().into()), - ] - .into(), - Some(( - (wnd_at_ah_westend(), WND * 1).into(), - BridgeHubWestend::sovereign_account_id_of(BridgeHubWestend::sibling_location_of( - AssetHubWestend::para_id(), - )), - )), - ); -} diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/send_xcm.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/send_xcm.rs index cfcb581238e6d2415b3b3aedefd0719da8a7a7be..799af037869754d70ddd14a97026429526816ea2 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/send_xcm.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/send_xcm.rs @@ -74,9 +74,6 @@ fn send_xcm_through_opened_lane_with_different_xcm_version_on_hops_works() { // fund sender AssetHubRococo::fund_accounts(vec![(AssetHubRococoSender::get().into(), amount * 10)]); - // open bridge - open_bridge_between_asset_hub_rococo_and_asset_hub_westend(); - // Initially set only default version on all runtimes let newer_xcm_version = xcm::prelude::XCM_VERSION; let older_xcm_version = newer_xcm_version - 1; diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/snowbridge.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/snowbridge.rs index 6364ff9fe959288041e369bffb90d117b080b12e..7f242bab5a9dafee282a8003cf92f46ee6897b0c 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/snowbridge.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/snowbridge.rs @@ -498,8 +498,8 @@ fn send_weth_asset_from_asset_hub_to_ethereum() { assert!( events.iter().any(|event| matches!( event, - RuntimeEvent::Balances(pallet_balances::Event::Minted { who, amount }) - if *who == TREASURY_ACCOUNT.into() && *amount == 16903333 + RuntimeEvent::Balances(pallet_balances::Event::Minted { who, amount: _amount }) + if *who == TREASURY_ACCOUNT.into() )), "Snowbridge sovereign takes local fee." ); @@ -507,8 +507,8 @@ fn send_weth_asset_from_asset_hub_to_ethereum() { assert!( events.iter().any(|event| matches!( event, - RuntimeEvent::Balances(pallet_balances::Event::Minted { who, amount }) - if *who == assethub_sovereign && *amount == 2680000000000, + RuntimeEvent::Balances(pallet_balances::Event::Minted { who, amount: _amount }) + if *who == assethub_sovereign )), "AssetHub sovereign takes remote fee." ); @@ -668,8 +668,8 @@ fn send_eth_asset_from_asset_hub_to_ethereum_and_back() { assert!( events.iter().any(|event| matches!( event, - RuntimeEvent::Balances(pallet_balances::Event::Minted { who, amount }) - if *who == TREASURY_ACCOUNT.into() && *amount == 16903333 + RuntimeEvent::Balances(pallet_balances::Event::Minted { who, amount: _amount }) + if *who == TREASURY_ACCOUNT.into() )), "Snowbridge sovereign takes local fee." ); @@ -677,8 +677,8 @@ fn send_eth_asset_from_asset_hub_to_ethereum_and_back() { assert!( events.iter().any(|event| matches!( event, - RuntimeEvent::Balances(pallet_balances::Event::Minted { who, amount }) - if *who == assethub_sovereign && *amount == 2680000000000, + RuntimeEvent::Balances(pallet_balances::Event::Minted { who, amount: _amount }) + if *who == assethub_sovereign )), "AssetHub sovereign takes remote fee." ); diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/Cargo.toml b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/Cargo.toml index dc3bbb269d70efe654a63a18ec1a92342486d6bd..f718e7e77f597723c2a53dac3552bb103bab96d9 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/Cargo.toml @@ -33,7 +33,6 @@ xcm-runtime-apis = { workspace = true } # Bridges pallet-bridge-messages = { workspace = true } -pallet-xcm-bridge-hub = { workspace = true } # Cumulus asset-hub-westend-runtime = { workspace = true } diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/asset_transfers.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/asset_transfers.rs index cc90c10b54bcf8099ba3d6c856799c2c29d666c7..a73c1280b406a7154c05707a4dfe53946ac9c1c9 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/asset_transfers.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/asset_transfers.rs @@ -26,9 +26,6 @@ fn send_assets_over_bridge<F: FnOnce()>(send_fn: F) { AssetHubWestend::force_xcm_version(asset_hub_rococo_location(), XCM_VERSION); BridgeHubWestend::force_xcm_version(bridge_hub_rococo_location(), XCM_VERSION); - // open bridge - open_bridge_between_asset_hub_rococo_and_asset_hub_westend(); - // send message over bridge send_fn(); diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/mod.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/mod.rs index 6c1cdb98e8b2a69b38431d1119d554069e362e4a..676b2862e66783618eeb6d8f0c90d66cbd657936 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/mod.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/mod.rs @@ -52,9 +52,6 @@ pub(crate) fn bridged_wnd_at_ah_rococo() -> Location { } // ROC and wROC -pub(crate) fn roc_at_ah_rococo() -> Location { - Parent.into() -} pub(crate) fn bridged_roc_at_ah_westend() -> Location { Location::new(2, [GlobalConsensus(ByGenesis(ROCOCO_GENESIS_HASH))]) } @@ -250,43 +247,3 @@ pub(crate) fn assert_bridge_hub_rococo_message_received() { ); }) } - -pub(crate) fn open_bridge_between_asset_hub_rococo_and_asset_hub_westend() { - use testnet_parachains_constants::{ - rococo::currency::UNITS as ROC, westend::currency::UNITS as WND, - }; - - // open AHR -> AHW - BridgeHubRococo::fund_para_sovereign(AssetHubRococo::para_id(), ROC * 5); - AssetHubRococo::open_bridge( - AssetHubRococo::sibling_location_of(BridgeHubRococo::para_id()), - [ - GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)), - Parachain(AssetHubWestend::para_id().into()), - ] - .into(), - Some(( - (roc_at_ah_rococo(), ROC * 1).into(), - BridgeHubRococo::sovereign_account_id_of(BridgeHubRococo::sibling_location_of( - AssetHubRococo::para_id(), - )), - )), - ); - - // open AHW -> AHR - BridgeHubWestend::fund_para_sovereign(AssetHubWestend::para_id(), WND * 5); - AssetHubWestend::open_bridge( - AssetHubWestend::sibling_location_of(BridgeHubWestend::para_id()), - [ - GlobalConsensus(ByGenesis(ROCOCO_GENESIS_HASH)), - Parachain(AssetHubRococo::para_id().into()), - ] - .into(), - Some(( - (wnd_at_ah_westend(), WND * 1).into(), - BridgeHubWestend::sovereign_account_id_of(BridgeHubWestend::sibling_location_of( - AssetHubWestend::para_id(), - )), - )), - ); -} diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/send_xcm.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/send_xcm.rs index 60f8af2242f96c504d1836dbb7c6996ca0cb40f2..e655f06a0f01c7d7189a0c6a905eb76821442917 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/send_xcm.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/send_xcm.rs @@ -74,9 +74,6 @@ fn send_xcm_through_opened_lane_with_different_xcm_version_on_hops_works() { // fund sender AssetHubWestend::fund_accounts(vec![(AssetHubWestendSender::get().into(), amount * 10)]); - // open bridge - open_bridge_between_asset_hub_rococo_and_asset_hub_westend(); - // Initially set only default version on all runtimes let newer_xcm_version = xcm::prelude::XCM_VERSION; let older_xcm_version = newer_xcm_version - 1; diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/snowbridge.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/snowbridge.rs index 15ca3a5cf1b85f23234024aa57aa9d472c6bf7ab..6789aae83ffe4bc4e48feaa3c1db353286cd1260 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/snowbridge.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/snowbridge.rs @@ -902,8 +902,8 @@ fn send_weth_asset_from_asset_hub_to_ethereum() { assert!( events.iter().any(|event| matches!( event, - RuntimeEvent::Balances(pallet_balances::Event::Minted { who, amount }) - if *who == TreasuryAccount::get().into() && *amount == 5071000000 + RuntimeEvent::Balances(pallet_balances::Event::Minted { who, amount: _amount }) + if *who == TreasuryAccount::get().into() )), "Snowbridge sovereign takes local fee." ); @@ -911,8 +911,8 @@ fn send_weth_asset_from_asset_hub_to_ethereum() { assert!( events.iter().any(|event| matches!( event, - RuntimeEvent::Balances(pallet_balances::Event::Minted { who, amount }) - if *who == assethub_sovereign && *amount == 2680000000000, + RuntimeEvent::Balances(pallet_balances::Event::Minted { who, amount: _amount }) + if *who == assethub_sovereign )), "AssetHub sovereign takes remote fee." ); diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml index d612dd03c247a101049de02c4bf7822c73302783..3da8aa9b6cfea9de7a0f7a3d685294f5b7fe5a94 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml @@ -40,7 +40,6 @@ pallet-message-queue = { workspace = true } pallet-multisig = { workspace = true } pallet-nft-fractionalization = { workspace = true } pallet-nfts = { workspace = true } -pallet-nfts-runtime-api = { workspace = true } pallet-proxy = { workspace = true } pallet-session = { workspace = true } pallet-timestamp = { workspace = true } @@ -226,7 +225,6 @@ std = [ "pallet-message-queue/std", "pallet-multisig/std", "pallet-nft-fractionalization/std", - "pallet-nfts-runtime-api/std", "pallet-nfts/std", "pallet-proxy/std", "pallet-session/std", diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_multisig.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_multisig.rs index cf9c523f6571f48b37a300295d162960d82528bd..1192478c90ac483d6b82c4a2704d4b1ba5903fbc 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_multisig.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_multisig.rs @@ -16,28 +16,28 @@ //! Autogenerated weights for `pallet_multisig` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-07-31, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2025-01-23, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-ynta1nyy-project-238-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: ``, WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-rococo-dev")`, DB CACHE: 1024 +//! HOSTNAME: `e20fc9f125eb`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-rococo-dev")`, DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot-parachain +// target/production/polkadot-parachain // benchmark // pallet +// --extrinsic=* // --chain=asset-hub-rococo-dev -// --wasm-execution=compiled // --pallet=pallet_multisig -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* +// --header=/__w/polkadot-sdk/polkadot-sdk/cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights +// --wasm-execution=compiled // --steps=50 // --repeat=20 -// --json -// --header=./file_header.txt -// --output=./parachains/runtimes/assets/asset-hub-rococo/src/weights/ +// --heap-pages=4096 +// --no-storage-info +// --no-min-squares +// --no-median-slopes #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -55,11 +55,11 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 13_714_000 picoseconds. - Weight::from_parts(14_440_231, 0) + // Minimum execution time: 16_059_000 picoseconds. + Weight::from_parts(17_033_878, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 5 - .saturating_add(Weight::from_parts(598, 0).saturating_mul(z.into())) + // Standard Error: 8 + .saturating_add(Weight::from_parts(489, 0).saturating_mul(z.into())) } /// Storage: `Multisig::Multisigs` (r:1 w:1) /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) @@ -67,15 +67,15 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { /// The range of component `z` is `[0, 10000]`. fn as_multi_create(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `262 + s * (2 ±0)` + // Measured: `295 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 44_768_000 picoseconds. - Weight::from_parts(33_662_218, 0) + // Minimum execution time: 46_128_000 picoseconds. + Weight::from_parts(33_704_180, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 1_633 - .saturating_add(Weight::from_parts(128_927, 0).saturating_mul(s.into())) - // Standard Error: 16 - .saturating_add(Weight::from_parts(1_543, 0).saturating_mul(z.into())) + // Standard Error: 1_456 + .saturating_add(Weight::from_parts(147_148, 0).saturating_mul(s.into())) + // Standard Error: 14 + .saturating_add(Weight::from_parts(2_037, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -85,15 +85,15 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { /// The range of component `z` is `[0, 10000]`. fn as_multi_approve(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `282` + // Measured: `315` // Estimated: `6811` - // Minimum execution time: 29_745_000 picoseconds. - Weight::from_parts(20_559_891, 0) + // Minimum execution time: 32_218_000 picoseconds. + Weight::from_parts(21_320_145, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 914 - .saturating_add(Weight::from_parts(103_601, 0).saturating_mul(s.into())) - // Standard Error: 8 - .saturating_add(Weight::from_parts(1_504, 0).saturating_mul(z.into())) + // Standard Error: 1_922 + .saturating_add(Weight::from_parts(131_349, 0).saturating_mul(s.into())) + // Standard Error: 18 + .saturating_add(Weight::from_parts(1_829, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -105,60 +105,63 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { /// The range of component `z` is `[0, 10000]`. fn as_multi_complete(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `385 + s * (33 ±0)` + // Measured: `418 + s * (33 ±0)` // Estimated: `6811` - // Minimum execution time: 51_506_000 picoseconds. - Weight::from_parts(36_510_777, 0) + // Minimum execution time: 53_641_000 picoseconds. + Weight::from_parts(32_057_363, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 2_183 - .saturating_add(Weight::from_parts(183_764, 0).saturating_mul(s.into())) - // Standard Error: 21 - .saturating_add(Weight::from_parts(1_653, 0).saturating_mul(z.into())) + // Standard Error: 2_897 + .saturating_add(Weight::from_parts(254_035, 0).saturating_mul(s.into())) + // Standard Error: 28 + .saturating_add(Weight::from_parts(2_432, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } /// Storage: `Multisig::Multisigs` (r:1 w:1) /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. + /// The range of component `z` is `[0, 10000]`. fn approve_as_multi_create(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `263 + s * (2 ±0)` + // Measured: `295 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 31_072_000 picoseconds. - Weight::from_parts(32_408_621, 0) + // Minimum execution time: 30_302_000 picoseconds. + Weight::from_parts(33_367_363, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 913 - .saturating_add(Weight::from_parts(121_410, 0).saturating_mul(s.into())) + // Standard Error: 1_389 + .saturating_add(Weight::from_parts(150_845, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `Multisig::Multisigs` (r:1 w:1) /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. + /// The range of component `z` is `[0, 10000]`. fn approve_as_multi_approve(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `282` + // Measured: `315` // Estimated: `6811` - // Minimum execution time: 18_301_000 picoseconds. - Weight::from_parts(18_223_547, 0) + // Minimum execution time: 17_008_000 picoseconds. + Weight::from_parts(18_452_875, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 747 - .saturating_add(Weight::from_parts(114_584, 0).saturating_mul(s.into())) + // Standard Error: 949 + .saturating_add(Weight::from_parts(130_051, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `Multisig::Multisigs` (r:1 w:1) /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. + /// The range of component `z` is `[0, 10000]`. fn cancel_as_multi(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `454 + s * (1 ±0)` + // Measured: `482 + s * (1 ±0)` // Estimated: `6811` - // Minimum execution time: 32_107_000 picoseconds. - Weight::from_parts(33_674_827, 0) + // Minimum execution time: 30_645_000 picoseconds. + Weight::from_parts(33_864_517, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 1_220 - .saturating_add(Weight::from_parts(122_011, 0).saturating_mul(s.into())) + // Standard Error: 1_511 + .saturating_add(Weight::from_parts(138_628, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml index 65ef63a7fb356c1b2c20a9fcddbc4bdc3d3b8bff..f7fb858de62e87c4048ea0cd8f987a9aba550d2e 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml @@ -36,6 +36,7 @@ pallet-assets-freezer = { workspace = true } pallet-aura = { workspace = true } pallet-authorship = { workspace = true } pallet-balances = { workspace = true } +pallet-migrations = { workspace = true } pallet-multisig = { workspace = true } pallet-nft-fractionalization = { workspace = true } pallet-nfts = { workspace = true } @@ -133,6 +134,7 @@ runtime-benchmarks = [ "pallet-balances/runtime-benchmarks", "pallet-collator-selection/runtime-benchmarks", "pallet-message-queue/runtime-benchmarks", + "pallet-migrations/runtime-benchmarks", "pallet-multisig/runtime-benchmarks", "pallet-nft-fractionalization/runtime-benchmarks", "pallet-nfts/runtime-benchmarks", @@ -177,6 +179,7 @@ try-runtime = [ "pallet-balances/try-runtime", "pallet-collator-selection/try-runtime", "pallet-message-queue/try-runtime", + "pallet-migrations/try-runtime", "pallet-multisig/try-runtime", "pallet-nft-fractionalization/try-runtime", "pallet-nfts/try-runtime", @@ -230,6 +233,7 @@ std = [ "pallet-balances/std", "pallet-collator-selection/std", "pallet-message-queue/std", + "pallet-migrations/std", "pallet-multisig/std", "pallet-nft-fractionalization/std", "pallet-nfts-runtime-api/std", diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index ecbe1fb0e62af8e84cd2086e61f15fd6e7c01451..bf26f0ff452bf63b0e6313461812ae0c26e615dc 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -185,6 +185,7 @@ impl frame_system::Config for Runtime { type SS58Prefix = SS58Prefix; type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode<Self>; type MaxConsumers = frame_support::traits::ConstU32<16>; + type MultiBlockMigrator = MultiBlockMigrations; } impl cumulus_pallet_weight_reclaim::Config for Runtime { @@ -1081,6 +1082,7 @@ impl pallet_revive::Config for Runtime { type ChainId = ConstU64<420_420_421>; type NativeToEthRatio = ConstU32<1_000_000>; // 10^(18 - 12) Eth is 10^18, Native is 10^12. type EthGasEncoder = (); + type FindAuthor = <Runtime as pallet_authorship::Config>::FindAuthor; } impl TryFrom<RuntimeCall> for pallet_revive::Call<Runtime> { @@ -1094,6 +1096,25 @@ impl TryFrom<RuntimeCall> for pallet_revive::Call<Runtime> { } } +parameter_types! { + pub MbmServiceWeight: Weight = Perbill::from_percent(80) * RuntimeBlockWeights::get().max_block; +} + +impl pallet_migrations::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + #[cfg(not(feature = "runtime-benchmarks"))] + type Migrations = pallet_migrations::migrations::ResetPallet<Runtime, Revive>; + // Benchmarks need mocked migrations to guarantee that they succeed. + #[cfg(feature = "runtime-benchmarks")] + type Migrations = pallet_migrations::mock_helpers::MockedMigrations; + type CursorMaxLen = ConstU32<65_536>; + type IdentifierMaxLen = ConstU32<256>; + type MigrationStatusHandler = (); + type FailedMigrationHandler = frame_support::migrations::FreezeChainOnFailedMigration; + type MaxServiceWeight = MbmServiceWeight; + type WeightInfo = weights::pallet_migrations::WeightInfo<Runtime>; +} + // Create the runtime by composing the FRAME pallets that were previously configured. construct_runtime!( pub enum Runtime @@ -1105,6 +1126,7 @@ construct_runtime!( Timestamp: pallet_timestamp = 3, ParachainInfo: parachain_info = 4, WeightReclaim: cumulus_pallet_weight_reclaim = 5, + MultiBlockMigrations: pallet_migrations = 6, // Monetary stuff. Balances: pallet_balances = 10, @@ -1429,6 +1451,7 @@ mod benches { [pallet_asset_conversion_tx_payment, AssetTxPayment] [pallet_balances, Balances] [pallet_message_queue, MessageQueue] + [pallet_migrations, MultiBlockMigrations] [pallet_multisig, Multisig] [pallet_nft_fractionalization, NftFractionalization] [pallet_nfts, Nfts] @@ -1443,7 +1466,6 @@ mod benches { [cumulus_pallet_xcmp_queue, XcmpQueue] [pallet_xcm_bridge_hub_router, ToRococo] [pallet_asset_conversion_ops, AssetConversionMigration] - [pallet_revive, Revive] // XCM [pallet_xcm, PalletXcmExtrinsicsBenchmark::<Runtime>] // NOTE: Make sure you point to the individual modules below. diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/mod.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/mod.rs index d653838ad80e61d9dd96a705a1871fe4c4858fa8..86cd12507401f0df64dee2806b51b6e42e8b6a86 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/mod.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/mod.rs @@ -30,6 +30,7 @@ pub mod pallet_assets_pool; pub mod pallet_balances; pub mod pallet_collator_selection; pub mod pallet_message_queue; +pub mod pallet_migrations; pub mod pallet_multisig; pub mod pallet_nft_fractionalization; pub mod pallet_nfts; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_migrations.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_migrations.rs new file mode 100644 index 0000000000000000000000000000000000000000..e771059cec8596ae5b86a60e3be85600d79bbe0c --- /dev/null +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_migrations.rs @@ -0,0 +1,225 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Cumulus. + +// Cumulus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Cumulus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Cumulus. If not, see <http://www.gnu.org/licenses/>. + +//! Autogenerated weights for `pallet_migrations` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2025-01-27, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `17938671047b`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: 1024 + +// Executed Command: +// frame-omni-bencher +// v1 +// benchmark +// pallet +// --extrinsic=* +// --runtime=target/production/wbuild/asset-hub-westend-runtime/asset_hub_westend_runtime.wasm +// --pallet=pallet_migrations +// --header=/__w/polkadot-sdk/polkadot-sdk/cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights +// --wasm-execution=compiled +// --steps=50 +// --repeat=20 +// --heap-pages=4096 +// --no-storage-info +// --no-min-squares +// --no-median-slopes + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_migrations`. +pub struct WeightInfo<T>(PhantomData<T>); +impl<T: frame_system::Config> pallet_migrations::WeightInfo for WeightInfo<T> { + /// Storage: `MultiBlockMigrations::Cursor` (r:1 w:1) + /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) + /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + fn onboard_new_mbms() -> Weight { + // Proof Size summary in bytes: + // Measured: `171` + // Estimated: `67035` + // Minimum execution time: 8_697_000 picoseconds. + Weight::from_parts(8_998_000, 0) + .saturating_add(Weight::from_parts(0, 67035)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `MultiBlockMigrations::Cursor` (r:1 w:0) + /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) + fn progress_mbms_none() -> Weight { + // Proof Size summary in bytes: + // Measured: `42` + // Estimated: `67035` + // Minimum execution time: 2_737_000 picoseconds. + Weight::from_parts(2_813_000, 0) + .saturating_add(Weight::from_parts(0, 67035)) + .saturating_add(T::DbWeight::get().reads(1)) + } + /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + /// Storage: `MultiBlockMigrations::Cursor` (r:0 w:1) + /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) + fn exec_migration_completed() -> Weight { + // Proof Size summary in bytes: + // Measured: `129` + // Estimated: `3594` + // Minimum execution time: 6_181_000 picoseconds. + Weight::from_parts(6_458_000, 0) + .saturating_add(Weight::from_parts(0, 3594)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + /// Storage: `MultiBlockMigrations::Historic` (r:1 w:0) + /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) + fn exec_migration_skipped_historic() -> Weight { + // Proof Size summary in bytes: + // Measured: `225` + // Estimated: `3731` + // Minimum execution time: 11_932_000 picoseconds. + Weight::from_parts(12_539_000, 0) + .saturating_add(Weight::from_parts(0, 3731)) + .saturating_add(T::DbWeight::get().reads(2)) + } + /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + /// Storage: `MultiBlockMigrations::Historic` (r:1 w:0) + /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) + fn exec_migration_advance() -> Weight { + // Proof Size summary in bytes: + // Measured: `171` + // Estimated: `3731` + // Minimum execution time: 11_127_000 picoseconds. + Weight::from_parts(11_584_000, 0) + .saturating_add(Weight::from_parts(0, 3731)) + .saturating_add(T::DbWeight::get().reads(2)) + } + /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + /// Storage: `MultiBlockMigrations::Historic` (r:1 w:1) + /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) + fn exec_migration_complete() -> Weight { + // Proof Size summary in bytes: + // Measured: `171` + // Estimated: `3731` + // Minimum execution time: 12_930_000 picoseconds. + Weight::from_parts(13_272_000, 0) + .saturating_add(Weight::from_parts(0, 3731)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + /// Storage: `MultiBlockMigrations::Historic` (r:1 w:0) + /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) + /// Storage: `MultiBlockMigrations::Cursor` (r:0 w:1) + /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) + fn exec_migration_fail() -> Weight { + // Proof Size summary in bytes: + // Measured: `171` + // Estimated: `3731` + // Minimum execution time: 13_709_000 picoseconds. + Weight::from_parts(14_123_000, 0) + .saturating_add(Weight::from_parts(0, 3731)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } + fn on_init_loop() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 162_000 picoseconds. + Weight::from_parts(188_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: `MultiBlockMigrations::Cursor` (r:0 w:1) + /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) + fn force_set_cursor() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 2_737_000 picoseconds. + Weight::from_parts(2_919_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `MultiBlockMigrations::Cursor` (r:0 w:1) + /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) + fn force_set_active_cursor() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 3_087_000 picoseconds. + Weight::from_parts(3_320_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `MultiBlockMigrations::Cursor` (r:1 w:0) + /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) + /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) + fn force_onboard_mbms() -> Weight { + // Proof Size summary in bytes: + // Measured: `147` + // Estimated: `67035` + // Minimum execution time: 6_470_000 picoseconds. + Weight::from_parts(6_760_000, 0) + .saturating_add(Weight::from_parts(0, 67035)) + .saturating_add(T::DbWeight::get().reads(2)) + } + /// Storage: `MultiBlockMigrations::Historic` (r:256 w:256) + /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) + /// The range of component `n` is `[0, 256]`. + fn clear_historic(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1022 + n * (271 ±0)` + // Estimated: `3834 + n * (2740 ±0)` + // Minimum execution time: 15_864_000 picoseconds. + Weight::from_parts(24_535_162, 0) + .saturating_add(Weight::from_parts(0, 3834)) + // Standard Error: 8_688 + .saturating_add(Weight::from_parts(1_530_542, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 2740).saturating_mul(n.into())) + } + /// Storage: `Skipped::Metadata` (r:0 w:0) + /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// The range of component `n` is `[0, 2048]`. + fn reset_pallet_migration(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1680 + n * (38 ±0)` + // Estimated: `758 + n * (39 ±0)` + // Minimum execution time: 2_168_000 picoseconds. + Weight::from_parts(2_226_000, 0) + .saturating_add(Weight::from_parts(0, 758)) + // Standard Error: 2_841 + .saturating_add(Weight::from_parts(935_438, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 39).saturating_mul(n.into())) + } +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_multisig.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_multisig.rs index 27687e10751b3ad052ddd6a9269cdcc415ef563d..737ee0f54df0cc7957a962d8275a6b68d97dcb2f 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_multisig.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_multisig.rs @@ -1,42 +1,43 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 +// This file is part of Cumulus. -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Cumulus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Cumulus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Cumulus. If not, see <http://www.gnu.org/licenses/>. //! Autogenerated weights for `pallet_multisig` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-07-31, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2025-01-23, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-ynta1nyy-project-238-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: ``, WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-westend-dev")`, DB CACHE: 1024 +//! HOSTNAME: `e20fc9f125eb`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-westend-dev")`, DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot-parachain +// target/production/polkadot-parachain // benchmark // pallet +// --extrinsic=* // --chain=asset-hub-westend-dev -// --wasm-execution=compiled // --pallet=pallet_multisig -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* +// --header=/__w/polkadot-sdk/polkadot-sdk/cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights +// --wasm-execution=compiled // --steps=50 // --repeat=20 -// --json -// --header=./file_header.txt -// --output=./parachains/runtimes/assets/asset-hub-westend/src/weights/ +// --heap-pages=4096 +// --no-storage-info +// --no-min-squares +// --no-median-slopes #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -54,11 +55,11 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 14_098_000 picoseconds. - Weight::from_parts(14_915_657, 0) + // Minimum execution time: 16_032_000 picoseconds. + Weight::from_parts(16_636_014, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 6 - .saturating_add(Weight::from_parts(454, 0).saturating_mul(z.into())) + // Standard Error: 11 + .saturating_add(Weight::from_parts(632, 0).saturating_mul(z.into())) } /// Storage: `Multisig::Multisigs` (r:1 w:1) /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) @@ -66,15 +67,15 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { /// The range of component `z` is `[0, 10000]`. fn as_multi_create(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `262 + s * (2 ±0)` + // Measured: `295 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 44_573_000 picoseconds. - Weight::from_parts(32_633_219, 0) + // Minimum execution time: 47_519_000 picoseconds. + Weight::from_parts(33_881_382, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 1_256 - .saturating_add(Weight::from_parts(131_767, 0).saturating_mul(s.into())) - // Standard Error: 12 - .saturating_add(Weight::from_parts(1_512, 0).saturating_mul(z.into())) + // Standard Error: 1_770 + .saturating_add(Weight::from_parts(159_560, 0).saturating_mul(s.into())) + // Standard Error: 17 + .saturating_add(Weight::from_parts(2_031, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -84,15 +85,15 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { /// The range of component `z` is `[0, 10000]`. fn as_multi_approve(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `282` + // Measured: `315` // Estimated: `6811` - // Minimum execution time: 30_035_000 picoseconds. - Weight::from_parts(20_179_371, 0) + // Minimum execution time: 31_369_000 picoseconds. + Weight::from_parts(18_862_672, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 827 - .saturating_add(Weight::from_parts(110_520, 0).saturating_mul(s.into())) - // Standard Error: 8 - .saturating_add(Weight::from_parts(1_419, 0).saturating_mul(z.into())) + // Standard Error: 1_519 + .saturating_add(Weight::from_parts(141_546, 0).saturating_mul(s.into())) + // Standard Error: 14 + .saturating_add(Weight::from_parts(2_057, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -104,60 +105,63 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { /// The range of component `z` is `[0, 10000]`. fn as_multi_complete(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `385 + s * (33 ±0)` + // Measured: `418 + s * (33 ±0)` // Estimated: `6811` - // Minimum execution time: 50_444_000 picoseconds. - Weight::from_parts(36_060_265, 0) + // Minimum execution time: 55_421_000 picoseconds. + Weight::from_parts(33_628_199, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 1_604 - .saturating_add(Weight::from_parts(187_796, 0).saturating_mul(s.into())) - // Standard Error: 15 - .saturating_add(Weight::from_parts(1_506, 0).saturating_mul(z.into())) + // Standard Error: 2_430 + .saturating_add(Weight::from_parts(247_959, 0).saturating_mul(s.into())) + // Standard Error: 23 + .saturating_add(Weight::from_parts(2_339, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } /// Storage: `Multisig::Multisigs` (r:1 w:1) /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. + /// The range of component `z` is `[0, 10000]`. fn approve_as_multi_create(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `263 + s * (2 ±0)` + // Measured: `295 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 30_298_000 picoseconds. - Weight::from_parts(31_284_628, 0) + // Minimum execution time: 30_380_000 picoseconds. + Weight::from_parts(32_147_463, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 924 - .saturating_add(Weight::from_parts(132_724, 0).saturating_mul(s.into())) + // Standard Error: 1_530 + .saturating_add(Weight::from_parts(156_234, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `Multisig::Multisigs` (r:1 w:1) /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. + /// The range of component `z` is `[0, 10000]`. fn approve_as_multi_approve(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `282` + // Measured: `315` // Estimated: `6811` - // Minimum execution time: 17_486_000 picoseconds. - Weight::from_parts(18_518_530, 0) + // Minimum execution time: 17_016_000 picoseconds. + Weight::from_parts(17_777_791, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 1_274 - .saturating_add(Weight::from_parts(103_767, 0).saturating_mul(s.into())) + // Standard Error: 1_216 + .saturating_add(Weight::from_parts(137_967, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `Multisig::Multisigs` (r:1 w:1) /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. + /// The range of component `z` is `[0, 10000]`. fn cancel_as_multi(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `454 + s * (1 ±0)` + // Measured: `482 + s * (1 ±0)` // Estimated: `6811` - // Minimum execution time: 31_236_000 picoseconds. - Weight::from_parts(32_663_816, 0) + // Minimum execution time: 31_594_000 picoseconds. + Weight::from_parts(31_850_574, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 1_445 - .saturating_add(Weight::from_parts(131_060, 0).saturating_mul(s.into())) + // Standard Error: 2_031 + .saturating_add(Weight::from_parts(159_513, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_multisig.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_multisig.rs index 832380d3876bc3d19339779c83bba031304d17db..4ee6f6725409b5bc0f0293cac4c8a42920cd0137 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_multisig.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/pallet_multisig.rs @@ -1,42 +1,43 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 +// This file is part of Cumulus. -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Cumulus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Cumulus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Cumulus. If not, see <http://www.gnu.org/licenses/>. //! Autogenerated weights for `pallet_multisig` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-07-31, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2025-01-23, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-ynta1nyy-project-238-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: ``, WASM-EXECUTION: `Compiled`, CHAIN: `Some("bridge-hub-rococo-dev")`, DB CACHE: 1024 +//! HOSTNAME: `e20fc9f125eb`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("bridge-hub-rococo-dev")`, DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot-parachain +// target/production/polkadot-parachain // benchmark // pallet +// --extrinsic=* // --chain=bridge-hub-rococo-dev -// --wasm-execution=compiled // --pallet=pallet_multisig -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* +// --header=/__w/polkadot-sdk/polkadot-sdk/cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights +// --wasm-execution=compiled // --steps=50 // --repeat=20 -// --json -// --header=./file_header.txt -// --output=./parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/ +// --heap-pages=4096 +// --no-storage-info +// --no-min-squares +// --no-median-slopes #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -54,11 +55,11 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 13_958_000 picoseconds. - Weight::from_parts(14_501_711, 0) + // Minimum execution time: 16_890_000 picoseconds. + Weight::from_parts(17_493_920, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 4 - .saturating_add(Weight::from_parts(626, 0).saturating_mul(z.into())) + // Standard Error: 11 + .saturating_add(Weight::from_parts(559, 0).saturating_mul(z.into())) } /// Storage: `Multisig::Multisigs` (r:1 w:1) /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) @@ -66,15 +67,15 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { /// The range of component `z` is `[0, 10000]`. fn as_multi_create(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `263 + s * (2 ±0)` + // Measured: `191 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 44_067_000 picoseconds. - Weight::from_parts(33_432_998, 0) + // Minimum execution time: 46_099_000 picoseconds. + Weight::from_parts(34_431_293, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 1_250 - .saturating_add(Weight::from_parts(131_851, 0).saturating_mul(s.into())) - // Standard Error: 12 - .saturating_add(Weight::from_parts(1_459, 0).saturating_mul(z.into())) + // Standard Error: 2_489 + .saturating_add(Weight::from_parts(151_886, 0).saturating_mul(s.into())) + // Standard Error: 24 + .saturating_add(Weight::from_parts(1_900, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -84,15 +85,15 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { /// The range of component `z` is `[0, 10000]`. fn as_multi_approve(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `282` + // Measured: `210` // Estimated: `6811` - // Minimum execution time: 29_373_000 picoseconds. - Weight::from_parts(19_409_201, 0) + // Minimum execution time: 31_133_000 picoseconds. + Weight::from_parts(19_877_758, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 725 - .saturating_add(Weight::from_parts(110_824, 0).saturating_mul(s.into())) - // Standard Error: 7 - .saturating_add(Weight::from_parts(1_502, 0).saturating_mul(z.into())) + // Standard Error: 1_220 + .saturating_add(Weight::from_parts(132_155, 0).saturating_mul(s.into())) + // Standard Error: 11 + .saturating_add(Weight::from_parts(1_916, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -104,60 +105,63 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { /// The range of component `z` is `[0, 10000]`. fn as_multi_complete(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `388 + s * (33 ±0)` + // Measured: `316 + s * (33 ±0)` // Estimated: `6811` - // Minimum execution time: 49_724_000 picoseconds. - Weight::from_parts(34_153_321, 0) + // Minimum execution time: 58_414_000 picoseconds. + Weight::from_parts(32_980_753, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 1_376 - .saturating_add(Weight::from_parts(174_634, 0).saturating_mul(s.into())) - // Standard Error: 13 - .saturating_add(Weight::from_parts(1_753, 0).saturating_mul(z.into())) + // Standard Error: 3_838 + .saturating_add(Weight::from_parts(302_359, 0).saturating_mul(s.into())) + // Standard Error: 37 + .saturating_add(Weight::from_parts(2_629, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } /// Storage: `Multisig::Multisigs` (r:1 w:1) /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. + /// The range of component `z` is `[0, 10000]`. fn approve_as_multi_create(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `263 + s * (2 ±0)` + // Measured: `191 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 31_081_000 picoseconds. - Weight::from_parts(31_552_702, 0) + // Minimum execution time: 29_917_000 picoseconds. + Weight::from_parts(33_459_806, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 1_066 - .saturating_add(Weight::from_parts(135_081, 0).saturating_mul(s.into())) + // Standard Error: 1_607 + .saturating_add(Weight::from_parts(150_128, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `Multisig::Multisigs` (r:1 w:1) /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. + /// The range of component `z` is `[0, 10000]`. fn approve_as_multi_approve(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `282` + // Measured: `210` // Estimated: `6811` - // Minimum execution time: 17_807_000 picoseconds. - Weight::from_parts(18_241_044, 0) + // Minimum execution time: 16_739_000 picoseconds. + Weight::from_parts(16_757_542, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 768 - .saturating_add(Weight::from_parts(112_957, 0).saturating_mul(s.into())) + // Standard Error: 909 + .saturating_add(Weight::from_parts(138_791, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `Multisig::Multisigs` (r:1 w:1) /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. + /// The range of component `z` is `[0, 10000]`. fn cancel_as_multi(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `454 + s * (1 ±0)` + // Measured: `382 + s * (1 ±0)` // Estimated: `6811` - // Minimum execution time: 32_421_000 picoseconds. - Weight::from_parts(32_554_061, 0) + // Minimum execution time: 35_004_000 picoseconds. + Weight::from_parts(35_434_253, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 1_157 - .saturating_add(Weight::from_parts(141_221, 0).saturating_mul(s.into())) + // Standard Error: 1_130 + .saturating_add(Weight::from_parts(158_542, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs index 3824a4e9a7cb3bd9eb66b524ed7525dcb92c5a69..36b565bdca1c9923cefe6f27617b9c38fc71ce0b 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs @@ -394,10 +394,14 @@ parameter_types! { impl pallet_message_queue::Config for Runtime { type RuntimeEvent = RuntimeEvent; type WeightInfo = weights::pallet_message_queue::WeightInfo<Runtime>; - #[cfg(feature = "runtime-benchmarks")] + // Use the NoopMessageProcessor exclusively for benchmarks, not for tests with the + // runtime-benchmarks feature as tests require the BridgeHubMessageRouter to process messages. + // The "test" feature flag doesn't work, hence the reliance on the "std" feature, which is + // enabled during tests. + #[cfg(all(not(feature = "std"), feature = "runtime-benchmarks"))] type MessageProcessor = pallet_message_queue::mock_helpers::NoopMessageProcessor<AggregateMessageOrigin>; - #[cfg(not(feature = "runtime-benchmarks"))] + #[cfg(any(feature = "std", not(feature = "runtime-benchmarks")))] type MessageProcessor = bridge_hub_common::BridgeHubMessageRouter< xcm_builder::ProcessXcmMessage< AggregateMessageOrigin, diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_multisig.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_multisig.rs index 91840ae0c6d77cfb4507d5f7d7b8f2aca7c84b35..599bed182de474b6e5b9d10e052e14ce32db21d0 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_multisig.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights/pallet_multisig.rs @@ -16,28 +16,28 @@ //! Autogenerated weights for `pallet_multisig` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-07-31, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2025-01-23, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-ynta1nyy-project-238-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: ``, WASM-EXECUTION: `Compiled`, CHAIN: `Some("bridge-hub-rococo-dev")`, DB CACHE: 1024 +//! HOSTNAME: `e20fc9f125eb`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("bridge-hub-westend-dev")`, DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot-parachain +// target/production/polkadot-parachain // benchmark // pallet -// --chain=bridge-hub-rococo-dev -// --wasm-execution=compiled -// --pallet=pallet_multisig -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --extrinsic=* +// --chain=bridge-hub-westend-dev +// --pallet=pallet_multisig +// --header=/__w/polkadot-sdk/polkadot-sdk/cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/weights +// --wasm-execution=compiled // --steps=50 // --repeat=20 -// --json -// --header=./file_header.txt -// --output=./parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/ +// --heap-pages=4096 +// --no-storage-info +// --no-min-squares +// --no-median-slopes #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -55,11 +55,11 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 13_958_000 picoseconds. - Weight::from_parts(14_501_711, 0) + // Minimum execution time: 16_960_000 picoseconds. + Weight::from_parts(17_458_038, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 4 - .saturating_add(Weight::from_parts(626, 0).saturating_mul(z.into())) + // Standard Error: 14 + .saturating_add(Weight::from_parts(745, 0).saturating_mul(z.into())) } /// Storage: `Multisig::Multisigs` (r:1 w:1) /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) @@ -67,15 +67,15 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { /// The range of component `z` is `[0, 10000]`. fn as_multi_create(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `263 + s * (2 ±0)` + // Measured: `296 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 44_067_000 picoseconds. - Weight::from_parts(33_432_998, 0) + // Minimum execution time: 49_023_000 picoseconds. + Weight::from_parts(36_653_713, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 1_250 - .saturating_add(Weight::from_parts(131_851, 0).saturating_mul(s.into())) - // Standard Error: 12 - .saturating_add(Weight::from_parts(1_459, 0).saturating_mul(z.into())) + // Standard Error: 1_966 + .saturating_add(Weight::from_parts(144_768, 0).saturating_mul(s.into())) + // Standard Error: 19 + .saturating_add(Weight::from_parts(1_983, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -85,15 +85,15 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { /// The range of component `z` is `[0, 10000]`. fn as_multi_approve(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `282` + // Measured: `315` // Estimated: `6811` - // Minimum execution time: 29_373_000 picoseconds. - Weight::from_parts(19_409_201, 0) + // Minimum execution time: 32_233_000 picoseconds. + Weight::from_parts(20_563_994, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 725 - .saturating_add(Weight::from_parts(110_824, 0).saturating_mul(s.into())) - // Standard Error: 7 - .saturating_add(Weight::from_parts(1_502, 0).saturating_mul(z.into())) + // Standard Error: 1_541 + .saturating_add(Weight::from_parts(137_834, 0).saturating_mul(s.into())) + // Standard Error: 15 + .saturating_add(Weight::from_parts(2_004, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -105,60 +105,63 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { /// The range of component `z` is `[0, 10000]`. fn as_multi_complete(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `388 + s * (33 ±0)` + // Measured: `421 + s * (33 ±0)` // Estimated: `6811` - // Minimum execution time: 49_724_000 picoseconds. - Weight::from_parts(34_153_321, 0) + // Minimum execution time: 57_893_000 picoseconds. + Weight::from_parts(32_138_684, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 1_376 - .saturating_add(Weight::from_parts(174_634, 0).saturating_mul(s.into())) - // Standard Error: 13 - .saturating_add(Weight::from_parts(1_753, 0).saturating_mul(z.into())) + // Standard Error: 3_096 + .saturating_add(Weight::from_parts(324_931, 0).saturating_mul(s.into())) + // Standard Error: 30 + .saturating_add(Weight::from_parts(2_617, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } /// Storage: `Multisig::Multisigs` (r:1 w:1) /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. + /// The range of component `z` is `[0, 10000]`. fn approve_as_multi_create(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `263 + s * (2 ±0)` + // Measured: `296 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 31_081_000 picoseconds. - Weight::from_parts(31_552_702, 0) + // Minimum execution time: 31_313_000 picoseconds. + Weight::from_parts(33_535_933, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 1_066 - .saturating_add(Weight::from_parts(135_081, 0).saturating_mul(s.into())) + // Standard Error: 1_649 + .saturating_add(Weight::from_parts(153_756, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `Multisig::Multisigs` (r:1 w:1) /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. + /// The range of component `z` is `[0, 10000]`. fn approve_as_multi_approve(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `282` + // Measured: `315` // Estimated: `6811` - // Minimum execution time: 17_807_000 picoseconds. - Weight::from_parts(18_241_044, 0) + // Minimum execution time: 17_860_000 picoseconds. + Weight::from_parts(18_559_535, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 768 - .saturating_add(Weight::from_parts(112_957, 0).saturating_mul(s.into())) + // Standard Error: 1_036 + .saturating_add(Weight::from_parts(135_049, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `Multisig::Multisigs` (r:1 w:1) /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. + /// The range of component `z` is `[0, 10000]`. fn cancel_as_multi(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `454 + s * (1 ±0)` + // Measured: `487 + s * (1 ±0)` // Estimated: `6811` - // Minimum execution time: 32_421_000 picoseconds. - Weight::from_parts(32_554_061, 0) + // Minimum execution time: 32_340_000 picoseconds. + Weight::from_parts(33_519_124, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 1_157 - .saturating_add(Weight::from_parts(141_221, 0).saturating_mul(s.into())) + // Standard Error: 1_932 + .saturating_add(Weight::from_parts(193_896, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/cumulus/parachains/runtimes/bridge-hubs/common/Cargo.toml b/cumulus/parachains/runtimes/bridge-hubs/common/Cargo.toml index 2fbb96d75163583f6be49b54a6b9238194987cfa..9c5c7c5139096782c6749bc72a987fa9d2cd0663 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/common/Cargo.toml +++ b/cumulus/parachains/runtimes/bridge-hubs/common/Cargo.toml @@ -19,6 +19,8 @@ sp-core = { workspace = true } sp-runtime = { workspace = true } sp-std = { workspace = true } xcm = { workspace = true } +xcm-builder = { workspace = true } +xcm-executor = { workspace = true } [features] default = ["std"] @@ -32,6 +34,8 @@ std = [ "sp-core/std", "sp-runtime/std", "sp-std/std", + "xcm-builder/std", + "xcm-executor/std", "xcm/std", ] @@ -41,5 +45,7 @@ runtime-benchmarks = [ "pallet-message-queue/runtime-benchmarks", "snowbridge-core/runtime-benchmarks", "sp-runtime/runtime-benchmarks", + "xcm-builder/runtime-benchmarks", + "xcm-executor/runtime-benchmarks", "xcm/runtime-benchmarks", ] diff --git a/cumulus/parachains/runtimes/bridge-hubs/common/src/barriers.rs b/cumulus/parachains/runtimes/bridge-hubs/common/src/barriers.rs new file mode 100644 index 0000000000000000000000000000000000000000..6b5dee3de3842a3fec59568ebf0dee7445a27ada --- /dev/null +++ b/cumulus/parachains/runtimes/bridge-hubs/common/src/barriers.rs @@ -0,0 +1,57 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use core::{marker::PhantomData, ops::ControlFlow}; +use cumulus_primitives_core::Weight; +use frame_support::traits::{Contains, ProcessMessageError}; +use xcm::prelude::{ExportMessage, Instruction, Location, NetworkId}; + +use xcm_builder::{CreateMatcher, MatchXcm}; +use xcm_executor::traits::{DenyExecution, Properties}; + +/// Deny execution if the message contains instruction `ExportMessage` with +/// a. origin is contained in `FromOrigin` (i.e.`FromOrigin::Contains(origin)`) +/// b. network is contained in `ToGlobalConsensus`, (i.e. `ToGlobalConsensus::contains(network)`) +pub struct DenyExportMessageFrom<FromOrigin, ToGlobalConsensus>( + PhantomData<(FromOrigin, ToGlobalConsensus)>, +); + +impl<FromOrigin, ToGlobalConsensus> DenyExecution + for DenyExportMessageFrom<FromOrigin, ToGlobalConsensus> +where + FromOrigin: Contains<Location>, + ToGlobalConsensus: Contains<NetworkId>, +{ + fn deny_execution<RuntimeCall>( + origin: &Location, + message: &mut [Instruction<RuntimeCall>], + _max_weight: Weight, + _properties: &mut Properties, + ) -> Result<(), ProcessMessageError> { + // This barrier only cares about messages with `origin` matching `FromOrigin`. + if !FromOrigin::contains(origin) { + return Ok(()) + } + message.matcher().match_next_inst_while( + |_| true, + |inst| match inst { + ExportMessage { network, .. } if ToGlobalConsensus::contains(network) => + Err(ProcessMessageError::Unsupported), + _ => Ok(ControlFlow::Continue(())), + }, + )?; + Ok(()) + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/common/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/common/src/lib.rs index b806b8cdb22db5386baf53b302cc06902c06f215..dbd87bea2142f7ad9be8a45247c059cabcc8b04d 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/common/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/common/src/lib.rs @@ -14,9 +14,11 @@ // limitations under the License. #![cfg_attr(not(feature = "std"), no_std)] +pub mod barriers; pub mod digest_item; pub mod message_queue; pub mod xcm_version; +pub use barriers::DenyExportMessageFrom; pub use digest_item::CustomDigestItem; pub use message_queue::{AggregateMessageOrigin, BridgeHubMessageRouter}; diff --git a/cumulus/parachains/runtimes/bridge-hubs/common/tests/tests.rs b/cumulus/parachains/runtimes/bridge-hubs/common/tests/tests.rs new file mode 100644 index 0000000000000000000000000000000000000000..84c135728d5dce17cbc8ef52dc0bedd9b20e304a --- /dev/null +++ b/cumulus/parachains/runtimes/bridge-hubs/common/tests/tests.rs @@ -0,0 +1,85 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Cumulus. + +// Cumulus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Cumulus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Cumulus. If not, see <http://www.gnu.org/licenses/>. + +#![cfg(test)] +use bridge_hub_common::DenyExportMessageFrom; +use frame_support::{ + parameter_types, + traits::{Equals, EverythingBut, ProcessMessageError::Unsupported}, +}; +use xcm::prelude::{ + AliasOrigin, ByGenesis, ExportMessage, Here, Instruction, Location, NetworkId, Parachain, + Weight, +}; +use xcm_executor::traits::{DenyExecution, Properties}; + +#[test] +fn test_deny_export_message_from() { + parameter_types! { + pub Source1: Location = Location::new(1, Parachain(1)); + pub Source2: Location = Location::new(1, Parachain(2)); + pub Remote1: NetworkId = ByGenesis([1;32]); + pub Remote2: NetworkId = ByGenesis([2;32]); + } + + // Deny ExportMessage when both of the conditions met: + // 1: source != Source1 + // 2: network == Remote1 + pub type Denied = DenyExportMessageFrom<EverythingBut<Equals<Source1>>, Equals<Remote1>>; + + let assert_deny_execution = |mut xcm: Vec<Instruction<()>>, origin, expected_result| { + assert_eq!( + Denied::deny_execution( + &origin, + &mut xcm, + Weight::zero(), + &mut Properties { weight_credit: Weight::zero(), message_id: None } + ), + expected_result + ); + }; + + // A message without an `ExportMessage` should pass + assert_deny_execution(vec![AliasOrigin(Here.into())], Source1::get(), Ok(())); + + // `ExportMessage` from source1 and remote1 should pass + assert_deny_execution( + vec![ExportMessage { network: Remote1::get(), destination: Here, xcm: Default::default() }], + Source1::get(), + Ok(()), + ); + + // `ExportMessage` from source1 and remote2 should pass + assert_deny_execution( + vec![ExportMessage { network: Remote2::get(), destination: Here, xcm: Default::default() }], + Source1::get(), + Ok(()), + ); + + // `ExportMessage` from source2 and remote2 should pass + assert_deny_execution( + vec![ExportMessage { network: Remote2::get(), destination: Here, xcm: Default::default() }], + Source2::get(), + Ok(()), + ); + + // `ExportMessage` from source2 and remote1 should be banned + assert_deny_execution( + vec![ExportMessage { network: Remote1::get(), destination: Here, xcm: Default::default() }], + Source2::get(), + Err(Unsupported), + ); +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/test-utils/Cargo.toml b/cumulus/parachains/runtimes/bridge-hubs/test-utils/Cargo.toml index ace23e71c4d119e7870eb86794bd4316e0a275c4..dc390d48cc777f8e5369da174d5ffe404d487542 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/test-utils/Cargo.toml +++ b/cumulus/parachains/runtimes/bridge-hubs/test-utils/Cargo.toml @@ -26,6 +26,7 @@ sp-core = { workspace = true } sp-io = { workspace = true } sp-keyring = { workspace = true, default-features = true } sp-runtime = { workspace = true } +sp-std = { workspace = true } sp-tracing = { workspace = true, default-features = true } # Cumulus @@ -49,8 +50,6 @@ bp-polkadot-core = { workspace = true } bp-relayers = { workspace = true } bp-runtime = { workspace = true } bp-test-utils = { workspace = true } -bp-xcm-bridge-hub = { workspace = true } -bridge-runtime-common = { workspace = true } pallet-bridge-grandpa = { workspace = true } pallet-bridge-messages = { features = ["test-helpers"], workspace = true } pallet-bridge-parachains = { workspace = true } @@ -68,8 +67,6 @@ std = [ "bp-relayers/std", "bp-runtime/std", "bp-test-utils/std", - "bp-xcm-bridge-hub/std", - "bridge-runtime-common/std", "codec/std", "cumulus-pallet-parachain-system/std", "cumulus-pallet-xcmp-queue/std", @@ -90,6 +87,7 @@ std = [ "sp-core/std", "sp-io/std", "sp-runtime/std", + "sp-std/std", "xcm-builder/std", "xcm-executor/std", "xcm/std", diff --git a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/lib.rs index bc28df0eb829cc02ba455b363ce6bea51d702950..240aac6c406350b0f1fbb59ddd3e9315af677099 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/lib.rs @@ -24,7 +24,7 @@ extern crate alloc; pub use bp_test_utils::test_header; pub use parachains_runtimes_test_utils::*; use sp_runtime::Perbill; -pub use test_cases::helpers::{ +pub use test_cases::helpers::for_pallet_xcm_bridge_hub::{ ensure_opened_bridge, open_bridge_with_extrinsic, open_bridge_with_storage, }; diff --git a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/from_grandpa_chain.rs b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/from_grandpa_chain.rs index 358c184c815d9953a0754a1ecb419b892cb12c0b..4a7975b2d9f288b1416e2d678a6af4130ecdfee2 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/from_grandpa_chain.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/from_grandpa_chain.rs @@ -20,13 +20,13 @@ use crate::{ test_cases::{bridges_prelude::*, helpers, run_test}, test_data, + test_data::XcmAsPlainPayload, }; use alloc::{boxed::Box, vec}; use bp_header_chain::ChainWithGrandpa; use bp_messages::UnrewardedRelayersState; use bp_relayers::{RewardsAccountOwner, RewardsAccountParams}; -use bp_xcm_bridge_hub::XcmAsPlainPayload; use frame_support::traits::{OnFinalize, OnInitialize}; use frame_system::pallet_prelude::BlockNumberFor; use pallet_bridge_messages::{BridgedChainOf, LaneIdOf, ThisChainOf}; diff --git a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/from_parachain.rs b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/from_parachain.rs index d8fff55b4b50a052afe47b3a4bfaf8a55f26b09e..7e87d703888a374979e174b005d77bda80eca828 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/from_parachain.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/from_parachain.rs @@ -20,6 +20,7 @@ use crate::{ test_cases::{bridges_prelude::*, helpers, run_test}, test_data, + test_data::XcmAsPlainPayload, }; use alloc::{boxed::Box, vec}; @@ -28,7 +29,6 @@ use bp_messages::UnrewardedRelayersState; use bp_polkadot_core::parachains::ParaHash; use bp_relayers::{RewardsAccountOwner, RewardsAccountParams}; use bp_runtime::{Chain, Parachain}; -use bp_xcm_bridge_hub::XcmAsPlainPayload; use frame_support::traits::{OnFinalize, OnInitialize}; use frame_system::pallet_prelude::BlockNumberFor; use pallet_bridge_messages::{BridgedChainOf, LaneIdOf, ThisChainOf}; diff --git a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/helpers.rs b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/helpers.rs index a99bda5bfdf476f679e0f47f90d7d5498071d629..505babdb64155601eb65e032139c5f463def4c7a 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/helpers.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/helpers.rs @@ -23,7 +23,6 @@ use bp_messages::MessageNonce; use bp_polkadot_core::parachains::{ParaHash, ParaId}; use bp_relayers::RewardsAccountParams; use bp_runtime::Chain; -use bp_xcm_bridge_hub::BridgeLocations; use codec::Decode; use core::marker::PhantomData; use frame_support::{ @@ -388,203 +387,210 @@ fn execute_and_verify_calls<Runtime: frame_system::Config>( } } -/// Helper function to open the bridge/lane for `source` and `destination` while ensuring all -/// required balances are placed into the SA of the source. -pub fn ensure_opened_bridge< - Runtime, - XcmOverBridgePalletInstance, - LocationToAccountId, - TokenLocation> -(source: Location, destination: InteriorLocation, is_paid_xcm_execution: bool, bridge_opener: impl Fn(BridgeLocations, Option<Asset>)) -> (BridgeLocations, pallet_xcm_bridge_hub::LaneIdOf<Runtime, XcmOverBridgePalletInstance>) -where - Runtime: BasicParachainRuntime + BridgeXcmOverBridgeConfig<XcmOverBridgePalletInstance>, - XcmOverBridgePalletInstance: 'static, - <Runtime as frame_system::Config>::RuntimeCall: GetDispatchInfo + From<BridgeXcmOverBridgeCall<Runtime, XcmOverBridgePalletInstance>>, - <Runtime as pallet_balances::Config>::Balance: From<<<Runtime as pallet_bridge_messages::Config<<Runtime as pallet_xcm_bridge_hub::Config<XcmOverBridgePalletInstance>>::BridgeMessagesPalletInstance>>::ThisChain as bp_runtime::Chain>::Balance>, - <Runtime as pallet_balances::Config>::Balance: From<u128>, - LocationToAccountId: ConvertLocation<AccountIdOf<Runtime>>, -TokenLocation: Get<Location>{ - // construct expected bridge configuration - let locations = - pallet_xcm_bridge_hub::Pallet::<Runtime, XcmOverBridgePalletInstance>::bridge_locations( - source.clone().into(), - destination.clone().into(), +pub(crate) mod for_pallet_xcm_bridge_hub { + use super::{super::for_pallet_xcm_bridge_hub::*, *}; + + /// Helper function to open the bridge/lane for `source` and `destination` while ensuring all + /// required balances are placed into the SA of the source. + pub fn ensure_opened_bridge< + Runtime, + XcmOverBridgePalletInstance, + LocationToAccountId, + TokenLocation> + (source: Location, destination: InteriorLocation, is_paid_xcm_execution: bool, bridge_opener: impl Fn(pallet_xcm_bridge_hub::BridgeLocations, Option<Asset>)) -> (pallet_xcm_bridge_hub::BridgeLocations, pallet_xcm_bridge_hub::LaneIdOf<Runtime, XcmOverBridgePalletInstance>) + where + Runtime: BasicParachainRuntime + BridgeXcmOverBridgeConfig<XcmOverBridgePalletInstance>, + XcmOverBridgePalletInstance: 'static, + <Runtime as frame_system::Config>::RuntimeCall: GetDispatchInfo + From<BridgeXcmOverBridgeCall<Runtime, XcmOverBridgePalletInstance>>, + <Runtime as pallet_balances::Config>::Balance: From<<<Runtime as pallet_bridge_messages::Config<<Runtime as pallet_xcm_bridge_hub::Config<XcmOverBridgePalletInstance>>::BridgeMessagesPalletInstance>>::ThisChain as bp_runtime::Chain>::Balance>, + <Runtime as pallet_balances::Config>::Balance: From<u128>, + LocationToAccountId: ConvertLocation<AccountIdOf<Runtime>>, + TokenLocation: Get<Location> + { + // construct expected bridge configuration + let locations = + pallet_xcm_bridge_hub::Pallet::<Runtime, XcmOverBridgePalletInstance>::bridge_locations( + source.clone().into(), + destination.clone().into(), + ) + .expect("valid bridge locations"); + assert!(pallet_xcm_bridge_hub::Bridges::<Runtime, XcmOverBridgePalletInstance>::get( + locations.bridge_id() ) - .expect("valid bridge locations"); - assert!(pallet_xcm_bridge_hub::Bridges::<Runtime, XcmOverBridgePalletInstance>::get( - locations.bridge_id() - ) - .is_none()); + .is_none()); + + // SA of source location needs to have some required balance + if !<Runtime as pallet_xcm_bridge_hub::Config<XcmOverBridgePalletInstance>>::AllowWithoutBridgeDeposit::contains(&source) { + // required balance: ED + fee + BridgeDeposit + let bridge_deposit = + <Runtime as pallet_xcm_bridge_hub::Config<XcmOverBridgePalletInstance>>::BridgeDeposit::get(); + let balance_needed = <Runtime as pallet_balances::Config>::ExistentialDeposit::get() + bridge_deposit.into(); + + let source_account_id = LocationToAccountId::convert_location(&source).expect("valid location"); + let _ = <pallet_balances::Pallet<Runtime>>::mint_into(&source_account_id, balance_needed) + .expect("mint_into passes"); + }; + + let maybe_paid_execution = if is_paid_xcm_execution { + // random high enough value for `BuyExecution` fees + let buy_execution_fee_amount = 5_000_000_000_000_u128; + let buy_execution_fee = (TokenLocation::get(), buy_execution_fee_amount).into(); + + let balance_needed = <Runtime as pallet_balances::Config>::ExistentialDeposit::get() + + buy_execution_fee_amount.into(); + let source_account_id = + LocationToAccountId::convert_location(&source).expect("valid location"); + let _ = + <pallet_balances::Pallet<Runtime>>::mint_into(&source_account_id, balance_needed) + .expect("mint_into passes"); + Some(buy_execution_fee) + } else { + None + }; + + // call the bridge opener + bridge_opener(*locations.clone(), maybe_paid_execution); + + // check opened bridge + let bridge = pallet_xcm_bridge_hub::Bridges::<Runtime, XcmOverBridgePalletInstance>::get( + locations.bridge_id(), + ) + .expect("opened bridge"); - // SA of source location needs to have some required balance - if !<Runtime as pallet_xcm_bridge_hub::Config<XcmOverBridgePalletInstance>>::AllowWithoutBridgeDeposit::contains(&source) { - // required balance: ED + fee + BridgeDeposit - let bridge_deposit = - <Runtime as pallet_xcm_bridge_hub::Config<XcmOverBridgePalletInstance>>::BridgeDeposit::get( - ); - let balance_needed = <Runtime as pallet_balances::Config>::ExistentialDeposit::get() + bridge_deposit.into(); - - let source_account_id = LocationToAccountId::convert_location(&source).expect("valid location"); - let _ = <pallet_balances::Pallet<Runtime>>::mint_into(&source_account_id, balance_needed) - .expect("mint_into passes"); - }; - - let maybe_paid_execution = if is_paid_xcm_execution { - // random high enough value for `BuyExecution` fees - let buy_execution_fee_amount = 5_000_000_000_000_u128; - let buy_execution_fee = (TokenLocation::get(), buy_execution_fee_amount).into(); - - let balance_needed = <Runtime as pallet_balances::Config>::ExistentialDeposit::get() + - buy_execution_fee_amount.into(); - let source_account_id = - LocationToAccountId::convert_location(&source).expect("valid location"); - let _ = <pallet_balances::Pallet<Runtime>>::mint_into(&source_account_id, balance_needed) - .expect("mint_into passes"); - Some(buy_execution_fee) - } else { - None - }; - - // call the bridge opener - bridge_opener(*locations.clone(), maybe_paid_execution); - - // check opened bridge - let bridge = pallet_xcm_bridge_hub::Bridges::<Runtime, XcmOverBridgePalletInstance>::get( - locations.bridge_id(), - ) - .expect("opened bridge"); + // check state + assert_ok!( + pallet_xcm_bridge_hub::Pallet::<Runtime, XcmOverBridgePalletInstance>::do_try_state() + ); - // check state - assert_ok!( - pallet_xcm_bridge_hub::Pallet::<Runtime, XcmOverBridgePalletInstance>::do_try_state() - ); + // return locations + (*locations, bridge.lane_id) + } - // return locations - (*locations, bridge.lane_id) -} + /// Utility for opening bridge with dedicated `pallet_xcm_bridge_hub`'s extrinsic. + pub fn open_bridge_with_extrinsic<Runtime, XcmOverBridgePalletInstance>( + (origin, origin_kind): (Location, OriginKind), + bridge_destination_universal_location: InteriorLocation, + maybe_paid_execution: Option<Asset>, + ) where + Runtime: frame_system::Config + + pallet_xcm_bridge_hub::Config<XcmOverBridgePalletInstance> + + cumulus_pallet_parachain_system::Config + + pallet_xcm::Config, + XcmOverBridgePalletInstance: 'static, + <Runtime as frame_system::Config>::RuntimeCall: + GetDispatchInfo + From<BridgeXcmOverBridgeCall<Runtime, XcmOverBridgePalletInstance>>, + { + // open bridge with `Transact` call + let open_bridge_call = RuntimeCallOf::<Runtime>::from(BridgeXcmOverBridgeCall::< + Runtime, + XcmOverBridgePalletInstance, + >::open_bridge { + bridge_destination_universal_location: Box::new( + bridge_destination_universal_location.clone().into(), + ), + }); + + // execute XCM as source origin would do with `Transact -> Origin::Xcm` + assert_ok!(RuntimeHelper::<Runtime>::execute_as_origin( + (origin, origin_kind), + open_bridge_call, + maybe_paid_execution + ) + .ensure_complete()); + } -/// Utility for opening bridge with dedicated `pallet_xcm_bridge_hub`'s extrinsic. -pub fn open_bridge_with_extrinsic<Runtime, XcmOverBridgePalletInstance>( - (origin, origin_kind): (Location, OriginKind), - bridge_destination_universal_location: InteriorLocation, - maybe_paid_execution: Option<Asset>, -) where - Runtime: frame_system::Config - + pallet_xcm_bridge_hub::Config<XcmOverBridgePalletInstance> - + cumulus_pallet_parachain_system::Config - + pallet_xcm::Config, - XcmOverBridgePalletInstance: 'static, - <Runtime as frame_system::Config>::RuntimeCall: - GetDispatchInfo + From<BridgeXcmOverBridgeCall<Runtime, XcmOverBridgePalletInstance>>, -{ - // open bridge with `Transact` call - let open_bridge_call = RuntimeCallOf::<Runtime>::from(BridgeXcmOverBridgeCall::< - Runtime, - XcmOverBridgePalletInstance, - >::open_bridge { - bridge_destination_universal_location: Box::new( - bridge_destination_universal_location.clone().into(), - ), - }); - - // execute XCM as source origin would do with `Transact -> Origin::Xcm` - assert_ok!(RuntimeHelper::<Runtime>::execute_as_origin( - (origin, origin_kind), - open_bridge_call, - maybe_paid_execution - ) - .ensure_complete()); -} + /// Utility for opening bridge directly inserting data to the `pallet_xcm_bridge_hub`'s storage + /// (used only for legacy purposes). + pub fn open_bridge_with_storage<Runtime, XcmOverBridgePalletInstance>( + locations: pallet_xcm_bridge_hub::BridgeLocations, + lane_id: pallet_xcm_bridge_hub::LaneIdOf<Runtime, XcmOverBridgePalletInstance>, + ) where + Runtime: pallet_xcm_bridge_hub::Config<XcmOverBridgePalletInstance>, + XcmOverBridgePalletInstance: 'static, + { + // insert bridge data directly to the storage + assert_ok!( + pallet_xcm_bridge_hub::Pallet::<Runtime, XcmOverBridgePalletInstance>::do_open_bridge( + Box::new(locations), + lane_id, + true + ) + ); + } -/// Utility for opening bridge directly inserting data to the storage (used only for legacy -/// purposes). -pub fn open_bridge_with_storage<Runtime, XcmOverBridgePalletInstance>( - locations: BridgeLocations, - lane_id: pallet_xcm_bridge_hub::LaneIdOf<Runtime, XcmOverBridgePalletInstance>, -) where - Runtime: pallet_xcm_bridge_hub::Config<XcmOverBridgePalletInstance>, - XcmOverBridgePalletInstance: 'static, -{ - // insert bridge data directly to the storage - assert_ok!( - pallet_xcm_bridge_hub::Pallet::<Runtime, XcmOverBridgePalletInstance>::do_open_bridge( - Box::new(locations), - lane_id, - true + /// Helper function to close the bridge/lane for `source` and `destination`. + pub fn close_bridge<Runtime, XcmOverBridgePalletInstance, LocationToAccountId, TokenLocation>( + expected_source: Location, + bridge_destination_universal_location: InteriorLocation, + (origin, origin_kind): (Location, OriginKind), + is_paid_xcm_execution: bool + ) where + Runtime: BasicParachainRuntime + BridgeXcmOverBridgeConfig<XcmOverBridgePalletInstance>, + XcmOverBridgePalletInstance: 'static, + <Runtime as frame_system::Config>::RuntimeCall: GetDispatchInfo + From<BridgeXcmOverBridgeCall<Runtime, XcmOverBridgePalletInstance>>, + <Runtime as pallet_balances::Config>::Balance: From<<<Runtime as pallet_bridge_messages::Config<<Runtime as pallet_xcm_bridge_hub::Config<XcmOverBridgePalletInstance>>::BridgeMessagesPalletInstance>>::ThisChain as bp_runtime::Chain>::Balance>, + <Runtime as pallet_balances::Config>::Balance: From<u128>, + LocationToAccountId: ConvertLocation<AccountIdOf<Runtime>>, + TokenLocation: Get<Location> + { + // construct expected bridge configuration + let locations = + pallet_xcm_bridge_hub::Pallet::<Runtime, XcmOverBridgePalletInstance>::bridge_locations( + expected_source.clone().into(), + bridge_destination_universal_location.clone().into(), + ) + .expect("valid bridge locations"); + assert!(pallet_xcm_bridge_hub::Bridges::<Runtime, XcmOverBridgePalletInstance>::get( + locations.bridge_id() ) - ); -} + .is_some()); -/// Helper function to close the bridge/lane for `source` and `destination`. -pub fn close_bridge<Runtime, XcmOverBridgePalletInstance, LocationToAccountId, TokenLocation>( - expected_source: Location, - bridge_destination_universal_location: InteriorLocation, - (origin, origin_kind): (Location, OriginKind), - is_paid_xcm_execution: bool -) where - Runtime: BasicParachainRuntime + BridgeXcmOverBridgeConfig<XcmOverBridgePalletInstance>, - XcmOverBridgePalletInstance: 'static, - <Runtime as frame_system::Config>::RuntimeCall: GetDispatchInfo + From<BridgeXcmOverBridgeCall<Runtime, XcmOverBridgePalletInstance>>, - <Runtime as pallet_balances::Config>::Balance: From<<<Runtime as pallet_bridge_messages::Config<<Runtime as pallet_xcm_bridge_hub::Config<XcmOverBridgePalletInstance>>::BridgeMessagesPalletInstance>>::ThisChain as bp_runtime::Chain>::Balance>, - <Runtime as pallet_balances::Config>::Balance: From<u128>, - LocationToAccountId: ConvertLocation<AccountIdOf<Runtime>>, -TokenLocation: Get<Location>{ - // construct expected bridge configuration - let locations = - pallet_xcm_bridge_hub::Pallet::<Runtime, XcmOverBridgePalletInstance>::bridge_locations( - expected_source.clone().into(), - bridge_destination_universal_location.clone().into(), + // required balance: ED + fee + BridgeDeposit + let maybe_paid_execution = if is_paid_xcm_execution { + // random high enough value for `BuyExecution` fees + let buy_execution_fee_amount = 2_500_000_000_000_u128; + let buy_execution_fee = (TokenLocation::get(), buy_execution_fee_amount).into(); + + let balance_needed = <Runtime as pallet_balances::Config>::ExistentialDeposit::get() + + buy_execution_fee_amount.into(); + let source_account_id = + LocationToAccountId::convert_location(&expected_source).expect("valid location"); + let _ = + <pallet_balances::Pallet<Runtime>>::mint_into(&source_account_id, balance_needed) + .expect("mint_into passes"); + Some(buy_execution_fee) + } else { + None + }; + + // close bridge with `Transact` call + let close_bridge_call = RuntimeCallOf::<Runtime>::from(BridgeXcmOverBridgeCall::< + Runtime, + XcmOverBridgePalletInstance, + >::close_bridge { + bridge_destination_universal_location: Box::new( + bridge_destination_universal_location.into(), + ), + may_prune_messages: 16, + }); + + // execute XCM as source origin would do with `Transact -> Origin::Xcm` + assert_ok!(RuntimeHelper::<Runtime>::execute_as_origin( + (origin, origin_kind), + close_bridge_call, + maybe_paid_execution ) - .expect("valid bridge locations"); - assert!(pallet_xcm_bridge_hub::Bridges::<Runtime, XcmOverBridgePalletInstance>::get( - locations.bridge_id() - ) - .is_some()); - - // required balance: ED + fee + BridgeDeposit - let maybe_paid_execution = if is_paid_xcm_execution { - // random high enough value for `BuyExecution` fees - let buy_execution_fee_amount = 2_500_000_000_000_u128; - let buy_execution_fee = (TokenLocation::get(), buy_execution_fee_amount).into(); - - let balance_needed = <Runtime as pallet_balances::Config>::ExistentialDeposit::get() + - buy_execution_fee_amount.into(); - let source_account_id = - LocationToAccountId::convert_location(&expected_source).expect("valid location"); - let _ = <pallet_balances::Pallet<Runtime>>::mint_into(&source_account_id, balance_needed) - .expect("mint_into passes"); - Some(buy_execution_fee) - } else { - None - }; - - // close bridge with `Transact` call - let close_bridge_call = RuntimeCallOf::<Runtime>::from(BridgeXcmOverBridgeCall::< - Runtime, - XcmOverBridgePalletInstance, - >::close_bridge { - bridge_destination_universal_location: Box::new( - bridge_destination_universal_location.into(), - ), - may_prune_messages: 16, - }); - - // execute XCM as source origin would do with `Transact -> Origin::Xcm` - assert_ok!(RuntimeHelper::<Runtime>::execute_as_origin( - (origin, origin_kind), - close_bridge_call, - maybe_paid_execution - ) - .ensure_complete()); + .ensure_complete()); - // bridge is closed - assert!(pallet_xcm_bridge_hub::Bridges::<Runtime, XcmOverBridgePalletInstance>::get( - locations.bridge_id() - ) - .is_none()); + // bridge is closed + assert!(pallet_xcm_bridge_hub::Bridges::<Runtime, XcmOverBridgePalletInstance>::get( + locations.bridge_id() + ) + .is_none()); - // check state - assert_ok!( - pallet_xcm_bridge_hub::Pallet::<Runtime, XcmOverBridgePalletInstance>::do_try_state() - ); + // check state + assert_ok!( + pallet_xcm_bridge_hub::Pallet::<Runtime, XcmOverBridgePalletInstance>::do_try_state() + ); + } } diff --git a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/mod.rs b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/mod.rs index f96d0bf405b9cdf60cef53f9b2b858d4805b4981..fa0229ce06881a2193ac36d8e05240dc2e149744 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/mod.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/mod.rs @@ -32,7 +32,6 @@ use bp_messages::{ LaneState, MessageKey, MessagesOperatingMode, OutboundLaneData, }; use bp_runtime::BasicOperatingMode; -use bp_xcm_bridge_hub::{Bridge, BridgeState, XcmAsPlainPayload}; use codec::Encode; use frame_support::{ assert_ok, @@ -63,12 +62,11 @@ pub(crate) mod bridges_prelude { pub use pallet_bridge_parachains::{ Call as BridgeParachainsCall, Config as BridgeParachainsConfig, }; - pub use pallet_xcm_bridge_hub::{ - Call as BridgeXcmOverBridgeCall, Config as BridgeXcmOverBridgeConfig, LanesManagerOf, - XcmBlobMessageDispatchResult, - }; } +// Re-export test-case +pub use for_pallet_xcm_bridge_hub::open_and_close_bridge_works; + // Re-export test_case from assets pub use asset_test_utils::include_teleports_for_native_asset_works; use pallet_bridge_messages::LaneIdOf; @@ -77,7 +75,6 @@ pub type RuntimeHelper<Runtime, AllPalletsWithoutSystem = ()> = parachains_runtimes_test_utils::RuntimeHelper<Runtime, AllPalletsWithoutSystem>; // Re-export test_case from `parachains-runtimes-test-utils` -use crate::test_cases::helpers::open_bridge_with_extrinsic; pub use parachains_runtimes_test_utils::test_cases::{ change_storage_constant_by_governance_works, set_storage_keys_by_governance_works, }; @@ -439,7 +436,7 @@ pub fn message_dispatch_routing_works< ) where Runtime: BasicParachainRuntime + cumulus_pallet_xcmp_queue::Config - + BridgeMessagesConfig<MessagesPalletInstance, InboundPayload = XcmAsPlainPayload>, + + BridgeMessagesConfig<MessagesPalletInstance, InboundPayload = test_data::XcmAsPlainPayload>, AllPalletsWithoutSystem: OnInitialize<BlockNumberFor<Runtime>> + OnFinalize<BlockNumberFor<Runtime>>, AccountIdOf<Runtime>: From<AccountId32> @@ -459,9 +456,15 @@ pub fn message_dispatch_routing_works< Location::new(C::get(), [GlobalConsensus(N::get())]) } } - assert_ne!(runtime_para_id, sibling_parachain_id); + #[derive(Debug)] + enum XcmBlobMessageDispatchResult { + Dispatched, + #[allow(dead_code)] + NotDispatched(Option<DispatchBlobError>), + } + run_test::<Runtime, _>(collator_session_key, runtime_para_id, vec![], || { prepare_configuration(); @@ -650,139 +653,150 @@ where estimated_fee.into() } -/// Test-case makes sure that `Runtime` can open/close bridges. -pub fn open_and_close_bridge_works<Runtime, XcmOverBridgePalletInstance, LocationToAccountId, TokenLocation>( - collator_session_key: CollatorSessionKeys<Runtime>, - runtime_para_id: u32, - expected_source: Location, - destination: InteriorLocation, - origin_with_origin_kind: (Location, OriginKind), - is_paid_xcm_execution: bool, -) where - Runtime: BasicParachainRuntime + BridgeXcmOverBridgeConfig<XcmOverBridgePalletInstance>, - XcmOverBridgePalletInstance: 'static, - <Runtime as frame_system::Config>::RuntimeCall: GetDispatchInfo + From<BridgeXcmOverBridgeCall<Runtime, XcmOverBridgePalletInstance>>, - <Runtime as pallet_balances::Config>::Balance: From<<<Runtime as pallet_bridge_messages::Config<<Runtime as pallet_xcm_bridge_hub::Config<XcmOverBridgePalletInstance>>::BridgeMessagesPalletInstance>>::ThisChain as bp_runtime::Chain>::Balance>, - <Runtime as pallet_balances::Config>::Balance: From<u128>, - <<Runtime as pallet_bridge_messages::Config<<Runtime as pallet_xcm_bridge_hub::Config<XcmOverBridgePalletInstance>>::BridgeMessagesPalletInstance>>::ThisChain as bp_runtime::Chain>::AccountId: From<<Runtime as frame_system::Config>::AccountId>, - LocationToAccountId: ConvertLocation<AccountIdOf<Runtime>>, - TokenLocation: Get<Location>, -{ - run_test::<Runtime, _>(collator_session_key, runtime_para_id, vec![], || { - // construct expected bridge configuration - let locations = pallet_xcm_bridge_hub::Pallet::<Runtime, XcmOverBridgePalletInstance>::bridge_locations( - expected_source.clone().into(), - destination.clone().into(), - ).expect("valid bridge locations"); - let expected_lane_id = - locations.calculate_lane_id(xcm::latest::VERSION).expect("valid laneId"); - let lanes_manager = LanesManagerOf::<Runtime, XcmOverBridgePalletInstance>::new(); - - let expected_deposit = if <Runtime as pallet_xcm_bridge_hub::Config< - XcmOverBridgePalletInstance, - >>::AllowWithoutBridgeDeposit::contains( - locations.bridge_origin_relative_location() - ) { - Zero::zero() - } else { - <Runtime as pallet_xcm_bridge_hub::Config< +pub(crate) mod for_pallet_xcm_bridge_hub { + use super::*; + use crate::test_cases::helpers::for_pallet_xcm_bridge_hub::{ + close_bridge, ensure_opened_bridge, open_bridge_with_extrinsic, + }; + pub(crate) use pallet_xcm_bridge_hub::{ + Bridge, BridgeState, Call as BridgeXcmOverBridgeCall, Config as BridgeXcmOverBridgeConfig, + LanesManagerOf, + }; + + /// Test-case makes sure that `Runtime` can open/close bridges. + pub fn open_and_close_bridge_works<Runtime, XcmOverBridgePalletInstance, LocationToAccountId, TokenLocation>( + collator_session_key: CollatorSessionKeys<Runtime>, + runtime_para_id: u32, + expected_source: Location, + destination: InteriorLocation, + origin_with_origin_kind: (Location, OriginKind), + is_paid_xcm_execution: bool, + ) where + Runtime: BasicParachainRuntime + BridgeXcmOverBridgeConfig<XcmOverBridgePalletInstance>, + XcmOverBridgePalletInstance: 'static, + <Runtime as frame_system::Config>::RuntimeCall: GetDispatchInfo + From<BridgeXcmOverBridgeCall<Runtime, XcmOverBridgePalletInstance>>, + <Runtime as pallet_balances::Config>::Balance: From<<<Runtime as pallet_bridge_messages::Config<<Runtime as pallet_xcm_bridge_hub::Config<XcmOverBridgePalletInstance>>::BridgeMessagesPalletInstance>>::ThisChain as bp_runtime::Chain>::Balance>, + <Runtime as pallet_balances::Config>::Balance: From<u128>, + <<Runtime as pallet_bridge_messages::Config<<Runtime as pallet_xcm_bridge_hub::Config<XcmOverBridgePalletInstance>>::BridgeMessagesPalletInstance>>::ThisChain as bp_runtime::Chain>::AccountId: From<<Runtime as frame_system::Config>::AccountId>, + LocationToAccountId: ConvertLocation<AccountIdOf<Runtime>>, + TokenLocation: Get<Location>, + { + run_test::<Runtime, _>(collator_session_key, runtime_para_id, vec![], || { + // construct expected bridge configuration + let locations = pallet_xcm_bridge_hub::Pallet::<Runtime, XcmOverBridgePalletInstance>::bridge_locations( + expected_source.clone().into(), + destination.clone().into(), + ).expect("valid bridge locations"); + let expected_lane_id = + locations.calculate_lane_id(xcm::latest::VERSION).expect("valid laneId"); + let lanes_manager = LanesManagerOf::<Runtime, XcmOverBridgePalletInstance>::new(); + + let expected_deposit = if <Runtime as pallet_xcm_bridge_hub::Config< XcmOverBridgePalletInstance, - >>::BridgeDeposit::get() - }; + >>::AllowWithoutBridgeDeposit::contains( + locations.bridge_origin_relative_location() + ) { + Zero::zero() + } else { + <Runtime as pallet_xcm_bridge_hub::Config< + XcmOverBridgePalletInstance, + >>::BridgeDeposit::get() + }; - // check bridge/lane DOES not exist - assert_eq!( - pallet_xcm_bridge_hub::Bridges::<Runtime, XcmOverBridgePalletInstance>::get( - locations.bridge_id() - ), - None - ); - assert_eq!( - lanes_manager.active_inbound_lane(expected_lane_id).map(drop), - Err(LanesManagerError::UnknownInboundLane) - ); - assert_eq!( - lanes_manager.active_outbound_lane(expected_lane_id).map(drop), - Err(LanesManagerError::UnknownOutboundLane) - ); + // check bridge/lane DOES not exist + assert_eq!( + pallet_xcm_bridge_hub::Bridges::<Runtime, XcmOverBridgePalletInstance>::get( + locations.bridge_id() + ), + None + ); + assert_eq!( + lanes_manager.active_inbound_lane(expected_lane_id).map(drop), + Err(LanesManagerError::UnknownInboundLane) + ); + assert_eq!( + lanes_manager.active_outbound_lane(expected_lane_id).map(drop), + Err(LanesManagerError::UnknownOutboundLane) + ); - // open bridge with Transact call - assert_eq!( - helpers::ensure_opened_bridge::< - Runtime, - XcmOverBridgePalletInstance, - LocationToAccountId, - TokenLocation, - >( - expected_source.clone(), - destination.clone(), - is_paid_xcm_execution, - |locations, maybe_paid_execution| open_bridge_with_extrinsic::< + // open bridge with Transact call + assert_eq!( + ensure_opened_bridge::< Runtime, XcmOverBridgePalletInstance, + LocationToAccountId, + TokenLocation, >( - origin_with_origin_kind.clone(), - locations.bridge_destination_universal_location().clone(), - maybe_paid_execution + expected_source.clone(), + destination.clone(), + is_paid_xcm_execution, + |locations, maybe_paid_execution| open_bridge_with_extrinsic::< + Runtime, + XcmOverBridgePalletInstance, + >( + origin_with_origin_kind.clone(), + locations.bridge_destination_universal_location().clone(), + maybe_paid_execution + ) ) - ) - .0 - .bridge_id(), - locations.bridge_id() - ); - - // check bridge/lane DOES exist - assert_eq!( - pallet_xcm_bridge_hub::Bridges::<Runtime, XcmOverBridgePalletInstance>::get( + .0 + .bridge_id(), locations.bridge_id() - ), - Some(Bridge { - bridge_origin_relative_location: Box::new(expected_source.clone().into()), - bridge_origin_universal_location: Box::new( - locations.bridge_origin_universal_location().clone().into() - ), - bridge_destination_universal_location: Box::new( - locations.bridge_destination_universal_location().clone().into() + ); + + // check bridge/lane DOES exist + assert_eq!( + pallet_xcm_bridge_hub::Bridges::<Runtime, XcmOverBridgePalletInstance>::get( + locations.bridge_id() ), - state: BridgeState::Opened, - bridge_owner_account: LocationToAccountId::convert_location(&expected_source) - .expect("valid location") - .into(), - deposit: expected_deposit, - lane_id: expected_lane_id - }) - ); - assert_eq!( - lanes_manager.active_inbound_lane(expected_lane_id).map(|lane| lane.state()), - Ok(LaneState::Opened) - ); - assert_eq!( - lanes_manager.active_outbound_lane(expected_lane_id).map(|lane| lane.state()), - Ok(LaneState::Opened) - ); + Some(Bridge { + bridge_origin_relative_location: Box::new(expected_source.clone().into()), + bridge_origin_universal_location: Box::new( + locations.bridge_origin_universal_location().clone().into() + ), + bridge_destination_universal_location: Box::new( + locations.bridge_destination_universal_location().clone().into() + ), + state: BridgeState::Opened, + bridge_owner_account: LocationToAccountId::convert_location(&expected_source) + .expect("valid location") + .into(), + deposit: expected_deposit, + lane_id: expected_lane_id, + }) + ); + assert_eq!( + lanes_manager.active_inbound_lane(expected_lane_id).map(|lane| lane.state()), + Ok(LaneState::Opened) + ); + assert_eq!( + lanes_manager.active_outbound_lane(expected_lane_id).map(|lane| lane.state()), + Ok(LaneState::Opened) + ); - // close bridge with Transact call - helpers::close_bridge::< - Runtime, - XcmOverBridgePalletInstance, - LocationToAccountId, - TokenLocation, - >(expected_source, destination, origin_with_origin_kind, is_paid_xcm_execution); + // close bridge with Transact call + close_bridge::<Runtime, XcmOverBridgePalletInstance, LocationToAccountId, TokenLocation>( + expected_source, + destination, + origin_with_origin_kind, + is_paid_xcm_execution, + ); - // check bridge/lane DOES not exist - assert_eq!( - pallet_xcm_bridge_hub::Bridges::<Runtime, XcmOverBridgePalletInstance>::get( - locations.bridge_id() - ), - None - ); - assert_eq!( - lanes_manager.active_inbound_lane(expected_lane_id).map(drop), - Err(LanesManagerError::UnknownInboundLane) - ); - assert_eq!( - lanes_manager.active_outbound_lane(expected_lane_id).map(drop), - Err(LanesManagerError::UnknownOutboundLane) - ); - }); + // check bridge/lane DOES not exist + assert_eq!( + pallet_xcm_bridge_hub::Bridges::<Runtime, XcmOverBridgePalletInstance>::get( + locations.bridge_id() + ), + None + ); + assert_eq!( + lanes_manager.active_inbound_lane(expected_lane_id).map(drop), + Err(LanesManagerError::UnknownInboundLane) + ); + assert_eq!( + lanes_manager.active_outbound_lane(expected_lane_id).map(drop), + Err(LanesManagerError::UnknownOutboundLane) + ); + }); + } } diff --git a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_data/from_grandpa_chain.rs b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_data/from_grandpa_chain.rs index 7461085330f27691b4da39e425aebcf64046641d..37605350b8e643a2de91b88dbfcc3a44d9e2d6da 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_data/from_grandpa_chain.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_data/from_grandpa_chain.rs @@ -16,7 +16,7 @@ //! Generating test data for bridges with remote GRANDPA chains. -use crate::test_data::prepare_inbound_xcm; +use crate::test_data::{prepare_inbound_xcm, XcmAsPlainPayload}; use bp_messages::{ source_chain::FromBridgedChainMessagesDeliveryProof, @@ -25,7 +25,6 @@ use bp_messages::{ }; use bp_runtime::{AccountIdOf, BlockNumberOf, Chain, HeaderOf, UnverifiedStorageProofParams}; use bp_test_utils::make_default_justification; -use bp_xcm_bridge_hub::XcmAsPlainPayload; use codec::Encode; use pallet_bridge_grandpa::{BridgedChain, BridgedHeader}; use sp_runtime::traits::Header as HeaderT; diff --git a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_data/from_parachain.rs b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_data/from_parachain.rs index a6659b8241dfd50aedbfe14ac2672756fa0a03af..4d91c8215880037cfb39b4c0fff00046b0e29b9b 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_data/from_parachain.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_data/from_parachain.rs @@ -16,7 +16,10 @@ //! Generating test data for bridges with remote parachains. -use super::{from_grandpa_chain::make_complex_bridged_grandpa_header_proof, prepare_inbound_xcm}; +use super::{ + from_grandpa_chain::make_complex_bridged_grandpa_header_proof, prepare_inbound_xcm, + XcmAsPlainPayload, +}; use bp_messages::{ source_chain::FromBridgedChainMessagesDeliveryProof, @@ -28,7 +31,6 @@ use bp_runtime::{ AccountIdOf, BlockNumberOf, Chain, HeaderOf, Parachain, UnverifiedStorageProofParams, }; use bp_test_utils::prepare_parachain_heads_proof; -use bp_xcm_bridge_hub::XcmAsPlainPayload; use codec::Encode; use pallet_bridge_grandpa::BridgedHeader; use sp_runtime::traits::Header as HeaderT; diff --git a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_data/mod.rs b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_data/mod.rs index c34188af506896d9fb4e18781b09d804077c3941..cef3c84b8178568e7a0ddb4939f76ca066c52655 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_data/mod.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_data/mod.rs @@ -35,6 +35,8 @@ use xcm::GetVersion; use xcm_builder::{BridgeMessage, HaulBlob, HaulBlobError, HaulBlobExporter}; use xcm_executor::traits::{validate_export, ExportXcm}; +pub(crate) type XcmAsPlainPayload = sp_std::vec::Vec<u8>; + pub fn prepare_inbound_xcm(xcm_message: Xcm<()>, destination: InteriorLocation) -> Vec<u8> { let location = xcm::VersionedInteriorLocation::from(destination); let xcm = xcm::VersionedXcm::<()>::from(xcm_message); diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/Cargo.toml b/cumulus/parachains/runtimes/collectives/collectives-westend/Cargo.toml index 2786321e48e2edcc9a975a5ec6f159c0bef41ad5..f9cc54495aea088bf3a309d83a43f4862e55db49 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/Cargo.toml +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/Cargo.toml @@ -65,6 +65,7 @@ sp-version = { workspace = true } # Polkadot pallet-xcm = { workspace = true } +pallet-xcm-benchmarks = { optional = true, workspace = true } polkadot-parachain-primitives = { workspace = true } polkadot-runtime-common = { workspace = true } westend-runtime-constants = { workspace = true } @@ -131,6 +132,7 @@ runtime-benchmarks = [ "pallet-transaction-payment/runtime-benchmarks", "pallet-treasury/runtime-benchmarks", "pallet-utility/runtime-benchmarks", + "pallet-xcm-benchmarks/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", "parachains-common/runtime-benchmarks", "polkadot-parachain-primitives/runtime-benchmarks", @@ -222,6 +224,7 @@ std = [ "pallet-transaction-payment/std", "pallet-treasury/std", "pallet-utility/std", + "pallet-xcm-benchmarks?/std", "pallet-xcm/std", "parachain-info/std", "parachains-common/std", diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs index 5eafc2960cc88cefe2be69d26467b7a60bb4c5d5..5e087832f0e82922fc52ac58a6158da74e06fd08 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/lib.rs @@ -801,7 +801,6 @@ mod benches { [cumulus_pallet_xcmp_queue, XcmpQueue] [pallet_alliance, Alliance] [pallet_collective, AllianceMotion] - [pallet_xcm, PalletXcmExtrinsicsBenchmark::<Runtime>] [pallet_preimage, Preimage] [pallet_scheduler, Scheduler] [pallet_referenda, FellowshipReferenda] @@ -816,6 +815,11 @@ mod benches { [pallet_treasury, FellowshipTreasury] [pallet_asset_rate, AssetRate] [cumulus_pallet_weight_reclaim, WeightReclaim] + // XCM + [pallet_xcm, PalletXcmExtrinsicsBenchmark::<Runtime>] + // NOTE: Make sure you point to the individual modules below. + [pallet_xcm_benchmarks::fungible, XcmBalances] + [pallet_xcm_benchmarks::generic, XcmGeneric] ); } @@ -1065,6 +1069,12 @@ impl_runtime_apis! { use cumulus_pallet_session_benchmarking::Pallet as SessionBench; use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; + // This is defined once again in dispatch_benchmark, because list_benchmarks! + // and add_benchmarks! are macros exported by define_benchmarks! macros and those types + // are referenced in that call. + type XcmBalances = pallet_xcm_benchmarks::fungible::Pallet::<Runtime>; + type XcmGeneric = pallet_xcm_benchmarks::generic::Pallet::<Runtime>; + let mut list = Vec::<BenchmarkList>::new(); list_benchmarks!(list, extra); @@ -1093,10 +1103,11 @@ impl_runtime_apis! { use cumulus_pallet_session_benchmarking::Pallet as SessionBench; impl cumulus_pallet_session_benchmarking::Config for Runtime {} + use xcm_config::WndLocation; parameter_types! { pub ExistentialDepositAsset: Option<Asset> = Some(( - xcm_config::WndLocation::get(), + WndLocation::get(), ExistentialDeposit::get() ).into()); } @@ -1149,6 +1160,112 @@ impl_runtime_apis! { } } + impl pallet_xcm_benchmarks::Config for Runtime { + type XcmConfig = xcm_config::XcmConfig; + type AccountIdConverter = xcm_config::LocationToAccountId; + type DeliveryHelper = cumulus_primitives_utility::ToParentDeliveryHelper< + xcm_config::XcmConfig, + ExistentialDepositAsset, + xcm_config::PriceForParentDelivery, + >; + fn valid_destination() -> Result<Location, BenchmarkError> { + Ok(WndLocation::get()) + } + fn worst_case_holding(_depositable_count: u32) -> Assets { + // just concrete assets according to relay chain. + let assets: Vec<Asset> = vec![ + Asset { + id: AssetId(WndLocation::get()), + fun: Fungible(1_000_000 * UNITS), + } + ]; + assets.into() + } + } + + parameter_types! { + pub const TrustedTeleporter: Option<(Location, Asset)> = Some(( + WndLocation::get(), + Asset { fun: Fungible(UNITS), id: AssetId(WndLocation::get()) }, + )); + pub const CheckedAccount: Option<(AccountId, xcm_builder::MintLocation)> = None; + pub const TrustedReserve: Option<(Location, Asset)> = None; + } + + impl pallet_xcm_benchmarks::fungible::Config for Runtime { + type TransactAsset = Balances; + + type CheckedAccount = CheckedAccount; + type TrustedTeleporter = TrustedTeleporter; + type TrustedReserve = TrustedReserve; + + fn get_asset() -> Asset { + Asset { + id: AssetId(WndLocation::get()), + fun: Fungible(UNITS), + } + } + } + + impl pallet_xcm_benchmarks::generic::Config for Runtime { + type TransactAsset = Balances; + type RuntimeCall = RuntimeCall; + + fn worst_case_response() -> (u64, Response) { + (0u64, Response::Version(Default::default())) + } + + fn worst_case_asset_exchange() -> Result<(Assets, Assets), BenchmarkError> { + Err(BenchmarkError::Skip) + } + + fn universal_alias() -> Result<(Location, Junction), BenchmarkError> { + Err(BenchmarkError::Skip) + } + + fn transact_origin_and_runtime_call() -> Result<(Location, RuntimeCall), BenchmarkError> { + Ok((WndLocation::get(), frame_system::Call::remark_with_event { remark: vec![] }.into())) + } + + fn subscribe_origin() -> Result<Location, BenchmarkError> { + Ok(WndLocation::get()) + } + + fn claimable_asset() -> Result<(Location, Location, Assets), BenchmarkError> { + let origin = WndLocation::get(); + let assets: Assets = (AssetId(WndLocation::get()), 1_000 * UNITS).into(); + let ticket = Location { parents: 0, interior: Here }; + Ok((origin, ticket, assets)) + } + + fn fee_asset() -> Result<Asset, BenchmarkError> { + Ok(Asset { + id: AssetId(WndLocation::get()), + fun: Fungible(1_000_000 * UNITS), + }) + } + + fn unlockable_asset() -> Result<(Location, Location, Asset), BenchmarkError> { + Err(BenchmarkError::Skip) + } + + fn export_message_origin_and_destination( + ) -> Result<(Location, NetworkId, InteriorLocation), BenchmarkError> { + Err(BenchmarkError::Skip) + } + + fn alias_origin() -> Result<(Location, Location), BenchmarkError> { + // Any location can alias to an internal location. + // Here parachain 1000 aliases to an internal account. + let origin = Location::new(1, [Parachain(1000)]); + let target = Location::new(1, [Parachain(1000), AccountId32 { id: [128u8; 32], network: None }]); + Ok((origin, target)) + } + } + + type XcmBalances = pallet_xcm_benchmarks::fungible::Pallet::<Runtime>; + type XcmGeneric = pallet_xcm_benchmarks::generic::Pallet::<Runtime>; + use frame_support::traits::WhitelistedStorageKeys; let whitelist: Vec<TrackedStorageKey> = AllPalletsWithSystem::whitelisted_storage_keys(); @@ -1156,7 +1273,6 @@ impl_runtime_apis! { let params = (&config, &whitelist); add_benchmarks!(params, batches); - if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } Ok(batches) } } diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/pallet_multisig.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/pallet_multisig.rs index a7827b7200906370039d245b02fcaec6d22430d2..5c428bb5e5eacfee1c0a94625d1fa9ab3ec46493 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/pallet_multisig.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/pallet_multisig.rs @@ -1,42 +1,43 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 +// This file is part of Cumulus. -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Cumulus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Cumulus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Cumulus. If not, see <http://www.gnu.org/licenses/>. //! Autogenerated weights for `pallet_multisig` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-07-31, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2025-01-23, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-ynta1nyy-project-238-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: ``, WASM-EXECUTION: `Compiled`, CHAIN: `Some("collectives-polkadot-dev")`, DB CACHE: 1024 +//! HOSTNAME: `e20fc9f125eb`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("collectives-westend-dev")`, DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot-parachain +// target/production/polkadot-parachain // benchmark // pallet -// --chain=collectives-polkadot-dev -// --wasm-execution=compiled -// --pallet=pallet_multisig -// --no-storage-info -// --no-median-slopes -// --no-min-squares // --extrinsic=* +// --chain=collectives-westend-dev +// --pallet=pallet_multisig +// --header=/__w/polkadot-sdk/polkadot-sdk/cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/collectives/collectives-westend/src/weights +// --wasm-execution=compiled // --steps=50 // --repeat=20 -// --json -// --header=./file_header.txt -// --output=./parachains/runtimes/collectives/collectives-polkadot/src/weights/ +// --heap-pages=4096 +// --no-storage-info +// --no-min-squares +// --no-median-slopes #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -54,11 +55,11 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 13_288_000 picoseconds. - Weight::from_parts(14_235_741, 0) + // Minimum execution time: 16_309_000 picoseconds. + Weight::from_parts(17_281_100, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 5 - .saturating_add(Weight::from_parts(500, 0).saturating_mul(z.into())) + // Standard Error: 10 + .saturating_add(Weight::from_parts(549, 0).saturating_mul(z.into())) } /// Storage: `Multisig::Multisigs` (r:1 w:1) /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) @@ -68,13 +69,13 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { // Proof Size summary in bytes: // Measured: `328 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 44_865_000 picoseconds. - Weight::from_parts(33_468_056, 0) + // Minimum execution time: 48_617_000 picoseconds. + Weight::from_parts(35_426_484, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 1_513 - .saturating_add(Weight::from_parts(130_544, 0).saturating_mul(s.into())) - // Standard Error: 14 - .saturating_add(Weight::from_parts(1_422, 0).saturating_mul(z.into())) + // Standard Error: 1_941 + .saturating_add(Weight::from_parts(164_183, 0).saturating_mul(s.into())) + // Standard Error: 19 + .saturating_add(Weight::from_parts(1_898, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -86,13 +87,13 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { // Proof Size summary in bytes: // Measured: `348` // Estimated: `6811` - // Minimum execution time: 29_284_000 picoseconds. - Weight::from_parts(18_708_967, 0) + // Minimum execution time: 32_600_000 picoseconds. + Weight::from_parts(18_613_047, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 916 - .saturating_add(Weight::from_parts(119_202, 0).saturating_mul(s.into())) - // Standard Error: 8 - .saturating_add(Weight::from_parts(1_447, 0).saturating_mul(z.into())) + // Standard Error: 1_498 + .saturating_add(Weight::from_parts(147_489, 0).saturating_mul(s.into())) + // Standard Error: 14 + .saturating_add(Weight::from_parts(2_094, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -106,28 +107,29 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { // Proof Size summary in bytes: // Measured: `451 + s * (33 ±0)` // Estimated: `6811` - // Minimum execution time: 49_462_000 picoseconds. - Weight::from_parts(34_470_286, 0) + // Minimum execution time: 55_580_000 picoseconds. + Weight::from_parts(32_757_473, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 1_738 - .saturating_add(Weight::from_parts(178_227, 0).saturating_mul(s.into())) - // Standard Error: 17 - .saturating_add(Weight::from_parts(1_644, 0).saturating_mul(z.into())) + // Standard Error: 3_265 + .saturating_add(Weight::from_parts(261_212, 0).saturating_mul(s.into())) + // Standard Error: 32 + .saturating_add(Weight::from_parts(2_407, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } /// Storage: `Multisig::Multisigs` (r:1 w:1) /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. + /// The range of component `z` is `[0, 10000]`. fn approve_as_multi_create(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `329 + s * (2 ±0)` + // Measured: `328 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 30_749_000 picoseconds. - Weight::from_parts(31_841_438, 0) + // Minimum execution time: 31_137_000 picoseconds. + Weight::from_parts(32_271_159, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 1_033 - .saturating_add(Weight::from_parts(123_126, 0).saturating_mul(s.into())) + // Standard Error: 1_280 + .saturating_add(Weight::from_parts(163_156, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -138,11 +140,11 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { // Proof Size summary in bytes: // Measured: `348` // Estimated: `6811` - // Minimum execution time: 17_436_000 picoseconds. - Weight::from_parts(18_036_002, 0) + // Minimum execution time: 17_763_000 picoseconds. + Weight::from_parts(18_235_437, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 829 - .saturating_add(Weight::from_parts(109_450, 0).saturating_mul(s.into())) + // Standard Error: 1_245 + .saturating_add(Weight::from_parts(138_553, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -151,13 +153,13 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { /// The range of component `s` is `[2, 100]`. fn cancel_as_multi(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `520 + s * (1 ±0)` + // Measured: `515 + s * (1 ±0)` // Estimated: `6811` - // Minimum execution time: 31_532_000 picoseconds. - Weight::from_parts(32_818_015, 0) + // Minimum execution time: 32_152_000 picoseconds. + Weight::from_parts(34_248_643, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 977 - .saturating_add(Weight::from_parts(123_121, 0).saturating_mul(s.into())) + // Standard Error: 1_943 + .saturating_add(Weight::from_parts(153_258, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/pallet_xcm.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/pallet_xcm.rs index ccf88873c2cd1911a6e1ccc9ad49b5063624e2b4..c0389cbcdb42ceea8656d99f53b2eb7ddac2e407 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/pallet_xcm.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/pallet_xcm.rs @@ -17,9 +17,9 @@ //! Autogenerated weights for `pallet_xcm` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-12-18, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2025-01-17, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `47a5bbdc8de3`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `17a605d70d1a`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("collectives-westend-dev")`, DB CACHE: 1024 // Executed Command: @@ -56,23 +56,19 @@ impl<T: frame_system::Config> pallet_xcm::WeightInfo for WeightInfo<T> { /// Proof: `ParachainSystem::UpwardDeliveryFeeFactor` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0) /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1) - /// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0) - /// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `ParachainSystem::HostConfiguration` (r:1 w:0) /// Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1) /// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn send() -> Weight { // Proof Size summary in bytes: - // Measured: `214` - // Estimated: `3679` - // Minimum execution time: 32_779_000 picoseconds. - Weight::from_parts(33_417_000, 0) - .saturating_add(Weight::from_parts(0, 3679)) - .saturating_add(T::DbWeight::get().reads(7)) - .saturating_add(T::DbWeight::get().writes(2)) + // Measured: `111` + // Estimated: `3576` + // Minimum execution time: 26_877_000 picoseconds. + Weight::from_parts(27_778_000, 0) + .saturating_add(Weight::from_parts(0, 3576)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `ParachainInfo::ParachainId` (r:1 w:0) /// Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) @@ -82,10 +78,6 @@ impl<T: frame_system::Config> pallet_xcm::WeightInfo for WeightInfo<T> { /// Proof: `ParachainSystem::UpwardDeliveryFeeFactor` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0) /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1) - /// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0) - /// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `ParachainSystem::HostConfiguration` (r:1 w:0) @@ -94,13 +86,13 @@ impl<T: frame_system::Config> pallet_xcm::WeightInfo for WeightInfo<T> { /// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn teleport_assets() -> Weight { // Proof Size summary in bytes: - // Measured: `214` - // Estimated: `3679` - // Minimum execution time: 116_031_000 picoseconds. - Weight::from_parts(118_863_000, 0) - .saturating_add(Weight::from_parts(0, 3679)) - .saturating_add(T::DbWeight::get().reads(9)) - .saturating_add(T::DbWeight::get().writes(3)) + // Measured: `111` + // Estimated: `3593` + // Minimum execution time: 109_606_000 picoseconds. + Weight::from_parts(120_756_000, 0) + .saturating_add(Weight::from_parts(0, 3593)) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(2)) } /// Storage: `Benchmark::Override` (r:0 w:0) /// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -120,10 +112,6 @@ impl<T: frame_system::Config> pallet_xcm::WeightInfo for WeightInfo<T> { /// Proof: `ParachainSystem::UpwardDeliveryFeeFactor` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0) /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1) - /// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0) - /// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// Storage: `ParachainSystem::HostConfiguration` (r:1 w:0) @@ -132,23 +120,23 @@ impl<T: frame_system::Config> pallet_xcm::WeightInfo for WeightInfo<T> { /// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn transfer_assets() -> Weight { // Proof Size summary in bytes: - // Measured: `214` - // Estimated: `3679` - // Minimum execution time: 116_267_000 picoseconds. - Weight::from_parts(119_519_000, 0) - .saturating_add(Weight::from_parts(0, 3679)) - .saturating_add(T::DbWeight::get().reads(9)) - .saturating_add(T::DbWeight::get().writes(3)) + // Measured: `111` + // Estimated: `3593` + // Minimum execution time: 109_165_000 picoseconds. + Weight::from_parts(110_899_000, 0) + .saturating_add(Weight::from_parts(0, 3593)) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(2)) } /// Storage: `PolkadotXcm::ShouldRecordXcm` (r:1 w:0) /// Proof: `PolkadotXcm::ShouldRecordXcm` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn execute() -> Weight { // Proof Size summary in bytes: - // Measured: `103` - // Estimated: `1588` - // Minimum execution time: 12_718_000 picoseconds. - Weight::from_parts(13_572_000, 0) - .saturating_add(Weight::from_parts(0, 1588)) + // Measured: `0` + // Estimated: `1485` + // Minimum execution time: 9_494_000 picoseconds. + Weight::from_parts(9_917_000, 0) + .saturating_add(Weight::from_parts(0, 1485)) .saturating_add(T::DbWeight::get().reads(1)) } /// Storage: `PolkadotXcm::SupportedVersion` (r:0 w:1) @@ -157,21 +145,18 @@ impl<T: frame_system::Config> pallet_xcm::WeightInfo for WeightInfo<T> { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_568_000 picoseconds. - Weight::from_parts(7_913_000, 0) + // Minimum execution time: 7_515_000 picoseconds. + Weight::from_parts(7_771_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: `PolkadotXcm::SafeXcmVersion` (r:0 w:1) - /// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn force_default_xcm_version() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_225_000 picoseconds. - Weight::from_parts(2_473_000, 0) + // Minimum execution time: 2_430_000 picoseconds. + Weight::from_parts(2_536_000, 0) .saturating_add(Weight::from_parts(0, 0)) - .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `PolkadotXcm::VersionNotifiers` (r:1 w:1) /// Proof: `PolkadotXcm::VersionNotifiers` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -181,10 +166,6 @@ impl<T: frame_system::Config> pallet_xcm::WeightInfo for WeightInfo<T> { /// Proof: `ParachainSystem::UpwardDeliveryFeeFactor` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0) /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1) - /// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0) - /// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `ParachainSystem::HostConfiguration` (r:1 w:0) /// Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1) @@ -193,13 +174,13 @@ impl<T: frame_system::Config> pallet_xcm::WeightInfo for WeightInfo<T> { /// Proof: `PolkadotXcm::Queries` (`max_values`: None, `max_size`: None, mode: `Measured`) fn force_subscribe_version_notify() -> Weight { // Proof Size summary in bytes: - // Measured: `145` - // Estimated: `3610` - // Minimum execution time: 35_869_000 picoseconds. - Weight::from_parts(37_848_000, 0) - .saturating_add(Weight::from_parts(0, 3610)) - .saturating_add(T::DbWeight::get().reads(8)) - .saturating_add(T::DbWeight::get().writes(5)) + // Measured: `42` + // Estimated: `3507` + // Minimum execution time: 28_913_000 picoseconds. + Weight::from_parts(29_949_000, 0) + .saturating_add(Weight::from_parts(0, 3507)) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `PolkadotXcm::VersionNotifiers` (r:1 w:1) /// Proof: `PolkadotXcm::VersionNotifiers` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -207,10 +188,6 @@ impl<T: frame_system::Config> pallet_xcm::WeightInfo for WeightInfo<T> { /// Proof: `ParachainSystem::UpwardDeliveryFeeFactor` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0) /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1) - /// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0) - /// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `ParachainSystem::HostConfiguration` (r:1 w:0) /// Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1) @@ -219,13 +196,13 @@ impl<T: frame_system::Config> pallet_xcm::WeightInfo for WeightInfo<T> { /// Proof: `PolkadotXcm::Queries` (`max_values`: None, `max_size`: None, mode: `Measured`) fn force_unsubscribe_version_notify() -> Weight { // Proof Size summary in bytes: - // Measured: `363` - // Estimated: `3828` - // Minimum execution time: 38_649_000 picoseconds. - Weight::from_parts(39_842_000, 0) - .saturating_add(Weight::from_parts(0, 3828)) - .saturating_add(T::DbWeight::get().reads(7)) - .saturating_add(T::DbWeight::get().writes(4)) + // Measured: `136` + // Estimated: `3601` + // Minimum execution time: 30_496_000 picoseconds. + Weight::from_parts(31_828_000, 0) + .saturating_add(Weight::from_parts(0, 3601)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) } /// Storage: `PolkadotXcm::XcmExecutionSuspended` (r:0 w:1) /// Proof: `PolkadotXcm::XcmExecutionSuspended` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) @@ -233,8 +210,8 @@ impl<T: frame_system::Config> pallet_xcm::WeightInfo for WeightInfo<T> { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_223_000 picoseconds. - Weight::from_parts(2_483_000, 0) + // Minimum execution time: 2_435_000 picoseconds. + Weight::from_parts(2_635_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -242,11 +219,11 @@ impl<T: frame_system::Config> pallet_xcm::WeightInfo for WeightInfo<T> { /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) fn migrate_supported_version() -> Weight { // Proof Size summary in bytes: - // Measured: `159` - // Estimated: `15999` - // Minimum execution time: 24_164_000 picoseconds. - Weight::from_parts(24_972_000, 0) - .saturating_add(Weight::from_parts(0, 15999)) + // Measured: `22` + // Estimated: `15862` + // Minimum execution time: 21_713_000 picoseconds. + Weight::from_parts(22_209_000, 0) + .saturating_add(Weight::from_parts(0, 15862)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -254,11 +231,11 @@ impl<T: frame_system::Config> pallet_xcm::WeightInfo for WeightInfo<T> { /// Proof: `PolkadotXcm::VersionNotifiers` (`max_values`: None, `max_size`: None, mode: `Measured`) fn migrate_version_notifiers() -> Weight { // Proof Size summary in bytes: - // Measured: `163` - // Estimated: `16003` - // Minimum execution time: 24_604_000 picoseconds. - Weight::from_parts(25_047_000, 0) - .saturating_add(Weight::from_parts(0, 16003)) + // Measured: `26` + // Estimated: `15866` + // Minimum execution time: 22_035_000 picoseconds. + Weight::from_parts(22_675_000, 0) + .saturating_add(Weight::from_parts(0, 15866)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -266,11 +243,11 @@ impl<T: frame_system::Config> pallet_xcm::WeightInfo for WeightInfo<T> { /// Proof: `PolkadotXcm::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) fn already_notified_target() -> Weight { // Proof Size summary in bytes: - // Measured: `173` - // Estimated: `18488` - // Minimum execution time: 28_088_000 picoseconds. - Weight::from_parts(28_431_000, 0) - .saturating_add(Weight::from_parts(0, 18488)) + // Measured: `36` + // Estimated: `18351` + // Minimum execution time: 24_882_000 picoseconds. + Weight::from_parts(25_172_000, 0) + .saturating_add(Weight::from_parts(0, 18351)) .saturating_add(T::DbWeight::get().reads(7)) } /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:2 w:1) @@ -279,44 +256,40 @@ impl<T: frame_system::Config> pallet_xcm::WeightInfo for WeightInfo<T> { /// Proof: `ParachainSystem::UpwardDeliveryFeeFactor` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0) /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1) - /// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0) - /// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `ParachainSystem::HostConfiguration` (r:1 w:0) /// Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1) /// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn notify_current_targets() -> Weight { // Proof Size summary in bytes: - // Measured: `212` - // Estimated: `6152` - // Minimum execution time: 33_814_000 picoseconds. - Weight::from_parts(34_741_000, 0) - .saturating_add(Weight::from_parts(0, 6152)) - .saturating_add(T::DbWeight::get().reads(8)) - .saturating_add(T::DbWeight::get().writes(3)) + // Measured: `75` + // Estimated: `6015` + // Minimum execution time: 28_244_000 picoseconds. + Weight::from_parts(28_873_000, 0) + .saturating_add(Weight::from_parts(0, 6015)) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(2)) } /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:5 w:0) /// Proof: `PolkadotXcm::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) fn notify_target_migration_fail() -> Weight { // Proof Size summary in bytes: - // Measured: `176` - // Estimated: `13541` - // Minimum execution time: 18_242_000 picoseconds. - Weight::from_parts(18_636_000, 0) - .saturating_add(Weight::from_parts(0, 13541)) + // Measured: `39` + // Estimated: `13404` + // Minimum execution time: 17_457_000 picoseconds. + Weight::from_parts(18_023_000, 0) + .saturating_add(Weight::from_parts(0, 13404)) .saturating_add(T::DbWeight::get().reads(5)) } /// Storage: `PolkadotXcm::VersionNotifyTargets` (r:6 w:2) /// Proof: `PolkadotXcm::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) fn migrate_version_notify_targets() -> Weight { // Proof Size summary in bytes: - // Measured: `170` - // Estimated: `16010` - // Minimum execution time: 24_249_000 picoseconds. - Weight::from_parts(24_768_000, 0) - .saturating_add(Weight::from_parts(0, 16010)) + // Measured: `33` + // Estimated: `15873` + // Minimum execution time: 22_283_000 picoseconds. + Weight::from_parts(22_783_000, 0) + .saturating_add(Weight::from_parts(0, 15873)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -326,23 +299,19 @@ impl<T: frame_system::Config> pallet_xcm::WeightInfo for WeightInfo<T> { /// Proof: `ParachainSystem::UpwardDeliveryFeeFactor` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0) /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1) - /// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - /// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0) - /// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `ParachainSystem::HostConfiguration` (r:1 w:0) /// Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1) /// Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) fn migrate_and_notify_old_targets() -> Weight { // Proof Size summary in bytes: - // Measured: `212` - // Estimated: `16052` - // Minimum execution time: 47_602_000 picoseconds. - Weight::from_parts(48_378_000, 0) - .saturating_add(Weight::from_parts(0, 16052)) - .saturating_add(T::DbWeight::get().reads(12)) - .saturating_add(T::DbWeight::get().writes(4)) + // Measured: `75` + // Estimated: `15915` + // Minimum execution time: 41_244_000 picoseconds. + Weight::from_parts(42_264_000, 0) + .saturating_add(Weight::from_parts(0, 15915)) + .saturating_add(T::DbWeight::get().reads(10)) + .saturating_add(T::DbWeight::get().writes(3)) } /// Storage: `PolkadotXcm::QueryCounter` (r:1 w:1) /// Proof: `PolkadotXcm::QueryCounter` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) @@ -350,11 +319,11 @@ impl<T: frame_system::Config> pallet_xcm::WeightInfo for WeightInfo<T> { /// Proof: `PolkadotXcm::Queries` (`max_values`: None, `max_size`: None, mode: `Measured`) fn new_query() -> Weight { // Proof Size summary in bytes: - // Measured: `103` - // Estimated: `1588` - // Minimum execution time: 5_566_000 picoseconds. - Weight::from_parts(5_768_000, 0) - .saturating_add(Weight::from_parts(0, 1588)) + // Measured: `0` + // Estimated: `1485` + // Minimum execution time: 2_678_000 picoseconds. + Weight::from_parts(2_892_000, 0) + .saturating_add(Weight::from_parts(0, 1485)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -362,11 +331,11 @@ impl<T: frame_system::Config> pallet_xcm::WeightInfo for WeightInfo<T> { /// Proof: `PolkadotXcm::Queries` (`max_values`: None, `max_size`: None, mode: `Measured`) fn take_response() -> Weight { // Proof Size summary in bytes: - // Measured: `7740` - // Estimated: `11205` - // Minimum execution time: 30_821_000 picoseconds. - Weight::from_parts(31_250_000, 0) - .saturating_add(Weight::from_parts(0, 11205)) + // Measured: `7576` + // Estimated: `11041` + // Minimum execution time: 26_677_000 picoseconds. + Weight::from_parts(27_470_000, 0) + .saturating_add(Weight::from_parts(0, 11041)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -376,11 +345,11 @@ impl<T: frame_system::Config> pallet_xcm::WeightInfo for WeightInfo<T> { /// Proof: `PolkadotXcm::AssetTraps` (`max_values`: None, `max_size`: None, mode: `Measured`) fn claim_assets() -> Weight { // Proof Size summary in bytes: - // Measured: `160` - // Estimated: `3625` - // Minimum execution time: 43_463_000 picoseconds. - Weight::from_parts(44_960_000, 0) - .saturating_add(Weight::from_parts(0, 3625)) + // Measured: `23` + // Estimated: `3488` + // Minimum execution time: 40_143_000 picoseconds. + Weight::from_parts(41_712_000, 0) + .saturating_add(Weight::from_parts(0, 3488)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/xcm/pallet_xcm_benchmarks_fungible.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/xcm/pallet_xcm_benchmarks_fungible.rs index 00826cbb8d79ea3cbf9cc9b8dd0622e6b781df5e..f6a140f3157fceb5337c6a26e0d926c7b68b9c4b 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/xcm/pallet_xcm_benchmarks_fungible.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/xcm/pallet_xcm_benchmarks_fungible.rs @@ -17,26 +17,28 @@ //! Autogenerated weights for `pallet_xcm_benchmarks::fungible` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-10-21, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2025-01-17, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-augrssgt-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `17a605d70d1a`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: Compiled, CHAIN: Some("collectives-westend-dev"), DB CACHE: 1024 // Executed Command: // target/production/polkadot-parachain // benchmark // pallet -// --steps=50 -// --repeat=20 // --extrinsic=* +// --chain=collectives-westend-dev +// --pallet=pallet_xcm_benchmarks::fungible +// --header=/__w/polkadot-sdk/polkadot-sdk/cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/xcm // --wasm-execution=compiled +// --steps=50 +// --repeat=20 // --heap-pages=4096 -// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json -// --pallet=pallet_xcm_benchmarks::fungible -// --chain=collectives-westend-dev -// --header=./cumulus/file_header.txt -// --template=./cumulus/templates/xcm-bench-template.hbs -// --output=./cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/xcm/ +// --template=cumulus/templates/xcm-bench-template.hbs +// --no-storage-info +// --no-min-squares +// --no-median-slopes #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -54,8 +56,8 @@ impl<T: frame_system::Config> WeightInfo<T> { // Proof Size summary in bytes: // Measured: `101` // Estimated: `3593` - // Minimum execution time: 30_401_000 picoseconds. - Weight::from_parts(30_813_000, 3593) + // Minimum execution time: 32_692_000 picoseconds. + Weight::from_parts(33_469_000, 3593) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -63,33 +65,31 @@ impl<T: frame_system::Config> WeightInfo<T> { // Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) pub fn transfer_asset() -> Weight { // Proof Size summary in bytes: - // Measured: `153` + // Measured: `101` // Estimated: `6196` - // Minimum execution time: 43_150_000 picoseconds. - Weight::from_parts(43_919_000, 6196) + // Minimum execution time: 42_464_000 picoseconds. + Weight::from_parts(43_897_000, 6196) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } - // Storage: `System::Account` (r:2 w:2) + // Storage: `System::Account` (r:3 w:3) // Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) // Storage: `ParachainInfo::ParachainId` (r:1 w:0) // Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + // Storage: `ParachainSystem::UpwardDeliveryFeeFactor` (r:1 w:0) + // Proof: `ParachainSystem::UpwardDeliveryFeeFactor` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) // Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0) // Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) - // Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1) - // Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - // Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0) - // Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) // Storage: `ParachainSystem::HostConfiguration` (r:1 w:0) // Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) // Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1) // Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) pub fn transfer_reserve_asset() -> Weight { // Proof Size summary in bytes: - // Measured: `223` - // Estimated: `6196` - // Minimum execution time: 67_808_000 picoseconds. - Weight::from_parts(69_114_000, 6196) + // Measured: `212` + // Estimated: `8799` + // Minimum execution time: 105_472_000 picoseconds. + Weight::from_parts(115_465_000, 8799) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(4)) } @@ -104,51 +104,49 @@ impl<T: frame_system::Config> WeightInfo<T> { } // Storage: `ParachainInfo::ParachainId` (r:1 w:0) // Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + // Storage: `ParachainSystem::UpwardDeliveryFeeFactor` (r:1 w:0) + // Proof: `ParachainSystem::UpwardDeliveryFeeFactor` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) // Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0) // Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) - // Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1) - // Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - // Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0) - // Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + // Storage: `System::Account` (r:2 w:2) + // Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) // Storage: `ParachainSystem::HostConfiguration` (r:1 w:0) // Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) // Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1) // Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) pub fn initiate_reserve_withdraw() -> Weight { // Proof Size summary in bytes: - // Measured: `70` - // Estimated: `3535` - // Minimum execution time: 29_312_000 picoseconds. - Weight::from_parts(30_347_000, 3535) - .saturating_add(T::DbWeight::get().reads(6)) - .saturating_add(T::DbWeight::get().writes(2)) + // Measured: `212` + // Estimated: `6196` + // Minimum execution time: 72_377_000 picoseconds. + Weight::from_parts(76_456_000, 6196) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(3)) } pub fn receive_teleported_asset() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_283_000 picoseconds. - Weight::from_parts(2_448_000, 0) + // Minimum execution time: 2_556_000 picoseconds. + Weight::from_parts(2_960_000, 0) } // Storage: `System::Account` (r:1 w:1) // Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) pub fn deposit_asset() -> Weight { // Proof Size summary in bytes: - // Measured: `52` + // Measured: `0` // Estimated: `3593` - // Minimum execution time: 23_556_000 picoseconds. - Weight::from_parts(24_419_000, 3593) + // Minimum execution time: 24_560_000 picoseconds. + Weight::from_parts(24_926_000, 3593) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } // Storage: `ParachainInfo::ParachainId` (r:1 w:0) // Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + // Storage: `ParachainSystem::UpwardDeliveryFeeFactor` (r:1 w:0) + // Proof: `ParachainSystem::UpwardDeliveryFeeFactor` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) // Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0) // Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) - // Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1) - // Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - // Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0) - // Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) // Storage: `System::Account` (r:1 w:1) // Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) // Storage: `ParachainSystem::HostConfiguration` (r:1 w:0) @@ -157,54 +155,50 @@ impl<T: frame_system::Config> WeightInfo<T> { // Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) pub fn deposit_reserve_asset() -> Weight { // Proof Size summary in bytes: - // Measured: `122` + // Measured: `111` // Estimated: `3593` - // Minimum execution time: 58_342_000 picoseconds. - Weight::from_parts(59_598_000, 3593) - .saturating_add(T::DbWeight::get().reads(7)) - .saturating_add(T::DbWeight::get().writes(3)) + // Minimum execution time: 57_780_000 picoseconds. + Weight::from_parts(59_561_000, 3593) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: `ParachainInfo::ParachainId` (r:1 w:0) // Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + // Storage: `ParachainSystem::UpwardDeliveryFeeFactor` (r:1 w:0) + // Proof: `ParachainSystem::UpwardDeliveryFeeFactor` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) // Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0) // Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) - // Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1) - // Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - // Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0) - // Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) // Storage: `ParachainSystem::HostConfiguration` (r:1 w:0) // Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) // Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1) // Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) pub fn initiate_teleport() -> Weight { // Proof Size summary in bytes: - // Measured: `70` - // Estimated: `3535` - // Minimum execution time: 28_285_000 picoseconds. - Weight::from_parts(29_016_000, 3535) - .saturating_add(T::DbWeight::get().reads(6)) - .saturating_add(T::DbWeight::get().writes(2)) + // Measured: `111` + // Estimated: `3576` + // Minimum execution time: 37_041_000 picoseconds. + Weight::from_parts(38_101_000, 3576) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(1)) } - // Storage: `System::Account` (r:1 w:1) + // Storage: `System::Account` (r:2 w:2) // Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) // Storage: `ParachainInfo::ParachainId` (r:1 w:0) // Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + // Storage: `ParachainSystem::UpwardDeliveryFeeFactor` (r:1 w:0) + // Proof: `ParachainSystem::UpwardDeliveryFeeFactor` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) // Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0) // Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) - // Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1) - // Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - // Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0) - // Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) // Storage: `ParachainSystem::HostConfiguration` (r:1 w:0) // Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) // Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1) // Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) pub fn initiate_transfer() -> Weight { // Proof Size summary in bytes: - // Measured: `122` - // Estimated: `3593` - // Minimum execution time: 65_211_000 picoseconds. - Weight::from_parts(67_200_000, 3593) + // Measured: `111` + // Estimated: `6196` + // Minimum execution time: 87_635_000 picoseconds. + Weight::from_parts(89_712_000, 6196) .saturating_add(T::DbWeight::get().reads(7)) .saturating_add(T::DbWeight::get().writes(3)) } diff --git a/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/xcm/pallet_xcm_benchmarks_generic.rs b/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/xcm/pallet_xcm_benchmarks_generic.rs index ae94edc3d7315c0738f1b202cffb75ca1f968919..8e732546437a9ae4993edfe1bd39e8887fafb1d4 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/xcm/pallet_xcm_benchmarks_generic.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/xcm/pallet_xcm_benchmarks_generic.rs @@ -17,26 +17,28 @@ //! Autogenerated weights for `pallet_xcm_benchmarks::generic` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-08-27, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2025-01-23, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-svzsllib-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `96ae15bb1012`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: Compiled, CHAIN: Some("collectives-westend-dev"), DB CACHE: 1024 // Executed Command: // target/production/polkadot-parachain // benchmark // pallet -// --steps=50 -// --repeat=20 // --extrinsic=* +// --chain=collectives-westend-dev +// --pallet=pallet_xcm_benchmarks::generic +// --header=/__w/polkadot-sdk/polkadot-sdk/cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/xcm // --wasm-execution=compiled +// --steps=50 +// --repeat=20 // --heap-pages=4096 -// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json -// --pallet=pallet_xcm_benchmarks::generic -// --chain=collectives-westend-dev -// --header=./cumulus/file_header.txt -// --template=./cumulus/templates/xcm-bench-template.hbs -// --output=./cumulus/parachains/runtimes/collectives/collectives-westend/src/weights/xcm/ +// --template=cumulus/templates/xcm-bench-template.hbs +// --no-storage-info +// --no-min-squares +// --no-median-slopes #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -50,127 +52,145 @@ pub struct WeightInfo<T>(PhantomData<T>); impl<T: frame_system::Config> WeightInfo<T> { // Storage: `ParachainInfo::ParachainId` (r:1 w:0) // Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + // Storage: `ParachainSystem::UpwardDeliveryFeeFactor` (r:1 w:0) + // Proof: `ParachainSystem::UpwardDeliveryFeeFactor` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) // Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0) // Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) - // Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1) - // Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - // Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0) - // Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + // Storage: `System::Account` (r:2 w:2) + // Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) // Storage: `ParachainSystem::HostConfiguration` (r:1 w:0) // Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) // Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1) // Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) pub fn report_holding() -> Weight { // Proof Size summary in bytes: - // Measured: `70` - // Estimated: `3535` - // Minimum execution time: 29_015_000 picoseconds. - Weight::from_parts(30_359_000, 3535) - .saturating_add(T::DbWeight::get().reads(6)) - .saturating_add(T::DbWeight::get().writes(2)) + // Measured: `212` + // Estimated: `6196` + // Minimum execution time: 72_839_000 picoseconds. + Weight::from_parts(74_957_000, 6196) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(3)) } pub fn buy_execution() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 572_000 picoseconds. - Weight::from_parts(637_000, 0) + // Minimum execution time: 592_000 picoseconds. + Weight::from_parts(646_000, 0) } + // Storage: `System::Account` (r:1 w:1) + // Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) pub fn pay_fees() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `3593` + // Minimum execution time: 3_630_000 picoseconds. + Weight::from_parts(3_843_000, 3593) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + pub fn asset_claimer() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_550_000 picoseconds. - Weight::from_parts(1_604_000, 0) + // Minimum execution time: 660_000 picoseconds. + Weight::from_parts(712_000, 0) } // Storage: `PolkadotXcm::Queries` (r:1 w:0) // Proof: `PolkadotXcm::Queries` (`max_values`: None, `max_size`: None, mode: `Measured`) pub fn query_response() -> Weight { // Proof Size summary in bytes: - // Measured: `32` - // Estimated: `3497` - // Minimum execution time: 7_354_000 picoseconds. - Weight::from_parts(7_808_000, 3497) + // Measured: `0` + // Estimated: `3465` + // Minimum execution time: 5_996_000 picoseconds. + Weight::from_parts(6_277_000, 3465) .saturating_add(T::DbWeight::get().reads(1)) } pub fn transact() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_716_000 picoseconds. - Weight::from_parts(7_067_000, 0) + // Minimum execution time: 7_427_000 picoseconds. + Weight::from_parts(7_817_000, 0) } pub fn refund_surplus() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_280_000 picoseconds. - Weight::from_parts(1_355_000, 0) + // Minimum execution time: 1_245_000 picoseconds. + Weight::from_parts(1_373_000, 0) } pub fn set_error_handler() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 587_000 picoseconds. - Weight::from_parts(645_000, 0) + // Minimum execution time: 589_000 picoseconds. + Weight::from_parts(647_000, 0) } pub fn set_appendix() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 629_000 picoseconds. - Weight::from_parts(662_000, 0) + // Minimum execution time: 593_000 picoseconds. + Weight::from_parts(653_000, 0) } pub fn clear_error() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 590_000 picoseconds. - Weight::from_parts(639_000, 0) + // Minimum execution time: 599_000 picoseconds. + Weight::from_parts(652_000, 0) } pub fn descend_origin() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 651_000 picoseconds. - Weight::from_parts(688_000, 0) + // Minimum execution time: 620_000 picoseconds. + Weight::from_parts(670_000, 0) + } + pub fn execute_with_origin() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 682_000 picoseconds. + Weight::from_parts(747_000, 0) } pub fn clear_origin() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 601_000 picoseconds. - Weight::from_parts(630_000, 0) + // Minimum execution time: 596_000 picoseconds. + Weight::from_parts(650_000, 0) } // Storage: `ParachainInfo::ParachainId` (r:1 w:0) // Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + // Storage: `ParachainSystem::UpwardDeliveryFeeFactor` (r:1 w:0) + // Proof: `ParachainSystem::UpwardDeliveryFeeFactor` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) // Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0) // Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) - // Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1) - // Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - // Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0) - // Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + // Storage: `System::Account` (r:2 w:2) + // Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) // Storage: `ParachainSystem::HostConfiguration` (r:1 w:0) // Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) // Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1) // Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) pub fn report_error() -> Weight { // Proof Size summary in bytes: - // Measured: `70` - // Estimated: `3535` - // Minimum execution time: 25_650_000 picoseconds. - Weight::from_parts(26_440_000, 3535) - .saturating_add(T::DbWeight::get().reads(6)) - .saturating_add(T::DbWeight::get().writes(2)) + // Measured: `212` + // Estimated: `6196` + // Minimum execution time: 68_183_000 picoseconds. + Weight::from_parts(70_042_000, 6196) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(3)) } // Storage: `PolkadotXcm::AssetTraps` (r:1 w:1) // Proof: `PolkadotXcm::AssetTraps` (`max_values`: None, `max_size`: None, mode: `Measured`) pub fn claim_asset() -> Weight { // Proof Size summary in bytes: - // Measured: `90` - // Estimated: `3555` - // Minimum execution time: 10_492_000 picoseconds. - Weight::from_parts(10_875_000, 3555) + // Measured: `23` + // Estimated: `3488` + // Minimum execution time: 9_661_000 picoseconds. + Weight::from_parts(9_943_000, 3488) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -178,29 +198,27 @@ impl<T: frame_system::Config> WeightInfo<T> { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 597_000 picoseconds. - Weight::from_parts(647_000, 0) + // Minimum execution time: 580_000 picoseconds. + Weight::from_parts(652_000, 0) } // Storage: `PolkadotXcm::VersionNotifyTargets` (r:1 w:1) // Proof: `PolkadotXcm::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) + // Storage: `ParachainSystem::UpwardDeliveryFeeFactor` (r:1 w:0) + // Proof: `ParachainSystem::UpwardDeliveryFeeFactor` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) // Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0) // Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) - // Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1) - // Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - // Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0) - // Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) // Storage: `ParachainSystem::HostConfiguration` (r:1 w:0) // Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) // Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1) // Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) pub fn subscribe_version() -> Weight { // Proof Size summary in bytes: - // Measured: `38` - // Estimated: `3503` - // Minimum execution time: 23_732_000 picoseconds. - Weight::from_parts(24_290_000, 3503) - .saturating_add(T::DbWeight::get().reads(6)) - .saturating_add(T::DbWeight::get().writes(3)) + // Measured: `42` + // Estimated: `3507` + // Minimum execution time: 24_197_000 picoseconds. + Weight::from_parts(25_199_000, 3507) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) } // Storage: `PolkadotXcm::VersionNotifyTargets` (r:0 w:1) // Proof: `PolkadotXcm::VersionNotifyTargets` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -208,148 +226,134 @@ impl<T: frame_system::Config> WeightInfo<T> { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_446_000 picoseconds. - Weight::from_parts(2_613_000, 0) + // Minimum execution time: 2_720_000 picoseconds. + Weight::from_parts(2_881_000, 0) .saturating_add(T::DbWeight::get().writes(1)) } pub fn burn_asset() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 960_000 picoseconds. - Weight::from_parts(1_045_000, 0) + // Minimum execution time: 950_000 picoseconds. + Weight::from_parts(1_076_000, 0) } pub fn expect_asset() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 703_000 picoseconds. - Weight::from_parts(739_000, 0) + // Minimum execution time: 742_000 picoseconds. + Weight::from_parts(785_000, 0) } pub fn expect_origin() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 616_000 picoseconds. - Weight::from_parts(651_000, 0) + // Minimum execution time: 598_000 picoseconds. + Weight::from_parts(671_000, 0) } pub fn expect_error() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 621_000 picoseconds. - Weight::from_parts(660_000, 0) + // Minimum execution time: 571_000 picoseconds. + Weight::from_parts(635_000, 0) } pub fn expect_transact_status() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 794_000 picoseconds. - Weight::from_parts(831_000, 0) + // Minimum execution time: 766_000 picoseconds. + Weight::from_parts(835_000, 0) } // Storage: `ParachainInfo::ParachainId` (r:1 w:0) // Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + // Storage: `ParachainSystem::UpwardDeliveryFeeFactor` (r:1 w:0) + // Proof: `ParachainSystem::UpwardDeliveryFeeFactor` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) // Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0) // Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) - // Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1) - // Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - // Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0) - // Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + // Storage: `System::Account` (r:2 w:2) + // Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) // Storage: `ParachainSystem::HostConfiguration` (r:1 w:0) // Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) // Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1) // Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) pub fn query_pallet() -> Weight { // Proof Size summary in bytes: - // Measured: `70` - // Estimated: `3535` - // Minimum execution time: 29_527_000 picoseconds. - Weight::from_parts(30_614_000, 3535) - .saturating_add(T::DbWeight::get().reads(6)) - .saturating_add(T::DbWeight::get().writes(2)) + // Measured: `212` + // Estimated: `6196` + // Minimum execution time: 76_301_000 picoseconds. + Weight::from_parts(79_269_000, 6196) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(3)) } pub fn expect_pallet() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_189_000 picoseconds. - Weight::from_parts(3_296_000, 0) + // Minimum execution time: 5_452_000 picoseconds. + Weight::from_parts(5_721_000, 0) } // Storage: `ParachainInfo::ParachainId` (r:1 w:0) // Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + // Storage: `ParachainSystem::UpwardDeliveryFeeFactor` (r:1 w:0) + // Proof: `ParachainSystem::UpwardDeliveryFeeFactor` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) // Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0) // Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) - // Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1) - // Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) - // Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0) - // Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + // Storage: `System::Account` (r:2 w:2) + // Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) // Storage: `ParachainSystem::HostConfiguration` (r:1 w:0) // Proof: `ParachainSystem::HostConfiguration` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) // Storage: `ParachainSystem::PendingUpwardMessages` (r:1 w:1) // Proof: `ParachainSystem::PendingUpwardMessages` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) pub fn report_transact_status() -> Weight { // Proof Size summary in bytes: - // Measured: `70` - // Estimated: `3535` - // Minimum execution time: 25_965_000 picoseconds. - Weight::from_parts(26_468_000, 3535) - .saturating_add(T::DbWeight::get().reads(6)) - .saturating_add(T::DbWeight::get().writes(2)) + // Measured: `212` + // Estimated: `6196` + // Minimum execution time: 68_763_000 picoseconds. + Weight::from_parts(71_142_000, 6196) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(3)) } pub fn clear_transact_status() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 618_000 picoseconds. - Weight::from_parts(659_000, 0) + // Minimum execution time: 630_000 picoseconds. + Weight::from_parts(676_000, 0) } pub fn set_topic() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 593_000 picoseconds. - Weight::from_parts(618_000, 0) + // Minimum execution time: 570_000 picoseconds. + Weight::from_parts(622_000, 0) } pub fn clear_topic() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 603_000 picoseconds. - Weight::from_parts(634_000, 0) - } - pub fn alias_origin() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 2_000_000 picoseconds. - Weight::from_parts(2_000_000, 0) + // Minimum execution time: 549_000 picoseconds. + Weight::from_parts(603_000, 0) } pub fn set_fees_mode() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 568_000 picoseconds. - Weight::from_parts(629_000, 0) + // Minimum execution time: 578_000 picoseconds. + Weight::from_parts(626_000, 0) } pub fn unpaid_execution() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 598_000 picoseconds. - Weight::from_parts(655_000, 0) - } - pub fn asset_claimer() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 707_000 picoseconds. - Weight::from_parts(749_000, 0) + // Minimum execution time: 594_000 picoseconds. + Weight::from_parts(639_000, 0) } - pub fn execute_with_origin() -> Weight { + pub fn alias_origin() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 713_000 picoseconds. - Weight::from_parts(776_000, 0) + // Minimum execution time: 637_000 picoseconds. + Weight::from_parts(676_000, 0) } } diff --git a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_multisig.rs b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_multisig.rs index 8e010d768f643ceb55fd233b3a60e3b8e3c2c945..f3ab1b1cac8a50178040be3504bd3fafdb969c0c 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_multisig.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/pallet_multisig.rs @@ -16,28 +16,28 @@ //! Autogenerated weights for `pallet_multisig` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2024-01-12, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2025-01-23, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-j8vvqcjr-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `e20fc9f125eb`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("coretime-rococo-dev")`, DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot-parachain +// target/production/polkadot-parachain // benchmark // pallet +// --extrinsic=* // --chain=coretime-rococo-dev -// --wasm-execution=compiled // --pallet=pallet_multisig -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* +// --header=/__w/polkadot-sdk/polkadot-sdk/cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights +// --wasm-execution=compiled // --steps=50 // --repeat=20 -// --json -// --header=./cumulus/file_header.txt -// --output=./cumulus/parachains/runtimes/coretime/coretime-rococo/src/weights/ +// --heap-pages=4096 +// --no-storage-info +// --no-min-squares +// --no-median-slopes #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -55,11 +55,11 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 12_905_000 picoseconds. - Weight::from_parts(13_544_225, 0) + // Minimum execution time: 16_150_000 picoseconds. + Weight::from_parts(17_417_293, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 2 - .saturating_add(Weight::from_parts(596, 0).saturating_mul(z.into())) + // Standard Error: 10 + .saturating_add(Weight::from_parts(488, 0).saturating_mul(z.into())) } /// Storage: `Multisig::Multisigs` (r:1 w:1) /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) @@ -69,13 +69,13 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { // Proof Size summary in bytes: // Measured: `262 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 38_729_000 picoseconds. - Weight::from_parts(27_942_442, 0) + // Minimum execution time: 47_027_000 picoseconds. + Weight::from_parts(33_446_171, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 648 - .saturating_add(Weight::from_parts(120_340, 0).saturating_mul(s.into())) - // Standard Error: 6 - .saturating_add(Weight::from_parts(1_578, 0).saturating_mul(z.into())) + // Standard Error: 1_434 + .saturating_add(Weight::from_parts(152_452, 0).saturating_mul(s.into())) + // Standard Error: 14 + .saturating_add(Weight::from_parts(2_012, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -87,13 +87,13 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { // Proof Size summary in bytes: // Measured: `282` // Estimated: `6811` - // Minimum execution time: 25_936_000 picoseconds. - Weight::from_parts(16_537_903, 0) + // Minimum execution time: 32_131_000 picoseconds. + Weight::from_parts(18_539_623, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 412 - .saturating_add(Weight::from_parts(105_835, 0).saturating_mul(s.into())) - // Standard Error: 4 - .saturating_add(Weight::from_parts(1_534, 0).saturating_mul(z.into())) + // Standard Error: 1_460 + .saturating_add(Weight::from_parts(140_999, 0).saturating_mul(s.into())) + // Standard Error: 14 + .saturating_add(Weight::from_parts(2_033, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -107,58 +107,61 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { // Proof Size summary in bytes: // Measured: `385 + s * (33 ±0)` // Estimated: `6811` - // Minimum execution time: 45_291_000 picoseconds. - Weight::from_parts(31_294_385, 0) + // Minimum execution time: 53_701_000 picoseconds. + Weight::from_parts(32_431_551, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 816 - .saturating_add(Weight::from_parts(152_838, 0).saturating_mul(s.into())) - // Standard Error: 8 - .saturating_add(Weight::from_parts(1_638, 0).saturating_mul(z.into())) + // Standard Error: 2_797 + .saturating_add(Weight::from_parts(255_676, 0).saturating_mul(s.into())) + // Standard Error: 27 + .saturating_add(Weight::from_parts(2_261, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } /// Storage: `Multisig::Multisigs` (r:1 w:1) /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. + /// The range of component `z` is `[0, 10000]`. fn approve_as_multi_create(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `263 + s * (2 ±0)` + // Measured: `262 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 26_585_000 picoseconds. - Weight::from_parts(27_424_168, 0) + // Minimum execution time: 30_011_000 picoseconds. + Weight::from_parts(32_146_378, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 732 - .saturating_add(Weight::from_parts(123_460, 0).saturating_mul(s.into())) + // Standard Error: 1_455 + .saturating_add(Weight::from_parts(160_784, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `Multisig::Multisigs` (r:1 w:1) /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. + /// The range of component `z` is `[0, 10000]`. fn approve_as_multi_approve(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `282` // Estimated: `6811` - // Minimum execution time: 15_228_000 picoseconds. - Weight::from_parts(15_568_631, 0) + // Minimum execution time: 16_968_000 picoseconds. + Weight::from_parts(16_851_993, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 441 - .saturating_add(Weight::from_parts(107_463, 0).saturating_mul(s.into())) + // Standard Error: 793 + .saturating_add(Weight::from_parts(142_320, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `Multisig::Multisigs` (r:1 w:1) /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. + /// The range of component `z` is `[0, 10000]`. fn cancel_as_multi(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `454 + s * (1 ±0)` + // Measured: `449 + s * (1 ±0)` // Estimated: `6811` - // Minimum execution time: 28_033_000 picoseconds. - Weight::from_parts(29_228_827, 0) + // Minimum execution time: 31_706_000 picoseconds. + Weight::from_parts(33_679_423, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 748 - .saturating_add(Weight::from_parts(117_495, 0).saturating_mul(s.into())) + // Standard Error: 1_154 + .saturating_add(Weight::from_parts(145_059, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_multisig.rs b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_multisig.rs index 1aaf3f4a6fb9dd88f83042915080b08bb735e664..044356f1e146728de721c78eba2e7b512d234113 100644 --- a/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_multisig.rs +++ b/cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/pallet_multisig.rs @@ -17,27 +17,27 @@ //! Autogenerated weights for `pallet_multisig` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-08, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2025-01-23, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `e20fc9f125eb`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("coretime-westend-dev")`, DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot-parachain +// target/production/polkadot-parachain // benchmark // pallet +// --extrinsic=* // --chain=coretime-westend-dev -// --wasm-execution=compiled // --pallet=pallet_multisig -// --no-storage-info -// --no-median-slopes -// --no-min-squares -// --extrinsic=* +// --header=/__w/polkadot-sdk/polkadot-sdk/cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/coretime/coretime-westend/src/weights +// --wasm-execution=compiled // --steps=50 // --repeat=20 -// --json -// --header=./cumulus/file_header.txt -// --output=./cumulus/parachains/runtimes/coretime/coretime-westend/src/weights/ +// --heap-pages=4096 +// --no-storage-info +// --no-min-squares +// --no-median-slopes #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -55,11 +55,11 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 11_938_000 picoseconds. - Weight::from_parts(13_021_007, 0) + // Minimum execution time: 16_090_000 picoseconds. + Weight::from_parts(16_926_991, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 4 - .saturating_add(Weight::from_parts(482, 0).saturating_mul(z.into())) + // Standard Error: 6 + .saturating_add(Weight::from_parts(500, 0).saturating_mul(z.into())) } /// Storage: `Multisig::Multisigs` (r:1 w:1) /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) @@ -69,13 +69,13 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { // Proof Size summary in bytes: // Measured: `262 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 37_643_000 picoseconds. - Weight::from_parts(27_088_068, 0) + // Minimum execution time: 46_739_000 picoseconds. + Weight::from_parts(34_253_833, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 828 - .saturating_add(Weight::from_parts(123_693, 0).saturating_mul(s.into())) - // Standard Error: 8 - .saturating_add(Weight::from_parts(1_456, 0).saturating_mul(z.into())) + // Standard Error: 1_258 + .saturating_add(Weight::from_parts(141_511, 0).saturating_mul(s.into())) + // Standard Error: 12 + .saturating_add(Weight::from_parts(1_969, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -87,13 +87,13 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { // Proof Size summary in bytes: // Measured: `282` // Estimated: `6811` - // Minimum execution time: 25_825_000 picoseconds. - Weight::from_parts(15_698_835, 0) + // Minimum execution time: 31_190_000 picoseconds. + Weight::from_parts(18_287_369, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 568 - .saturating_add(Weight::from_parts(111_928, 0).saturating_mul(s.into())) - // Standard Error: 5 - .saturating_add(Weight::from_parts(1_421, 0).saturating_mul(z.into())) + // Standard Error: 1_405 + .saturating_add(Weight::from_parts(143_414, 0).saturating_mul(s.into())) + // Standard Error: 13 + .saturating_add(Weight::from_parts(2_047, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -107,58 +107,61 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { // Proof Size summary in bytes: // Measured: `385 + s * (33 ±0)` // Estimated: `6811` - // Minimum execution time: 43_587_000 picoseconds. - Weight::from_parts(29_740_539, 0) + // Minimum execution time: 53_340_000 picoseconds. + Weight::from_parts(31_091_227, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 771 - .saturating_add(Weight::from_parts(154_861, 0).saturating_mul(s.into())) - // Standard Error: 7 - .saturating_add(Weight::from_parts(1_557, 0).saturating_mul(z.into())) + // Standard Error: 3_346 + .saturating_add(Weight::from_parts(256_292, 0).saturating_mul(s.into())) + // Standard Error: 32 + .saturating_add(Weight::from_parts(2_518, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } /// Storage: `Multisig::Multisigs` (r:1 w:1) /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. + /// The range of component `z` is `[0, 10000]`. fn approve_as_multi_create(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `263 + s * (2 ±0)` + // Measured: `262 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 24_966_000 picoseconds. - Weight::from_parts(25_879_458, 0) + // Minimum execution time: 30_024_000 picoseconds. + Weight::from_parts(32_926_280, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 777 - .saturating_add(Weight::from_parts(122_823, 0).saturating_mul(s.into())) + // Standard Error: 1_559 + .saturating_add(Weight::from_parts(151_433, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `Multisig::Multisigs` (r:1 w:1) /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. + /// The range of component `z` is `[0, 10000]`. fn approve_as_multi_approve(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `282` // Estimated: `6811` - // Minimum execution time: 14_450_000 picoseconds. - Weight::from_parts(14_607_858, 0) + // Minimum execution time: 16_853_000 picoseconds. + Weight::from_parts(17_314_743, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 471 - .saturating_add(Weight::from_parts(107_007, 0).saturating_mul(s.into())) + // Standard Error: 1_022 + .saturating_add(Weight::from_parts(139_694, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `Multisig::Multisigs` (r:1 w:1) /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. + /// The range of component `z` is `[0, 10000]`. fn cancel_as_multi(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `454 + s * (1 ±0)` + // Measured: `449 + s * (1 ±0)` // Estimated: `6811` - // Minimum execution time: 26_861_000 picoseconds. - Weight::from_parts(27_846_825, 0) + // Minimum execution time: 31_102_000 picoseconds. + Weight::from_parts(32_212_096, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 714 - .saturating_add(Weight::from_parts(116_914, 0).saturating_mul(s.into())) + // Standard Error: 1_524 + .saturating_add(Weight::from_parts(151_963, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/weights/pallet_migrations.rs b/cumulus/parachains/runtimes/people/people-rococo/src/weights/pallet_migrations.rs index 61857ac8202a0383afdbb06198a528886dfbe418..57048b6e7095caa22ac4d4920d7040e56c13e398 100644 --- a/cumulus/parachains/runtimes/people/people-rococo/src/weights/pallet_migrations.rs +++ b/cumulus/parachains/runtimes/people/people-rococo/src/weights/pallet_migrations.rs @@ -1,19 +1,46 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 +// This file is part of Cumulus. -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Cumulus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. -// Need to rerun! +// Cumulus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Cumulus. If not, see <http://www.gnu.org/licenses/>. + +//! Autogenerated weights for `pallet_migrations` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2025-01-27, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `17938671047b`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: 1024 + +// Executed Command: +// frame-omni-bencher +// v1 +// benchmark +// pallet +// --extrinsic=* +// --runtime=target/production/wbuild/people-rococo-runtime/people_rococo_runtime.wasm +// --pallet=pallet_migrations +// --header=/__w/polkadot-sdk/polkadot-sdk/cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/people/people-rococo/src/weights +// --wasm-execution=compiled +// --steps=50 +// --repeat=20 +// --heap-pages=4096 +// --no-storage-info +// --no-min-squares +// --no-median-slopes +// --genesis-builder-policy=none +// --exclude-pallets=pallet_xcm,pallet_xcm_benchmarks::fungible,pallet_xcm_benchmarks::generic #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -32,22 +59,24 @@ impl<T: frame_system::Config> pallet_migrations::WeightInfo for WeightInfo<T> { /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) fn onboard_new_mbms() -> Weight { // Proof Size summary in bytes: - // Measured: `276` + // Measured: `0` // Estimated: `67035` - // Minimum execution time: 7_762_000 picoseconds. - Weight::from_parts(8_100_000, 67035) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Minimum execution time: 4_483_000 picoseconds. + Weight::from_parts(4_781_000, 0) + .saturating_add(Weight::from_parts(0, 67035)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `MultiBlockMigrations::Cursor` (r:1 w:0) /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) fn progress_mbms_none() -> Weight { // Proof Size summary in bytes: - // Measured: `142` + // Measured: `0` // Estimated: `67035` - // Minimum execution time: 2_077_000 picoseconds. - Weight::from_parts(2_138_000, 67035) - .saturating_add(T::DbWeight::get().reads(1_u64)) + // Minimum execution time: 864_000 picoseconds. + Weight::from_parts(907_000, 0) + .saturating_add(Weight::from_parts(0, 67035)) + .saturating_add(T::DbWeight::get().reads(1)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -55,12 +84,13 @@ impl<T: frame_system::Config> pallet_migrations::WeightInfo for WeightInfo<T> { /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) fn exec_migration_completed() -> Weight { // Proof Size summary in bytes: - // Measured: `134` - // Estimated: `3599` - // Minimum execution time: 5_868_000 picoseconds. - Weight::from_parts(6_143_000, 3599) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Measured: `0` + // Estimated: `3465` + // Minimum execution time: 3_978_000 picoseconds. + Weight::from_parts(4_149_000, 0) + .saturating_add(Weight::from_parts(0, 3465)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -68,11 +98,12 @@ impl<T: frame_system::Config> pallet_migrations::WeightInfo for WeightInfo<T> { /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) fn exec_migration_skipped_historic() -> Weight { // Proof Size summary in bytes: - // Measured: `330` - // Estimated: `3795` - // Minimum execution time: 10_283_000 picoseconds. - Weight::from_parts(10_964_000, 3795) - .saturating_add(T::DbWeight::get().reads(2_u64)) + // Measured: `34` + // Estimated: `3731` + // Minimum execution time: 7_432_000 picoseconds. + Weight::from_parts(7_663_000, 0) + .saturating_add(Weight::from_parts(0, 3731)) + .saturating_add(T::DbWeight::get().reads(2)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -80,11 +111,12 @@ impl<T: frame_system::Config> pallet_migrations::WeightInfo for WeightInfo<T> { /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) fn exec_migration_advance() -> Weight { // Proof Size summary in bytes: - // Measured: `276` - // Estimated: `3741` - // Minimum execution time: 9_900_000 picoseconds. - Weight::from_parts(10_396_000, 3741) - .saturating_add(T::DbWeight::get().reads(2_u64)) + // Measured: `0` + // Estimated: `3731` + // Minimum execution time: 6_915_000 picoseconds. + Weight::from_parts(7_112_000, 0) + .saturating_add(Weight::from_parts(0, 3731)) + .saturating_add(T::DbWeight::get().reads(2)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -92,12 +124,13 @@ impl<T: frame_system::Config> pallet_migrations::WeightInfo for WeightInfo<T> { /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) fn exec_migration_complete() -> Weight { // Proof Size summary in bytes: - // Measured: `276` - // Estimated: `3741` - // Minimum execution time: 11_411_000 picoseconds. - Weight::from_parts(11_956_000, 3741) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Measured: `0` + // Estimated: `3731` + // Minimum execution time: 8_561_000 picoseconds. + Weight::from_parts(8_701_000, 0) + .saturating_add(Weight::from_parts(0, 3731)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -107,19 +140,21 @@ impl<T: frame_system::Config> pallet_migrations::WeightInfo for WeightInfo<T> { /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) fn exec_migration_fail() -> Weight { // Proof Size summary in bytes: - // Measured: `276` - // Estimated: `3741` - // Minimum execution time: 12_398_000 picoseconds. - Weight::from_parts(12_910_000, 3741) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Measured: `0` + // Estimated: `3731` + // Minimum execution time: 8_998_000 picoseconds. + Weight::from_parts(9_348_000, 0) + .saturating_add(Weight::from_parts(0, 3731)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } fn on_init_loop() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 166_000 picoseconds. - Weight::from_parts(193_000, 0) + // Minimum execution time: 145_000 picoseconds. + Weight::from_parts(183_000, 0) + .saturating_add(Weight::from_parts(0, 0)) } /// Storage: `MultiBlockMigrations::Cursor` (r:0 w:1) /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) @@ -127,9 +162,10 @@ impl<T: frame_system::Config> pallet_migrations::WeightInfo for WeightInfo<T> { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_686_000 picoseconds. - Weight::from_parts(2_859_000, 0) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Minimum execution time: 2_137_000 picoseconds. + Weight::from_parts(2_275_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `MultiBlockMigrations::Cursor` (r:0 w:1) /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) @@ -137,9 +173,10 @@ impl<T: frame_system::Config> pallet_migrations::WeightInfo for WeightInfo<T> { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_070_000 picoseconds. - Weight::from_parts(3_250_000, 0) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Minimum execution time: 2_625_000 picoseconds. + Weight::from_parts(2_748_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `MultiBlockMigrations::Cursor` (r:1 w:0) /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) @@ -147,26 +184,44 @@ impl<T: frame_system::Config> pallet_migrations::WeightInfo for WeightInfo<T> { /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) fn force_onboard_mbms() -> Weight { // Proof Size summary in bytes: - // Measured: `251` + // Measured: `0` // Estimated: `67035` - // Minimum execution time: 5_901_000 picoseconds. - Weight::from_parts(6_320_000, 67035) - .saturating_add(T::DbWeight::get().reads(2_u64)) + // Minimum execution time: 3_010_000 picoseconds. + Weight::from_parts(3_170_000, 0) + .saturating_add(Weight::from_parts(0, 67035)) + .saturating_add(T::DbWeight::get().reads(2)) } /// Storage: `MultiBlockMigrations::Historic` (r:256 w:256) /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 256]`. fn clear_historic(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1122 + n * (271 ±0)` + // Measured: `960 + n * (271 ±0)` // Estimated: `3834 + n * (2740 ±0)` - // Minimum execution time: 15_952_000 picoseconds. - Weight::from_parts(14_358_665, 3834) - // Standard Error: 3_358 - .saturating_add(Weight::from_parts(1_323_674, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(1_u64)) + // Minimum execution time: 15_088_000 picoseconds. + Weight::from_parts(27_216_754, 0) + .saturating_add(Weight::from_parts(0, 3834)) + // Standard Error: 5_635 + .saturating_add(Weight::from_parts(1_399_330, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) .saturating_add(Weight::from_parts(0, 2740).saturating_mul(n.into())) } -} \ No newline at end of file + /// Storage: `Skipped::Metadata` (r:0 w:0) + /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// The range of component `n` is `[0, 2048]`. + fn reset_pallet_migration(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1605 + n * (38 ±0)` + // Estimated: `686 + n * (39 ±0)` + // Minimum execution time: 1_168_000 picoseconds. + Weight::from_parts(1_235_000, 0) + .saturating_add(Weight::from_parts(0, 686)) + // Standard Error: 2_626 + .saturating_add(Weight::from_parts(936_331, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 39).saturating_mul(n.into())) + } +} diff --git a/cumulus/parachains/runtimes/people/people-rococo/src/weights/pallet_multisig.rs b/cumulus/parachains/runtimes/people/people-rococo/src/weights/pallet_multisig.rs index 73abb62b0482cc444fb2066e2eb6c4831ff5f159..82fcacf64aca642ac892929cb2ac9cc295533053 100644 --- a/cumulus/parachains/runtimes/people/people-rococo/src/weights/pallet_multisig.rs +++ b/cumulus/parachains/runtimes/people/people-rococo/src/weights/pallet_multisig.rs @@ -1,40 +1,43 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 +// This file is part of Cumulus. -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Cumulus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Cumulus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Cumulus. If not, see <http://www.gnu.org/licenses/>. //! Autogenerated weights for `pallet_multisig` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-05-31, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2025-01-23, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("people-kusama-dev"), DB CACHE: 1024 +//! HOSTNAME: `e20fc9f125eb`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("people-rococo-dev")`, DB CACHE: 1024 // Executed Command: -// ./artifacts/polkadot-parachain +// target/production/polkadot-parachain // benchmark // pallet -// --chain=people-kusama-dev -// --execution=wasm -// --wasm-execution=compiled -// --pallet=pallet_multisig // --extrinsic=* +// --chain=people-rococo-dev +// --pallet=pallet_multisig +// --header=/__w/polkadot-sdk/polkadot-sdk/cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/people/people-rococo/src/weights +// --wasm-execution=compiled // --steps=50 // --repeat=20 -// --json -// --header=./file_header.txt -// --output=./cumulus/parachains/runtimes/people/people-kusama/src/weights/pallet_multisig.rs +// --heap-pages=4096 +// --no-storage-info +// --no-min-squares +// --no-median-slopes #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -52,110 +55,113 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 11_056_000 picoseconds. - Weight::from_parts(11_510_137, 0) + // Minimum execution time: 16_209_000 picoseconds. + Weight::from_parts(16_941_673, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 1 - .saturating_add(Weight::from_parts(528, 0).saturating_mul(z.into())) + // Standard Error: 10 + .saturating_add(Weight::from_parts(551, 0).saturating_mul(z.into())) } - /// Storage: Multisig Multisigs (r:1 w:1) - /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) + /// Storage: `Multisig::Multisigs` (r:1 w:1) + /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. /// The range of component `z` is `[0, 10000]`. fn as_multi_create(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `263 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 41_105_000 picoseconds. - Weight::from_parts(34_947_072, 0) + // Minimum execution time: 47_880_000 picoseconds. + Weight::from_parts(35_747_073, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 499 - .saturating_add(Weight::from_parts(67_375, 0).saturating_mul(s.into())) - // Standard Error: 4 - .saturating_add(Weight::from_parts(1_227, 0).saturating_mul(z.into())) + // Standard Error: 2_069 + .saturating_add(Weight::from_parts(147_421, 0).saturating_mul(s.into())) + // Standard Error: 20 + .saturating_add(Weight::from_parts(1_853, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Multisig Multisigs (r:1 w:1) - /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) + /// Storage: `Multisig::Multisigs` (r:1 w:1) + /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[3, 100]`. /// The range of component `z` is `[0, 10000]`. fn as_multi_approve(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `282` // Estimated: `6811` - // Minimum execution time: 26_640_000 picoseconds. - Weight::from_parts(21_515_344, 0) + // Minimum execution time: 31_245_000 picoseconds. + Weight::from_parts(19_011_583, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 943 - .saturating_add(Weight::from_parts(58_769, 0).saturating_mul(s.into())) - // Standard Error: 9 - .saturating_add(Weight::from_parts(1_233, 0).saturating_mul(z.into())) + // Standard Error: 1_336 + .saturating_add(Weight::from_parts(136_422, 0).saturating_mul(s.into())) + // Standard Error: 13 + .saturating_add(Weight::from_parts(2_013, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Multisig Multisigs (r:1 w:1) - /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Multisig::Multisigs` (r:1 w:1) + /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. /// The range of component `z` is `[0, 10000]`. fn as_multi_complete(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `388 + s * (33 ±0)` // Estimated: `6811` - // Minimum execution time: 45_875_000 picoseconds. - Weight::from_parts(38_052_994, 0) + // Minimum execution time: 52_116_000 picoseconds. + Weight::from_parts(33_912_565, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 507 - .saturating_add(Weight::from_parts(82_957, 0).saturating_mul(s.into())) - // Standard Error: 4 - .saturating_add(Weight::from_parts(1_277, 0).saturating_mul(z.into())) + // Standard Error: 3_064 + .saturating_add(Weight::from_parts(258_562, 0).saturating_mul(s.into())) + // Standard Error: 30 + .saturating_add(Weight::from_parts(2_206, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: Multisig Multisigs (r:1 w:1) - /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) + /// Storage: `Multisig::Multisigs` (r:1 w:1) + /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. + /// The range of component `z` is `[0, 10000]`. fn approve_as_multi_create(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `263 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 32_359_000 picoseconds. - Weight::from_parts(33_845_761, 0) + // Minimum execution time: 31_142_000 picoseconds. + Weight::from_parts(32_417_223, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 623 - .saturating_add(Weight::from_parts(69_809, 0).saturating_mul(s.into())) + // Standard Error: 1_622 + .saturating_add(Weight::from_parts(163_533, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Multisig Multisigs (r:1 w:1) - /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) + /// Storage: `Multisig::Multisigs` (r:1 w:1) + /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. + /// The range of component `z` is `[0, 10000]`. fn approve_as_multi_approve(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `282` // Estimated: `6811` - // Minimum execution time: 18_791_000 picoseconds. - Weight::from_parts(20_017_375, 0) + // Minimum execution time: 17_183_000 picoseconds. + Weight::from_parts(18_181_089, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 466 - .saturating_add(Weight::from_parts(64_780, 0).saturating_mul(s.into())) + // Standard Error: 1_123 + .saturating_add(Weight::from_parts(134_567, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Multisig Multisigs (r:1 w:1) - /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) + /// Storage: `Multisig::Multisigs` (r:1 w:1) + /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. + /// The range of component `z` is `[0, 10000]`. fn cancel_as_multi(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `454 + s * (1 ±0)` // Estimated: `6811` - // Minimum execution time: 33_132_000 picoseconds. - Weight::from_parts(34_485_734, 0) + // Minimum execution time: 32_006_000 picoseconds. + Weight::from_parts(33_910_335, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 601 - .saturating_add(Weight::from_parts(70_191, 0).saturating_mul(s.into())) + // Standard Error: 1_347 + .saturating_add(Weight::from_parts(138_258, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/cumulus/parachains/runtimes/people/people-westend/src/weights/pallet_migrations.rs b/cumulus/parachains/runtimes/people/people-westend/src/weights/pallet_migrations.rs index 61857ac8202a0383afdbb06198a528886dfbe418..ecc52360a3ce11f1db4d572c3d310941e89f846b 100644 --- a/cumulus/parachains/runtimes/people/people-westend/src/weights/pallet_migrations.rs +++ b/cumulus/parachains/runtimes/people/people-westend/src/weights/pallet_migrations.rs @@ -1,19 +1,46 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 +// This file is part of Cumulus. -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Cumulus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. -// Need to rerun! +// Cumulus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Cumulus. If not, see <http://www.gnu.org/licenses/>. + +//! Autogenerated weights for `pallet_migrations` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2025-01-27, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `17938671047b`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: 1024 + +// Executed Command: +// frame-omni-bencher +// v1 +// benchmark +// pallet +// --extrinsic=* +// --runtime=target/production/wbuild/people-westend-runtime/people_westend_runtime.wasm +// --pallet=pallet_migrations +// --header=/__w/polkadot-sdk/polkadot-sdk/cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/people/people-westend/src/weights +// --wasm-execution=compiled +// --steps=50 +// --repeat=20 +// --heap-pages=4096 +// --no-storage-info +// --no-min-squares +// --no-median-slopes +// --genesis-builder-policy=none +// --exclude-pallets=pallet_xcm,pallet_xcm_benchmarks::fungible,pallet_xcm_benchmarks::generic #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -32,22 +59,24 @@ impl<T: frame_system::Config> pallet_migrations::WeightInfo for WeightInfo<T> { /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) fn onboard_new_mbms() -> Weight { // Proof Size summary in bytes: - // Measured: `276` + // Measured: `0` // Estimated: `67035` - // Minimum execution time: 7_762_000 picoseconds. - Weight::from_parts(8_100_000, 67035) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Minimum execution time: 4_484_000 picoseconds. + Weight::from_parts(4_646_000, 0) + .saturating_add(Weight::from_parts(0, 67035)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `MultiBlockMigrations::Cursor` (r:1 w:0) /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) fn progress_mbms_none() -> Weight { // Proof Size summary in bytes: - // Measured: `142` + // Measured: `0` // Estimated: `67035` - // Minimum execution time: 2_077_000 picoseconds. - Weight::from_parts(2_138_000, 67035) - .saturating_add(T::DbWeight::get().reads(1_u64)) + // Minimum execution time: 777_000 picoseconds. + Weight::from_parts(841_000, 0) + .saturating_add(Weight::from_parts(0, 67035)) + .saturating_add(T::DbWeight::get().reads(1)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -55,12 +84,13 @@ impl<T: frame_system::Config> pallet_migrations::WeightInfo for WeightInfo<T> { /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) fn exec_migration_completed() -> Weight { // Proof Size summary in bytes: - // Measured: `134` - // Estimated: `3599` - // Minimum execution time: 5_868_000 picoseconds. - Weight::from_parts(6_143_000, 3599) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Measured: `0` + // Estimated: `3465` + // Minimum execution time: 3_883_000 picoseconds. + Weight::from_parts(4_097_000, 0) + .saturating_add(Weight::from_parts(0, 3465)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -68,11 +98,12 @@ impl<T: frame_system::Config> pallet_migrations::WeightInfo for WeightInfo<T> { /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) fn exec_migration_skipped_historic() -> Weight { // Proof Size summary in bytes: - // Measured: `330` - // Estimated: `3795` - // Minimum execution time: 10_283_000 picoseconds. - Weight::from_parts(10_964_000, 3795) - .saturating_add(T::DbWeight::get().reads(2_u64)) + // Measured: `34` + // Estimated: `3731` + // Minimum execution time: 7_695_000 picoseconds. + Weight::from_parts(8_015_000, 0) + .saturating_add(Weight::from_parts(0, 3731)) + .saturating_add(T::DbWeight::get().reads(2)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -80,11 +111,12 @@ impl<T: frame_system::Config> pallet_migrations::WeightInfo for WeightInfo<T> { /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) fn exec_migration_advance() -> Weight { // Proof Size summary in bytes: - // Measured: `276` - // Estimated: `3741` - // Minimum execution time: 9_900_000 picoseconds. - Weight::from_parts(10_396_000, 3741) - .saturating_add(T::DbWeight::get().reads(2_u64)) + // Measured: `0` + // Estimated: `3731` + // Minimum execution time: 6_999_000 picoseconds. + Weight::from_parts(7_323_000, 0) + .saturating_add(Weight::from_parts(0, 3731)) + .saturating_add(T::DbWeight::get().reads(2)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -92,12 +124,13 @@ impl<T: frame_system::Config> pallet_migrations::WeightInfo for WeightInfo<T> { /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) fn exec_migration_complete() -> Weight { // Proof Size summary in bytes: - // Measured: `276` - // Estimated: `3741` - // Minimum execution time: 11_411_000 picoseconds. - Weight::from_parts(11_956_000, 3741) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Measured: `0` + // Estimated: `3731` + // Minimum execution time: 8_302_000 picoseconds. + Weight::from_parts(8_589_000, 0) + .saturating_add(Weight::from_parts(0, 3731)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -107,19 +140,21 @@ impl<T: frame_system::Config> pallet_migrations::WeightInfo for WeightInfo<T> { /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) fn exec_migration_fail() -> Weight { // Proof Size summary in bytes: - // Measured: `276` - // Estimated: `3741` - // Minimum execution time: 12_398_000 picoseconds. - Weight::from_parts(12_910_000, 3741) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Measured: `0` + // Estimated: `3731` + // Minimum execution time: 9_122_000 picoseconds. + Weight::from_parts(9_541_000, 0) + .saturating_add(Weight::from_parts(0, 3731)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } fn on_init_loop() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 166_000 picoseconds. - Weight::from_parts(193_000, 0) + // Minimum execution time: 146_000 picoseconds. + Weight::from_parts(168_000, 0) + .saturating_add(Weight::from_parts(0, 0)) } /// Storage: `MultiBlockMigrations::Cursor` (r:0 w:1) /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) @@ -127,9 +162,10 @@ impl<T: frame_system::Config> pallet_migrations::WeightInfo for WeightInfo<T> { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_686_000 picoseconds. - Weight::from_parts(2_859_000, 0) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Minimum execution time: 2_271_000 picoseconds. + Weight::from_parts(2_367_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `MultiBlockMigrations::Cursor` (r:0 w:1) /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) @@ -137,9 +173,10 @@ impl<T: frame_system::Config> pallet_migrations::WeightInfo for WeightInfo<T> { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_070_000 picoseconds. - Weight::from_parts(3_250_000, 0) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Minimum execution time: 2_653_000 picoseconds. + Weight::from_parts(2_798_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `MultiBlockMigrations::Cursor` (r:1 w:0) /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) @@ -147,26 +184,44 @@ impl<T: frame_system::Config> pallet_migrations::WeightInfo for WeightInfo<T> { /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) fn force_onboard_mbms() -> Weight { // Proof Size summary in bytes: - // Measured: `251` + // Measured: `0` // Estimated: `67035` - // Minimum execution time: 5_901_000 picoseconds. - Weight::from_parts(6_320_000, 67035) - .saturating_add(T::DbWeight::get().reads(2_u64)) + // Minimum execution time: 3_084_000 picoseconds. + Weight::from_parts(3_233_000, 0) + .saturating_add(Weight::from_parts(0, 67035)) + .saturating_add(T::DbWeight::get().reads(2)) } /// Storage: `MultiBlockMigrations::Historic` (r:256 w:256) /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 256]`. fn clear_historic(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1122 + n * (271 ±0)` + // Measured: `960 + n * (271 ±0)` // Estimated: `3834 + n * (2740 ±0)` - // Minimum execution time: 15_952_000 picoseconds. - Weight::from_parts(14_358_665, 3834) - // Standard Error: 3_358 - .saturating_add(Weight::from_parts(1_323_674, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(1_u64)) + // Minimum execution time: 18_761_000 picoseconds. + Weight::from_parts(22_980_278, 0) + .saturating_add(Weight::from_parts(0, 3834)) + // Standard Error: 5_634 + .saturating_add(Weight::from_parts(1_419_653, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) .saturating_add(Weight::from_parts(0, 2740).saturating_mul(n.into())) } -} \ No newline at end of file + /// Storage: `Skipped::Metadata` (r:0 w:0) + /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// The range of component `n` is `[0, 2048]`. + fn reset_pallet_migration(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1605 + n * (38 ±0)` + // Estimated: `686 + n * (39 ±0)` + // Minimum execution time: 1_174_000 picoseconds. + Weight::from_parts(1_216_000, 0) + .saturating_add(Weight::from_parts(0, 686)) + // Standard Error: 3_009 + .saturating_add(Weight::from_parts(952_922, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 39).saturating_mul(n.into())) + } +} diff --git a/cumulus/parachains/runtimes/people/people-westend/src/weights/pallet_multisig.rs b/cumulus/parachains/runtimes/people/people-westend/src/weights/pallet_multisig.rs index 70809dea2366cc71e5ffb6bfe62feeb6d546f46f..5857a140e05e089fd059208372f8d13d8fc18ab9 100644 --- a/cumulus/parachains/runtimes/people/people-westend/src/weights/pallet_multisig.rs +++ b/cumulus/parachains/runtimes/people/people-westend/src/weights/pallet_multisig.rs @@ -1,40 +1,43 @@ // Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 +// This file is part of Cumulus. -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Cumulus is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Cumulus is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Cumulus. If not, see <http://www.gnu.org/licenses/>. //! Autogenerated weights for `pallet_multisig` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-05-31, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2025-01-23, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `bm4`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("people-polkadot-dev"), DB CACHE: 1024 +//! HOSTNAME: `e20fc9f125eb`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("people-westend-dev")`, DB CACHE: 1024 // Executed Command: -// ./artifacts/polkadot-parachain +// target/production/polkadot-parachain // benchmark // pallet -// --chain=people-polkadot-dev -// --execution=wasm -// --wasm-execution=compiled -// --pallet=pallet_multisig // --extrinsic=* +// --chain=people-westend-dev +// --pallet=pallet_multisig +// --header=/__w/polkadot-sdk/polkadot-sdk/cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/people/people-westend/src/weights +// --wasm-execution=compiled // --steps=50 // --repeat=20 -// --json -// --header=./file_header.txt -// --output=./cumulus/parachains/runtimes/people/people-polkadot/src/weights/pallet_multisig.rs +// --heap-pages=4096 +// --no-storage-info +// --no-min-squares +// --no-median-slopes #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -52,110 +55,113 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 11_337_000 picoseconds. - Weight::from_parts(11_960_522, 0) + // Minimum execution time: 15_664_000 picoseconds. + Weight::from_parts(16_483_544, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 9 - .saturating_add(Weight::from_parts(504, 0).saturating_mul(z.into())) + // Standard Error: 6 + .saturating_add(Weight::from_parts(527, 0).saturating_mul(z.into())) } - /// Storage: Multisig Multisigs (r:1 w:1) - /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) + /// Storage: `Multisig::Multisigs` (r:1 w:1) + /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. /// The range of component `z` is `[0, 10000]`. fn as_multi_create(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `263 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 41_128_000 picoseconds. - Weight::from_parts(35_215_592, 0) + // Minimum execution time: 47_543_000 picoseconds. + Weight::from_parts(32_140_648, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 429 - .saturating_add(Weight::from_parts(65_959, 0).saturating_mul(s.into())) - // Standard Error: 4 - .saturating_add(Weight::from_parts(1_230, 0).saturating_mul(z.into())) + // Standard Error: 2_184 + .saturating_add(Weight::from_parts(163_779, 0).saturating_mul(s.into())) + // Standard Error: 21 + .saturating_add(Weight::from_parts(2_192, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Multisig Multisigs (r:1 w:1) - /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) + /// Storage: `Multisig::Multisigs` (r:1 w:1) + /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[3, 100]`. /// The range of component `z` is `[0, 10000]`. fn as_multi_approve(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `282` // Estimated: `6811` - // Minimum execution time: 26_878_000 picoseconds. - Weight::from_parts(21_448_577, 0) + // Minimum execution time: 31_080_000 picoseconds. + Weight::from_parts(19_282_980, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 354 - .saturating_add(Weight::from_parts(60_286, 0).saturating_mul(s.into())) - // Standard Error: 3 - .saturating_add(Weight::from_parts(1_236, 0).saturating_mul(z.into())) + // Standard Error: 1_261 + .saturating_add(Weight::from_parts(134_865, 0).saturating_mul(s.into())) + // Standard Error: 12 + .saturating_add(Weight::from_parts(2_015, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Multisig Multisigs (r:1 w:1) - /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Multisig::Multisigs` (r:1 w:1) + /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. /// The range of component `z` is `[0, 10000]`. fn as_multi_complete(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `388 + s * (33 ±0)` // Estimated: `6811` - // Minimum execution time: 45_716_000 picoseconds. - Weight::from_parts(38_332_947, 0) + // Minimum execution time: 54_063_000 picoseconds. + Weight::from_parts(34_760_071, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 554 - .saturating_add(Weight::from_parts(81_026, 0).saturating_mul(s.into())) - // Standard Error: 5 - .saturating_add(Weight::from_parts(1_265, 0).saturating_mul(z.into())) + // Standard Error: 2_858 + .saturating_add(Weight::from_parts(242_502, 0).saturating_mul(s.into())) + // Standard Error: 28 + .saturating_add(Weight::from_parts(2_187, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: Multisig Multisigs (r:1 w:1) - /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) + /// Storage: `Multisig::Multisigs` (r:1 w:1) + /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. + /// The range of component `z` is `[0, 10000]`. fn approve_as_multi_create(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `263 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 32_089_000 picoseconds. - Weight::from_parts(33_664_508, 0) + // Minimum execution time: 30_997_000 picoseconds. + Weight::from_parts(32_861_544, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 487 - .saturating_add(Weight::from_parts(67_443, 0).saturating_mul(s.into())) + // Standard Error: 1_172 + .saturating_add(Weight::from_parts(144_646, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Multisig Multisigs (r:1 w:1) - /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) + /// Storage: `Multisig::Multisigs` (r:1 w:1) + /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. + /// The range of component `z` is `[0, 10000]`. fn approve_as_multi_approve(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `282` // Estimated: `6811` - // Minimum execution time: 18_631_000 picoseconds. - Weight::from_parts(19_909_964, 0) + // Minimum execution time: 17_110_000 picoseconds. + Weight::from_parts(16_883_743, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 434 - .saturating_add(Weight::from_parts(62_989, 0).saturating_mul(s.into())) + // Standard Error: 1_170 + .saturating_add(Weight::from_parts(141_623, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Multisig Multisigs (r:1 w:1) - /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) + /// Storage: `Multisig::Multisigs` (r:1 w:1) + /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. + /// The range of component `z` is `[0, 10000]`. fn cancel_as_multi(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `454 + s * (1 ±0)` // Estimated: `6811` - // Minimum execution time: 32_486_000 picoseconds. - Weight::from_parts(34_303_784, 0) + // Minimum execution time: 31_575_000 picoseconds. + Weight::from_parts(33_599_222, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 585 - .saturating_add(Weight::from_parts(69_979, 0).saturating_mul(s.into())) + // Standard Error: 1_343 + .saturating_add(Weight::from_parts(148_578, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/cumulus/polkadot-omni-node/lib/Cargo.toml b/cumulus/polkadot-omni-node/lib/Cargo.toml index 018fc88a2aeaf2018681e96a7e4baccaa17b2afa..020d980d3d9d6f96ed05f6afa474f695873d40d9 100644 --- a/cumulus/polkadot-omni-node/lib/Cargo.toml +++ b/cumulus/polkadot-omni-node/lib/Cargo.toml @@ -50,6 +50,7 @@ sc-consensus = { workspace = true, default-features = true } sc-consensus-manual-seal = { workspace = true, default-features = true } sc-executor = { workspace = true, default-features = true } sc-network = { workspace = true, default-features = true } +sc-offchain = { workspace = true, default-features = true } sc-rpc = { workspace = true, default-features = true } sc-runtime-utilities = { workspace = true, default-features = true } sc-service = { workspace = true, default-features = true } @@ -57,6 +58,7 @@ sc-sysinfo = { workspace = true, default-features = true } sc-telemetry = { workspace = true, default-features = true } sc-tracing = { workspace = true, default-features = true } sc-transaction-pool = { workspace = true, default-features = true } +sc-transaction-pool-api = { workspace = true, default-features = true } sp-api = { workspace = true, default-features = true } sp-block-builder = { workspace = true, default-features = true } sp-consensus = { workspace = true, default-features = true } @@ -66,6 +68,7 @@ sp-crypto-hashing = { workspace = true } sp-genesis-builder = { workspace = true } sp-inherents = { workspace = true, default-features = true } sp-keystore = { workspace = true, default-features = true } +sp-offchain = { workspace = true, default-features = true } sp-runtime = { workspace = true } sp-session = { workspace = true, default-features = true } sp-storage = { workspace = true, default-features = true } diff --git a/cumulus/polkadot-omni-node/lib/src/common/mod.rs b/cumulus/polkadot-omni-node/lib/src/common/mod.rs index 37660a5347a20b8fad5b6452eed331f98806c8d7..843183425dabfa44f481855691dfaba69cd056fa 100644 --- a/cumulus/polkadot-omni-node/lib/src/common/mod.rs +++ b/cumulus/polkadot-omni-node/lib/src/common/mod.rs @@ -28,6 +28,7 @@ pub mod types; use cumulus_primitives_core::{CollectCollationInfo, GetCoreSelectorApi}; use sc_client_db::DbHash; +use sc_offchain::OffchainWorkerApi; use serde::de::DeserializeOwned; use sp_api::{ApiExt, CallApiAt, ConstructRuntimeApi, Metadata}; use sp_block_builder::BlockBuilder; @@ -65,6 +66,7 @@ pub trait NodeRuntimeApi<Block: BlockT>: + SessionKeys<Block> + BlockBuilder<Block> + TaggedTransactionQueue<Block> + + OffchainWorkerApi<Block> + CollectCollationInfo<Block> + GetCoreSelectorApi<Block> + Sized @@ -77,6 +79,7 @@ impl<T, Block: BlockT> NodeRuntimeApi<Block> for T where + SessionKeys<Block> + BlockBuilder<Block> + TaggedTransactionQueue<Block> + + OffchainWorkerApi<Block> + GetCoreSelectorApi<Block> + CollectCollationInfo<Block> { diff --git a/cumulus/polkadot-omni-node/lib/src/common/spec.rs b/cumulus/polkadot-omni-node/lib/src/common/spec.rs index 868368f3ca1a7b2179854ad77cbba52bf97ae5a0..d497337904b9798fcaaa2aa5d78853d33b959fb8 100644 --- a/cumulus/polkadot-omni-node/lib/src/common/spec.rs +++ b/cumulus/polkadot-omni-node/lib/src/common/spec.rs @@ -30,9 +30,11 @@ use cumulus_client_service::{ }; use cumulus_primitives_core::{BlockT, ParaId}; use cumulus_relay_chain_interface::{OverseerHandle, RelayChainInterface}; +use futures::FutureExt; use parachains_common::Hash; use polkadot_primitives::CollatorPair; use prometheus_endpoint::Registry; +use sc_client_api::Backend; use sc_consensus::DefaultImportQueue; use sc_executor::{HeapAllocStrategy, DEFAULT_HEAP_ALLOC_STRATEGY}; use sc_network::{config::FullNetworkConfiguration, NetworkBackend, NetworkBlock}; @@ -41,6 +43,7 @@ use sc_sysinfo::HwBench; use sc_telemetry::{TelemetryHandle, TelemetryWorker}; use sc_tracing::tracing::Instrument; use sc_transaction_pool::TransactionPoolHandle; +use sc_transaction_pool_api::OffchainTransactionPoolFactory; use sp_keystore::KeystorePtr; use std::{future::Future, pin::Pin, sync::Arc, time::Duration}; @@ -303,6 +306,27 @@ pub(crate) trait NodeSpec: BaseNodeSpec { }) .await?; + if parachain_config.offchain_worker.enabled { + let offchain_workers = + sc_offchain::OffchainWorkers::new(sc_offchain::OffchainWorkerOptions { + runtime_api_provider: client.clone(), + keystore: Some(params.keystore_container.keystore()), + offchain_db: backend.offchain_storage(), + transaction_pool: Some(OffchainTransactionPoolFactory::new( + transaction_pool.clone(), + )), + network_provider: Arc::new(network.clone()), + is_validator: parachain_config.role.is_authority(), + enable_http_requests: false, + custom_extensions: move |_| vec![], + })?; + task_manager.spawn_handle().spawn( + "offchain-workers-runner", + "offchain-work", + offchain_workers.run(client.clone(), task_manager.spawn_handle()).boxed(), + ); + } + let rpc_builder = { let client = client.clone(); let transaction_pool = transaction_pool.clone(); diff --git a/cumulus/polkadot-omni-node/lib/src/fake_runtime_api/utils.rs b/cumulus/polkadot-omni-node/lib/src/fake_runtime_api/utils.rs index 6bfd5f4f4cbd1743782303d0d5f6ab78d16c7b4a..915f156f8cb53ceee4b4d5976297586f11438f96 100644 --- a/cumulus/polkadot-omni-node/lib/src/fake_runtime_api/utils.rs +++ b/cumulus/polkadot-omni-node/lib/src/fake_runtime_api/utils.rs @@ -111,6 +111,12 @@ macro_rules! impl_node_runtime_apis { } } + impl sp_offchain::OffchainWorkerApi<$block> for $runtime { + fn offchain_worker(_: &<$block as BlockT>::Header) { + unimplemented!() + } + } + impl sp_session::SessionKeys<$block> for $runtime { fn generate_session_keys(_: Option<Vec<u8>>) -> Vec<u8> { unimplemented!() diff --git a/cumulus/polkadot-omni-node/lib/src/lib.rs b/cumulus/polkadot-omni-node/lib/src/lib.rs index ccc1b542b253dd9e002baf3f62f23a6dc3b32f02..92ea3d7d8791f9929dbebdbb9f8d3de897e077f3 100644 --- a/cumulus/polkadot-omni-node/lib/src/lib.rs +++ b/cumulus/polkadot-omni-node/lib/src/lib.rs @@ -26,3 +26,4 @@ mod nodes; pub use cli::CliConfig; pub use command::{run, RunConfig}; pub use common::{chain_spec, runtime}; +pub use nodes::NODE_VERSION; diff --git a/cumulus/polkadot-omni-node/lib/src/nodes/manual_seal.rs b/cumulus/polkadot-omni-node/lib/src/nodes/manual_seal.rs index f33865ad45cddd5bd9b6b9bb858cb69d86313bda..96802177ec1049e5b508015cca634636b894355a 100644 --- a/cumulus/polkadot-omni-node/lib/src/nodes/manual_seal.rs +++ b/cumulus/polkadot-omni-node/lib/src/nodes/manual_seal.rs @@ -21,14 +21,18 @@ use crate::common::{ }; use codec::Encode; use cumulus_client_parachain_inherent::{MockValidationDataInherentDataProvider, MockXcmConfig}; +use cumulus_primitives_aura::AuraUnincludedSegmentApi; use cumulus_primitives_core::{CollectCollationInfo, ParaId}; +use futures::FutureExt; use polkadot_primitives::UpgradeGoAhead; +use sc_client_api::Backend; use sc_consensus::{DefaultImportQueue, LongestChain}; use sc_consensus_manual_seal::rpc::{ManualSeal, ManualSealApiServer}; use sc_network::NetworkBackend; use sc_service::{Configuration, PartialComponents, TaskManager}; use sc_telemetry::TelemetryHandle; -use sp_api::ProvideRuntimeApi; +use sc_transaction_pool_api::OffchainTransactionPoolFactory; +use sp_api::{ApiExt, ProvideRuntimeApi}; use sp_runtime::traits::Header; use std::{marker::PhantomData, sync::Arc}; @@ -117,6 +121,27 @@ impl<NodeSpec: NodeSpecT> ManualSealNode<NodeSpec> { metrics, })?; + if config.offchain_worker.enabled { + let offchain_workers = + sc_offchain::OffchainWorkers::new(sc_offchain::OffchainWorkerOptions { + runtime_api_provider: client.clone(), + keystore: Some(keystore_container.keystore()), + offchain_db: backend.offchain_storage(), + transaction_pool: Some(OffchainTransactionPoolFactory::new( + transaction_pool.clone(), + )), + network_provider: Arc::new(network.clone()), + is_validator: config.role.is_authority(), + enable_http_requests: true, + custom_extensions: move |_| vec![], + })?; + task_manager.spawn_handle().spawn( + "offchain-workers-runner", + "offchain-work", + offchain_workers.run(client.clone(), task_manager.spawn_handle()).boxed(), + ); + } + let proposer = sc_basic_authorship::ProposerFactory::new( task_manager.spawn_handle(), client.clone(), @@ -158,16 +183,24 @@ impl<NodeSpec: NodeSpecT> ManualSealNode<NodeSpec> { .expect("Header lookup should succeed") .expect("Header passed in as parent should be present in backend."); - let should_send_go_ahead = match client_for_cidp + let should_send_go_ahead = client_for_cidp .runtime_api() .collect_collation_info(block, ¤t_para_head) - { - Ok(info) => info.new_validation_code.is_some(), - Err(e) => { - log::error!("Failed to collect collation info: {:?}", e); - false - }, - }; + .map(|info| info.new_validation_code.is_some()) + .unwrap_or_default(); + + // The API version is relevant here because the constraints in the runtime changed + // in https://github.com/paritytech/polkadot-sdk/pull/6825. In general, the logic + // here assumes that we are using the aura-ext consensushook in the parachain + // runtime. + let requires_relay_progress = client_for_cidp + .runtime_api() + .has_api_with::<dyn AuraUnincludedSegmentApi<NodeSpec::Block>, _>( + block, + |version| version > 1, + ) + .ok() + .unwrap_or_default(); let current_para_block_head = Some(polkadot_primitives::HeadData(current_para_head.encode())); @@ -183,8 +216,10 @@ impl<NodeSpec: NodeSpecT> ManualSealNode<NodeSpec> { ), para_id, current_para_block_head, - relay_offset: 1000, - relay_blocks_per_para_block: 1, + relay_offset: 0, + relay_blocks_per_para_block: requires_relay_progress + .then(|| 1) + .unwrap_or_default(), para_blocks_per_relay_epoch: 10, relay_randomness_config: (), xcm_config: MockXcmConfig::new(&*client_for_xcm, block, Default::default()), diff --git a/cumulus/polkadot-omni-node/lib/src/nodes/mod.rs b/cumulus/polkadot-omni-node/lib/src/nodes/mod.rs index ab13322e80ab9123732b427107c540107c38068d..5570170f90b2d55c0caa4627e44a4649c841e32c 100644 --- a/cumulus/polkadot-omni-node/lib/src/nodes/mod.rs +++ b/cumulus/polkadot-omni-node/lib/src/nodes/mod.rs @@ -22,6 +22,11 @@ use cumulus_primitives_core::ParaId; use manual_seal::ManualSealNode; use sc_service::{Configuration, TaskManager}; +/// The current node version for cumulus official binaries, which takes the basic +/// SemVer form `<major>.<minor>.<patch>`. It should correspond to the latest +/// `polkadot` version of a stable release. +pub const NODE_VERSION: &'static str = "1.17.1"; + /// Trait that extends the `DynNodeSpec` trait with manual seal related logic. /// /// We need it in order to be able to access both the `DynNodeSpec` and the manual seal logic diff --git a/cumulus/polkadot-omni-node/src/main.rs b/cumulus/polkadot-omni-node/src/main.rs index a6c1dd3cadbb0c90c1103d62db09d6b29e8bc556..1183f488df8b1525dbc33384abbb8c637d8c8263 100644 --- a/cumulus/polkadot-omni-node/src/main.rs +++ b/cumulus/polkadot-omni-node/src/main.rs @@ -23,14 +23,15 @@ use polkadot_omni_node_lib::{ chain_spec::DiskChainSpecLoader, run, runtime::DefaultRuntimeResolver, CliConfig as CliConfigT, - RunConfig, + RunConfig, NODE_VERSION, }; struct CliConfig; impl CliConfigT for CliConfig { fn impl_version() -> String { - env!("SUBSTRATE_CLI_IMPL_VERSION").into() + let commit_hash = env!("SUBSTRATE_CLI_COMMIT_HASH"); + format!("{}-{commit_hash}", NODE_VERSION) } fn author() -> String { diff --git a/cumulus/polkadot-parachain/Cargo.toml b/cumulus/polkadot-parachain/Cargo.toml index 9130f60ceb38b47631c9cf6f82bae350c4d35475..6b578779997c03eb3a8d308895bc477920ba2fa6 100644 --- a/cumulus/polkadot-parachain/Cargo.toml +++ b/cumulus/polkadot-parachain/Cargo.toml @@ -29,7 +29,6 @@ asset-hub-westend-runtime = { workspace = true } bridge-hub-rococo-runtime = { workspace = true, default-features = true } bridge-hub-westend-runtime = { workspace = true, default-features = true } collectives-westend-runtime = { workspace = true } -contracts-rococo-runtime = { workspace = true } coretime-rococo-runtime = { workspace = true } coretime-westend-runtime = { workspace = true } glutton-westend-runtime = { workspace = true } @@ -70,7 +69,6 @@ runtime-benchmarks = [ "bridge-hub-rococo-runtime/runtime-benchmarks", "bridge-hub-westend-runtime/runtime-benchmarks", "collectives-westend-runtime/runtime-benchmarks", - "contracts-rococo-runtime/runtime-benchmarks", "coretime-rococo-runtime/runtime-benchmarks", "coretime-westend-runtime/runtime-benchmarks", "glutton-westend-runtime/runtime-benchmarks", @@ -88,7 +86,6 @@ try-runtime = [ "bridge-hub-rococo-runtime/try-runtime", "bridge-hub-westend-runtime/try-runtime", "collectives-westend-runtime/try-runtime", - "contracts-rococo-runtime/try-runtime", "coretime-rococo-runtime/try-runtime", "coretime-westend-runtime/try-runtime", "glutton-westend-runtime/try-runtime", diff --git a/cumulus/polkadot-parachain/src/main.rs b/cumulus/polkadot-parachain/src/main.rs index 61764636a0600f58578f87539ed857bb78d4e51a..a84fb0dfb18f8c9f86d3b8c481b682c82ddfec7b 100644 --- a/cumulus/polkadot-parachain/src/main.rs +++ b/cumulus/polkadot-parachain/src/main.rs @@ -21,13 +21,14 @@ mod chain_spec; -use polkadot_omni_node_lib::{run, CliConfig as CliConfigT, RunConfig}; +use polkadot_omni_node_lib::{run, CliConfig as CliConfigT, RunConfig, NODE_VERSION}; struct CliConfig; impl CliConfigT for CliConfig { fn impl_version() -> String { - env!("SUBSTRATE_CLI_IMPL_VERSION").into() + let commit_hash = env!("SUBSTRATE_CLI_COMMIT_HASH"); + format!("{}-{commit_hash}", NODE_VERSION) } fn author() -> String { diff --git a/cumulus/test/runtime/Cargo.toml b/cumulus/test/runtime/Cargo.toml index 4cc4f483c0287903f12c76a88d9c0bacdbc5ec0e..711525a297c728e5f721282615b460aa70490d8e 100644 --- a/cumulus/test/runtime/Cargo.toml +++ b/cumulus/test/runtime/Cargo.toml @@ -47,7 +47,6 @@ cumulus-pallet-parachain-system = { workspace = true } cumulus-pallet-weight-reclaim = { workspace = true } cumulus-primitives-aura = { workspace = true } cumulus-primitives-core = { workspace = true } -pallet-collator-selection = { workspace = true } parachain-info = { workspace = true } [build-dependencies] @@ -69,7 +68,6 @@ std = [ "pallet-aura/std", "pallet-authorship/std", "pallet-balances/std", - "pallet-collator-selection/std", "pallet-glutton/std", "pallet-message-queue/std", "pallet-session/std", @@ -96,4 +94,5 @@ std = [ ] increment-spec-version = [] elastic-scaling = [] +elastic-scaling-500ms = [] experimental-ump-signals = ["cumulus-pallet-parachain-system/experimental-ump-signals"] diff --git a/cumulus/test/runtime/build.rs b/cumulus/test/runtime/build.rs index 43e60c1074a047ecaeda05838178bac87f857899..99d30ce6dc37257ae1a8aadf3a4f96ad5be97864 100644 --- a/cumulus/test/runtime/build.rs +++ b/cumulus/test/runtime/build.rs @@ -39,6 +39,14 @@ fn main() { .import_memory() .set_file_name("wasm_binary_elastic_scaling.rs") .build(); + + WasmBuilder::new() + .with_current_project() + .enable_feature("elastic-scaling-500ms") + .enable_feature("experimental-ump-signals") + .import_memory() + .set_file_name("wasm_binary_elastic_scaling_500ms.rs") + .build(); } #[cfg(not(feature = "std"))] diff --git a/cumulus/test/runtime/src/lib.rs b/cumulus/test/runtime/src/lib.rs index 01ce3427c1f19b21663bd7b940c1fa95e212c48b..09e1361603a08377a8e3fdd2a71968dac8dedec2 100644 --- a/cumulus/test/runtime/src/lib.rs +++ b/cumulus/test/runtime/src/lib.rs @@ -27,6 +27,10 @@ pub mod wasm_spec_version_incremented { include!(concat!(env!("OUT_DIR"), "/wasm_binary_spec_version_incremented.rs")); } +pub mod elastic_scaling_500ms { + #[cfg(feature = "std")] + include!(concat!(env!("OUT_DIR"), "/wasm_binary_elastic_scaling_500ms.rs")); +} pub mod elastic_scaling_mvp { #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary_elastic_scaling_mvp.rs")); @@ -98,21 +102,21 @@ impl_opaque_keys! { /// The para-id used in this runtime. pub const PARACHAIN_ID: u32 = 100; -#[cfg(not(feature = "elastic-scaling"))] -const UNINCLUDED_SEGMENT_CAPACITY: u32 = 4; -#[cfg(not(feature = "elastic-scaling"))] -const BLOCK_PROCESSING_VELOCITY: u32 = 1; - -#[cfg(feature = "elastic-scaling")] -const UNINCLUDED_SEGMENT_CAPACITY: u32 = 7; -#[cfg(feature = "elastic-scaling")] -const BLOCK_PROCESSING_VELOCITY: u32 = 4; - -#[cfg(not(feature = "elastic-scaling"))] +#[cfg(not(any(feature = "elastic-scaling", feature = "elastic-scaling-500ms")))] pub const MILLISECS_PER_BLOCK: u64 = 6000; -#[cfg(feature = "elastic-scaling")] + +#[cfg(all(feature = "elastic-scaling", not(feature = "elastic-scaling-500ms")))] pub const MILLISECS_PER_BLOCK: u64 = 2000; +#[cfg(feature = "elastic-scaling-500ms")] +pub const MILLISECS_PER_BLOCK: u64 = 500; + +const BLOCK_PROCESSING_VELOCITY: u32 = + RELAY_CHAIN_SLOT_DURATION_MILLIS / (MILLISECS_PER_BLOCK as u32); + +// The `+2` shouldn't be needed, https://github.com/paritytech/polkadot-sdk/issues/5260 +const UNINCLUDED_SEGMENT_CAPACITY: u32 = BLOCK_PROCESSING_VELOCITY * 2 + 2; + pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK; const RELAY_CHAIN_SLOT_DURATION_MILLIS: u32 = 6000; diff --git a/cumulus/test/service/Cargo.toml b/cumulus/test/service/Cargo.toml index 794007532621e196066ada89fdae09f9e4f09247..407c657bd14ef6e839c6d5d9a624e3cc2293f49e 100644 --- a/cumulus/test/service/Cargo.toml +++ b/cumulus/test/service/Cargo.toml @@ -76,7 +76,6 @@ cumulus-client-collator = { workspace = true, default-features = true } cumulus-client-consensus-aura = { workspace = true, default-features = true } cumulus-client-consensus-common = { workspace = true, default-features = true } cumulus-client-consensus-proposer = { workspace = true, default-features = true } -cumulus-client-consensus-relay-chain = { workspace = true, default-features = true } cumulus-client-parachain-inherent = { workspace = true, default-features = true } cumulus-client-pov-recovery = { workspace = true, default-features = true } cumulus-client-service = { workspace = true, default-features = true } @@ -89,12 +88,10 @@ cumulus-relay-chain-minimal-node = { workspace = true, default-features = true } cumulus-test-relay-sproof-builder = { workspace = true, default-features = true } cumulus-test-runtime = { workspace = true } pallet-timestamp = { workspace = true, default-features = true } -parachains-common = { workspace = true, default-features = true } [dev-dependencies] cumulus-test-client = { workspace = true } futures = { workspace = true } -portpicker = { workspace = true } sp-authority-discovery = { workspace = true, default-features = true } # Polkadot dependencies @@ -102,7 +99,6 @@ polkadot-test-service = { workspace = true } # Substrate dependencies sc-cli = { workspace = true, default-features = true } -substrate-test-utils = { workspace = true } [features] runtime-benchmarks = [ @@ -113,7 +109,6 @@ runtime-benchmarks = [ "frame-system/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", "pallet-transaction-payment/runtime-benchmarks", - "parachains-common/runtime-benchmarks", "polkadot-cli/runtime-benchmarks", "polkadot-primitives/runtime-benchmarks", "polkadot-service/runtime-benchmarks", diff --git a/cumulus/test/service/src/chain_spec.rs b/cumulus/test/service/src/chain_spec.rs index 5ebcc14592d74d2585fbc8f6e54f41dd1b0b700d..b59bd7ab46bdbd9fb1591cc6b71a5dae141f0e06 100644 --- a/cumulus/test/service/src/chain_spec.rs +++ b/cumulus/test/service/src/chain_spec.rs @@ -117,6 +117,16 @@ pub fn get_elastic_scaling_chain_spec(id: Option<ParaId>) -> ChainSpec { ) } +/// Get the chain spec for a specific parachain ID. +pub fn get_elastic_scaling_500ms_chain_spec(id: Option<ParaId>) -> ChainSpec { + get_chain_spec_with_extra_endowed( + id, + Default::default(), + cumulus_test_runtime::elastic_scaling_500ms::WASM_BINARY + .expect("WASM binary was not built, please build it!"), + ) +} + /// Get the chain spec for a specific parachain ID. pub fn get_elastic_scaling_mvp_chain_spec(id: Option<ParaId>) -> ChainSpec { get_chain_spec_with_extra_endowed( diff --git a/cumulus/test/service/src/cli.rs b/cumulus/test/service/src/cli.rs index e019089e70fe8e8b7b12543d78459a0fed539ff7..7909ffbf7142f3ae34338340fdc6561fc709f22f 100644 --- a/cumulus/test/service/src/cli.rs +++ b/cumulus/test/service/src/cli.rs @@ -274,6 +274,12 @@ impl SubstrateCli for TestCollatorCli { 2200, )))) as Box<_> }, + "elastic-scaling-500ms" => { + tracing::info!("Using elastic-scaling 500ms chain spec."); + Box::new(cumulus_test_service::get_elastic_scaling_500ms_chain_spec(Some( + ParaId::from(2300), + ))) as Box<_> + }, path => { let chain_spec = cumulus_test_service::chain_spec::ChainSpec::from_json_file(path.into())?; diff --git a/cumulus/xcm/xcm-emulator/Cargo.toml b/cumulus/xcm/xcm-emulator/Cargo.toml index ae8cb79bb55e1dd49fb35955f156b68935dc4303..b6fbbe3e4ce4f859a7fc5f17e4dac25a6f889e14 100644 --- a/cumulus/xcm/xcm-emulator/Cargo.toml +++ b/cumulus/xcm/xcm-emulator/Cargo.toml @@ -33,7 +33,6 @@ sp-tracing = { workspace = true, default-features = true } # Cumulus cumulus-pallet-parachain-system = { workspace = true, default-features = true } -cumulus-pallet-xcmp-queue = { workspace = true, default-features = true } cumulus-primitives-core = { workspace = true, default-features = true } cumulus-primitives-parachain-inherent = { workspace = true, default-features = true } cumulus-test-relay-sproof-builder = { workspace = true, default-features = true } diff --git a/cumulus/zombienet/tests/0008-elastic_authoring.toml b/cumulus/zombienet/tests/0008-elastic_authoring.toml index f2e2010a9e4582feefaebdaa355ab96b6a8f7695..516c152471b113e6c527045c9aaff1b58c8c1fed 100644 --- a/cumulus/zombienet/tests/0008-elastic_authoring.toml +++ b/cumulus/zombienet/tests/0008-elastic_authoring.toml @@ -1,10 +1,6 @@ [settings] timeout = 1000 -[relaychain.genesis.runtimeGenesis.patch.configuration.config.async_backing_params] - max_candidate_depth = 6 - allowed_ancestry_len = 3 - [relaychain.genesis.runtimeGenesis.patch.configuration.config.scheduler_params] max_validators_per_core = 1 num_cores = 4 diff --git a/cumulus/zombienet/tests/0009-elastic_pov_recovery.toml b/cumulus/zombienet/tests/0009-elastic_pov_recovery.toml index 1cf0775a2e177be85445de1f5a85c745670a76ee..b65ed77ec1ba5bd986f9505c0915b15fbd98eee7 100644 --- a/cumulus/zombienet/tests/0009-elastic_pov_recovery.toml +++ b/cumulus/zombienet/tests/0009-elastic_pov_recovery.toml @@ -9,10 +9,6 @@ requests = { memory = "2G", cpu = "1" } limits = { memory = "4G", cpu = "2" } requests = { memory = "2G", cpu = "1" } -[relaychain.genesis.runtimeGenesis.patch.configuration.config.async_backing_params] - max_candidate_depth = 6 - allowed_ancestry_len = 3 - [relaychain.genesis.runtimeGenesis.patch.configuration.config.scheduler_params] max_validators_per_core = 1 num_cores = 4 diff --git a/docs/sdk/src/reference_docs/chain_spec_runtime/src/runtime.rs b/docs/sdk/src/reference_docs/chain_spec_runtime/src/runtime.rs index 282fc1ff489c0195973d712c085688bdaf77a30a..3ffa3d61263f2cc6c9204ec208b3c68cbfdc236a 100644 --- a/docs/sdk/src/reference_docs/chain_spec_runtime/src/runtime.rs +++ b/docs/sdk/src/reference_docs/chain_spec_runtime/src/runtime.rs @@ -57,7 +57,14 @@ type SignedExtra = (); mod runtime { /// The main runtime type. #[runtime::runtime] - #[runtime::derive(RuntimeCall, RuntimeEvent, RuntimeError, RuntimeOrigin, RuntimeTask)] + #[runtime::derive( + RuntimeCall, + RuntimeEvent, + RuntimeError, + RuntimeOrigin, + RuntimeTask, + RuntimeViewFunction + )] pub struct Runtime; /// Mandatory system pallet that should always be included in a FRAME runtime. diff --git a/polkadot/node/core/candidate-validation/src/lib.rs b/polkadot/node/core/candidate-validation/src/lib.rs index 2a4643031bf8788b1def68b76a916ab32a355821..24590fe0c90ea9f8a1e164efc52cd5da18dbf436 100644 --- a/polkadot/node/core/candidate-validation/src/lib.rs +++ b/polkadot/node/core/candidate-validation/src/lib.rs @@ -39,9 +39,9 @@ use polkadot_node_subsystem::{ }; use polkadot_node_subsystem_util::{ self as util, - runtime::{prospective_parachains_mode, ClaimQueueSnapshot, ProspectiveParachainsMode}, + runtime::{fetch_scheduling_lookahead, ClaimQueueSnapshot}, }; -use polkadot_overseer::ActiveLeavesUpdate; +use polkadot_overseer::{ActivatedLeaf, ActiveLeavesUpdate}; use polkadot_parachain_primitives::primitives::ValidationResult as WasmValidationResult; use polkadot_primitives::{ executor_params::{ @@ -158,7 +158,7 @@ where Sender: SubsystemSender<RuntimeApiMessage>, { match util::runtime::fetch_claim_queue(sender, relay_parent).await { - Ok(maybe_cq) => maybe_cq, + Ok(cq) => Some(cq), Err(err) => { gum::warn!( target: LOG_TARGET, @@ -190,40 +190,30 @@ where exec_kind, response_sender, .. - } => - async move { - let _timer = metrics.time_validate_from_exhaustive(); - let relay_parent = candidate_receipt.descriptor.relay_parent(); - - let maybe_claim_queue = claim_queue(relay_parent, &mut sender).await; - - let maybe_expected_session_index = - match util::request_session_index_for_child(relay_parent, &mut sender) - .await - .await - { - Ok(Ok(expected_session_index)) => Some(expected_session_index), - _ => None, - }; - - let res = validate_candidate_exhaustive( - maybe_expected_session_index, - validation_host, - validation_data, - validation_code, - candidate_receipt, - pov, - executor_params, - exec_kind, - &metrics, - maybe_claim_queue, - ) - .await; + } => async move { + let _timer = metrics.time_validate_from_exhaustive(); + let relay_parent = candidate_receipt.descriptor.relay_parent(); + + let maybe_claim_queue = claim_queue(relay_parent, &mut sender).await; + + let res = validate_candidate_exhaustive( + get_session_index(&mut sender, relay_parent).await, + validation_host, + validation_data, + validation_code, + candidate_receipt, + pov, + executor_params, + exec_kind, + &metrics, + maybe_claim_queue, + ) + .await; - metrics.on_validation_event(&res); - let _ = response_sender.send(res); - } - .boxed(), + metrics.on_validation_event(&res); + let _ = response_sender.send(res); + } + .boxed(), CandidateValidationMessage::PreCheck { relay_parent, validation_code_hash, @@ -257,7 +247,7 @@ async fn run<Context>( pvf_prepare_workers_hard_max_num, }: Config, ) -> SubsystemResult<()> { - let (validation_host, task) = polkadot_node_core_pvf::start( + let (mut validation_host, task) = polkadot_node_core_pvf::start( polkadot_node_core_pvf::Config::new( artifacts_cache_path, node_version, @@ -282,8 +272,13 @@ async fn run<Context>( comm = ctx.recv().fuse() => { match comm { Ok(FromOrchestra::Signal(OverseerSignal::ActiveLeaves(update))) => { - update_active_leaves(ctx.sender(), validation_host.clone(), update.clone()).await; - maybe_prepare_validation(ctx.sender(), keystore.clone(), validation_host.clone(), update, &mut prepare_state).await; + handle_active_leaves_update( + ctx.sender(), + keystore.clone(), + &mut validation_host, + update, + &mut prepare_state, + ).await }, Ok(FromOrchestra::Signal(OverseerSignal::BlockFinalized(..))) => {}, Ok(FromOrchestra::Signal(OverseerSignal::Conclude)) => return Ok(()), @@ -343,17 +338,46 @@ impl Default for PrepareValidationState { } } -async fn maybe_prepare_validation<Sender>( +async fn handle_active_leaves_update<Sender>( sender: &mut Sender, keystore: KeystorePtr, - validation_backend: impl ValidationBackend, + validation_host: &mut impl ValidationBackend, update: ActiveLeavesUpdate, + prepare_state: &mut PrepareValidationState, +) where + Sender: SubsystemSender<ChainApiMessage> + SubsystemSender<RuntimeApiMessage>, +{ + let maybe_session_index = update_active_leaves(sender, validation_host, update.clone()).await; + + if let Some(activated) = update.activated { + let maybe_new_session_index = match (prepare_state.session_index, maybe_session_index) { + (Some(existing_index), Some(new_index)) => + (new_index > existing_index).then_some(new_index), + (None, Some(new_index)) => Some(new_index), + _ => None, + }; + maybe_prepare_validation( + sender, + keystore.clone(), + validation_host, + activated, + prepare_state, + maybe_new_session_index, + ) + .await; + } +} + +async fn maybe_prepare_validation<Sender>( + sender: &mut Sender, + keystore: KeystorePtr, + validation_backend: &mut impl ValidationBackend, + leaf: ActivatedLeaf, state: &mut PrepareValidationState, + new_session_index: Option<SessionIndex>, ) where Sender: SubsystemSender<RuntimeApiMessage>, { - let Some(leaf) = update.activated else { return }; - let new_session_index = new_session_index(sender, state.session_index, leaf.hash).await; if new_session_index.is_some() { state.session_index = new_session_index; state.already_prepared_code_hashes.clear(); @@ -380,16 +404,11 @@ async fn maybe_prepare_validation<Sender>( } } -// Returns the new session index if it is greater than the current one. -async fn new_session_index<Sender>( - sender: &mut Sender, - session_index: Option<SessionIndex>, - relay_parent: Hash, -) -> Option<SessionIndex> +async fn get_session_index<Sender>(sender: &mut Sender, relay_parent: Hash) -> Option<SessionIndex> where Sender: SubsystemSender<RuntimeApiMessage>, { - let Ok(Ok(new_session_index)) = + let Ok(Ok(session_index)) = util::request_session_index_for_child(relay_parent, sender).await.await else { gum::warn!( @@ -400,13 +419,7 @@ where return None }; - session_index.map_or(Some(new_session_index), |index| { - if new_session_index > index { - Some(new_session_index) - } else { - None - } - }) + Some(session_index) } // Returns true if the node is an authority in the next session. @@ -460,7 +473,7 @@ where // Sends PVF with unknown code hashes to the validation host returning the list of code hashes sent. async fn prepare_pvfs_for_backed_candidates<Sender>( sender: &mut Sender, - mut validation_backend: impl ValidationBackend, + validation_backend: &mut impl ValidationBackend, relay_parent: Hash, already_prepared: &HashSet<ValidationCodeHash>, per_block_limit: usize, @@ -557,12 +570,21 @@ where async fn update_active_leaves<Sender>( sender: &mut Sender, - mut validation_backend: impl ValidationBackend, + validation_backend: &mut impl ValidationBackend, update: ActiveLeavesUpdate, -) where +) -> Option<SessionIndex> +where Sender: SubsystemSender<ChainApiMessage> + SubsystemSender<RuntimeApiMessage>, { - let ancestors = get_block_ancestors(sender, update.activated.as_ref().map(|x| x.hash)).await; + let maybe_new_leaf = if let Some(activated) = &update.activated { + get_session_index(sender, activated.hash) + .await + .map(|index| (activated.hash, index)) + } else { + None + }; + + let ancestors = get_block_ancestors(sender, maybe_new_leaf).await; if let Err(err) = validation_backend.update_active_leaves(update, ancestors).await { gum::warn!( target: LOG_TARGET, @@ -570,39 +592,33 @@ async fn update_active_leaves<Sender>( "cannot update active leaves in validation backend", ); }; -} -async fn get_allowed_ancestry_len<Sender>(sender: &mut Sender, relay_parent: Hash) -> Option<usize> -where - Sender: SubsystemSender<ChainApiMessage> + SubsystemSender<RuntimeApiMessage>, -{ - match prospective_parachains_mode(sender, relay_parent).await { - Ok(ProspectiveParachainsMode::Enabled { allowed_ancestry_len, .. }) => - Some(allowed_ancestry_len), - res => { - gum::warn!(target: LOG_TARGET, ?res, "async backing is disabled"); - None - }, - } + maybe_new_leaf.map(|l| l.1) } async fn get_block_ancestors<Sender>( sender: &mut Sender, - maybe_relay_parent: Option<Hash>, + maybe_new_leaf: Option<(Hash, SessionIndex)>, ) -> Vec<Hash> where Sender: SubsystemSender<ChainApiMessage> + SubsystemSender<RuntimeApiMessage>, { - let Some(relay_parent) = maybe_relay_parent else { return vec![] }; - let Some(allowed_ancestry_len) = get_allowed_ancestry_len(sender, relay_parent).await else { - return vec![] - }; + let Some((relay_parent, session_index)) = maybe_new_leaf else { return vec![] }; + let scheduling_lookahead = + match fetch_scheduling_lookahead(relay_parent, session_index, sender).await { + Ok(scheduling_lookahead) => scheduling_lookahead, + res => { + gum::warn!(target: LOG_TARGET, ?res, "Failed to request scheduling lookahead"); + return vec![] + }, + }; let (tx, rx) = oneshot::channel(); sender .send_message(ChainApiMessage::Ancestors { hash: relay_parent, - k: allowed_ancestry_len, + // Subtract 1 from the claim queue length, as it includes current `relay_parent`. + k: scheduling_lookahead.saturating_sub(1) as usize, response_channel: tx, }) .await; diff --git a/polkadot/node/core/candidate-validation/src/tests.rs b/polkadot/node/core/candidate-validation/src/tests.rs index 795d7c93f8a70ee939cf4580118efca3381f0d63..ee72daa1f86eb5988c9e8f0aa52549344621454b 100644 --- a/polkadot/node/core/candidate-validation/src/tests.rs +++ b/polkadot/node/core/candidate-validation/src/tests.rs @@ -26,6 +26,7 @@ use futures::executor; use polkadot_node_core_pvf::PrepareError; use polkadot_node_primitives::{BlockData, VALIDATION_CODE_BOMB_LIMIT}; use polkadot_node_subsystem::messages::AllMessages; +use polkadot_node_subsystem_test_helpers::{make_subsystem_context, TestSubsystemContextHandle}; use polkadot_node_subsystem_util::reexports::SubsystemContext; use polkadot_overseer::ActivatedLeaf; use polkadot_primitives::{ @@ -34,7 +35,7 @@ use polkadot_primitives::{ MutateDescriptorV2, UMPSignal, UMP_SEPARATOR, }, CandidateDescriptor, CoreIndex, GroupIndex, HeadData, Id as ParaId, OccupiedCoreAssumption, - SessionInfo, UpwardMessage, ValidatorId, + SessionInfo, UpwardMessage, ValidatorId, DEFAULT_SCHEDULING_LOOKAHEAD, }; use polkadot_primitives_test_helpers::{ dummy_collator, dummy_collator_signature, dummy_hash, make_valid_candidate_descriptor, @@ -119,10 +120,7 @@ fn correctly_checks_included_assumption() { .into(); let pool = TaskExecutor::new(); - let (mut ctx, mut ctx_handle) = polkadot_node_subsystem_test_helpers::make_subsystem_context::< - AllMessages, - _, - >(pool.clone()); + let (mut ctx, mut ctx_handle) = make_subsystem_context::<AllMessages, _>(pool.clone()); let (check_fut, check_result) = check_assumption_validation_data( ctx.sender(), @@ -194,10 +192,7 @@ fn correctly_checks_timed_out_assumption() { .into(); let pool = TaskExecutor::new(); - let (mut ctx, mut ctx_handle) = polkadot_node_subsystem_test_helpers::make_subsystem_context::< - AllMessages, - _, - >(pool.clone()); + let (mut ctx, mut ctx_handle) = make_subsystem_context::<AllMessages, _>(pool.clone()); let (check_fut, check_result) = check_assumption_validation_data( ctx.sender(), @@ -267,10 +262,7 @@ fn check_is_bad_request_if_no_validation_data() { .into(); let pool = TaskExecutor::new(); - let (mut ctx, mut ctx_handle) = polkadot_node_subsystem_test_helpers::make_subsystem_context::< - AllMessages, - _, - >(pool.clone()); + let (mut ctx, mut ctx_handle) = make_subsystem_context::<AllMessages, _>(pool.clone()); let (check_fut, check_result) = check_assumption_validation_data( ctx.sender(), @@ -324,10 +316,7 @@ fn check_is_bad_request_if_no_validation_code() { .into(); let pool = TaskExecutor::new(); - let (mut ctx, mut ctx_handle) = polkadot_node_subsystem_test_helpers::make_subsystem_context::< - AllMessages, - _, - >(pool.clone()); + let (mut ctx, mut ctx_handle) = make_subsystem_context::<AllMessages, _>(pool.clone()); let (check_fut, check_result) = check_assumption_validation_data( ctx.sender(), @@ -393,10 +382,7 @@ fn check_does_not_match() { .into(); let pool = TaskExecutor::new(); - let (mut ctx, mut ctx_handle) = polkadot_node_subsystem_test_helpers::make_subsystem_context::< - AllMessages, - _, - >(pool.clone()); + let (mut ctx, mut ctx_handle) = make_subsystem_context::<AllMessages, _>(pool.clone()); let (check_fut, check_result) = check_assumption_validation_data( ctx.sender(), @@ -1393,10 +1379,7 @@ fn candidate_validation_code_mismatch_is_invalid() { let candidate_receipt = CandidateReceipt { descriptor, commitments_hash: Hash::zero() }; let pool = TaskExecutor::new(); - let (_ctx, _ctx_handle) = polkadot_node_subsystem_test_helpers::make_subsystem_context::< - AllMessages, - _, - >(pool.clone()); + let (_ctx, _ctx_handle) = make_subsystem_context::<AllMessages, _>(pool.clone()); let v = executor::block_on(validate_candidate_exhaustive( Some(1), @@ -1524,10 +1507,7 @@ fn precheck_works() { let validation_code_hash = validation_code.hash(); let pool = TaskExecutor::new(); - let (mut ctx, mut ctx_handle) = polkadot_node_subsystem_test_helpers::make_subsystem_context::< - AllMessages, - _, - >(pool.clone()); + let (mut ctx, mut ctx_handle) = make_subsystem_context::<AllMessages, _>(pool.clone()); let (check_fut, check_result) = precheck_pvf( ctx.sender(), @@ -1584,10 +1564,7 @@ fn precheck_properly_classifies_outcomes() { let validation_code_hash = validation_code.hash(); let pool = TaskExecutor::new(); - let (mut ctx, mut ctx_handle) = - polkadot_node_subsystem_test_helpers::make_subsystem_context::<AllMessages, _>( - pool.clone(), - ); + let (mut ctx, mut ctx_handle) = make_subsystem_context::<AllMessages, _>(pool.clone()); let (check_fut, check_result) = precheck_pvf( ctx.sender(), @@ -1677,7 +1654,7 @@ impl ValidationBackend for MockHeadsUp { _update: ActiveLeavesUpdate, _ancestors: Vec<Hash>, ) -> Result<(), String> { - unreachable!() + Ok(()) } } @@ -1754,28 +1731,51 @@ fn dummy_session_info(keys: Vec<Public>) -> SessionInfo { } } +async fn assert_new_active_leaf_messages( + recv_handle: &mut TestSubsystemContextHandle<AllMessages>, + expected_session_index: SessionIndex, +) { + assert_matches!( + recv_handle.recv().await, + AllMessages::RuntimeApi(RuntimeApiMessage::Request(_, RuntimeApiRequest::SessionIndexForChild(tx))) => { + let _ = tx.send(Ok(expected_session_index)); + } + ); + + let lookahead_value = DEFAULT_SCHEDULING_LOOKAHEAD; + assert_matches!( + recv_handle.recv().await, + AllMessages::RuntimeApi(RuntimeApiMessage::Request(_, RuntimeApiRequest::SchedulingLookahead(index, tx))) => { + assert_eq!(index, expected_session_index); + let _ = tx.send(Ok(lookahead_value)); + } + ); + + assert_matches!( + recv_handle.recv().await, + AllMessages::ChainApi(ChainApiMessage::Ancestors {k, response_channel, ..}) => { + assert_eq!(k as u32, lookahead_value - 1); + let _ = response_channel.send(Ok((0..(lookahead_value - 1)).into_iter().map(|i| Hash::from_low_u64_be(i as u64)).collect())); + } + ); +} + #[test] fn maybe_prepare_validation_golden_path() { let pool = TaskExecutor::new(); - let (mut ctx, mut ctx_handle) = - polkadot_node_subsystem_test_helpers::make_subsystem_context::<AllMessages, _>(pool); + let (mut ctx, mut ctx_handle) = make_subsystem_context::<AllMessages, _>(pool); let keystore = alice_keystore(); - let backend = MockHeadsUp::default(); + let mut backend = MockHeadsUp::default(); let activated_hash = Hash::random(); let update = dummy_active_leaves_update(activated_hash); let mut state = PrepareValidationState::default(); let check_fut = - maybe_prepare_validation(ctx.sender(), keystore, backend.clone(), update, &mut state); + handle_active_leaves_update(ctx.sender(), keystore, &mut backend, update, &mut state); let test_fut = async move { - assert_matches!( - ctx_handle.recv().await, - AllMessages::RuntimeApi(RuntimeApiMessage::Request(_, RuntimeApiRequest::SessionIndexForChild(tx))) => { - let _ = tx.send(Ok(1)); - } - ); + assert_new_active_leaf_messages(&mut ctx_handle, 1).await; assert_matches!( ctx_handle.recv().await, @@ -1834,11 +1834,10 @@ fn maybe_prepare_validation_golden_path() { #[test] fn maybe_prepare_validation_checkes_authority_once_per_session() { let pool = TaskExecutor::new(); - let (mut ctx, mut ctx_handle) = - polkadot_node_subsystem_test_helpers::make_subsystem_context::<AllMessages, _>(pool); + let (mut ctx, mut ctx_handle) = make_subsystem_context::<AllMessages, _>(pool); let keystore = alice_keystore(); - let backend = MockHeadsUp::default(); + let mut backend = MockHeadsUp::default(); let activated_hash = Hash::random(); let update = dummy_active_leaves_update(activated_hash); let mut state = PrepareValidationState { @@ -1848,16 +1847,9 @@ fn maybe_prepare_validation_checkes_authority_once_per_session() { }; let check_fut = - maybe_prepare_validation(ctx.sender(), keystore, backend.clone(), update, &mut state); + handle_active_leaves_update(ctx.sender(), keystore, &mut backend, update, &mut state); - let test_fut = async move { - assert_matches!( - ctx_handle.recv().await, - AllMessages::RuntimeApi(RuntimeApiMessage::Request(_, RuntimeApiRequest::SessionIndexForChild(tx))) => { - let _ = tx.send(Ok(1)); - } - ); - }; + let test_fut = assert_new_active_leaf_messages(&mut ctx_handle, 1); let test_fut = future::join(test_fut, check_fut); executor::block_on(test_fut); @@ -1870,11 +1862,10 @@ fn maybe_prepare_validation_checkes_authority_once_per_session() { #[test] fn maybe_prepare_validation_resets_state_on_a_new_session() { let pool = TaskExecutor::new(); - let (mut ctx, mut ctx_handle) = - polkadot_node_subsystem_test_helpers::make_subsystem_context::<AllMessages, _>(pool); + let (mut ctx, mut ctx_handle) = make_subsystem_context::<AllMessages, _>(pool); let keystore = alice_keystore(); - let backend = MockHeadsUp::default(); + let mut backend = MockHeadsUp::default(); let activated_hash = Hash::random(); let update = dummy_active_leaves_update(activated_hash); let mut state = PrepareValidationState { @@ -1885,15 +1876,10 @@ fn maybe_prepare_validation_resets_state_on_a_new_session() { }; let check_fut = - maybe_prepare_validation(ctx.sender(), keystore, backend.clone(), update, &mut state); + handle_active_leaves_update(ctx.sender(), keystore, &mut backend, update, &mut state); let test_fut = async move { - assert_matches!( - ctx_handle.recv().await, - AllMessages::RuntimeApi(RuntimeApiMessage::Request(_, RuntimeApiRequest::SessionIndexForChild(tx))) => { - let _ = tx.send(Ok(2)); - } - ); + assert_new_active_leaf_messages(&mut ctx_handle, 2).await; assert_matches!( ctx_handle.recv().await, @@ -1923,26 +1909,18 @@ fn maybe_prepare_validation_resets_state_on_a_new_session() { #[test] fn maybe_prepare_validation_does_not_prepare_pvfs_if_no_new_session_and_not_a_validator() { let pool = TaskExecutor::new(); - let (mut ctx, mut ctx_handle) = - polkadot_node_subsystem_test_helpers::make_subsystem_context::<AllMessages, _>(pool); + let (mut ctx, mut ctx_handle) = make_subsystem_context::<AllMessages, _>(pool); let keystore = alice_keystore(); - let backend = MockHeadsUp::default(); + let mut backend = MockHeadsUp::default(); let activated_hash = Hash::random(); let update = dummy_active_leaves_update(activated_hash); let mut state = PrepareValidationState { session_index: Some(1), ..Default::default() }; let check_fut = - maybe_prepare_validation(ctx.sender(), keystore, backend.clone(), update, &mut state); + handle_active_leaves_update(ctx.sender(), keystore, &mut backend, update, &mut state); - let test_fut = async move { - assert_matches!( - ctx_handle.recv().await, - AllMessages::RuntimeApi(RuntimeApiMessage::Request(_, RuntimeApiRequest::SessionIndexForChild(tx))) => { - let _ = tx.send(Ok(1)); - } - ); - }; + let test_fut = assert_new_active_leaf_messages(&mut ctx_handle, 1); let test_fut = future::join(test_fut, check_fut); executor::block_on(test_fut); @@ -1955,11 +1933,10 @@ fn maybe_prepare_validation_does_not_prepare_pvfs_if_no_new_session_and_not_a_va #[test] fn maybe_prepare_validation_does_not_prepare_pvfs_if_no_new_session_but_a_validator() { let pool = TaskExecutor::new(); - let (mut ctx, mut ctx_handle) = - polkadot_node_subsystem_test_helpers::make_subsystem_context::<AllMessages, _>(pool); + let (mut ctx, mut ctx_handle) = make_subsystem_context::<AllMessages, _>(pool); let keystore = alice_keystore(); - let backend = MockHeadsUp::default(); + let mut backend = MockHeadsUp::default(); let activated_hash = Hash::random(); let update = dummy_active_leaves_update(activated_hash); let mut state = PrepareValidationState { @@ -1969,15 +1946,10 @@ fn maybe_prepare_validation_does_not_prepare_pvfs_if_no_new_session_but_a_valida }; let check_fut = - maybe_prepare_validation(ctx.sender(), keystore, backend.clone(), update, &mut state); + handle_active_leaves_update(ctx.sender(), keystore, &mut backend, update, &mut state); let test_fut = async move { - assert_matches!( - ctx_handle.recv().await, - AllMessages::RuntimeApi(RuntimeApiMessage::Request(_, RuntimeApiRequest::SessionIndexForChild(tx))) => { - let _ = tx.send(Ok(1)); - } - ); + assert_new_active_leaf_messages(&mut ctx_handle, 1).await; assert_matches!( ctx_handle.recv().await, @@ -2021,25 +1993,19 @@ fn maybe_prepare_validation_does_not_prepare_pvfs_if_no_new_session_but_a_valida #[test] fn maybe_prepare_validation_does_not_prepare_pvfs_if_not_a_validator_in_the_next_session() { let pool = TaskExecutor::new(); - let (mut ctx, mut ctx_handle) = - polkadot_node_subsystem_test_helpers::make_subsystem_context::<AllMessages, _>(pool); + let (mut ctx, mut ctx_handle) = make_subsystem_context::<AllMessages, _>(pool); let keystore = alice_keystore(); - let backend = MockHeadsUp::default(); + let mut backend = MockHeadsUp::default(); let activated_hash = Hash::random(); let update = dummy_active_leaves_update(activated_hash); let mut state = PrepareValidationState::default(); let check_fut = - maybe_prepare_validation(ctx.sender(), keystore, backend.clone(), update, &mut state); + handle_active_leaves_update(ctx.sender(), keystore, &mut backend, update, &mut state); let test_fut = async move { - assert_matches!( - ctx_handle.recv().await, - AllMessages::RuntimeApi(RuntimeApiMessage::Request(_, RuntimeApiRequest::SessionIndexForChild(tx))) => { - let _ = tx.send(Ok(1)); - } - ); + assert_new_active_leaf_messages(&mut ctx_handle, 1).await; assert_matches!( ctx_handle.recv().await, @@ -2068,25 +2034,19 @@ fn maybe_prepare_validation_does_not_prepare_pvfs_if_not_a_validator_in_the_next #[test] fn maybe_prepare_validation_does_not_prepare_pvfs_if_a_validator_in_the_current_session() { let pool = TaskExecutor::new(); - let (mut ctx, mut ctx_handle) = - polkadot_node_subsystem_test_helpers::make_subsystem_context::<AllMessages, _>(pool); + let (mut ctx, mut ctx_handle) = make_subsystem_context::<AllMessages, _>(pool); let keystore = alice_keystore(); - let backend = MockHeadsUp::default(); + let mut backend = MockHeadsUp::default(); let activated_hash = Hash::random(); let update = dummy_active_leaves_update(activated_hash); let mut state = PrepareValidationState::default(); let check_fut = - maybe_prepare_validation(ctx.sender(), keystore, backend.clone(), update, &mut state); + handle_active_leaves_update(ctx.sender(), keystore, &mut backend, update, &mut state); let test_fut = async move { - assert_matches!( - ctx_handle.recv().await, - AllMessages::RuntimeApi(RuntimeApiMessage::Request(_, RuntimeApiRequest::SessionIndexForChild(tx))) => { - let _ = tx.send(Ok(1)); - } - ); + assert_new_active_leaf_messages(&mut ctx_handle, 1).await; assert_matches!( ctx_handle.recv().await, @@ -2115,25 +2075,19 @@ fn maybe_prepare_validation_does_not_prepare_pvfs_if_a_validator_in_the_current_ #[test] fn maybe_prepare_validation_prepares_a_limited_number_of_pvfs() { let pool = TaskExecutor::new(); - let (mut ctx, mut ctx_handle) = - polkadot_node_subsystem_test_helpers::make_subsystem_context::<AllMessages, _>(pool); + let (mut ctx, mut ctx_handle) = make_subsystem_context::<AllMessages, _>(pool); let keystore = alice_keystore(); - let backend = MockHeadsUp::default(); + let mut backend = MockHeadsUp::default(); let activated_hash = Hash::random(); let update = dummy_active_leaves_update(activated_hash); let mut state = PrepareValidationState { per_block_limit: 2, ..Default::default() }; let check_fut = - maybe_prepare_validation(ctx.sender(), keystore, backend.clone(), update, &mut state); + handle_active_leaves_update(ctx.sender(), keystore, &mut backend, update, &mut state); let test_fut = async move { - assert_matches!( - ctx_handle.recv().await, - AllMessages::RuntimeApi(RuntimeApiMessage::Request(_, RuntimeApiRequest::SessionIndexForChild(tx))) => { - let _ = tx.send(Ok(1)); - } - ); + assert_new_active_leaf_messages(&mut ctx_handle, 1).await; assert_matches!( ctx_handle.recv().await, @@ -2206,11 +2160,10 @@ fn maybe_prepare_validation_prepares_a_limited_number_of_pvfs() { #[test] fn maybe_prepare_validation_does_not_prepare_already_prepared_pvfs() { let pool = TaskExecutor::new(); - let (mut ctx, mut ctx_handle) = - polkadot_node_subsystem_test_helpers::make_subsystem_context::<AllMessages, _>(pool); + let (mut ctx, mut ctx_handle) = make_subsystem_context::<AllMessages, _>(pool); let keystore = alice_keystore(); - let backend = MockHeadsUp::default(); + let mut backend = MockHeadsUp::default(); let activated_hash = Hash::random(); let update = dummy_active_leaves_update(activated_hash); let mut state = PrepareValidationState { @@ -2224,15 +2177,10 @@ fn maybe_prepare_validation_does_not_prepare_already_prepared_pvfs() { }; let check_fut = - maybe_prepare_validation(ctx.sender(), keystore, backend.clone(), update, &mut state); + handle_active_leaves_update(ctx.sender(), keystore, &mut backend, update, &mut state); let test_fut = async move { - assert_matches!( - ctx_handle.recv().await, - AllMessages::RuntimeApi(RuntimeApiMessage::Request(_, RuntimeApiRequest::SessionIndexForChild(tx))) => { - let _ = tx.send(Ok(1)); - } - ); + assert_new_active_leaf_messages(&mut ctx_handle, 1).await; assert_matches!( ctx_handle.recv().await, diff --git a/polkadot/node/core/prospective-parachains/src/fragment_chain/mod.rs b/polkadot/node/core/prospective-parachains/src/fragment_chain/mod.rs index 72a76537160d7ac58d250193d9a82ece619031e0..d92c98623823d1baebdef6a890eacc8f271362dc 100644 --- a/polkadot/node/core/prospective-parachains/src/fragment_chain/mod.rs +++ b/polkadot/node/core/prospective-parachains/src/fragment_chain/mod.rs @@ -32,7 +32,7 @@ //! The best chain contains all the candidates pending availability and a subsequent chain //! of candidates that have reached the backing quorum and are better than any other backable forks //! according to the fork selection rule (more on this rule later). It has a length of size at most -//! `max_candidate_depth + 1`. +//! `num_of_pending_candidates + num_of_assigned_cores_for_para`. //! //! The unconnected storage keeps a record of seconded/backable candidates that may be //! added to the best chain in the future. @@ -100,13 +100,10 @@ //! bounded. This means that higher-level code needs to be selective about limiting the amount of //! candidates that are considered. //! -//! Practically speaking, the collator-protocol will not allow more than `max_candidate_depth + 1` -//! collations to be fetched at a relay parent and statement-distribution will not allow more than -//! `max_candidate_depth + 1` seconded candidates at a relay parent per each validator in the -//! backing group. Considering the `allowed_ancestry_len` configuration value, the number of -//! candidates in a `FragmentChain` (including its unconnected storage) should not exceed: -//! -//! `allowed_ancestry_len * (max_candidate_depth + 1) * backing_group_size`. +//! Practically speaking, the collator-protocol will limit the number of fetched collations per +//! core, to the number of claim queue assignments for the paraid on that core. +//! Statement-distribution will not allow more than `scheduler_params.lookahead` seconded candidates +//! at a relay parent per each validator in the backing group. //! //! The code in this module is not designed for speed or efficiency, but conceptual simplicity. //! Our assumption is that the amount of candidates and parachains we consider will be reasonably @@ -453,8 +450,8 @@ pub(crate) struct Scope { pending_availability: Vec<PendingAvailability>, /// The base constraints derived from the latest included candidate. base_constraints: Constraints, - /// Equal to `max_candidate_depth`. - max_depth: usize, + /// Maximum length of the best backable chain (including candidates pending availability). + max_backable_len: usize, } /// An error variant indicating that ancestors provided to a scope @@ -474,7 +471,8 @@ pub(crate) struct UnexpectedAncestor { impl Scope { /// Define a new [`Scope`]. /// - /// All arguments are straightforward except the ancestors. + /// `max_backable_len` should be the maximum length of the best backable chain (excluding + /// pending availability candidates). /// /// Ancestors should be in reverse order, starting with the parent /// of the `relay_parent`, and proceeding backwards in block number @@ -492,7 +490,7 @@ impl Scope { relay_parent: RelayChainBlockInfo, base_constraints: Constraints, pending_availability: Vec<PendingAvailability>, - max_depth: usize, + max_backable_len: usize, ancestors: impl IntoIterator<Item = RelayChainBlockInfo>, ) -> Result<Self, UnexpectedAncestor> { let mut ancestors_map = BTreeMap::new(); @@ -517,8 +515,8 @@ impl Scope { Ok(Scope { relay_parent, base_constraints, + max_backable_len: max_backable_len + pending_availability.len(), pending_availability, - max_depth, ancestors: ancestors_map, ancestors_by_hash, }) @@ -1192,7 +1190,7 @@ impl FragmentChain { let Some(mut earliest_rp) = self.earliest_relay_parent() else { return }; loop { - if self.best_chain.chain.len() > self.scope.max_depth { + if self.best_chain.chain.len() >= self.scope.max_backable_len { break; } diff --git a/polkadot/node/core/prospective-parachains/src/fragment_chain/tests.rs b/polkadot/node/core/prospective-parachains/src/fragment_chain/tests.rs index 9e7e570bd16f94b7cbdb3b0ba454ff4f983eb8f4..6bda09ecc26d4cf215b093516fcdb8f6cf112952 100644 --- a/polkadot/node/core/prospective-parachains/src/fragment_chain/tests.rs +++ b/polkadot/node/core/prospective-parachains/src/fragment_chain/tests.rs @@ -116,7 +116,7 @@ fn scope_rejects_ancestors_that_skip_blocks() { storage_root: Hash::repeat_byte(69), }]; - let max_depth = 2; + let max_depth = 3; let base_constraints = make_constraints(8, vec![8, 9], vec![1, 2, 3].into()); let pending_availability = Vec::new(); @@ -146,7 +146,7 @@ fn scope_rejects_ancestor_for_0_block() { storage_root: Hash::repeat_byte(69), }]; - let max_depth = 2; + let max_depth = 3; let base_constraints = make_constraints(0, vec![], vec![1, 2, 3].into()); let pending_availability = Vec::new(); @@ -188,7 +188,7 @@ fn scope_only_takes_ancestors_up_to_min() { }, ]; - let max_depth = 2; + let max_depth = 3; let base_constraints = make_constraints(3, vec![2], vec![1, 2, 3].into()); let pending_availability = Vec::new(); @@ -231,7 +231,7 @@ fn scope_rejects_unordered_ancestors() { }, ]; - let max_depth = 2; + let max_depth = 3; let base_constraints = make_constraints(0, vec![2], vec![1, 2, 3].into()); let pending_availability = Vec::new(); @@ -497,7 +497,7 @@ fn test_populate_and_check_potential() { relay_parent_z_info.clone(), wrong_constraints.clone(), vec![], - 4, + 5, ancestors.clone(), ) .unwrap(); @@ -530,7 +530,7 @@ fn test_populate_and_check_potential() { // Various depths { - // Depth is 0, only allows one candidate, but the others will be kept as potential. + // Depth is 0, doesn't allow any candidate, but the others will be kept as potential. let scope = Scope::with_ancestors( relay_parent_z_info.clone(), base_constraints.clone(), @@ -544,6 +544,27 @@ fn test_populate_and_check_potential() { assert!(chain.can_add_candidate_as_potential(&candidate_b_entry).is_ok()); assert!(chain.can_add_candidate_as_potential(&candidate_c_entry).is_ok()); + let chain = populate_chain_from_previous_storage(&scope, &storage); + assert!(chain.best_chain_vec().is_empty()); + assert_eq!( + chain.unconnected().map(|c| c.candidate_hash).collect::<HashSet<_>>(), + [candidate_a_hash, candidate_b_hash, candidate_c_hash].into_iter().collect() + ); + + // Depth is 1, only allows one candidate, but the others will be kept as potential. + let scope = Scope::with_ancestors( + relay_parent_z_info.clone(), + base_constraints.clone(), + vec![], + 1, + ancestors.clone(), + ) + .unwrap(); + let chain = FragmentChain::init(scope.clone(), CandidateStorage::default()); + assert!(chain.can_add_candidate_as_potential(&candidate_a_entry).is_ok()); + assert!(chain.can_add_candidate_as_potential(&candidate_b_entry).is_ok()); + assert!(chain.can_add_candidate_as_potential(&candidate_c_entry).is_ok()); + let chain = populate_chain_from_previous_storage(&scope, &storage); assert_eq!(chain.best_chain_vec(), vec![candidate_a_hash]); assert_eq!( @@ -551,12 +572,12 @@ fn test_populate_and_check_potential() { [candidate_b_hash, candidate_c_hash].into_iter().collect() ); - // depth is 1, allows two candidates + // depth is 2, allows two candidates let scope = Scope::with_ancestors( relay_parent_z_info.clone(), base_constraints.clone(), vec![], - 1, + 2, ancestors.clone(), ) .unwrap(); @@ -572,8 +593,8 @@ fn test_populate_and_check_potential() { [candidate_c_hash].into_iter().collect() ); - // depth is larger than 2, allows all three candidates - for depth in 2..6 { + // depth is at least 3, allows all three candidates + for depth in 3..6 { let scope = Scope::with_ancestors( relay_parent_z_info.clone(), base_constraints.clone(), @@ -605,7 +626,7 @@ fn test_populate_and_check_potential() { relay_parent_z_info.clone(), base_constraints.clone(), vec![], - 4, + 5, ancestors_without_x, ) .unwrap(); @@ -628,7 +649,7 @@ fn test_populate_and_check_potential() { relay_parent_z_info.clone(), base_constraints.clone(), vec![], - 4, + 5, vec![], ) .unwrap(); @@ -674,7 +695,7 @@ fn test_populate_and_check_potential() { relay_parent_z_info.clone(), base_constraints.clone(), vec![], - 4, + 5, ancestors.clone(), ) .unwrap(); @@ -716,7 +737,7 @@ fn test_populate_and_check_potential() { relay_parent_z_info.clone(), base_constraints.clone(), vec![], - 4, + 5, ancestors.clone(), ) .unwrap(); @@ -758,7 +779,7 @@ fn test_populate_and_check_potential() { relay_parent_z_info.clone(), base_constraints.clone(), vec![], - 4, + 5, ancestors.clone(), ) .unwrap(); @@ -987,7 +1008,7 @@ fn test_populate_and_check_potential() { relay_parent_z_info.clone(), base_constraints.clone(), vec![], - 2, + 3, ancestors.clone(), ) .unwrap(); @@ -1302,7 +1323,7 @@ fn test_populate_and_check_potential() { relay_parent: relay_parent_z_info.clone(), }, ], - 2, + 0, ancestors.clone(), ) .unwrap(); @@ -1327,7 +1348,7 @@ fn test_populate_and_check_potential() { relay_parent_z_info.clone(), base_constraints.clone(), vec![], - 2, + 3, ancestors.clone(), ) .unwrap(); @@ -1356,7 +1377,7 @@ fn test_populate_and_check_potential() { fn test_find_ancestor_path_and_find_backable_chain_empty_best_chain() { let relay_parent = Hash::repeat_byte(1); let required_parent: HeadData = vec![0xff].into(); - let max_depth = 10; + let max_depth = 11; // Empty chain let base_constraints = make_constraints(0, vec![0], required_parent.clone()); @@ -1383,7 +1404,7 @@ fn test_find_ancestor_path_and_find_backable_chain() { let para_id = ParaId::from(5u32); let relay_parent = Hash::repeat_byte(1); let required_parent: HeadData = vec![0xff].into(); - let max_depth = 5; + let max_depth = 6; let relay_parent_number = 0; let relay_parent_storage_root = Hash::zero(); @@ -1568,7 +1589,7 @@ fn test_find_ancestor_path_and_find_backable_chain() { candidate_hash: candidates[3], relay_parent: relay_parent_info, }], - max_depth, + max_depth - 1, vec![], ) .unwrap(); diff --git a/polkadot/node/core/prospective-parachains/src/lib.rs b/polkadot/node/core/prospective-parachains/src/lib.rs index 7416c97f3cd0251186aef8f043d09e7188148261..9b2006ee988a256c7b74aa51cb21ee88daf3f336 100644 --- a/polkadot/node/core/prospective-parachains/src/lib.rs +++ b/polkadot/node/core/prospective-parachains/src/lib.rs @@ -28,7 +28,7 @@ #![deny(unused_crate_dependencies)] -use std::collections::{HashMap, HashSet}; +use std::collections::{BTreeSet, HashMap, HashSet}; use fragment_chain::CandidateStorage; use futures::{channel::oneshot, prelude::*}; @@ -47,10 +47,10 @@ use polkadot_node_subsystem_util::{ inclusion_emulator::{Constraints, RelayChainBlockInfo}, request_backing_constraints, request_candidates_pending_availability, request_session_index_for_child, - runtime::{fetch_claim_queue, prospective_parachains_mode, ProspectiveParachainsMode}, + runtime::{fetch_claim_queue, fetch_scheduling_lookahead}, }; use polkadot_primitives::{ - vstaging::{CommittedCandidateReceiptV2 as CommittedCandidateReceipt, CoreState}, + vstaging::{transpose_claim_queue, CommittedCandidateReceiptV2 as CommittedCandidateReceipt}, BlockNumber, CandidateHash, Hash, Header, Id as ParaId, PersistedValidationData, }; @@ -212,23 +212,8 @@ async fn handle_active_leaves_update<Context>( let hash = activated.hash; - let mode = prospective_parachains_mode(ctx.sender(), hash) - .await - .map_err(JfyiError::Runtime)?; - - let ProspectiveParachainsMode::Enabled { max_candidate_depth, allowed_ancestry_len } = mode - else { - gum::trace!( - target: LOG_TARGET, - block_hash = ?hash, - "Skipping leaf activation since async backing is disabled" - ); - - // Not a part of any allowed ancestry. - return Ok(()) - }; - - let scheduled_paras = fetch_upcoming_paras(ctx, hash).await?; + let transposed_claim_queue = + transpose_claim_queue(fetch_claim_queue(ctx.sender(), hash).await?.0); let block_info = match fetch_block_info(ctx, &mut temp_header_cache, hash).await? { None => { @@ -246,17 +231,26 @@ async fn handle_active_leaves_update<Context>( Some(info) => info, }; + let session_index = request_session_index_for_child(hash, ctx.sender()) + .await + .await + .map_err(JfyiError::RuntimeApiRequestCanceled)??; + let ancestry_len = fetch_scheduling_lookahead(hash, session_index, ctx.sender()) + .await? + .saturating_sub(1); + let ancestry = - fetch_ancestry(ctx, &mut temp_header_cache, hash, allowed_ancestry_len).await?; + fetch_ancestry(ctx, &mut temp_header_cache, hash, ancestry_len as usize, session_index) + .await?; let prev_fragment_chains = ancestry.first().and_then(|prev_leaf| view.get_fragment_chains(&prev_leaf.hash)); let mut fragment_chains = HashMap::new(); - for para in scheduled_paras { + for (para, claims_by_depth) in transposed_claim_queue.iter() { // Find constraints and pending availability candidates. let Some((constraints, pending_availability)) = - fetch_backing_constraints_and_candidates(ctx, hash, para).await? + fetch_backing_constraints_and_candidates(ctx, hash, *para).await? else { // This indicates a runtime conflict of some kind. gum::debug!( @@ -306,11 +300,13 @@ async fn handle_active_leaves_update<Context>( compact_pending.push(c.compact); } + let max_backable_chain_len = + claims_by_depth.values().flatten().collect::<BTreeSet<_>>().len(); let scope = match FragmentChainScope::with_ancestors( block_info.clone().into(), constraints, compact_pending, - max_candidate_depth, + max_backable_chain_len, ancestry .iter() .map(|a| RelayChainBlockInfo::from(a.clone())) @@ -321,7 +317,7 @@ async fn handle_active_leaves_update<Context>( gum::warn!( target: LOG_TARGET, para_id = ?para, - max_candidate_depth, + max_backable_chain_len, ?ancestry, leaf = ?hash, "Relay chain ancestors have wrong order: {:?}", @@ -335,6 +331,7 @@ async fn handle_active_leaves_update<Context>( target: LOG_TARGET, relay_parent = ?hash, min_relay_parent = scope.earliest_relay_parent().number, + max_backable_chain_len, para_id = ?para, ancestors = ?ancestry, "Creating fragment chain" @@ -359,7 +356,7 @@ async fn handle_active_leaves_update<Context>( // If we know the previous fragment chain, use that for further populating the fragment // chain. if let Some(prev_fragment_chain) = - prev_fragment_chains.and_then(|chains| chains.get(¶)) + prev_fragment_chains.and_then(|chains| chains.get(para)) { chain.populate_from_previous(prev_fragment_chain); } @@ -381,7 +378,7 @@ async fn handle_active_leaves_update<Context>( chain.unconnected().map(|candidate| candidate.hash()).collect::<Vec<_>>() ); - fragment_chains.insert(para, chain); + fragment_chains.insert(*para, chain); } view.per_relay_parent.insert(hash, RelayBlockViewData { fragment_chains }); @@ -950,57 +947,6 @@ async fn fetch_backing_constraints_and_candidates_inner<Context>( Ok(Some((From::from(constraints), pending_availability))) } -#[overseer::contextbounds(ProspectiveParachains, prefix = self::overseer)] -async fn fetch_upcoming_paras<Context>( - ctx: &mut Context, - relay_parent: Hash, -) -> JfyiErrorResult<HashSet<ParaId>> { - Ok(match fetch_claim_queue(ctx.sender(), relay_parent).await? { - Some(claim_queue) => { - // Runtime supports claim queue - use it - claim_queue - .iter_all_claims() - .flat_map(|(_, paras)| paras.into_iter()) - .copied() - .collect() - }, - None => { - // fallback to availability cores - remove this branch once claim queue is released - // everywhere - let (tx, rx) = oneshot::channel(); - ctx.send_message(RuntimeApiMessage::Request( - relay_parent, - RuntimeApiRequest::AvailabilityCores(tx), - )) - .await; - - let cores = rx.await.map_err(JfyiError::RuntimeApiRequestCanceled)??; - - let mut upcoming = HashSet::with_capacity(cores.len()); - for core in cores { - match core { - CoreState::Occupied(occupied) => { - // core sharing won't work optimally with this branch because the collations - // can't be prepared in advance. - if let Some(next_up_on_available) = occupied.next_up_on_available { - upcoming.insert(next_up_on_available.para_id); - } - if let Some(next_up_on_time_out) = occupied.next_up_on_time_out { - upcoming.insert(next_up_on_time_out.para_id); - } - }, - CoreState::Scheduled(scheduled) => { - upcoming.insert(scheduled.para_id); - }, - CoreState::Free => {}, - } - } - - upcoming - }, - }) -} - // Fetch ancestors in descending order, up to the amount requested. #[overseer::contextbounds(ProspectiveParachains, prefix = self::overseer)] async fn fetch_ancestry<Context>( @@ -1008,6 +954,7 @@ async fn fetch_ancestry<Context>( cache: &mut HashMap<Hash, Header>, relay_hash: Hash, ancestors: usize, + required_session: u32, ) -> JfyiErrorResult<Vec<BlockInfo>> { if ancestors == 0 { return Ok(Vec::new()) @@ -1022,10 +969,6 @@ async fn fetch_ancestry<Context>( .await; let hashes = rx.map_err(JfyiError::ChainApiRequestCanceled).await??; - let required_session = request_session_index_for_child(relay_hash, ctx.sender()) - .await - .await - .map_err(JfyiError::RuntimeApiRequestCanceled)??; let mut block_info = Vec::with_capacity(hashes.len()); for hash in hashes { diff --git a/polkadot/node/core/prospective-parachains/src/tests.rs b/polkadot/node/core/prospective-parachains/src/tests.rs index 5d1ef2f2f51cbeba95368e2f6767c11678817bb5..0900a3ee890005d84c25f14d4caafc9c5c8eb551 100644 --- a/polkadot/node/core/prospective-parachains/src/tests.rs +++ b/polkadot/node/core/prospective-parachains/src/tests.rs @@ -17,20 +17,21 @@ use super::*; use assert_matches::assert_matches; use polkadot_node_subsystem::{ - errors::RuntimeApiError, messages::{ AllMessages, HypotheticalMembershipRequest, ParentHeadData, ProspectiveParachainsMessage, ProspectiveValidationDataRequest, }, + RuntimeApiError, }; use polkadot_node_subsystem_test_helpers as test_helpers; use polkadot_primitives::{ - async_backing::{AsyncBackingParams, Constraints, InboundHrmpLimitations}, + async_backing::{Constraints, InboundHrmpLimitations}, vstaging::{ async_backing::{BackingState, CandidatePendingAvailability, Constraints as ConstraintsV2}, CommittedCandidateReceiptV2 as CommittedCandidateReceipt, MutateDescriptorV2, }, - CoreIndex, HeadData, Header, PersistedValidationData, ScheduledCore, ValidationCodeHash, + CoreIndex, HeadData, Header, PersistedValidationData, ValidationCodeHash, + DEFAULT_SCHEDULING_LOOKAHEAD, }; use polkadot_primitives_test_helpers::make_candidate; use rstest::rstest; @@ -40,10 +41,6 @@ use std::{ }; use test_helpers::mock::new_leaf; -const ALLOWED_ANCESTRY_LEN: u32 = 3; -const ASYNC_BACKING_PARAMETERS: AsyncBackingParams = - AsyncBackingParams { max_candidate_depth: 4, allowed_ancestry_len: ALLOWED_ANCESTRY_LEN }; - const RUNTIME_API_NOT_SUPPORTED: RuntimeApiError = RuntimeApiError::NotSupported { runtime_api_name: "test-runtime" }; @@ -113,15 +110,21 @@ impl Default for TestState { let chain_b = ParaId::from(2); let mut claim_queue = BTreeMap::new(); - claim_queue.insert(CoreIndex(0), [chain_a].into_iter().collect()); - claim_queue.insert(CoreIndex(1), [chain_b].into_iter().collect()); + claim_queue.insert( + CoreIndex(0), + std::iter::repeat(chain_a).take(DEFAULT_SCHEDULING_LOOKAHEAD as _).collect(), + ); + claim_queue.insert( + CoreIndex(1), + std::iter::repeat(chain_b).take(DEFAULT_SCHEDULING_LOOKAHEAD as _).collect(), + ); let validation_code_hash = Hash::repeat_byte(42).into(); Self { validation_code_hash, claim_queue, - runtime_api_version: RuntimeApiRequest::CLAIM_QUEUE_RUNTIME_REQUIREMENT, + runtime_api_version: RuntimeApiRequest::CONSTRAINTS_RUNTIME_REQUIREMENT, } } } @@ -229,15 +232,6 @@ async fn activate_leaf( virtual_overseer: &mut VirtualOverseer, leaf: &TestLeaf, test_state: &TestState, -) { - activate_leaf_with_params(virtual_overseer, leaf, test_state, ASYNC_BACKING_PARAMETERS).await; -} - -async fn activate_leaf_with_parent_hash_fn( - virtual_overseer: &mut VirtualOverseer, - leaf: &TestLeaf, - test_state: &TestState, - parent_hash_fn: impl Fn(Hash) -> Hash, ) { let TestLeaf { number, hash, .. } = leaf; @@ -249,21 +243,14 @@ async fn activate_leaf_with_parent_hash_fn( )))) .await; - handle_leaf_activation( - virtual_overseer, - leaf, - test_state, - ASYNC_BACKING_PARAMETERS, - parent_hash_fn, - ) - .await; + handle_leaf_activation(virtual_overseer, leaf, test_state, get_parent_hash).await; } -async fn activate_leaf_with_params( +async fn activate_leaf_with_parent_hash_fn( virtual_overseer: &mut VirtualOverseer, leaf: &TestLeaf, test_state: &TestState, - async_backing_params: AsyncBackingParams, + parent_hash_fn: impl Fn(Hash) -> Hash, ) { let TestLeaf { number, hash, .. } = leaf; @@ -275,21 +262,13 @@ async fn activate_leaf_with_params( )))) .await; - handle_leaf_activation( - virtual_overseer, - leaf, - test_state, - async_backing_params, - get_parent_hash, - ) - .await; + handle_leaf_activation(virtual_overseer, leaf, test_state, parent_hash_fn).await; } async fn handle_leaf_activation( virtual_overseer: &mut VirtualOverseer, leaf: &TestLeaf, test_state: &TestState, - async_backing_params: AsyncBackingParams, parent_hash_fn: impl Fn(Hash) -> Hash, ) { let TestLeaf { number, hash, para_data } = leaf; @@ -297,49 +276,31 @@ async fn handle_leaf_activation( assert_matches!( virtual_overseer.recv().await, AllMessages::RuntimeApi( - RuntimeApiMessage::Request(parent, RuntimeApiRequest::AsyncBackingParams(tx)) + RuntimeApiMessage::Request(parent, RuntimeApiRequest::ClaimQueue(tx)) ) if parent == *hash => { - tx.send(Ok(async_backing_params)).unwrap(); + tx.send(Ok(test_state.claim_queue.clone())).unwrap(); } ); + send_block_header(virtual_overseer, *hash, *number).await; + assert_matches!( virtual_overseer.recv().await, AllMessages::RuntimeApi( - RuntimeApiMessage::Request(parent, RuntimeApiRequest::Version(tx)) + RuntimeApiMessage::Request(parent, RuntimeApiRequest::SessionIndexForChild(tx)) ) if parent == *hash => { - tx.send( - Ok(test_state.runtime_api_version) - ).unwrap(); + tx.send(Ok(1)).unwrap(); } ); - if test_state.runtime_api_version < RuntimeApiRequest::CLAIM_QUEUE_RUNTIME_REQUIREMENT { - assert_matches!( - virtual_overseer.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(parent, RuntimeApiRequest::AvailabilityCores(tx)) - ) if parent == *hash => { - tx.send(Ok(test_state.claim_queue.values().map(|paras| CoreState::Scheduled( - ScheduledCore { - para_id: *paras.front().unwrap(), - collator: None - } - )).collect())).unwrap(); - } - ); - } else { - assert_matches!( - virtual_overseer.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(parent, RuntimeApiRequest::ClaimQueue(tx)) - ) if parent == *hash => { - tx.send(Ok(test_state.claim_queue.clone())).unwrap(); - } - ); - } - - send_block_header(virtual_overseer, *hash, *number).await; + assert_matches!( + virtual_overseer.recv().await, + AllMessages::RuntimeApi( + RuntimeApiMessage::Request(parent, RuntimeApiRequest::SchedulingLookahead(session_index, tx)) + ) if parent == *hash && session_index == 1 => { + tx.send(Ok(DEFAULT_SCHEDULING_LOOKAHEAD)).unwrap(); + } + ); // Check that subsystem job issues a request for ancestors. let min_min = para_data.iter().map(|(_, data)| data.min_relay_parent).min().unwrap_or(*number); @@ -356,19 +317,10 @@ async fn handle_leaf_activation( virtual_overseer.recv().await, AllMessages::ChainApi( ChainApiMessage::Ancestors{hash: block_hash, k, response_channel: tx} - ) if block_hash == *hash && k == ALLOWED_ANCESTRY_LEN as usize => { + ) if block_hash == *hash && k == (DEFAULT_SCHEDULING_LOOKAHEAD - 1) as usize => { tx.send(Ok(ancestry_hashes.clone())).unwrap(); } ); - - assert_matches!( - virtual_overseer.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(parent, RuntimeApiRequest::SessionIndexForChild(tx)) - ) if parent == *hash => { - tx.send(Ok(1)).unwrap(); - } - ); } let mut used_relay_parents = HashSet::new(); @@ -653,37 +605,6 @@ macro_rules! make_and_back_candidate { }}; } -#[test] -fn should_do_no_work_if_async_backing_disabled_for_leaf() { - async fn activate_leaf_async_backing_disabled(virtual_overseer: &mut VirtualOverseer) { - let hash = Hash::from_low_u64_be(130); - - // Start work on some new parent. - virtual_overseer - .send(FromOrchestra::Signal(OverseerSignal::ActiveLeaves( - ActiveLeavesUpdate::start_work(new_leaf(hash, 1)), - ))) - .await; - - assert_matches!( - virtual_overseer.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(parent, RuntimeApiRequest::AsyncBackingParams(tx)) - ) if parent == hash => { - tx.send(Err(RUNTIME_API_NOT_SUPPORTED)).unwrap(); - } - ); - } - - let view = test_harness(|mut virtual_overseer| async move { - activate_leaf_async_backing_disabled(&mut virtual_overseer).await; - - virtual_overseer - }); - - assert!(view.active_leaves.is_empty()); -} - // Send some candidates and make sure all are found: // - Two for the same leaf A (one for parachain 1 and one for parachain 2) // - One for leaf B on parachain 1 @@ -869,6 +790,10 @@ fn introduce_candidates_basic(#[case] runtime_api_version: u32) { fn introduce_candidates_error(#[case] runtime_api_version: u32) { let mut test_state = TestState::default(); test_state.set_runtime_api_version(runtime_api_version); + test_state.claim_queue.insert( + CoreIndex(2), + std::iter::repeat(1.into()).take(DEFAULT_SCHEDULING_LOOKAHEAD as _).collect(), + ); let view = test_harness(|mut virtual_overseer| async move { // Leaf A @@ -882,13 +807,7 @@ fn introduce_candidates_error(#[case] runtime_api_version: u32) { }; // Activate leaves. - activate_leaf_with_params( - &mut virtual_overseer, - &leaf_a, - &test_state, - AsyncBackingParams { allowed_ancestry_len: 3, max_candidate_depth: 1 }, - ) - .await; + activate_leaf(&mut virtual_overseer, &leaf_a, &test_state).await; // Candidate A. let (candidate_a, pvd_a) = make_candidate( @@ -1054,7 +973,11 @@ fn introduce_candidate_multiple_times(#[case] runtime_api_version: u32) { #[test] fn fragment_chain_best_chain_length_is_bounded() { - let test_state = TestState::default(); + let mut test_state = TestState::default(); + test_state.claim_queue.insert( + CoreIndex(2), + std::iter::repeat(1.into()).take(DEFAULT_SCHEDULING_LOOKAHEAD as _).collect(), + ); let view = test_harness(|mut virtual_overseer| async move { // Leaf A let leaf_a = TestLeaf { @@ -1066,13 +989,7 @@ fn fragment_chain_best_chain_length_is_bounded() { ], }; // Activate leaves. - activate_leaf_with_params( - &mut virtual_overseer, - &leaf_a, - &test_state, - AsyncBackingParams { max_candidate_depth: 1, allowed_ancestry_len: 3 }, - ) - .await; + activate_leaf(&mut virtual_overseer, &leaf_a, &test_state).await; // Candidates A, B and C form a chain. let (candidate_a, pvd_a) = make_candidate( @@ -1100,7 +1017,7 @@ fn fragment_chain_best_chain_length_is_bounded() { test_state.validation_code_hash, ); - // Introduce candidates A and B. Since max depth is 1, only these two will be allowed. + // Introduce candidates A and B. Since max depth is 2, only these two will be allowed. introduce_seconded_candidate(&mut virtual_overseer, candidate_a.clone(), pvd_a).await; introduce_seconded_candidate(&mut virtual_overseer, candidate_b.clone(), pvd_b).await; @@ -1447,6 +1364,13 @@ fn unconnected_candidates_become_connected(#[case] runtime_api_version: u32) { // This doesn't test all the complicated cases with many unconnected candidates, as it's more // extensively tested in the `fragment_chain::tests` module. let mut test_state = TestState::default(); + for i in 2..=4 { + test_state.claim_queue.insert( + CoreIndex(i), + std::iter::repeat(1.into()).take(DEFAULT_SCHEDULING_LOOKAHEAD as _).collect(), + ); + } + test_state.set_runtime_api_version(runtime_api_version); let view = test_harness(|mut virtual_overseer| async move { // Leaf A @@ -1547,7 +1471,11 @@ fn unconnected_candidates_become_connected(#[case] runtime_api_version: u32) { // Backs some candidates and tests `GetBackableCandidates` when requesting a single candidate. #[test] fn check_backable_query_single_candidate() { - let test_state = TestState::default(); + let mut test_state = TestState::default(); + test_state.claim_queue.insert( + CoreIndex(2), + std::iter::repeat(1.into()).take(DEFAULT_SCHEDULING_LOOKAHEAD as _).collect(), + ); let view = test_harness(|mut virtual_overseer| async move { // Leaf A let leaf_a = TestLeaf { @@ -1688,11 +1616,20 @@ fn check_backable_query_single_candidate() { #[rstest] #[case(RuntimeApiRequest::CONSTRAINTS_RUNTIME_REQUIREMENT)] #[case(RuntimeApiRequest::CLAIM_QUEUE_RUNTIME_REQUIREMENT)] + fn check_backable_query_multiple_candidates(#[case] runtime_api_version: u32) { // This doesn't test all the complicated cases with many unconnected candidates, as it's more // extensively tested in the `fragment_chain::tests` module. let mut test_state = TestState::default(); test_state.set_runtime_api_version(runtime_api_version); + // Add three more cores for para A, so that we can get a chain of max length 4 + for i in 2..=4 { + test_state.claim_queue.insert( + CoreIndex(i), + std::iter::repeat(1.into()).take(DEFAULT_SCHEDULING_LOOKAHEAD as _).collect(), + ); + } + let view = test_harness(|mut virtual_overseer| async move { // Leaf A let leaf_a = TestLeaf { @@ -1990,20 +1927,8 @@ fn check_hypothetical_membership_query(#[case] runtime_api_version: u32) { }; // Activate leaves. - activate_leaf_with_params( - &mut virtual_overseer, - &leaf_a, - &test_state, - AsyncBackingParams { allowed_ancestry_len: 3, max_candidate_depth: 1 }, - ) - .await; - activate_leaf_with_params( - &mut virtual_overseer, - &leaf_b, - &test_state, - AsyncBackingParams { allowed_ancestry_len: 3, max_candidate_depth: 1 }, - ) - .await; + activate_leaf(&mut virtual_overseer, &leaf_a, &test_state).await; + activate_leaf(&mut virtual_overseer, &leaf_b, &test_state).await; // Candidates will be valid on both leaves. @@ -2285,15 +2210,9 @@ fn check_pvd_query(#[case] runtime_api_version: u32) { // Test simultaneously activating and deactivating leaves, and simultaneously deactivating // multiple leaves. -// This test is parametrised with the runtime api version. For versions that don't support the claim -// queue API, we check that av-cores are used. -#[rstest] -#[case(RuntimeApiRequest::CONSTRAINTS_RUNTIME_REQUIREMENT)] -#[case(RuntimeApiRequest::CLAIM_QUEUE_RUNTIME_REQUIREMENT)] -#[case(8)] -fn correctly_updates_leaves(#[case] runtime_api_version: u32) { - let mut test_state = TestState::default(); - test_state.set_runtime_api_version(runtime_api_version); +#[test] +fn correctly_updates_leaves() { + let test_state = TestState::default(); let view = test_harness(|mut virtual_overseer| async move { // Leaf A @@ -2347,14 +2266,7 @@ fn correctly_updates_leaves(#[case] runtime_api_version: u32) { virtual_overseer .send(FromOrchestra::Signal(OverseerSignal::ActiveLeaves(update))) .await; - handle_leaf_activation( - &mut virtual_overseer, - &leaf_c, - &test_state, - ASYNC_BACKING_PARAMETERS, - get_parent_hash, - ) - .await; + handle_leaf_activation(&mut virtual_overseer, &leaf_c, &test_state, get_parent_hash).await; // Remove all remaining leaves. let update = ActiveLeavesUpdate { @@ -2394,17 +2306,21 @@ fn correctly_updates_leaves(#[case] runtime_api_version: u32) { #[case(RuntimeApiRequest::CONSTRAINTS_RUNTIME_REQUIREMENT)] #[case(RuntimeApiRequest::CLAIM_QUEUE_RUNTIME_REQUIREMENT)] fn handle_active_leaves_update_gets_candidates_from_parent(#[case] runtime_api_version: u32) { + let para_id = ParaId::from(1); + // This doesn't test all the complicated cases with many unconnected candidates, as it's more // extensively tested in the `fragment_chain::tests` module. let mut test_state = TestState::default(); test_state.set_runtime_api_version(runtime_api_version); - let para_id = ParaId::from(1); - test_state.claim_queue = test_state - .claim_queue - .into_iter() - .filter(|(_, paras)| matches!(paras.front(), Some(para) if para == ¶_id)) - .collect(); - assert_eq!(test_state.claim_queue.len(), 1); + + test_state.claim_queue = BTreeMap::new(); + for i in 0..=4 { + test_state.claim_queue.insert( + CoreIndex(i), + std::iter::repeat(para_id).take(DEFAULT_SCHEDULING_LOOKAHEAD as _).collect(), + ); + } + let view = test_harness(|mut virtual_overseer| async move { // Leaf A let leaf_a = TestLeaf { @@ -2657,12 +2573,14 @@ fn handle_active_leaves_update_bounded_implicit_view() { .collect(); assert_eq!(test_state.claim_queue.len(), 1); + let scheduling_lookahead = DEFAULT_SCHEDULING_LOOKAHEAD; + let mut leaves = vec![TestLeaf { number: 100, hash: Hash::from_low_u64_be(130), para_data: vec![( para_id, - PerParaData::new(100 - ALLOWED_ANCESTRY_LEN, HeadData(vec![1, 2, 3])), + PerParaData::new(100 - (scheduling_lookahead - 1), HeadData(vec![1, 2, 3])), )], }]; @@ -2674,7 +2592,7 @@ fn handle_active_leaves_update_bounded_implicit_view() { para_data: vec![( para_id, PerParaData::new( - prev_leaf.number - 1 - ALLOWED_ANCESTRY_LEN, + prev_leaf.number - 1 - (scheduling_lookahead - 1), HeadData(vec![1, 2, 3]), ), )], @@ -2698,16 +2616,13 @@ fn handle_active_leaves_update_bounded_implicit_view() { // Only latest leaf is active. assert_eq!(view.active_leaves.len(), 1); - // We keep allowed_ancestry_len implicit leaves. The latest leaf is also present here. - assert_eq!( - view.per_relay_parent.len() as u32, - ASYNC_BACKING_PARAMETERS.allowed_ancestry_len + 1 - ); + // We keep scheduling_lookahead - 1 implicit leaves. The latest leaf is also present here. + assert_eq!(view.per_relay_parent.len() as u32, scheduling_lookahead); assert_eq!(view.active_leaves, [leaves[9].hash].into_iter().collect()); assert_eq!( view.per_relay_parent.into_keys().collect::<HashSet<_>>(), - leaves[6..].into_iter().map(|l| l.hash).collect::<HashSet<_>>() + leaves[7..].into_iter().map(|l| l.hash).collect::<HashSet<_>>() ); } @@ -2735,7 +2650,7 @@ fn persists_pending_availability_candidate(#[case] runtime_api_version: u32) { let candidate_relay_parent_number = 97; let leaf_a = TestLeaf { - number: candidate_relay_parent_number + ALLOWED_ANCESTRY_LEN, + number: candidate_relay_parent_number + DEFAULT_SCHEDULING_LOOKAHEAD, hash: Hash::from_low_u64_be(2), para_data: vec![( para_id, @@ -2823,102 +2738,12 @@ fn persists_pending_availability_candidate(#[case] runtime_api_version: u32) { }); } -#[test] -fn backwards_compatible_with_non_async_backing_params() { - let mut test_state = TestState::default(); - let para_id = ParaId::from(1); - test_state.claim_queue = test_state - .claim_queue - .into_iter() - .filter(|(_, paras)| matches!(paras.front(), Some(para) if para == ¶_id)) - .collect(); - assert_eq!(test_state.claim_queue.len(), 1); - - test_harness(|mut virtual_overseer| async move { - let para_head = HeadData(vec![1, 2, 3]); - - let leaf_b_hash = Hash::repeat_byte(15); - let candidate_relay_parent = get_parent_hash(leaf_b_hash); - let candidate_relay_parent_number = 100; - - let leaf_a = TestLeaf { - number: candidate_relay_parent_number, - hash: candidate_relay_parent, - para_data: vec![( - para_id, - PerParaData::new(candidate_relay_parent_number, para_head.clone()), - )], - }; - - // Activate leaf. - activate_leaf_with_params( - &mut virtual_overseer, - &leaf_a, - &test_state, - AsyncBackingParams { allowed_ancestry_len: 0, max_candidate_depth: 0 }, - ) - .await; - - // Candidate A - let (candidate_a, pvd_a) = make_candidate( - candidate_relay_parent, - candidate_relay_parent_number, - para_id, - para_head.clone(), - HeadData(vec![1]), - test_state.validation_code_hash, - ); - let candidate_hash_a = candidate_a.hash(); - - introduce_seconded_candidate(&mut virtual_overseer, candidate_a.clone(), pvd_a).await; - back_candidate(&mut virtual_overseer, &candidate_a, candidate_hash_a).await; - - get_backable_candidates( - &mut virtual_overseer, - &leaf_a, - para_id, - Ancestors::new(), - 1, - vec![(candidate_hash_a, candidate_relay_parent)], - ) - .await; - - let leaf_b = TestLeaf { - number: candidate_relay_parent_number + 1, - hash: leaf_b_hash, - para_data: vec![( - para_id, - PerParaData::new(candidate_relay_parent_number + 1, para_head.clone()), - )], - }; - activate_leaf_with_params( - &mut virtual_overseer, - &leaf_b, - &test_state, - AsyncBackingParams { allowed_ancestry_len: 0, max_candidate_depth: 0 }, - ) - .await; - - get_backable_candidates( - &mut virtual_overseer, - &leaf_b, - para_id, - Ancestors::new(), - 1, - vec![], - ) - .await; - - virtual_overseer - }); -} - #[test] fn uses_ancestry_only_within_session() { test_harness(|mut virtual_overseer| async move { let number = 5; let hash = Hash::repeat_byte(5); - let ancestry_len = 3; + let scheduling_lookahead = DEFAULT_SCHEDULING_LOOKAHEAD; let session = 2; let ancestry_hashes = @@ -2933,51 +2758,41 @@ fn uses_ancestry_only_within_session() { ))) .await; - assert_matches!( - virtual_overseer.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request( - parent, - RuntimeApiRequest::AsyncBackingParams(tx) - )) if parent == hash => { - tx.send(Ok(AsyncBackingParams { max_candidate_depth: 0, allowed_ancestry_len: ancestry_len})).unwrap(); - }); - assert_matches!( virtual_overseer.recv().await, AllMessages::RuntimeApi( - RuntimeApiMessage::Request(parent, RuntimeApiRequest::Version(tx)) + RuntimeApiMessage::Request(parent, RuntimeApiRequest::ClaimQueue(tx)) ) if parent == hash => { - tx.send(Ok(RuntimeApiRequest::CLAIM_QUEUE_RUNTIME_REQUIREMENT)).unwrap(); + tx.send(Ok(BTreeMap::new())).unwrap(); } ); + send_block_header(&mut virtual_overseer, hash, number).await; + assert_matches!( virtual_overseer.recv().await, AllMessages::RuntimeApi( - RuntimeApiMessage::Request(parent, RuntimeApiRequest::ClaimQueue(tx)) + RuntimeApiMessage::Request(parent, RuntimeApiRequest::SessionIndexForChild(tx)) ) if parent == hash => { - tx.send(Ok(BTreeMap::new())).unwrap(); + tx.send(Ok(session)).unwrap(); } ); - send_block_header(&mut virtual_overseer, hash, number).await; - assert_matches!( virtual_overseer.recv().await, - AllMessages::ChainApi( - ChainApiMessage::Ancestors{hash: block_hash, k, response_channel: tx} - ) if block_hash == hash && k == ancestry_len as usize => { - tx.send(Ok(ancestry_hashes.clone())).unwrap(); + AllMessages::RuntimeApi( + RuntimeApiMessage::Request(parent, RuntimeApiRequest::SchedulingLookahead(session_index, tx)) + ) if parent == hash && session_index == session => { + tx.send(Ok(scheduling_lookahead)).unwrap(); } ); assert_matches!( virtual_overseer.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(parent, RuntimeApiRequest::SessionIndexForChild(tx)) - ) if parent == hash => { - tx.send(Ok(session)).unwrap(); + AllMessages::ChainApi( + ChainApiMessage::Ancestors{hash: block_hash, k, response_channel: tx} + ) if block_hash == hash && k == (scheduling_lookahead - 1) as usize => { + tx.send(Ok(ancestry_hashes.clone())).unwrap(); } ); diff --git a/polkadot/node/core/provisioner/src/disputes/prioritized_selection/tests.rs b/polkadot/node/core/provisioner/src/disputes/prioritized_selection/tests.rs index 8c0d478b67df4e65553ab5ed6614ff1a920d7491..1f814989fc6a85fc104d0f565402fcf09388391a 100644 --- a/polkadot/node/core/provisioner/src/disputes/prioritized_selection/tests.rs +++ b/polkadot/node/core/provisioner/src/disputes/prioritized_selection/tests.rs @@ -26,8 +26,8 @@ use polkadot_node_subsystem::messages::{ }; use polkadot_node_subsystem_test_helpers::{mock::new_leaf, TestSubsystemSender}; use polkadot_primitives::{ - CandidateHash, DisputeState, InvalidDisputeStatementKind, SessionIndex, - ValidDisputeStatementKind, ValidatorSignature, + vstaging::CandidateReceiptV2 as CandidateReceipt, CandidateHash, DisputeState, + InvalidDisputeStatementKind, SessionIndex, ValidDisputeStatementKind, ValidatorSignature, }; // diff --git a/polkadot/node/core/provisioner/src/lib.rs b/polkadot/node/core/provisioner/src/lib.rs index a95df6c5f8808950f4531c0ba5f20cac07a959ab..4aced8eaefdfe09e294a97e7cfce2840b0583cca 100644 --- a/polkadot/node/core/provisioner/src/lib.rs +++ b/polkadot/node/core/provisioner/src/lib.rs @@ -28,23 +28,21 @@ use schnellru::{ByLength, LruMap}; use polkadot_node_subsystem::{ messages::{ - Ancestors, CandidateBackingMessage, ChainApiMessage, ProspectiveParachainsMessage, - ProvisionableData, ProvisionerInherentData, ProvisionerMessage, RuntimeApiRequest, + Ancestors, CandidateBackingMessage, ProspectiveParachainsMessage, ProvisionableData, + ProvisionerInherentData, ProvisionerMessage, }, overseer, ActivatedLeaf, ActiveLeavesUpdate, FromOrchestra, OverseerSignal, SpawnedSubsystem, SubsystemError, }; use polkadot_node_subsystem_util::{ - has_required_runtime, request_availability_cores, request_persisted_validation_data, - request_session_index_for_child, - runtime::{prospective_parachains_mode, request_node_features, ProspectiveParachainsMode}, + request_availability_cores, request_session_index_for_child, runtime::request_node_features, TimeoutExt, }; use polkadot_primitives::{ node_features::FeatureIndex, - vstaging::{BackedCandidate, CandidateReceiptV2 as CandidateReceipt, CoreState}, - BlockNumber, CandidateHash, CoreIndex, Hash, Id as ParaId, NodeFeatures, - OccupiedCoreAssumption, SessionIndex, SignedAvailabilityBitfield, ValidatorIndex, + vstaging::{BackedCandidate, CoreState}, + CandidateHash, CoreIndex, Hash, Id as ParaId, NodeFeatures, SessionIndex, + SignedAvailabilityBitfield, ValidatorIndex, }; use std::collections::{BTreeMap, HashMap}; @@ -65,9 +63,6 @@ const SEND_INHERENT_DATA_TIMEOUT: std::time::Duration = core::time::Duration::fr const LOG_TARGET: &str = "parachain::provisioner"; -const PRIORITIZED_SELECTION_RUNTIME_VERSION_REQUIREMENT: u32 = - RuntimeApiRequest::DISPUTES_RUNTIME_REQUIREMENT; - /// The provisioner subsystem. pub struct ProvisionerSubsystem { metrics: Metrics, @@ -82,15 +77,12 @@ impl ProvisionerSubsystem { /// Per-session info we need for the provisioner subsystem. pub struct PerSession { - prospective_parachains_mode: ProspectiveParachainsMode, elastic_scaling_mvp: bool, } /// A per-relay-parent state for the provisioning subsystem. pub struct PerRelayParent { leaf: ActivatedLeaf, - backed_candidates: Vec<CandidateReceipt>, - prospective_parachains_mode: ProspectiveParachainsMode, elastic_scaling_mvp: bool, signed_bitfields: Vec<SignedAvailabilityBitfield>, is_inherent_ready: bool, @@ -101,8 +93,6 @@ impl PerRelayParent { fn new(leaf: ActivatedLeaf, per_session: &PerSession) -> Self { Self { leaf, - backed_candidates: Vec::new(), - prospective_parachains_mode: per_session.prospective_parachains_mode, elastic_scaling_mvp: per_session.elastic_scaling_mvp, signed_bitfields: Vec::new(), is_inherent_ready: false, @@ -212,8 +202,6 @@ async fn handle_active_leaves_update( .await .map_err(Error::CanceledSessionIndex)??; if per_session.get(&session_index).is_none() { - let prospective_parachains_mode = - prospective_parachains_mode(sender, leaf.hash).await?; let elastic_scaling_mvp = request_node_features(leaf.hash, session_index, sender) .await? .unwrap_or(NodeFeatures::EMPTY) @@ -221,10 +209,7 @@ async fn handle_active_leaves_update( .map(|b| *b) .unwrap_or(false); - per_session.insert( - session_index, - PerSession { prospective_parachains_mode, elastic_scaling_mvp }, - ); + per_session.insert(session_index, PerSession { elastic_scaling_mvp }); } let session_info = per_session.get(&session_index).expect("Just inserted"); @@ -287,8 +272,6 @@ async fn send_inherent_data_bg<Context>( ) -> Result<(), Error> { let leaf = per_relay_parent.leaf.clone(); let signed_bitfields = per_relay_parent.signed_bitfields.clone(); - let backed_candidates = per_relay_parent.backed_candidates.clone(); - let mode = per_relay_parent.prospective_parachains_mode; let elastic_scaling_mvp = per_relay_parent.elastic_scaling_mvp; let mut sender = ctx.sender().clone(); @@ -305,8 +288,6 @@ async fn send_inherent_data_bg<Context>( let send_result = send_inherent_data( &leaf, &signed_bitfields, - &backed_candidates, - mode, elastic_scaling_mvp, return_senders, &mut sender, @@ -357,16 +338,6 @@ fn note_provisionable_data( match provisionable_data { ProvisionableData::Bitfield(_, signed_bitfield) => per_relay_parent.signed_bitfields.push(signed_bitfield), - ProvisionableData::BackedCandidate(backed_candidate) => { - let candidate_hash = backed_candidate.hash(); - gum::trace!( - target: LOG_TARGET, - ?candidate_hash, - para = ?backed_candidate.descriptor().para_id(), - "noted backed candidate", - ); - per_relay_parent.backed_candidates.push(backed_candidate); - }, // We choose not to punish these forms of misbehavior for the time being. // Risks from misbehavior are sufficiently mitigated at the protocol level // via reputation changes. Punitive actions here may become desirable @@ -412,8 +383,6 @@ type CoreAvailability = BitVec<u8, bitvec::order::Lsb0>; async fn send_inherent_data( leaf: &ActivatedLeaf, bitfields: &[SignedAvailabilityBitfield], - candidates: &[CandidateReceipt], - prospective_parachains_mode: ProspectiveParachainsMode, elastic_scaling_mvp: bool, return_senders: Vec<oneshot::Sender<ProvisionerInherentData>>, from_job: &mut impl overseer::ProvisionerSenderTrait, @@ -435,16 +404,6 @@ async fn send_inherent_data( "Selecting disputes" ); - debug_assert!( - has_required_runtime( - from_job, - leaf.hash, - PRIORITIZED_SELECTION_RUNTIME_VERSION_REQUIREMENT, - ) - .await, - "randomized selection no longer supported, please upgrade your runtime!" - ); - let disputes = disputes::prioritized_selection::select_disputes(from_job, metrics, leaf).await; gum::trace!( @@ -461,16 +420,9 @@ async fn send_inherent_data( "Selected bitfields" ); - let candidates = select_candidates( - &availability_cores, - &bitfields, - candidates, - prospective_parachains_mode, - elastic_scaling_mvp, - leaf.hash, - from_job, - ) - .await?; + let candidates = + select_candidates(&availability_cores, &bitfields, elastic_scaling_mvp, leaf, from_job) + .await?; gum::trace!( target: LOG_TARGET, @@ -577,114 +529,16 @@ fn select_availability_bitfields( selected.into_values().collect() } -/// Selects candidates from tracked ones to note in a relay chain block. -/// -/// Should be called when prospective parachains are disabled. -async fn select_candidate_hashes_from_tracked( - availability_cores: &[CoreState], - bitfields: &[SignedAvailabilityBitfield], - candidates: &[CandidateReceipt], - relay_parent: Hash, - sender: &mut impl overseer::ProvisionerSenderTrait, -) -> Result<HashMap<ParaId, Vec<(CandidateHash, Hash)>>, Error> { - let block_number = get_block_number_under_construction(relay_parent, sender).await?; - - let mut selected_candidates = - HashMap::with_capacity(candidates.len().min(availability_cores.len())); - - gum::debug!( - target: LOG_TARGET, - leaf_hash=?relay_parent, - n_candidates = candidates.len(), - "Candidate receipts (before selection)", - ); - - for (core_idx, core) in availability_cores.iter().enumerate() { - let (scheduled_core, assumption) = match core { - CoreState::Scheduled(scheduled_core) => (scheduled_core, OccupiedCoreAssumption::Free), - CoreState::Occupied(occupied_core) => { - if bitfields_indicate_availability(core_idx, bitfields, &occupied_core.availability) - { - if let Some(ref scheduled_core) = occupied_core.next_up_on_available { - (scheduled_core, OccupiedCoreAssumption::Included) - } else { - continue - } - } else { - if occupied_core.time_out_at != block_number { - continue - } - if let Some(ref scheduled_core) = occupied_core.next_up_on_time_out { - (scheduled_core, OccupiedCoreAssumption::TimedOut) - } else { - continue - } - } - }, - CoreState::Free => continue, - }; - - if selected_candidates.contains_key(&scheduled_core.para_id) { - // We already picked a candidate for this parachain. Elastic scaling only works with - // prospective parachains mode. - continue - } - - let validation_data = match request_persisted_validation_data( - relay_parent, - scheduled_core.para_id, - assumption, - sender, - ) - .await - .await - .map_err(|err| Error::CanceledPersistedValidationData(err))?? - { - Some(v) => v, - None => continue, - }; - - let computed_validation_data_hash = validation_data.hash(); - - // we arbitrarily pick the first of the backed candidates which match the appropriate - // selection criteria - if let Some(candidate) = candidates.iter().find(|backed_candidate| { - let descriptor = &backed_candidate.descriptor; - descriptor.para_id() == scheduled_core.para_id && - descriptor.persisted_validation_data_hash() == computed_validation_data_hash - }) { - let candidate_hash = candidate.hash(); - gum::trace!( - target: LOG_TARGET, - leaf_hash=?relay_parent, - ?candidate_hash, - para = ?candidate.descriptor.para_id(), - core = core_idx, - "Selected candidate receipt", - ); - - selected_candidates.insert( - candidate.descriptor.para_id(), - vec![(candidate_hash, candidate.descriptor.relay_parent())], - ); - } - } - - Ok(selected_candidates) -} - /// Requests backable candidates from Prospective Parachains subsystem /// based on core states. -/// -/// Should be called when prospective parachains are enabled. async fn request_backable_candidates( availability_cores: &[CoreState], elastic_scaling_mvp: bool, bitfields: &[SignedAvailabilityBitfield], - relay_parent: Hash, + relay_parent: &ActivatedLeaf, sender: &mut impl overseer::ProvisionerSenderTrait, ) -> Result<HashMap<ParaId, Vec<(CandidateHash, Hash)>>, Error> { - let block_number = get_block_number_under_construction(relay_parent, sender).await?; + let block_number_under_construction = relay_parent.number + 1; // Record how many cores are scheduled for each paraid. Use a BTreeMap because // we'll need to iterate through them. @@ -716,7 +570,7 @@ async fn request_backable_candidates( // Request a new backable candidate for the newly scheduled para id. *scheduled_cores_per_para.entry(scheduled_core.para_id).or_insert(0) += 1; } - } else if occupied_core.time_out_at <= block_number { + } else if occupied_core.time_out_at <= block_number_under_construction { // Timed out before being available. if let Some(ref scheduled_core) = occupied_core.next_up_on_time_out { @@ -747,7 +601,7 @@ async fn request_backable_candidates( } let response = get_backable_candidates( - relay_parent, + relay_parent.hash, para_id, para_ancestors, core_count as u32, @@ -758,7 +612,7 @@ async fn request_backable_candidates( if response.is_empty() { gum::debug!( target: LOG_TARGET, - leaf_hash = ?relay_parent, + leaf_hash = ?relay_parent.hash, ?para_id, "No backable candidate returned by prospective parachains", ); @@ -776,38 +630,26 @@ async fn request_backable_candidates( async fn select_candidates( availability_cores: &[CoreState], bitfields: &[SignedAvailabilityBitfield], - candidates: &[CandidateReceipt], - prospective_parachains_mode: ProspectiveParachainsMode, elastic_scaling_mvp: bool, - relay_parent: Hash, + leaf: &ActivatedLeaf, sender: &mut impl overseer::ProvisionerSenderTrait, ) -> Result<Vec<BackedCandidate>, Error> { + let relay_parent = leaf.hash; gum::trace!( target: LOG_TARGET, leaf_hash=?relay_parent, "before GetBackedCandidates" ); - let selected_candidates = match prospective_parachains_mode { - ProspectiveParachainsMode::Enabled { .. } => - request_backable_candidates( - availability_cores, - elastic_scaling_mvp, - bitfields, - relay_parent, - sender, - ) - .await?, - ProspectiveParachainsMode::Disabled => - select_candidate_hashes_from_tracked( - availability_cores, - bitfields, - &candidates, - relay_parent, - sender, - ) - .await?, - }; + let selected_candidates = request_backable_candidates( + availability_cores, + elastic_scaling_mvp, + bitfields, + leaf, + sender, + ) + .await?; + gum::debug!(target: LOG_TARGET, ?selected_candidates, "Got backable candidates"); // now get the backed candidates corresponding to these candidate receipts @@ -817,8 +659,11 @@ async fn select_candidates( tx, )); let candidates = rx.await.map_err(|err| Error::CanceledBackedCandidates(err))?; - gum::trace!(target: LOG_TARGET, leaf_hash=?relay_parent, - "Got {} backed candidates", candidates.len()); + gum::trace!( + target: LOG_TARGET, + leaf_hash=?relay_parent, + "Got {} backed candidates", candidates.len() + ); // keep only one candidate with validation code. let mut with_validation_code = false; @@ -850,22 +695,6 @@ async fn select_candidates( Ok(merged_candidates) } -/// Produces a block number 1 higher than that of the relay parent -/// in the event of an invalid `relay_parent`, returns `Ok(0)` -async fn get_block_number_under_construction( - relay_parent: Hash, - sender: &mut impl overseer::ProvisionerSenderTrait, -) -> Result<BlockNumber, Error> { - let (tx, rx) = oneshot::channel(); - sender.send_message(ChainApiMessage::BlockNumber(relay_parent, tx)).await; - - match rx.await.map_err(|err| Error::CanceledBlockNumber(err))? { - Ok(Some(n)) => Ok(n + 1), - Ok(None) => Ok(0), - Err(err) => Err(err.into()), - } -} - /// Requests backable candidates from Prospective Parachains based on /// the given ancestors in the fragment chain. The ancestors may not be ordered. async fn get_backable_candidates( diff --git a/polkadot/node/core/provisioner/src/tests.rs b/polkadot/node/core/provisioner/src/tests.rs index a09b243f3ab1338ecff24ba239978d60f2acaebc..4667f44d65a0310fbf3e32d712dcdbc7aed31f0a 100644 --- a/polkadot/node/core/provisioner/src/tests.rs +++ b/polkadot/node/core/provisioner/src/tests.rs @@ -254,10 +254,12 @@ mod select_candidates { AvailabilityCores, PersistedValidationData as PersistedValidationDataReq, }, }; - use polkadot_node_subsystem_test_helpers::TestSubsystemSender; - use polkadot_node_subsystem_util::runtime::ProspectiveParachainsMode; + use polkadot_node_subsystem_test_helpers::{mock::new_leaf, TestSubsystemSender}; use polkadot_primitives::{ - vstaging::{CommittedCandidateReceiptV2 as CommittedCandidateReceipt, MutateDescriptorV2}, + vstaging::{ + CandidateReceiptV2 as CandidateReceipt, + CommittedCandidateReceiptV2 as CommittedCandidateReceipt, MutateDescriptorV2, + }, BlockNumber, CandidateCommitments, PersistedValidationData, }; use polkadot_primitives_test_helpers::{dummy_candidate_descriptor_v2, dummy_hash}; @@ -557,9 +559,7 @@ mod select_candidates { mock_availability_cores: Vec<CoreState>, mut expected: Vec<BackedCandidate>, mut expected_ancestors: HashMap<Vec<CandidateHash>, Ancestors>, - prospective_parachains_mode: ProspectiveParachainsMode, ) { - use ChainApiMessage::BlockNumber; use RuntimeApiMessage::Request; let mut backed = expected.clone().into_iter().fold(HashMap::new(), |mut acc, candidate| { @@ -574,8 +574,6 @@ mod select_candidates { while let Some(from_job) = receiver.next().await { match from_job { - AllMessages::ChainApi(BlockNumber(_relay_parent, tx)) => - tx.send(Ok(Some(BLOCK_UNDER_PRODUCTION - 1))).unwrap(), AllMessages::RuntimeApi(Request( _parent_hash, PersistedValidationDataReq(_para_id, _assumption, tx), @@ -624,175 +622,57 @@ mod select_candidates { actual_ancestors, tx, ), - ) => match prospective_parachains_mode { - ProspectiveParachainsMode::Enabled { .. } => { - assert!(count > 0); - let candidates = - (&mut candidates_iter).take(count as usize).collect::<Vec<_>>(); - assert_eq!(candidates.len(), count as usize); - - if !expected_ancestors.is_empty() { - if let Some(expected_required_ancestors) = expected_ancestors.remove( - &(candidates - .clone() - .into_iter() - .take(actual_ancestors.len()) - .map(|(c_hash, _)| c_hash) - .collect::<Vec<_>>()), - ) { - assert_eq!(expected_required_ancestors, actual_ancestors); - } else { - assert_eq!(actual_ancestors.len(), 0); - } + ) => { + assert!(count > 0); + let candidates = + (&mut candidates_iter).take(count as usize).collect::<Vec<_>>(); + assert_eq!(candidates.len(), count as usize); + + if !expected_ancestors.is_empty() { + if let Some(expected_required_ancestors) = expected_ancestors.remove( + &(candidates + .clone() + .into_iter() + .take(actual_ancestors.len()) + .map(|(c_hash, _)| c_hash) + .collect::<Vec<_>>()), + ) { + assert_eq!(expected_required_ancestors, actual_ancestors); + } else { + assert_eq!(actual_ancestors.len(), 0); } + } - let _ = tx.send(candidates); - }, - ProspectiveParachainsMode::Disabled => - panic!("unexpected prospective parachains request"), + let _ = tx.send(candidates); }, _ => panic!("Unexpected message: {:?}", from_job), } } - if let ProspectiveParachainsMode::Enabled { .. } = prospective_parachains_mode { - assert_eq!(candidates_iter.next(), None); - } + assert_eq!(candidates_iter.next(), None); assert_eq!(expected_ancestors.len(), 0); } - #[rstest] - #[case(ProspectiveParachainsMode::Disabled)] - #[case(ProspectiveParachainsMode::Enabled {max_candidate_depth: 0, allowed_ancestry_len: 0})] - fn can_succeed(#[case] prospective_parachains_mode: ProspectiveParachainsMode) { + #[test] + fn can_succeed() { test_harness( - |r| { - mock_overseer( - r, - Vec::new(), - Vec::new(), - HashMap::new(), - prospective_parachains_mode, - ) - }, + |r| mock_overseer(r, Vec::new(), Vec::new(), HashMap::new()), |mut tx: TestSubsystemSender| async move { select_candidates( &[], &[], - &[], - prospective_parachains_mode, false, - Default::default(), - &mut tx, - ) - .await - .unwrap(); - }, - ) - } - - // Test candidate selection when prospective parachains mode is disabled. - // This tests that only the appropriate candidates get selected when prospective parachains mode - // is disabled. To accomplish this, we supply a candidate list containing one candidate per - // possible core; the candidate selection algorithm must filter them to the appropriate set - #[rstest] - // why those particular indices? see the comments on mock_availability_cores_*() functions. - #[case(mock_availability_cores_one_per_para(), vec![1, 4, 7, 8, 10], true)] - #[case(mock_availability_cores_one_per_para(), vec![1, 4, 7, 8, 10], false)] - #[case(mock_availability_cores_multiple_per_para(), vec![1, 4, 7, 8, 10, 12, 13, 14, 15], true)] - #[case(mock_availability_cores_multiple_per_para(), vec![1, 4, 7, 8, 10, 12, 13, 14, 15], false)] - fn test_in_subsystem_selection( - #[case] mock_cores: Vec<CoreState>, - #[case] expected_candidates: Vec<usize>, - #[case] elastic_scaling_mvp: bool, - ) { - let candidate_template = dummy_candidate_template(); - let candidates: Vec<_> = std::iter::repeat(candidate_template) - .take(mock_cores.len()) - .enumerate() - .map(|(idx, mut candidate)| { - candidate.descriptor.set_para_id(idx.into()); - candidate - }) - .cycle() - .take(mock_cores.len() * 3) - .enumerate() - .map(|(idx, mut candidate)| { - if idx < mock_cores.len() { - // first go-around: use candidates which should work - candidate - } else if idx < mock_cores.len() * 2 { - // for the second repetition of the candidates, give them the wrong hash - candidate.descriptor.set_persisted_validation_data_hash(Default::default()); - candidate - } else { - // third go-around: right hash, wrong para_id - candidate.descriptor.set_para_id(idx.into()); - candidate - } - }) - .collect(); - - let expected_candidates: Vec<_> = - expected_candidates.into_iter().map(|idx| candidates[idx].clone()).collect(); - let prospective_parachains_mode = ProspectiveParachainsMode::Disabled; - - let expected_backed = expected_candidates - .iter() - .map(|c| { - BackedCandidate::new( - CommittedCandidateReceipt { - descriptor: c.descriptor().clone(), - commitments: Default::default(), - }, - Vec::new(), - default_bitvec(MOCK_GROUP_SIZE), - None, - ) - }) - .collect(); - - let mock_cores_clone = mock_cores.clone(); - test_harness( - |r| { - mock_overseer( - r, - mock_cores_clone, - expected_backed, - HashMap::new(), - prospective_parachains_mode, - ) - }, - |mut tx: TestSubsystemSender| async move { - let result: Vec<BackedCandidate> = select_candidates( - &mock_cores, - &[], - &candidates, - prospective_parachains_mode, - elastic_scaling_mvp, - Default::default(), + &new_leaf(Default::default(), BLOCK_UNDER_PRODUCTION - 1), &mut tx, ) .await .unwrap(); - - result.into_iter().for_each(|c| { - assert!( - expected_candidates.iter().any(|c2| c.candidate().corresponds_to(c2)), - "Failed to find candidate: {:?}", - c, - ) - }); }, ) } - #[rstest] - #[case(ProspectiveParachainsMode::Disabled)] - #[case(ProspectiveParachainsMode::Enabled {max_candidate_depth: 0, allowed_ancestry_len: 0})] - fn selects_max_one_code_upgrade_one_core_per_para( - #[case] prospective_parachains_mode: ProspectiveParachainsMode, - ) { + #[test] + fn selects_max_one_code_upgrade_one_core_per_para() { let mock_cores = mock_availability_cores_one_per_para(); let empty_hash = PersistedValidationData::<Hash, BlockNumber>::default().hash(); @@ -855,23 +735,13 @@ mod select_candidates { let mock_cores_clone = mock_cores.clone(); test_harness( - |r| { - mock_overseer( - r, - mock_cores_clone, - expected_backed, - HashMap::new(), - prospective_parachains_mode, - ) - }, + |r| mock_overseer(r, mock_cores_clone, expected_backed, HashMap::new()), |mut tx: TestSubsystemSender| async move { let result = select_candidates( &mock_cores, &[], - &candidates, - prospective_parachains_mode, false, - Default::default(), + &new_leaf(Default::default(), BLOCK_UNDER_PRODUCTION - 1), &mut tx, ) .await @@ -890,8 +760,6 @@ mod select_candidates { #[test] fn selects_max_one_code_upgrade_multiple_cores_per_para() { - let prospective_parachains_mode = - ProspectiveParachainsMode::Enabled { max_candidate_depth: 0, allowed_ancestry_len: 0 }; let mock_cores = vec![ // 0: Scheduled(default), Scheduled(scheduled_core(1)), @@ -970,23 +838,13 @@ mod select_candidates { let mock_cores_clone = mock_cores.clone(); test_harness( - |r| { - mock_overseer( - r, - mock_cores_clone, - expected_backed, - HashMap::new(), - prospective_parachains_mode, - ) - }, + |r| mock_overseer(r, mock_cores_clone, expected_backed, HashMap::new()), |mut tx: TestSubsystemSender| async move { let result = select_candidates( &mock_cores, &[], - &candidates, - prospective_parachains_mode, true, - Default::default(), + &new_leaf(Default::default(), BLOCK_UNDER_PRODUCTION - 1), &mut tx, ) .await @@ -1004,7 +862,7 @@ mod select_candidates { #[rstest] #[case(true)] #[case(false)] - fn request_from_prospective_parachains_one_core_per_para(#[case] elastic_scaling_mvp: bool) { + fn one_core_per_para(#[case] elastic_scaling_mvp: bool) { let mock_cores = mock_availability_cores_one_per_para(); // why those particular indices? see the comments on mock_availability_cores() @@ -1012,10 +870,6 @@ mod select_candidates { let (candidates, expected_candidates) = make_candidates(mock_cores.len() + 1, expected_candidates); - // Expect prospective parachains subsystem requests. - let prospective_parachains_mode = - ProspectiveParachainsMode::Enabled { max_candidate_depth: 0, allowed_ancestry_len: 0 }; - let mut required_ancestors: HashMap<Vec<CandidateHash>, Ancestors> = HashMap::new(); required_ancestors.insert( vec![candidates[4]], @@ -1029,23 +883,13 @@ mod select_candidates { let mock_cores_clone = mock_cores.clone(); let expected_candidates_clone = expected_candidates.clone(); test_harness( - |r| { - mock_overseer( - r, - mock_cores_clone, - expected_candidates_clone, - required_ancestors, - prospective_parachains_mode, - ) - }, + |r| mock_overseer(r, mock_cores_clone, expected_candidates_clone, required_ancestors), |mut tx: TestSubsystemSender| async move { let result = select_candidates( &mock_cores, &[], - &[], - prospective_parachains_mode, elastic_scaling_mvp, - Default::default(), + &new_leaf(Default::default(), BLOCK_UNDER_PRODUCTION - 1), &mut tx, ) .await @@ -1066,15 +910,12 @@ mod select_candidates { } #[test] - fn request_from_prospective_parachains_multiple_cores_per_para_elastic_scaling_mvp() { + fn multiple_cores_per_para_elastic_scaling_mvp() { let mock_cores = mock_availability_cores_multiple_per_para(); // why those particular indices? see the comments on mock_availability_cores() let expected_candidates: Vec<_> = vec![1, 4, 7, 8, 10, 12, 12, 12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15]; - // Expect prospective parachains subsystem requests. - let prospective_parachains_mode = - ProspectiveParachainsMode::Enabled { max_candidate_depth: 0, allowed_ancestry_len: 0 }; let (candidates, expected_candidates) = make_candidates(mock_cores.len(), expected_candidates); @@ -1119,23 +960,13 @@ mod select_candidates { let mock_cores_clone = mock_cores.clone(); let expected_candidates_clone = expected_candidates.clone(); test_harness( - |r| { - mock_overseer( - r, - mock_cores_clone, - expected_candidates, - required_ancestors, - prospective_parachains_mode, - ) - }, + |r| mock_overseer(r, mock_cores_clone, expected_candidates, required_ancestors), |mut tx: TestSubsystemSender| async move { let result = select_candidates( &mock_cores, &[], - &[], - prospective_parachains_mode, true, - Default::default(), + &new_leaf(Default::default(), BLOCK_UNDER_PRODUCTION - 1), &mut tx, ) .await @@ -1156,14 +987,11 @@ mod select_candidates { } #[test] - fn request_from_prospective_parachains_multiple_cores_per_para_elastic_scaling_mvp_disabled() { + fn multiple_cores_per_para_elastic_scaling_mvp_disabled() { let mock_cores = mock_availability_cores_multiple_per_para(); // why those particular indices? see the comments on mock_availability_cores() let expected_candidates: Vec<_> = vec![1, 4, 7, 8, 10]; - // Expect prospective parachains subsystem requests. - let prospective_parachains_mode = - ProspectiveParachainsMode::Enabled { max_candidate_depth: 0, allowed_ancestry_len: 0 }; let (candidates, expected_candidates) = make_candidates(mock_cores.len(), expected_candidates); @@ -1181,23 +1009,13 @@ mod select_candidates { let mock_cores_clone = mock_cores.clone(); let expected_candidates_clone = expected_candidates.clone(); test_harness( - |r| { - mock_overseer( - r, - mock_cores_clone, - expected_candidates, - required_ancestors, - prospective_parachains_mode, - ) - }, + |r| mock_overseer(r, mock_cores_clone, expected_candidates, required_ancestors), |mut tx: TestSubsystemSender| async move { let result = select_candidates( &mock_cores, &[], - &[], - prospective_parachains_mode, false, - Default::default(), + &new_leaf(Default::default(), BLOCK_UNDER_PRODUCTION - 1), &mut tx, ) .await @@ -1235,9 +1053,6 @@ mod select_candidates { // why those particular indices? see the comments on mock_availability_cores() let expected_candidates: Vec<_> = [1, 4, 7, 8, 10, 12].iter().map(|&idx| candidates[idx].clone()).collect(); - // Expect prospective parachains subsystem requests. - let prospective_parachains_mode = - ProspectiveParachainsMode::Enabled { max_candidate_depth: 0, allowed_ancestry_len: 0 }; let expected_backed = expected_candidates .iter() @@ -1256,23 +1071,13 @@ mod select_candidates { let mock_cores_clone = mock_cores.clone(); test_harness( - |r| { - mock_overseer( - r, - mock_cores_clone, - expected_backed, - HashMap::new(), - prospective_parachains_mode, - ) - }, + |r| mock_overseer(r, mock_cores_clone, expected_backed, HashMap::new()), |mut tx: TestSubsystemSender| async move { let result = select_candidates( &mock_cores, &[], - &[], - prospective_parachains_mode, false, - Default::default(), + &new_leaf(Default::default(), BLOCK_UNDER_PRODUCTION - 1), &mut tx, ) .await diff --git a/polkadot/node/core/runtime-api/src/cache.rs b/polkadot/node/core/runtime-api/src/cache.rs index 8a885ea9cc92fc9948074ce5aeff85db496da1a0..4ed42626d88eeba2fdcfcc0f3960b4803361dbb9 100644 --- a/polkadot/node/core/runtime-api/src/cache.rs +++ b/polkadot/node/core/runtime-api/src/cache.rs @@ -76,6 +76,7 @@ pub(crate) struct RequestResultCache { approval_voting_params: LruMap<SessionIndex, ApprovalVotingParams>, claim_queue: LruMap<Hash, BTreeMap<CoreIndex, VecDeque<ParaId>>>, backing_constraints: LruMap<(Hash, ParaId), Option<Constraints>>, + scheduling_lookahead: LruMap<SessionIndex, u32>, } impl Default for RequestResultCache { @@ -114,6 +115,7 @@ impl Default for RequestResultCache { node_features: LruMap::new(ByLength::new(DEFAULT_CACHE_CAP)), claim_queue: LruMap::new(ByLength::new(DEFAULT_CACHE_CAP)), backing_constraints: LruMap::new(ByLength::new(DEFAULT_CACHE_CAP)), + scheduling_lookahead: LruMap::new(ByLength::new(DEFAULT_CACHE_CAP)), } } } @@ -576,10 +578,21 @@ impl RequestResultCache { ) { self.backing_constraints.insert(key, value); } + + pub(crate) fn scheduling_lookahead(&mut self, session_index: SessionIndex) -> Option<u32> { + self.scheduling_lookahead.get(&session_index).copied() + } + + pub(crate) fn cache_scheduling_lookahead( + &mut self, + session_index: SessionIndex, + scheduling_lookahead: u32, + ) { + self.scheduling_lookahead.insert(session_index, scheduling_lookahead); + } } pub(crate) enum RequestResult { - // The structure of each variant is (relay_parent, [params,]*, result) Authorities(Hash, Vec<AuthorityDiscoveryId>), Validators(Hash, Vec<ValidatorId>), MinimumBackingVotes(SessionIndex, u32), @@ -628,4 +641,5 @@ pub(crate) enum RequestResult { ClaimQueue(Hash, BTreeMap<CoreIndex, VecDeque<ParaId>>), CandidatesPendingAvailability(Hash, ParaId, Vec<CommittedCandidateReceipt>), BackingConstraints(Hash, ParaId, Option<Constraints>), + SchedulingLookahead(SessionIndex, u32), } diff --git a/polkadot/node/core/runtime-api/src/lib.rs b/polkadot/node/core/runtime-api/src/lib.rs index 4889822b46a9b3dc8de972f265b2febee6d7d762..2d864c8cf2f4c59355c35161f5ecab90a0dfeb30 100644 --- a/polkadot/node/core/runtime-api/src/lib.rs +++ b/polkadot/node/core/runtime-api/src/lib.rs @@ -168,7 +168,7 @@ where KeyOwnershipProof(relay_parent, validator_id, key_ownership_proof) => self .requests_cache .cache_key_ownership_proof((relay_parent, validator_id), key_ownership_proof), - RequestResult::ApprovalVotingParams(_relay_parent, session_index, params) => + ApprovalVotingParams(_relay_parent, session_index, params) => self.requests_cache.cache_approval_voting_params(session_index, params), SubmitReportDisputeLost(_) => {}, DisabledValidators(relay_parent, disabled_validators) => @@ -186,6 +186,9 @@ where BackingConstraints(relay_parent, para_id, constraints) => self .requests_cache .cache_backing_constraints((relay_parent, para_id), constraints), + SchedulingLookahead(session_index, scheduling_lookahead) => self + .requests_cache + .cache_scheduling_lookahead(session_index, scheduling_lookahead), } } @@ -345,6 +348,15 @@ where query!(claim_queue(), sender).map(|sender| Request::ClaimQueue(sender)), Request::BackingConstraints(para, sender) => query!(backing_constraints(para), sender) .map(|sender| Request::BackingConstraints(para, sender)), + Request::SchedulingLookahead(index, sender) => { + if let Some(value) = self.requests_cache.scheduling_lookahead(index) { + self.metrics.on_cached_request(); + let _ = sender.send(Ok(value)); + None + } else { + Some(Request::SchedulingLookahead(index, sender)) + } + }, } } @@ -665,5 +677,12 @@ where sender ) }, + Request::SchedulingLookahead(index, sender) => query!( + SchedulingLookahead, + scheduling_lookahead(), + ver = Request::SCHEDULING_LOOKAHEAD_RUNTIME_REQUIREMENT, + sender, + result = (index) + ), } } diff --git a/polkadot/node/core/runtime-api/src/tests.rs b/polkadot/node/core/runtime-api/src/tests.rs index 56c6087695786bc55bd400a817d449d6fdc7a559..bbc580129002271ad718e75d1b31874ddc839064 100644 --- a/polkadot/node/core/runtime-api/src/tests.rs +++ b/polkadot/node/core/runtime-api/src/tests.rs @@ -308,6 +308,10 @@ impl RuntimeApiSubsystemClient for MockSubsystemClient { todo!("Not required for tests") } + async fn scheduling_lookahead(&self, _: Hash) -> Result<u32, ApiError> { + todo!("Not required for tests") + } + async fn backing_constraints( &self, _at: Hash, diff --git a/polkadot/node/metrics/Cargo.toml b/polkadot/node/metrics/Cargo.toml index 318deca4f2438aa972cf0ba4fedc2adb685fc5a5..8d15391b11c2a275cf9cf85c4f5d29538ace0e75 100644 --- a/polkadot/node/metrics/Cargo.toml +++ b/polkadot/node/metrics/Cargo.toml @@ -29,7 +29,6 @@ prometheus-endpoint = { workspace = true, default-features = true } sc-tracing = { workspace = true, default-features = true } [dev-dependencies] -assert_cmd = { workspace = true } http-body-util = { workspace = true } hyper = { workspace = true } hyper-util = { features = ["client-legacy", "tokio"], workspace = true } @@ -37,7 +36,6 @@ polkadot-test-service = { features = ["runtime-metrics"], workspace = true } prometheus-parse = { workspace = true } sc-service = { workspace = true, default-features = true } sp-keyring = { workspace = true, default-features = true } -substrate-test-utils = { workspace = true } tempfile = { workspace = true } tokio = { workspace = true, default-features = true } diff --git a/polkadot/node/network/collator-protocol/src/collator_side/collation.rs b/polkadot/node/network/collator-protocol/src/collator_side/collation.rs index 6a570331f710b3a845d5ebcd02a007e45eb3f662..aa2fc52e90c522e52f31683a184a71e5557d8f1c 100644 --- a/polkadot/node/network/collator-protocol/src/collator_side/collation.rs +++ b/polkadot/node/network/collator-protocol/src/collator_side/collation.rs @@ -21,9 +21,7 @@ use std::collections::{HashSet, VecDeque}; use futures::{future::BoxFuture, stream::FuturesUnordered}; use polkadot_node_network_protocol::{ - request_response::{ - incoming::OutgoingResponse, v1 as protocol_v1, v2 as protocol_v2, IncomingRequest, - }, + request_response::{incoming::OutgoingResponse, v2 as protocol_v2, IncomingRequest}, PeerId, }; use polkadot_node_primitives::PoV; @@ -90,16 +88,9 @@ pub struct WaitingCollationFetches { /// Backwards-compatible wrapper for incoming collations requests. pub enum VersionedCollationRequest { - V1(IncomingRequest<protocol_v1::CollationFetchingRequest>), V2(IncomingRequest<protocol_v2::CollationFetchingRequest>), } -impl From<IncomingRequest<protocol_v1::CollationFetchingRequest>> for VersionedCollationRequest { - fn from(req: IncomingRequest<protocol_v1::CollationFetchingRequest>) -> Self { - Self::V1(req) - } -} - impl From<IncomingRequest<protocol_v2::CollationFetchingRequest>> for VersionedCollationRequest { fn from(req: IncomingRequest<protocol_v2::CollationFetchingRequest>) -> Self { Self::V2(req) @@ -110,15 +101,20 @@ impl VersionedCollationRequest { /// Returns parachain id from the request payload. pub fn para_id(&self) -> ParaId { match self { - VersionedCollationRequest::V1(req) => req.payload.para_id, VersionedCollationRequest::V2(req) => req.payload.para_id, } } + /// Returns candidate hash from the request payload. + pub fn candidate_hash(&self) -> CandidateHash { + match self { + VersionedCollationRequest::V2(req) => req.payload.candidate_hash, + } + } + /// Returns relay parent from the request payload. pub fn relay_parent(&self) -> Hash { match self { - VersionedCollationRequest::V1(req) => req.payload.relay_parent, VersionedCollationRequest::V2(req) => req.payload.relay_parent, } } @@ -126,7 +122,6 @@ impl VersionedCollationRequest { /// Returns id of the peer the request was received from. pub fn peer_id(&self) -> PeerId { match self { - VersionedCollationRequest::V1(req) => req.peer, VersionedCollationRequest::V2(req) => req.peer, } } @@ -134,10 +129,9 @@ impl VersionedCollationRequest { /// Sends the response back to requester. pub fn send_outgoing_response( self, - response: OutgoingResponse<protocol_v1::CollationFetchingResponse>, + response: OutgoingResponse<protocol_v2::CollationFetchingResponse>, ) -> Result<(), ()> { match self { - VersionedCollationRequest::V1(req) => req.send_outgoing_response(response), VersionedCollationRequest::V2(req) => req.send_outgoing_response(response), } } diff --git a/polkadot/node/network/collator-protocol/src/collator_side/mod.rs b/polkadot/node/network/collator-protocol/src/collator_side/mod.rs index d77480272cb4f80f7190a3f8362242037baefbcb..50c933599f5497a6e92862d5a69c17eccceb01f7 100644 --- a/polkadot/node/network/collator-protocol/src/collator_side/mod.rs +++ b/polkadot/node/network/collator-protocol/src/collator_side/mod.rs @@ -31,7 +31,7 @@ use polkadot_node_network_protocol::{ peer_set::{CollationVersion, PeerSet}, request_response::{ incoming::{self, OutgoingResponse}, - v1 as request_v1, v2 as request_v2, IncomingRequestReceiver, + v2 as request_v2, IncomingRequestReceiver, }, v1 as protocol_v1, v2 as protocol_v2, OurView, PeerId, UnifiedReputationChange as Rep, Versioned, View, @@ -40,23 +40,18 @@ use polkadot_node_primitives::{CollationSecondedSignal, PoV, Statement}; use polkadot_node_subsystem::{ messages::{ CollatorProtocolMessage, NetworkBridgeEvent, NetworkBridgeTxMessage, ParentHeadData, - RuntimeApiMessage, }, overseer, FromOrchestra, OverseerSignal, }; use polkadot_node_subsystem_util::{ backing_implicit_view::View as ImplicitView, reputation::{ReputationAggregator, REPUTATION_CHANGE_INTERVAL}, - runtime::{ - fetch_claim_queue, get_availability_cores, get_group_rotation_info, - prospective_parachains_mode, ProspectiveParachainsMode, RuntimeInfo, - }, + runtime::{fetch_claim_queue, get_group_rotation_info, ClaimQueueSnapshot, RuntimeInfo}, TimeoutExt, }; use polkadot_primitives::{ - vstaging::{CandidateReceiptV2 as CandidateReceipt, CoreState}, - AuthorityDiscoveryId, CandidateHash, CollatorPair, CoreIndex, GroupIndex, Hash, HeadData, - Id as ParaId, SessionIndex, + vstaging::CandidateReceiptV2 as CandidateReceipt, AuthorityDiscoveryId, CandidateHash, + CollatorPair, CoreIndex, GroupIndex, Hash, HeadData, Id as ParaId, SessionIndex, }; use super::LOG_TARGET; @@ -199,8 +194,6 @@ impl ValidatorGroup { struct PeerData { /// Peer's view. view: View, - /// Network protocol version. - version: CollationVersion, /// Unknown heads in the view. /// /// This can happen when the validator is faster at importing a block and sending out its @@ -229,21 +222,27 @@ impl CollationWithCoreIndex { } struct PerRelayParent { - prospective_parachains_mode: ProspectiveParachainsMode, /// Per core index validators group responsible for backing candidates built /// on top of this relay parent. validator_group: HashMap<CoreIndex, ValidatorGroup>, /// Distributed collations. collations: HashMap<CandidateHash, CollationWithCoreIndex>, + /// Number of assignments per core + assignments: HashMap<CoreIndex, usize>, } impl PerRelayParent { - fn new(mode: ProspectiveParachainsMode) -> Self { - Self { - prospective_parachains_mode: mode, - validator_group: HashMap::default(), - collations: HashMap::new(), - } + fn new(para_id: ParaId, claim_queue: ClaimQueueSnapshot) -> Self { + let assignments = + claim_queue.iter_all_claims().fold(HashMap::new(), |mut acc, (core, claims)| { + let n_claims = claims.iter().filter(|para| para == &¶_id).count(); + if n_claims > 0 { + acc.insert(*core, n_claims); + } + acc + }); + + Self { validator_group: HashMap::default(), collations: HashMap::new(), assignments } } } @@ -262,24 +261,11 @@ struct State { /// to determine what is relevant to them. peer_data: HashMap<PeerId, PeerData>, - /// Leaves that do support asynchronous backing along with - /// implicit ancestry. Leaves from the implicit view are present in - /// `active_leaves`, the opposite doesn't hold true. - /// - /// Relay-chain blocks which don't support prospective parachains are - /// never included in the fragment chains of active leaves which do. In - /// particular, this means that if a given relay parent belongs to implicit - /// ancestry of some active leaf, then it does support prospective parachains. + /// Leaves along with implicit ancestry. /// /// It's `None` if the collator is not yet collating for a paraid. implicit_view: Option<ImplicitView>, - /// All active leaves observed by us, including both that do and do not - /// support prospective parachains. This mapping works as a replacement for - /// [`polkadot_node_network_protocol::View`] and can be dropped once the transition - /// to asynchronous backing is done. - active_leaves: HashMap<Hash, ProspectiveParachainsMode>, - /// Validators and distributed collations tracked for each relay parent from /// our view, including both leaves and implicit ancestry. per_relay_parent: HashMap<Hash, PerRelayParent>, @@ -340,7 +326,6 @@ impl State { collating_on: Default::default(), peer_data: Default::default(), implicit_view: None, - active_leaves: Default::default(), per_relay_parent: Default::default(), collation_result_senders: Default::default(), peer_ids: Default::default(), @@ -359,7 +344,7 @@ impl State { /// Figure out the core our para is assigned to and the relevant validators. /// Issue a connection request to these validators. /// If the para is not scheduled or next up on any core, at the relay-parent, -/// or the relay-parent isn't in the active-leaves set, we ignore the message +/// or the relay-parent isn't in the implicit ancestry, we ignore the message /// as it must be invalid in that case - although this indicates a logic error /// elsewhere in the node. #[overseer::contextbounds(CollatorProtocol, prefix = self::overseer)] @@ -391,20 +376,32 @@ async fn distribute_collation<Context>( return Ok(()) }, }; - let relay_parent_mode = per_relay_parent.prospective_parachains_mode; - let collations_limit = match relay_parent_mode { - ProspectiveParachainsMode::Disabled => 1, - ProspectiveParachainsMode::Enabled { max_candidate_depth, .. } => max_candidate_depth + 1, + let Some(collations_limit) = per_relay_parent.assignments.get(&core_index) else { + gum::warn!( + target: LOG_TARGET, + para_id = %id, + relay_parent = ?candidate_relay_parent, + cores = ?per_relay_parent.assignments.keys(), + ?core_index, + "Attempting to distribute collation for a core we are not assigned to ", + ); + + return Ok(()) }; - if per_relay_parent.collations.len() >= collations_limit { + let current_collations_count = per_relay_parent + .collations + .values() + .filter(|c| c.core_index() == &core_index) + .count(); + if current_collations_count >= *collations_limit { gum::debug!( target: LOG_TARGET, ?candidate_relay_parent, - ?relay_parent_mode, - "The limit of {} collations per relay parent is already reached", + "The limit of {} collations per relay parent for core {} is already reached", collations_limit, + core_index.0, ); return Ok(()) } @@ -420,54 +417,21 @@ async fn distribute_collation<Context>( return Ok(()) } - // Determine which core(s) the para collated-on is assigned to. - // If it is not scheduled then ignore the message. - let (our_cores, num_cores) = - match determine_cores(ctx.sender(), id, candidate_relay_parent, relay_parent_mode).await? { - (cores, _num_cores) if cores.is_empty() => { - gum::warn!( - target: LOG_TARGET, - para_id = %id, - "looks like no core is assigned to {} at {}", id, candidate_relay_parent, - ); - - return Ok(()) - }, - (cores, num_cores) => (cores, num_cores), - }; - - let elastic_scaling = our_cores.len() > 1; + let elastic_scaling = per_relay_parent.assignments.len() > 1; if elastic_scaling { gum::debug!( target: LOG_TARGET, para_id = %id, - cores = ?our_cores, - "{} is assigned to {} cores at {}", id, our_cores.len(), candidate_relay_parent, + cores = ?per_relay_parent.assignments.keys(), + "{} is assigned to {} cores at {}", id, per_relay_parent.assignments.len(), candidate_relay_parent, ); } - // Double check that the specified `core_index` is among the ones our para has assignments for. - if !our_cores.iter().any(|assigned_core| assigned_core == &core_index) { - gum::warn!( - target: LOG_TARGET, - para_id = %id, - relay_parent = ?candidate_relay_parent, - cores = ?our_cores, - ?core_index, - "Attempting to distribute collation for a core we are not assigned to ", - ); - - return Ok(()) - } - let our_core = core_index; // Determine the group on that core. - // - // When prospective parachains are disabled, candidate relay parent here is - // guaranteed to be an active leaf. let GroupValidators { validators, session_index, group_index } = - determine_our_validators(ctx, runtime, our_core, num_cores, candidate_relay_parent).await?; + determine_our_validators(ctx, runtime, our_core, candidate_relay_parent).await?; if validators.is_empty() { gum::warn!( @@ -495,7 +459,6 @@ async fn distribute_collation<Context>( target: LOG_TARGET, para_id = %id, candidate_relay_parent = %candidate_relay_parent, - relay_parent_mode = ?relay_parent_mode, ?candidate_hash, pov_hash = ?pov.hash(), core = ?our_core, @@ -531,35 +494,32 @@ async fn distribute_collation<Context>( ), ); - // If prospective parachains are disabled, a leaf should be known to peer. - // Otherwise, it should be present in allowed ancestry of some leaf. + // The leaf should be present in the allowed ancestry of some leaf. // // It's collation-producer responsibility to verify that there exists // a hypothetical membership in a fragment chain for the candidate. - let interested = - state - .peer_data - .iter() - .filter(|(_, PeerData { view: v, .. })| match relay_parent_mode { - ProspectiveParachainsMode::Disabled => v.contains(&candidate_relay_parent), - ProspectiveParachainsMode::Enabled { .. } => v.iter().any(|block_hash| { - state.implicit_view.as_ref().map(|implicit_view| { - implicit_view - .known_allowed_relay_parents_under(block_hash, Some(id)) - .unwrap_or_default() - .contains(&candidate_relay_parent) - }) == Some(true) - }), - }); + let interested = state + .peer_data + .iter() + .filter(|(_, PeerData { view: v, .. })| { + v.iter().any(|block_hash| { + state.implicit_view.as_ref().map(|implicit_view| { + implicit_view + .known_allowed_relay_parents_under(block_hash, Some(id)) + .unwrap_or_default() + .contains(&candidate_relay_parent) + }) == Some(true) + }) + }) + .map(|(id, _)| id); // Make sure already connected peers get collations: - for (peer_id, peer_data) in interested { + for peer_id in interested { advertise_collation( ctx, candidate_relay_parent, per_relay_parent, peer_id, - peer_data.version, &state.peer_ids, &mut state.advertisement_timeouts, &state.metrics, @@ -570,45 +530,6 @@ async fn distribute_collation<Context>( Ok(()) } -/// Get the core indices that are assigned to the para being collated on if any -/// and the total number of cores. -async fn determine_cores( - sender: &mut impl overseer::SubsystemSender<RuntimeApiMessage>, - para_id: ParaId, - relay_parent: Hash, - relay_parent_mode: ProspectiveParachainsMode, -) -> Result<(Vec<CoreIndex>, usize)> { - let cores = get_availability_cores(sender, relay_parent).await?; - let n_cores = cores.len(); - let mut assigned_cores = Vec::new(); - let maybe_claim_queue = fetch_claim_queue(sender, relay_parent).await?; - - for (idx, core) in cores.iter().enumerate() { - let core_is_scheduled = match maybe_claim_queue { - Some(ref claim_queue) => { - // Runtime supports claim queue - use it. - claim_queue - .iter_claims_for_core(&CoreIndex(idx as u32)) - .any(|para| para == ¶_id) - }, - None => match core { - CoreState::Scheduled(scheduled) if scheduled.para_id == para_id => true, - CoreState::Occupied(occupied) if relay_parent_mode.is_enabled() => - // With async backing we don't care about the core state, - // it is only needed for figuring our validators group. - occupied.next_up_on_available.as_ref().map(|c| c.para_id) == Some(para_id), - _ => false, - }, - }; - - if core_is_scheduled { - assigned_cores.push(CoreIndex::from(idx as u32)); - } - } - - Ok((assigned_cores, n_cores)) -} - /// Validators of a particular group index. #[derive(Debug)] struct GroupValidators { @@ -627,7 +548,6 @@ async fn determine_our_validators<Context>( ctx: &mut Context, runtime: &mut RuntimeInfo, core_index: CoreIndex, - cores: usize, relay_parent: Hash, ) -> Result<GroupValidators> { let session_index = runtime.get_session_index_for_child(ctx.sender(), relay_parent).await?; @@ -637,9 +557,10 @@ async fn determine_our_validators<Context>( .session_info; gum::debug!(target: LOG_TARGET, ?session_index, "Received session info"); let groups = &info.validator_groups; + let num_cores = groups.len(); let rotation_info = get_group_rotation_info(ctx.sender(), relay_parent).await?; - let current_group_index = rotation_info.group_for_core(core_index, cores); + let current_group_index = rotation_info.group_for_core(core_index, num_cores); let current_validators = groups.get(current_group_index).map(|v| v.as_slice()).unwrap_or_default(); @@ -657,46 +578,24 @@ async fn determine_our_validators<Context>( Ok(current_validators) } -/// Construct the declare message to be sent to validator depending on its -/// network protocol version. +/// Construct the declare message to be sent to validator. fn declare_message( state: &mut State, - version: CollationVersion, ) -> Option<Versioned<protocol_v1::CollationProtocol, protocol_v2::CollationProtocol>> { let para_id = state.collating_on?; - Some(match version { - CollationVersion::V1 => { - let declare_signature_payload = - protocol_v1::declare_signature_payload(&state.local_peer_id); - let wire_message = protocol_v1::CollatorProtocolMessage::Declare( - state.collator_pair.public(), - para_id, - state.collator_pair.sign(&declare_signature_payload), - ); - Versioned::V1(protocol_v1::CollationProtocol::CollatorProtocol(wire_message)) - }, - CollationVersion::V2 => { - let declare_signature_payload = - protocol_v2::declare_signature_payload(&state.local_peer_id); - let wire_message = protocol_v2::CollatorProtocolMessage::Declare( - state.collator_pair.public(), - para_id, - state.collator_pair.sign(&declare_signature_payload), - ); - Versioned::V2(protocol_v2::CollationProtocol::CollatorProtocol(wire_message)) - }, - }) + let declare_signature_payload = protocol_v2::declare_signature_payload(&state.local_peer_id); + let wire_message = protocol_v2::CollatorProtocolMessage::Declare( + state.collator_pair.public(), + para_id, + state.collator_pair.sign(&declare_signature_payload), + ); + Some(Versioned::V2(protocol_v2::CollationProtocol::CollatorProtocol(wire_message))) } /// Issue versioned `Declare` collation message to the given `peer`. #[overseer::contextbounds(CollatorProtocol, prefix = self::overseer)] -async fn declare<Context>( - ctx: &mut Context, - state: &mut State, - peer: &PeerId, - version: CollationVersion, -) { - if let Some(wire_message) = declare_message(state, version) { +async fn declare<Context>(ctx: &mut Context, state: &mut State, peer: &PeerId) { + if let Some(wire_message) = declare_message(state) { ctx.send_message(NetworkBridgeTxMessage::SendCollationMessage(vec![*peer], wire_message)) .await; } @@ -735,7 +634,6 @@ async fn advertise_collation<Context>( relay_parent: Hash, per_relay_parent: &mut PerRelayParent, peer: &PeerId, - protocol_version: CollationVersion, peer_ids: &HashMap<PeerId, HashSet<AuthorityDiscoveryId>>, advertisement_timeouts: &mut FuturesUnordered<ResetInterestTimeout>, metrics: &Metrics, @@ -744,19 +642,6 @@ async fn advertise_collation<Context>( let core_index = *collation_and_core.core_index(); let collation = collation_and_core.collation_mut(); - // Check that peer will be able to request the collation. - if let CollationVersion::V1 = protocol_version { - if per_relay_parent.prospective_parachains_mode.is_enabled() { - gum::trace!( - target: LOG_TARGET, - ?relay_parent, - peer_id = %peer, - "Skipping advertising to validator, incorrect network protocol version", - ); - return - } - } - let Some(validator_group) = per_relay_parent.validator_group.get_mut(&core_index) else { gum::debug!( target: LOG_TARGET, @@ -793,25 +678,15 @@ async fn advertise_collation<Context>( collation.status.advance_to_advertised(); - let collation_message = match protocol_version { - CollationVersion::V2 => { - let wire_message = protocol_v2::CollatorProtocolMessage::AdvertiseCollation { + ctx.send_message(NetworkBridgeTxMessage::SendCollationMessage( + vec![*peer], + Versioned::V2(protocol_v2::CollationProtocol::CollatorProtocol( + protocol_v2::CollatorProtocolMessage::AdvertiseCollation { relay_parent, candidate_hash: *candidate_hash, parent_head_data_hash: collation.parent_head_data.hash(), - }; - Versioned::V2(protocol_v2::CollationProtocol::CollatorProtocol(wire_message)) - }, - CollationVersion::V1 => { - let wire_message = - protocol_v1::CollatorProtocolMessage::AdvertiseCollation(relay_parent); - Versioned::V1(protocol_v1::CollationProtocol::CollatorProtocol(wire_message)) - }, - }; - - ctx.send_message(NetworkBridgeTxMessage::SendCollationMessage( - vec![*peer], - collation_message, + }, + )), )) .await; @@ -933,7 +808,7 @@ async fn send_collation( parent_head_data: head_data, }), ParentHeadData::OnlyHash(_) => - Ok(request_v1::CollationFetchingResponse::Collation(receipt, pov)), + Ok(request_v2::CollationFetchingResponse::Collation(receipt, pov)), }; let response = @@ -998,7 +873,16 @@ async fn handle_incoming_peer_message<Context>( ctx.send_message(NetworkBridgeTxMessage::DisconnectPeer(origin, PeerSet::Collation)) .await; }, - Versioned::V1(V1::CollationSeconded(relay_parent, statement)) | + Versioned::V1(V1::CollationSeconded(relay_parent, statement)) => { + // Impossible, we no longer accept connections on v1. + gum::warn!( + target: LOG_TARGET, + ?statement, + ?origin, + ?relay_parent, + "Collation seconded message received on unsupported protocol version 1", + ); + }, Versioned::V2(V2::CollationSeconded(relay_parent, statement)) | Versioned::V3(V2::CollationSeconded(relay_parent, statement)) => { if !matches!(statement.unchecked_payload(), Statement::Seconded(_)) { @@ -1092,24 +976,10 @@ async fn handle_incoming_request<Context>( return Ok(()) }, }; - let mode = per_relay_parent.prospective_parachains_mode; let collation_with_core = match &req { - VersionedCollationRequest::V1(_) if !mode.is_enabled() => - per_relay_parent.collations.values_mut().next(), VersionedCollationRequest::V2(req) => per_relay_parent.collations.get_mut(&req.payload.candidate_hash), - _ => { - gum::warn!( - target: LOG_TARGET, - relay_parent = %relay_parent, - prospective_parachains_mode = ?mode, - ?peer_id, - "Collation request version is invalid", - ); - - return Ok(()) - }, }; let (receipt, pov, parent_head_data) = if let Some(collation_with_core) = collation_with_core { @@ -1187,9 +1057,7 @@ async fn handle_peer_view_change<Context>( peer_id: PeerId, view: View, ) { - let Some(PeerData { view: current, version, unknown_heads }) = - state.peer_data.get_mut(&peer_id) - else { + let Some(PeerData { view: current, unknown_heads }) = state.peer_data.get_mut(&peer_id) else { return }; @@ -1198,20 +1066,15 @@ async fn handle_peer_view_change<Context>( *current = view; for added in added.into_iter() { - let block_hashes = match state - .per_relay_parent - .get(&added) - .map(|per_relay_parent| per_relay_parent.prospective_parachains_mode) - { - Some(ProspectiveParachainsMode::Disabled) => std::slice::from_ref(&added), - Some(ProspectiveParachainsMode::Enabled { .. }) => state + let block_hashes = match state.per_relay_parent.contains_key(&added) { + true => state .implicit_view .as_ref() .and_then(|implicit_view| { implicit_view.known_allowed_relay_parents_under(&added, state.collating_on) }) .unwrap_or_default(), - None => { + false => { gum::trace!( target: LOG_TARGET, ?peer_id, @@ -1235,7 +1098,6 @@ async fn handle_peer_view_change<Context>( *block_hash, per_relay_parent, &peer_id, - *version, &state.peer_ids, &mut state.advertisement_timeouts, &state.metrics, @@ -1261,7 +1123,7 @@ async fn handle_network_msg<Context>( // it should be handled here. gum::trace!(target: LOG_TARGET, ?peer_id, ?observed_role, ?maybe_authority, "Peer connected"); - let version = match protocol_version.try_into() { + let version: CollationVersion = match protocol_version.try_into() { Ok(version) => version, Err(err) => { // Network bridge is expected to handle this. @@ -1275,9 +1137,25 @@ async fn handle_network_msg<Context>( return Ok(()) }, }; + if version == CollationVersion::V1 { + gum::warn!( + target: LOG_TARGET, + ?peer_id, + ?observed_role, + "Unsupported protocol version v1" + ); + + // V1 no longer supported, we should disconnect. + ctx.send_message(NetworkBridgeTxMessage::DisconnectPeer( + peer_id, + PeerSet::Collation, + )) + .await; + return Ok(()) + } + state.peer_data.entry(peer_id).or_insert_with(|| PeerData { view: View::default(), - version, // Unlikely that the collator is falling 10 blocks behind and if so, it probably is // not able to keep up any way. unknown_heads: LruMap::new(ByLength::new(10)), @@ -1292,7 +1170,7 @@ async fn handle_network_msg<Context>( ); state.peer_ids.insert(peer_id, authority_ids); - declare(ctx, state, &peer_id, version).await; + declare(ctx, state, &peer_id).await; } }, PeerViewChange(peer_id, view) => { @@ -1313,9 +1191,9 @@ async fn handle_network_msg<Context>( }, UpdatedAuthorityIds(peer_id, authority_ids) => { gum::trace!(target: LOG_TARGET, ?peer_id, ?authority_ids, "Updated authority ids"); - if let Some(version) = state.peer_data.get(&peer_id).map(|d| d.version) { + if state.peer_data.contains_key(&peer_id) { if state.peer_ids.insert(peer_id, authority_ids).is_none() { - declare(ctx, state, &peer_id, version).await; + declare(ctx, state, &peer_id).await; } } }, @@ -1334,77 +1212,66 @@ async fn handle_our_view_change<Context>( state: &mut State, view: OurView, ) -> Result<()> { - let current_leaves = state.active_leaves.clone(); + let Some(implicit_view) = &mut state.implicit_view else { return Ok(()) }; + let Some(para_id) = state.collating_on else { return Ok(()) }; - let removed = current_leaves.iter().filter(|(h, _)| !view.contains(h)); - let added = view.iter().filter(|h| !current_leaves.contains_key(h)); + let removed: Vec<_> = + implicit_view.leaves().map(|l| *l).filter(|h| !view.contains(h)).collect(); + let added: Vec<_> = view.iter().filter(|h| !implicit_view.contains_leaf(h)).collect(); for leaf in added { - let mode = prospective_parachains_mode(ctx.sender(), *leaf).await?; - - state.active_leaves.insert(*leaf, mode); - state.per_relay_parent.insert(*leaf, PerRelayParent::new(mode)); - - if mode.is_enabled() { - if let Some(ref mut implicit_view) = state.implicit_view { - implicit_view - .activate_leaf(ctx.sender(), *leaf) - .await - .map_err(Error::ImplicitViewFetchError)?; - - let allowed_ancestry = implicit_view - .known_allowed_relay_parents_under(leaf, state.collating_on) - .unwrap_or_default(); - - // Get the peers that already reported us this head, but we didn't knew it at this - // point. - let peers = state - .peer_data - .iter_mut() - .filter_map(|(id, data)| { - data.unknown_heads.remove(leaf).map(|_| (id, data.version)) - }) - .collect::<Vec<_>>(); - - for block_hash in allowed_ancestry { - let per_relay_parent = state - .per_relay_parent - .entry(*block_hash) - .or_insert_with(|| PerRelayParent::new(mode)); - - // Announce relevant collations to these peers. - for (peer_id, peer_version) in &peers { - advertise_collation( - ctx, - *block_hash, - per_relay_parent, - &peer_id, - *peer_version, - &state.peer_ids, - &mut state.advertisement_timeouts, - &state.metrics, - ) - .await; - } - } + let claim_queue = fetch_claim_queue(ctx.sender(), *leaf).await?; + state.per_relay_parent.insert(*leaf, PerRelayParent::new(para_id, claim_queue)); + + implicit_view + .activate_leaf(ctx.sender(), *leaf) + .await + .map_err(Error::ImplicitViewFetchError)?; + + let allowed_ancestry = implicit_view + .known_allowed_relay_parents_under(leaf, state.collating_on) + .unwrap_or_default(); + + // Get the peers that already reported us this head, but we didn't know it at this + // point. + let peers = state + .peer_data + .iter_mut() + .filter_map(|(id, data)| data.unknown_heads.remove(leaf).map(|_| id)) + .collect::<Vec<_>>(); + + for block_hash in allowed_ancestry { + if state.per_relay_parent.get(block_hash).is_none() { + let claim_queue = fetch_claim_queue(ctx.sender(), *block_hash).await?; + state + .per_relay_parent + .insert(*block_hash, PerRelayParent::new(para_id, claim_queue)); + } + + let per_relay_parent = + state.per_relay_parent.get_mut(block_hash).expect("Just inserted"); + + // Announce relevant collations to these peers. + for peer_id in &peers { + advertise_collation( + ctx, + *block_hash, + per_relay_parent, + &peer_id, + &state.peer_ids, + &mut state.advertisement_timeouts, + &state.metrics, + ) + .await; } } } - for (leaf, mode) in removed { - state.active_leaves.remove(leaf); + for leaf in removed { // If the leaf is deactivated it still may stay in the view as a part // of implicit ancestry. Only update the state after the hash is actually // pruned from the block info storage. - let pruned = if mode.is_enabled() { - state - .implicit_view - .as_mut() - .map(|view| view.deactivate_leaf(*leaf)) - .unwrap_or_default() - } else { - vec![*leaf] - }; + let pruned = implicit_view.deactivate_leaf(leaf); for removed in &pruned { gum::debug!(target: LOG_TARGET, relay_parent = ?removed, "Removing relay parent because our view changed."); @@ -1454,7 +1321,6 @@ pub(crate) async fn run<Context>( ctx: Context, local_peer_id: PeerId, collator_pair: CollatorPair, - req_v1_receiver: IncomingRequestReceiver<request_v1::CollationFetchingRequest>, req_v2_receiver: IncomingRequestReceiver<request_v2::CollationFetchingRequest>, metrics: Metrics, ) -> std::result::Result<(), FatalError> { @@ -1462,7 +1328,6 @@ pub(crate) async fn run<Context>( ctx, local_peer_id, collator_pair, - req_v1_receiver, req_v2_receiver, metrics, ReputationAggregator::default(), @@ -1476,7 +1341,6 @@ async fn run_inner<Context>( mut ctx: Context, local_peer_id: PeerId, collator_pair: CollatorPair, - mut req_v1_receiver: IncomingRequestReceiver<request_v1::CollationFetchingRequest>, mut req_v2_receiver: IncomingRequestReceiver<request_v2::CollationFetchingRequest>, metrics: Metrics, reputation: ReputationAggregator, @@ -1492,9 +1356,7 @@ async fn run_inner<Context>( loop { let reputation_changes = || vec![COST_INVALID_REQUEST]; - let recv_req_v1 = req_v1_receiver.recv(reputation_changes).fuse(); let recv_req_v2 = req_v2_receiver.recv(reputation_changes).fuse(); - pin_mut!(recv_req_v1); pin_mut!(recv_req_v2); let mut reconnect_timeout = &mut state.reconnect_timeout; @@ -1558,18 +1420,7 @@ async fn run_inner<Context>( None => continue, }; - match (per_relay_parent.prospective_parachains_mode, &next) { - (ProspectiveParachainsMode::Disabled, VersionedCollationRequest::V1(_)) => { - per_relay_parent.collations.values().next() - }, - (ProspectiveParachainsMode::Enabled { .. }, VersionedCollationRequest::V2(req)) => { - per_relay_parent.collations.get(&req.payload.candidate_hash) - }, - _ => { - // Request version is checked in `handle_incoming_request`. - continue - }, - } + per_relay_parent.collations.get(&next.candidate_hash()) }; if let Some(collation_with_core) = next_collation_with_core { @@ -1601,14 +1452,6 @@ async fn run_inner<Context>( "Peer-set updated due to a timeout" ); }, - in_req = recv_req_v1 => { - let request = in_req.map(VersionedCollationRequest::from); - - log_error( - handle_incoming_request(&mut ctx, &mut state, request).await, - "Handling incoming collation fetch request V1" - )?; - } in_req = recv_req_v2 => { let request = in_req.map(VersionedCollationRequest::from); diff --git a/polkadot/node/network/collator-protocol/src/collator_side/tests/mod.rs b/polkadot/node/network/collator-protocol/src/collator_side/tests/mod.rs index 23954f8d781bdfa7c78a0ddd75898aff1d893bd3..5e7bc2d569d41e04a7dee77d9dbd989ec7d0af52 100644 --- a/polkadot/node/network/collator-protocol/src/collator_side/tests/mod.rs +++ b/polkadot/node/network/collator-protocol/src/collator_side/tests/mod.rs @@ -33,33 +33,31 @@ use sp_keyring::Sr25519Keyring; use sp_runtime::traits::AppVerify; use polkadot_node_network_protocol::{ - our_view, peer_set::CollationVersion, - request_response::{IncomingRequest, ReqProtocolNames}, + request_response::{ + v2::{CollationFetchingRequest, CollationFetchingResponse}, + IncomingRequest, ReqProtocolNames, + }, view, }; use polkadot_node_primitives::BlockData; -use polkadot_node_subsystem::{ - errors::RuntimeApiError, - messages::{AllMessages, ReportPeerMessage, RuntimeApiMessage, RuntimeApiRequest}, - ActiveLeavesUpdate, +use polkadot_node_subsystem::messages::{ + AllMessages, ReportPeerMessage, RuntimeApiMessage, RuntimeApiRequest, }; use polkadot_node_subsystem_test_helpers as test_helpers; use polkadot_node_subsystem_util::{reputation::add_reputation, TimeoutExt}; use polkadot_primitives::{ AuthorityDiscoveryId, Block, CollatorPair, ExecutorParams, GroupIndex, GroupRotationInfo, - IndexedVec, NodeFeatures, ScheduledCore, SessionIndex, SessionInfo, ValidatorId, - ValidatorIndex, + IndexedVec, NodeFeatures, SessionIndex, SessionInfo, ValidatorId, ValidatorIndex, }; use polkadot_primitives_test_helpers::TestCandidateBuilder; -use test_helpers::mock::new_leaf; mod prospective_parachains; +use prospective_parachains::{expect_declare_msg, update_view}; const REPUTATION_CHANGE_TEST_INTERVAL: Duration = Duration::from_millis(10); -const ASYNC_BACKING_DISABLED_ERROR: RuntimeApiError = - RuntimeApiError::NotSupported { runtime_api_name: "test-runtime" }; +const SCHEDULING_LOOKAHEAD: usize = 4; #[derive(Clone)] struct TestState { @@ -108,7 +106,8 @@ impl Default for TestState { GroupRotationInfo { session_start_block: 0, group_rotation_frequency: 100, now: 1 }; let mut claim_queue = BTreeMap::new(); - claim_queue.insert(CoreIndex(0), [para_id].into_iter().collect()); + claim_queue + .insert(CoreIndex(0), std::iter::repeat(para_id).take(SCHEDULING_LOOKAHEAD).collect()); claim_queue.insert(CoreIndex(1), VecDeque::new()); let relay_parent = Hash::random(); @@ -179,47 +178,6 @@ impl TestState { .map(|i| self.session_info.discovery_keys[i.0 as usize].clone()) .collect() } - - /// Generate a new relay parent and inform the subsystem about the new view. - /// - /// If `merge_views == true` it means the subsystem will be informed that we are working on the - /// old `relay_parent` and the new one. - async fn advance_to_new_round( - &mut self, - virtual_overseer: &mut VirtualOverseer, - merge_views: bool, - ) { - let old_relay_parent = self.relay_parent; - - while self.relay_parent == old_relay_parent { - self.relay_parent.randomize(); - } - - let our_view = if merge_views { - our_view![old_relay_parent, self.relay_parent] - } else { - our_view![self.relay_parent] - }; - - overseer_send( - virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdate(NetworkBridgeEvent::OurViewChange( - our_view, - )), - ) - .await; - - assert_matches!( - overseer_recv(virtual_overseer).await, - AllMessages::RuntimeApi(RuntimeApiMessage::Request( - relay_parent, - RuntimeApiRequest::AsyncBackingParams(tx) - )) => { - assert_eq!(relay_parent, self.relay_parent); - tx.send(Err(ASYNC_BACKING_DISABLED_ERROR)).unwrap(); - } - ); - } } type VirtualOverseer = @@ -227,7 +185,6 @@ type VirtualOverseer = struct TestHarness { virtual_overseer: VirtualOverseer, - req_v1_cfg: sc_network::config::RequestResponseConfig, req_v2_cfg: sc_network::config::RequestResponseConfig, } @@ -247,10 +204,6 @@ fn test_harness<T: Future<Output = TestHarness>>( let genesis_hash = Hash::repeat_byte(0xff); let req_protocol_names = ReqProtocolNames::new(&genesis_hash, None); - let (collation_req_receiver, req_v1_cfg) = IncomingRequest::get_config_receiver::< - Block, - sc_network::NetworkWorker<Block, Hash>, - >(&req_protocol_names); let (collation_req_v2_receiver, req_v2_cfg) = IncomingRequest::get_config_receiver::< Block, sc_network::NetworkWorker<Block, Hash>, @@ -260,7 +213,6 @@ fn test_harness<T: Future<Output = TestHarness>>( context, local_peer_id, collator_pair, - collation_req_receiver, collation_req_v2_receiver, Default::default(), reputation, @@ -270,7 +222,7 @@ fn test_harness<T: Future<Output = TestHarness>>( .unwrap(); }; - let test_fut = test(TestHarness { virtual_overseer, req_v1_cfg, req_v2_cfg }); + let test_fut = test(TestHarness { virtual_overseer, req_v2_cfg }); futures::pin_mut!(test_fut); futures::pin_mut!(subsystem); @@ -334,39 +286,6 @@ async fn overseer_signal(overseer: &mut VirtualOverseer, signal: OverseerSignal) .expect(&format!("{:?} is more than enough for sending signals.", TIMEOUT)); } -// Setup the system by sending the `CollateOn`, `ActiveLeaves` and `OurViewChange` messages. -async fn setup_system(virtual_overseer: &mut VirtualOverseer, test_state: &TestState) { - overseer_send(virtual_overseer, CollatorProtocolMessage::CollateOn(test_state.para_id)).await; - - overseer_signal( - virtual_overseer, - OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(new_leaf( - test_state.relay_parent, - 1, - ))), - ) - .await; - - overseer_send( - virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdate(NetworkBridgeEvent::OurViewChange(our_view![ - test_state.relay_parent - ])), - ) - .await; - - assert_matches!( - overseer_recv(virtual_overseer).await, - AllMessages::RuntimeApi(RuntimeApiMessage::Request( - relay_parent, - RuntimeApiRequest::AsyncBackingParams(tx) - )) => { - assert_eq!(relay_parent, test_state.relay_parent); - tx.send(Err(ASYNC_BACKING_DISABLED_ERROR)).unwrap(); - } - ); -} - /// Result of [`distribute_collation`] struct DistributeCollation { candidate: CandidateReceipt, @@ -390,52 +309,11 @@ async fn distribute_collation_with_receipt( pov: pov.clone(), parent_head_data: HeadData(vec![1, 2, 3]), result_sender: None, - core_index: CoreIndex(0), + core_index: candidate.descriptor.core_index().unwrap(), }, ) .await; - // obtain the availability cores. - assert_matches!( - overseer_recv(virtual_overseer).await, - AllMessages::RuntimeApi(RuntimeApiMessage::Request( - _relay_parent, - RuntimeApiRequest::AvailabilityCores(tx) - )) => { - assert_eq!(relay_parent, _relay_parent); - tx.send(Ok(test_state.claim_queue.values().map(|paras| - if let Some(para) = paras.front() { - CoreState::Scheduled(ScheduledCore { para_id: *para, collator: None }) - } else { - CoreState::Free - } - ).collect())).unwrap(); - } - ); - - assert_matches!( - overseer_recv(virtual_overseer).await, - AllMessages::RuntimeApi(RuntimeApiMessage::Request( - _relay_parent, - RuntimeApiRequest::Version(tx) - )) => { - assert_eq!(relay_parent, _relay_parent); - tx.send(Ok(RuntimeApiRequest::CLAIM_QUEUE_RUNTIME_REQUIREMENT)).unwrap(); - } - ); - - // obtain the claim queue schedule. - assert_matches!( - overseer_recv(virtual_overseer).await, - AllMessages::RuntimeApi(RuntimeApiMessage::Request( - _relay_parent, - RuntimeApiRequest::ClaimQueue(tx) - )) => { - assert_eq!(relay_parent, _relay_parent); - tx.send(Ok(test_state.claim_queue.clone())).unwrap(); - } - ); - // We don't know precisely what is going to come as session info might be cached: loop { match overseer_recv(virtual_overseer).await { @@ -555,14 +433,16 @@ async fn connect_peer( ) .await; - overseer_send( - virtual_overseer, - CollatorProtocolMessage::NetworkBridgeUpdate(NetworkBridgeEvent::PeerViewChange( - peer, - view![], - )), - ) - .await; + if version != CollationVersion::V1 { + overseer_send( + virtual_overseer, + CollatorProtocolMessage::NetworkBridgeUpdate(NetworkBridgeEvent::PeerViewChange( + peer, + view![], + )), + ) + .await; + } } /// Disconnect a peer @@ -574,52 +454,15 @@ async fn disconnect_peer(virtual_overseer: &mut VirtualOverseer, peer: PeerId) { .await; } -/// Check that the next received message is a `Declare` message. -async fn expect_declare_msg( - virtual_overseer: &mut VirtualOverseer, - test_state: &TestState, - peer: &PeerId, -) { - assert_matches!( - overseer_recv(virtual_overseer).await, - AllMessages::NetworkBridgeTx( - NetworkBridgeTxMessage::SendCollationMessage( - to, - Versioned::V1(protocol_v1::CollationProtocol::CollatorProtocol(wire_message)), - ) - ) => { - assert_eq!(to[0], *peer); - assert_matches!( - wire_message, - protocol_v1::CollatorProtocolMessage::Declare( - collator_id, - para_id, - signature, - ) => { - assert!(signature.verify( - &*protocol_v1::declare_signature_payload(&test_state.local_peer_id), - &collator_id), - ); - assert_eq!(collator_id, test_state.collator_pair.public()); - assert_eq!(para_id, test_state.para_id); - } - ); - } - ); -} - /// Check that the next received message is a collation advertisement message. -/// -/// Expects v2 message if `expected_candidate_hashes` is `Some`, v1 otherwise. async fn expect_advertise_collation_msg( virtual_overseer: &mut VirtualOverseer, any_peers: &[PeerId], expected_relay_parent: Hash, - expected_candidate_hashes: Option<Vec<CandidateHash>>, + expected_candidate_hashes: Vec<CandidateHash>, ) { - let mut candidate_hashes: Option<HashSet<_>> = - expected_candidate_hashes.map(|hashes| hashes.into_iter().collect()); - let iter_num = candidate_hashes.as_ref().map(|hashes| hashes.len()).unwrap_or(1); + let mut candidate_hashes: HashSet<_> = expected_candidate_hashes.into_iter().collect(); + let iter_num = candidate_hashes.len(); for _ in 0..iter_num { assert_matches!( @@ -631,23 +474,10 @@ async fn expect_advertise_collation_msg( ) ) => { assert!(any_peers.iter().any(|p| to.contains(p))); - match (candidate_hashes.as_mut(), wire_message) { - (None, Versioned::V1(protocol_v1::CollationProtocol::CollatorProtocol(wire_message))) => { - assert_matches!( - wire_message, - protocol_v1::CollatorProtocolMessage::AdvertiseCollation( - relay_parent, - ) => { - assert_eq!(relay_parent, expected_relay_parent); - } - ); - }, - ( - Some(candidate_hashes), - Versioned::V2(protocol_v2::CollationProtocol::CollatorProtocol( - wire_message, - )), - ) => { + match wire_message { + Versioned::V2(protocol_v2::CollationProtocol::CollatorProtocol( + wire_message, + )) => { assert_matches!( wire_message, protocol_v2::CollatorProtocolMessage::AdvertiseCollation { @@ -687,17 +517,59 @@ async fn send_peer_view_change( } fn decode_collation_response(bytes: &[u8]) -> (CandidateReceipt, PoV) { - let response: request_v1::CollationFetchingResponse = - request_v1::CollationFetchingResponse::decode(&mut &bytes[..]) - .expect("Decoding should work"); + let response: CollationFetchingResponse = + CollationFetchingResponse::decode(&mut &bytes[..]).expect("Decoding should work"); match response { - request_v1::CollationFetchingResponse::Collation(receipt, pov) => (receipt, pov), - request_v1::CollationFetchingResponse::CollationWithParentHeadData { - receipt, pov, .. - } => (receipt, pov), + CollationFetchingResponse::Collation(receipt, pov) => (receipt, pov), + CollationFetchingResponse::CollationWithParentHeadData { receipt, pov, .. } => + (receipt, pov), } } +// Test that connecting on v1 results in disconnect. +#[test] +fn v1_protocol_rejected() { + let test_state = TestState::default(); + let local_peer_id = test_state.local_peer_id; + let collator_pair = test_state.collator_pair.clone(); + + test_harness( + local_peer_id, + collator_pair, + ReputationAggregator::new(|_| true), + |mut test_harness| async move { + let virtual_overseer = &mut test_harness.virtual_overseer; + + overseer_send(virtual_overseer, CollatorProtocolMessage::CollateOn(test_state.para_id)) + .await; + + update_view(&test_state, virtual_overseer, vec![(test_state.relay_parent, 10)], 1) + .await; + + distribute_collation(virtual_overseer, &test_state, test_state.relay_parent, true) + .await; + + for (val, peer) in test_state + .current_group_validator_authority_ids() + .into_iter() + .zip(test_state.current_group_validator_peer_ids()) + { + connect_peer(virtual_overseer, peer, CollationVersion::V1, Some(val.clone())).await; + + assert_matches!( + overseer_recv(virtual_overseer).await, + AllMessages::NetworkBridgeTx(NetworkBridgeTxMessage::DisconnectPeer(bad_peer, peer_set)) => { + assert_eq!(peer_set, PeerSet::Collation); + assert_eq!(bad_peer, peer); + } + ); + } + + test_harness + }, + ); +} + #[test] fn advertise_and_send_collation() { let mut test_state = TestState::default(); @@ -710,10 +582,16 @@ fn advertise_and_send_collation() { ReputationAggregator::new(|_| true), |test_harness| async move { let mut virtual_overseer = test_harness.virtual_overseer; - let mut req_v1_cfg = test_harness.req_v1_cfg; - let req_v2_cfg = test_harness.req_v2_cfg; + let mut req_v2_cfg = test_harness.req_v2_cfg; + + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::CollateOn(test_state.para_id), + ) + .await; - setup_system(&mut virtual_overseer, &test_state).await; + update_view(&test_state, &mut virtual_overseer, vec![(test_state.relay_parent, 10)], 1) + .await; let DistributeCollation { candidate, pov_block } = distribute_collation( &mut virtual_overseer, @@ -728,7 +606,7 @@ fn advertise_and_send_collation() { .into_iter() .zip(test_state.current_group_validator_peer_ids()) { - connect_peer(&mut virtual_overseer, peer, CollationVersion::V1, Some(val.clone())) + connect_peer(&mut virtual_overseer, peer, CollationVersion::V2, Some(val.clone())) .await; } @@ -751,20 +629,21 @@ fn advertise_and_send_collation() { &mut virtual_overseer, &[peer], test_state.relay_parent, - None, + vec![candidate.hash()], ) .await; // Request a collation. let (pending_response, rx) = oneshot::channel(); - req_v1_cfg + req_v2_cfg .inbound_queue .as_mut() .unwrap() .send(RawIncomingRequest { peer, - payload: request_v1::CollationFetchingRequest { + payload: CollationFetchingRequest { relay_parent: test_state.relay_parent, + candidate_hash: candidate.hash(), para_id: test_state.para_id, } .encode(), @@ -776,14 +655,15 @@ fn advertise_and_send_collation() { { let (pending_response, rx) = oneshot::channel(); - req_v1_cfg + req_v2_cfg .inbound_queue .as_mut() .unwrap() .send(RawIncomingRequest { peer, - payload: request_v1::CollationFetchingRequest { + payload: CollationFetchingRequest { relay_parent: test_state.relay_parent, + candidate_hash: candidate.hash(), para_id: test_state.para_id, } .encode(), @@ -817,21 +697,26 @@ fn advertise_and_send_collation() { ); let old_relay_parent = test_state.relay_parent; - test_state.advance_to_new_round(&mut virtual_overseer, false).await; + test_state.relay_parent.randomize(); + + // Update our view, making the old relay parent go out of the implicit view. + update_view(&test_state, &mut virtual_overseer, vec![(test_state.relay_parent, 20)], 1) + .await; let peer = test_state.validator_peer_id[2]; - // Re-request a collation. + // Re-request the collation. let (pending_response, rx) = oneshot::channel(); - req_v1_cfg + req_v2_cfg .inbound_queue .as_mut() .unwrap() .send(RawIncomingRequest { peer, - payload: request_v1::CollationFetchingRequest { + payload: CollationFetchingRequest { relay_parent: old_relay_parent, + candidate_hash: candidate.hash(), para_id: test_state.para_id, } .encode(), @@ -839,13 +724,18 @@ fn advertise_and_send_collation() { }) .await .unwrap(); - // Re-requesting collation should fail: + // Re-requesting collation should fail, becasue the relay parent is out of the view. rx.await.unwrap_err(); assert!(overseer_recv_with_timeout(&mut virtual_overseer, TIMEOUT).await.is_none()); - distribute_collation(&mut virtual_overseer, &test_state, test_state.relay_parent, true) - .await; + let DistributeCollation { candidate, .. } = distribute_collation( + &mut virtual_overseer, + &test_state, + test_state.relay_parent, + true, + ) + .await; // Send info about peer's view. overseer_send( @@ -861,10 +751,10 @@ fn advertise_and_send_collation() { &mut virtual_overseer, &[peer], test_state.relay_parent, - None, + vec![candidate.hash()], ) .await; - TestHarness { virtual_overseer, req_v1_cfg, req_v2_cfg } + TestHarness { virtual_overseer, req_v2_cfg } }, ); } @@ -881,12 +771,18 @@ fn delay_reputation_change() { ReputationAggregator::new(|_| false), |test_harness| async move { let mut virtual_overseer = test_harness.virtual_overseer; - let mut req_v1_cfg = test_harness.req_v1_cfg; - let req_v2_cfg = test_harness.req_v2_cfg; + let mut req_v2_cfg = test_harness.req_v2_cfg; - setup_system(&mut virtual_overseer, &test_state).await; + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::CollateOn(test_state.para_id), + ) + .await; + + update_view(&test_state, &mut virtual_overseer, vec![(test_state.relay_parent, 10)], 1) + .await; - let _ = distribute_collation( + let DistributeCollation { candidate, .. } = distribute_collation( &mut virtual_overseer, &test_state, test_state.relay_parent, @@ -899,7 +795,7 @@ fn delay_reputation_change() { .into_iter() .zip(test_state.current_group_validator_peer_ids()) { - connect_peer(&mut virtual_overseer, peer, CollationVersion::V1, Some(val.clone())) + connect_peer(&mut virtual_overseer, peer, CollationVersion::V2, Some(val.clone())) .await; } @@ -922,21 +818,22 @@ fn delay_reputation_change() { &mut virtual_overseer, &[peer], test_state.relay_parent, - None, + vec![candidate.hash()], ) .await; // Request a collation. let (pending_response, _rx) = oneshot::channel(); - req_v1_cfg + req_v2_cfg .inbound_queue .as_mut() .unwrap() .send(RawIncomingRequest { peer, - payload: request_v1::CollationFetchingRequest { + payload: CollationFetchingRequest { relay_parent: test_state.relay_parent, para_id: test_state.para_id, + candidate_hash: candidate.hash(), } .encode(), pending_response, @@ -947,15 +844,16 @@ fn delay_reputation_change() { { let (pending_response, _rx) = oneshot::channel(); - req_v1_cfg + req_v2_cfg .inbound_queue .as_mut() .unwrap() .send(RawIncomingRequest { peer, - payload: request_v1::CollationFetchingRequest { + payload: CollationFetchingRequest { relay_parent: test_state.relay_parent, para_id: test_state.para_id, + candidate_hash: candidate.hash(), } .encode(), pending_response, @@ -978,85 +876,7 @@ fn delay_reputation_change() { ); } - TestHarness { virtual_overseer, req_v1_cfg, req_v2_cfg } - }, - ); -} - -/// Tests that collator side works with v2 network protocol -/// before async backing is enabled. -#[test] -fn advertise_collation_v2_protocol() { - let test_state = TestState::default(); - let local_peer_id = test_state.local_peer_id; - let collator_pair = test_state.collator_pair.clone(); - - test_harness( - local_peer_id, - collator_pair, - ReputationAggregator::new(|_| true), - |mut test_harness| async move { - let virtual_overseer = &mut test_harness.virtual_overseer; - - setup_system(virtual_overseer, &test_state).await; - - let DistributeCollation { candidate, .. } = - distribute_collation(virtual_overseer, &test_state, test_state.relay_parent, true) - .await; - - let validators = test_state.current_group_validator_authority_ids(); - assert!(validators.len() >= 2); - let peer_ids = test_state.current_group_validator_peer_ids(); - - // Connect first peer with v1. - connect_peer( - virtual_overseer, - peer_ids[0], - CollationVersion::V1, - Some(validators[0].clone()), - ) - .await; - // The rest with v2. - for (val, peer) in validators.iter().zip(peer_ids.iter()).skip(1) { - connect_peer(virtual_overseer, *peer, CollationVersion::V2, Some(val.clone())) - .await; - } - - // Declare messages. - expect_declare_msg(virtual_overseer, &test_state, &peer_ids[0]).await; - for peer_id in peer_ids.iter().skip(1) { - prospective_parachains::expect_declare_msg_v2( - virtual_overseer, - &test_state, - &peer_id, - ) - .await; - } - - // Send info about peers view. - for peer in peer_ids.iter() { - send_peer_view_change(virtual_overseer, peer, vec![test_state.relay_parent]).await; - } - - // Versioned advertisements work. - expect_advertise_collation_msg( - virtual_overseer, - &[peer_ids[0]], - test_state.relay_parent, - None, - ) - .await; - for peer_id in peer_ids.iter().skip(1) { - expect_advertise_collation_msg( - virtual_overseer, - &[*peer_id], - test_state.relay_parent, - Some(vec![candidate.hash()]), // This is `Some`, advertisement is v2. - ) - .await; - } - - test_harness + TestHarness { virtual_overseer, req_v2_cfg } }, ); } @@ -1100,13 +920,25 @@ fn collators_declare_to_connected_peers() { let peer = test_state.validator_peer_id[0]; let validator_id = test_state.current_group_validator_authority_ids()[0].clone(); - setup_system(&mut test_harness.virtual_overseer, &test_state).await; + overseer_send( + &mut test_harness.virtual_overseer, + CollatorProtocolMessage::CollateOn(test_state.para_id), + ) + .await; + + update_view( + &test_state, + &mut test_harness.virtual_overseer, + vec![(test_state.relay_parent, 10)], + 1, + ) + .await; // A validator connected to us connect_peer( &mut test_harness.virtual_overseer, peer, - CollationVersion::V1, + CollationVersion::V2, Some(validator_id), ) .await; @@ -1135,13 +967,17 @@ fn collations_are_only_advertised_to_validators_with_correct_view() { let peer2 = test_state.current_group_validator_peer_ids()[1]; let validator_id2 = test_state.current_group_validator_authority_ids()[1].clone(); - setup_system(virtual_overseer, &test_state).await; + overseer_send(virtual_overseer, CollatorProtocolMessage::CollateOn(test_state.para_id)) + .await; + + update_view(&test_state, virtual_overseer, vec![(test_state.relay_parent, 10)], 1) + .await; // A validator connected to us - connect_peer(virtual_overseer, peer, CollationVersion::V1, Some(validator_id)).await; + connect_peer(virtual_overseer, peer, CollationVersion::V2, Some(validator_id)).await; // Connect the second validator - connect_peer(virtual_overseer, peer2, CollationVersion::V1, Some(validator_id2)).await; + connect_peer(virtual_overseer, peer2, CollationVersion::V2, Some(validator_id2)).await; expect_declare_msg(virtual_overseer, &test_state, &peer).await; expect_declare_msg(virtual_overseer, &test_state, &peer2).await; @@ -1149,14 +985,15 @@ fn collations_are_only_advertised_to_validators_with_correct_view() { // And let it tell us that it is has the same view. send_peer_view_change(virtual_overseer, &peer2, vec![test_state.relay_parent]).await; - distribute_collation(virtual_overseer, &test_state, test_state.relay_parent, true) - .await; + let DistributeCollation { candidate, .. } = + distribute_collation(virtual_overseer, &test_state, test_state.relay_parent, true) + .await; expect_advertise_collation_msg( virtual_overseer, &[peer2], test_state.relay_parent, - None, + vec![candidate.hash()], ) .await; @@ -1168,7 +1005,7 @@ fn collations_are_only_advertised_to_validators_with_correct_view() { virtual_overseer, &[peer], test_state.relay_parent, - None, + vec![candidate.hash()], ) .await; test_harness @@ -1195,31 +1032,50 @@ fn collate_on_two_different_relay_chain_blocks() { let peer2 = test_state.current_group_validator_peer_ids()[1]; let validator_id2 = test_state.current_group_validator_authority_ids()[1].clone(); - setup_system(virtual_overseer, &test_state).await; + overseer_send(virtual_overseer, CollatorProtocolMessage::CollateOn(test_state.para_id)) + .await; + + update_view(&test_state, virtual_overseer, vec![(test_state.relay_parent, 10)], 1) + .await; // A validator connected to us - connect_peer(virtual_overseer, peer, CollationVersion::V1, Some(validator_id)).await; + connect_peer(virtual_overseer, peer, CollationVersion::V2, Some(validator_id)).await; // Connect the second validator - connect_peer(virtual_overseer, peer2, CollationVersion::V1, Some(validator_id2)).await; + connect_peer(virtual_overseer, peer2, CollationVersion::V2, Some(validator_id2)).await; expect_declare_msg(virtual_overseer, &test_state, &peer).await; expect_declare_msg(virtual_overseer, &test_state, &peer2).await; - distribute_collation(virtual_overseer, &test_state, test_state.relay_parent, true) - .await; + let DistributeCollation { candidate: old_candidate, .. } = + distribute_collation(virtual_overseer, &test_state, test_state.relay_parent, true) + .await; let old_relay_parent = test_state.relay_parent; - // Advance to a new round, while informing the subsystem that the old and the new relay + // Update our view, informing the subsystem that the old and the new relay // parent are active. - test_state.advance_to_new_round(virtual_overseer, true).await; + test_state.relay_parent.randomize(); + update_view( + &test_state, + virtual_overseer, + vec![(old_relay_parent, 10), (test_state.relay_parent, 10)], + 1, + ) + .await; - distribute_collation(virtual_overseer, &test_state, test_state.relay_parent, true) - .await; + let DistributeCollation { candidate: new_candidate, .. } = + distribute_collation(virtual_overseer, &test_state, test_state.relay_parent, true) + .await; send_peer_view_change(virtual_overseer, &peer, vec![old_relay_parent]).await; - expect_advertise_collation_msg(virtual_overseer, &[peer], old_relay_parent, None).await; + expect_advertise_collation_msg( + virtual_overseer, + &[peer], + old_relay_parent, + vec![old_candidate.hash()], + ) + .await; send_peer_view_change(virtual_overseer, &peer2, vec![test_state.relay_parent]).await; @@ -1227,7 +1083,7 @@ fn collate_on_two_different_relay_chain_blocks() { virtual_overseer, &[peer2], test_state.relay_parent, - None, + vec![new_candidate.hash()], ) .await; test_harness @@ -1251,28 +1107,33 @@ fn validator_reconnect_does_not_advertise_a_second_time() { let peer = test_state.current_group_validator_peer_ids()[0]; let validator_id = test_state.current_group_validator_authority_ids()[0].clone(); - setup_system(virtual_overseer, &test_state).await; + overseer_send(virtual_overseer, CollatorProtocolMessage::CollateOn(test_state.para_id)) + .await; + + update_view(&test_state, virtual_overseer, vec![(test_state.relay_parent, 10)], 1) + .await; // A validator connected to us - connect_peer(virtual_overseer, peer, CollationVersion::V1, Some(validator_id.clone())) + connect_peer(virtual_overseer, peer, CollationVersion::V2, Some(validator_id.clone())) .await; expect_declare_msg(virtual_overseer, &test_state, &peer).await; - distribute_collation(virtual_overseer, &test_state, test_state.relay_parent, true) - .await; + let DistributeCollation { candidate, .. } = + distribute_collation(virtual_overseer, &test_state, test_state.relay_parent, true) + .await; send_peer_view_change(virtual_overseer, &peer, vec![test_state.relay_parent]).await; expect_advertise_collation_msg( virtual_overseer, &[peer], test_state.relay_parent, - None, + vec![candidate.hash()], ) .await; // Disconnect and reconnect directly disconnect_peer(virtual_overseer, peer).await; - connect_peer(virtual_overseer, peer, CollationVersion::V1, Some(validator_id)).await; + connect_peer(virtual_overseer, peer, CollationVersion::V2, Some(validator_id)).await; expect_declare_msg(virtual_overseer, &test_state, &peer).await; send_peer_view_change(virtual_overseer, &peer, vec![test_state.relay_parent]).await; @@ -1300,10 +1161,14 @@ fn collators_reject_declare_messages() { let peer = test_state.current_group_validator_peer_ids()[0]; let validator_id = test_state.current_group_validator_authority_ids()[0].clone(); - setup_system(virtual_overseer, &test_state).await; + overseer_send(virtual_overseer, CollatorProtocolMessage::CollateOn(test_state.para_id)) + .await; + + update_view(&test_state, virtual_overseer, vec![(test_state.relay_parent, 10)], 1) + .await; // A validator connected to us - connect_peer(virtual_overseer, peer, CollationVersion::V1, Some(validator_id)).await; + connect_peer(virtual_overseer, peer, CollationVersion::V2, Some(validator_id)).await; expect_declare_msg(virtual_overseer, &test_state, &peer).await; overseer_send( @@ -1355,9 +1220,13 @@ where ReputationAggregator::new(|_| true), |mut test_harness| async move { let virtual_overseer = &mut test_harness.virtual_overseer; - let req_cfg = &mut test_harness.req_v1_cfg; + let req_cfg = &mut test_harness.req_v2_cfg; + + overseer_send(virtual_overseer, CollatorProtocolMessage::CollateOn(test_state.para_id)) + .await; - setup_system(virtual_overseer, &test_state).await; + update_view(&test_state, virtual_overseer, vec![(test_state.relay_parent, 10)], 1) + .await; let DistributeCollation { candidate, pov_block } = distribute_collation(virtual_overseer, &test_state, test_state.relay_parent, true) @@ -1368,7 +1237,7 @@ where .into_iter() .zip(test_state.current_group_validator_peer_ids()) { - connect_peer(virtual_overseer, peer, CollationVersion::V1, Some(val.clone())).await; + connect_peer(virtual_overseer, peer, CollationVersion::V2, Some(val.clone())).await; } // We declare to the connected validators that we are a collator. @@ -1393,14 +1262,14 @@ where virtual_overseer, &[validator_0], test_state.relay_parent, - None, + vec![candidate.hash()], ) .await; expect_advertise_collation_msg( virtual_overseer, &[validator_1], test_state.relay_parent, - None, + vec![candidate.hash()], ) .await; @@ -1412,9 +1281,10 @@ where .unwrap() .send(RawIncomingRequest { peer: validator_0, - payload: request_v1::CollationFetchingRequest { + payload: CollationFetchingRequest { relay_parent: test_state.relay_parent, para_id: test_state.para_id, + candidate_hash: candidate.hash(), } .encode(), pending_response, @@ -1446,9 +1316,10 @@ where .unwrap() .send(RawIncomingRequest { peer: validator_1, - payload: request_v1::CollationFetchingRequest { + payload: CollationFetchingRequest { relay_parent: test_state.relay_parent, para_id: test_state.para_id, + candidate_hash: candidate.hash(), } .encode(), pending_response, @@ -1490,16 +1361,22 @@ fn connect_to_buffered_groups() { ReputationAggregator::new(|_| true), |test_harness| async move { let mut virtual_overseer = test_harness.virtual_overseer; - let mut req_cfg = test_harness.req_v1_cfg; - let req_v2_cfg = test_harness.req_v2_cfg; + let mut req_cfg = test_harness.req_v2_cfg; + + overseer_send( + &mut virtual_overseer, + CollatorProtocolMessage::CollateOn(test_state.para_id), + ) + .await; - setup_system(&mut virtual_overseer, &test_state).await; + update_view(&test_state, &mut virtual_overseer, vec![(test_state.relay_parent, 10)], 1) + .await; let group_a = test_state.current_group_validator_authority_ids(); let peers_a = test_state.current_group_validator_peer_ids(); assert!(group_a.len() > 1); - distribute_collation( + let DistributeCollation { candidate, .. } = distribute_collation( &mut virtual_overseer, &test_state, test_state.relay_parent, @@ -1519,7 +1396,7 @@ fn connect_to_buffered_groups() { let head_a = test_state.relay_parent; for (val, peer) in group_a.iter().zip(&peers_a) { - connect_peer(&mut virtual_overseer, *peer, CollationVersion::V1, Some(val.clone())) + connect_peer(&mut virtual_overseer, *peer, CollationVersion::V2, Some(val.clone())) .await; } @@ -1530,8 +1407,13 @@ fn connect_to_buffered_groups() { // Update views. for peer_id in &peers_a { send_peer_view_change(&mut virtual_overseer, peer_id, vec![head_a]).await; - expect_advertise_collation_msg(&mut virtual_overseer, &[*peer_id], head_a, None) - .await; + expect_advertise_collation_msg( + &mut virtual_overseer, + &[*peer_id], + head_a, + vec![candidate.hash()], + ) + .await; } let peer = peers_a[0]; @@ -1543,9 +1425,10 @@ fn connect_to_buffered_groups() { .unwrap() .send(RawIncomingRequest { peer, - payload: request_v1::CollationFetchingRequest { + payload: CollationFetchingRequest { relay_parent: head_a, para_id: test_state.para_id, + candidate_hash: candidate.hash(), } .encode(), pending_response, @@ -1565,7 +1448,17 @@ fn connect_to_buffered_groups() { // Let the subsystem process process the collation event. test_helpers::Yield::new().await; - test_state.advance_to_new_round(&mut virtual_overseer, true).await; + let old_relay_parent = test_state.relay_parent; + test_state.relay_parent.randomize(); + + // Update our view. + update_view( + &test_state, + &mut virtual_overseer, + vec![(old_relay_parent, 10), (test_state.relay_parent, 20)], + 1, + ) + .await; test_state.group_rotation_info = test_state.group_rotation_info.bump_rotation(); let head_b = test_state.relay_parent; @@ -1596,7 +1489,7 @@ fn connect_to_buffered_groups() { } ); - TestHarness { virtual_overseer, req_v1_cfg: req_cfg, req_v2_cfg } + TestHarness { virtual_overseer, req_v2_cfg: req_cfg } }, ); } diff --git a/polkadot/node/network/collator-protocol/src/collator_side/tests/prospective_parachains.rs b/polkadot/node/network/collator-protocol/src/collator_side/tests/prospective_parachains.rs index 348feb9dd1dbc01641556b25c813e4f4c205c870..a5c74a1205c9ef5ef3d2e6d3d55a7e54c912c9f6 100644 --- a/polkadot/node/network/collator-protocol/src/collator_side/tests/prospective_parachains.rs +++ b/polkadot/node/network/collator-protocol/src/collator_side/tests/prospective_parachains.rs @@ -19,17 +19,16 @@ use super::*; use polkadot_node_subsystem::messages::ChainApiMessage; -use polkadot_primitives::{AsyncBackingParams, Header}; - -const ASYNC_BACKING_PARAMETERS: AsyncBackingParams = - AsyncBackingParams { max_candidate_depth: 4, allowed_ancestry_len: 3 }; +use polkadot_primitives::Header; +use rstest::rstest; fn get_parent_hash(hash: Hash) -> Hash { Hash::from_low_u64_be(hash.to_low_u64_be() + 1) } /// Handle a view update. -async fn update_view( +pub(super) async fn update_view( + test_state: &TestState, virtual_overseer: &mut VirtualOverseer, new_view: Vec<(Hash, u32)>, // Hash and block number. activated: u8, // How many new heads does this update contain? @@ -45,18 +44,19 @@ async fn update_view( .await; for _ in 0..activated { + // obtain the claim queue schedule. let (leaf_hash, leaf_number) = assert_matches!( overseer_recv(virtual_overseer).await, AllMessages::RuntimeApi(RuntimeApiMessage::Request( parent, - RuntimeApiRequest::AsyncBackingParams(tx), + RuntimeApiRequest::ClaimQueue(tx), )) => { - tx.send(Ok(ASYNC_BACKING_PARAMETERS)).unwrap(); + tx.send(Ok(test_state.claim_queue.clone())).unwrap(); (parent, new_view.get(&parent).copied().expect("Unknown parent requested")) } ); - let min_number = leaf_number.saturating_sub(ASYNC_BACKING_PARAMETERS.allowed_ancestry_len); + let min_number = leaf_number.saturating_sub(SCHEDULING_LOOKAHEAD as u32 - 1); let ancestry_len = leaf_number + 1 - min_number; let ancestry_hashes = std::iter::successors(Some(leaf_hash), |h| Some(get_parent_hash(*h))) @@ -85,12 +85,12 @@ async fn update_view( AllMessages::RuntimeApi( RuntimeApiMessage::Request( .., - RuntimeApiRequest::AsyncBackingParams( + RuntimeApiRequest::SessionIndexForChild( tx ) ) ) => { - tx.send(Ok(ASYNC_BACKING_PARAMETERS)).unwrap(); + tx.send(Ok(1)).unwrap(); } ); @@ -99,12 +99,14 @@ async fn update_view( AllMessages::RuntimeApi( RuntimeApiMessage::Request( .., - RuntimeApiRequest::SessionIndexForChild( + RuntimeApiRequest::SchedulingLookahead( + session_index, tx ) ) ) => { - tx.send(Ok(1)).unwrap(); + assert_eq!(session_index, 1); + tx.send(Ok(SCHEDULING_LOOKAHEAD as u32)).unwrap(); } ); @@ -117,9 +119,10 @@ async fn update_view( .. } ) => { - assert_eq!(k, ASYNC_BACKING_PARAMETERS.allowed_ancestry_len as usize); - - tx.send(Ok(ancestry_hashes.clone().skip(1).into_iter().collect())).unwrap(); + assert_eq!(k, SCHEDULING_LOOKAHEAD - 1); + let hashes: Vec<_> = ancestry_hashes.clone().skip(1).into_iter().collect(); + assert_eq!(k, hashes.len()); + tx.send(Ok(hashes)).unwrap(); } ); } @@ -140,10 +143,11 @@ async fn update_view( ); } - while let Some((hash, number)) = ancestry_iter.next() { + let mut iter_clone = ancestry_iter.clone(); + while let Some((hash, number)) = iter_clone.next() { // May be `None` for the last element. let parent_hash = - ancestry_iter.peek().map(|(h, _)| *h).unwrap_or_else(|| get_parent_hash(hash)); + iter_clone.peek().map(|(h, _)| *h).unwrap_or_else(|| get_parent_hash(hash)); let Some(msg) = overseer_peek_with_timeout(virtual_overseer, Duration::from_millis(50)).await @@ -175,11 +179,40 @@ async fn update_view( } ); } + + for _ in ancestry_iter { + let Some(msg) = + overseer_peek_with_timeout(virtual_overseer, Duration::from_millis(50)).await + else { + return + }; + + if !matches!( + &msg, + AllMessages::RuntimeApi(RuntimeApiMessage::Request( + _, + RuntimeApiRequest::ClaimQueue(_) + )) + ) { + // Claim queue has already been fetched for this leaf. + break + } + + assert_matches!( + overseer_recv_with_timeout(virtual_overseer, Duration::from_millis(50)).await.unwrap(), + AllMessages::RuntimeApi(RuntimeApiMessage::Request( + _, + RuntimeApiRequest::ClaimQueue(tx), + )) => { + tx.send(Ok(test_state.claim_queue.clone())).unwrap(); + } + ); + } } } /// Check that the next received message is a `Declare` message. -pub(super) async fn expect_declare_msg_v2( +pub(super) async fn expect_declare_msg( virtual_overseer: &mut VirtualOverseer, test_state: &TestState, peer: &PeerId, @@ -214,8 +247,12 @@ pub(super) async fn expect_declare_msg_v2( /// Test that a collator distributes a collation from the allowed ancestry /// to correct validators group. -#[test] -fn distribute_collation_from_implicit_view() { +/// Run once with validators sending their view first and then the collator setting their own +/// view first. +#[rstest] +#[case(true)] +#[case(false)] +fn distribute_collation_from_implicit_view(#[case] validator_sends_view_first: bool) { let head_a = Hash::from_low_u64_be(126); let head_a_num: u32 = 66; @@ -227,163 +264,160 @@ fn distribute_collation_from_implicit_view() { let head_c = Hash::from_low_u64_be(130); let head_c_num = 62; - // Run once with validators sending their view first and then the collator setting their own - // view first. - for validator_sends_view_first in [true, false] { - let group_rotation_info = GroupRotationInfo { - session_start_block: head_c_num - 2, - group_rotation_frequency: 3, - now: head_c_num, - }; - - let mut test_state = TestState::default(); - test_state.group_rotation_info = group_rotation_info; - - let local_peer_id = test_state.local_peer_id; - let collator_pair = test_state.collator_pair.clone(); - - test_harness( - local_peer_id, - collator_pair, - ReputationAggregator::new(|_| true), - |mut test_harness| async move { - let virtual_overseer = &mut test_harness.virtual_overseer; - - // Set collating para id. - overseer_send( + let group_rotation_info = GroupRotationInfo { + session_start_block: head_c_num - 2, + group_rotation_frequency: 3, + now: head_c_num, + }; + + let mut test_state = TestState::default(); + test_state.group_rotation_info = group_rotation_info; + + let local_peer_id = test_state.local_peer_id; + let collator_pair = test_state.collator_pair.clone(); + + test_harness( + local_peer_id, + collator_pair, + ReputationAggregator::new(|_| true), + |mut test_harness| async move { + let virtual_overseer = &mut test_harness.virtual_overseer; + + // Set collating para id. + overseer_send(virtual_overseer, CollatorProtocolMessage::CollateOn(test_state.para_id)) + .await; + + if validator_sends_view_first { + // Activate leaf `c` to accept at least the collation. + update_view(&test_state, virtual_overseer, vec![(head_c, head_c_num)], 1).await; + } else { + // Activated leaf is `b`, but the collation will be based on `c`. + update_view(&test_state, virtual_overseer, vec![(head_b, head_b_num)], 1).await; + } + + let validator_peer_ids = test_state.current_group_validator_peer_ids(); + for (val, peer) in test_state + .current_group_validator_authority_ids() + .into_iter() + .zip(validator_peer_ids.clone()) + { + connect_peer(virtual_overseer, peer, CollationVersion::V2, Some(val.clone())).await; + } + + // Collator declared itself to each peer. + for peer_id in &validator_peer_ids { + expect_declare_msg(virtual_overseer, &test_state, peer_id).await; + } + + let pov = PoV { block_data: BlockData(vec![1, 2, 3]) }; + let parent_head_data_hash = Hash::repeat_byte(0xAA); + let candidate = TestCandidateBuilder { + para_id: test_state.para_id, + relay_parent: head_c, + pov_hash: pov.hash(), + ..Default::default() + } + .build(); + let DistributeCollation { candidate, pov_block: _ } = + distribute_collation_with_receipt( virtual_overseer, - CollatorProtocolMessage::CollateOn(test_state.para_id), + &test_state, + head_c, + false, // Check the group manually. + candidate, + pov, + parent_head_data_hash, ) .await; + assert_matches!( + overseer_recv(virtual_overseer).await, + AllMessages::NetworkBridgeTx( + NetworkBridgeTxMessage::ConnectToValidators { validator_ids, .. } + ) => { + let expected_validators = test_state.current_group_validator_authority_ids(); - if validator_sends_view_first { - // Activate leaf `c` to accept at least the collation. - update_view(virtual_overseer, vec![(head_c, head_c_num)], 1).await; - } else { - // Activated leaf is `b`, but the collation will be based on `c`. - update_view(virtual_overseer, vec![(head_b, head_b_num)], 1).await; + assert_eq!(expected_validators, validator_ids); } + ); - let validator_peer_ids = test_state.current_group_validator_peer_ids(); - for (val, peer) in test_state - .current_group_validator_authority_ids() - .into_iter() - .zip(validator_peer_ids.clone()) - { - connect_peer(virtual_overseer, peer, CollationVersion::V2, Some(val.clone())) - .await; - } + let candidate_hash = candidate.hash(); - // Collator declared itself to each peer. - for peer_id in &validator_peer_ids { - expect_declare_msg_v2(virtual_overseer, &test_state, peer_id).await; - } + // Update peer views. + for peer_id in &validator_peer_ids { + send_peer_view_change(virtual_overseer, peer_id, vec![head_b]).await; - let pov = PoV { block_data: BlockData(vec![1, 2, 3]) }; - let parent_head_data_hash = Hash::repeat_byte(0xAA); - let candidate = TestCandidateBuilder { - para_id: test_state.para_id, - relay_parent: head_c, - pov_hash: pov.hash(), - ..Default::default() - } - .build(); - let DistributeCollation { candidate, pov_block: _ } = - distribute_collation_with_receipt( + if !validator_sends_view_first { + expect_advertise_collation_msg( virtual_overseer, - &test_state, + &[*peer_id], head_c, - false, // Check the group manually. - candidate, - pov, - parent_head_data_hash, + vec![candidate_hash], ) .await; - assert_matches!( - overseer_recv(virtual_overseer).await, - AllMessages::NetworkBridgeTx( - NetworkBridgeTxMessage::ConnectToValidators { validator_ids, .. } - ) => { - let expected_validators = test_state.current_group_validator_authority_ids(); - - assert_eq!(expected_validators, validator_ids); - } - ); - - let candidate_hash = candidate.hash(); - - // Update peer views. - for peer_id in &validator_peer_ids { - send_peer_view_change(virtual_overseer, peer_id, vec![head_b]).await; - - if !validator_sends_view_first { - expect_advertise_collation_msg( - virtual_overseer, - &[*peer_id], - head_c, - Some(vec![candidate_hash]), - ) - .await; - } } + } - if validator_sends_view_first { - // Activated leaf is `b`, but the collation will be based on `c`. - update_view(virtual_overseer, vec![(head_b, head_b_num)], 1).await; + if validator_sends_view_first { + // Activated leaf is `b`, but the collation will be based on `c`. + update_view(&test_state, virtual_overseer, vec![(head_b, head_b_num)], 1).await; - for _ in &validator_peer_ids { - expect_advertise_collation_msg( - virtual_overseer, - &validator_peer_ids, - head_c, - Some(vec![candidate_hash]), - ) - .await; - } + for _ in &validator_peer_ids { + expect_advertise_collation_msg( + virtual_overseer, + &validator_peer_ids, + head_c, + vec![candidate_hash], + ) + .await; } + } - // Head `c` goes out of view. - // Build a different candidate for this relay parent and attempt to distribute it. - update_view(virtual_overseer, vec![(head_a, head_a_num)], 1).await; + // Head `c` goes out of view. + // Build a different candidate for this relay parent and attempt to distribute it. + update_view(&test_state, virtual_overseer, vec![(head_a, head_a_num)], 1).await; - let pov = PoV { block_data: BlockData(vec![4, 5, 6]) }; - let parent_head_data_hash = Hash::repeat_byte(0xBB); - let candidate = TestCandidateBuilder { - para_id: test_state.para_id, - relay_parent: head_c, - pov_hash: pov.hash(), - ..Default::default() - } - .build(); - overseer_send( - virtual_overseer, - CollatorProtocolMessage::DistributeCollation { - candidate_receipt: candidate.clone(), - parent_head_data_hash, - pov: pov.clone(), - parent_head_data: HeadData(vec![1, 2, 3]), - result_sender: None, - core_index: CoreIndex(0), - }, - ) - .await; + let pov = PoV { block_data: BlockData(vec![4, 5, 6]) }; + let parent_head_data_hash = Hash::repeat_byte(0xBB); + let candidate = TestCandidateBuilder { + para_id: test_state.para_id, + relay_parent: head_c, + pov_hash: pov.hash(), + ..Default::default() + } + .build(); + overseer_send( + virtual_overseer, + CollatorProtocolMessage::DistributeCollation { + candidate_receipt: candidate.clone(), + parent_head_data_hash, + pov: pov.clone(), + parent_head_data: HeadData(vec![1, 2, 3]), + result_sender: None, + core_index: CoreIndex(0), + }, + ) + .await; - // Parent out of view, nothing happens. - assert!(overseer_recv_with_timeout(virtual_overseer, Duration::from_millis(100)) - .await - .is_none()); + // Parent out of view, nothing happens. + assert!(overseer_recv_with_timeout(virtual_overseer, Duration::from_millis(100)) + .await + .is_none()); - test_harness - }, - ); - } + test_harness + }, + ); } -/// Tests that collator can distribute up to `MAX_CANDIDATE_DEPTH + 1` candidates -/// per relay parent. +/// Tests that collator respects the per relay parent limit of collations, which is equal to the +/// number of assignments they have in the claim queue for that core. #[test] fn distribute_collation_up_to_limit() { - let test_state = TestState::default(); + let mut test_state = TestState::default(); + // Claim queue has 4 assignments for our paraid on core 0, 1 assignment for another paraid on + // core 1. Let's replace one of our assignments on core 0. + + *test_state.claim_queue.get_mut(&CoreIndex(0)).unwrap().get_mut(1).unwrap() = ParaId::from(3); + let expected_assignments = SCHEDULING_LOOKAHEAD - 1; let local_peer_id = test_state.local_peer_id; let collator_pair = test_state.collator_pair.clone(); @@ -405,15 +439,16 @@ fn distribute_collation_up_to_limit() { overseer_send(virtual_overseer, CollatorProtocolMessage::CollateOn(test_state.para_id)) .await; // Activated leaf is `a`, but the collation will be based on `b`. - update_view(virtual_overseer, vec![(head_a, head_a_num)], 1).await; + update_view(&test_state, virtual_overseer, vec![(head_a, head_a_num)], 1).await; - for i in 0..(ASYNC_BACKING_PARAMETERS.max_candidate_depth + 1) { + for i in 0..expected_assignments { let pov = PoV { block_data: BlockData(vec![i as u8]) }; let parent_head_data_hash = Hash::repeat_byte(0xAA); let candidate = TestCandidateBuilder { para_id: test_state.para_id, relay_parent: head_b, pov_hash: pov.hash(), + core_index: CoreIndex(0), ..Default::default() } .build(); @@ -435,6 +470,7 @@ fn distribute_collation_up_to_limit() { para_id: test_state.para_id, relay_parent: head_b, pov_hash: pov.hash(), + core_index: CoreIndex(0), ..Default::default() } .build(); @@ -452,6 +488,35 @@ fn distribute_collation_up_to_limit() { .await; // Limit has been reached. + assert!(overseer_recv_with_timeout(virtual_overseer, Duration::from_millis(100)) + .await + .is_none()); + + // Let's also try on core 1, where we don't have any assignments. + + let pov = PoV { block_data: BlockData(vec![10, 12, 6]) }; + let parent_head_data_hash = Hash::repeat_byte(0xBB); + let candidate = TestCandidateBuilder { + para_id: test_state.para_id, + relay_parent: head_b, + pov_hash: pov.hash(), + core_index: CoreIndex(1), + ..Default::default() + } + .build(); + overseer_send( + virtual_overseer, + CollatorProtocolMessage::DistributeCollation { + candidate_receipt: candidate.clone(), + parent_head_data_hash, + pov: pov.clone(), + parent_head_data: HeadData(vec![1, 2, 3]), + result_sender: None, + core_index: CoreIndex(1), + }, + ) + .await; + assert!(overseer_recv_with_timeout(virtual_overseer, Duration::from_millis(100)) .await .is_none()); @@ -476,7 +541,6 @@ fn send_parent_head_data_for_elastic_scaling() { ReputationAggregator::new(|_| true), |test_harness| async move { let mut virtual_overseer = test_harness.virtual_overseer; - let req_v1_cfg = test_harness.req_v1_cfg; let mut req_v2_cfg = test_harness.req_v2_cfg; let head_b = Hash::from_low_u64_be(129); @@ -488,7 +552,7 @@ fn send_parent_head_data_for_elastic_scaling() { CollatorProtocolMessage::CollateOn(test_state.para_id), ) .await; - update_view(&mut virtual_overseer, vec![(head_b, head_b_num)], 1).await; + update_view(&test_state, &mut virtual_overseer, vec![(head_b, head_b_num)], 1).await; let pov_data = PoV { block_data: BlockData(vec![1 as u8]) }; let candidate = TestCandidateBuilder { @@ -522,12 +586,11 @@ fn send_parent_head_data_for_elastic_scaling() { Some(validator_id.clone()), ) .await; - expect_declare_msg_v2(&mut virtual_overseer, &test_state, &peer).await; + expect_declare_msg(&mut virtual_overseer, &test_state, &peer).await; send_peer_view_change(&mut virtual_overseer, &peer, vec![head_b]).await; let hashes: Vec<_> = vec![candidate.hash()]; - expect_advertise_collation_msg(&mut virtual_overseer, &[peer], head_b, Some(hashes)) - .await; + expect_advertise_collation_msg(&mut virtual_overseer, &[peer], head_b, hashes).await; let (pending_response, rx) = oneshot::channel(); req_v2_cfg @@ -536,7 +599,7 @@ fn send_parent_head_data_for_elastic_scaling() { .unwrap() .send(RawIncomingRequest { peer, - payload: request_v2::CollationFetchingRequest { + payload: CollationFetchingRequest { relay_parent: head_b, para_id: test_state.para_id, candidate_hash: candidate.hash(), @@ -550,14 +613,14 @@ fn send_parent_head_data_for_elastic_scaling() { assert_matches!( rx.await, Ok(full_response) => { - let response: request_v2::CollationFetchingResponse = - request_v2::CollationFetchingResponse::decode(&mut - full_response.result + let response: CollationFetchingResponse = + CollationFetchingResponse::decode( + &mut full_response.result .expect("We should have a proper answer").as_ref() ).expect("Decoding should work"); assert_matches!( response, - request_v1::CollationFetchingResponse::CollationWithParentHeadData { + CollationFetchingResponse::CollationWithParentHeadData { receipt, pov, parent_head_data } => { assert_eq!(receipt, candidate); @@ -568,7 +631,7 @@ fn send_parent_head_data_for_elastic_scaling() { } ); - TestHarness { virtual_overseer, req_v1_cfg, req_v2_cfg } + TestHarness { virtual_overseer, req_v2_cfg } }, ) } @@ -587,7 +650,6 @@ fn advertise_and_send_collation_by_hash() { ReputationAggregator::new(|_| true), |test_harness| async move { let mut virtual_overseer = test_harness.virtual_overseer; - let req_v1_cfg = test_harness.req_v1_cfg; let mut req_v2_cfg = test_harness.req_v2_cfg; let head_a = Hash::from_low_u64_be(128); @@ -603,8 +665,8 @@ fn advertise_and_send_collation_by_hash() { CollatorProtocolMessage::CollateOn(test_state.para_id), ) .await; - update_view(&mut virtual_overseer, vec![(head_b, head_b_num)], 1).await; - update_view(&mut virtual_overseer, vec![(head_a, head_a_num)], 1).await; + update_view(&test_state, &mut virtual_overseer, vec![(head_b, head_b_num)], 1).await; + update_view(&test_state, &mut virtual_overseer, vec![(head_a, head_a_num)], 1).await; let candidates: Vec<_> = (0..2) .map(|i| { @@ -641,13 +703,12 @@ fn advertise_and_send_collation_by_hash() { Some(validator_id.clone()), ) .await; - expect_declare_msg_v2(&mut virtual_overseer, &test_state, &peer).await; + expect_declare_msg(&mut virtual_overseer, &test_state, &peer).await; // Head `b` is not a leaf, but both advertisements are still relevant. send_peer_view_change(&mut virtual_overseer, &peer, vec![head_b]).await; let hashes: Vec<_> = candidates.iter().map(|(candidate, _)| candidate.hash()).collect(); - expect_advertise_collation_msg(&mut virtual_overseer, &[peer], head_b, Some(hashes)) - .await; + expect_advertise_collation_msg(&mut virtual_overseer, &[peer], head_b, hashes).await; for (candidate, pov_block) in candidates { let (pending_response, rx) = oneshot::channel(); @@ -657,7 +718,7 @@ fn advertise_and_send_collation_by_hash() { .unwrap() .send(RawIncomingRequest { peer, - payload: request_v2::CollationFetchingRequest { + payload: CollationFetchingRequest { relay_parent: head_b, para_id: test_state.para_id, candidate_hash: candidate.hash(), @@ -682,7 +743,7 @@ fn advertise_and_send_collation_by_hash() { ); } - TestHarness { virtual_overseer, req_v1_cfg, req_v2_cfg } + TestHarness { virtual_overseer, req_v2_cfg } }, ) } diff --git a/polkadot/node/network/collator-protocol/src/lib.rs b/polkadot/node/network/collator-protocol/src/lib.rs index 1edc67664172400503158f8a451756ca3674a3d9..79b5719ba3a448e6ce6e4bcac40a8924359eb59c 100644 --- a/polkadot/node/network/collator-protocol/src/lib.rs +++ b/polkadot/node/network/collator-protocol/src/lib.rs @@ -32,7 +32,7 @@ use polkadot_node_subsystem_util::reputation::ReputationAggregator; use sp_keystore::KeystorePtr; use polkadot_node_network_protocol::{ - request_response::{v1 as request_v1, v2 as protocol_v2, IncomingRequestReceiver}, + request_response::{v2 as protocol_v2, IncomingRequestReceiver}, PeerId, UnifiedReputationChange as Rep, }; use polkadot_primitives::CollatorPair; @@ -81,8 +81,6 @@ pub enum ProtocolSide { peer_id: PeerId, /// Parachain collator pair. collator_pair: CollatorPair, - /// Receiver for v1 collation fetching requests. - request_receiver_v1: IncomingRequestReceiver<request_v1::CollationFetchingRequest>, /// Receiver for v2 collation fetching requests. request_receiver_v2: IncomingRequestReceiver<protocol_v2::CollationFetchingRequest>, /// Metrics. @@ -116,22 +114,10 @@ impl<Context> CollatorProtocolSubsystem { validator_side::run(ctx, keystore, eviction_policy, metrics) .map_err(|e| SubsystemError::with_origin("collator-protocol", e)) .boxed(), - ProtocolSide::Collator { - peer_id, - collator_pair, - request_receiver_v1, - request_receiver_v2, - metrics, - } => collator_side::run( - ctx, - peer_id, - collator_pair, - request_receiver_v1, - request_receiver_v2, - metrics, - ) - .map_err(|e| SubsystemError::with_origin("collator-protocol", e)) - .boxed(), + ProtocolSide::Collator { peer_id, collator_pair, request_receiver_v2, metrics } => + collator_side::run(ctx, peer_id, collator_pair, request_receiver_v2, metrics) + .map_err(|e| SubsystemError::with_origin("collator-protocol", e)) + .boxed(), ProtocolSide::None => return DummySubsystem.start(ctx), }; diff --git a/polkadot/node/network/collator-protocol/src/validator_side/claim_queue_state.rs b/polkadot/node/network/collator-protocol/src/validator_side/claim_queue_state.rs index 3a34cf52fec6e897c854a022af6bf97107929d6a..d677da1ac4f03329bf77df2a85c355b96f8aeb9d 100644 --- a/polkadot/node/network/collator-protocol/src/validator_side/claim_queue_state.rs +++ b/polkadot/node/network/collator-protocol/src/validator_side/claim_queue_state.rs @@ -155,7 +155,7 @@ impl ClaimQueueState { fn get_window<'a>( &'a mut self, relay_parent: &'a Hash, - ) -> impl Iterator<Item = &mut ClaimInfo> + 'a { + ) -> impl Iterator<Item = &'a mut ClaimInfo> + 'a { let mut window = self .block_state .iter_mut() diff --git a/polkadot/node/network/collator-protocol/src/validator_side/mod.rs b/polkadot/node/network/collator-protocol/src/validator_side/mod.rs index 5f5effcde9a8cd4f2d03a8b38da7591aa27fc2ba..93a8c31168c8980a6159121e9ab6d84fccbfb6d5 100644 --- a/polkadot/node/network/collator-protocol/src/validator_side/mod.rs +++ b/polkadot/node/network/collator-protocol/src/validator_side/mod.rs @@ -49,14 +49,14 @@ use polkadot_node_subsystem::{ use polkadot_node_subsystem_util::{ backing_implicit_view::View as ImplicitView, reputation::{ReputationAggregator, REPUTATION_CHANGE_INTERVAL}, - request_async_backing_params, request_claim_queue, request_session_index_for_child, - runtime::{recv_runtime, request_node_features}, + request_claim_queue, request_session_index_for_child, + runtime::request_node_features, }; use polkadot_primitives::{ node_features, vstaging::{CandidateDescriptorV2, CandidateDescriptorVersion}, - AsyncBackingParams, CandidateHash, CollatorId, CoreIndex, Hash, HeadData, Id as ParaId, - OccupiedCoreAssumption, PersistedValidationData, SessionIndex, + CandidateHash, CollatorId, CoreIndex, Hash, HeadData, Id as ParaId, OccupiedCoreAssumption, + PersistedValidationData, SessionIndex, }; use crate::error::{Error, FetchError, Result, SecondingError}; @@ -166,7 +166,7 @@ impl PeerData { fn update_view( &mut self, implicit_view: &ImplicitView, - active_leaves: &HashMap<Hash, AsyncBackingParams>, + active_leaves: &HashSet<Hash>, new_view: View, ) { let old_view = std::mem::replace(&mut self.view, new_view); @@ -191,7 +191,7 @@ impl PeerData { fn prune_old_advertisements( &mut self, implicit_view: &ImplicitView, - active_leaves: &HashMap<Hash, AsyncBackingParams>, + active_leaves: &HashSet<Hash>, ) { if let PeerState::Collating(ref mut peer_state) = self.state { peer_state.advertisements.retain(|hash, _| { @@ -215,7 +215,7 @@ impl PeerData { on_relay_parent: Hash, candidate_hash: Option<CandidateHash>, implicit_view: &ImplicitView, - active_leaves: &HashMap<Hash, AsyncBackingParams>, + active_leaves: &HashSet<Hash>, per_relay_parent: &PerRelayParent, ) -> std::result::Result<(CollatorId, ParaId), InsertAdvertisementError> { match self.state { @@ -365,10 +365,10 @@ struct State { /// ancestry of some active leaf, then it does support prospective parachains. implicit_view: ImplicitView, - /// All active leaves observed by us. This mapping works as a replacement for + /// All active leaves observed by us. This works as a replacement for /// [`polkadot_node_network_protocol::View`] and can be dropped once the transition /// to asynchronous backing is done. - active_leaves: HashMap<Hash, AsyncBackingParams>, + active_leaves: HashSet<Hash>, /// State tracked per relay parent. per_relay_parent: HashMap<Hash, PerRelayParent>, @@ -465,10 +465,10 @@ impl State { fn is_relay_parent_in_implicit_view( relay_parent: &Hash, implicit_view: &ImplicitView, - active_leaves: &HashMap<Hash, AsyncBackingParams>, + active_leaves: &HashSet<Hash>, para_id: ParaId, ) -> bool { - active_leaves.iter().any(|(hash, _)| { + active_leaves.iter().any(|hash| { implicit_view .known_allowed_relay_parents_under(hash, Some(para_id)) .unwrap_or_default() @@ -1118,8 +1118,7 @@ where { let peer_data = state.peer_data.get_mut(&peer_id).ok_or(AdvertisementError::UnknownPeer)?; - if peer_data.version == CollationVersion::V1 && !state.active_leaves.contains_key(&relay_parent) - { + if peer_data.version == CollationVersion::V1 && !state.active_leaves.contains(&relay_parent) { return Err(AdvertisementError::ProtocolMisuse) } @@ -1274,8 +1273,8 @@ where { let current_leaves = state.active_leaves.clone(); - let removed = current_leaves.iter().filter(|(h, _)| !view.contains(h)); - let added = view.iter().filter(|h| !current_leaves.contains_key(h)); + let removed = current_leaves.iter().filter(|h| !view.contains(h)); + let added = view.iter().filter(|h| !current_leaves.contains(h)); for leaf in added { let session_index = request_session_index_for_child(*leaf, sender) @@ -1283,9 +1282,6 @@ where .await .map_err(Error::CancelledSessionIndex)??; - let async_backing_params = - recv_runtime(request_async_backing_params(*leaf, sender).await).await?; - let v2_receipts = request_node_features(*leaf, session_index, sender) .await? .unwrap_or_default() @@ -1306,7 +1302,7 @@ where continue }; - state.active_leaves.insert(*leaf, async_backing_params); + state.active_leaves.insert(*leaf); state.per_relay_parent.insert(*leaf, per_relay_parent); state @@ -1340,7 +1336,7 @@ where } } - for (removed, _) in removed { + for removed in removed { gum::trace!( target: LOG_TARGET, ?view, diff --git a/polkadot/node/network/collator-protocol/src/validator_side/tests/mod.rs b/polkadot/node/network/collator-protocol/src/validator_side/tests/mod.rs index 5a2e135419dd2645f7efbea29ba86fc3441d4858..308aec578dee0ddc26f664f747ebf58ae5080a1c 100644 --- a/polkadot/node/network/collator-protocol/src/validator_side/tests/mod.rs +++ b/polkadot/node/network/collator-protocol/src/validator_side/tests/mod.rs @@ -41,9 +41,9 @@ use polkadot_node_subsystem::messages::{ use polkadot_node_subsystem_test_helpers as test_helpers; use polkadot_node_subsystem_util::{reputation::add_reputation, TimeoutExt}; use polkadot_primitives::{ - node_features, vstaging::CandidateReceiptV2 as CandidateReceipt, AsyncBackingParams, - CollatorPair, CoreIndex, GroupRotationInfo, HeadData, NodeFeatures, PersistedValidationData, - ValidatorId, ValidatorIndex, + node_features, vstaging::CandidateReceiptV2 as CandidateReceipt, CollatorPair, CoreIndex, + GroupRotationInfo, HeadData, NodeFeatures, PersistedValidationData, ValidatorId, + ValidatorIndex, }; use polkadot_primitives_test_helpers::{dummy_candidate_receipt_bad_sig, dummy_hash}; @@ -71,7 +71,7 @@ struct TestState { validator_groups: Vec<Vec<ValidatorIndex>>, group_rotation_info: GroupRotationInfo, claim_queue: BTreeMap<CoreIndex, VecDeque<ParaId>>, - async_backing_params: AsyncBackingParams, + scheduling_lookahead: u32, node_features: NodeFeatures, session_index: SessionIndex, // Used by `update_view` to keep track of latest requested ancestor @@ -101,18 +101,19 @@ impl Default for TestState { let group_rotation_info = GroupRotationInfo { session_start_block: 0, group_rotation_frequency: 1, now: 0 }; + let scheduling_lookahead = 3; let mut claim_queue = BTreeMap::new(); claim_queue.insert( CoreIndex(0), iter::repeat(ParaId::from(Self::CHAIN_IDS[0])) - .take(Self::ASYNC_BACKING_PARAMS.allowed_ancestry_len as usize) + .take(scheduling_lookahead as usize) .collect(), ); claim_queue.insert(CoreIndex(1), VecDeque::new()); claim_queue.insert( CoreIndex(2), iter::repeat(ParaId::from(Self::CHAIN_IDS[1])) - .take(Self::ASYNC_BACKING_PARAMS.allowed_ancestry_len as usize) + .take(scheduling_lookahead as usize) .collect(), ); @@ -128,7 +129,7 @@ impl Default for TestState { validator_groups, group_rotation_info, claim_queue, - async_backing_params: Self::ASYNC_BACKING_PARAMS, + scheduling_lookahead, node_features, session_index: 1, last_known_block: None, @@ -138,8 +139,6 @@ impl Default for TestState { impl TestState { const CHAIN_IDS: [u32; 2] = [1, 2]; - const ASYNC_BACKING_PARAMS: AsyncBackingParams = - AsyncBackingParams { max_candidate_depth: 4, allowed_ancestry_len: 3 }; fn with_shared_core() -> Self { let mut state = Self::default(); @@ -159,8 +158,7 @@ impl TestState { state.validator_groups.truncate(1); assert!( - claim_queue.get(&CoreIndex(0)).unwrap().len() == - Self::ASYNC_BACKING_PARAMS.allowed_ancestry_len as usize + claim_queue.get(&CoreIndex(0)).unwrap().len() == state.scheduling_lookahead as usize ); state.claim_queue = claim_queue; @@ -187,8 +185,7 @@ impl TestState { ); assert!( - claim_queue.get(&CoreIndex(0)).unwrap().len() == - Self::ASYNC_BACKING_PARAMS.allowed_ancestry_len as usize + claim_queue.get(&CoreIndex(0)).unwrap().len() == state.scheduling_lookahead as usize ); state.validator_groups = validator_groups; diff --git a/polkadot/node/network/collator-protocol/src/validator_side/tests/prospective_parachains.rs b/polkadot/node/network/collator-protocol/src/validator_side/tests/prospective_parachains.rs index fac63aeb2097f745e46810d941e7f6e52a7034e7..0a00fb6f7b783d028187963ef1721561332acc21 100644 --- a/polkadot/node/network/collator-protocol/src/validator_side/tests/prospective_parachains.rs +++ b/polkadot/node/network/collator-protocol/src/validator_side/tests/prospective_parachains.rs @@ -108,16 +108,6 @@ pub(super) async fn update_view( } ); - assert_matches!( - overseer_recv(virtual_overseer).await, - AllMessages::RuntimeApi(RuntimeApiMessage::Request( - _, - RuntimeApiRequest::AsyncBackingParams(tx), - )) => { - tx.send(Ok(test_state.async_backing_params)).unwrap(); - } - ); - assert_matches!( overseer_recv(virtual_overseer).await, AllMessages::RuntimeApi(RuntimeApiMessage::Request( @@ -137,8 +127,7 @@ pub(super) async fn update_view( ) .await; - let min_number = - leaf_number.saturating_sub(test_state.async_backing_params.allowed_ancestry_len); + let min_number = leaf_number.saturating_sub(test_state.scheduling_lookahead); let ancestry_len = leaf_number + 1 - min_number; let ancestry_hashes = std::iter::successors(Some(leaf_hash), |h| Some(get_parent_hash(*h))) @@ -730,8 +719,7 @@ fn second_multiple_candidates_per_relay_parent() { ) .await; - // `allowed_ancestry_len` equals the size of the claim queue - for i in 0..test_state.async_backing_params.allowed_ancestry_len { + for i in 0..test_state.scheduling_lookahead { submit_second_and_assert( &mut virtual_overseer, keystore.clone(), @@ -2189,8 +2177,7 @@ fn claims_below_are_counted_correctly() { ), ); test_state.claim_queue = claim_queue; - test_state.async_backing_params.max_candidate_depth = 3; - test_state.async_backing_params.allowed_ancestry_len = 2; + test_state.scheduling_lookahead = 2; test_harness(ReputationAggregator::new(|_| true), |test_harness| async move { let TestHarness { mut virtual_overseer, keystore } = test_harness; @@ -2280,8 +2267,7 @@ fn claims_above_are_counted_correctly() { ), ); test_state.claim_queue = claim_queue; - test_state.async_backing_params.max_candidate_depth = 3; - test_state.async_backing_params.allowed_ancestry_len = 2; + test_state.scheduling_lookahead = 2; test_harness(ReputationAggregator::new(|_| true), |test_harness| async move { let TestHarness { mut virtual_overseer, keystore } = test_harness; @@ -2386,8 +2372,7 @@ fn claim_fills_last_free_slot() { ), ); test_state.claim_queue = claim_queue; - test_state.async_backing_params.max_candidate_depth = 3; - test_state.async_backing_params.allowed_ancestry_len = 2; + test_state.scheduling_lookahead = 2; test_harness(ReputationAggregator::new(|_| true), |test_harness| async move { let TestHarness { mut virtual_overseer, keystore } = test_harness; diff --git a/polkadot/node/network/statement-distribution/src/legacy_v1/mod.rs b/polkadot/node/network/statement-distribution/src/legacy_v1/mod.rs index bd6d4ebe755cde4d86be23a8cc24483741208fe9..06e52dbe3a4572b1511ff7046511f84294f75895 100644 --- a/polkadot/node/network/statement-distribution/src/legacy_v1/mod.rs +++ b/polkadot/node/network/statement-distribution/src/legacy_v1/mod.rs @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see <http://www.gnu.org/licenses/>. - +#![allow(dead_code)] use codec::Encode; use net_protocol::{filter_by_peer_version, peer_set::ProtocolVersion}; diff --git a/polkadot/node/network/statement-distribution/src/legacy_v1/tests.rs b/polkadot/node/network/statement-distribution/src/legacy_v1/tests.rs index d2fd016ec2f1ef6408590d8cf4b3368442d03499..92acfa870154f58f34884215e00af56fc38b7045 100644 --- a/polkadot/node/network/statement-distribution/src/legacy_v1/tests.rs +++ b/polkadot/node/network/statement-distribution/src/legacy_v1/tests.rs @@ -20,51 +20,27 @@ use super::*; use crate::{metrics::Metrics, *}; use assert_matches::assert_matches; -use codec::{Decode, Encode}; use futures::executor; -use futures_timer::Delay; use polkadot_node_network_protocol::{ - grid_topology::{SessionGridTopology, TopologyPeerInfo}, - peer_set::ValidationVersion, - request_response::{ - v1::{StatementFetchingRequest, StatementFetchingResponse}, - IncomingRequest, Recipient, ReqProtocolNames, Requests, - }, - view, ObservedRole, VersionedValidationProtocol, + peer_set::ValidationVersion, view, VersionedValidationProtocol, }; use polkadot_node_primitives::{ SignedFullStatementWithPVD, Statement, UncheckedSignedFullStatement, }; -use polkadot_node_subsystem::{ - messages::{ - network_bridge_event, AllMessages, ReportPeerMessage, RuntimeApiMessage, RuntimeApiRequest, - }, - RuntimeApiError, -}; -use polkadot_node_subsystem_test_helpers::mock::{make_ferdie_keystore, new_leaf}; -use polkadot_primitives::{ - Block, ExecutorParams, GroupIndex, Hash, HeadData, Id as ParaId, IndexedVec, NodeFeatures, - SessionInfo, ValidationCode, -}; +use polkadot_node_subsystem::messages::AllMessages; +use polkadot_primitives::{GroupIndex, Hash, HeadData, Id as ParaId, IndexedVec, SessionInfo}; use polkadot_primitives_test_helpers::{ - dummy_committed_candidate_receipt, dummy_committed_candidate_receipt_v2, dummy_hash, - AlwaysZeroRng, + dummy_committed_candidate_receipt, dummy_hash, AlwaysZeroRng, }; use sc_keystore::LocalKeystore; -use sc_network::ProtocolName; use sp_application_crypto::{sr25519::Pair, AppCrypto, Pair as TraitPair}; -use sp_authority_discovery::AuthorityPair; use sp_keyring::Sr25519Keyring; use sp_keystore::{Keystore, KeystorePtr}; -use std::{sync::Arc, time::Duration}; -use util::reputation::add_reputation; +use std::sync::Arc; // Some deterministic genesis hash for protocol names const GENESIS_HASH: Hash = Hash::repeat_byte(0xff); -const ASYNC_BACKING_DISABLED_ERROR: RuntimeApiError = - RuntimeApiError::NotSupported { runtime_api_name: "test-runtime" }; - fn dummy_pvd() -> PersistedValidationData { PersistedValidationData { parent_head: HeadData(vec![7, 8, 9]), @@ -737,2320 +713,6 @@ fn circulated_statement_goes_to_all_peers_with_view() { }); } -#[test] -fn receiving_from_one_sends_to_another_and_to_candidate_backing() { - const PARA_ID: ParaId = ParaId::new(1); - let hash_a = Hash::repeat_byte(1); - let pvd = dummy_pvd(); - - let candidate = { - let mut c = dummy_committed_candidate_receipt(dummy_hash()); - c.descriptor.relay_parent = hash_a; - c.descriptor.para_id = PARA_ID; - c.into() - }; - - let peer_a = PeerId::random(); - let peer_b = PeerId::random(); - - let validators = vec![ - Sr25519Keyring::Alice.pair(), - Sr25519Keyring::Bob.pair(), - Sr25519Keyring::Charlie.pair(), - ]; - - let session_info = make_session_info(validators, vec![]); - - let session_index = 1; - - let pool = sp_core::testing::TaskExecutor::new(); - let (ctx, mut handle) = polkadot_node_subsystem_test_helpers::make_subsystem_context(pool); - - let req_protocol_names = ReqProtocolNames::new(&GENESIS_HASH, None); - let (statement_req_receiver, _) = IncomingRequest::get_config_receiver::< - Block, - sc_network::NetworkWorker<Block, Hash>, - >(&req_protocol_names); - let (candidate_req_receiver, _) = IncomingRequest::get_config_receiver::< - Block, - sc_network::NetworkWorker<Block, Hash>, - >(&req_protocol_names); - - let bg = async move { - let s = StatementDistributionSubsystem { - keystore: Arc::new(LocalKeystore::in_memory()), - v1_req_receiver: Some(statement_req_receiver), - req_receiver: Some(candidate_req_receiver), - metrics: Default::default(), - rng: AlwaysZeroRng, - reputation: ReputationAggregator::new(|_| true), - }; - s.run(ctx).await.unwrap(); - }; - - let test_fut = async move { - // register our active heads. - handle - .send(FromOrchestra::Signal(OverseerSignal::ActiveLeaves( - ActiveLeavesUpdate::start_work(new_leaf(hash_a, 1)), - ))) - .await; - - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(r, RuntimeApiRequest::AsyncBackingParams(tx)) - ) - if r == hash_a - => { - let _ = tx.send(Err(ASYNC_BACKING_DISABLED_ERROR)); - } - ); - - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(r, RuntimeApiRequest::SessionIndexForChild(tx)) - ) - if r == hash_a - => { - let _ = tx.send(Ok(session_index)); - } - ); - - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(r, RuntimeApiRequest::SessionInfo(sess_index, tx)) - ) - if r == hash_a && sess_index == session_index - => { - let _ = tx.send(Ok(Some(session_info))); - } - ); - - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(r, RuntimeApiRequest::SessionExecutorParams(sess_index, tx)) - ) - if r == hash_a && sess_index == session_index - => { - let _ = tx.send(Ok(Some(ExecutorParams::default()))); - } - ); - - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(_, RuntimeApiRequest::NodeFeatures(_, si_tx), ) - ) => { - si_tx.send(Ok(NodeFeatures::EMPTY)).unwrap(); - } - ); - - // notify of peers and view - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerConnected( - peer_a, - ObservedRole::Full, - ValidationVersion::V1.into(), - None, - ), - ), - }) - .await; - - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerConnected( - peer_b, - ObservedRole::Full, - ValidationVersion::V1.into(), - None, - ), - ), - }) - .await; - - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerViewChange(peer_a, view![hash_a]), - ), - }) - .await; - - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerViewChange(peer_b, view![hash_a]), - ), - }) - .await; - - // receive a seconded statement from peer A. it should be propagated onwards to peer B and - // to candidate backing. - let statement = { - let signing_context = SigningContext { parent_hash: hash_a, session_index }; - - let keystore: KeystorePtr = Arc::new(LocalKeystore::in_memory()); - let alice_public = Keystore::sr25519_generate_new( - &*keystore, - ValidatorId::ID, - Some(&Sr25519Keyring::Alice.to_seed()), - ) - .unwrap(); - - SignedFullStatement::sign( - &keystore, - Statement::Seconded(candidate), - &signing_context, - ValidatorIndex(0), - &alice_public.into(), - ) - .ok() - .flatten() - .expect("should be signed") - }; - - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerMessage( - peer_a, - Versioned::V1(protocol_v1::StatementDistributionMessage::Statement( - hash_a, - statement.clone().into(), - )), - ), - ), - }) - .await; - - let statement_with_pvd = extend_statement_with_pvd(statement.clone(), pvd.clone()); - - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi(RuntimeApiMessage::Request( - hash, - RuntimeApiRequest::PersistedValidationData(para_id, assumption, tx), - )) if para_id == PARA_ID && - assumption == OccupiedCoreAssumption::Free && - hash == hash_a => - { - tx.send(Ok(Some(pvd))).unwrap(); - } - ); - - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridgeTx( - NetworkBridgeTxMessage::ReportPeer(ReportPeerMessage::Single(p, r)) - ) if p == peer_a && r == BENEFIT_VALID_STATEMENT_FIRST.into() => {} - ); - assert_matches!( - handle.recv().await, - AllMessages::CandidateBacking( - CandidateBackingMessage::Statement(r, s) - ) if r == hash_a && s == statement_with_pvd => {} - ); - - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridgeTx( - NetworkBridgeTxMessage::SendValidationMessage( - recipients, - Versioned::V1(protocol_v1::ValidationProtocol::StatementDistribution( - protocol_v1::StatementDistributionMessage::Statement(r, s) - )), - ) - ) => { - assert_eq!(recipients, vec![peer_b]); - assert_eq!(r, hash_a); - assert_eq!(s, statement.into()); - } - ); - handle.send(FromOrchestra::Signal(OverseerSignal::Conclude)).await; - }; - - futures::pin_mut!(test_fut); - futures::pin_mut!(bg); - - executor::block_on(future::join(test_fut, bg)); -} - -#[test] -fn receiving_large_statement_from_one_sends_to_another_and_to_candidate_backing() { - const PARA_ID: ParaId = ParaId::new(1); - let pvd = dummy_pvd(); - - sp_tracing::try_init_simple(); - let hash_a = Hash::repeat_byte(1); - let hash_b = Hash::repeat_byte(2); - - let candidate = { - let mut c = dummy_committed_candidate_receipt(dummy_hash()); - c.descriptor.relay_parent = hash_a; - c.descriptor.para_id = PARA_ID; - c.commitments.new_validation_code = Some(ValidationCode(vec![1, 2, 3])); - c - }; - - let peer_a = PeerId::random(); // Alice - let peer_b = PeerId::random(); // Bob - let peer_c = PeerId::random(); // Charlie - let peer_bad = PeerId::random(); // No validator - - let validators = vec![ - Sr25519Keyring::Alice.pair(), - Sr25519Keyring::Bob.pair(), - Sr25519Keyring::Charlie.pair(), - // We: - Sr25519Keyring::Ferdie.pair(), - ]; - - let session_info = make_session_info(validators, vec![vec![0, 1, 2, 4], vec![3]]); - - let session_index = 1; - - let pool = sp_core::testing::TaskExecutor::new(); - let (ctx, mut handle) = polkadot_node_subsystem_test_helpers::make_subsystem_context(pool); - - let req_protocol_names = ReqProtocolNames::new(&GENESIS_HASH, None); - let (statement_req_receiver, mut req_cfg) = IncomingRequest::get_config_receiver::< - Block, - sc_network::NetworkWorker<Block, Hash>, - >(&req_protocol_names); - let (candidate_req_receiver, _) = IncomingRequest::get_config_receiver::< - Block, - sc_network::NetworkWorker<Block, Hash>, - >(&req_protocol_names); - - let bg = async move { - let s = StatementDistributionSubsystem { - keystore: make_ferdie_keystore(), - v1_req_receiver: Some(statement_req_receiver), - req_receiver: Some(candidate_req_receiver), - metrics: Default::default(), - rng: AlwaysZeroRng, - reputation: ReputationAggregator::new(|_| true), - }; - s.run(ctx).await.unwrap(); - }; - - let test_fut = async move { - // register our active heads. - handle - .send(FromOrchestra::Signal(OverseerSignal::ActiveLeaves( - ActiveLeavesUpdate::start_work(new_leaf(hash_a, 1)), - ))) - .await; - - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(r, RuntimeApiRequest::AsyncBackingParams(tx)) - ) - if r == hash_a - => { - let _ = tx.send(Err(ASYNC_BACKING_DISABLED_ERROR)); - } - ); - - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(r, RuntimeApiRequest::SessionIndexForChild(tx)) - ) - if r == hash_a - => { - let _ = tx.send(Ok(session_index)); - } - ); - - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(r, RuntimeApiRequest::SessionInfo(sess_index, tx)) - ) - if r == hash_a && sess_index == session_index - => { - let _ = tx.send(Ok(Some(session_info))); - } - ); - - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(r, RuntimeApiRequest::SessionExecutorParams(sess_index, tx)) - ) - if r == hash_a && sess_index == session_index - => { - let _ = tx.send(Ok(Some(ExecutorParams::default()))); - } - ); - - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(_, RuntimeApiRequest::NodeFeatures(_, si_tx), ) - ) => { - si_tx.send(Ok(NodeFeatures::EMPTY)).unwrap(); - } - ); - - // notify of peers and view - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerConnected( - peer_a, - ObservedRole::Full, - ValidationVersion::V1.into(), - Some(HashSet::from([Sr25519Keyring::Alice.public().into()])), - ), - ), - }) - .await; - - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerConnected( - peer_b, - ObservedRole::Full, - ValidationVersion::V1.into(), - Some(HashSet::from([Sr25519Keyring::Bob.public().into()])), - ), - ), - }) - .await; - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerConnected( - peer_c, - ObservedRole::Full, - ValidationVersion::V1.into(), - Some(HashSet::from([Sr25519Keyring::Charlie.public().into()])), - ), - ), - }) - .await; - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerConnected( - peer_bad, - ObservedRole::Full, - ValidationVersion::V1.into(), - None, - ), - ), - }) - .await; - - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerViewChange(peer_a, view![hash_a]), - ), - }) - .await; - - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerViewChange(peer_b, view![hash_a]), - ), - }) - .await; - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerViewChange(peer_c, view![hash_a]), - ), - }) - .await; - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerViewChange(peer_bad, view![hash_a]), - ), - }) - .await; - - // receive a seconded statement from peer A, which does not provide the request data, - // then get that data from peer C. It should be propagated onwards to peer B and to - // candidate backing. - let statement = { - let signing_context = SigningContext { parent_hash: hash_a, session_index }; - - let keystore: KeystorePtr = Arc::new(LocalKeystore::in_memory()); - let alice_public = Keystore::sr25519_generate_new( - &*keystore, - ValidatorId::ID, - Some(&Sr25519Keyring::Alice.to_seed()), - ) - .unwrap(); - - SignedFullStatement::sign( - &keystore, - Statement::Seconded(candidate.clone().into()), - &signing_context, - ValidatorIndex(0), - &alice_public.into(), - ) - .ok() - .flatten() - .expect("should be signed") - }; - - let metadata = derive_metadata_assuming_seconded(hash_a, statement.clone().into()); - - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerMessage( - peer_a, - Versioned::V1(protocol_v1::StatementDistributionMessage::LargeStatement( - metadata.clone(), - )), - ), - ), - }) - .await; - - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridgeTx( - NetworkBridgeTxMessage::SendRequests( - mut reqs, IfDisconnected::ImmediateError - ) - ) => { - let reqs = reqs.pop().unwrap(); - let outgoing = match reqs { - Requests::StatementFetchingV1(outgoing) => outgoing, - _ => panic!("Unexpected request"), - }; - let req = outgoing.payload; - assert_eq!(req.relay_parent, metadata.relay_parent); - assert_eq!(req.candidate_hash, metadata.candidate_hash); - assert_eq!(outgoing.peer, Recipient::Peer(peer_a)); - // Just drop request - should trigger error. - } - ); - - // There is a race between request handler asking for more peers and processing of the - // coming `PeerMessage`s, we want the request handler to ask first here for better test - // coverage: - Delay::new(Duration::from_millis(20)).await; - - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerMessage( - peer_c, - Versioned::V1(protocol_v1::StatementDistributionMessage::LargeStatement( - metadata.clone(), - )), - ), - ), - }) - .await; - - // Malicious peer: - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerMessage( - peer_bad, - Versioned::V1(protocol_v1::StatementDistributionMessage::LargeStatement( - metadata.clone(), - )), - ), - ), - }) - .await; - - // Let c fail once too: - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridgeTx( - NetworkBridgeTxMessage::SendRequests( - mut reqs, IfDisconnected::ImmediateError - ) - ) => { - let reqs = reqs.pop().unwrap(); - let outgoing = match reqs { - Requests::StatementFetchingV1(outgoing) => outgoing, - _ => panic!("Unexpected request"), - }; - let req = outgoing.payload; - assert_eq!(req.relay_parent, metadata.relay_parent); - assert_eq!(req.candidate_hash, metadata.candidate_hash); - assert_eq!(outgoing.peer, Recipient::Peer(peer_c)); - } - ); - - // a fails again: - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridgeTx( - NetworkBridgeTxMessage::SendRequests( - mut reqs, IfDisconnected::ImmediateError - ) - ) => { - let reqs = reqs.pop().unwrap(); - let outgoing = match reqs { - Requests::StatementFetchingV1(outgoing) => outgoing, - _ => panic!("Unexpected request"), - }; - let req = outgoing.payload; - assert_eq!(req.relay_parent, metadata.relay_parent); - assert_eq!(req.candidate_hash, metadata.candidate_hash); - // On retry, we should have reverse order: - assert_eq!(outgoing.peer, Recipient::Peer(peer_a)); - } - ); - - // Send invalid response (all other peers have been tried now): - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridgeTx( - NetworkBridgeTxMessage::SendRequests( - mut reqs, IfDisconnected::ImmediateError - ) - ) => { - let reqs = reqs.pop().unwrap(); - let outgoing = match reqs { - Requests::StatementFetchingV1(outgoing) => outgoing, - _ => panic!("Unexpected request"), - }; - let req = outgoing.payload; - assert_eq!(req.relay_parent, metadata.relay_parent); - assert_eq!(req.candidate_hash, metadata.candidate_hash); - assert_eq!(outgoing.peer, Recipient::Peer(peer_bad)); - let bad_candidate = { - let mut bad = candidate.clone(); - bad.descriptor.para_id = 0xeadbeaf.into(); - bad.into() - }; - let response = StatementFetchingResponse::Statement(bad_candidate); - outgoing.pending_response.send(Ok((response.encode(), ProtocolName::from("")))).unwrap(); - } - ); - - // Should get punished and never tried again: - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridgeTx( - NetworkBridgeTxMessage::ReportPeer(ReportPeerMessage::Single(p, r)) - ) if p == peer_bad && r == COST_WRONG_HASH.into() => {} - ); - - // a is tried again (retried in reverse order): - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridgeTx( - NetworkBridgeTxMessage::SendRequests( - mut reqs, IfDisconnected::ImmediateError - ) - ) => { - let reqs = reqs.pop().unwrap(); - let outgoing = match reqs { - Requests::StatementFetchingV1(outgoing) => outgoing, - _ => panic!("Unexpected request"), - }; - let req = outgoing.payload; - assert_eq!(req.relay_parent, metadata.relay_parent); - assert_eq!(req.candidate_hash, metadata.candidate_hash); - // On retry, we should have reverse order: - assert_eq!(outgoing.peer, Recipient::Peer(peer_a)); - } - ); - - // c succeeds now: - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridgeTx( - NetworkBridgeTxMessage::SendRequests( - mut reqs, IfDisconnected::ImmediateError - ) - ) => { - let reqs = reqs.pop().unwrap(); - let outgoing = match reqs { - Requests::StatementFetchingV1(outgoing) => outgoing, - _ => panic!("Unexpected request"), - }; - let req = outgoing.payload; - assert_eq!(req.relay_parent, metadata.relay_parent); - assert_eq!(req.candidate_hash, metadata.candidate_hash); - // On retry, we should have reverse order: - assert_eq!(outgoing.peer, Recipient::Peer(peer_c)); - let response = StatementFetchingResponse::Statement(candidate.clone().into()); - outgoing.pending_response.send(Ok((response.encode(), ProtocolName::from("")))).unwrap(); - } - ); - - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridgeTx( - NetworkBridgeTxMessage::ReportPeer(ReportPeerMessage::Single(p, r)) - ) if p == peer_a && r == COST_FETCH_FAIL.into() => {} - ); - - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridgeTx( - NetworkBridgeTxMessage::ReportPeer(ReportPeerMessage::Single(p, r)) - ) if p == peer_c && r == BENEFIT_VALID_RESPONSE.into() => {} - ); - - let statement_with_pvd = extend_statement_with_pvd(statement.clone(), pvd.clone()); - - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi(RuntimeApiMessage::Request( - hash, - RuntimeApiRequest::PersistedValidationData(para_id, assumption, tx), - )) if para_id == PARA_ID && - assumption == OccupiedCoreAssumption::Free && - hash == hash_a => - { - tx.send(Ok(Some(pvd))).unwrap(); - } - ); - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridgeTx( - NetworkBridgeTxMessage::ReportPeer(ReportPeerMessage::Single(p, r)) - ) if p == peer_a && r == BENEFIT_VALID_STATEMENT_FIRST.into() => {} - ); - - assert_matches!( - handle.recv().await, - AllMessages::CandidateBacking( - CandidateBackingMessage::Statement(r, s) - ) if r == hash_a && s == statement_with_pvd => {} - ); - - // Now messages should go out: - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridgeTx( - NetworkBridgeTxMessage::SendValidationMessage( - mut recipients, - Versioned::V1(protocol_v1::ValidationProtocol::StatementDistribution( - protocol_v1::StatementDistributionMessage::LargeStatement(meta) - )), - ) - ) => { - gum::debug!( - target: LOG_TARGET, - ?recipients, - "Recipients received" - ); - recipients.sort(); - let mut expected = vec![peer_b, peer_c, peer_bad]; - expected.sort(); - assert_eq!(recipients, expected); - assert_eq!(meta.relay_parent, hash_a); - assert_eq!(meta.candidate_hash, statement.payload().candidate_hash()); - assert_eq!(meta.signed_by, statement.validator_index()); - assert_eq!(&meta.signature, statement.signature()); - } - ); - - // Now that it has the candidate it should answer requests accordingly (even after a - // failed request): - - // Failing request first (wrong relay parent hash): - let (pending_response, response_rx) = oneshot::channel(); - let inner_req = StatementFetchingRequest { - relay_parent: hash_b, - candidate_hash: metadata.candidate_hash, - }; - let req = sc_network::config::IncomingRequest { - peer: peer_b, - payload: inner_req.encode(), - pending_response, - }; - req_cfg.inbound_queue.as_mut().unwrap().send(req).await.unwrap(); - assert_matches!( - response_rx.await.unwrap().result, - Err(()) => {} - ); - - // Another failing request (peer_a never received a statement from us, so it is not - // allowed to request the data): - let (pending_response, response_rx) = oneshot::channel(); - let inner_req = StatementFetchingRequest { - relay_parent: metadata.relay_parent, - candidate_hash: metadata.candidate_hash, - }; - let req = sc_network::config::IncomingRequest { - peer: peer_a, - payload: inner_req.encode(), - pending_response, - }; - req_cfg.inbound_queue.as_mut().unwrap().send(req).await.unwrap(); - assert_matches!( - response_rx.await.unwrap().result, - Err(()) => {} - ); - - // And now the succeeding request from peer_b: - let (pending_response, response_rx) = oneshot::channel(); - let inner_req = StatementFetchingRequest { - relay_parent: metadata.relay_parent, - candidate_hash: metadata.candidate_hash, - }; - let req = sc_network::config::IncomingRequest { - peer: peer_b, - payload: inner_req.encode(), - pending_response, - }; - req_cfg.inbound_queue.as_mut().unwrap().send(req).await.unwrap(); - let StatementFetchingResponse::Statement(committed) = - Decode::decode(&mut response_rx.await.unwrap().result.unwrap().as_ref()).unwrap(); - assert_eq!(committed, candidate.into()); - - handle.send(FromOrchestra::Signal(OverseerSignal::Conclude)).await; - }; - - futures::pin_mut!(test_fut); - futures::pin_mut!(bg); - - executor::block_on(future::join(test_fut, bg)); -} - -#[test] -fn delay_reputation_changes() { - sp_tracing::try_init_simple(); - let hash_a = Hash::repeat_byte(1); - let pvd = dummy_pvd(); - - let candidate = { - let mut c = dummy_committed_candidate_receipt(dummy_hash()); - c.descriptor.relay_parent = hash_a; - c.descriptor.para_id = 1.into(); - c.commitments.new_validation_code = Some(ValidationCode(vec![1, 2, 3])); - c - }; - - let peer_a = PeerId::random(); // Alice - let peer_b = PeerId::random(); // Bob - let peer_c = PeerId::random(); // Charlie - let peer_bad = PeerId::random(); // No validator - - let validators = vec![ - Sr25519Keyring::Alice.pair(), - Sr25519Keyring::Bob.pair(), - Sr25519Keyring::Charlie.pair(), - // We: - Sr25519Keyring::Ferdie.pair(), - ]; - - let session_info = make_session_info(validators, vec![vec![0, 1, 2, 4], vec![3]]); - - let session_index = 1; - - let pool = sp_core::testing::TaskExecutor::new(); - let (ctx, mut handle) = polkadot_node_subsystem_test_helpers::make_subsystem_context(pool); - - let req_protocol_names = ReqProtocolNames::new(&GENESIS_HASH, None); - let (statement_req_receiver, _) = IncomingRequest::get_config_receiver::< - Block, - sc_network::NetworkWorker<Block, Hash>, - >(&req_protocol_names); - let (candidate_req_receiver, _) = IncomingRequest::get_config_receiver::< - Block, - sc_network::NetworkWorker<Block, Hash>, - >(&req_protocol_names); - - let reputation_interval = Duration::from_millis(100); - - let bg = async move { - let s = StatementDistributionSubsystem { - keystore: make_ferdie_keystore(), - v1_req_receiver: Some(statement_req_receiver), - req_receiver: Some(candidate_req_receiver), - metrics: Default::default(), - rng: AlwaysZeroRng, - reputation: ReputationAggregator::new(|_| false), - }; - s.run_inner(ctx, reputation_interval).await.unwrap(); - }; - - let test_fut = async move { - // register our active heads. - handle - .send(FromOrchestra::Signal(OverseerSignal::ActiveLeaves( - ActiveLeavesUpdate::start_work(new_leaf(hash_a, 1)), - ))) - .await; - - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(r, RuntimeApiRequest::AsyncBackingParams(tx)) - ) - if r == hash_a - => { - let _ = tx.send(Err(ASYNC_BACKING_DISABLED_ERROR)); - } - ); - - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(r, RuntimeApiRequest::SessionIndexForChild(tx)) - ) - if r == hash_a - => { - let _ = tx.send(Ok(session_index)); - } - ); - - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(r, RuntimeApiRequest::SessionInfo(sess_index, tx)) - ) - if r == hash_a && sess_index == session_index - => { - let _ = tx.send(Ok(Some(session_info))); - } - ); - - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(r, RuntimeApiRequest::SessionExecutorParams(sess_index, tx)) - ) - if r == hash_a && sess_index == session_index - => { - let _ = tx.send(Ok(Some(ExecutorParams::default()))); - } - ); - - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(_, RuntimeApiRequest::NodeFeatures(_, si_tx), ) - ) => { - si_tx.send(Ok(NodeFeatures::EMPTY)).unwrap(); - } - ); - - // notify of peers and view - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerConnected( - peer_a, - ObservedRole::Full, - ValidationVersion::V1.into(), - Some(HashSet::from([Sr25519Keyring::Alice.public().into()])), - ), - ), - }) - .await; - - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerConnected( - peer_b, - ObservedRole::Full, - ValidationVersion::V1.into(), - Some(HashSet::from([Sr25519Keyring::Bob.public().into()])), - ), - ), - }) - .await; - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerConnected( - peer_c, - ObservedRole::Full, - ValidationVersion::V1.into(), - Some(HashSet::from([Sr25519Keyring::Charlie.public().into()])), - ), - ), - }) - .await; - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerConnected( - peer_bad, - ObservedRole::Full, - ValidationVersion::V1.into(), - None, - ), - ), - }) - .await; - - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerViewChange(peer_a, view![hash_a]), - ), - }) - .await; - - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerViewChange(peer_b, view![hash_a]), - ), - }) - .await; - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerViewChange(peer_c, view![hash_a]), - ), - }) - .await; - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerViewChange(peer_bad, view![hash_a]), - ), - }) - .await; - - // receive a seconded statement from peer A, which does not provide the request data, - // then get that data from peer C. It should be propagated onwards to peer B and to - // candidate backing. - let statement = { - let signing_context = SigningContext { parent_hash: hash_a, session_index }; - - let keystore: KeystorePtr = Arc::new(LocalKeystore::in_memory()); - let alice_public = Keystore::sr25519_generate_new( - &*keystore, - ValidatorId::ID, - Some(&Sr25519Keyring::Alice.to_seed()), - ) - .unwrap(); - - SignedFullStatement::sign( - &keystore, - Statement::Seconded(candidate.clone().into()), - &signing_context, - ValidatorIndex(0), - &alice_public.into(), - ) - .ok() - .flatten() - .expect("should be signed") - }; - - let metadata = derive_metadata_assuming_seconded(hash_a, statement.clone().into()); - - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerMessage( - peer_a, - Versioned::V1(protocol_v1::StatementDistributionMessage::LargeStatement( - metadata.clone(), - )), - ), - ), - }) - .await; - - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridgeTx( - NetworkBridgeTxMessage::SendRequests( - mut reqs, IfDisconnected::ImmediateError - ) - ) => { - let reqs = reqs.pop().unwrap(); - let outgoing = match reqs { - Requests::StatementFetchingV1(outgoing) => outgoing, - _ => panic!("Unexpected request"), - }; - let req = outgoing.payload; - assert_eq!(req.relay_parent, metadata.relay_parent); - assert_eq!(req.candidate_hash, metadata.candidate_hash); - assert_eq!(outgoing.peer, Recipient::Peer(peer_a)); - // Just drop request - should trigger error. - } - ); - - // There is a race between request handler asking for more peers and processing of the - // coming `PeerMessage`s, we want the request handler to ask first here for better test - // coverage: - Delay::new(Duration::from_millis(20)).await; - - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerMessage( - peer_c, - Versioned::V1(protocol_v1::StatementDistributionMessage::LargeStatement( - metadata.clone(), - )), - ), - ), - }) - .await; - - // Malicious peer: - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerMessage( - peer_bad, - Versioned::V1(protocol_v1::StatementDistributionMessage::LargeStatement( - metadata.clone(), - )), - ), - ), - }) - .await; - - // Let c fail once too: - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridgeTx( - NetworkBridgeTxMessage::SendRequests( - mut reqs, IfDisconnected::ImmediateError - ) - ) => { - let reqs = reqs.pop().unwrap(); - let outgoing = match reqs { - Requests::StatementFetchingV1(outgoing) => outgoing, - _ => panic!("Unexpected request"), - }; - let req = outgoing.payload; - assert_eq!(req.relay_parent, metadata.relay_parent); - assert_eq!(req.candidate_hash, metadata.candidate_hash); - assert_eq!(outgoing.peer, Recipient::Peer(peer_c)); - } - ); - - // a fails again: - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridgeTx( - NetworkBridgeTxMessage::SendRequests( - mut reqs, IfDisconnected::ImmediateError - ) - ) => { - let reqs = reqs.pop().unwrap(); - let outgoing = match reqs { - Requests::StatementFetchingV1(outgoing) => outgoing, - _ => panic!("Unexpected request"), - }; - let req = outgoing.payload; - assert_eq!(req.relay_parent, metadata.relay_parent); - assert_eq!(req.candidate_hash, metadata.candidate_hash); - // On retry, we should have reverse order: - assert_eq!(outgoing.peer, Recipient::Peer(peer_a)); - } - ); - - // Send invalid response (all other peers have been tried now): - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridgeTx( - NetworkBridgeTxMessage::SendRequests( - mut reqs, IfDisconnected::ImmediateError - ) - ) => { - let reqs = reqs.pop().unwrap(); - let outgoing = match reqs { - Requests::StatementFetchingV1(outgoing) => outgoing, - _ => panic!("Unexpected request"), - }; - let req = outgoing.payload; - assert_eq!(req.relay_parent, metadata.relay_parent); - assert_eq!(req.candidate_hash, metadata.candidate_hash); - assert_eq!(outgoing.peer, Recipient::Peer(peer_bad)); - let bad_candidate = { - let mut bad = candidate.clone(); - bad.descriptor.para_id = 0xeadbeaf.into(); - bad - }; - let response = StatementFetchingResponse::Statement(bad_candidate.into()); - outgoing.pending_response.send(Ok((response.encode(), ProtocolName::from("")))).unwrap(); - } - ); - - // a is tried again (retried in reverse order): - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridgeTx( - NetworkBridgeTxMessage::SendRequests( - mut reqs, IfDisconnected::ImmediateError - ) - ) => { - let reqs = reqs.pop().unwrap(); - let outgoing = match reqs { - Requests::StatementFetchingV1(outgoing) => outgoing, - _ => panic!("Unexpected request"), - }; - let req = outgoing.payload; - assert_eq!(req.relay_parent, metadata.relay_parent); - assert_eq!(req.candidate_hash, metadata.candidate_hash); - // On retry, we should have reverse order: - assert_eq!(outgoing.peer, Recipient::Peer(peer_a)); - } - ); - - // c succeeds now: - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridgeTx( - NetworkBridgeTxMessage::SendRequests( - mut reqs, IfDisconnected::ImmediateError - ) - ) => { - let reqs = reqs.pop().unwrap(); - let outgoing = match reqs { - Requests::StatementFetchingV1(outgoing) => outgoing, - _ => panic!("Unexpected request"), - }; - let req = outgoing.payload; - assert_eq!(req.relay_parent, metadata.relay_parent); - assert_eq!(req.candidate_hash, metadata.candidate_hash); - // On retry, we should have reverse order: - assert_eq!(outgoing.peer, Recipient::Peer(peer_c)); - let response = StatementFetchingResponse::Statement(candidate.clone().into()); - outgoing.pending_response.send(Ok((response.encode(), ProtocolName::from("")))).unwrap(); - } - ); - - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi(RuntimeApiMessage::Request( - hash, - RuntimeApiRequest::PersistedValidationData(_, assumption, tx), - )) if assumption == OccupiedCoreAssumption::Free && hash == hash_a => - { - tx.send(Ok(Some(pvd))).unwrap(); - } - ); - - assert_matches!( - handle.recv().await, - AllMessages::CandidateBacking(CandidateBackingMessage::Statement(..)) - ); - - // Now messages should go out: - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridgeTx( - NetworkBridgeTxMessage::SendValidationMessage( - mut recipients, - Versioned::V1(protocol_v1::ValidationProtocol::StatementDistribution( - protocol_v1::StatementDistributionMessage::LargeStatement(meta) - )), - ) - ) => { - gum::debug!( - target: LOG_TARGET, - ?recipients, - "Recipients received" - ); - recipients.sort(); - let mut expected = vec![peer_b, peer_c, peer_bad]; - expected.sort(); - assert_eq!(recipients, expected); - assert_eq!(meta.relay_parent, hash_a); - assert_eq!(meta.candidate_hash, statement.payload().candidate_hash()); - assert_eq!(meta.signed_by, statement.validator_index()); - assert_eq!(&meta.signature, statement.signature()); - } - ); - - // Wait enough to fire reputation delay - futures_timer::Delay::new(reputation_interval).await; - - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridgeTx( - NetworkBridgeTxMessage::ReportPeer(ReportPeerMessage::Batch(v)) - ) => { - let mut expected_change = HashMap::new(); - for rep in vec![COST_FETCH_FAIL, BENEFIT_VALID_STATEMENT_FIRST] { - add_reputation(&mut expected_change, peer_a, rep) - } - for rep in vec![BENEFIT_VALID_RESPONSE, BENEFIT_VALID_STATEMENT] { - add_reputation(&mut expected_change, peer_c, rep) - } - for rep in vec![COST_WRONG_HASH, BENEFIT_VALID_STATEMENT] { - add_reputation(&mut expected_change, peer_bad, rep) - } - assert_eq!(v, expected_change); - } - ); - - handle.send(FromOrchestra::Signal(OverseerSignal::Conclude)).await; - }; - - futures::pin_mut!(test_fut); - futures::pin_mut!(bg); - - executor::block_on(future::join(test_fut, bg)); -} - -#[test] -fn share_prioritizes_backing_group() { - sp_tracing::try_init_simple(); - let hash_a = Hash::repeat_byte(1); - - let candidate = { - let mut c = dummy_committed_candidate_receipt(dummy_hash()); - c.descriptor.relay_parent = hash_a; - c.descriptor.para_id = 1.into(); - c.commitments.new_validation_code = Some(ValidationCode(vec![1, 2, 3])); - c - }; - - let peer_a = PeerId::random(); // Alice - let peer_b = PeerId::random(); // Bob - let peer_c = PeerId::random(); // Charlie - let peer_bad = PeerId::random(); // No validator - let peer_other_group = PeerId::random(); //Ferdie - - let mut validators = vec![ - Sr25519Keyring::Alice.pair(), - Sr25519Keyring::Bob.pair(), - Sr25519Keyring::Charlie.pair(), - // other group - Sr25519Keyring::Dave.pair(), - // We: - Sr25519Keyring::Ferdie.pair(), - ]; - - // Strictly speaking we only need MIN_GOSSIP_PEERS - 3 to make sure only priority peers - // will be served, but by using a larger value we test for overflow errors: - let dummy_count = MIN_GOSSIP_PEERS; - - // We artificially inflate our group, so there won't be any free slots for other peers. (We - // want to test that our group is prioritized): - let dummy_pairs: Vec<_> = - std::iter::repeat_with(|| Pair::generate().0).take(dummy_count).collect(); - let dummy_peers: Vec<_> = - std::iter::repeat_with(|| PeerId::random()).take(dummy_count).collect(); - - validators = validators.into_iter().chain(dummy_pairs.clone()).collect(); - - let mut first_group = vec![0, 1, 2, 4]; - first_group.append(&mut (0..dummy_count as u32).map(|v| v + 5).collect()); - let session_info = make_session_info(validators, vec![first_group, vec![3]]); - - let session_index = 1; - - let pool = sp_core::testing::TaskExecutor::new(); - let (ctx, mut handle) = polkadot_node_subsystem_test_helpers::make_subsystem_context(pool); - - let req_protocol_names = ReqProtocolNames::new(&GENESIS_HASH, None); - let (statement_req_receiver, mut req_cfg) = IncomingRequest::get_config_receiver::< - Block, - sc_network::NetworkWorker<Block, Hash>, - >(&req_protocol_names); - let (candidate_req_receiver, _) = IncomingRequest::get_config_receiver::< - Block, - sc_network::NetworkWorker<Block, Hash>, - >(&req_protocol_names); - - let bg = async move { - let s = StatementDistributionSubsystem { - keystore: make_ferdie_keystore(), - v1_req_receiver: Some(statement_req_receiver), - req_receiver: Some(candidate_req_receiver), - metrics: Default::default(), - rng: AlwaysZeroRng, - reputation: ReputationAggregator::new(|_| true), - }; - s.run(ctx).await.unwrap(); - }; - - let test_fut = async move { - // register our active heads. - handle - .send(FromOrchestra::Signal(OverseerSignal::ActiveLeaves( - ActiveLeavesUpdate::start_work(new_leaf(hash_a, 1)), - ))) - .await; - - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(r, RuntimeApiRequest::AsyncBackingParams(tx)) - ) - if r == hash_a - => { - let _ = tx.send(Err(ASYNC_BACKING_DISABLED_ERROR)); - } - ); - - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(r, RuntimeApiRequest::SessionIndexForChild(tx)) - ) - if r == hash_a - => { - let _ = tx.send(Ok(session_index)); - } - ); - - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(r, RuntimeApiRequest::SessionInfo(sess_index, tx)) - ) - if r == hash_a && sess_index == session_index - => { - let _ = tx.send(Ok(Some(session_info))); - } - ); - - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(r, RuntimeApiRequest::SessionExecutorParams(sess_index, tx)) - ) - if r == hash_a && sess_index == session_index - => { - let _ = tx.send(Ok(Some(ExecutorParams::default()))); - } - ); - - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(_, RuntimeApiRequest::NodeFeatures(_, si_tx), ) - ) => { - si_tx.send(Ok(NodeFeatures::EMPTY)).unwrap(); - } - ); - - // notify of dummy peers and view - for (peer, pair) in dummy_peers.clone().into_iter().zip(dummy_pairs) { - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerConnected( - peer, - ObservedRole::Full, - ValidationVersion::V1.into(), - Some(HashSet::from([pair.public().into()])), - ), - ), - }) - .await; - - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerViewChange(peer, view![hash_a]), - ), - }) - .await; - } - - // notify of peers and view - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerConnected( - peer_a, - ObservedRole::Full, - ValidationVersion::V1.into(), - Some(HashSet::from([Sr25519Keyring::Alice.public().into()])), - ), - ), - }) - .await; - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerConnected( - peer_b, - ObservedRole::Full, - ValidationVersion::V1.into(), - Some(HashSet::from([Sr25519Keyring::Bob.public().into()])), - ), - ), - }) - .await; - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerConnected( - peer_c, - ObservedRole::Full, - ValidationVersion::V1.into(), - Some(HashSet::from([Sr25519Keyring::Charlie.public().into()])), - ), - ), - }) - .await; - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerConnected( - peer_bad, - ObservedRole::Full, - ValidationVersion::V1.into(), - None, - ), - ), - }) - .await; - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerConnected( - peer_other_group, - ObservedRole::Full, - ValidationVersion::V1.into(), - Some(HashSet::from([Sr25519Keyring::Dave.public().into()])), - ), - ), - }) - .await; - - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerViewChange(peer_a, view![hash_a]), - ), - }) - .await; - - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerViewChange(peer_b, view![hash_a]), - ), - }) - .await; - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerViewChange(peer_c, view![hash_a]), - ), - }) - .await; - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerViewChange(peer_bad, view![hash_a]), - ), - }) - .await; - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerViewChange(peer_other_group, view![hash_a]), - ), - }) - .await; - - // receive a seconded statement from peer A, which does not provide the request data, - // then get that data from peer C. It should be propagated onwards to peer B and to - // candidate backing. - let statement = { - let signing_context = SigningContext { parent_hash: hash_a, session_index }; - - let keystore: KeystorePtr = Arc::new(LocalKeystore::in_memory()); - let ferdie_public = Keystore::sr25519_generate_new( - &*keystore, - ValidatorId::ID, - Some(&Sr25519Keyring::Ferdie.to_seed()), - ) - .unwrap(); - - // note: this is ignored by legacy-v1 code. - let pvd = PersistedValidationData { - parent_head: HeadData::from(vec![1, 2, 3]), - relay_parent_number: 0, - relay_parent_storage_root: Hash::repeat_byte(42), - max_pov_size: 100, - }; - - SignedFullStatementWithPVD::sign( - &keystore, - Statement::Seconded(candidate.clone().into()).supply_pvd(pvd), - &signing_context, - ValidatorIndex(4), - &ferdie_public.into(), - ) - .ok() - .flatten() - .expect("should be signed") - }; - - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::Share(hash_a, statement.clone()), - }) - .await; - - let statement = StatementWithPVD::drop_pvd_from_signed(statement); - let metadata = derive_metadata_assuming_seconded(hash_a, statement.clone().into()); - - // Messages should go out: - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridgeTx( - NetworkBridgeTxMessage::SendValidationMessage( - mut recipients, - Versioned::V1(protocol_v1::ValidationProtocol::StatementDistribution( - protocol_v1::StatementDistributionMessage::LargeStatement(meta) - )), - ) - ) => { - gum::debug!( - target: LOG_TARGET, - ?recipients, - "Recipients received" - ); - recipients.sort(); - // We expect only our backing group to be the recipients, du to the inflated - // test group above: - let mut expected: Vec<_> = vec![peer_a, peer_b, peer_c].into_iter().chain(dummy_peers).collect(); - expected.sort(); - assert_eq!(recipients.len(), expected.len()); - assert_eq!(recipients, expected); - assert_eq!(meta.relay_parent, hash_a); - assert_eq!(meta.candidate_hash, statement.payload().candidate_hash()); - assert_eq!(meta.signed_by, statement.validator_index()); - assert_eq!(&meta.signature, statement.signature()); - } - ); - - // Now that it has the candidate it should answer requests accordingly: - - let (pending_response, response_rx) = oneshot::channel(); - let inner_req = StatementFetchingRequest { - relay_parent: metadata.relay_parent, - candidate_hash: metadata.candidate_hash, - }; - let req = sc_network::config::IncomingRequest { - peer: peer_b, - payload: inner_req.encode(), - pending_response, - }; - req_cfg.inbound_queue.as_mut().unwrap().send(req).await.unwrap(); - let StatementFetchingResponse::Statement(committed) = - Decode::decode(&mut response_rx.await.unwrap().result.unwrap().as_ref()).unwrap(); - assert_eq!(committed, candidate.into()); - - handle.send(FromOrchestra::Signal(OverseerSignal::Conclude)).await; - }; - - futures::pin_mut!(test_fut); - futures::pin_mut!(bg); - - executor::block_on(future::join(test_fut, bg)); -} - -#[test] -fn peer_cant_flood_with_large_statements() { - sp_tracing::try_init_simple(); - let hash_a = Hash::repeat_byte(1); - - let candidate = { - let mut c = dummy_committed_candidate_receipt(dummy_hash()); - c.descriptor.relay_parent = hash_a; - c.descriptor.para_id = 1.into(); - c.commitments.new_validation_code = Some(ValidationCode(vec![1, 2, 3])); - c - }; - - let peer_a = PeerId::random(); // Alice - - let validators = vec![ - Sr25519Keyring::Alice.pair(), - Sr25519Keyring::Bob.pair(), - Sr25519Keyring::Charlie.pair(), - // other group - Sr25519Keyring::Dave.pair(), - // We: - Sr25519Keyring::Ferdie.pair(), - ]; - - let first_group = vec![0, 1, 2, 4]; - let session_info = make_session_info(validators, vec![first_group, vec![3]]); - - let session_index = 1; - - let pool = sp_core::testing::TaskExecutor::new(); - let (ctx, mut handle) = polkadot_node_subsystem_test_helpers::make_subsystem_context(pool); - - let req_protocol_names = ReqProtocolNames::new(&GENESIS_HASH, None); - let (statement_req_receiver, _) = IncomingRequest::get_config_receiver::< - Block, - sc_network::NetworkWorker<Block, Hash>, - >(&req_protocol_names); - let (candidate_req_receiver, _) = IncomingRequest::get_config_receiver::< - Block, - sc_network::NetworkWorker<Block, Hash>, - >(&req_protocol_names); - let bg = async move { - let s = StatementDistributionSubsystem { - keystore: make_ferdie_keystore(), - v1_req_receiver: Some(statement_req_receiver), - req_receiver: Some(candidate_req_receiver), - metrics: Default::default(), - rng: AlwaysZeroRng, - reputation: ReputationAggregator::new(|_| true), - }; - s.run(ctx).await.unwrap(); - }; - - let test_fut = async move { - // register our active heads. - handle - .send(FromOrchestra::Signal(OverseerSignal::ActiveLeaves( - ActiveLeavesUpdate::start_work(new_leaf(hash_a, 1)), - ))) - .await; - - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(r, RuntimeApiRequest::AsyncBackingParams(tx)) - ) - if r == hash_a - => { - let _ = tx.send(Err(ASYNC_BACKING_DISABLED_ERROR)); - } - ); - - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(r, RuntimeApiRequest::SessionIndexForChild(tx)) - ) - if r == hash_a - => { - let _ = tx.send(Ok(session_index)); - } - ); - - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(r, RuntimeApiRequest::SessionInfo(sess_index, tx)) - ) - if r == hash_a && sess_index == session_index - => { - let _ = tx.send(Ok(Some(session_info))); - } - ); - - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(r, RuntimeApiRequest::SessionExecutorParams(sess_index, tx)) - ) - if r == hash_a && sess_index == session_index - => { - let _ = tx.send(Ok(Some(ExecutorParams::default()))); - } - ); - - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(_, RuntimeApiRequest::NodeFeatures(_, si_tx), ) - ) => { - si_tx.send(Ok(NodeFeatures::EMPTY)).unwrap(); - } - ); - - // notify of peers and view - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerConnected( - peer_a, - ObservedRole::Full, - ValidationVersion::V1.into(), - Some(HashSet::from([Sr25519Keyring::Alice.public().into()])), - ), - ), - }) - .await; - - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerViewChange(peer_a, view![hash_a]), - ), - }) - .await; - - // receive a seconded statement from peer A. - let statement = { - let signing_context = SigningContext { parent_hash: hash_a, session_index }; - - let keystore: KeystorePtr = Arc::new(LocalKeystore::in_memory()); - let alice_public = Keystore::sr25519_generate_new( - &*keystore, - ValidatorId::ID, - Some(&Sr25519Keyring::Alice.to_seed()), - ) - .unwrap(); - - SignedFullStatement::sign( - &keystore, - Statement::Seconded(candidate.clone().into()), - &signing_context, - ValidatorIndex(0), - &alice_public.into(), - ) - .ok() - .flatten() - .expect("should be signed") - }; - - let metadata = derive_metadata_assuming_seconded(hash_a, statement.clone().into()); - - for _ in 0..MAX_LARGE_STATEMENTS_PER_SENDER + 1 { - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerMessage( - peer_a, - Versioned::V1( - protocol_v1::StatementDistributionMessage::LargeStatement( - metadata.clone(), - ), - ), - ), - ), - }) - .await; - } - - // We should try to fetch the data and punish the peer (but we don't know what comes - // first): - let mut requested = false; - let mut punished = false; - for _ in 0..2 { - match handle.recv().await { - AllMessages::NetworkBridgeTx(NetworkBridgeTxMessage::SendRequests( - mut reqs, - IfDisconnected::ImmediateError, - )) => { - let reqs = reqs.pop().unwrap(); - let outgoing = match reqs { - Requests::StatementFetchingV1(outgoing) => outgoing, - _ => panic!("Unexpected request"), - }; - let req = outgoing.payload; - assert_eq!(req.relay_parent, metadata.relay_parent); - assert_eq!(req.candidate_hash, metadata.candidate_hash); - assert_eq!(outgoing.peer, Recipient::Peer(peer_a)); - // Just drop request - should trigger error. - requested = true; - }, - - AllMessages::NetworkBridgeTx(NetworkBridgeTxMessage::ReportPeer( - ReportPeerMessage::Single(p, r), - )) if p == peer_a && r == COST_APPARENT_FLOOD.into() => { - punished = true; - }, - - m => panic!("Unexpected message: {:?}", m), - } - } - assert!(requested, "large data has not been requested."); - assert!(punished, "Peer should have been punished for flooding."); - - handle.send(FromOrchestra::Signal(OverseerSignal::Conclude)).await; - }; - - futures::pin_mut!(test_fut); - futures::pin_mut!(bg); - - executor::block_on(future::join(test_fut, bg)); -} - -// This test addresses an issue when received knowledge is not updated on a -// subsequent `Seconded` statements -// See https://github.com/paritytech/polkadot/pull/5177 -#[test] -fn handle_multiple_seconded_statements() { - let relay_parent_hash = Hash::repeat_byte(1); - let pvd = dummy_pvd(); - - let candidate = dummy_committed_candidate_receipt_v2(relay_parent_hash); - let candidate_hash = candidate.hash(); - - // We want to ensure that our peers are not lucky - let mut all_peers: Vec<PeerId> = Vec::with_capacity(MIN_GOSSIP_PEERS + 4); - let peer_a = PeerId::random(); - let peer_b = PeerId::random(); - assert_ne!(peer_a, peer_b); - - for _ in 0..MIN_GOSSIP_PEERS + 2 { - all_peers.push(PeerId::random()); - } - all_peers.push(peer_a); - all_peers.push(peer_b); - - let mut lucky_peers = all_peers.clone(); - util::choose_random_subset_with_rng( - |_| false, - &mut lucky_peers, - &mut AlwaysZeroRng, - MIN_GOSSIP_PEERS, - ); - lucky_peers.sort(); - assert_eq!(lucky_peers.len(), MIN_GOSSIP_PEERS); - assert!(!lucky_peers.contains(&peer_a)); - assert!(!lucky_peers.contains(&peer_b)); - - let validators = vec![ - Sr25519Keyring::Alice.pair(), - Sr25519Keyring::Bob.pair(), - Sr25519Keyring::Charlie.pair(), - ]; - - let session_info = make_session_info(validators, vec![]); - - let session_index = 1; - - let pool = sp_core::testing::TaskExecutor::new(); - let (ctx, mut handle) = polkadot_node_subsystem_test_helpers::make_subsystem_context(pool); - - let req_protocol_names = ReqProtocolNames::new(&GENESIS_HASH, None); - let (statement_req_receiver, _) = IncomingRequest::get_config_receiver::< - Block, - sc_network::NetworkWorker<Block, Hash>, - >(&req_protocol_names); - let (candidate_req_receiver, _) = IncomingRequest::get_config_receiver::< - Block, - sc_network::NetworkWorker<Block, Hash>, - >(&req_protocol_names); - - let virtual_overseer_fut = async move { - let s = StatementDistributionSubsystem { - keystore: Arc::new(LocalKeystore::in_memory()), - v1_req_receiver: Some(statement_req_receiver), - req_receiver: Some(candidate_req_receiver), - metrics: Default::default(), - rng: AlwaysZeroRng, - reputation: ReputationAggregator::new(|_| true), - }; - s.run(ctx).await.unwrap(); - }; - - let test_fut = async move { - // register our active heads. - handle - .send(FromOrchestra::Signal(OverseerSignal::ActiveLeaves( - ActiveLeavesUpdate::start_work(new_leaf(relay_parent_hash, 1)), - ))) - .await; - - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(r, RuntimeApiRequest::AsyncBackingParams(tx)) - ) - if r == relay_parent_hash - => { - let _ = tx.send(Err(ASYNC_BACKING_DISABLED_ERROR)); - } - ); - - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(r, RuntimeApiRequest::SessionIndexForChild(tx)) - ) - if r == relay_parent_hash - => { - let _ = tx.send(Ok(session_index)); - } - ); - - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(r, RuntimeApiRequest::SessionInfo(sess_index, tx)) - ) - if r == relay_parent_hash && sess_index == session_index - => { - let _ = tx.send(Ok(Some(session_info))); - } - ); - - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(r, RuntimeApiRequest::SessionExecutorParams(sess_index, tx)) - ) - if r == relay_parent_hash && sess_index == session_index - => { - let _ = tx.send(Ok(Some(ExecutorParams::default()))); - } - ); - - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(_, RuntimeApiRequest::NodeFeatures(_, si_tx), ) - ) => { - si_tx.send(Ok(NodeFeatures::EMPTY)).unwrap(); - } - ); - // notify of peers and view - for peer in all_peers.iter() { - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerConnected( - *peer, - ObservedRole::Full, - ValidationVersion::V1.into(), - None, - ), - ), - }) - .await; - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerViewChange(*peer, view![relay_parent_hash]), - ), - }) - .await; - } - - // Set up a topology which puts peers a & b in a column together. - let gossip_topology = { - // create a lucky_peers+1 * lucky_peers+1 grid topology where we are at index 2, sharing - // a row with peer_a (0) and peer_b (1) and a column with all the lucky peers. - // the rest is filled with junk. - // This is an absolute garbage hack depending on quirks of the implementation - // and not on sound architecture. - - let n_lucky = lucky_peers.len(); - let dim = n_lucky + 1; - let grid_size = dim * dim; - let topology_peer_info: Vec<_> = (0..grid_size) - .map(|i| { - if i == 0 { - TopologyPeerInfo { - peer_ids: vec![peer_a], - validator_index: ValidatorIndex(0), - discovery_id: AuthorityPair::generate().0.public(), - } - } else if i == 1 { - TopologyPeerInfo { - peer_ids: vec![peer_b], - validator_index: ValidatorIndex(1), - discovery_id: AuthorityPair::generate().0.public(), - } - } else if i == 2 { - TopologyPeerInfo { - peer_ids: vec![], - validator_index: ValidatorIndex(2), - discovery_id: AuthorityPair::generate().0.public(), - } - } else if (i - 2) % dim == 0 { - let lucky_index = ((i - 2) / dim) - 1; - TopologyPeerInfo { - peer_ids: vec![lucky_peers[lucky_index]], - validator_index: ValidatorIndex(i as _), - discovery_id: AuthorityPair::generate().0.public(), - } - } else { - TopologyPeerInfo { - peer_ids: vec![PeerId::random()], - validator_index: ValidatorIndex(i as _), - discovery_id: AuthorityPair::generate().0.public(), - } - } - }) - .collect(); - - // also a hack: this is only required to be accurate for - // the validator indices we compute grid neighbors for. - let mut shuffled_indices = vec![0; grid_size]; - shuffled_indices[2] = 2; - - // Some sanity checking to make sure this hack is set up correctly. - let topology = SessionGridTopology::new(shuffled_indices, topology_peer_info); - let grid_neighbors = topology.compute_grid_neighbors_for(ValidatorIndex(2)).unwrap(); - assert_eq!(grid_neighbors.peers_x.len(), 25); - assert!(grid_neighbors.peers_x.contains(&peer_a)); - assert!(grid_neighbors.peers_x.contains(&peer_b)); - assert!(!grid_neighbors.peers_y.contains(&peer_b)); - assert!(!grid_neighbors.route_to_peer(RequiredRouting::GridY, &peer_b)); - assert_eq!(grid_neighbors.peers_y.len(), lucky_peers.len()); - for lucky in &lucky_peers { - assert!(grid_neighbors.peers_y.contains(lucky)); - } - - network_bridge_event::NewGossipTopology { - session: 1, - topology, - local_index: Some(ValidatorIndex(2)), - } - }; - - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::NewGossipTopology(gossip_topology), - ), - }) - .await; - - // receive a seconded statement from peer A. it should be propagated onwards to peer B and - // to candidate backing. - let statement = { - let signing_context = SigningContext { parent_hash: relay_parent_hash, session_index }; - - let keystore: KeystorePtr = Arc::new(LocalKeystore::in_memory()); - let alice_public = Keystore::sr25519_generate_new( - &*keystore, - ValidatorId::ID, - Some(&Sr25519Keyring::Alice.to_seed()), - ) - .unwrap(); - - SignedFullStatement::sign( - &keystore, - Statement::Seconded(candidate.clone()), - &signing_context, - ValidatorIndex(0), - &alice_public.into(), - ) - .ok() - .flatten() - .expect("should be signed") - }; - - // `PeerA` sends a `Seconded` message - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerMessage( - peer_a, - Versioned::V1(protocol_v1::StatementDistributionMessage::Statement( - relay_parent_hash, - statement.clone().into(), - )), - ), - ), - }) - .await; - - let statement_with_pvd = extend_statement_with_pvd(statement.clone(), pvd.clone()); - - assert_matches!( - handle.recv().await, - AllMessages::RuntimeApi(RuntimeApiMessage::Request( - _, - RuntimeApiRequest::PersistedValidationData(_, assumption, tx), - )) if assumption == OccupiedCoreAssumption::Free => { - tx.send(Ok(Some(pvd.clone()))).unwrap(); - } - ); - - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridgeTx( - NetworkBridgeTxMessage::ReportPeer(ReportPeerMessage::Single(p, r)) - ) => { - assert_eq!(p, peer_a); - assert_eq!(r, BENEFIT_VALID_STATEMENT_FIRST.into()); - } - ); - - // After the first valid statement, we expect messages to be circulated - assert_matches!( - handle.recv().await, - AllMessages::CandidateBacking( - CandidateBackingMessage::Statement(r, s) - ) => { - assert_eq!(r, relay_parent_hash); - assert_eq!(s, statement_with_pvd); - } - ); - - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridgeTx( - NetworkBridgeTxMessage::SendValidationMessage( - recipients, - Versioned::V1(protocol_v1::ValidationProtocol::StatementDistribution( - protocol_v1::StatementDistributionMessage::Statement(r, s) - )), - ) - ) => { - assert!(!recipients.contains(&peer_b)); - assert_eq!(r, relay_parent_hash); - assert_eq!(s, statement.clone().into()); - } - ); - - // `PeerB` sends a `Seconded` message: valid but known - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerMessage( - peer_b, - Versioned::V1(protocol_v1::StatementDistributionMessage::Statement( - relay_parent_hash, - statement.clone().into(), - )), - ), - ), - }) - .await; - - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridgeTx( - NetworkBridgeTxMessage::ReportPeer(ReportPeerMessage::Single(p, r)) - ) => { - assert_eq!(p, peer_b); - assert_eq!(r, BENEFIT_VALID_STATEMENT.into()); - } - ); - - // Create a `Valid` statement - let statement = { - let signing_context = SigningContext { parent_hash: relay_parent_hash, session_index }; - - let keystore: KeystorePtr = Arc::new(LocalKeystore::in_memory()); - let alice_public = Keystore::sr25519_generate_new( - &*keystore, - ValidatorId::ID, - Some(&Sr25519Keyring::Alice.to_seed()), - ) - .unwrap(); - - SignedFullStatement::sign( - &keystore, - Statement::Valid(candidate_hash), - &signing_context, - ValidatorIndex(0), - &alice_public.into(), - ) - .ok() - .flatten() - .expect("should be signed") - }; - - // `PeerA` sends a `Valid` message - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerMessage( - peer_a, - Versioned::V1(protocol_v1::StatementDistributionMessage::Statement( - relay_parent_hash, - statement.clone().into(), - )), - ), - ), - }) - .await; - - let statement_with_pvd = extend_statement_with_pvd(statement.clone(), pvd.clone()); - - // Persisted validation data is cached. - - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridgeTx( - NetworkBridgeTxMessage::ReportPeer(ReportPeerMessage::Single(p, r)) - ) => { - assert_eq!(p, peer_a); - assert_eq!(r, BENEFIT_VALID_STATEMENT_FIRST.into()); - } - ); - - assert_matches!( - handle.recv().await, - AllMessages::CandidateBacking( - CandidateBackingMessage::Statement(r, s) - ) => { - assert_eq!(r, relay_parent_hash); - assert_eq!(s, statement_with_pvd); - } - ); - - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridgeTx( - NetworkBridgeTxMessage::SendValidationMessage( - recipients, - Versioned::V1(protocol_v1::ValidationProtocol::StatementDistribution( - protocol_v1::StatementDistributionMessage::Statement(r, s) - )), - ) - ) => { - assert!(!recipients.contains(&peer_b)); - assert_eq!(r, relay_parent_hash); - assert_eq!(s, statement.clone().into()); - } - ); - - // `PeerB` sends a `Valid` message - handle - .send(FromOrchestra::Communication { - msg: StatementDistributionMessage::NetworkBridgeUpdate( - NetworkBridgeEvent::PeerMessage( - peer_b, - Versioned::V1(protocol_v1::StatementDistributionMessage::Statement( - relay_parent_hash, - statement.clone().into(), - )), - ), - ), - }) - .await; - - // We expect that this is still valid despite the fact that `PeerB` was not - // the first when sending `Seconded` - assert_matches!( - handle.recv().await, - AllMessages::NetworkBridgeTx( - NetworkBridgeTxMessage::ReportPeer(ReportPeerMessage::Single(p, r)) - ) => { - assert_eq!(p, peer_b); - assert_eq!(r, BENEFIT_VALID_STATEMENT.into()); - } - ); - - handle.send(FromOrchestra::Signal(OverseerSignal::Conclude)).await; - }; - - futures::pin_mut!(test_fut); - futures::pin_mut!(virtual_overseer_fut); - - executor::block_on(future::join(test_fut, virtual_overseer_fut)); -} - fn make_session_info(validators: Vec<Pair>, groups: Vec<Vec<u32>>) -> SessionInfo { let validator_groups: IndexedVec<GroupIndex, Vec<ValidatorIndex>> = groups .iter() diff --git a/polkadot/node/network/statement-distribution/src/lib.rs b/polkadot/node/network/statement-distribution/src/lib.rs index 33431eb1edce585943100e4c23d7234a39779f9c..3b5d00921ca0cf00387e6aa7626524df00ff4c31 100644 --- a/polkadot/node/network/statement-distribution/src/lib.rs +++ b/polkadot/node/network/statement-distribution/src/lib.rs @@ -28,7 +28,6 @@ use polkadot_node_network_protocol::{ request_response::{v1 as request_v1, v2::AttestedCandidateRequest, IncomingRequestReceiver}, v2 as protocol_v2, v3 as protocol_v3, Versioned, }; -use polkadot_node_primitives::StatementWithPVD; use polkadot_node_subsystem::{ messages::{NetworkBridgeEvent, StatementDistributionMessage}, overseer, ActiveLeavesUpdate, FromOrchestra, OverseerSignal, SpawnedSubsystem, SubsystemError, @@ -36,7 +35,6 @@ use polkadot_node_subsystem::{ use polkadot_node_subsystem_util::{ rand, reputation::{ReputationAggregator, REPUTATION_CHANGE_INTERVAL}, - runtime::{prospective_parachains_mode, ProspectiveParachainsMode}, }; use futures::{channel::mpsc, prelude::*}; @@ -322,33 +320,14 @@ impl<R: rand::Rng> StatementDistributionSubsystem<R> { })) => { let _timer = metrics.time_active_leaves_update(); - // v2 should handle activated first because of implicit view. if let Some(ref activated) = activated { - let mode = prospective_parachains_mode(ctx.sender(), activated.hash).await?; - if let ProspectiveParachainsMode::Enabled { .. } = mode { - let res = - v2::handle_active_leaves_update(ctx, state, activated, mode, &metrics) - .await; - // Regardless of the result of leaf activation, we always prune before - // handling it to avoid leaks. - v2::handle_deactivate_leaves(state, &deactivated); - res?; - } else if let ProspectiveParachainsMode::Disabled = mode { - for deactivated in &deactivated { - crate::legacy_v1::handle_deactivate_leaf(legacy_v1_state, *deactivated); - } - - crate::legacy_v1::handle_activated_leaf( - ctx, - legacy_v1_state, - activated.clone(), - ) - .await?; - } + let res = + v2::handle_active_leaves_update(ctx, state, activated, &metrics).await; + // Regardless of the result of leaf activation, we always prune before + // handling it to avoid leaks. + v2::handle_deactivate_leaves(state, &deactivated); + res?; } else { - for deactivated in &deactivated { - crate::legacy_v1::handle_deactivate_leaf(legacy_v1_state, *deactivated); - } v2::handle_deactivate_leaves(state, &deactivated); } }, @@ -360,28 +339,15 @@ impl<R: rand::Rng> StatementDistributionSubsystem<R> { StatementDistributionMessage::Share(relay_parent, statement) => { let _timer = metrics.time_share(); - // pass to legacy if legacy state contains head. - if legacy_v1_state.contains_relay_parent(&relay_parent) { - crate::legacy_v1::share_local_statement( - ctx, - legacy_v1_state, - relay_parent, - StatementWithPVD::drop_pvd_from_signed(statement), - &mut self.rng, - metrics, - ) - .await?; - } else { - v2::share_local_statement( - ctx, - state, - relay_parent, - statement, - &mut self.reputation, - &self.metrics, - ) - .await?; - } + v2::share_local_statement( + ctx, + state, + relay_parent, + statement, + &mut self.reputation, + &self.metrics, + ) + .await?; }, StatementDistributionMessage::NetworkBridgeUpdate(event) => { // pass all events to both protocols except for messages, diff --git a/polkadot/node/network/statement-distribution/src/v2/mod.rs b/polkadot/node/network/statement-distribution/src/v2/mod.rs index 6bb49e5de13dd35ed0d285dd2789b6f12d9e702c..3034ca7caf851df09c267880991f15718abeb277 100644 --- a/polkadot/node/network/statement-distribution/src/v2/mod.rs +++ b/polkadot/node/network/statement-distribution/src/v2/mod.rs @@ -45,10 +45,7 @@ use polkadot_node_subsystem::{ use polkadot_node_subsystem_util::{ backing_implicit_view::View as ImplicitView, reputation::ReputationAggregator, - runtime::{ - request_min_backing_votes, request_node_features, ClaimQueueSnapshot, - ProspectiveParachainsMode, - }, + runtime::{request_min_backing_votes, request_node_features, ClaimQueueSnapshot}, }; use polkadot_primitives::{ node_features::FeatureIndex, @@ -163,11 +160,11 @@ pub(crate) const REQUEST_RETRY_DELAY: Duration = Duration::from_secs(1); struct PerRelayParentState { local_validator: Option<LocalValidatorState>, statement_store: StatementStore, - seconding_limit: usize, session: SessionIndex, transposed_cq: TransposedClaimQueue, groups_per_para: HashMap<ParaId, Vec<GroupIndex>>, disabled_validators: HashSet<ValidatorIndex>, + assignments_per_group: HashMap<GroupIndex, Vec<ParaId>>, } impl PerRelayParentState { @@ -304,8 +301,6 @@ impl PerSessionState { pub(crate) struct State { /// The utility for managing the implicit and explicit views in a consistent way. - /// - /// We only feed leaves which have prospective parachains enabled to this view. implicit_view: ImplicitView, candidates: Candidates, per_relay_parent: HashMap<Hash, PerRelayParentState>, @@ -572,23 +567,14 @@ pub(crate) async fn handle_network_update<Context>( } } -/// If there is a new leaf, this should only be called for leaves which support -/// prospective parachains. +/// Called on new leaf updates. #[overseer::contextbounds(StatementDistribution, prefix=self::overseer)] pub(crate) async fn handle_active_leaves_update<Context>( ctx: &mut Context, state: &mut State, activated: &ActivatedLeaf, - leaf_mode: ProspectiveParachainsMode, metrics: &Metrics, ) -> JfyiErrorResult<()> { - let max_candidate_depth = match leaf_mode { - ProspectiveParachainsMode::Disabled => return Ok(()), - ProspectiveParachainsMode::Enabled { max_candidate_depth, .. } => max_candidate_depth, - }; - - let seconding_limit = max_candidate_depth + 1; - state .implicit_view .activate_leaf(ctx.sender(), activated.hash) @@ -697,27 +683,21 @@ pub(crate) async fn handle_active_leaves_update<Context>( .map_err(JfyiError::FetchClaimQueue)?, ); + let (groups_per_para, assignments_per_group) = determine_group_assignments( + per_session.groups.all().len(), + group_rotation_info, + &claim_queue, + ) + .await; + let local_validator = per_session.local_validator.and_then(|v| { if let LocalValidatorIndex::Active(idx) = v { - find_active_validator_state( - idx, - &per_session.groups, - &group_rotation_info, - &claim_queue, - seconding_limit, - ) + find_active_validator_state(idx, &per_session.groups, &assignments_per_group) } else { Some(LocalValidatorState { grid_tracker: GridTracker::default(), active: None }) } }); - let groups_per_para = determine_groups_per_para( - per_session.groups.all().len(), - group_rotation_info, - &claim_queue, - ) - .await; - let transposed_cq = transpose_claim_queue(claim_queue.0); state.per_relay_parent.insert( @@ -725,11 +705,11 @@ pub(crate) async fn handle_active_leaves_update<Context>( PerRelayParentState { local_validator, statement_store: StatementStore::new(&per_session.groups), - seconding_limit, session: session_index, groups_per_para, disabled_validators, transposed_cq, + assignments_per_group, }, ); } @@ -769,9 +749,7 @@ pub(crate) async fn handle_active_leaves_update<Context>( fn find_active_validator_state( validator_index: ValidatorIndex, groups: &Groups, - group_rotation_info: &GroupRotationInfo, - claim_queue: &ClaimQueueSnapshot, - seconding_limit: usize, + assignments_per_group: &HashMap<GroupIndex, Vec<ParaId>>, ) -> Option<LocalValidatorState> { if groups.all().is_empty() { return None @@ -779,17 +757,17 @@ fn find_active_validator_state( let our_group = groups.by_validator_index(validator_index)?; - let core_index = group_rotation_info.core_for_group(our_group, groups.all().len()); - let paras_assigned_to_core = claim_queue.iter_claims_for_core(&core_index).copied().collect(); let group_validators = groups.get(our_group)?.to_owned(); + let paras_assigned_to_core = assignments_per_group.get(&our_group).cloned().unwrap_or_default(); + let seconding_limit = paras_assigned_to_core.len(); Some(LocalValidatorState { active: Some(ActiveValidatorState { index: validator_index, group: our_group, - assignments: paras_assigned_to_core, cluster_tracker: ClusterTracker::new(group_validators, seconding_limit) .expect("group is non-empty because we are in it; qed"), + assignments: paras_assigned_to_core.clone(), }), grid_tracker: GridTracker::default(), }) @@ -1231,13 +1209,14 @@ pub(crate) async fn share_local_statement<Context>( return Err(JfyiError::InvalidShare) } + let seconding_limit = local_assignments.len(); + if is_seconded && - per_relay_parent.statement_store.seconded_count(&local_index) == - per_relay_parent.seconding_limit + per_relay_parent.statement_store.seconded_count(&local_index) >= seconding_limit { gum::warn!( target: LOG_TARGET, - limit = ?per_relay_parent.seconding_limit, + limit = ?seconding_limit, "Local node has issued too many `Seconded` statements", ); return Err(JfyiError::InvalidShare) @@ -2183,12 +2162,14 @@ async fn provide_candidate_to_grid<Context>( } } -// Utility function to populate per relay parent `ParaId` to `GroupIndex` mappings. -async fn determine_groups_per_para( +// Utility function to populate: +// - per relay parent `ParaId` to `GroupIndex` mappings. +// - per `GroupIndex` claim queue assignments +async fn determine_group_assignments( n_cores: usize, group_rotation_info: GroupRotationInfo, claim_queue: &ClaimQueueSnapshot, -) -> HashMap<ParaId, Vec<GroupIndex>> { +) -> (HashMap<ParaId, Vec<GroupIndex>>, HashMap<GroupIndex, Vec<ParaId>>) { // Determine the core indices occupied by each para at the current relay parent. To support // on-demand parachains we also consider the core indices at next blocks. let schedule: HashMap<CoreIndex, Vec<ParaId>> = claim_queue @@ -2197,16 +2178,19 @@ async fn determine_groups_per_para( .collect(); let mut groups_per_para = HashMap::new(); + let mut assignments_per_group = HashMap::with_capacity(schedule.len()); + // Map from `CoreIndex` to `GroupIndex` and collect as `HashMap`. for (core_index, paras) in schedule { let group_index = group_rotation_info.group_for_core(core_index, n_cores); + assignments_per_group.insert(group_index, paras.clone()); for para in paras { groups_per_para.entry(para).or_insert_with(Vec::new).push(group_index); } } - groups_per_para + (groups_per_para, assignments_per_group) } #[overseer::contextbounds(StatementDistribution, prefix=self::overseer)] @@ -2351,10 +2335,7 @@ async fn handle_incoming_manifest_common<'a, Context>( reputation: &mut ReputationAggregator, ) -> Option<ManifestImportSuccess<'a>> { // 1. sanity checks: peer is connected, relay-parent in state, para ID matches group index. - let peer_state = match peers.get(&peer) { - None => return None, - Some(p) => p, - }; + let peer_state = peers.get(&peer)?; let relay_parent_state = match per_relay_parent.get_mut(&relay_parent) { None => { @@ -2370,10 +2351,7 @@ async fn handle_incoming_manifest_common<'a, Context>( Some(s) => s, }; - let per_session = match per_session.get(&relay_parent_state.session) { - None => return None, - Some(s) => s, - }; + let per_session = per_session.get(&relay_parent_state.session)?; if relay_parent_state.local_validator.is_none() { if per_session.is_not_validator() { @@ -2398,10 +2376,7 @@ async fn handle_incoming_manifest_common<'a, Context>( return None } - let grid_topology = match per_session.grid_view.as_ref() { - None => return None, - Some(x) => x, - }; + let grid_topology = per_session.grid_view.as_ref()?; let sender_index = grid_topology .iter_sending_for_group(manifest_summary.claimed_group_index, manifest_kind) @@ -2436,11 +2411,18 @@ async fn handle_incoming_manifest_common<'a, Context>( let local_validator = relay_parent_state.local_validator.as_mut().expect("checked above; qed"); + let seconding_limit = relay_parent_state + .assignments_per_group + .get(&group_index)? + .iter() + .filter(|para| para == &¶_id) + .count(); + let acknowledge = match local_validator.grid_tracker.import_manifest( grid_topology, &per_session.groups, candidate_hash, - relay_parent_state.seconding_limit, + seconding_limit, manifest_summary, manifest_kind, sender_index, @@ -3015,7 +2997,7 @@ pub(crate) async fn dispatch_requests<Context>(ctx: &mut Context, state: &mut St let relay_parent_state = state.per_relay_parent.get(&relay_parent)?; let per_session = state.per_session.get(&relay_parent_state.session)?; let group = per_session.groups.get(group_index)?; - let seconding_limit = relay_parent_state.seconding_limit; + let seconding_limit = relay_parent_state.assignments_per_group.get(&group_index)?.len(); // Request nothing which would be an 'over-seconded' statement. let mut unwanted_mask = StatementFilter::blank(group.len()); diff --git a/polkadot/node/network/statement-distribution/src/v2/statement_store.rs b/polkadot/node/network/statement-distribution/src/v2/statement_store.rs index 56a54f6316c070df0111d22bbc9649fb8de6d0b4..e1dfc2f5a2faaecee68926fae4f1fc298ae87821 100644 --- a/polkadot/node/network/statement-distribution/src/v2/statement_store.rs +++ b/polkadot/node/network/statement-distribution/src/v2/statement_store.rs @@ -217,7 +217,7 @@ impl StatementStore { &'a self, validators: &'a [ValidatorIndex], candidate_hash: CandidateHash, - ) -> impl Iterator<Item = &SignedStatement> + 'a { + ) -> impl Iterator<Item = &'a SignedStatement> + 'a { let s_st = CompactStatement::Seconded(candidate_hash); let v_st = CompactStatement::Valid(candidate_hash); diff --git a/polkadot/node/network/statement-distribution/src/v2/tests/cluster.rs b/polkadot/node/network/statement-distribution/src/v2/tests/cluster.rs index 040123f1774cf727341be0bd0a1899b2430b51bd..750bcca9cb50b2d11c316bcc7b01c7dfe9064495 100644 --- a/polkadot/node/network/statement-distribution/src/v2/tests/cluster.rs +++ b/polkadot/node/network/statement-distribution/src/v2/tests/cluster.rs @@ -24,7 +24,6 @@ fn share_seconded_circulated_to_cluster() { validator_count: 20, group_size: 3, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors: false, }; @@ -125,7 +124,6 @@ fn cluster_valid_statement_before_seconded_ignored() { validator_count: 20, group_size: 3, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors: false, }; @@ -186,7 +184,6 @@ fn cluster_statement_bad_signature() { validator_count: 20, group_size: 3, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors: false, }; @@ -260,7 +257,6 @@ fn useful_cluster_statement_from_non_cluster_peer_rejected() { validator_count: 20, group_size: 3, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors: false, }; @@ -323,7 +319,6 @@ fn elastic_scaling_useful_cluster_statement_from_non_cluster_peer_rejected() { validator_count: 20, group_size: 3, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors: false, }; @@ -383,7 +378,6 @@ fn statement_from_non_cluster_originator_unexpected() { validator_count: 20, group_size: 3, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors: false, }; @@ -439,7 +433,6 @@ fn seconded_statement_leads_to_request() { validator_count: 20, group_size, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors: false, }; @@ -528,7 +521,6 @@ fn cluster_statements_shared_seconded_first() { validator_count: 20, group_size: 3, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors: false, }; @@ -643,7 +635,6 @@ fn cluster_accounts_for_implicit_view() { validator_count: 20, group_size: 3, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors: false, }; @@ -743,8 +734,7 @@ fn cluster_accounts_for_implicit_view() { // peer B never had the relay parent in its view, so this tests that // the implicit view is working correctly for B. // - // the fact that the statement isn't sent again to A also indicates that it works - // it's working. + // the fact that the statement isn't sent again to A also indicates that it's working. assert_matches!( overseer.recv().await, AllMessages::NetworkBridgeTx(NetworkBridgeTxMessage::SendValidationMessages(messages)) => { @@ -780,7 +770,6 @@ fn cluster_messages_imported_after_confirmed_candidate_importable_check() { validator_count: 20, group_size, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors: false, }; @@ -904,7 +893,6 @@ fn cluster_messages_imported_after_new_leaf_importable_check() { validator_count: 20, group_size, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors: false, }; @@ -1033,18 +1021,14 @@ fn cluster_messages_imported_after_new_leaf_importable_check() { #[test] fn ensure_seconding_limit_is_respected() { - // `max_candidate_depth: 1` for a `seconding_limit` of 2. + // use a scheduling_lookahead of two to restrict the per-core seconding limit to 2. + let scheduling_lookahead = 2; let config = TestConfig { validator_count: 20, group_size: 4, local_validator: LocalRole::Validator, - async_backing_params: Some(AsyncBackingParams { - max_candidate_depth: 1, - allowed_ancestry_len: 3, - }), allow_v2_descriptors: false, }; - let relay_parent = Hash::repeat_byte(1); let peer_a = PeerId::random(); @@ -1053,7 +1037,8 @@ fn ensure_seconding_limit_is_respected() { let local_group_index = local_validator.group_index.unwrap(); let local_para = ParaId::from(local_group_index.0); - let test_leaf = state.make_dummy_leaf(relay_parent); + let test_leaf = + state.make_dummy_leaf_with_scheduling_lookahead(relay_parent, scheduling_lookahead); let (candidate_1, pvd_1) = make_candidate( relay_parent, @@ -1232,3 +1217,117 @@ fn ensure_seconding_limit_is_respected() { overseer }); } + +#[test] +fn delayed_reputation_changes() { + let config = TestConfig { + validator_count: 20, + group_size: 3, + local_validator: LocalRole::Validator, + allow_v2_descriptors: false, + }; + + let keystore = test_helpers::mock::make_ferdie_keystore(); + let req_protocol_names = ReqProtocolNames::new(&GENESIS_HASH, None); + let (statement_req_receiver, _) = IncomingRequest::get_config_receiver::< + Block, + sc_network::NetworkWorker<Block, Hash>, + >(&req_protocol_names); + let (candidate_req_receiver, req_cfg) = IncomingRequest::get_config_receiver::< + Block, + sc_network::NetworkWorker<Block, Hash>, + >(&req_protocol_names); + let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(0); + + let state = TestState::from_config(config, req_cfg.inbound_queue.unwrap(), &mut rng); + + // We can't use the test harness as we need to spawn our own subsystem with custom config. + let (context, mut virtual_overseer) = + polkadot_node_subsystem_test_helpers::make_subsystem_context( + sp_core::testing::TaskExecutor::new(), + ); + let subsystem = async move { + let subsystem = crate::StatementDistributionSubsystem { + keystore, + v1_req_receiver: Some(statement_req_receiver), + req_receiver: Some(candidate_req_receiver), + metrics: Default::default(), + rng, + reputation: ReputationAggregator::new(|_| false), + }; + + if let Err(e) = subsystem.run_inner(context, Duration::from_millis(100)).await { + panic!("Fatal error: {:?}", e); + } + }; + + let test_fut = async move { + let relay_parent = Hash::repeat_byte(1); + let peer_a = PeerId::random(); + + let local_validator = state.local.clone().unwrap(); + let local_group_index = local_validator.group_index.unwrap(); + let candidate_hash = CandidateHash(Hash::repeat_byte(42)); + + let test_leaf = state.make_dummy_leaf(relay_parent); + + // peer A is in group, has relay parent in view. + let other_group_validators = state.group_validators(local_group_index, true); + let v_a = other_group_validators[0]; + connect_peer( + &mut virtual_overseer, + peer_a.clone(), + Some(vec![state.discovery_id(v_a)].into_iter().collect()), + ) + .await; + + send_peer_view_change(&mut virtual_overseer, peer_a.clone(), view![relay_parent]).await; + activate_leaf(&mut virtual_overseer, &test_leaf, &state, true, vec![]).await; + + let signed_valid = state.sign_statement( + v_a, + CompactStatement::Valid(candidate_hash), + &SigningContext { parent_hash: relay_parent, session_index: 1 }, + ); + + send_peer_message( + &mut virtual_overseer, + peer_a.clone(), + protocol_v2::StatementDistributionMessage::Statement( + relay_parent, + signed_valid.as_unchecked().clone(), + ), + ) + .await; + + assert_matches!(virtual_overseer.rx.next().timeout(Duration::from_millis(50)).await, None); + // Wait enough to fire reputation delay + futures_timer::Delay::new(Duration::from_millis(60)).await; + + assert_matches!( + virtual_overseer.recv().await, + AllMessages::NetworkBridgeTx(NetworkBridgeTxMessage::ReportPeer(ReportPeerMessage::Batch(reps))) => { + let mut expected = HashMap::new(); + expected.insert(peer_a, COST_UNEXPECTED_STATEMENT_CLUSTER_REJECTED.cost_or_benefit()); + assert_eq!(expected, reps); + } + ); + + virtual_overseer + }; + + futures::pin_mut!(test_fut); + futures::pin_mut!(subsystem); + futures::executor::block_on(future::join( + async move { + let mut virtual_overseer = test_fut.await; + // Ensure we have handled all responses. + if let Ok(Some(msg)) = virtual_overseer.rx.try_next() { + panic!("Did not handle all responses: {:?}", msg); + } + // Conclude. + virtual_overseer.send(FromOrchestra::Signal(OverseerSignal::Conclude)).await; + }, + subsystem, + )); +} diff --git a/polkadot/node/network/statement-distribution/src/v2/tests/grid.rs b/polkadot/node/network/statement-distribution/src/v2/tests/grid.rs index 0133d9e219f6eafacf0d1f73f6c261eb550a9af2..494e2a7f5dbf57a9ed7b9d659f23367d6626f6c7 100644 --- a/polkadot/node/network/statement-distribution/src/v2/tests/grid.rs +++ b/polkadot/node/network/statement-distribution/src/v2/tests/grid.rs @@ -30,7 +30,6 @@ fn backed_candidate_leads_to_advertisement() { validator_count, group_size, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors: false, }; @@ -240,7 +239,6 @@ fn received_advertisement_before_confirmation_leads_to_request() { validator_count, group_size, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors: false, }; @@ -413,7 +411,6 @@ fn received_advertisement_after_backing_leads_to_acknowledgement() { validator_count, group_size, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors: false, }; @@ -595,7 +592,6 @@ fn receive_ack_for_unconfirmed_candidate() { validator_count, group_size, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors: false, }; @@ -657,7 +653,6 @@ fn received_acknowledgements_for_locally_confirmed() { validator_count, group_size, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors: false, }; @@ -820,7 +815,6 @@ fn received_acknowledgements_for_externally_confirmed() { validator_count, group_size, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors: false, }; @@ -956,7 +950,6 @@ fn received_advertisement_after_confirmation_before_backing() { validator_count, group_size, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors: false, }; @@ -1135,7 +1128,6 @@ fn additional_statements_are_shared_after_manifest_exchange() { validator_count, group_size, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors: false, }; @@ -1423,7 +1415,6 @@ fn advertisement_sent_when_peer_enters_relay_parent_view() { validator_count, group_size, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors: false, }; @@ -1637,7 +1628,6 @@ fn advertisement_not_re_sent_when_peer_re_enters_view() { validator_count, group_size, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors: false, }; @@ -1849,7 +1839,6 @@ fn inner_grid_statements_imported_to_backing(groups_for_first_para: usize) { validator_count, group_size, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors: false, }; @@ -2058,7 +2047,6 @@ fn advertisements_rejected_from_incorrect_peers() { validator_count, group_size, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors: false, }; @@ -2195,7 +2183,6 @@ fn manifest_rejected_with_unknown_relay_parent() { validator_count, group_size, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors: false, }; @@ -2293,7 +2280,6 @@ fn manifest_rejected_when_not_a_validator() { validator_count, group_size, local_validator: LocalRole::None, - async_backing_params: None, allow_v2_descriptors: false, }; @@ -2387,7 +2373,6 @@ fn manifest_rejected_when_group_does_not_match_para() { validator_count, group_size, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors: false, }; @@ -2486,7 +2471,6 @@ fn peer_reported_for_advertisement_conflicting_with_confirmed_candidate() { validator_count, group_size, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors: false, }; @@ -2677,7 +2661,6 @@ fn inactive_local_participates_in_grid() { validator_count, group_size, local_validator: LocalRole::InactiveValidator, - async_backing_params: None, allow_v2_descriptors: false, }; diff --git a/polkadot/node/network/statement-distribution/src/v2/tests/mod.rs b/polkadot/node/network/statement-distribution/src/v2/tests/mod.rs index 46b72f5adac9859f05f3ee9733a9b960b991715b..5a9b8efa2a13b60144a51a8fb9b26ec5358d8e32 100644 --- a/polkadot/node/network/statement-distribution/src/v2/tests/mod.rs +++ b/polkadot/node/network/statement-distribution/src/v2/tests/mod.rs @@ -24,7 +24,7 @@ use polkadot_node_network_protocol::{ v2::{BackedCandidateAcknowledgement, BackedCandidateManifest}, view, ObservedRole, }; -use polkadot_node_primitives::Statement; +use polkadot_node_primitives::{Statement, StatementWithPVD}; use polkadot_node_subsystem::messages::{ network_bridge_event::NewGossipTopology, AllMessages, ChainApiMessage, HypotheticalCandidate, HypotheticalMembership, NetworkBridgeEvent, ProspectiveParachainsMessage, ReportPeerMessage, @@ -33,9 +33,9 @@ use polkadot_node_subsystem::messages::{ use polkadot_node_subsystem_test_helpers as test_helpers; use polkadot_node_subsystem_util::TimeoutExt; use polkadot_primitives::{ - vstaging::CommittedCandidateReceiptV2 as CommittedCandidateReceipt, AssignmentPair, - AsyncBackingParams, Block, BlockNumber, GroupRotationInfo, HeadData, Header, IndexedVec, - PersistedValidationData, SessionIndex, SessionInfo, ValidatorPair, + vstaging::CommittedCandidateReceiptV2 as CommittedCandidateReceipt, AssignmentPair, Block, + BlockNumber, GroupRotationInfo, HeadData, Header, IndexedVec, PersistedValidationData, + SessionIndex, SessionInfo, ValidatorPair, DEFAULT_SCHEDULING_LOOKAHEAD, }; use sc_keystore::LocalKeystore; use sc_network::ProtocolName; @@ -58,9 +58,6 @@ mod requests; type VirtualOverseer = polkadot_node_subsystem_test_helpers::TestSubsystemContextHandle<StatementDistributionMessage>; -const DEFAULT_ASYNC_BACKING_PARAMETERS: AsyncBackingParams = - AsyncBackingParams { max_candidate_depth: 4, allowed_ancestry_len: 3 }; - // Some deterministic genesis hash for req/res protocol names const GENESIS_HASH: Hash = Hash::repeat_byte(0xff); @@ -81,7 +78,6 @@ struct TestConfig { group_size: usize, // whether the local node should be a validator local_validator: LocalRole, - async_backing_params: Option<AsyncBackingParams>, // allow v2 descriptors (feature bit) allow_v2_descriptors: bool, } @@ -187,23 +183,26 @@ impl TestState { } fn make_dummy_leaf(&self, relay_parent: Hash) -> TestLeaf { - self.make_dummy_leaf_with_multiple_cores_per_para(relay_parent, 1) + self.make_dummy_leaf_inner(relay_parent, 1, DEFAULT_SCHEDULING_LOOKAHEAD as usize) } - fn make_dummy_leaf_with_multiple_cores_per_para( + fn make_dummy_leaf_inner( &self, relay_parent: Hash, groups_for_first_para: usize, + scheduling_lookahead: usize, ) -> TestLeaf { let mut cq = std::collections::BTreeMap::new(); for i in 0..self.session_info.validator_groups.len() { if i < groups_for_first_para { - cq.entry(CoreIndex(i as u32)) - .or_insert_with(|| vec![ParaId::from(0u32), ParaId::from(0u32)].into()); + cq.entry(CoreIndex(i as u32)).or_insert_with(|| { + std::iter::repeat(ParaId::from(0u32)).take(scheduling_lookahead).collect() + }); } else { - cq.entry(CoreIndex(i as u32)) - .or_insert_with(|| vec![ParaId::from(i), ParaId::from(i)].into()); + cq.entry(CoreIndex(i as u32)).or_insert_with(|| { + std::iter::repeat(ParaId::from(i)).take(scheduling_lookahead).collect() + }); }; } @@ -229,6 +228,26 @@ impl TestState { } } + fn make_dummy_leaf_with_scheduling_lookahead( + &self, + relay_parent: Hash, + scheduling_lookahead: usize, + ) -> TestLeaf { + self.make_dummy_leaf_inner(relay_parent, 1, scheduling_lookahead) + } + + fn make_dummy_leaf_with_multiple_cores_per_para( + &self, + relay_parent: Hash, + groups_for_first_para: usize, + ) -> TestLeaf { + self.make_dummy_leaf_inner( + relay_parent, + groups_for_first_para, + DEFAULT_SCHEDULING_LOOKAHEAD as usize, + ) + } + fn make_dummy_leaf_with_disabled_validators( &self, relay_parent: Hash, @@ -588,15 +607,6 @@ async fn handle_leaf_activation( claim_queue, } = leaf; - assert_matches!( - virtual_overseer.recv().await, - AllMessages::RuntimeApi( - RuntimeApiMessage::Request(parent, RuntimeApiRequest::AsyncBackingParams(tx)) - ) if parent == *hash => { - tx.send(Ok(test_state.config.async_backing_params.unwrap_or(DEFAULT_ASYNC_BACKING_PARAMETERS))).unwrap(); - } - ); - let header = Header { parent_hash: *parent_hash, number: *number, diff --git a/polkadot/node/network/statement-distribution/src/v2/tests/requests.rs b/polkadot/node/network/statement-distribution/src/v2/tests/requests.rs index fc880c1d9a836d9ece1475c687d81b1e5b8fea37..91df8e0a2f8c3417a23452f80aa205526595c775 100644 --- a/polkadot/node/network/statement-distribution/src/v2/tests/requests.rs +++ b/polkadot/node/network/statement-distribution/src/v2/tests/requests.rs @@ -38,7 +38,6 @@ fn cluster_peer_allowed_to_send_incomplete_statements(#[case] allow_v2_descripto validator_count: 20, group_size, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors, }; @@ -202,14 +201,12 @@ fn peer_reported_for_providing_statements_meant_to_be_masked_out() { validator_count, group_size, local_validator: LocalRole::Validator, - async_backing_params: Some(AsyncBackingParams { - // Makes `seconding_limit: 2` (easier to hit the limit). - max_candidate_depth: 1, - allowed_ancestry_len: 3, - }), allow_v2_descriptors: false, }; + // use a scheduling_lookahead of two to restrict the per-core seconding limit to 2. + let scheduling_lookahead = 2; + let relay_parent = Hash::repeat_byte(1); let peer_c = PeerId::random(); let peer_d = PeerId::random(); @@ -222,7 +219,8 @@ fn peer_reported_for_providing_statements_meant_to_be_masked_out() { let other_group = next_group_index(local_group_index, validator_count, group_size); let other_para = ParaId::from(other_group.0); - let test_leaf = state.make_dummy_leaf(relay_parent); + let test_leaf = + state.make_dummy_leaf_with_scheduling_lookahead(relay_parent, scheduling_lookahead); let (candidate_1, pvd_1) = make_candidate( relay_parent, @@ -482,7 +480,6 @@ fn peer_reported_for_not_enough_statements() { validator_count, group_size, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors: false, }; @@ -670,7 +667,6 @@ fn peer_reported_for_duplicate_statements() { validator_count: 20, group_size, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors: false, }; @@ -824,7 +820,6 @@ fn peer_reported_for_providing_statements_with_invalid_signatures() { validator_count: 20, group_size, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors: false, }; @@ -956,7 +951,6 @@ fn peer_reported_for_invalid_v2_descriptor() { validator_count: 20, group_size, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors: true, }; @@ -988,7 +982,6 @@ fn peer_reported_for_invalid_v2_descriptor() { let other_group_validators = state.group_validators(local_group_index, true); let v_a = other_group_validators[0]; let v_b = other_group_validators[1]; - let v_c = other_group_validators[1]; // peer A is in group, has relay parent in view. // peer B is in group, has no relay parent in view. @@ -997,14 +990,14 @@ fn peer_reported_for_invalid_v2_descriptor() { connect_peer( &mut overseer, peer_a.clone(), - Some(vec![state.discovery_id(other_group_validators[0])].into_iter().collect()), + Some(vec![state.discovery_id(v_a)].into_iter().collect()), ) .await; connect_peer( &mut overseer, peer_b.clone(), - Some(vec![state.discovery_id(other_group_validators[1])].into_iter().collect()), + Some(vec![state.discovery_id(v_b)].into_iter().collect()), ) .await; @@ -1177,11 +1170,17 @@ fn peer_reported_for_invalid_v2_descriptor() { .clone(); let statements = vec![b_seconded_invalid.clone()]; + // v_a has exhausted its seconded statements (3). + let mut statement_filter = StatementFilter::blank(group_size); + statement_filter + .seconded_in_group + .set(state.index_within_group(local_group_index, v_a).unwrap(), true); + handle_sent_request( &mut overseer, peer_a, candidate_hash, - StatementFilter::blank(group_size), + statement_filter, candidate.clone(), pvd.clone(), statements, @@ -1213,7 +1212,7 @@ fn peer_reported_for_invalid_v2_descriptor() { assert_eq!(peers, vec![peer_a.clone()]); assert_eq!(r, relay_parent); assert_eq!(s.unchecked_payload(), &CompactStatement::Seconded(candidate_hash)); - assert_eq!(s.unchecked_validator_index(), v_c); + assert_eq!(s.unchecked_validator_index(), v_b); } ); @@ -1234,7 +1233,6 @@ fn v2_descriptors_filtered(#[case] allow_v2_descriptors: bool) { validator_count: 20, group_size, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors, }; @@ -1365,7 +1363,6 @@ fn peer_reported_for_providing_statements_with_wrong_validator_id() { validator_count: 20, group_size, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors: false, }; @@ -1496,7 +1493,6 @@ fn disabled_validators_added_to_unwanted_mask() { validator_count: 20, group_size, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors: false, }; @@ -1663,7 +1659,6 @@ fn disabling_works_from_relay_parent_not_the_latest_state() { validator_count: 20, group_size, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors: false, }; @@ -1863,7 +1858,6 @@ fn local_node_sanity_checks_incoming_requests() { validator_count: 20, group_size: 3, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors: false, }; @@ -2065,7 +2059,6 @@ fn local_node_checks_that_peer_can_request_before_responding() { validator_count: 20, group_size: 3, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors: false, }; @@ -2265,7 +2258,6 @@ fn local_node_respects_statement_mask() { validator_count, group_size, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors: false, }; @@ -2508,7 +2500,6 @@ fn should_delay_before_retrying_dropped_requests() { validator_count, group_size, local_validator: LocalRole::Validator, - async_backing_params: None, allow_v2_descriptors: false, }; diff --git a/polkadot/node/overseer/src/lib.rs b/polkadot/node/overseer/src/lib.rs index 3881ddbcc9046dfb1f805c82a46c824d169e19f6..17470d74577d2147bb4faf2461aa2e1faa85ffae 100644 --- a/polkadot/node/overseer/src/lib.rs +++ b/polkadot/node/overseer/src/lib.rs @@ -533,7 +533,6 @@ pub struct Overseer<SupportsParachains> { #[subsystem(ProvisionerMessage, sends: [ RuntimeApiMessage, CandidateBackingMessage, - ChainApiMessage, DisputeCoordinatorMessage, ProspectiveParachainsMessage, ])] diff --git a/polkadot/node/primitives/src/lib.rs b/polkadot/node/primitives/src/lib.rs index 1e5ce6489bc8259f121d6737447c5cf097ac60cf..845daa2679850cea080400dfe6abdec11146d8aa 100644 --- a/polkadot/node/primitives/src/lib.rs +++ b/polkadot/node/primitives/src/lib.rs @@ -59,7 +59,7 @@ pub use disputes::{ /// relatively rare. /// /// The associated worker binaries should use the same version as the node that spawns them. -pub const NODE_VERSION: &'static str = "1.17.0"; +pub const NODE_VERSION: &'static str = "1.17.1"; // For a 16-ary Merkle Prefix Trie, we can expect at most 16 32-byte hashes per node // plus some overhead: diff --git a/polkadot/node/service/src/overseer.rs b/polkadot/node/service/src/overseer.rs index e4ea6efeaac22bacf78074b3ba21c53fa160ff37..a90570a149b52807d1da3c5dc47a13e7d4d1fbdd 100644 --- a/polkadot/node/service/src/overseer.rs +++ b/polkadot/node/service/src/overseer.rs @@ -600,7 +600,7 @@ pub fn collator_overseer_builder<Spawner, RuntimeClient>( network_service, sync_service, authority_discovery_service, - collation_req_v1_receiver, + collation_req_v1_receiver: _, collation_req_v2_receiver, available_data_req_receiver, registry, @@ -703,7 +703,6 @@ where IsParachainNode::Collator(collator_pair) => ProtocolSide::Collator { peer_id: network_service.local_peer_id(), collator_pair, - request_receiver_v1: collation_req_v1_receiver, request_receiver_v2: collation_req_v2_receiver, metrics: Metrics::register(registry)?, }, diff --git a/polkadot/node/subsystem-types/src/messages.rs b/polkadot/node/subsystem-types/src/messages.rs index 8a3b91b3ec741baa9003b0c637567b8f79e614d7..4d4fc89a6addc10866ff7c2b00af75c7a28b2ae3 100644 --- a/polkadot/node/subsystem-types/src/messages.rs +++ b/polkadot/node/subsystem-types/src/messages.rs @@ -775,6 +775,9 @@ pub enum RuntimeApiRequest { /// Get the backing constraints for a particular parachain. /// `V12` BackingConstraints(ParaId, RuntimeApiSender<Option<Constraints>>), + /// Get the lookahead from the scheduler params. + /// `V12` + SchedulingLookahead(SessionIndex, RuntimeApiSender<u32>), } impl RuntimeApiRequest { @@ -818,6 +821,9 @@ impl RuntimeApiRequest { /// `backing_constraints` pub const CONSTRAINTS_RUNTIME_REQUIREMENT: u32 = 12; + + /// `SchedulingLookahead` + pub const SCHEDULING_LOOKAHEAD_RUNTIME_REQUIREMENT: u32 = 12; } /// A message to the Runtime API subsystem. @@ -852,9 +858,6 @@ pub enum StatementDistributionMessage { pub enum ProvisionableData { /// This bitfield indicates the availability of various candidate blocks. Bitfield(Hash, SignedAvailabilityBitfield), - /// The Candidate Backing subsystem believes that this candidate is valid, pending - /// availability. - BackedCandidate(CandidateReceipt), /// Misbehavior reports are self-contained proofs of validator misbehavior. MisbehaviorReport(Hash, ValidatorIndex, Misbehavior), /// Disputes trigger a broad dispute resolution process. diff --git a/polkadot/node/subsystem-types/src/runtime_client.rs b/polkadot/node/subsystem-types/src/runtime_client.rs index 018b52bedcd24fd57fbddaf55c769a99db4a8765..7e3849c20694dc2343bcd32e644b79af03ac761e 100644 --- a/polkadot/node/subsystem-types/src/runtime_client.rs +++ b/polkadot/node/subsystem-types/src/runtime_client.rs @@ -241,23 +241,18 @@ pub trait RuntimeApiSubsystemClient { /***** Added in v3 **** */ /// Returns all onchain disputes. - /// This is a staging method! Do not use on production runtimes! async fn disputes( &self, at: Hash, ) -> Result<Vec<(SessionIndex, CandidateHash, DisputeState<BlockNumber>)>, ApiError>; /// Returns a list of validators that lost a past session dispute and need to be slashed. - /// - /// WARNING: This is a staging method! Do not use on production runtimes! async fn unapplied_slashes( &self, at: Hash, ) -> Result<Vec<(SessionIndex, CandidateHash, slashing::PendingSlashes)>, ApiError>; /// Returns a merkle proof of a validator session key in a past session. - /// - /// WARNING: This is a staging method! Do not use on production runtimes! async fn key_ownership_proof( &self, at: Hash, @@ -266,8 +261,6 @@ pub trait RuntimeApiSubsystemClient { /// Submits an unsigned extrinsic to slash validators who lost a dispute about /// a candidate of a past session. - /// - /// WARNING: This is a staging method! Do not use on production runtimes! async fn submit_report_dispute_lost( &self, at: Hash, @@ -356,6 +349,10 @@ pub trait RuntimeApiSubsystemClient { at: Hash, para_id: Id, ) -> Result<Option<Constraints>, ApiError>; + + // === v12 === + /// Fetch the scheduling lookahead value + async fn scheduling_lookahead(&self, at: Hash) -> Result<u32, ApiError>; } /// Default implementation of [`RuntimeApiSubsystemClient`] using the client. @@ -641,6 +638,10 @@ where ) -> Result<Option<Constraints>, ApiError> { self.client.runtime_api().backing_constraints(at, para_id) } + + async fn scheduling_lookahead(&self, at: Hash) -> Result<u32, ApiError> { + self.client.runtime_api().scheduling_lookahead(at) + } } impl<Client, Block> HeaderBackend<Block> for DefaultSubsystemClient<Client> diff --git a/polkadot/node/subsystem-util/src/backing_implicit_view.rs b/polkadot/node/subsystem-util/src/backing_implicit_view.rs index 67f5dad518e18ed71ae540db804a71a6681b0f9a..d8e242109955a1ef778c88d6f5161dd05b4feb8a 100644 --- a/polkadot/node/subsystem-util/src/backing_implicit_view.rs +++ b/polkadot/node/subsystem-util/src/backing_implicit_view.rs @@ -20,14 +20,14 @@ use polkadot_node_subsystem::{ messages::{ChainApiMessage, ProspectiveParachainsMessage, RuntimeApiMessage}, SubsystemSender, }; -use polkadot_primitives::{AsyncBackingParams, BlockNumber, Hash, Id as ParaId}; +use polkadot_primitives::{BlockNumber, Hash, Id as ParaId}; use std::collections::{HashMap, HashSet}; use crate::{ inclusion_emulator::RelayChainBlockInfo, - request_async_backing_params, request_session_index_for_child, - runtime::{self, recv_runtime}, + request_session_index_for_child, + runtime::{self, fetch_scheduling_lookahead, recv_runtime}, LOG_TARGET, }; @@ -149,6 +149,11 @@ impl View { self.leaves.keys() } + /// Check if the given block hash is an active leaf of the current view. + pub fn contains_leaf(&self, leaf_hash: &Hash) -> bool { + self.leaves.contains_key(leaf_hash) + } + /// Activate a leaf in the view. /// This will request the minimum relay parents the leaf and will load headers in the /// ancestry of the leaf as needed. These are the 'implicit ancestors' of the leaf. @@ -590,22 +595,22 @@ where + SubsystemSender<RuntimeApiMessage> + SubsystemSender<ChainApiMessage>, { - let AsyncBackingParams { allowed_ancestry_len, .. } = - recv_runtime(request_async_backing_params(leaf_hash, sender).await).await?; - // Fetch the session of the leaf. We must make sure that we stop at the ancestor which has a // different session index. let required_session = recv_runtime(request_session_index_for_child(leaf_hash, sender).await).await?; + let scheduling_lookahead = + fetch_scheduling_lookahead(leaf_hash, required_session, sender).await?; + let mut min = leaf_number; - // Fetch the ancestors, up to allowed_ancestry_len. + // Fetch the ancestors, up to (scheduling_lookahead - 1). let (tx, rx) = oneshot::channel(); sender .send_message(ChainApiMessage::Ancestors { hash: leaf_hash, - k: allowed_ancestry_len as usize, + k: scheduling_lookahead.saturating_sub(1) as usize, response_channel: tx, }) .await; @@ -642,7 +647,7 @@ mod tests { make_subsystem_context, TestSubsystemContextHandle, }; use polkadot_overseer::SubsystemContext; - use polkadot_primitives::{AsyncBackingParams, Header}; + use polkadot_primitives::Header; use sp_core::testing::TaskExecutor; use std::time::Duration; @@ -743,23 +748,24 @@ mod tests { ); } - async fn assert_async_backing_params_request( + async fn assert_scheduling_lookahead_request( virtual_overseer: &mut VirtualOverseer, leaf: Hash, - params: AsyncBackingParams, + lookahead: u32, ) { assert_matches!( overseer_recv(virtual_overseer).await, AllMessages::RuntimeApi( RuntimeApiMessage::Request( leaf_hash, - RuntimeApiRequest::AsyncBackingParams( + RuntimeApiRequest::SchedulingLookahead( + _, tx ) ) ) => { assert_eq!(leaf, leaf_hash, "received unexpected leaf hash"); - tx.send(Ok(params)).unwrap(); + tx.send(Ok(lookahead)).unwrap(); } ); } @@ -946,18 +952,11 @@ mod tests { let overseer_fut = async { assert_block_header_requests(&mut ctx_handle, CHAIN_B, &CHAIN_B[leaf_idx..]).await; - assert_async_backing_params_request( - &mut ctx_handle, - *leaf, - AsyncBackingParams { - max_candidate_depth: 0, - allowed_ancestry_len: PARA_A_MIN_PARENT, - }, - ) - .await; - assert_session_index_request(&mut ctx_handle, *leaf, current_session).await; + assert_scheduling_lookahead_request(&mut ctx_handle, *leaf, PARA_A_MIN_PARENT + 1) + .await; + assert_ancestors_request( &mut ctx_handle, *leaf, @@ -1020,18 +1019,11 @@ mod tests { let overseer_fut = async { assert_block_header_requests(&mut ctx_handle, CHAIN_A, &blocks[leaf_idx..]).await; - assert_async_backing_params_request( - &mut ctx_handle, - *leaf, - AsyncBackingParams { - max_candidate_depth: 0, - allowed_ancestry_len: blocks.len() as u32, - }, - ) - .await; - assert_session_index_request(&mut ctx_handle, *leaf, current_session).await; + assert_scheduling_lookahead_request(&mut ctx_handle, *leaf, blocks.len() as u32 + 1) + .await; + assert_ancestors_request( &mut ctx_handle, *leaf, diff --git a/polkadot/node/subsystem-util/src/runtime/mod.rs b/polkadot/node/subsystem-util/src/runtime/mod.rs index d84951ae1366518c5a7037dcbe227c9ec574ea66..dd843cfb01fa9030511ddd426417f85433d8802b 100644 --- a/polkadot/node/subsystem-util/src/runtime/mod.rs +++ b/polkadot/node/subsystem-util/src/runtime/mod.rs @@ -33,21 +33,20 @@ use polkadot_primitives::{ node_features::FeatureIndex, slashing, vstaging::{CandidateEvent, CoreState, OccupiedCore, ScrapedOnChainVotes}, - AsyncBackingParams, CandidateHash, CoreIndex, EncodeAs, ExecutorParams, GroupIndex, - GroupRotationInfo, Hash, Id as ParaId, IndexedVec, NodeFeatures, SessionIndex, SessionInfo, - Signed, SigningContext, UncheckedSigned, ValidationCode, ValidationCodeHash, ValidatorId, - ValidatorIndex, LEGACY_MIN_BACKING_VOTES, + CandidateHash, CoreIndex, EncodeAs, ExecutorParams, GroupIndex, GroupRotationInfo, Hash, + Id as ParaId, IndexedVec, NodeFeatures, SessionIndex, SessionInfo, Signed, SigningContext, + UncheckedSigned, ValidationCode, ValidationCodeHash, ValidatorId, ValidatorIndex, + DEFAULT_SCHEDULING_LOOKAHEAD, LEGACY_MIN_BACKING_VOTES, }; use std::collections::{BTreeMap, VecDeque}; use crate::{ - has_required_runtime, request_async_backing_params, request_availability_cores, - request_candidate_events, request_claim_queue, request_disabled_validators, - request_from_runtime, request_key_ownership_proof, request_on_chain_votes, - request_session_executor_params, request_session_index_for_child, request_session_info, - request_submit_report_dispute_lost, request_unapplied_slashes, request_validation_code_by_hash, - request_validator_groups, + has_required_runtime, request_availability_cores, request_candidate_events, + request_claim_queue, request_disabled_validators, request_from_runtime, + request_key_ownership_proof, request_on_chain_votes, request_session_executor_params, + request_session_index_for_child, request_session_info, request_submit_report_dispute_lost, + request_unapplied_slashes, request_validation_code_by_hash, request_validator_groups, }; /// Errors that can happen on runtime fetches. @@ -469,64 +468,6 @@ where .await } -/// Prospective parachains mode of a relay parent. Defined by -/// the Runtime API version. -/// -/// Needed for the period of transition to asynchronous backing. -#[derive(Debug, Copy, Clone)] -pub enum ProspectiveParachainsMode { - /// Runtime API without support of `async_backing_params`: no prospective parachains. - Disabled, - /// v6 runtime API: prospective parachains. - Enabled { - /// The maximum number of para blocks between the para head in a relay parent - /// and a new candidate. Restricts nodes from building arbitrary long chains - /// and spamming other validators. - max_candidate_depth: usize, - /// How many ancestors of a relay parent are allowed to build candidates on top - /// of. - allowed_ancestry_len: usize, - }, -} - -impl ProspectiveParachainsMode { - /// Returns `true` if mode is enabled, `false` otherwise. - pub fn is_enabled(&self) -> bool { - matches!(self, ProspectiveParachainsMode::Enabled { .. }) - } -} - -/// Requests prospective parachains mode for a given relay parent based on -/// the Runtime API version. -pub async fn prospective_parachains_mode<Sender>( - sender: &mut Sender, - relay_parent: Hash, -) -> Result<ProspectiveParachainsMode> -where - Sender: SubsystemSender<RuntimeApiMessage>, -{ - let result = recv_runtime(request_async_backing_params(relay_parent, sender).await).await; - - if let Err(error::Error::RuntimeRequest(RuntimeApiError::NotSupported { runtime_api_name })) = - &result - { - gum::trace!( - target: LOG_TARGET, - ?relay_parent, - "Prospective parachains are disabled, {} is not supported by the current Runtime API", - runtime_api_name, - ); - - Ok(ProspectiveParachainsMode::Disabled) - } else { - let AsyncBackingParams { max_candidate_depth, allowed_ancestry_len } = result?; - Ok(ProspectiveParachainsMode::Enabled { - max_candidate_depth: max_candidate_depth as _, - allowed_ancestry_len: allowed_ancestry_len as _, - }) - } -} - /// Request the min backing votes value. /// Prior to runtime API version 6, just return a hardcoded constant. pub async fn request_min_backing_votes( @@ -655,27 +596,44 @@ pub async fn get_disabled_validators_with_fallback<Sender: SubsystemSender<Runti Ok(disabled_validators) } -/// Checks if the runtime supports `request_claim_queue` and attempts to fetch the claim queue. -/// Returns `ClaimQueueSnapshot` or `None` if claim queue API is not supported by runtime. -/// Any specific `RuntimeApiError` is bubbled up to the caller. +/// Fetch the claim queue and wrap it into a helpful `ClaimQueueSnapshot` pub async fn fetch_claim_queue( sender: &mut impl SubsystemSender<RuntimeApiMessage>, relay_parent: Hash, -) -> Result<Option<ClaimQueueSnapshot>> { - if has_required_runtime( - sender, - relay_parent, - RuntimeApiRequest::CLAIM_QUEUE_RUNTIME_REQUIREMENT, +) -> Result<ClaimQueueSnapshot> { + let cq = request_claim_queue(relay_parent, sender) + .await + .await + .map_err(Error::RuntimeRequestCanceled)??; + + Ok(cq.into()) +} + +/// Checks if the runtime supports `request_claim_queue` and attempts to fetch the claim queue. +/// Returns `ClaimQueueSnapshot` or `None` if claim queue API is not supported by runtime. +pub async fn fetch_scheduling_lookahead( + parent: Hash, + session_index: SessionIndex, + sender: &mut impl overseer::SubsystemSender<RuntimeApiMessage>, +) -> Result<u32> { + let res = recv_runtime( + request_from_runtime(parent, sender, |tx| { + RuntimeApiRequest::SchedulingLookahead(session_index, tx) + }) + .await, ) - .await - { - let res = request_claim_queue(relay_parent, sender) - .await - .await - .map_err(Error::RuntimeRequestCanceled)??; - Ok(Some(res.into())) + .await; + + if let Err(Error::RuntimeRequest(RuntimeApiError::NotSupported { .. })) = res { + gum::trace!( + target: LOG_TARGET, + ?parent, + "Querying the scheduling lookahead from the runtime is not supported by the current Runtime API, falling back to default value of {}", + DEFAULT_SCHEDULING_LOOKAHEAD + ); + + Ok(DEFAULT_SCHEDULING_LOOKAHEAD) } else { - gum::trace!(target: LOG_TARGET, "Runtime doesn't support `request_claim_queue`"); - Ok(None) + res } } diff --git a/polkadot/node/test/service/Cargo.toml b/polkadot/node/test/service/Cargo.toml index 54db2a0ac942512eb79785b3d91ca1b2b2d22270..96bbdd2e7bdefd558b2a9a3fa7649612e62463cd 100644 --- a/polkadot/node/test/service/Cargo.toml +++ b/polkadot/node/test/service/Cargo.toml @@ -62,7 +62,6 @@ substrate-test-client = { workspace = true } [dev-dependencies] pallet-balances = { workspace = true } -substrate-test-utils = { workspace = true } tokio = { features = ["macros"], workspace = true, default-features = true } [features] diff --git a/polkadot/node/test/service/src/chain_spec.rs b/polkadot/node/test/service/src/chain_spec.rs index ae4e84b7725e50348a2d635e0e340614dd445043..ef83c4795dc6889895dbf03e9e87c36161e6bb1e 100644 --- a/polkadot/node/test/service/src/chain_spec.rs +++ b/polkadot/node/test/service/src/chain_spec.rs @@ -18,7 +18,8 @@ use pallet_staking::Forcing; use polkadot_primitives::{ - AccountId, AssignmentId, SchedulerParams, ValidatorId, MAX_CODE_SIZE, MAX_POV_SIZE, + node_features, AccountId, AssignmentId, NodeFeatures, SchedulerParams, ValidatorId, + MAX_CODE_SIZE, MAX_POV_SIZE, }; use polkadot_service::chain_spec::Extensions; use polkadot_test_runtime::BABE_GENESIS_EPOCH_CONFIG; @@ -110,6 +111,11 @@ fn polkadot_testnet_genesis( const ENDOWMENT: u128 = 1_000_000 * DOTS; const STASH: u128 = 100 * DOTS; + // Prepare node features with V2 receipts enabled. + let mut node_features = NodeFeatures::new(); + node_features.resize(node_features::FeatureIndex::CandidateReceiptV2 as usize + 1, false); + node_features.set(node_features::FeatureIndex::CandidateReceiptV2 as u8 as usize, true); + serde_json::json!({ "balances": { "balances": endowed_accounts.iter().map(|k| (k.clone(), ENDOWMENT)).collect::<Vec<_>>(), @@ -158,6 +164,7 @@ fn polkadot_testnet_genesis( no_show_slots: 10, minimum_validation_upgrade_delay: 5, max_downward_message_size: 1024, + node_features, scheduler_params: SchedulerParams { group_rotation_frequency: 20, paras_availability_period: 4, diff --git a/polkadot/parachain/test-parachains/adder/collator/Cargo.toml b/polkadot/parachain/test-parachains/adder/collator/Cargo.toml index 20305dc07c3a5709e9b4626c89aa5b06398eb30d..301a0d10ba851e189396fb199903027efe8bf2c0 100644 --- a/polkadot/parachain/test-parachains/adder/collator/Cargo.toml +++ b/polkadot/parachain/test-parachains/adder/collator/Cargo.toml @@ -39,6 +39,5 @@ polkadot-test-service = { workspace = true } sc-service = { workspace = true, default-features = true } sp-keyring = { workspace = true, default-features = true } -substrate-test-utils = { workspace = true } tokio = { features = ["macros"], workspace = true, default-features = true } diff --git a/polkadot/parachain/test-parachains/undying/Cargo.toml b/polkadot/parachain/test-parachains/undying/Cargo.toml index 43b5a3352434feff95274d4c5b0435829e390573..f8dfc8936c0ef3bd7abd7e85fe3094c9318edb02 100644 --- a/polkadot/parachain/test-parachains/undying/Cargo.toml +++ b/polkadot/parachain/test-parachains/undying/Cargo.toml @@ -16,6 +16,7 @@ codec = { features = ["derive"], workspace = true } dlmalloc = { features = ["global"], workspace = true } log = { workspace = true } polkadot-parachain-primitives = { features = ["wasm-api"], workspace = true } +polkadot-primitives = { workspace = true, default-features = false } tiny-keccak = { features = ["keccak"], workspace = true } # We need to make sure the global allocator is disabled until we have support of full substrate externalities @@ -30,5 +31,6 @@ std = [ "codec/std", "log/std", "polkadot-parachain-primitives/std", + "polkadot-primitives/std", "sp-io/std", ] diff --git a/polkadot/parachain/test-parachains/undying/collator/Cargo.toml b/polkadot/parachain/test-parachains/undying/collator/Cargo.toml index b964b4dc49ce5d4e18cdc33ba8907d043423d32c..e26b9f59acd4bf7724c9308dda6827c95e8a8651 100644 --- a/polkadot/parachain/test-parachains/undying/collator/Cargo.toml +++ b/polkadot/parachain/test-parachains/undying/collator/Cargo.toml @@ -22,6 +22,7 @@ futures-timer = { workspace = true } log = { workspace = true, default-features = true } polkadot-cli = { workspace = true, default-features = true } +polkadot-erasure-coding = { workspace = true, default-features = true } polkadot-node-primitives = { workspace = true, default-features = true } polkadot-node-subsystem = { workspace = true, default-features = true } polkadot-primitives = { workspace = true, default-features = true } @@ -29,6 +30,7 @@ polkadot-service = { features = ["rococo-native"], workspace = true, default-fea test-parachain-undying = { workspace = true } sc-cli = { workspace = true, default-features = true } +sc-client-api = { workspace = true, default-features = true } sc-service = { workspace = true, default-features = true } sp-core = { workspace = true, default-features = true } @@ -39,6 +41,5 @@ polkadot-test-service = { workspace = true } sc-service = { workspace = true, default-features = true } sp-keyring = { workspace = true, default-features = true } -substrate-test-utils = { workspace = true } tokio = { features = ["macros"], workspace = true, default-features = true } diff --git a/polkadot/parachain/test-parachains/undying/collator/src/cli.rs b/polkadot/parachain/test-parachains/undying/collator/src/cli.rs index 9572887a51a2a195a01e6ceced60ee711288ead2..a3de7c80d214a2e9c0669dacdd33be65bdf9ab18 100644 --- a/polkadot/parachain/test-parachains/undying/collator/src/cli.rs +++ b/polkadot/parachain/test-parachains/undying/collator/src/cli.rs @@ -61,6 +61,15 @@ pub struct ExportGenesisWasmCommand { pub output: Option<PathBuf>, } +/// Enum representing different types of malicious behaviors for collators. +#[derive(Debug, Parser, Clone, PartialEq, clap::ValueEnum)] +pub enum MalusType { + /// No malicious behavior. + None, + /// Submit the same collations to all assigned cores. + DuplicateCollations, +} + #[allow(missing_docs)] #[derive(Debug, Parser)] #[group(skip)] @@ -81,6 +90,10 @@ pub struct RunCmd { /// we compute per block. #[arg(long, default_value_t = 1)] pub pvf_complexity: u32, + + /// Specifies the malicious behavior of the collator. + #[arg(long, value_enum, default_value_t = MalusType::None)] + pub malus_type: MalusType, } #[allow(missing_docs)] diff --git a/polkadot/parachain/test-parachains/undying/collator/src/lib.rs b/polkadot/parachain/test-parachains/undying/collator/src/lib.rs index 448c181ae062bbaac7dc1b8312d50d26f1643ea9..3d5724ae79ba8fcfd24f4bd56e6a7b0eaa23bdf4 100644 --- a/polkadot/parachain/test-parachains/undying/collator/src/lib.rs +++ b/polkadot/parachain/test-parachains/undying/collator/src/lib.rs @@ -17,14 +17,25 @@ //! Collator for the `Undying` test parachain. use codec::{Decode, Encode}; -use futures::channel::oneshot; +use futures::{channel::oneshot, StreamExt}; use futures_timer::Delay; +use polkadot_cli::ProvideRuntimeApi; use polkadot_node_primitives::{ - maybe_compress_pov, Collation, CollationResult, CollationSecondedSignal, CollatorFn, - MaybeCompressedPoV, PoV, Statement, + maybe_compress_pov, AvailableData, Collation, CollationResult, CollationSecondedSignal, + CollatorFn, MaybeCompressedPoV, PoV, Statement, UpwardMessages, }; -use polkadot_primitives::{CollatorId, CollatorPair, Hash}; +use polkadot_node_subsystem::messages::CollatorProtocolMessage; +use polkadot_primitives::{ + vstaging::{ + CandidateDescriptorV2, CandidateReceiptV2, ClaimQueueOffset, DEFAULT_CLAIM_QUEUE_OFFSET, + }, + CandidateCommitments, CollatorId, CollatorPair, CoreIndex, Hash, Id as ParaId, + OccupiedCoreAssumption, +}; +use polkadot_service::{Handle, NewFull, ParachainHost}; +use sc_client_api::client::BlockchainEvents; use sp_core::Pair; + use std::{ collections::HashMap, sync::{ @@ -37,6 +48,8 @@ use test_parachain_undying::{ execute, hash_state, BlockData, GraveyardState, HeadData, StateMismatch, }; +pub const LOG_TARGET: &str = "parachain::undying-collator"; + /// Default PoV size which also drives state size. const DEFAULT_POV_SIZE: usize = 1000; /// Default PVF time complexity - 1 signature per block. @@ -52,19 +65,20 @@ fn calculate_head_and_state_for_number( let mut graveyard = vec![0u8; graveyard_size * graveyard_size]; let zombies = 0; let seal = [0u8; 32]; + let core_selector_number = 0; // Ensure a larger compressed PoV. graveyard.iter_mut().enumerate().for_each(|(i, grave)| { *grave = i as u8; }); - let mut state = GraveyardState { index, graveyard, zombies, seal }; + let mut state = GraveyardState { index, graveyard, zombies, seal, core_selector_number }; let mut head = HeadData { number: 0, parent_hash: Hash::default().into(), post_state: hash_state(&state) }; while head.number < number { let block = BlockData { state, tombstones: 1_000, iterations: pvf_complexity }; - let (new_head, new_state) = execute(head.hash(), head.clone(), block)?; + let (new_head, new_state, _) = execute(head.hash(), head.clone(), block)?; head = new_head; state = new_state; } @@ -99,13 +113,14 @@ impl State { let mut graveyard = vec![0u8; graveyard_size * graveyard_size]; let zombies = 0; let seal = [0u8; 32]; + let core_selector_number = 0; // Ensure a larger compressed PoV. graveyard.iter_mut().enumerate().for_each(|(i, grave)| { *grave = i as u8; }); - let state = GraveyardState { index, graveyard, zombies, seal }; + let state = GraveyardState { index, graveyard, zombies, seal, core_selector_number }; let head_data = HeadData { number: 0, parent_hash: Default::default(), post_state: hash_state(&state) }; @@ -123,7 +138,10 @@ impl State { /// Advance the state and produce a new block based on the given `parent_head`. /// /// Returns the new [`BlockData`] and the new [`HeadData`]. - fn advance(&mut self, parent_head: HeadData) -> Result<(BlockData, HeadData), StateMismatch> { + fn advance( + &mut self, + parent_head: HeadData, + ) -> Result<(BlockData, HeadData, UpwardMessages), StateMismatch> { self.best_block = parent_head.number; let state = if let Some(state) = self @@ -144,14 +162,15 @@ impl State { // Start with prev state and transaction to execute (place 1000 tombstones). let block = BlockData { state, tombstones: 1000, iterations: self.pvf_complexity }; - let (new_head, new_state) = execute(parent_head.hash(), parent_head, block.clone())?; + let (new_head, new_state, upward_messages) = + execute(parent_head.hash(), parent_head, block.clone())?; let new_head_arc = Arc::new(new_head.clone()); self.head_to_state.insert(new_head_arc.clone(), new_state); self.number_to_head.insert(new_head.number, new_head_arc); - Ok((block, new_head)) + Ok((block, new_head, upward_messages)) } } @@ -175,13 +194,18 @@ impl Collator { let graveyard_size = ((pov_size / std::mem::size_of::<u8>()) as f64).sqrt().ceil() as usize; log::info!( + target: LOG_TARGET, "PoV target size: {} bytes. Graveyard size: ({} x {})", pov_size, graveyard_size, - graveyard_size + graveyard_size, ); - log::info!("PVF time complexity: {}", pvf_complexity); + log::info!( + target: LOG_TARGET, + "PVF time complexity: {}", + pvf_complexity, + ); Self { state: Arc::new(Mutex::new(State::genesis(graveyard_size, pvf_complexity))), @@ -232,21 +256,32 @@ impl Collator { Box::new(move |relay_parent, validation_data| { let parent = match HeadData::decode(&mut &validation_data.parent_head.0[..]) { Err(err) => { - log::error!("Requested to build on top of malformed head-data: {:?}", err); + log::error!( + target: LOG_TARGET, + "Requested to build on top of malformed head-data: {:?}", + err, + ); return futures::future::ready(None).boxed() }, Ok(p) => p, }; - let (block_data, head_data) = match state.lock().unwrap().advance(parent.clone()) { - Err(err) => { - log::error!("Unable to build on top of {:?}: {:?}", parent, err); - return futures::future::ready(None).boxed() - }, - Ok(x) => x, - }; + let (block_data, head_data, upward_messages) = + match state.lock().unwrap().advance(parent.clone()) { + Err(err) => { + log::error!( + target: LOG_TARGET, + "Unable to build on top of {:?}: {:?}", + parent, + err, + ); + return futures::future::ready(None).boxed() + }, + Ok(x) => x, + }; log::info!( + target: LOG_TARGET, "created a new collation on relay-parent({}): {:?}", relay_parent, head_data, @@ -256,7 +291,7 @@ impl Collator { let pov = PoV { block_data: block_data.encode().into() }; let collation = Collation { - upward_messages: Default::default(), + upward_messages, horizontal_messages: Default::default(), new_validation_code: None, head_data: head_data.encode().into(), @@ -265,10 +300,15 @@ impl Collator { hrmp_watermark: validation_data.relay_parent_number, }; - log::info!("Raw PoV size for collation: {} bytes", pov.block_data.0.len(),); + log::info!( + target: LOG_TARGET, + "Raw PoV size for collation: {} bytes", + pov.block_data.0.len(), + ); let compressed_pov = maybe_compress_pov(pov); log::info!( + target: LOG_TARGET, "Compressed PoV size for collation: {} bytes", compressed_pov.block_data.0.len(), ); @@ -285,8 +325,9 @@ impl Collator { Statement::Seconded(s) if s.descriptor.pov_hash() == compressed_pov.hash(), ) { log::error!( + target: LOG_TARGET, "Seconded statement should match our collation: {:?}", - res.statement.payload() + res.statement.payload(), ); } @@ -330,6 +371,259 @@ impl Collator { } } } + + pub fn send_same_collations_to_all_assigned_cores( + &self, + full_node: &NewFull, + mut overseer_handle: Handle, + para_id: ParaId, + ) { + let client = full_node.client.clone(); + + let collation_function = + self.create_collation_function(full_node.task_manager.spawn_handle()); + + full_node + .task_manager + .spawn_handle() + .spawn("malus-undying-collator", None, async move { + // Subscribe to relay chain block import notifications. In each iteration, build a + // collation in response to a block import notification and submits it to all cores + // assigned to the parachain. + let mut import_notifications = client.import_notification_stream(); + + while let Some(notification) = import_notifications.next().await { + let relay_parent = notification.hash; + + // Get the list of cores assigned to the parachain. + let claim_queue = match client.runtime_api().claim_queue(relay_parent) { + Ok(claim_queue) => claim_queue, + Err(error) => { + log::error!( + target: LOG_TARGET, + "Failed to query claim queue runtime API: {error:?}", + ); + continue; + }, + }; + + let claim_queue_offset = ClaimQueueOffset(DEFAULT_CLAIM_QUEUE_OFFSET); + + let scheduled_cores: Vec<CoreIndex> = claim_queue + .iter() + .filter_map(move |(core_index, paras)| { + paras.get(claim_queue_offset.0 as usize).and_then(|core_para_id| { + (core_para_id == ¶_id).then_some(*core_index) + }) + }) + .collect(); + + if scheduled_cores.is_empty() { + log::info!( + target: LOG_TARGET, + "Scheduled cores is empty.", + ); + continue; + } + + if scheduled_cores.len() == 1 { + log::info!( + target: LOG_TARGET, + "Malus collator configured with duplicate collations, but only 1 core assigned. \ + Collator will not do anything malicious.", + ); + } + + // Fetch validation data for the collation. + let validation_data = match client.runtime_api().persisted_validation_data( + relay_parent, + para_id, + OccupiedCoreAssumption::Included, + ) { + Ok(Some(validation_data)) => validation_data, + Ok(None) => { + log::info!( + target: LOG_TARGET, + "Persisted validation data is None.", + ); + continue; + }, + Err(error) => { + log::error!( + target: LOG_TARGET, + "Failed to query persisted validation data runtime API: {error:?}", + ); + continue; + }, + }; + + // Generate the collation. + let collation = + match collation_function(relay_parent, &validation_data).await { + Some(collation) => collation, + None => { + log::info!( + target: LOG_TARGET, + "Collation result is None.", + ); + continue; + }, + } + .collation; + + // Fetch the validation code hash. + let validation_code_hash = match client.runtime_api().validation_code_hash( + relay_parent, + para_id, + OccupiedCoreAssumption::Included, + ) { + Ok(Some(validation_code_hash)) => validation_code_hash, + Ok(None) => { + log::info!( + target: LOG_TARGET, + "Validation code hash is None.", + ); + continue; + }, + Err(error) => { + log::error!( + target: LOG_TARGET, + "Failed to query validation code hash runtime API: {error:?}", + ); + continue; + }, + }; + + // Fetch the session index. + let session_index = + match client.runtime_api().session_index_for_child(relay_parent) { + Ok(session_index) => session_index, + Err(error) => { + log::error!( + target: LOG_TARGET, + "Failed to query session index for child runtime API: {error:?}", + ); + continue; + }, + }; + + let persisted_validation_data_hash = validation_data.hash(); + let parent_head_data = validation_data.parent_head.clone(); + let parent_head_data_hash = validation_data.parent_head.hash(); + + // Apply compression to the block data. + let pov = { + let pov = collation.proof_of_validity.into_compressed(); + let encoded_size = pov.encoded_size(); + let max_pov_size = validation_data.max_pov_size as usize; + + // As long as `POV_BOMB_LIMIT` is at least `max_pov_size`, this ensures + // that honest collators never produce a PoV which is uncompressed. + // + // As such, honest collators never produce an uncompressed PoV which starts + // with a compression magic number, which would lead validators to + // reject the collation. + if encoded_size > max_pov_size { + log::error!( + target: LOG_TARGET, + "PoV size {encoded_size} exceeded maximum size of {max_pov_size}", + ); + continue; + } + + pov + }; + + let pov_hash = pov.hash(); + + // Fetch the session info. + let session_info = + match client.runtime_api().session_info(relay_parent, session_index) { + Ok(Some(session_info)) => session_info, + Ok(None) => { + log::info!( + target: LOG_TARGET, + "Session info is None.", + ); + continue; + }, + Err(error) => { + log::error!( + target: LOG_TARGET, + "Failed to query session info runtime API: {error:?}", + ); + continue; + }, + }; + + let n_validators = session_info.validators.len(); + + let available_data = + AvailableData { validation_data, pov: Arc::new(pov.clone()) }; + let chunks = match polkadot_erasure_coding::obtain_chunks_v1( + n_validators, + &available_data, + ) { + Ok(chunks) => chunks, + Err(error) => { + log::error!( + target: LOG_TARGET, + "Failed to obtain chunks v1: {error:?}", + ); + continue; + }, + }; + let erasure_root = polkadot_erasure_coding::branches(&chunks).root(); + + let commitments = CandidateCommitments { + upward_messages: collation.upward_messages, + horizontal_messages: collation.horizontal_messages, + new_validation_code: collation.new_validation_code, + head_data: collation.head_data, + processed_downward_messages: collation.processed_downward_messages, + hrmp_watermark: collation.hrmp_watermark, + }; + + // Submit the same collation to all assigned cores. + for core_index in &scheduled_cores { + let candidate_receipt = CandidateReceiptV2 { + descriptor: CandidateDescriptorV2::new( + para_id, + relay_parent, + *core_index, + session_index, + persisted_validation_data_hash, + pov_hash, + erasure_root, + commitments.head_data.hash(), + validation_code_hash, + ), + commitments_hash: commitments.hash(), + }; + + // We cannot use SubmitCollation here because it includes an additional + // check for the core index by calling `check_core_index`. This check + // enforces that the parachain always selects the correct core by comparing + // the descriptor and commitments core indexes. To bypass this check, we are + // simulating the behavior of SubmitCollation while skipping the core index + // validation. + overseer_handle + .send_msg( + CollatorProtocolMessage::DistributeCollation { + candidate_receipt, + parent_head_data_hash, + pov: pov.clone(), + parent_head_data: parent_head_data.clone(), + result_sender: None, + core_index: *core_index, + }, + "Collator", + ) + .await; + } + } + }); + } } use sp_core::traits::SpawnNamed; diff --git a/polkadot/parachain/test-parachains/undying/collator/src/main.rs b/polkadot/parachain/test-parachains/undying/collator/src/main.rs index 017eefe5ee31e1695272ac63ad43567604152f03..9d993dd818b2f7486665103b83e7d613d8f86071 100644 --- a/polkadot/parachain/test-parachains/undying/collator/src/main.rs +++ b/polkadot/parachain/test-parachains/undying/collator/src/main.rs @@ -29,7 +29,7 @@ use std::{ use test_parachain_undying_collator::Collator; mod cli; -use cli::Cli; +use cli::{Cli, MalusType}; fn main() -> Result<()> { let cli = Cli::from_args(); @@ -105,6 +105,7 @@ fn main() -> Result<()> { .map_err(|e| e.to_string())?; let mut overseer_handle = full_node .overseer_handle + .clone() .expect("Overseer handle should be initialized for collators"); let genesis_head_hex = @@ -120,9 +121,16 @@ fn main() -> Result<()> { let config = CollationGenerationConfig { key: collator.collator_key(), - collator: Some( - collator.create_collation_function(full_node.task_manager.spawn_handle()), - ), + // If the collator is malicious, disable the collation function + // (set to None) and manually handle collation submission later. + collator: if cli.run.malus_type == MalusType::None { + Some( + collator + .create_collation_function(full_node.task_manager.spawn_handle()), + ) + } else { + None + }, para_id, }; overseer_handle @@ -133,6 +141,16 @@ fn main() -> Result<()> { .send_msg(CollatorProtocolMessage::CollateOn(para_id), "Collator") .await; + // If the collator is configured to behave maliciously, simulate the specified + // malicious behavior. + if cli.run.malus_type == MalusType::DuplicateCollations { + collator.send_same_collations_to_all_assigned_cores( + &full_node, + overseer_handle, + para_id, + ); + } + Ok(full_node.task_manager) }) }, diff --git a/polkadot/parachain/test-parachains/undying/collator/tests/integration.rs b/polkadot/parachain/test-parachains/undying/collator/tests/integration.rs index b8e32b13bc9c78eed14b0a827212bd2316785802..866b2f888f84e86a67bb578269c3571dd84bf4f5 100644 --- a/polkadot/parachain/test-parachains/undying/collator/tests/integration.rs +++ b/polkadot/parachain/test-parachains/undying/collator/tests/integration.rs @@ -19,6 +19,12 @@ // If this test is failing, make sure to run all tests with the `real-overseer` feature being // enabled. + +use polkadot_node_subsystem::TimeoutExt; +use std::time::Duration; + +const TIMEOUT: Duration = Duration::from_secs(120); + #[tokio::test(flavor = "multi_thread")] async fn collating_using_undying_collator() { use polkadot_primitives::Id as ParaId; @@ -82,8 +88,16 @@ async fn collating_using_undying_collator() { .await; // Wait until the parachain has 4 blocks produced. - collator.wait_for_blocks(4).await; + collator + .wait_for_blocks(4) + .timeout(TIMEOUT) + .await + .expect("Timed out waiting for 4 produced blocks"); // Wait until the collator received `12` seconded statements for its collations. - collator.wait_for_seconded_collations(12).await; + collator + .wait_for_seconded_collations(12) + .timeout(TIMEOUT) + .await + .expect("Timed out waiting for 12 seconded collations"); } diff --git a/polkadot/parachain/test-parachains/undying/src/lib.rs b/polkadot/parachain/test-parachains/undying/src/lib.rs index e4ec7e99346bbef4f3ce2fdb03b6084c053926f8..4f014320d09bbd4f7045376016dfa564e65d1053 100644 --- a/polkadot/parachain/test-parachains/undying/src/lib.rs +++ b/polkadot/parachain/test-parachains/undying/src/lib.rs @@ -22,6 +22,10 @@ extern crate alloc; use alloc::vec::Vec; use codec::{Decode, Encode}; +use polkadot_parachain_primitives::primitives::UpwardMessages; +use polkadot_primitives::vstaging::{ + ClaimQueueOffset, CoreSelector, UMPSignal, DEFAULT_CLAIM_QUEUE_OFFSET, UMP_SEPARATOR, +}; use tiny_keccak::{Hasher as _, Keccak}; #[cfg(not(feature = "std"))] @@ -86,6 +90,8 @@ pub struct GraveyardState { pub zombies: u64, // Grave seal. pub seal: [u8; 32], + // Increasing sequence number for core selector. + pub core_selector_number: u8, } /// Block data for this parachain. @@ -119,6 +125,7 @@ pub fn execute_transaction(mut block_data: BlockData) -> GraveyardState { // Chain hash the seals and burn CPU. block_data.state.seal = hash_state(&block_data.state); } + block_data.state.core_selector_number = block_data.state.core_selector_number.wrapping_add(1); block_data.state } @@ -133,7 +140,7 @@ pub fn execute( parent_hash: [u8; 32], parent_head: HeadData, block_data: BlockData, -) -> Result<(HeadData, GraveyardState), StateMismatch> { +) -> Result<(HeadData, GraveyardState, UpwardMessages), StateMismatch> { assert_eq!(parent_hash, parent_head.hash()); if hash_state(&block_data.state) != parent_head.post_state { @@ -146,6 +153,16 @@ pub fn execute( return Err(StateMismatch) } + let mut upward_messages: UpwardMessages = Default::default(); + upward_messages.force_push(UMP_SEPARATOR); + upward_messages.force_push( + UMPSignal::SelectCore( + CoreSelector(block_data.state.core_selector_number), + ClaimQueueOffset(DEFAULT_CLAIM_QUEUE_OFFSET), + ) + .encode(), + ); + // We need to clone the block data as the fn will mutate it's state. let new_state = execute_transaction(block_data.clone()); @@ -156,5 +173,6 @@ pub fn execute( post_state: hash_state(&new_state), }, new_state, + upward_messages, )) } diff --git a/polkadot/parachain/test-parachains/undying/src/wasm_validation.rs b/polkadot/parachain/test-parachains/undying/src/wasm_validation.rs index 46b66aa518e490e117c6d190d52a4d4dc85574d7..42917484cfdc2f0622e30260cb0b7c979a64c9d9 100644 --- a/polkadot/parachain/test-parachains/undying/src/wasm_validation.rs +++ b/polkadot/parachain/test-parachains/undying/src/wasm_validation.rs @@ -31,13 +31,13 @@ pub extern "C" fn validate_block(params: *const u8, len: usize) -> u64 { let parent_hash = crate::keccak256(¶ms.parent_head.0[..]); - let (new_head, _) = + let (new_head, _, upward_messages) = crate::execute(parent_hash, parent_head, block_data).expect("Executes block"); polkadot_parachain_primitives::write_result(&ValidationResult { head_data: GenericHeadData(new_head.encode()), new_validation_code: None, - upward_messages: alloc::vec::Vec::new().try_into().expect("empty vec fits within bounds"), + upward_messages, horizontal_messages: alloc::vec::Vec::new() .try_into() .expect("empty vec fits within bounds"), diff --git a/polkadot/primitives/src/lib.rs b/polkadot/primitives/src/lib.rs index 493f9fb5ba92ee66320ad6ead60e5bb1111213b9..361b66cf27f677fc2e7c6d52568ee65a799b8fdb 100644 --- a/polkadot/primitives/src/lib.rs +++ b/polkadot/primitives/src/lib.rs @@ -60,8 +60,8 @@ pub use v8::{ UncheckedSignedAvailabilityBitfields, UncheckedSignedStatement, UpgradeGoAhead, UpgradeRestriction, UpwardMessage, ValidDisputeStatementKind, ValidationCode, ValidationCodeHash, ValidatorId, ValidatorIndex, ValidatorSignature, ValidityAttestation, - ValidityError, ASSIGNMENT_KEY_TYPE_ID, LEGACY_MIN_BACKING_VOTES, LOWEST_PUBLIC_ID, - MAX_CODE_SIZE, MAX_HEAD_DATA_SIZE, MAX_POV_SIZE, MIN_CODE_SIZE, + ValidityError, ASSIGNMENT_KEY_TYPE_ID, DEFAULT_SCHEDULING_LOOKAHEAD, LEGACY_MIN_BACKING_VOTES, + LOWEST_PUBLIC_ID, MAX_CODE_SIZE, MAX_HEAD_DATA_SIZE, MAX_POV_SIZE, MIN_CODE_SIZE, ON_DEMAND_DEFAULT_QUEUE_MAX_SIZE, ON_DEMAND_MAX_QUEUE_MAX_SIZE, PARACHAINS_INHERENT_IDENTIFIER, PARACHAIN_KEY_TYPE_ID, }; diff --git a/polkadot/primitives/src/runtime_api.rs b/polkadot/primitives/src/runtime_api.rs index df1dfbac4001383eeacd3fdc84084960d9e2c465..e0516a2f77e423345776df303171b2df7c385f89 100644 --- a/polkadot/primitives/src/runtime_api.rs +++ b/polkadot/primitives/src/runtime_api.rs @@ -303,5 +303,10 @@ sp_api::decl_runtime_apis! { /// block. #[api_version(12)] fn backing_constraints(para_id: ppp::Id) -> Option<Constraints>; + + /***** Added in v12 *****/ + /// Retrieve the scheduling lookahead + #[api_version(12)] + fn scheduling_lookahead() -> u32; } } diff --git a/polkadot/primitives/src/v8/mod.rs b/polkadot/primitives/src/v8/mod.rs index 7fc4c5b5c3f1d4a21b3addd50d396c50e95bd77d..93bb5ef23667288eb8a4a79e8589a39f32c742fc 100644 --- a/polkadot/primitives/src/v8/mod.rs +++ b/polkadot/primitives/src/v8/mod.rs @@ -444,6 +444,9 @@ pub const ON_DEMAND_MAX_QUEUE_MAX_SIZE: u32 = 1_000_000_000; /// prior to v9 configuration migration. pub const LEGACY_MIN_BACKING_VOTES: u32 = 2; +/// Default value for `SchedulerParams.lookahead` +pub const DEFAULT_SCHEDULING_LOOKAHEAD: u32 = 3; + // The public key of a keypair used by a validator for determining assignments /// to approve included parachain candidates. mod assignment_app { @@ -2132,11 +2135,13 @@ impl<BlockNumber: Default + From<u32>> Default for SchedulerParams<BlockNumber> } #[cfg(test)] +/// Test helpers pub mod tests { use super::*; use bitvec::bitvec; use sp_core::sr25519; + /// Create a dummy committed candidate receipt pub fn dummy_committed_candidate_receipt() -> CommittedCandidateReceipt { let zeros = Hash::zero(); diff --git a/polkadot/primitives/test-helpers/src/lib.rs b/polkadot/primitives/test-helpers/src/lib.rs index 1717dd5b0edae7ee3c2d67c0da8a04403e79972a..b7cdfa83e10d32c3d0beaf5975b9af61c1adccc8 100644 --- a/polkadot/primitives/test-helpers/src/lib.rs +++ b/polkadot/primitives/test-helpers/src/lib.rs @@ -381,22 +381,30 @@ pub struct TestCandidateBuilder { pub pov_hash: Hash, pub relay_parent: Hash, pub commitments_hash: Hash, + pub core_index: CoreIndex, } impl std::default::Default for TestCandidateBuilder { fn default() -> Self { let zeros = Hash::zero(); - Self { para_id: 0.into(), pov_hash: zeros, relay_parent: zeros, commitments_hash: zeros } + Self { + para_id: 0.into(), + pov_hash: zeros, + relay_parent: zeros, + commitments_hash: zeros, + core_index: CoreIndex(0), + } } } impl TestCandidateBuilder { /// Build a `CandidateReceipt`. pub fn build(self) -> CandidateReceiptV2 { - let mut descriptor = dummy_candidate_descriptor(self.relay_parent); - descriptor.para_id = self.para_id; - descriptor.pov_hash = self.pov_hash; - CandidateReceipt { descriptor, commitments_hash: self.commitments_hash }.into() + let mut descriptor = dummy_candidate_descriptor_v2(self.relay_parent); + descriptor.set_para_id(self.para_id); + descriptor.set_pov_hash(self.pov_hash); + descriptor.set_core_index(self.core_index); + CandidateReceiptV2 { descriptor, commitments_hash: self.commitments_hash } } } diff --git a/polkadot/runtime/common/src/slots/mod.rs b/polkadot/runtime/common/src/slots/mod.rs index 131a75f3d743c981da13c8886618cc611efa2fff..1fbfe451dcbf7304b8e17de8ec590893ffa71533 100644 --- a/polkadot/runtime/common/src/slots/mod.rs +++ b/polkadot/runtime/common/src/slots/mod.rs @@ -149,7 +149,7 @@ pub mod pallet { if let Some((lease_period, first_block)) = Self::lease_period_index(n) { // If we're beginning a new lease period then handle that. if first_block { - return Self::manage_lease_period_start(lease_period) + return Self::manage_lease_period_start(lease_period); } } @@ -237,7 +237,7 @@ impl<T: Config> Pallet<T> { let mut parachains = Vec::new(); for (para, mut lease_periods) in Leases::<T>::iter() { if lease_periods.is_empty() { - continue + continue; } // ^^ should never be empty since we would have deleted the entry otherwise. @@ -381,7 +381,7 @@ impl<T: Config> Leaser<BlockNumberFor<T>> for Pallet<T> { // attempt. // // We bail, not giving any lease and leave it for governance to sort out. - return Err(LeaseError::AlreadyLeased) + return Err(LeaseError::AlreadyLeased); } } else if d.len() == i { // Doesn't exist. This is usual. @@ -488,7 +488,7 @@ impl<T: Config> Leaser<BlockNumberFor<T>> for Pallet<T> { for slot in offset..=offset + period_count { if let Some(Some(_)) = leases.get(slot) { // If there exists any lease period, we exit early and return true. - return true + return true; } } @@ -962,7 +962,7 @@ mod benchmarking { use polkadot_runtime_parachains::paras; use sp_runtime::traits::{Bounded, One}; - use frame_benchmarking::{account, benchmarks, whitelisted_caller, BenchmarkError}; + use frame_benchmarking::v2::*; use crate::slots::Pallet as Slots; @@ -998,10 +998,15 @@ mod benchmarking { (para, leaser) } - benchmarks! { - where_clause { where T: paras::Config } + #[benchmarks( + where T: paras::Config, + )] - force_lease { + mod benchmarks { + use super::*; + + #[benchmark] + fn force_lease() -> Result<(), BenchmarkError> { // If there is an offset, we need to be on that block to be able to do lease things. frame_system::Pallet::<T>::set_block_number(T::LeaseOffset::get() + One::one()); let para = ParaId::from(1337); @@ -1012,23 +1017,32 @@ mod benchmarking { let period_count = 3u32.into(); let origin = T::ForceOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; - }: _<T::RuntimeOrigin>(origin, para, leaser.clone(), amount, period_begin, period_count) - verify { - assert_last_event::<T>(Event::<T>::Leased { - para_id: para, - leaser, period_begin, - period_count, - extra_reserved: amount, - total_amount: amount, - }.into()); - } - // Worst case scenario, T on-demand parachains onboard, and C lease holding parachains offboard. - manage_lease_period_start { - // Assume reasonable maximum of 100 paras at any time - let c in 0 .. 100; - let t in 0 .. 100; + #[extrinsic_call] + _(origin as T::RuntimeOrigin, para, leaser.clone(), amount, period_begin, period_count); + + assert_last_event::<T>( + Event::<T>::Leased { + para_id: para, + leaser, + period_begin, + period_count, + extra_reserved: amount, + total_amount: amount, + } + .into(), + ); + Ok(()) + } + + // Worst case scenario, T on-demand parachains onboard, and C lease holding parachains + // offboard. Assume reasonable maximum of 100 paras at any time + #[benchmark] + fn manage_lease_period_start( + c: Linear<0, 100>, + t: Linear<0, 100>, + ) -> Result<(), BenchmarkError> { let period_begin = 1u32.into(); let period_count = 4u32.into(); @@ -1036,9 +1050,7 @@ mod benchmarking { frame_system::Pallet::<T>::set_block_number(T::LeaseOffset::get() + One::one()); // Make T parathreads (on-demand parachains) - let paras_info = (0..t).map(|i| { - register_a_parathread::<T>(i) - }).collect::<Vec<_>>(); + let paras_info = (0..t).map(|i| register_a_parathread::<T>(i)).collect::<Vec<_>>(); T::Registrar::execute_pending_transitions(); @@ -1053,43 +1065,48 @@ mod benchmarking { T::Registrar::execute_pending_transitions(); // C lease holding parachains are downgrading to on-demand parachains - for i in 200 .. 200 + c { - let (para, leaser) = register_a_parathread::<T>(i); + for i in 200..200 + c { + let (para, _) = register_a_parathread::<T>(i); T::Registrar::make_parachain(para)?; } T::Registrar::execute_pending_transitions(); - for i in 0 .. t { + for i in 0..t { assert!(T::Registrar::is_parathread(ParaId::from(i))); } - for i in 200 .. 200 + c { + for i in 200..200 + c { assert!(T::Registrar::is_parachain(ParaId::from(i))); } - }: { - Slots::<T>::manage_lease_period_start(period_begin); - } verify { + #[block] + { + let _ = Slots::<T>::manage_lease_period_start(period_begin); + } + // All paras should have switched. T::Registrar::execute_pending_transitions(); - for i in 0 .. t { + for i in 0..t { assert!(T::Registrar::is_parachain(ParaId::from(i))); } - for i in 200 .. 200 + c { + for i in 200..200 + c { assert!(T::Registrar::is_parathread(ParaId::from(i))); } + + Ok(()) } // Assume that at most 8 people have deposits for leases on a parachain. // This would cover at least 4 years of leases in the worst case scenario. - clear_all_leases { + #[benchmark] + fn clear_all_leases() -> Result<(), BenchmarkError> { let max_people = 8; let (para, _) = register_a_parathread::<T>(1); // If there is an offset, we need to be on that block to be able to do lease things. frame_system::Pallet::<T>::set_block_number(T::LeaseOffset::get() + One::one()); - for i in 0 .. max_people { + for i in 0..max_people { let leaser = account("lease_deposit", i, 0); let amount = T::Currency::minimum_balance(); T::Currency::make_free_balance_be(&leaser, BalanceOf::<T>::max_value()); @@ -1102,31 +1119,45 @@ mod benchmarking { Slots::<T>::force_lease(origin, para, leaser, amount, period_begin, period_count)?; } - for i in 0 .. max_people { + for i in 0..max_people { let leaser = account("lease_deposit", i, 0); assert_eq!(T::Currency::reserved_balance(&leaser), T::Currency::minimum_balance()); } let origin = T::ForceOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; - }: _<T::RuntimeOrigin>(origin, para) - verify { - for i in 0 .. max_people { + + #[extrinsic_call] + _(origin as T::RuntimeOrigin, para); + + for i in 0..max_people { let leaser = account("lease_deposit", i, 0); assert_eq!(T::Currency::reserved_balance(&leaser), 0u32.into()); } + + Ok(()) } - trigger_onboard { + #[benchmark] + fn trigger_onboard() -> Result<(), BenchmarkError> { // get a parachain into a bad state where they did not onboard let (para, _) = register_a_parathread::<T>(1); - Leases::<T>::insert(para, vec![Some((account::<T::AccountId>("lease_insert", 0, 0), BalanceOf::<T>::default()))]); + Leases::<T>::insert( + para, + vec![Some(( + account::<T::AccountId>("lease_insert", 0, 0), + BalanceOf::<T>::default(), + ))], + ); assert!(T::Registrar::is_parathread(para)); let caller = whitelisted_caller(); - }: _(RawOrigin::Signed(caller), para) - verify { + + #[extrinsic_call] + _(RawOrigin::Signed(caller), para); + T::Registrar::execute_pending_transitions(); assert!(T::Registrar::is_parachain(para)); + Ok(()) } impl_benchmark_test_suite!( diff --git a/polkadot/runtime/parachains/Cargo.toml b/polkadot/runtime/parachains/Cargo.toml index 7c00995d2291e7bc872da4c20f8b370f83b4347d..6c87f7773c235dcca7f591791e5295a84e2c26cf 100644 --- a/polkadot/runtime/parachains/Cargo.toml +++ b/polkadot/runtime/parachains/Cargo.toml @@ -47,7 +47,6 @@ pallet-mmr = { workspace = true, optional = true } pallet-session = { workspace = true } pallet-staking = { workspace = true } pallet-timestamp = { workspace = true } -pallet-vesting = { workspace = true } polkadot-primitives = { workspace = true } xcm = { workspace = true } @@ -96,7 +95,6 @@ std = [ "pallet-session/std", "pallet-staking/std", "pallet-timestamp/std", - "pallet-vesting/std", "polkadot-core-primitives/std", "polkadot-parachain-primitives/std", "polkadot-primitives/std", @@ -131,7 +129,6 @@ runtime-benchmarks = [ "pallet-mmr/runtime-benchmarks", "pallet-staking/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", - "pallet-vesting/runtime-benchmarks", "polkadot-parachain-primitives/runtime-benchmarks", "polkadot-primitives/runtime-benchmarks", "sp-application-crypto", @@ -156,7 +153,6 @@ try-runtime = [ "pallet-session/try-runtime", "pallet-staking/try-runtime", "pallet-timestamp/try-runtime", - "pallet-vesting/try-runtime", "sp-runtime/try-runtime", ] runtime-metrics = [ diff --git a/polkadot/runtime/parachains/src/paras_inherent/mod.rs b/polkadot/runtime/parachains/src/paras_inherent/mod.rs index 4c1394fd1347395371a581619d56a70df1bc9c73..b3057c25d8563cb1de61216e80b1373000312ee5 100644 --- a/polkadot/runtime/parachains/src/paras_inherent/mod.rs +++ b/polkadot/runtime/parachains/src/paras_inherent/mod.rs @@ -329,7 +329,7 @@ impl<T: Config> Pallet<T> { }) .collect(), parent_number, - config.async_backing_params.allowed_ancestry_len, + config.scheduler_params.lookahead, ); }); } diff --git a/polkadot/runtime/parachains/src/paras_inherent/weights.rs b/polkadot/runtime/parachains/src/paras_inherent/weights.rs index 81c926a90e0bf81e427fe6ecfbb71c4c4c62f3b2..31958cf4acfb340274aeebcfb4e4997581fe9f59 100644 --- a/polkadot/runtime/parachains/src/paras_inherent/weights.rs +++ b/polkadot/runtime/parachains/src/paras_inherent/weights.rs @@ -94,10 +94,13 @@ pub fn paras_inherent_total_weight<T: Config>( bitfields: &UncheckedSignedAvailabilityBitfields, disputes: &MultiDisputeStatementSet, ) -> Weight { - backed_candidates_weight::<T>(backed_candidates) + let weight = backed_candidates_weight::<T>(backed_candidates) .saturating_add(signed_bitfields_weight::<T>(bitfields)) .saturating_add(multi_dispute_statement_sets_weight::<T>(disputes)) - .saturating_add(enact_candidates_max_weight::<T>(bitfields)) + .saturating_add(enact_candidates_max_weight::<T>(bitfields)); + // Relay chain blocks pre-dispatch weight can be set to any high enough value + // but the proof size is irrelevant for the relay chain either way. + weight.set_proof_size(u64::MAX) } pub fn multi_dispute_statement_sets_weight<T: Config>( diff --git a/polkadot/runtime/parachains/src/runtime_api_impl/v11.rs b/polkadot/runtime/parachains/src/runtime_api_impl/v11.rs index 3f2cb5771098750e965d5efaef0899bdb47ae438..133d4ca1877d2ba1b2900e10e9d886fc5bbe95fa 100644 --- a/polkadot/runtime/parachains/src/runtime_api_impl/v11.rs +++ b/polkadot/runtime/parachains/src/runtime_api_impl/v11.rs @@ -420,12 +420,12 @@ pub(crate) fn backing_constraints<T: initializer::Config>( { shared::migration::v0::AllowedRelayParents::<T>::get().hypothetical_earliest_block_number( now, - config.async_backing_params.allowed_ancestry_len, + config.scheduler_params.lookahead.saturating_sub(1), ) } else { shared::AllowedRelayParents::<T>::get().hypothetical_earliest_block_number( now, - config.async_backing_params.allowed_ancestry_len, + config.scheduler_params.lookahead.saturating_sub(1), ) }; @@ -508,6 +508,7 @@ pub fn backing_state<T: initializer::Config>( } /// Implementation for `AsyncBackingParams` function from the runtime API +#[deprecated = "AsyncBackingParams are going to be removed and ignored by relay chain validators, in favour of dynamically computed values based on the claim queue assignments"] pub fn async_backing_params<T: configuration::Config>() -> AsyncBackingParams { configuration::ActiveConfig::<T>::get().async_backing_params } diff --git a/polkadot/runtime/parachains/src/runtime_api_impl/vstaging.rs b/polkadot/runtime/parachains/src/runtime_api_impl/vstaging.rs index 52a9a9e122889d6c0be793320553b4f1719296e6..5a77af0d79731e5d06d1c5b7e5bf9f02b7a3485d 100644 --- a/polkadot/runtime/parachains/src/runtime_api_impl/vstaging.rs +++ b/polkadot/runtime/parachains/src/runtime_api_impl/vstaging.rs @@ -45,3 +45,8 @@ pub fn backing_constraints<T: initializer::Config>( future_validation_code: constraints_v11.future_validation_code, }) } + +/// Implementation for `scheduling_lookahead` function from the runtime API +pub fn scheduling_lookahead<T: initializer::Config>() -> u32 { + configuration::ActiveConfig::<T>::get().scheduler_params.lookahead +} diff --git a/polkadot/runtime/parachains/src/shared.rs b/polkadot/runtime/parachains/src/shared.rs index 473c1aba7a066d198f7bcdad8ad920cf7cf955e8..94b69e4ae4b4a4b89aaa35b0b7a044281f4ab1e8 100644 --- a/polkadot/runtime/parachains/src/shared.rs +++ b/polkadot/runtime/parachains/src/shared.rs @@ -96,13 +96,10 @@ impl<Hash: PartialEq + Copy, BlockNumber: AtLeast32BitUnsigned + Copy> let claim_queue = transpose_claim_queue(claim_queue); - // + 1 for the most recent block, which is always allowed. - let buffer_size_limit = max_ancestry_len as usize + 1; - self.buffer.push_back(RelayParentInfo { relay_parent, state_root, claim_queue }); self.latest_number = number; - while self.buffer.len() > buffer_size_limit { + while self.buffer.len() > (max_ancestry_len as usize) { let _ = self.buffer.pop_front(); } @@ -295,7 +292,7 @@ impl<T: Config> Pallet<T> { max_ancestry_len: u32, ) { AllowedRelayParents::<T>::mutate(|tracker| { - tracker.update(relay_parent, state_root, claim_queue, number, max_ancestry_len) + tracker.update(relay_parent, state_root, claim_queue, number, max_ancestry_len + 1) }) } } diff --git a/polkadot/runtime/parachains/src/shared/tests.rs b/polkadot/runtime/parachains/src/shared/tests.rs index f7ea5148ce33417740f09b9e39b64f94b0a2c29b..a35945549e74261c37e4e28575a12e074f0c5a39 100644 --- a/polkadot/runtime/parachains/src/shared/tests.rs +++ b/polkadot/runtime/parachains/src/shared/tests.rs @@ -36,8 +36,8 @@ fn tracker_earliest_block_number() { // Push a single block into the tracker, suppose max capacity is 1. let max_ancestry_len = 0; - tracker.update(Hash::zero(), Hash::zero(), Default::default(), 0, max_ancestry_len); - assert_eq!(tracker.hypothetical_earliest_block_number(now, max_ancestry_len), now); + tracker.update(Hash::zero(), Hash::zero(), Default::default(), 0, max_ancestry_len + 1); + assert_eq!(tracker.hypothetical_earliest_block_number(now, max_ancestry_len as _), now); // Test a greater capacity. let max_ancestry_len = 4; @@ -48,14 +48,14 @@ fn tracker_earliest_block_number() { Hash::zero(), Default::default(), i, - max_ancestry_len, + max_ancestry_len + 1, ); - assert_eq!(tracker.hypothetical_earliest_block_number(i + 1, max_ancestry_len), 0); + assert_eq!(tracker.hypothetical_earliest_block_number(i + 1, max_ancestry_len as _), 0); } // Capacity exceeded. tracker.update(Hash::zero(), Hash::zero(), Default::default(), now, max_ancestry_len); - assert_eq!(tracker.hypothetical_earliest_block_number(now + 1, max_ancestry_len), 1); + assert_eq!(tracker.hypothetical_earliest_block_number(now + 1, max_ancestry_len as _), 1); } #[test] @@ -67,7 +67,7 @@ fn tracker_claim_queue_transpose() { claim_queue.insert(CoreIndex(1), vec![Id::from(0), Id::from(0), Id::from(100)].into()); claim_queue.insert(CoreIndex(2), vec![Id::from(1), Id::from(2), Id::from(100)].into()); - tracker.update(Hash::zero(), Hash::zero(), claim_queue, 1u32, 3u32); + tracker.update(Hash::zero(), Hash::zero(), claim_queue, 1u32, 4); let (info, _block_num) = tracker.acquire_info(Hash::zero(), None).unwrap(); assert_eq!( @@ -120,14 +120,20 @@ fn tracker_acquire_info() { ]; let (relay_parent, state_root) = blocks[0]; - tracker.update(relay_parent, state_root, Default::default(), 0, max_ancestry_len); + tracker.update(relay_parent, state_root, Default::default(), 0, max_ancestry_len + 1); assert_matches!( tracker.acquire_info(relay_parent, None), Some((s, b)) if s.state_root == state_root && b == 0 ); // Try to push a duplicate. Should be ignored. - tracker.update(relay_parent, Hash::repeat_byte(13), Default::default(), 0, max_ancestry_len); + tracker.update( + relay_parent, + Hash::repeat_byte(13), + Default::default(), + 0, + max_ancestry_len + 1, + ); assert_eq!(tracker.buffer.len(), 1); assert_matches!( tracker.acquire_info(relay_parent, None), @@ -135,9 +141,9 @@ fn tracker_acquire_info() { ); let (relay_parent, state_root) = blocks[1]; - tracker.update(relay_parent, state_root, Default::default(), 1u32, max_ancestry_len); + tracker.update(relay_parent, state_root, Default::default(), 1u32, max_ancestry_len + 1); let (relay_parent, state_root) = blocks[2]; - tracker.update(relay_parent, state_root, Default::default(), 2u32, max_ancestry_len); + tracker.update(relay_parent, state_root, Default::default(), 2u32, max_ancestry_len + 1); for (block_num, (rp, state_root)) in blocks.iter().enumerate().take(2) { assert_matches!( tracker.acquire_info(*rp, None), diff --git a/polkadot/runtime/rococo/Cargo.toml b/polkadot/runtime/rococo/Cargo.toml index e7f463566e3a6350a5c6c336e642f7c5738844af..67c7cacc296b9bb210bbca53284e2656852a6611 100644 --- a/polkadot/runtime/rococo/Cargo.toml +++ b/polkadot/runtime/rococo/Cargo.toml @@ -59,14 +59,12 @@ pallet-beefy = { workspace = true } pallet-beefy-mmr = { workspace = true } pallet-bounties = { workspace = true } pallet-child-bounties = { workspace = true } -pallet-collective = { workspace = true } pallet-conviction-voting = { workspace = true } pallet-democracy = { workspace = true } pallet-elections-phragmen = { workspace = true } pallet-grandpa = { workspace = true } pallet-identity = { workspace = true } pallet-indices = { workspace = true } -pallet-membership = { workspace = true } pallet-message-queue = { workspace = true } pallet-migrations = { workspace = true } pallet-mmr = { workspace = true } @@ -115,12 +113,10 @@ xcm-runtime-apis = { workspace = true } [dev-dependencies] remote-externalities = { workspace = true, default-features = true } -separator = { workspace = true } serde_json = { workspace = true, default-features = true } sp-keyring = { workspace = true, default-features = true } sp-tracing = { workspace = true } sp-trie = { workspace = true, default-features = true } -tiny-keccak = { features = ["keccak"], workspace = true } tokio = { features = ["macros"], workspace = true, default-features = true } [build-dependencies] @@ -151,14 +147,12 @@ std = [ "pallet-beefy/std", "pallet-bounties/std", "pallet-child-bounties/std", - "pallet-collective/std", "pallet-conviction-voting/std", "pallet-democracy/std", "pallet-elections-phragmen/std", "pallet-grandpa/std", "pallet-identity/std", "pallet-indices/std", - "pallet-membership/std", "pallet-message-queue/std", "pallet-migrations/std", "pallet-mmr/std", @@ -234,14 +228,12 @@ runtime-benchmarks = [ "pallet-beefy-mmr/runtime-benchmarks", "pallet-bounties/runtime-benchmarks", "pallet-child-bounties/runtime-benchmarks", - "pallet-collective/runtime-benchmarks", "pallet-conviction-voting/runtime-benchmarks", "pallet-democracy/runtime-benchmarks", "pallet-elections-phragmen/runtime-benchmarks", "pallet-grandpa/runtime-benchmarks", "pallet-identity/runtime-benchmarks", "pallet-indices/runtime-benchmarks", - "pallet-membership/runtime-benchmarks", "pallet-message-queue/runtime-benchmarks", "pallet-migrations/runtime-benchmarks", "pallet-mmr/runtime-benchmarks", @@ -294,14 +286,12 @@ try-runtime = [ "pallet-beefy/try-runtime", "pallet-bounties/try-runtime", "pallet-child-bounties/try-runtime", - "pallet-collective/try-runtime", "pallet-conviction-voting/try-runtime", "pallet-democracy/try-runtime", "pallet-elections-phragmen/try-runtime", "pallet-grandpa/try-runtime", "pallet-identity/try-runtime", "pallet-indices/try-runtime", - "pallet-membership/try-runtime", "pallet-message-queue/try-runtime", "pallet-migrations/try-runtime", "pallet-mmr/try-runtime", diff --git a/polkadot/runtime/rococo/src/genesis_config_presets.rs b/polkadot/runtime/rococo/src/genesis_config_presets.rs index 83bd1fbbc8faf42e4b9c0579e937628293d7a17b..80be075bea2566d95de7ee7e97f90bbb788ab9d7 100644 --- a/polkadot/runtime/rococo/src/genesis_config_presets.rs +++ b/polkadot/runtime/rococo/src/genesis_config_presets.rs @@ -125,8 +125,8 @@ fn default_parachains_host_configuration( zeroth_delay_tranche_width: 0, minimum_validation_upgrade_delay: 5, async_backing_params: AsyncBackingParams { - max_candidate_depth: 3, - allowed_ancestry_len: 2, + max_candidate_depth: 0, + allowed_ancestry_len: 0, }, node_features: bitvec::vec::BitVec::from_element( 1u8 << (FeatureIndex::ElasticScalingMVP as usize) | diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index f165091beda4790b55c8ed57686bf076e754f675..f7716e8b7d9cfa92d19d1f738649b358e72e7b20 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -79,7 +79,7 @@ use polkadot_runtime_parachains::{ origin as parachains_origin, paras as parachains_paras, paras_inherent as parachains_paras_inherent, runtime_api_impl::{ - v11 as parachains_runtime_api_impl, vstaging as parachains_runtime_vstaging_api_impl, + v11 as parachains_runtime_api_impl, vstaging as parachains_staging_runtime_api_impl, }, scheduler as parachains_scheduler, session_info as parachains_session_info, shared as parachains_shared, @@ -2129,6 +2129,7 @@ sp_api::impl_runtime_apis! { } fn async_backing_params() -> polkadot_primitives::AsyncBackingParams { + #[allow(deprecated)] parachains_runtime_api_impl::async_backing_params::<Runtime>() } @@ -2153,7 +2154,11 @@ sp_api::impl_runtime_apis! { } fn backing_constraints(para_id: ParaId) -> Option<Constraints> { - parachains_runtime_vstaging_api_impl::backing_constraints::<Runtime>(para_id) + parachains_staging_runtime_api_impl::backing_constraints::<Runtime>(para_id) + } + + fn scheduling_lookahead() -> u32 { + parachains_staging_runtime_api_impl::scheduling_lookahead::<Runtime>() } } diff --git a/polkadot/runtime/rococo/src/weights/pallet_migrations.rs b/polkadot/runtime/rococo/src/weights/pallet_migrations.rs index 4fa07a23bb8ab4376d64cb4aa425f1cc515bb4fa..a0623a9c951331a54c036b9a3b2e1fee42df8d70 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_migrations.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_migrations.rs @@ -14,7 +14,31 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see <http://www.gnu.org/licenses/>. -// Need to rerun! +//! Autogenerated weights for `pallet_migrations` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2025-01-27, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `17938671047b`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: 1024 + +// Executed Command: +// frame-omni-bencher +// v1 +// benchmark +// pallet +// --extrinsic=* +// --runtime=target/production/wbuild/rococo-runtime/rococo_runtime.wasm +// --pallet=pallet_migrations +// --header=/__w/polkadot-sdk/polkadot-sdk/polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights +// --wasm-execution=compiled +// --steps=50 +// --repeat=20 +// --heap-pages=4096 +// --no-storage-info +// --no-min-squares +// --no-median-slopes #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -33,22 +57,24 @@ impl<T: frame_system::Config> pallet_migrations::WeightInfo for WeightInfo<T> { /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) fn onboard_new_mbms() -> Weight { // Proof Size summary in bytes: - // Measured: `276` + // Measured: `100` // Estimated: `67035` - // Minimum execution time: 7_762_000 picoseconds. - Weight::from_parts(8_100_000, 67035) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Minimum execution time: 8_300_000 picoseconds. + Weight::from_parts(8_664_000, 0) + .saturating_add(Weight::from_parts(0, 67035)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `MultiBlockMigrations::Cursor` (r:1 w:0) /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) fn progress_mbms_none() -> Weight { // Proof Size summary in bytes: - // Measured: `142` + // Measured: `4` // Estimated: `67035` - // Minimum execution time: 2_077_000 picoseconds. - Weight::from_parts(2_138_000, 67035) - .saturating_add(T::DbWeight::get().reads(1_u64)) + // Minimum execution time: 2_017_000 picoseconds. + Weight::from_parts(2_129_000, 0) + .saturating_add(Weight::from_parts(0, 67035)) + .saturating_add(T::DbWeight::get().reads(1)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -56,12 +82,13 @@ impl<T: frame_system::Config> pallet_migrations::WeightInfo for WeightInfo<T> { /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) fn exec_migration_completed() -> Weight { // Proof Size summary in bytes: - // Measured: `134` - // Estimated: `3599` - // Minimum execution time: 5_868_000 picoseconds. - Weight::from_parts(6_143_000, 3599) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Measured: `96` + // Estimated: `3561` + // Minimum execution time: 6_414_000 picoseconds. + Weight::from_parts(6_644_000, 0) + .saturating_add(Weight::from_parts(0, 3561)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -69,11 +96,12 @@ impl<T: frame_system::Config> pallet_migrations::WeightInfo for WeightInfo<T> { /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) fn exec_migration_skipped_historic() -> Weight { // Proof Size summary in bytes: - // Measured: `330` - // Estimated: `3795` - // Minimum execution time: 10_283_000 picoseconds. - Weight::from_parts(10_964_000, 3795) - .saturating_add(T::DbWeight::get().reads(2_u64)) + // Measured: `154` + // Estimated: `3731` + // Minimum execution time: 11_600_000 picoseconds. + Weight::from_parts(12_137_000, 0) + .saturating_add(Weight::from_parts(0, 3731)) + .saturating_add(T::DbWeight::get().reads(2)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -81,11 +109,12 @@ impl<T: frame_system::Config> pallet_migrations::WeightInfo for WeightInfo<T> { /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) fn exec_migration_advance() -> Weight { // Proof Size summary in bytes: - // Measured: `276` - // Estimated: `3741` - // Minimum execution time: 9_900_000 picoseconds. - Weight::from_parts(10_396_000, 3741) - .saturating_add(T::DbWeight::get().reads(2_u64)) + // Measured: `100` + // Estimated: `3731` + // Minimum execution time: 10_944_000 picoseconds. + Weight::from_parts(11_354_000, 0) + .saturating_add(Weight::from_parts(0, 3731)) + .saturating_add(T::DbWeight::get().reads(2)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -93,12 +122,13 @@ impl<T: frame_system::Config> pallet_migrations::WeightInfo for WeightInfo<T> { /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) fn exec_migration_complete() -> Weight { // Proof Size summary in bytes: - // Measured: `276` - // Estimated: `3741` - // Minimum execution time: 11_411_000 picoseconds. - Weight::from_parts(11_956_000, 3741) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Measured: `100` + // Estimated: `3731` + // Minimum execution time: 12_525_000 picoseconds. + Weight::from_parts(12_890_000, 0) + .saturating_add(Weight::from_parts(0, 3731)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -108,19 +138,21 @@ impl<T: frame_system::Config> pallet_migrations::WeightInfo for WeightInfo<T> { /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) fn exec_migration_fail() -> Weight { // Proof Size summary in bytes: - // Measured: `276` - // Estimated: `3741` - // Minimum execution time: 12_398_000 picoseconds. - Weight::from_parts(12_910_000, 3741) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Measured: `100` + // Estimated: `3731` + // Minimum execution time: 13_749_000 picoseconds. + Weight::from_parts(14_411_000, 0) + .saturating_add(Weight::from_parts(0, 3731)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } fn on_init_loop() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 166_000 picoseconds. - Weight::from_parts(193_000, 0) + // Minimum execution time: 174_000 picoseconds. + Weight::from_parts(232_000, 0) + .saturating_add(Weight::from_parts(0, 0)) } /// Storage: `MultiBlockMigrations::Cursor` (r:0 w:1) /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) @@ -128,9 +160,10 @@ impl<T: frame_system::Config> pallet_migrations::WeightInfo for WeightInfo<T> { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_686_000 picoseconds. - Weight::from_parts(2_859_000, 0) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Minimum execution time: 2_906_000 picoseconds. + Weight::from_parts(3_195_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `MultiBlockMigrations::Cursor` (r:0 w:1) /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) @@ -138,9 +171,10 @@ impl<T: frame_system::Config> pallet_migrations::WeightInfo for WeightInfo<T> { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_070_000 picoseconds. - Weight::from_parts(3_250_000, 0) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Minimum execution time: 3_313_000 picoseconds. + Weight::from_parts(3_469_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `MultiBlockMigrations::Cursor` (r:1 w:0) /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) @@ -148,26 +182,44 @@ impl<T: frame_system::Config> pallet_migrations::WeightInfo for WeightInfo<T> { /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) fn force_onboard_mbms() -> Weight { // Proof Size summary in bytes: - // Measured: `251` + // Measured: `76` // Estimated: `67035` - // Minimum execution time: 5_901_000 picoseconds. - Weight::from_parts(6_320_000, 67035) - .saturating_add(T::DbWeight::get().reads(2_u64)) + // Minimum execution time: 5_960_000 picoseconds. + Weight::from_parts(6_262_000, 0) + .saturating_add(Weight::from_parts(0, 67035)) + .saturating_add(T::DbWeight::get().reads(2)) } /// Storage: `MultiBlockMigrations::Historic` (r:256 w:256) /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 256]`. fn clear_historic(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1122 + n * (271 ±0)` + // Measured: `984 + n * (271 ±0)` // Estimated: `3834 + n * (2740 ±0)` - // Minimum execution time: 15_952_000 picoseconds. - Weight::from_parts(14_358_665, 3834) - // Standard Error: 3_358 - .saturating_add(Weight::from_parts(1_323_674, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(1_u64)) + // Minimum execution time: 24_007_000 picoseconds. + Weight::from_parts(19_756_256, 0) + .saturating_add(Weight::from_parts(0, 3834)) + // Standard Error: 6_508 + .saturating_add(Weight::from_parts(1_553_207, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) .saturating_add(Weight::from_parts(0, 2740).saturating_mul(n.into())) } -} \ No newline at end of file + /// Storage: `Skipped::Metadata` (r:0 w:0) + /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// The range of component `n` is `[0, 2048]`. + fn reset_pallet_migration(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1676 + n * (38 ±0)` + // Estimated: `754 + n * (39 ±0)` + // Minimum execution time: 2_019_000 picoseconds. + Weight::from_parts(6_578_665, 0) + .saturating_add(Weight::from_parts(0, 754)) + // Standard Error: 5_209 + .saturating_add(Weight::from_parts(894_607, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 39).saturating_mul(n.into())) + } +} diff --git a/polkadot/runtime/rococo/src/weights/pallet_multisig.rs b/polkadot/runtime/rococo/src/weights/pallet_multisig.rs index f1b81759ece6c4c360a4bfb61afafb76836d11b2..d63c82daacdef2cbc197d93fcb9762347308b6e6 100644 --- a/polkadot/runtime/rococo/src/weights/pallet_multisig.rs +++ b/polkadot/runtime/rococo/src/weights/pallet_multisig.rs @@ -17,27 +17,27 @@ //! Autogenerated weights for `pallet_multisig` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-02-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2025-01-23, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-bn-ce5rx-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `e20fc9f125eb`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("rococo-dev")`, DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot +// target/production/polkadot // benchmark // pallet +// --extrinsic=* // --chain=rococo-dev +// --pallet=pallet_multisig +// --header=/__w/polkadot-sdk/polkadot-sdk/polkadot/file_header.txt +// --output=./polkadot/runtime/rococo/src/weights +// --wasm-execution=compiled // --steps=50 // --repeat=20 +// --heap-pages=4096 // --no-storage-info -// --no-median-slopes // --no-min-squares -// --pallet=pallet_multisig -// --extrinsic=* -// --execution=wasm -// --wasm-execution=compiled -// --header=./polkadot/file_header.txt -// --output=./polkadot/runtime/rococo/src/weights/ +// --no-median-slopes #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -55,11 +55,11 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 12_023_000 picoseconds. - Weight::from_parts(12_643_116, 0) + // Minimum execution time: 15_707_000 picoseconds. + Weight::from_parts(17_199_004, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 3 - .saturating_add(Weight::from_parts(582, 0).saturating_mul(z.into())) + // Standard Error: 15 + .saturating_add(Weight::from_parts(639, 0).saturating_mul(z.into())) } /// Storage: `Multisig::Multisigs` (r:1 w:1) /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) @@ -69,13 +69,13 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { // Proof Size summary in bytes: // Measured: `229 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 39_339_000 picoseconds. - Weight::from_parts(27_243_033, 0) + // Minimum execution time: 47_949_000 picoseconds. + Weight::from_parts(33_500_294, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 1_319 - .saturating_add(Weight::from_parts(142_212, 0).saturating_mul(s.into())) - // Standard Error: 12 - .saturating_add(Weight::from_parts(1_592, 0).saturating_mul(z.into())) + // Standard Error: 1_775 + .saturating_add(Weight::from_parts(159_011, 0).saturating_mul(s.into())) + // Standard Error: 17 + .saturating_add(Weight::from_parts(2_213, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -87,13 +87,13 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { // Proof Size summary in bytes: // Measured: `248` // Estimated: `6811` - // Minimum execution time: 27_647_000 picoseconds. - Weight::from_parts(15_828_725, 0) + // Minimum execution time: 31_197_000 picoseconds. + Weight::from_parts(19_488_352, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 908 - .saturating_add(Weight::from_parts(130_880, 0).saturating_mul(s.into())) - // Standard Error: 8 - .saturating_add(Weight::from_parts(1_532, 0).saturating_mul(z.into())) + // Standard Error: 1_332 + .saturating_add(Weight::from_parts(138_347, 0).saturating_mul(s.into())) + // Standard Error: 13 + .saturating_add(Weight::from_parts(2_122, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -107,28 +107,29 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { // Proof Size summary in bytes: // Measured: `354 + s * (33 ±0)` // Estimated: `6811` - // Minimum execution time: 46_971_000 picoseconds. - Weight::from_parts(32_150_393, 0) + // Minimum execution time: 54_297_000 picoseconds. + Weight::from_parts(33_256_178, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 1_129 - .saturating_add(Weight::from_parts(154_796, 0).saturating_mul(s.into())) - // Standard Error: 11 - .saturating_add(Weight::from_parts(1_603, 0).saturating_mul(z.into())) + // Standard Error: 3_088 + .saturating_add(Weight::from_parts(256_364, 0).saturating_mul(s.into())) + // Standard Error: 30 + .saturating_add(Weight::from_parts(2_488, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } /// Storage: `Multisig::Multisigs` (r:1 w:1) /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. + /// The range of component `z` is `[0, 10000]`. fn approve_as_multi_create(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `229 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 24_947_000 picoseconds. - Weight::from_parts(26_497_183, 0) + // Minimum execution time: 31_246_000 picoseconds. + Weight::from_parts(32_245_711, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 1_615 - .saturating_add(Weight::from_parts(147_071, 0).saturating_mul(s.into())) + // Standard Error: 1_704 + .saturating_add(Weight::from_parts(156_235, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -139,11 +140,11 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { // Proof Size summary in bytes: // Measured: `248` // Estimated: `6811` - // Minimum execution time: 13_897_000 picoseconds. - Weight::from_parts(14_828_339, 0) + // Minimum execution time: 17_353_000 picoseconds. + Weight::from_parts(17_418_506, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 1_136 - .saturating_add(Weight::from_parts(133_925, 0).saturating_mul(s.into())) + // Standard Error: 1_126 + .saturating_add(Weight::from_parts(136_788, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -154,11 +155,11 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { // Proof Size summary in bytes: // Measured: `420 + s * (1 ±0)` // Estimated: `6811` - // Minimum execution time: 28_984_000 picoseconds. - Weight::from_parts(29_853_232, 0) + // Minimum execution time: 32_603_000 picoseconds. + Weight::from_parts(33_456_399, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 650 - .saturating_add(Weight::from_parts(113_440, 0).saturating_mul(s.into())) + // Standard Error: 1_239 + .saturating_add(Weight::from_parts(146_249, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/polkadot/runtime/test-runtime/Cargo.toml b/polkadot/runtime/test-runtime/Cargo.toml index f35bb53ac904970671f9fc67bab22e049511b973..cd5507decd5d1a81085d9e84705e4942d04621ba 100644 --- a/polkadot/runtime/test-runtime/Cargo.toml +++ b/polkadot/runtime/test-runtime/Cargo.toml @@ -68,7 +68,6 @@ hex-literal = { workspace = true, default-features = true } serde_json = { workspace = true, default-features = true } sp-keyring = { workspace = true, default-features = true } sp-trie = { workspace = true, default-features = true } -tiny-keccak = { features = ["keccak"], workspace = true } [build-dependencies] substrate-wasm-builder = { workspace = true, default-features = true } diff --git a/polkadot/runtime/test-runtime/src/lib.rs b/polkadot/runtime/test-runtime/src/lib.rs index 4126193388caef427992db4cd3e0c4964f682feb..1a19b637b798afbd03ac2cae5694407fdf05edb2 100644 --- a/polkadot/runtime/test-runtime/src/lib.rs +++ b/polkadot/runtime/test-runtime/src/lib.rs @@ -32,12 +32,14 @@ use pallet_transaction_payment::FungibleAdapter; use polkadot_runtime_parachains::{ assigner_coretime as parachains_assigner_coretime, configuration as parachains_configuration, - configuration::ActiveConfigHrmpChannelSizeAndCapacityRatio, coretime, - disputes as parachains_disputes, disputes::slashing as parachains_slashing, + configuration::ActiveConfigHrmpChannelSizeAndCapacityRatio, + coretime, disputes as parachains_disputes, + disputes::slashing as parachains_slashing, dmp as parachains_dmp, hrmp as parachains_hrmp, inclusion as parachains_inclusion, initializer as parachains_initializer, on_demand as parachains_on_demand, origin as parachains_origin, paras as parachains_paras, - paras_inherent as parachains_paras_inherent, runtime_api_impl::v11 as runtime_impl, + paras_inherent as parachains_paras_inherent, + runtime_api_impl::{v11 as runtime_impl, vstaging as staging_runtime_impl}, scheduler as parachains_scheduler, session_info as parachains_session_info, shared as parachains_shared, }; @@ -61,8 +63,8 @@ use pallet_transaction_payment::{FeeDetails, RuntimeDispatchInfo}; use polkadot_primitives::{ slashing, vstaging::{ - CandidateEvent, CommittedCandidateReceiptV2 as CommittedCandidateReceipt, CoreState, - ScrapedOnChainVotes, + async_backing::Constraints, CandidateEvent, + CommittedCandidateReceiptV2 as CommittedCandidateReceipt, CoreState, ScrapedOnChainVotes, }, AccountId, AccountIndex, Balance, BlockNumber, CandidateHash, CoreIndex, DisputeState, ExecutorParams, GroupRotationInfo, Hash as HashT, Id as ParaId, InboundDownwardMessage, @@ -932,7 +934,7 @@ sp_api::impl_runtime_apis! { } } - #[api_version(11)] + #[api_version(12)] impl polkadot_primitives::runtime_api::ParachainHost<Block> for Runtime { fn validators() -> Vec<ValidatorId> { runtime_impl::validators::<Runtime>() @@ -1072,6 +1074,7 @@ sp_api::impl_runtime_apis! { } fn async_backing_params() -> polkadot_primitives::AsyncBackingParams { + #[allow(deprecated)] runtime_impl::async_backing_params::<Runtime>() } @@ -1094,6 +1097,14 @@ sp_api::impl_runtime_apis! { fn candidates_pending_availability(para_id: ParaId) -> Vec<CommittedCandidateReceipt<Hash>> { runtime_impl::candidates_pending_availability::<Runtime>(para_id) } + + fn backing_constraints(para_id: ParaId) -> Option<Constraints> { + staging_runtime_impl::backing_constraints::<Runtime>(para_id) + } + + fn scheduling_lookahead() -> u32 { + staging_runtime_impl::scheduling_lookahead::<Runtime>() + } } impl sp_consensus_beefy::BeefyApi<Block, BeefyId> for Runtime { diff --git a/polkadot/runtime/westend/Cargo.toml b/polkadot/runtime/westend/Cargo.toml index e945e64e7fc071db211fbe3ca5ac80bccfe33426..3317484419a9a2472da1b28f6dcf9ce1d04e0d45 100644 --- a/polkadot/runtime/westend/Cargo.toml +++ b/polkadot/runtime/westend/Cargo.toml @@ -60,10 +60,8 @@ pallet-bags-list = { workspace = true } pallet-balances = { workspace = true } pallet-beefy = { workspace = true } pallet-beefy-mmr = { workspace = true } -pallet-collective = { workspace = true } pallet-conviction-voting = { workspace = true } pallet-delegated-staking = { workspace = true } -pallet-democracy = { workspace = true } pallet-election-provider-multi-phase = { workspace = true } pallet-elections-phragmen = { workspace = true } pallet-fast-unstake = { workspace = true } @@ -159,10 +157,8 @@ std = [ "pallet-balances/std", "pallet-beefy-mmr/std", "pallet-beefy/std", - "pallet-collective/std", "pallet-conviction-voting/std", "pallet-delegated-staking/std", - "pallet-democracy/std", "pallet-election-provider-multi-phase/std", "pallet-election-provider-support-benchmarking?/std", "pallet-elections-phragmen/std", @@ -250,10 +246,8 @@ runtime-benchmarks = [ "pallet-bags-list/runtime-benchmarks", "pallet-balances/runtime-benchmarks", "pallet-beefy-mmr/runtime-benchmarks", - "pallet-collective/runtime-benchmarks", "pallet-conviction-voting/runtime-benchmarks", "pallet-delegated-staking/runtime-benchmarks", - "pallet-democracy/runtime-benchmarks", "pallet-election-provider-multi-phase/runtime-benchmarks", "pallet-election-provider-support-benchmarking/runtime-benchmarks", "pallet-elections-phragmen/runtime-benchmarks", @@ -315,10 +309,8 @@ try-runtime = [ "pallet-balances/try-runtime", "pallet-beefy-mmr/try-runtime", "pallet-beefy/try-runtime", - "pallet-collective/try-runtime", "pallet-conviction-voting/try-runtime", "pallet-delegated-staking/try-runtime", - "pallet-democracy/try-runtime", "pallet-election-provider-multi-phase/try-runtime", "pallet-elections-phragmen/try-runtime", "pallet-fast-unstake/try-runtime", diff --git a/polkadot/runtime/westend/src/genesis_config_presets.rs b/polkadot/runtime/westend/src/genesis_config_presets.rs index 729df20b3c65e9cd45ac1d5a46ba25251fe9ad1c..76c0ce015c0d8a8fb3106f06cb570cbdf4bd8608 100644 --- a/polkadot/runtime/westend/src/genesis_config_presets.rs +++ b/polkadot/runtime/westend/src/genesis_config_presets.rs @@ -128,8 +128,8 @@ fn default_parachains_host_configuration( zeroth_delay_tranche_width: 0, minimum_validation_upgrade_delay: 5, async_backing_params: AsyncBackingParams { - max_candidate_depth: 3, - allowed_ancestry_len: 2, + max_candidate_depth: 0, + allowed_ancestry_len: 0, }, node_features: bitvec::vec::BitVec::from_element( 1u8 << (FeatureIndex::ElasticScalingMVP as usize) | diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index 935b62c23388ee1c9dd47ccad4e70e488e074b53..51eede7c7342ee1976c0c12cb69d9d395602cd65 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -85,7 +85,7 @@ use polkadot_runtime_parachains::{ origin as parachains_origin, paras as parachains_paras, paras_inherent as parachains_paras_inherent, reward_points as parachains_reward_points, runtime_api_impl::{ - v11 as parachains_runtime_api_impl, vstaging as parachains_runtime_vstaging_api_impl, + v11 as parachains_runtime_api_impl, vstaging as parachains_staging_runtime_api_impl, }, scheduler as parachains_scheduler, session_info as parachains_session_info, shared as parachains_shared, @@ -1613,7 +1613,8 @@ mod runtime { RuntimeHoldReason, RuntimeSlashReason, RuntimeLockId, - RuntimeTask + RuntimeTask, + RuntimeViewFunction )] pub struct Runtime; @@ -1975,6 +1976,12 @@ sp_api::impl_runtime_apis! { } } + impl frame_support::view_functions::runtime_api::RuntimeViewFunction<Block> for Runtime { + fn execute_view_function(id: frame_support::view_functions::ViewFunctionId, input: Vec<u8>) -> Result<Vec<u8>, frame_support::view_functions::ViewFunctionDispatchError> { + Runtime::execute_view_function(id, input) + } + } + impl sp_block_builder::BlockBuilder<Block> for Runtime { fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult { Executive::apply_extrinsic(extrinsic) @@ -2155,6 +2162,7 @@ sp_api::impl_runtime_apis! { } fn async_backing_params() -> polkadot_primitives::AsyncBackingParams { + #[allow(deprecated)] parachains_runtime_api_impl::async_backing_params::<Runtime>() } @@ -2179,7 +2187,11 @@ sp_api::impl_runtime_apis! { } fn backing_constraints(para_id: ParaId) -> Option<Constraints> { - parachains_runtime_vstaging_api_impl::backing_constraints::<Runtime>(para_id) + parachains_staging_runtime_api_impl::backing_constraints::<Runtime>(para_id) + } + + fn scheduling_lookahead() -> u32 { + parachains_staging_runtime_api_impl::scheduling_lookahead::<Runtime>() } } diff --git a/polkadot/runtime/westend/src/weights/pallet_migrations.rs b/polkadot/runtime/westend/src/weights/pallet_migrations.rs index 4fa07a23bb8ab4376d64cb4aa425f1cc515bb4fa..f5d4f079ca6d3b509a899ca11ddd041ca7b644fc 100644 --- a/polkadot/runtime/westend/src/weights/pallet_migrations.rs +++ b/polkadot/runtime/westend/src/weights/pallet_migrations.rs @@ -14,7 +14,31 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see <http://www.gnu.org/licenses/>. -// Need to rerun! +//! Autogenerated weights for `pallet_migrations` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2025-01-27, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `17938671047b`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: 1024 + +// Executed Command: +// frame-omni-bencher +// v1 +// benchmark +// pallet +// --extrinsic=* +// --runtime=target/production/wbuild/westend-runtime/westend_runtime.wasm +// --pallet=pallet_migrations +// --header=/__w/polkadot-sdk/polkadot-sdk/polkadot/file_header.txt +// --output=./polkadot/runtime/westend/src/weights +// --wasm-execution=compiled +// --steps=50 +// --repeat=20 +// --heap-pages=4096 +// --no-storage-info +// --no-min-squares +// --no-median-slopes #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -33,22 +57,24 @@ impl<T: frame_system::Config> pallet_migrations::WeightInfo for WeightInfo<T> { /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) fn onboard_new_mbms() -> Weight { // Proof Size summary in bytes: - // Measured: `276` + // Measured: `133` // Estimated: `67035` - // Minimum execution time: 7_762_000 picoseconds. - Weight::from_parts(8_100_000, 67035) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Minimum execution time: 8_228_000 picoseconds. + Weight::from_parts(8_589_000, 0) + .saturating_add(Weight::from_parts(0, 67035)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `MultiBlockMigrations::Cursor` (r:1 w:0) /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) fn progress_mbms_none() -> Weight { // Proof Size summary in bytes: - // Measured: `142` + // Measured: `4` // Estimated: `67035` - // Minimum execution time: 2_077_000 picoseconds. - Weight::from_parts(2_138_000, 67035) - .saturating_add(T::DbWeight::get().reads(1_u64)) + // Minimum execution time: 1_980_000 picoseconds. + Weight::from_parts(2_175_000, 0) + .saturating_add(Weight::from_parts(0, 67035)) + .saturating_add(T::DbWeight::get().reads(1)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -56,12 +82,13 @@ impl<T: frame_system::Config> pallet_migrations::WeightInfo for WeightInfo<T> { /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) fn exec_migration_completed() -> Weight { // Proof Size summary in bytes: - // Measured: `134` - // Estimated: `3599` - // Minimum execution time: 5_868_000 picoseconds. - Weight::from_parts(6_143_000, 3599) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Measured: `129` + // Estimated: `3594` + // Minimum execution time: 6_390_000 picoseconds. + Weight::from_parts(6_711_000, 0) + .saturating_add(Weight::from_parts(0, 3594)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -69,11 +96,12 @@ impl<T: frame_system::Config> pallet_migrations::WeightInfo for WeightInfo<T> { /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) fn exec_migration_skipped_historic() -> Weight { // Proof Size summary in bytes: - // Measured: `330` - // Estimated: `3795` - // Minimum execution time: 10_283_000 picoseconds. - Weight::from_parts(10_964_000, 3795) - .saturating_add(T::DbWeight::get().reads(2_u64)) + // Measured: `187` + // Estimated: `3731` + // Minimum execution time: 14_970_000 picoseconds. + Weight::from_parts(16_023_000, 0) + .saturating_add(Weight::from_parts(0, 3731)) + .saturating_add(T::DbWeight::get().reads(2)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -81,11 +109,12 @@ impl<T: frame_system::Config> pallet_migrations::WeightInfo for WeightInfo<T> { /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) fn exec_migration_advance() -> Weight { // Proof Size summary in bytes: - // Measured: `276` - // Estimated: `3741` - // Minimum execution time: 9_900_000 picoseconds. - Weight::from_parts(10_396_000, 3741) - .saturating_add(T::DbWeight::get().reads(2_u64)) + // Measured: `133` + // Estimated: `3731` + // Minimum execution time: 10_908_000 picoseconds. + Weight::from_parts(11_291_000, 0) + .saturating_add(Weight::from_parts(0, 3731)) + .saturating_add(T::DbWeight::get().reads(2)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -93,12 +122,13 @@ impl<T: frame_system::Config> pallet_migrations::WeightInfo for WeightInfo<T> { /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) fn exec_migration_complete() -> Weight { // Proof Size summary in bytes: - // Measured: `276` - // Estimated: `3741` - // Minimum execution time: 11_411_000 picoseconds. - Weight::from_parts(11_956_000, 3741) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Measured: `133` + // Estimated: `3731` + // Minimum execution time: 12_433_000 picoseconds. + Weight::from_parts(12_862_000, 0) + .saturating_add(Weight::from_parts(0, 3731)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -108,19 +138,21 @@ impl<T: frame_system::Config> pallet_migrations::WeightInfo for WeightInfo<T> { /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) fn exec_migration_fail() -> Weight { // Proof Size summary in bytes: - // Measured: `276` - // Estimated: `3741` - // Minimum execution time: 12_398_000 picoseconds. - Weight::from_parts(12_910_000, 3741) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Measured: `133` + // Estimated: `3731` + // Minimum execution time: 13_407_000 picoseconds. + Weight::from_parts(13_901_000, 0) + .saturating_add(Weight::from_parts(0, 3731)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) } fn on_init_loop() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 166_000 picoseconds. - Weight::from_parts(193_000, 0) + // Minimum execution time: 162_000 picoseconds. + Weight::from_parts(207_000, 0) + .saturating_add(Weight::from_parts(0, 0)) } /// Storage: `MultiBlockMigrations::Cursor` (r:0 w:1) /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) @@ -128,9 +160,10 @@ impl<T: frame_system::Config> pallet_migrations::WeightInfo for WeightInfo<T> { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_686_000 picoseconds. - Weight::from_parts(2_859_000, 0) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Minimum execution time: 2_696_000 picoseconds. + Weight::from_parts(2_867_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `MultiBlockMigrations::Cursor` (r:0 w:1) /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) @@ -138,9 +171,10 @@ impl<T: frame_system::Config> pallet_migrations::WeightInfo for WeightInfo<T> { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_070_000 picoseconds. - Weight::from_parts(3_250_000, 0) - .saturating_add(T::DbWeight::get().writes(1_u64)) + // Minimum execution time: 3_232_000 picoseconds. + Weight::from_parts(3_436_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `MultiBlockMigrations::Cursor` (r:1 w:0) /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) @@ -148,26 +182,44 @@ impl<T: frame_system::Config> pallet_migrations::WeightInfo for WeightInfo<T> { /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) fn force_onboard_mbms() -> Weight { // Proof Size summary in bytes: - // Measured: `251` + // Measured: `109` // Estimated: `67035` - // Minimum execution time: 5_901_000 picoseconds. - Weight::from_parts(6_320_000, 67035) - .saturating_add(T::DbWeight::get().reads(2_u64)) + // Minimum execution time: 5_849_000 picoseconds. + Weight::from_parts(6_156_000, 0) + .saturating_add(Weight::from_parts(0, 67035)) + .saturating_add(T::DbWeight::get().reads(2)) } /// Storage: `MultiBlockMigrations::Historic` (r:256 w:256) /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) /// The range of component `n` is `[0, 256]`. fn clear_historic(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1122 + n * (271 ±0)` + // Measured: `984 + n * (271 ±0)` // Estimated: `3834 + n * (2740 ±0)` - // Minimum execution time: 15_952_000 picoseconds. - Weight::from_parts(14_358_665, 3834) - // Standard Error: 3_358 - .saturating_add(Weight::from_parts(1_323_674, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(1_u64)) + // Minimum execution time: 20_906_000 picoseconds. + Weight::from_parts(15_361_535, 0) + .saturating_add(Weight::from_parts(0, 3834)) + // Standard Error: 7_911 + .saturating_add(Weight::from_parts(1_518_172, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) .saturating_add(Weight::from_parts(0, 2740).saturating_mul(n.into())) } -} \ No newline at end of file + /// Storage: `Skipped::Metadata` (r:0 w:0) + /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// The range of component `n` is `[0, 2048]`. + fn reset_pallet_migration(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1676 + n * (38 ±0)` + // Estimated: `754 + n * (39 ±0)` + // Minimum execution time: 1_913_000 picoseconds. + Weight::from_parts(1_986_000, 0) + .saturating_add(Weight::from_parts(0, 754)) + // Standard Error: 2_511 + .saturating_add(Weight::from_parts(919_965, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 39).saturating_mul(n.into())) + } +} diff --git a/polkadot/runtime/westend/src/weights/pallet_multisig.rs b/polkadot/runtime/westend/src/weights/pallet_multisig.rs index 616aea9c8e73f0bf078de9d5e4cb55d8565b40b9..83521f3d1927b81b37371fafe21bc6fdcfbfc397 100644 --- a/polkadot/runtime/westend/src/weights/pallet_multisig.rs +++ b/polkadot/runtime/westend/src/weights/pallet_multisig.rs @@ -16,28 +16,28 @@ //! Autogenerated weights for `pallet_multisig` //! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-06-14, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2025-01-23, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner--ss9ysm1-project-163-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("westend-dev"), DB CACHE: 1024 +//! HOSTNAME: `e20fc9f125eb`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("westend-dev")`, DB CACHE: 1024 // Executed Command: -// ./target/production/polkadot +// target/production/polkadot // benchmark // pallet +// --extrinsic=* // --chain=westend-dev +// --pallet=pallet_multisig +// --header=/__w/polkadot-sdk/polkadot-sdk/polkadot/file_header.txt +// --output=./polkadot/runtime/westend/src/weights +// --wasm-execution=compiled // --steps=50 // --repeat=20 +// --heap-pages=4096 // --no-storage-info -// --no-median-slopes // --no-min-squares -// --pallet=pallet_multisig -// --extrinsic=* -// --execution=wasm -// --wasm-execution=compiled -// --header=./file_header.txt -// --output=./runtime/westend/src/weights/ +// --no-median-slopes #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] @@ -55,110 +55,111 @@ impl<T: frame_system::Config> pallet_multisig::WeightInfo for WeightInfo<T> { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 13_218_000 picoseconds. - Weight::from_parts(14_749_472, 0) + // Minimum execution time: 15_705_000 picoseconds. + Weight::from_parts(16_890_096, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 10 - .saturating_add(Weight::from_parts(507, 0).saturating_mul(z.into())) + // Standard Error: 13 + .saturating_add(Weight::from_parts(549, 0).saturating_mul(z.into())) } - /// Storage: Multisig Multisigs (r:1 w:1) - /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) + /// Storage: `Multisig::Multisigs` (r:1 w:1) + /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. /// The range of component `z` is `[0, 10000]`. fn as_multi_create(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `309 + s * (2 ±0)` + // Measured: `267 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 45_891_000 picoseconds. - Weight::from_parts(33_546_627, 0) + // Minimum execution time: 54_293_000 picoseconds. + Weight::from_parts(39_710_880, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 2_347 - .saturating_add(Weight::from_parts(136_466, 0).saturating_mul(s.into())) - // Standard Error: 23 - .saturating_add(Weight::from_parts(1_595, 0).saturating_mul(z.into())) + // Standard Error: 1_591 + .saturating_add(Weight::from_parts(164_846, 0).saturating_mul(s.into())) + // Standard Error: 15 + .saturating_add(Weight::from_parts(1_993, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Multisig Multisigs (r:1 w:1) - /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) + /// Storage: `Multisig::Multisigs` (r:1 w:1) + /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[3, 100]`. /// The range of component `z` is `[0, 10000]`. fn as_multi_approve(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `286` // Estimated: `6811` - // Minimum execution time: 30_355_000 picoseconds. - Weight::from_parts(19_611_682, 0) + // Minimum execution time: 36_477_000 picoseconds. + Weight::from_parts(22_595_904, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 1_383 - .saturating_add(Weight::from_parts(123_652, 0).saturating_mul(s.into())) - // Standard Error: 13 - .saturating_add(Weight::from_parts(1_488, 0).saturating_mul(z.into())) + // Standard Error: 1_526 + .saturating_add(Weight::from_parts(159_314, 0).saturating_mul(s.into())) + // Standard Error: 14 + .saturating_add(Weight::from_parts(2_219, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Multisig Multisigs (r:1 w:1) - /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: `Multisig::Multisigs` (r:1 w:1) + /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) + /// Storage: `System::Account` (r:1 w:1) + /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. /// The range of component `z` is `[0, 10000]`. fn as_multi_complete(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `392 + s * (33 ±0)` // Estimated: `6811` - // Minimum execution time: 50_453_000 picoseconds. - Weight::from_parts(35_628_285, 0) + // Minimum execution time: 60_127_000 picoseconds. + Weight::from_parts(33_469_803, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 3_693 - .saturating_add(Weight::from_parts(203_453, 0).saturating_mul(s.into())) - // Standard Error: 36 - .saturating_add(Weight::from_parts(1_726, 0).saturating_mul(z.into())) + // Standard Error: 3_400 + .saturating_add(Weight::from_parts(309_634, 0).saturating_mul(s.into())) + // Standard Error: 33 + .saturating_add(Weight::from_parts(2_795, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } - /// Storage: Multisig Multisigs (r:1 w:1) - /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) + /// Storage: `Multisig::Multisigs` (r:1 w:1) + /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. + /// The range of component `z` is `[0, 10000]`. fn approve_as_multi_create(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `314 + s * (2 ±0)` + // Measured: `267 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 32_500_000 picoseconds. - Weight::from_parts(33_231_806, 0) + // Minimum execution time: 36_697_000 picoseconds. + Weight::from_parts(38_746_125, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 1_511 - .saturating_add(Weight::from_parts(134_500, 0).saturating_mul(s.into())) + // Standard Error: 2_073 + .saturating_add(Weight::from_parts(159_426, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Multisig Multisigs (r:1 w:1) - /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) + /// Storage: `Multisig::Multisigs` (r:1 w:1) + /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. fn approve_as_multi_approve(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `286` // Estimated: `6811` - // Minimum execution time: 17_906_000 picoseconds. - Weight::from_parts(18_757_928, 0) + // Minimum execution time: 21_909_000 picoseconds. + Weight::from_parts(22_227_385, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 1_172 - .saturating_add(Weight::from_parts(113_535, 0).saturating_mul(s.into())) + // Standard Error: 1_063 + .saturating_add(Weight::from_parts(146_021, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - /// Storage: Multisig Multisigs (r:1 w:1) - /// Proof: Multisig Multisigs (max_values: None, max_size: Some(3346), added: 5821, mode: MaxEncodedLen) + /// Storage: `Multisig::Multisigs` (r:1 w:1) + /// Proof: `Multisig::Multisigs` (`max_values`: None, `max_size`: Some(3346), added: 5821, mode: `MaxEncodedLen`) /// The range of component `s` is `[2, 100]`. fn cancel_as_multi(s: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `458 + s * (1 ±0)` // Estimated: `6811` - // Minimum execution time: 33_018_000 picoseconds. - Weight::from_parts(34_186_533, 0) + // Minimum execution time: 36_637_000 picoseconds. + Weight::from_parts(36_457_379, 0) .saturating_add(Weight::from_parts(0, 6811)) - // Standard Error: 1_188 - .saturating_add(Weight::from_parts(128_449, 0).saturating_mul(s.into())) + // Standard Error: 1_709 + .saturating_add(Weight::from_parts(171_090, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } diff --git a/polkadot/xcm/Cargo.toml b/polkadot/xcm/Cargo.toml index e90354e4e6ac7697df704e495ee08a56c7df587e..f5f824ee409f0b12d05a822f2970d1c92b3c7649 100644 --- a/polkadot/xcm/Cargo.toml +++ b/polkadot/xcm/Cargo.toml @@ -15,7 +15,7 @@ workspace = true array-bytes = { workspace = true, default-features = true } bounded-collections = { features = ["serde"], workspace = true } codec = { features = ["derive", "max-encoded-len"], workspace = true } -derivative = { features = ["use_core"], workspace = true } +derive-where = { workspace = true } environmental = { workspace = true } frame-support = { workspace = true } hex-literal = { workspace = true, default-features = true } diff --git a/polkadot/xcm/src/lib.rs b/polkadot/xcm/src/lib.rs index a41a8e797b0f703302f62be04769c07ad2b9c3c4..2271835a9a5e87b6616e61f42d35ee8775abdb9b 100644 --- a/polkadot/xcm/src/lib.rs +++ b/polkadot/xcm/src/lib.rs @@ -25,7 +25,7 @@ extern crate alloc; use codec::{Decode, DecodeLimit, Encode, Error as CodecError, Input, MaxEncodedLen}; -use derivative::Derivative; +use derive_where::derive_where; use frame_support::dispatch::GetDispatchInfo; use scale_info::TypeInfo; @@ -88,13 +88,7 @@ macro_rules! versioned_type { $(#[$index5:meta])+ V5($v5:ty), }) => { - #[derive(Derivative, Encode, Decode, TypeInfo)] - #[derivative( - Clone(bound = ""), - Eq(bound = ""), - PartialEq(bound = ""), - Debug(bound = "") - )] + #[derive(Clone, Eq, PartialEq, Debug, Encode, Decode, TypeInfo)] #[codec(encode_bound())] #[codec(decode_bound())] #[scale_info(replace_segment("staging_xcm", "xcm"))] @@ -311,8 +305,8 @@ versioned_type! { } /// A single XCM message, together with its version code. -#[derive(Derivative, Encode, Decode, TypeInfo)] -#[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))] +#[derive(Encode, Decode, TypeInfo)] +#[derive_where(Clone, Eq, PartialEq, Debug)] #[codec(encode_bound())] #[codec(decode_bound())] #[scale_info(bounds(), skip_type_params(RuntimeCall))] diff --git a/polkadot/xcm/src/v3/mod.rs b/polkadot/xcm/src/v3/mod.rs index b60209a440c620f52746c407691213b664d215b7..6ae987a9830f1c6e426c1030316b97ecf6611262 100644 --- a/polkadot/xcm/src/v3/mod.rs +++ b/polkadot/xcm/src/v3/mod.rs @@ -28,7 +28,7 @@ use codec::{ MaxEncodedLen, }; use core::{fmt::Debug, result}; -use derivative::Derivative; +use derive_where::derive_where; use scale_info::TypeInfo; mod junction; @@ -57,8 +57,8 @@ pub const VERSION: super::Version = 3; /// An identifier for a query. pub type QueryId = u64; -#[derive(Derivative, Default, Encode, TypeInfo)] -#[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))] +#[derive(Default, Encode, TypeInfo)] +#[derive_where(Clone, Eq, PartialEq, Debug)] #[codec(encode_bound())] #[scale_info(bounds(), skip_type_params(Call))] #[scale_info(replace_segment("staging_xcm", "xcm"))] @@ -474,15 +474,8 @@ impl XcmContext { /// /// This is the inner XCM format and is version-sensitive. Messages are typically passed using the /// outer XCM format, known as `VersionedXcm`. -#[derive( - Derivative, - Encode, - Decode, - TypeInfo, - xcm_procedural::XcmWeightInfoTrait, - xcm_procedural::Builder, -)] -#[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))] +#[derive(Encode, Decode, TypeInfo, xcm_procedural::XcmWeightInfoTrait, xcm_procedural::Builder)] +#[derive_where(Clone, Eq, PartialEq, Debug)] #[codec(encode_bound())] #[codec(decode_bound())] #[scale_info(bounds(), skip_type_params(Call))] diff --git a/polkadot/xcm/src/v4/mod.rs b/polkadot/xcm/src/v4/mod.rs index a0ce551b7608cd2ff751eeb10877ef764cbde38f..66816e2fb6e7e3e4aaee7cef5de32d647c679d66 100644 --- a/polkadot/xcm/src/v4/mod.rs +++ b/polkadot/xcm/src/v4/mod.rs @@ -35,7 +35,7 @@ use codec::{ MaxEncodedLen, }; use core::{fmt::Debug, result}; -use derivative::Derivative; +use derive_where::derive_where; use frame_support::dispatch::GetDispatchInfo; use scale_info::TypeInfo; @@ -65,8 +65,8 @@ pub const VERSION: super::Version = 4; /// An identifier for a query. pub type QueryId = u64; -#[derive(Derivative, Default, Encode, TypeInfo)] -#[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))] +#[derive(Default, Encode, TypeInfo)] +#[derive_where(Clone, Eq, PartialEq, Debug)] #[codec(encode_bound())] #[codec(decode_bound())] #[scale_info(bounds(), skip_type_params(Call))] @@ -436,15 +436,8 @@ impl XcmContext { /// /// This is the inner XCM format and is version-sensitive. Messages are typically passed using the /// outer XCM format, known as `VersionedXcm`. -#[derive( - Derivative, - Encode, - Decode, - TypeInfo, - xcm_procedural::XcmWeightInfoTrait, - xcm_procedural::Builder, -)] -#[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))] +#[derive(Encode, Decode, TypeInfo, xcm_procedural::XcmWeightInfoTrait, xcm_procedural::Builder)] +#[derive_where(Clone, Eq, PartialEq, Debug)] #[codec(encode_bound())] #[codec(decode_bound())] #[scale_info(bounds(), skip_type_params(Call))] diff --git a/polkadot/xcm/src/v5/mod.rs b/polkadot/xcm/src/v5/mod.rs index 21845d07529efda1b0843ce77a26108eb43a92d6..51f6d839e972abfc3b98e94c7e649f7f2b9426bb 100644 --- a/polkadot/xcm/src/v5/mod.rs +++ b/polkadot/xcm/src/v5/mod.rs @@ -29,7 +29,7 @@ use codec::{ MaxEncodedLen, }; use core::{fmt::Debug, result}; -use derivative::Derivative; +use derive_where::derive_where; use scale_info::TypeInfo; mod asset; @@ -59,8 +59,8 @@ pub const VERSION: super::Version = 5; /// An identifier for a query. pub type QueryId = u64; -#[derive(Derivative, Default, Encode, TypeInfo)] -#[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))] +#[derive(Default, Encode, TypeInfo)] +#[derive_where(Clone, Eq, PartialEq, Debug)] #[codec(encode_bound())] #[codec(decode_bound())] #[scale_info(bounds(), skip_type_params(Call))] @@ -378,15 +378,8 @@ impl XcmContext { /// /// This is the inner XCM format and is version-sensitive. Messages are typically passed using the /// outer XCM format, known as `VersionedXcm`. -#[derive( - Derivative, - Encode, - Decode, - TypeInfo, - xcm_procedural::XcmWeightInfoTrait, - xcm_procedural::Builder, -)] -#[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))] +#[derive(Encode, Decode, TypeInfo, xcm_procedural::XcmWeightInfoTrait, xcm_procedural::Builder)] +#[derive_where(Clone, Eq, PartialEq, Debug)] #[codec(encode_bound())] #[codec(decode_bound())] #[scale_info(bounds(), skip_type_params(Call))] diff --git a/polkadot/xcm/xcm-builder/Cargo.toml b/polkadot/xcm/xcm-builder/Cargo.toml index f75c984c068eac33fa5c8e88989cc7ba7001aeb1..5169f586d723784e408afc3b4437635a6485ec02 100644 --- a/polkadot/xcm/xcm-builder/Cargo.toml +++ b/polkadot/xcm/xcm-builder/Cargo.toml @@ -31,7 +31,6 @@ xcm-executor = { workspace = true } polkadot-parachain-primitives = { workspace = true } [dev-dependencies] -assert_matches = { workspace = true } pallet-assets = { workspace = true, default-features = true } pallet-balances = { workspace = true, default-features = true } pallet-salary = { workspace = true, default-features = true } diff --git a/polkadot/xcm/xcm-builder/src/barriers.rs b/polkadot/xcm/xcm-builder/src/barriers.rs index 27153a3f441da0a9983bbbedbcaa090cf70bce8c..9f9d3c2321228d088ab12078dfec83d7c00e9bc6 100644 --- a/polkadot/xcm/xcm-builder/src/barriers.rs +++ b/polkadot/xcm/xcm-builder/src/barriers.rs @@ -24,7 +24,7 @@ use frame_support::{ }; use polkadot_parachain_primitives::primitives::IsSystem; use xcm::prelude::*; -use xcm_executor::traits::{CheckSuspension, OnResponse, Properties, ShouldExecute}; +use xcm_executor::traits::{CheckSuspension, DenyExecution, OnResponse, Properties, ShouldExecute}; /// Execution barrier that just takes `max_weight` from `properties.weight_credit`. /// @@ -444,12 +444,12 @@ impl ShouldExecute for AllowHrmpNotificationsFromRelayChain { /// If it passes the Deny, and matches one of the Allow cases then it is let through. pub struct DenyThenTry<Deny, Allow>(PhantomData<Deny>, PhantomData<Allow>) where - Deny: ShouldExecute, + Deny: DenyExecution, Allow: ShouldExecute; impl<Deny, Allow> ShouldExecute for DenyThenTry<Deny, Allow> where - Deny: ShouldExecute, + Deny: DenyExecution, Allow: ShouldExecute, { fn should_execute<RuntimeCall>( @@ -458,15 +458,15 @@ where max_weight: Weight, properties: &mut Properties, ) -> Result<(), ProcessMessageError> { - Deny::should_execute(origin, message, max_weight, properties)?; + Deny::deny_execution(origin, message, max_weight, properties)?; Allow::should_execute(origin, message, max_weight, properties) } } // See issue <https://github.com/paritytech/polkadot/issues/5233> pub struct DenyReserveTransferToRelayChain; -impl ShouldExecute for DenyReserveTransferToRelayChain { - fn should_execute<RuntimeCall>( +impl DenyExecution for DenyReserveTransferToRelayChain { + fn deny_execution<RuntimeCall>( origin: &Location, message: &mut [Instruction<RuntimeCall>], _max_weight: Weight, @@ -499,8 +499,6 @@ impl ShouldExecute for DenyReserveTransferToRelayChain { _ => Ok(ControlFlow::Continue(())), }, )?; - - // Permit everything else Ok(()) } } diff --git a/polkadot/xcm/xcm-builder/src/tests/barriers.rs b/polkadot/xcm/xcm-builder/src/tests/barriers.rs index d8805274d3a56f31debb31a0a01e9939f599ac71..2fb8e8ed0363b09794f7e4720f8eeab58994e0ff 100644 --- a/polkadot/xcm/xcm-builder/src/tests/barriers.rs +++ b/polkadot/xcm/xcm-builder/src/tests/barriers.rs @@ -532,3 +532,235 @@ fn allow_hrmp_notifications_from_relay_chain_should_work() { Ok(()), ); } + +#[test] +fn deny_then_try_works() { + /// A dummy `DenyExecution` impl which returns `ProcessMessageError::Yield` when XCM contains + /// `ClearTransactStatus` + struct DenyClearTransactStatusAsYield; + impl DenyExecution for DenyClearTransactStatusAsYield { + fn deny_execution<RuntimeCall>( + _origin: &Location, + instructions: &mut [Instruction<RuntimeCall>], + _max_weight: Weight, + _properties: &mut Properties, + ) -> Result<(), ProcessMessageError> { + instructions.matcher().match_next_inst_while( + |_| true, + |inst| match inst { + ClearTransactStatus { .. } => Err(ProcessMessageError::Yield), + _ => Ok(ControlFlow::Continue(())), + }, + )?; + Ok(()) + } + } + + /// A dummy `DenyExecution` impl which returns `ProcessMessageError::BadFormat` when XCM + /// contains `ClearOrigin` with origin location from `Here` + struct DenyClearOriginFromHereAsBadFormat; + impl DenyExecution for DenyClearOriginFromHereAsBadFormat { + fn deny_execution<RuntimeCall>( + origin: &Location, + instructions: &mut [Instruction<RuntimeCall>], + _max_weight: Weight, + _properties: &mut Properties, + ) -> Result<(), ProcessMessageError> { + instructions.matcher().match_next_inst_while( + |_| true, + |inst| match inst { + ClearOrigin { .. } => + if origin.clone() == Here.into_location() { + Err(ProcessMessageError::BadFormat) + } else { + Ok(ControlFlow::Continue(())) + }, + _ => Ok(ControlFlow::Continue(())), + }, + )?; + Ok(()) + } + } + + /// A dummy `DenyExecution` impl which returns `ProcessMessageError::StackLimitReached` when XCM + /// contains a single `UnsubscribeVersion` + struct DenyUnsubscribeVersionAsStackLimitReached; + impl DenyExecution for DenyUnsubscribeVersionAsStackLimitReached { + fn deny_execution<RuntimeCall>( + _origin: &Location, + instructions: &mut [Instruction<RuntimeCall>], + _max_weight: Weight, + _properties: &mut Properties, + ) -> Result<(), ProcessMessageError> { + if instructions.len() != 1 { + return Ok(()) + } + match instructions.get(0).unwrap() { + UnsubscribeVersion { .. } => Err(ProcessMessageError::StackLimitReached), + _ => Ok(()), + } + } + } + + /// A dummy `ShouldExecute` impl which returns `Ok(())` when XCM contains a single `ClearError`, + /// else return `ProcessMessageError::Yield` + struct AllowSingleClearErrorOrYield; + impl ShouldExecute for AllowSingleClearErrorOrYield { + fn should_execute<Call>( + _origin: &Location, + instructions: &mut [Instruction<Call>], + _max_weight: Weight, + _properties: &mut Properties, + ) -> Result<(), ProcessMessageError> { + instructions.matcher().assert_remaining_insts(1)?.match_next_inst( + |inst| match inst { + ClearError { .. } => Ok(()), + _ => Err(ProcessMessageError::Yield), + }, + )?; + Ok(()) + } + } + + /// A dummy `ShouldExecute` impl which returns `Ok(())` when XCM contains `ClearTopic` and + /// origin from `Here`, else return `ProcessMessageError::Unsupported` + struct AllowClearTopicFromHere; + impl ShouldExecute for AllowClearTopicFromHere { + fn should_execute<Call>( + origin: &Location, + instructions: &mut [Instruction<Call>], + _max_weight: Weight, + _properties: &mut Properties, + ) -> Result<(), ProcessMessageError> { + ensure!(origin.clone() == Here.into_location(), ProcessMessageError::Unsupported); + let mut found = false; + instructions.matcher().match_next_inst_while( + |_| true, + |inst| match inst { + ClearTopic { .. } => { + found = true; + Ok(ControlFlow::Break(())) + }, + _ => Ok(ControlFlow::Continue(())), + }, + )?; + ensure!(found, ProcessMessageError::Unsupported); + Ok(()) + } + } + // closure for (xcm, origin) testing with `DenyThenTry` + let assert_should_execute = |mut xcm: Vec<Instruction<()>>, origin, expected_result| { + pub type Barrier = DenyThenTry< + ( + DenyClearTransactStatusAsYield, + DenyClearOriginFromHereAsBadFormat, + DenyUnsubscribeVersionAsStackLimitReached, + ), + (AllowSingleClearErrorOrYield, AllowClearTopicFromHere), + >; + assert_eq!( + Barrier::should_execute( + &origin, + &mut xcm, + Weight::from_parts(10, 10), + &mut props(Weight::zero()), + ), + expected_result + ); + }; + + // Deny cases: + // trigger DenyClearTransactStatusAsYield + assert_should_execute( + vec![ClearTransactStatus], + Parachain(1).into_location(), + Err(ProcessMessageError::Yield), + ); + // DenyClearTransactStatusAsYield wins against AllowSingleClearErrorOrYield + assert_should_execute( + vec![ClearError, ClearTransactStatus], + Parachain(1).into_location(), + Err(ProcessMessageError::Yield), + ); + // trigger DenyClearOriginFromHereAsBadFormat + assert_should_execute( + vec![ClearOrigin], + Here.into_location(), + Err(ProcessMessageError::BadFormat), + ); + // trigger DenyUnsubscribeVersionAsStackLimitReached + assert_should_execute( + vec![UnsubscribeVersion], + Here.into_location(), + Err(ProcessMessageError::StackLimitReached), + ); + + // deny because none of the allow items match + assert_should_execute( + vec![ClearError, ClearTopic], + Parachain(1).into_location(), + Err(ProcessMessageError::Unsupported), + ); + + // ok + assert_should_execute(vec![ClearError], Parachain(1).into_location(), Ok(())); + assert_should_execute(vec![ClearTopic], Here.into(), Ok(())); + assert_should_execute(vec![ClearError, ClearTopic], Here.into_location(), Ok(())); +} + +#[test] +fn deny_reserve_transfer_to_relaychain_should_work() { + let assert_deny_execution = |mut xcm: Vec<Instruction<()>>, origin, expected_result| { + assert_eq!( + DenyReserveTransferToRelayChain::deny_execution( + &origin, + &mut xcm, + Weight::from_parts(10, 10), + &mut props(Weight::zero()), + ), + expected_result + ); + }; + // deny DepositReserveAsset to RelayChain + assert_deny_execution( + vec![DepositReserveAsset { + assets: Wild(All), + dest: Location::parent(), + xcm: vec![].into(), + }], + Here.into_location(), + Err(ProcessMessageError::Unsupported), + ); + // deny InitiateReserveWithdraw to RelayChain + assert_deny_execution( + vec![InitiateReserveWithdraw { + assets: Wild(All), + reserve: Location::parent(), + xcm: vec![].into(), + }], + Here.into_location(), + Err(ProcessMessageError::Unsupported), + ); + // deny TransferReserveAsset to RelayChain + assert_deny_execution( + vec![TransferReserveAsset { + assets: vec![].into(), + dest: Location::parent(), + xcm: vec![].into(), + }], + Here.into_location(), + Err(ProcessMessageError::Unsupported), + ); + // accept DepositReserveAsset to destination other than RelayChain + assert_deny_execution( + vec![DepositReserveAsset { + assets: Wild(All), + dest: Here.into_location(), + xcm: vec![].into(), + }], + Here.into_location(), + Ok(()), + ); + // others instructions should pass + assert_deny_execution(vec![ClearOrigin], Here.into_location(), Ok(())); +} diff --git a/polkadot/xcm/xcm-builder/src/tests/mock.rs b/polkadot/xcm/xcm-builder/src/tests/mock.rs index bec7b253977b6de1319cd3e974e7b74d8a36835d..127888104a4ad77b0272d8e230f724d3e1cca7ac 100644 --- a/polkadot/xcm/xcm-builder/src/tests/mock.rs +++ b/polkadot/xcm/xcm-builder/src/tests/mock.rs @@ -31,6 +31,7 @@ pub use codec::{Decode, Encode}; pub use core::{ cell::{Cell, RefCell}, fmt::Debug, + ops::ControlFlow, }; use frame_support::traits::{ContainsPair, Everything}; pub use frame_support::{ @@ -40,11 +41,11 @@ pub use frame_support::{ traits::{Contains, Get, IsInVec}, }; pub use xcm::latest::{prelude::*, QueryId, Weight}; -use xcm_executor::traits::{Properties, QueryHandler, QueryResponseStatus}; pub use xcm_executor::{ traits::{ - AssetExchange, AssetLock, CheckSuspension, ConvertOrigin, Enact, ExportXcm, FeeManager, - FeeReason, LockError, OnResponse, TransactAsset, + AssetExchange, AssetLock, CheckSuspension, ConvertOrigin, DenyExecution, Enact, ExportXcm, + FeeManager, FeeReason, LockError, OnResponse, Properties, QueryHandler, + QueryResponseStatus, TransactAsset, }, AssetsInHolding, Config, }; diff --git a/polkadot/xcm/xcm-executor/src/traits/mod.rs b/polkadot/xcm/xcm-executor/src/traits/mod.rs index feb2922bcdffce1ea9e3a40e22875c085c82870f..fe73477f516fbc7e0b42fcf1edff004d4b8a89fd 100644 --- a/polkadot/xcm/xcm-executor/src/traits/mod.rs +++ b/polkadot/xcm/xcm-executor/src/traits/mod.rs @@ -42,7 +42,7 @@ pub use on_response::{OnResponse, QueryHandler, QueryResponseStatus, VersionChan mod process_transaction; pub use process_transaction::ProcessTransaction; mod should_execute; -pub use should_execute::{CheckSuspension, Properties, ShouldExecute}; +pub use should_execute::{CheckSuspension, DenyExecution, Properties, ShouldExecute}; mod transact_asset; pub use transact_asset::TransactAsset; mod hrmp; diff --git a/polkadot/xcm/xcm-executor/src/traits/should_execute.rs b/polkadot/xcm/xcm-executor/src/traits/should_execute.rs index ec9ef70cc817e5a230ae843581fb736ce06770ee..48a562a1648ddb28bb90a68a3c7e501c2077bec2 100644 --- a/polkadot/xcm/xcm-executor/src/traits/should_execute.rs +++ b/polkadot/xcm/xcm-executor/src/traits/should_execute.rs @@ -127,3 +127,67 @@ impl CheckSuspension for Tuple { false } } + +/// Trait to determine whether the execution engine should not execute a given XCM. +/// +/// Can be amalgamated into a tuple to have multiple traits. If any of the tuple elements returns +/// `Err(ProcessMessageError)`, the execution stops. Else, `Ok(())` is returned if all elements +/// accept the message. +pub trait DenyExecution { + /// Returns `Ok(())` if there is no reason to deny execution, + /// while `Err(ProcessMessageError)` indicates there is a reason to deny execution. + /// + /// - `origin`: The origin (sender) of the message. + /// - `instructions`: The message itself. + /// - `max_weight`: The (possibly over-) estimation of the weight of execution of the message. + /// - `properties`: Various pre-established properties of the message which may be mutated by + /// this API. + fn deny_execution<RuntimeCall>( + origin: &Location, + instructions: &mut [Instruction<RuntimeCall>], + max_weight: Weight, + properties: &mut Properties, + ) -> Result<(), ProcessMessageError>; +} + +#[impl_trait_for_tuples::impl_for_tuples(10)] +impl DenyExecution for Tuple { + fn deny_execution<RuntimeCall>( + origin: &Location, + instructions: &mut [Instruction<RuntimeCall>], + max_weight: Weight, + properties: &mut Properties, + ) -> Result<(), ProcessMessageError> { + for_tuples!( #( + let barrier = core::any::type_name::<Tuple>(); + match Tuple::deny_execution(origin, instructions, max_weight, properties) { + Err(error) => { + tracing::error!( + target: "xcm::deny_execution", + ?origin, + ?instructions, + ?max_weight, + ?properties, + ?error, + %barrier, + "did not pass barrier", + ); + return Err(error); + }, + Ok(()) => { + tracing::trace!( + target: "xcm::deny_execution", + ?origin, + ?instructions, + ?max_weight, + ?properties, + %barrier, + "pass barrier", + ); + }, + } + )* ); + + Ok(()) + } +} diff --git a/polkadot/zombienet-sdk-tests/tests/elastic_scaling/basic_3cores.rs b/polkadot/zombienet-sdk-tests/tests/elastic_scaling/basic_3cores.rs index 42aa83d9da7a22c2e21b9020cade89cf7c89c8ca..1bf972750d67f238ea8ccac8dffc0e6f796d6375 100644 --- a/polkadot/zombienet-sdk-tests/tests/elastic_scaling/basic_3cores.rs +++ b/polkadot/zombienet-sdk-tests/tests/elastic_scaling/basic_3cores.rs @@ -41,10 +41,6 @@ async fn basic_3cores_test() -> Result<(), anyhow::Error> { "num_cores": 2, "max_validators_per_core": 1 }, - "async_backing_params": { - "max_candidate_depth": 6, - "allowed_ancestry_len": 2 - } } } })) diff --git a/polkadot/zombienet-sdk-tests/tests/elastic_scaling/doesnt_break_parachains.rs b/polkadot/zombienet-sdk-tests/tests/elastic_scaling/doesnt_break_parachains.rs index e65029d7095cb224ad9ef03b3013d3ff3f30b2eb..37b36efec772577ab613b3f67f7d45bb9ec0f713 100644 --- a/polkadot/zombienet-sdk-tests/tests/elastic_scaling/doesnt_break_parachains.rs +++ b/polkadot/zombienet-sdk-tests/tests/elastic_scaling/doesnt_break_parachains.rs @@ -40,11 +40,7 @@ async fn doesnt_break_parachains_test() -> Result<(), anyhow::Error> { "config": { "scheduler_params": { "num_cores": 1, - "max_validators_per_core": 2 - }, - "async_backing_params": { - "max_candidate_depth": 6, - "allowed_ancestry_len": 2 + "max_validators_per_core": 2, } } } diff --git a/polkadot/zombienet-sdk-tests/tests/elastic_scaling/mod.rs b/polkadot/zombienet-sdk-tests/tests/elastic_scaling/mod.rs index 9cfd5db5a096dbd393f84ea4fff7bf2b1df59227..a993e8e27214b649c00e35cbf8e24105a1d1dd60 100644 --- a/polkadot/zombienet-sdk-tests/tests/elastic_scaling/mod.rs +++ b/polkadot/zombienet-sdk-tests/tests/elastic_scaling/mod.rs @@ -3,4 +3,5 @@ mod basic_3cores; mod doesnt_break_parachains; +mod slot_based_12cores; mod slot_based_3cores; diff --git a/polkadot/zombienet-sdk-tests/tests/elastic_scaling/slot_based_12cores.rs b/polkadot/zombienet-sdk-tests/tests/elastic_scaling/slot_based_12cores.rs new file mode 100644 index 0000000000000000000000000000000000000000..4d0e1adad0849a5a695c0a47db33ec7e3fe5378f --- /dev/null +++ b/polkadot/zombienet-sdk-tests/tests/elastic_scaling/slot_based_12cores.rs @@ -0,0 +1,129 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Test that a parachain that uses a single slot-based collator with elastic scaling can use 12 +// cores in order to achieve 500ms blocks. + +use anyhow::anyhow; + +use crate::helpers::{ + assert_finalized_block_height, assert_para_throughput, rococo, + rococo::runtime_types::{ + pallet_broker::coretime_interface::CoreAssignment, + polkadot_runtime_parachains::assigner_coretime::PartsOf57600, + }, +}; +use polkadot_primitives::Id as ParaId; +use serde_json::json; +use subxt::{OnlineClient, PolkadotConfig}; +use subxt_signer::sr25519::dev; +use zombienet_sdk::NetworkConfigBuilder; + +#[tokio::test(flavor = "multi_thread")] +async fn slot_based_12cores_test() -> Result<(), anyhow::Error> { + let _ = env_logger::try_init_from_env( + env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, "info"), + ); + + let images = zombienet_sdk::environment::get_images_from_env(); + + let config = NetworkConfigBuilder::new() + .with_relaychain(|r| { + let r = r + .with_chain("rococo-local") + .with_default_command("polkadot") + .with_default_image(images.polkadot.as_str()) + .with_default_args(vec![("-lparachain=debug").into()]) + .with_genesis_overrides(json!({ + "configuration": { + "config": { + "scheduler_params": { + "num_cores": 11, + "max_validators_per_core": 1 + }, + "async_backing_params": { + "max_candidate_depth": 24, + "allowed_ancestry_len": 2 + } + } + } + })) + // Have to set a `with_node` outside of the loop below, so that `r` has the right + // type. + .with_node(|node| node.with_name("validator-0")); + + (1..12) + .fold(r, |acc, i| acc.with_node(|node| node.with_name(&format!("validator-{i}")))) + }) + .with_parachain(|p| { + p.with_id(2300) + .with_default_command("test-parachain") + .with_default_image(images.cumulus.as_str()) + .with_chain("elastic-scaling-500ms") + .with_default_args(vec![ + ("--experimental-use-slot-based").into(), + ("-lparachain=debug,aura=debug").into(), + ]) + .with_collator(|n| n.with_name("collator-elastic")) + }) + .build() + .map_err(|e| { + let errs = e.into_iter().map(|e| e.to_string()).collect::<Vec<_>>().join(" "); + anyhow!("config errs: {errs}") + })?; + + let spawn_fn = zombienet_sdk::environment::get_spawn_fn(); + let network = spawn_fn(config).await?; + + let relay_node = network.get_node("validator-0")?; + let para_node = network.get_node("collator-elastic")?; + + let relay_client: OnlineClient<PolkadotConfig> = relay_node.wait_client().await?; + let alice = dev::alice(); + + // Assign 11 extra cores to the parachain. + + relay_client + .tx() + .sign_and_submit_then_watch_default( + &rococo::tx() + .sudo() + .sudo(rococo::runtime_types::rococo_runtime::RuntimeCall::Utility( + rococo::runtime_types::pallet_utility::pallet::Call::batch { + calls: (0..11).map(|idx| rococo::runtime_types::rococo_runtime::RuntimeCall::Coretime( + rococo::runtime_types::polkadot_runtime_parachains::coretime::pallet::Call::assign_core { + core: idx, + begin: 0, + assignment: vec![(CoreAssignment::Task(2300), PartsOf57600(57600))], + end_hint: None + } + )).collect() + }, + )), + &alice, + ) + .await? + .wait_for_finalized_success() + .await?; + + log::info!("11 more cores assigned to the parachain"); + + // Expect a backed candidate count of at least 170 in 15 relay chain blocks + // (11.33 candidates per para per relay chain block). + // Note that only blocks after the first session change and blocks that don't contain a session + // change will be counted. + assert_para_throughput( + &relay_client, + 15, + [(ParaId::from(2300), 170..181)].into_iter().collect(), + ) + .await?; + + // Assert the parachain finalized block height is also on par with the number of backed + // candidates. + assert_finalized_block_height(¶_node.wait_client().await?, 158..181).await?; + + log::info!("Test finished successfully"); + + Ok(()) +} diff --git a/polkadot/zombienet-sdk-tests/tests/elastic_scaling/slot_based_3cores.rs b/polkadot/zombienet-sdk-tests/tests/elastic_scaling/slot_based_3cores.rs index aa9f41320135defd9a85e9ba3c5dafa623a3187b..aa1e54d7da5d98c02dbbc74eb8149f204212744c 100644 --- a/polkadot/zombienet-sdk-tests/tests/elastic_scaling/slot_based_3cores.rs +++ b/polkadot/zombienet-sdk-tests/tests/elastic_scaling/slot_based_3cores.rs @@ -41,10 +41,6 @@ async fn slot_based_3cores_test() -> Result<(), anyhow::Error> { // Num cores is 4, because 2 extra will be added automatically when registering the paras. "num_cores": 4, "max_validators_per_core": 2 - }, - "async_backing_params": { - "max_candidate_depth": 6, - "allowed_ancestry_len": 2 } } } diff --git a/polkadot/zombienet-sdk-tests/tests/functional/async_backing_6_seconds_rate.rs b/polkadot/zombienet-sdk-tests/tests/functional/async_backing_6_seconds_rate.rs index 14f86eb130f78e24796db6280f17fcb430d604ae..1f8c2aeff1c23ad2c22ac00a0ca9a7b45c1d45ba 100644 --- a/polkadot/zombienet-sdk-tests/tests/functional/async_backing_6_seconds_rate.rs +++ b/polkadot/zombienet-sdk-tests/tests/functional/async_backing_6_seconds_rate.rs @@ -30,11 +30,8 @@ async fn async_backing_6_seconds_rate_test() -> Result<(), anyhow::Error> { "configuration": { "config": { "scheduler_params": { - "group_rotation_frequency": 4, - "lookahead": 2, - "max_candidate_depth": 3, - "allowed_ancestry_len": 2, - }, + "group_rotation_frequency": 4 + } } } })) diff --git a/polkadot/zombienet-sdk-tests/tests/functional/duplicate_collations.rs b/polkadot/zombienet-sdk-tests/tests/functional/duplicate_collations.rs new file mode 100644 index 0000000000000000000000000000000000000000..43420692d32ed1999fc1d256b6baafa89389afba --- /dev/null +++ b/polkadot/zombienet-sdk-tests/tests/functional/duplicate_collations.rs @@ -0,0 +1,154 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Test that a parachain using a malus undying collator, sending the same collation to all assigned +// cores, does not break the relay chain and that blocks are included, backed by a normal collator. + +use anyhow::anyhow; + +use crate::helpers::{ + assert_para_throughput, rococo, + rococo::runtime_types::{ + pallet_broker::coretime_interface::CoreAssignment, + polkadot_runtime_parachains::assigner_coretime::PartsOf57600, + }, +}; +use polkadot_primitives::Id as ParaId; +use serde_json::json; +use subxt::{OnlineClient, PolkadotConfig}; +use subxt_signer::sr25519::dev; +use zombienet_sdk::NetworkConfigBuilder; + +const VALIDATOR_COUNT: u8 = 3; + +#[tokio::test(flavor = "multi_thread")] +async fn duplicate_collations_test() -> Result<(), anyhow::Error> { + let _ = env_logger::try_init_from_env( + env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, "info"), + ); + + let images = zombienet_sdk::environment::get_images_from_env(); + + let config = NetworkConfigBuilder::new() + .with_relaychain(|r| { + let r = r + .with_chain("rococo-local") + .with_default_command("polkadot") + .with_default_image(images.polkadot.as_str()) + .with_default_args(vec![("-lparachain=debug").into()]) + .with_genesis_overrides(json!({ + "configuration": { + "config": { + "scheduler_params": { + "num_cores": 2 + }, + "async_backing_params": { + "max_candidate_depth": 6 + } + } + } + })) + // Have to set a `with_node` outside of the loop below, so that `r` has the right + // type. + .with_node(|node| node.with_name("validator-0")); + + (1..VALIDATOR_COUNT) + .fold(r, |acc, i| acc.with_node(|node| node.with_name(&format!("validator-{i}")))) + }) + .with_parachain(|p| { + p.with_id(2000) + .with_default_command("undying-collator") + .cumulus_based(false) + .with_default_image( + std::env::var("COL_IMAGE") + .unwrap_or("docker.io/paritypr/colander:latest".to_string()) + .as_str(), + ) + .with_collator(|n| { + n.with_name("normal-collator").with_args(vec![("-lparachain=debug").into()]) + }) + .with_collator(|n| { + n.with_name("malus-collator").with_args(vec![ + ("-lparachain=debug").into(), + ("--malus-type=duplicate-collations").into(), + ]) + }) + }) + .build() + .map_err(|e| { + let errs = e.into_iter().map(|e| e.to_string()).collect::<Vec<_>>().join(" "); + anyhow!("config errs: {errs}") + })?; + + let spawn_fn = zombienet_sdk::environment::get_spawn_fn(); + let network = spawn_fn(config).await?; + + let relay_node = network.get_node("validator-0")?; + + let relay_client: OnlineClient<PolkadotConfig> = relay_node.wait_client().await?; + let alice = dev::alice(); + + // Assign two extra cores to parachain-2000. + relay_client + .tx() + .sign_and_submit_then_watch_default( + &rococo::tx() + .sudo() + .sudo(rococo::runtime_types::rococo_runtime::RuntimeCall::Utility( + rococo::runtime_types::pallet_utility::pallet::Call::batch { + calls: vec![ + rococo::runtime_types::rococo_runtime::RuntimeCall::Coretime( + rococo::runtime_types::polkadot_runtime_parachains::coretime::pallet::Call::assign_core { + core: 0, + begin: 0, + assignment: vec![(CoreAssignment::Task(2000), PartsOf57600(57600))], + end_hint: None + } + ), + rococo::runtime_types::rococo_runtime::RuntimeCall::Coretime( + rococo::runtime_types::polkadot_runtime_parachains::coretime::pallet::Call::assign_core { + core: 1, + begin: 0, + assignment: vec![(CoreAssignment::Task(2000), PartsOf57600(57600))], + end_hint: None + } + ), + ], + }, + )), + &alice, + ) + .await? + .wait_for_finalized_success() + .await?; + + log::info!("2 more cores assigned to parachain-2000"); + + assert_para_throughput(&relay_client, 15, [(ParaId::from(2000), 40..46)].into_iter().collect()) + .await?; + + // Verify that all validators detect the malicious collator by checking their logs. This check + // must be performed after the para throughput check because the validator group needs to rotate + // at least once. This ensures that all validators have had a chance to detect the malicious + // behavior. + for i in 0..VALIDATOR_COUNT { + let validator_name = &format!("validator-{}", i); + let validator_node = network.get_node(validator_name)?; + validator_node + .wait_log_line_count_with_timeout( + "Candidate core index is invalid: The core index in commitments doesn't match the one in descriptor", + false, + 1_usize, + // Since we have this check after the para throughput check, all validators + // should have already detected the malicious collator, and all expected logs + // should have already appeared, so there is no need to wait more than 1 second. + 1_u64, + ) + .await + .unwrap_or_else(|error| panic!("Expected log not found for {}: {:?}", validator_name, error)); + } + + log::info!("Test finished successfully"); + + Ok(()) +} diff --git a/polkadot/zombienet-sdk-tests/tests/functional/mod.rs b/polkadot/zombienet-sdk-tests/tests/functional/mod.rs index ecdab38e1d2865faaa6957c5f2ce331dc96d61df..7e5d313ff68dd194db0d6cdaa2ad8154e6010359 100644 --- a/polkadot/zombienet-sdk-tests/tests/functional/mod.rs +++ b/polkadot/zombienet-sdk-tests/tests/functional/mod.rs @@ -2,4 +2,5 @@ // SPDX-License-Identifier: Apache-2.0 mod async_backing_6_seconds_rate; +mod duplicate_collations; mod sync_backing; diff --git a/polkadot/zombienet_tests/functional/0015-coretime-shared-core.toml b/polkadot/zombienet_tests/functional/0015-coretime-shared-core.toml index fed30e0db05321631fdce66da858e1431ded64dd..c6545e476a64d22b242f2c4e238a3e7ba5df7ec0 100644 --- a/polkadot/zombienet_tests/functional/0015-coretime-shared-core.toml +++ b/polkadot/zombienet_tests/functional/0015-coretime-shared-core.toml @@ -1,13 +1,8 @@ [settings] timeout = 1000 -[relaychain.genesis.runtimeGenesis.patch.configuration.config.async_backing_params] - max_candidate_depth = 3 - allowed_ancestry_len = 2 - [relaychain.genesis.runtimeGenesis.patch.configuration.config.scheduler_params] max_validators_per_core = 1 - lookahead = 2 num_cores = 4 [relaychain.genesis.runtimeGenesis.patch.configuration.config.approval_voting_params] diff --git a/polkadot/zombienet_tests/functional/0018-shared-core-idle-parachain.toml b/polkadot/zombienet_tests/functional/0018-shared-core-idle-parachain.toml index d3ff0000224279476bd7715ee87318ac3e89012b..050c1f01923bc07ecd80271bbf9f1ab98fd754b2 100644 --- a/polkadot/zombienet_tests/functional/0018-shared-core-idle-parachain.toml +++ b/polkadot/zombienet_tests/functional/0018-shared-core-idle-parachain.toml @@ -3,7 +3,6 @@ timeout = 1000 [relaychain.genesis.runtimeGenesis.patch.configuration.config.scheduler_params] max_validators_per_core = 2 - lookahead = 2 num_cores = 4 group_rotation_frequency = 4 diff --git a/polkadot/zombienet_tests/functional/0019-coretime-collation-fetching-fairness.toml b/polkadot/zombienet_tests/functional/0019-coretime-collation-fetching-fairness.toml index 43f3ef8f9e559a3266dc274c4dca8854e5704db8..f9028b930cfec9b32b54185f4097867beb9b02cf 100644 --- a/polkadot/zombienet_tests/functional/0019-coretime-collation-fetching-fairness.toml +++ b/polkadot/zombienet_tests/functional/0019-coretime-collation-fetching-fairness.toml @@ -1,14 +1,9 @@ [settings] timeout = 1000 -[relaychain.genesis.runtimeGenesis.patch.configuration.config.async_backing_params] - max_candidate_depth = 3 - allowed_ancestry_len = 2 - [relaychain.genesis.runtimeGenesis.patch.configuration.config.scheduler_params] max_validators_per_core = 4 num_cores = 1 - lookahead = 2 [relaychain.genesis.runtimeGenesis.patch.configuration.config.approval_voting_params] needed_approvals = 3 diff --git a/polkadot/zombienet_tests/misc/0002-upgrade-node.toml b/polkadot/zombienet_tests/misc/0002-upgrade-node.toml index 1edb18abcececa32cadcf3756ac11e66be5f12c6..5e5e3719936ab0432479fcd217945bf113659b6d 100644 --- a/polkadot/zombienet_tests/misc/0002-upgrade-node.toml +++ b/polkadot/zombienet_tests/misc/0002-upgrade-node.toml @@ -30,7 +30,7 @@ addToGenesis = true [parachains.collator] name = "collator01" image = "{{COL_IMAGE}}" - command = "undying-collator" + command = "adder-collator" args = ["-lparachain=debug"] [[parachains]] @@ -40,7 +40,7 @@ addToGenesis = true [parachains.collator] name = "collator02" image = "{{COL_IMAGE}}" - command = "undying-collator" + command = "adder-collator" args = ["-lparachain=debug"] [types.Header] diff --git a/prdoc/pr_4722.prdoc b/prdoc/pr_4722.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..a5bdbbeb3df9aa45868aa8cdd0156d40ae23e683 --- /dev/null +++ b/prdoc/pr_4722.prdoc @@ -0,0 +1,33 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Implement pallet view functions + +doc: + - audience: Runtime Dev + description: | + Read-only view functions can now be defined on pallets. These functions provide an interface for querying state, + from both outside and inside the runtime. Common queries can be defined on pallets, without users having to + access the storage directly. + + - audience: Runtime User + description: | + Querying the runtime state is now easier with the introduction of pallet view functions. Clients can call commonly + defined view functions rather than accessing the storage directly. These are similar to the Runtime APIs, but + are defined within the runtime itself. + +crates: + - name: frame-support + bump: minor + - name: sp-metadata-ir + bump: major + - name: frame-support-procedural + bump: patch + - name: pallet-example-view-functions + bump: patch + - name: cumulus-pov-validator + bump: none + - name: cumulus-pallet-weight-reclaim + bump: patch + - name: westend-runtime + bump: minor \ No newline at end of file diff --git a/prdoc/pr_6897.prdoc b/prdoc/pr_6897.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..38fd9417f48aba86065a3421656464dc961832b7 --- /dev/null +++ b/prdoc/pr_6897.prdoc @@ -0,0 +1,7 @@ +title: 'Tracing Log for fork-aware transaction pool' +doc: +- audience: Node Dev + description: Replacement of log crate with tracing crate for better logging. +crates: +- name: sc-transaction-pool + bump: minor \ No newline at end of file diff --git a/prdoc/pr_6924.prdoc b/prdoc/pr_6924.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..dc27bb9adfcba0029d6438c62762134ede3595aa --- /dev/null +++ b/prdoc/pr_6924.prdoc @@ -0,0 +1,19 @@ +title: "malus-collator: implement malicious collator submitting same collation to all backing groups" + +doc: + - audience: Node Dev + description: | + This PR modifies the undying collator to include a malus mode, + enabling it to submit the same collation to all assigned backing groups. + + It also includes a test that spawns a network with the malus collator + and verifies that everything functions correctly. + +crates: + - name: polkadot + bump: none + validate: false + - name: test-parachain-undying + bump: patch + - name: test-parachain-undying-collator + bump: patch diff --git a/prdoc/pr_6983.prdoc b/prdoc/pr_6983.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..fddf831ead12761b4a60742bf77eb79cae19fd16 --- /dev/null +++ b/prdoc/pr_6983.prdoc @@ -0,0 +1,17 @@ +title: 'cumulus: bump PARENT_SEARCH_DEPTH to allow for 12-core elastic scaling' +doc: +- audience: Node Dev + description: | + Bumps the PARENT_SEARCH_DEPTH constant to a larger value (30). + This is a node-side limit that restricts the number of allowed pending availability candidates when choosing the parent parablock during authoring. + This limit is rather redundant, as the parachain runtime already restricts the unincluded segment length to the configured value in the + FixedVelocityConsensusHook. + For 12 cores, a value of 24 should be enough, but bumped it to 30 to have some extra buffer. + +crates: +- name: cumulus-client-consensus-aura + bump: patch +- name: cumulus-test-runtime + bump: minor +- name: cumulus-test-service + bump: minor diff --git a/prdoc/pr_7042.prdoc b/prdoc/pr_7042.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..00fb34c6af493b9b5d1e560bde28555242fa0d3d --- /dev/null +++ b/prdoc/pr_7042.prdoc @@ -0,0 +1,9 @@ +title: `networking::TransactionPool` should accept `Arc` +doc: +- audience: Node Dev + description: The `sc_network_transactions::config::TransactionPool` trait now returns an `Arc` for transactions. +crates: +- name: sc-network-transactions + bump: minor +- name: sc-service + bump: minor \ No newline at end of file diff --git a/prdoc/pr_7169.prdoc b/prdoc/pr_7169.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..f78dbfd8d2cd18cccbd3f7c94958c23371fdfbaf --- /dev/null +++ b/prdoc/pr_7169.prdoc @@ -0,0 +1,14 @@ +title: 'xcm: fix DenyThenTry when work with multiple Deny tuples' +doc: +- audience: Runtime User + description: |- + This PR changes the behavior of DenyThenTry to fix #7148 + If any of the tuple elements returns `Err(())`, the execution stops. + Else, `Ok(_)` is returned if all elements accept the message. +crates: +- name: staging-xcm-executor + bump: minor +- name: staging-xcm-builder + bump: minor +- name: bridge-hub-common + bump: minor diff --git a/prdoc/pr_7198.prdoc b/prdoc/pr_7198.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..15478d9341d689d4e775f0359fb5c1e7de0f46e5 --- /dev/null +++ b/prdoc/pr_7198.prdoc @@ -0,0 +1,12 @@ +title: '[pallet-revive] implement the block author API ' +doc: +- audience: Runtime Dev + description: This PR implements the block author API method. Runtimes ought to implement + it such that it corresponds to the `coinbase` EVM opcode. +crates: +- name: pallet-revive + bump: major +- name: pallet-revive-fixtures + bump: minor +- name: pallet-revive-uapi + bump: minor diff --git a/prdoc/pr_7230.prdoc b/prdoc/pr_7230.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..027694f604fe907d7781783e70698a0952e27644 --- /dev/null +++ b/prdoc/pr_7230.prdoc @@ -0,0 +1,46 @@ +title: 'revive: Include immutable storage deposit into the contracts `storage_base_deposit`' +doc: +- audience: Runtime Dev + description: |- + This PR is centered around a main fix regarding the base deposit and a bunch of drive by or related fixtures that make sense to resolve in one go. It could be broken down more but I am constantly rebasing this PR and would appreciate getting those fixes in as-one. + + ## Record the deposit for immutable data into the `storage_base_deposit` + + The `storage_base_deposit` are all the deposit a contract has to pay for existing. It included the deposit for its own metadata and a deposit proportional (< 1.0x) to the size of its code. However, the immutable code size was not recorded there. This would lead to the situation where on terminate this portion wouldn't be refunded staying locked into the contract. It would also make the calculation of the deposit changes on `set_code_hash` more complicated when it updates the immutable data (to be done in #6985). Reason is because it didn't know how much was payed before since the storage prices could have changed in the mean time. + + In order for this solution to work I needed to delay the deposit calculation for a new contract for after the contract is done executing is constructor as only then we know the immutable data size. Before, we just charged this eagerly in `charge_instantiate` before we execute the constructor. Now, we merely send the ED as free balance before the constructor in order to create the account. After the constructor is done we calculate the contract base deposit and charge it. This will make `set_code_hash` much easier to implement. + + As a side effect it is now legal to call `set_immutable_data` multiple times per constructor (even though I see no reason to do so). It simply overrides the immutable data with the new value. The deposit accounting will be done after the constructor returns (as mentioned above) instead of when setting the immutable data. + + ## Don't pre-charge for reading immutable data + + I noticed that we were pre-charging weight for the max allowable immutable data when reading those values and then refunding after read. This is not necessary as we know its length without reading the storage as we store it out of band in contract metadata. This makes reading it free. Less pre-charging less problems. + + ## Remove delegate locking + + Fixes #7092 + + This is also in the spirit of making #6985 easier to implement. The locking complicates `set_code_hash` as we might need to block settings the code hash when locks exist. Check #7092 for further rationale. + + ## Enforce "no terminate in constructor" eagerly + + We used to enforce this rule after the contract execution returned. Now we error out early in the host call. This makes it easier to be sure to argue that a contract info still exists (wasn't terminated) when a constructor successfully returns. All around this his just much simpler than dealing this check. + + ## Moved refcount functions to `CodeInfo` + + They never really made sense to exist on `Stack`. But now with the locking gone this makes even less sense. The refcount is stored inside `CodeInfo` to lets just move them there. + + ## Set `CodeHashLockupDepositPercent` for test runtime + + The test runtime was setting `CodeHashLockupDepositPercent` to zero. This was trivializing many code paths and excluded them from testing. I set it to `30%` which is our default value and fixed up all the tests that broke. This should give us confidence that the lockup doeposit collections properly works. + + ## Reworked the `MockExecutable` to have both a `deploy` and a `call` entry point + + This type used for testing could only have either entry points but not both. In order to fix the `immutable_data_set_overrides` I needed to a new function `add_both` to `MockExecutable` that allows to have both entry points. Make sure to make use of it in the future :) +crates: +- name: pallet-revive-fixtures + bump: patch +- name: pallet-revive + bump: patch +- name: pallet-revive-uapi + bump: major diff --git a/prdoc/pr_7254.prdoc b/prdoc/pr_7254.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..a6a6cc5f1ef535bfed37f840f87eb41d478f14d5 --- /dev/null +++ b/prdoc/pr_7254.prdoc @@ -0,0 +1,58 @@ +title: deprecate AsyncBackingParams +doc: + +- audience: [Node Dev, Runtime Dev] + description: |- + Removes all usage of the static async backing params, replacing them with dynamically computed equivalent values (based on the claim queue and scheduling lookahead). + + Adds a new runtime API for querying the scheduling lookahead value. If not present, falls back to 3 (the default value that is backwards compatible with values we have on production networks for allowed_ancestry_len) + + Also removes most code that handles async backing not yet being enabled, which includes support for collation protocol version 1 on collators, as it only worked for leaves not supporting async backing (which are none). + +crates: +- name: cumulus-relay-chain-minimal-node + bump: minor +- name: cumulus-relay-chain-rpc-interface + bump: minor +- name: polkadot-node-core-candidate-validation + bump: minor +- name: polkadot-node-core-prospective-parachains + bump: minor +- name: polkadot-node-core-provisioner + bump: minor +- name: polkadot-node-core-runtime-api + bump: minor +- name: polkadot-collator-protocol + bump: major +- name: polkadot-overseer + bump: major +- name: polkadot-node-subsystem-types + bump: major +- name: polkadot-node-subsystem-util + bump: major +- name: polkadot-primitives + bump: minor +- name: polkadot-runtime-parachains + bump: minor +- name: rococo-runtime + bump: minor +- name: westend-runtime + bump: minor +- name: cumulus-client-consensus-aura + bump: minor +- name: cumulus-relay-chain-inprocess-interface + bump: minor +- name: cumulus-relay-chain-interface + bump: major +- name: polkadot-statement-distribution + bump: major +- name: polkadot + bump: none +- name: polkadot-service + bump: minor +- name: cumulus-client-consensus-common + bump: minor +- name: cumulus-client-network + bump: minor +- name: cumulus-client-pov-recovery + bump: minor diff --git a/prdoc/pr_7318.prdoc b/prdoc/pr_7318.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..ec41b648a9c2862a7785ce244c0004f6a8871ac0 --- /dev/null +++ b/prdoc/pr_7318.prdoc @@ -0,0 +1,8 @@ +title: 'revive: Fix compilation of `uapi` crate when `unstable-hostfn` is not set' +doc: +- audience: Runtime Dev + description: This regression was introduced with some of the recent PRs. Regression + fixed and test added. +crates: +- name: pallet-revive-uapi + bump: minor diff --git a/prdoc/pr_7319.prdoc b/prdoc/pr_7319.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..d572f7e707e1f39dbfbb34d3043ec19ad51ca2e6 --- /dev/null +++ b/prdoc/pr_7319.prdoc @@ -0,0 +1,16 @@ +title: '[pallet-revive] pack exceeding syscall arguments into registers' +doc: +- audience: Runtime Dev + description: |- + This PR changes how we call runtime API methods with more than 6 arguments: They are no longer spilled to the stack but packed into registers instead. Pointers are 32 bit wide so we can pack two of them into a single 64 bit register. Since we mostly pass pointers, this technique effectively increases the number of arguments we can pass using the available registers. + + To make this work for `instantiate` too we now pass the code hash and the call data in the same buffer, akin to how the `create` family opcodes work in the EVM. The code hash is fixed in size, implying the start of the constructor call data. +crates: +- name: pallet-revive-fixtures + bump: major +- name: pallet-revive-proc-macro + bump: major +- name: pallet-revive + bump: major +- name: pallet-revive-uapi + bump: major diff --git a/prdoc/pr_7324.prdoc b/prdoc/pr_7324.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..e4fb7db781766656a6d02cf0d9bd7b7fd16bce8c --- /dev/null +++ b/prdoc/pr_7324.prdoc @@ -0,0 +1,17 @@ +title: Replace derivative dependency with derive-where +author: conr2d +topic: runtime + +doc: +- audience: Runtime Dev + description: |- + The `derivative` crate, previously used to derive basic traits for structs with + generics or enums, is no longer actively maintained. It has been replaced with + the `derive-where` crate, which offers a more straightforward syntax while + providing the same features as `derivative`. + +crates: + - name: cumulus-pallet-weight-reclaim + bump: patch + - name: staging-xcm + bump: patch diff --git a/prdoc/pr_7325.prdoc b/prdoc/pr_7325.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..788f01cb32470ab5f7a10dfc520c6dcc9f5d4310 --- /dev/null +++ b/prdoc/pr_7325.prdoc @@ -0,0 +1,11 @@ +title: '[pallet-revive] eth-rpc minor fixes' +doc: +- audience: Runtime Dev + description: |- + - Add option to specify database_url from an environment variable + - Add a test-deployment.rs rust script that can be used to test deployment and call of a contract before releasing eth-rpc + - Make evm_block non fallible so that it can return an Ok response for older blocks when the runtime API is not available + - Update subxt version to integrate changes from https://github.com/paritytech/subxt/pull/1904 +crates: +- name: pallet-revive-eth-rpc + bump: minor diff --git a/prdoc/pr_7327.prdoc b/prdoc/pr_7327.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..bb2d7a671af31781dec2fe819b2c155b52780111 --- /dev/null +++ b/prdoc/pr_7327.prdoc @@ -0,0 +1,11 @@ +title: Correctly register the weight n `set_validation_data` in `cumulus-pallet-parachain-system` + +doc: + - audience: Runtime Dev + description: | + The actual weight of the call was register as a refund, but the pre-dispatch weight is 0, + and we can't refund from 0. Now the actual weight is registered manually instead of ignored. + +crates: + - name: cumulus-pallet-parachain-system + bump: patch diff --git a/prdoc/pr_7338.prdoc b/prdoc/pr_7338.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..20948eb0d52f6e234294843f1d85e11022bc4bfb --- /dev/null +++ b/prdoc/pr_7338.prdoc @@ -0,0 +1,10 @@ +title: '[net/libp2p] Use raw `Identify` observed addresses to discover external addresses' +doc: +- audience: Node Dev + description: |- + Instead of using libp2p-provided external address candidates, susceptible to address translation issues, use litep2p-backend approach based on confirming addresses observed by multiple peers as external. + + Fixes https://github.com/paritytech/polkadot-sdk/issues/7207. +crates: +- name: sc-network + bump: major diff --git a/prdoc/pr_7359.prdoc b/prdoc/pr_7359.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..e54fcb877d1de78f153b54ce3ff740bed070e441 --- /dev/null +++ b/prdoc/pr_7359.prdoc @@ -0,0 +1,7 @@ +title: Improve `set_validation_data` error message. +doc: +- audience: Runtime Dev + description: Adds a more elaborate error message to the error that appears when `set_validation_data` is missing in a parachain block. +crates: +- name: cumulus-pallet-parachain-system + bump: patch diff --git a/prdoc/pr_7365.prdoc b/prdoc/pr_7365.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..dcee76e01c789ce2c67f714701d0725e1a59db18 --- /dev/null +++ b/prdoc/pr_7365.prdoc @@ -0,0 +1,12 @@ +title: Use checked math in frame-balances named_reserve +doc: +- audience: Runtime Dev + description: |- + This PR modifies `named_reserve()` in frame-balances to use checked math instead of defensive saturating math. + + The use of saturating math relies on the assumption that the value will always fit in `u128::MAX`. However, there is nothing preventing the implementing pallet from passing a larger value which overflows. This can happen if the implementing pallet does not validate user input and instead relies on `named_reserve()` to return an error (this saves an additional read) + + This is not a security concern, as the method will subsequently return an error thanks to `<Self as ReservableCurrency<_>>::reserve(who, value)?;`. However, the `defensive_saturating_add` will panic in `--all-features`, creating false positive crashes in fuzzing operations. +crates: +- name: pallet-balances + bump: patch diff --git a/prdoc/pr_7377.prdoc b/prdoc/pr_7377.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..1dfa88099a16e260b162227f28ac7f93ada8649c --- /dev/null +++ b/prdoc/pr_7377.prdoc @@ -0,0 +1,20 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Add missing events to nomination pool extrinsics + +doc: + - audience: [Runtime Dev, Runtime User] + description: | + Introduces events to extrinsics from `pallet_nomination_pools` that previously had none: + - `set_metadata` + - `nominate` + - `chill` + - `set_configs` + - `set_claim_permission` + +crates: +- name: pallet-nomination-pools + bump: major +- name: pallet-staking + bump: none \ No newline at end of file diff --git a/prdoc/pr_7378.prdoc b/prdoc/pr_7378.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..8754966d3e82c18cd7abfa1f4ef6065e1d5c2edf --- /dev/null +++ b/prdoc/pr_7378.prdoc @@ -0,0 +1,13 @@ +title: fix pre-dispatch PoV underweight for ParasInherent +doc: +- audience: Runtime Dev + description: |- + This should fix the error log related to PoV pre-dispatch weight being lower than post-dispatch for `ParasInherent`: + ``` + ERROR tokio-runtime-worker runtime::frame-support: Post dispatch weight is greater than pre dispatch weight. Pre dispatch weight may underestimating the actual weight. Greater post dispatch weight components are ignored. + Pre dispatch weight: Weight { ref_time: 47793353978, proof_size: 1019 }, + Post dispatch weight: Weight { ref_time: 5030321719, proof_size: 135395 } + ``` +crates: +- name: polkadot-runtime-parachains + bump: patch diff --git a/prdoc/pr_7379.prdoc b/prdoc/pr_7379.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..0bd904346d68d4e88d43170c05115be27f12231b --- /dev/null +++ b/prdoc/pr_7379.prdoc @@ -0,0 +1,13 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: "Add support for feature pallet_balances/insecure_zero_ed in benchmarks and testing" + +doc: + - audience: Runtime Dev + description: | + Currently benchmarks and tests on pallet_balances would fail when the feature insecure_zero_ed is enabled. This PR allows to run such benchmark and tests keeping into account the fact that accounts would not be deleted when their balance goes below a threshold. + +crates: + - name: pallet-balances + bump: patch diff --git a/prdoc/pr_7383.prdoc b/prdoc/pr_7383.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..bd421d73ab2025f530ebe15ed4d291fa9411533b --- /dev/null +++ b/prdoc/pr_7383.prdoc @@ -0,0 +1,12 @@ +title: Bridges small nits/improvements +doc: +- audience: Runtime Dev + description: 'This PR contains small fixes and backwards compatibility issues identified + during work on the larger PR: https://github.com/paritytech/polkadot-sdk/issues/6906.' +crates: +- name: cumulus-pallet-xcmp-queue + bump: patch +- name: pallet-xcm-bridge-hub + bump: minor +- name: bridge-hub-test-utils + bump: minor diff --git a/prdoc/pr_7414.prdoc b/prdoc/pr_7414.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..41edc1fe7cb38214c14e48f474b2eec3bd0a3dcf --- /dev/null +++ b/prdoc/pr_7414.prdoc @@ -0,0 +1,20 @@ +title: '[pallet-revive] do not trap the caller on instantiations with duplicate contracts' +doc: +- audience: Runtime Dev + description: |- + This PR changes the behavior of `instantiate` when the resulting contract address already exists (because the caller tried to instantiate the same contract with the same salt multiple times): Instead of trapping the caller, return an error code. + + Solidity allows `catch`ing this, which doesn't work if we are trapping the caller. For example, the change makes the following snippet work: + + ```Solidity + try new Foo{salt: hex"00"}() returns (Foo) { + // Instantiation was successful (contract address was free and constructor did not revert) + } catch { + // This branch is expected to be taken if the instantiation failed because of a duplicate salt + } + ``` +crates: +- name: pallet-revive + bump: major +- name: pallet-revive-uapi + bump: major diff --git a/prdoc/pr_7451.prdoc b/prdoc/pr_7451.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..dd8090cdd7cb72ea5b58eaf811e79ccba21e5dbe --- /dev/null +++ b/prdoc/pr_7451.prdoc @@ -0,0 +1,8 @@ +title: 'omni-node: Adjust manual seal parameters' +doc: +- audience: Runtime Dev + description: |- + This PR restores compatibility of older runtimes with the dev mode of omni-node. Before, runtimes built without the changes in https://github.com/paritytech/polkadot-sdk/pull/6825 were failing. +crates: +- name: polkadot-omni-node-lib + bump: patch diff --git a/prdoc/pr_7479.prdoc b/prdoc/pr_7479.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..444eaa420a4562ebe2ad0bb298b197fd83e5f036 --- /dev/null +++ b/prdoc/pr_7479.prdoc @@ -0,0 +1,9 @@ +title: 'omni-node: add offchain worker' +doc: +- audience: [ Runtime Dev, Node Dev, Node Operator ] + description: |- + Added support for offchain worker to omni-node-lib for both aura and manual seal nodes. + +crates: +- name: polkadot-omni-node-lib + bump: patch diff --git a/prdoc/pr_6463.prdoc b/prdoc/stable2412-1/pr_6463.prdoc similarity index 100% rename from prdoc/pr_6463.prdoc rename to prdoc/stable2412-1/pr_6463.prdoc diff --git a/prdoc/pr_6807.prdoc b/prdoc/stable2412-1/pr_6807.prdoc similarity index 100% rename from prdoc/pr_6807.prdoc rename to prdoc/stable2412-1/pr_6807.prdoc diff --git a/prdoc/pr_6825.prdoc b/prdoc/stable2412-1/pr_6825.prdoc similarity index 100% rename from prdoc/pr_6825.prdoc rename to prdoc/stable2412-1/pr_6825.prdoc diff --git a/prdoc/pr_6855.prdoc b/prdoc/stable2412-1/pr_6855.prdoc similarity index 100% rename from prdoc/pr_6855.prdoc rename to prdoc/stable2412-1/pr_6855.prdoc diff --git a/prdoc/pr_6971.prdoc b/prdoc/stable2412-1/pr_6971.prdoc similarity index 100% rename from prdoc/pr_6971.prdoc rename to prdoc/stable2412-1/pr_6971.prdoc diff --git a/prdoc/pr_6973.prdoc b/prdoc/stable2412-1/pr_6973.prdoc similarity index 100% rename from prdoc/pr_6973.prdoc rename to prdoc/stable2412-1/pr_6973.prdoc diff --git a/prdoc/pr_7013.prdoc b/prdoc/stable2412-1/pr_7013.prdoc similarity index 100% rename from prdoc/pr_7013.prdoc rename to prdoc/stable2412-1/pr_7013.prdoc diff --git a/prdoc/pr_7028.prdoc b/prdoc/stable2412-1/pr_7028.prdoc similarity index 100% rename from prdoc/pr_7028.prdoc rename to prdoc/stable2412-1/pr_7028.prdoc diff --git a/prdoc/pr_7050.prdoc b/prdoc/stable2412-1/pr_7050.prdoc similarity index 100% rename from prdoc/pr_7050.prdoc rename to prdoc/stable2412-1/pr_7050.prdoc diff --git a/prdoc/stable2412-1/pr_7067.prdoc b/prdoc/stable2412-1/pr_7067.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..ead918fc2e0077ef4972075705e1e0cc10447cc4 --- /dev/null +++ b/prdoc/stable2412-1/pr_7067.prdoc @@ -0,0 +1,25 @@ +title: 'Fix implication order in implementation of `TransactionExtension` for tuple' +doc: +- audience: + - Runtime Dev + - Runtime User + description: |- + Before this PR, the implications were different in the pipeline `(A, B, C)` and `((A, B), C)`. + This PR fixes this behavior and make nested tuple transparant, the implication order of tuple of + tuple is now the same as in a single tuple. + + For runtime users this mean that the implication can be breaking depending on the pipeline used + in the runtime. + + For runtime developers this breaks usage of `TransactionExtension::validate`. + When calling `TransactionExtension::validate` the implication must now implement `Implication` + trait, you can use `TxBaseImplication` to wrap the type and use it as the base implication. + E.g. instead of `&(extension_version, call),` you can write `&TxBaseImplication((extension_version, call))`. + +crates: +- name: sp-runtime + bump: major +- name: pallet-skip-feeless-payment + bump: major +- name: frame-system + bump: major diff --git a/prdoc/pr_7074.prdoc b/prdoc/stable2412-1/pr_7074.prdoc similarity index 100% rename from prdoc/pr_7074.prdoc rename to prdoc/stable2412-1/pr_7074.prdoc diff --git a/prdoc/stable2412-1/pr_7090.prdoc b/prdoc/stable2412-1/pr_7090.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..a665115ce6c72ab2e147538018bbc33ee14820e9 --- /dev/null +++ b/prdoc/stable2412-1/pr_7090.prdoc @@ -0,0 +1,16 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Snowbridge - Support bridging native ETH + +doc: + - audience: Runtime User + description: + Support Native ETH as an asset type instead of only supporting WETH. WETH is still supported, but adds + support for ETH in the inbound and outbound routers. + +crates: + - name: snowbridge-router-primitives + bump: minor + - name: snowbridge-pallet-inbound-queue-fixtures + bump: minor diff --git a/prdoc/pr_7099.prdoc b/prdoc/stable2412-1/pr_7099.prdoc similarity index 100% rename from prdoc/pr_7099.prdoc rename to prdoc/stable2412-1/pr_7099.prdoc diff --git a/prdoc/pr_7116.prdoc b/prdoc/stable2412-1/pr_7116.prdoc similarity index 100% rename from prdoc/pr_7116.prdoc rename to prdoc/stable2412-1/pr_7116.prdoc diff --git a/prdoc/pr_7133.prdoc b/prdoc/stable2412-1/pr_7133.prdoc similarity index 100% rename from prdoc/pr_7133.prdoc rename to prdoc/stable2412-1/pr_7133.prdoc diff --git a/prdoc/pr_7158.prdoc b/prdoc/stable2412-1/pr_7158.prdoc similarity index 100% rename from prdoc/pr_7158.prdoc rename to prdoc/stable2412-1/pr_7158.prdoc diff --git a/prdoc/pr_7205.prdoc b/prdoc/stable2412-1/pr_7205.prdoc similarity index 100% rename from prdoc/pr_7205.prdoc rename to prdoc/stable2412-1/pr_7205.prdoc diff --git a/prdoc/pr_7222.prdoc b/prdoc/stable2412-1/pr_7222.prdoc similarity index 100% rename from prdoc/pr_7222.prdoc rename to prdoc/stable2412-1/pr_7222.prdoc diff --git a/prdoc/stable2412-1/pr_7322.prdoc b/prdoc/stable2412-1/pr_7322.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..72c566f7a8146a3ecb52c95168fecf5c98317b8c --- /dev/null +++ b/prdoc/stable2412-1/pr_7322.prdoc @@ -0,0 +1,8 @@ +title: 'Bridges: emulated tests small nits/improvements' +doc: +- audience: Runtime Dev + description: |- + This PR removes the use of `open_bridge_between_asset_hub_rococo_and_asset_hub_westend`. This function was used in the generic `test_dry_run_transfer_across_pk_bridge` macro, which could cause compilation issues when used in other contexts (e.g. fellows repo). +crates: +- name: emulated-integration-tests-common + bump: patch diff --git a/prdoc/stable2412-1/pr_7344.prdoc b/prdoc/stable2412-1/pr_7344.prdoc new file mode 100644 index 0000000000000000000000000000000000000000..a3ffa32f125c3729af09ab6037fd0dbb0e28d12d --- /dev/null +++ b/prdoc/stable2412-1/pr_7344.prdoc @@ -0,0 +1,14 @@ +title: '[sync] Let new subscribers know about already connected peers (backward-compatible)' +doc: +- audience: Node Dev + description: Revert https://github.com/paritytech/polkadot-sdk/pull/7011 and replace + it with a backward-compatible solution suitable for backporting to a release branch. +crates: +- name: sc-network-gossip + bump: patch +- name: sc-network-statement + bump: patch +- name: sc-network-sync + bump: patch +- name: sc-network-transactions + bump: patch diff --git a/substrate/.maintain/frame-umbrella-weight-template.hbs b/substrate/.maintain/frame-umbrella-weight-template.hbs index b174823b38403028af697d9c7103c0108201e74a..050e74a16d7e7a8163e4cd08f1f3d5bcbcd36582 100644 --- a/substrate/.maintain/frame-umbrella-weight-template.hbs +++ b/substrate/.maintain/frame-umbrella-weight-template.hbs @@ -16,6 +16,7 @@ #![allow(unused_parens)] #![allow(unused_imports)] #![allow(missing_docs)] +#[allow(dead_code)] use frame::weights_prelude::*; diff --git a/substrate/.maintain/frame-weight-template.hbs b/substrate/.maintain/frame-weight-template.hbs index ec9eee205cee37b534eca5187ece031daa54dd99..541f064850a71c9dc06497612991daf0063c4ced 100644 --- a/substrate/.maintain/frame-weight-template.hbs +++ b/substrate/.maintain/frame-weight-template.hbs @@ -16,6 +16,7 @@ #![allow(unused_parens)] #![allow(unused_imports)] #![allow(missing_docs)] +#[allow(dead_code)] use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; diff --git a/substrate/bin/node/cli/Cargo.toml b/substrate/bin/node/cli/Cargo.toml index 9e063ee3cde0f231ea353691c4998eeeb4c3b744..7b355074823c3dd17d1414205d9b8d4cd47e945c 100644 --- a/substrate/bin/node/cli/Cargo.toml +++ b/substrate/bin/node/cli/Cargo.toml @@ -144,7 +144,6 @@ assert_cmd = { workspace = true } criterion = { features = ["async_tokio"], workspace = true, default-features = true } futures = { workspace = true } nix = { features = ["signal"], workspace = true } -platforms = { workspace = true } pretty_assertions.workspace = true regex = { workspace = true } scale-info = { features = ["derive", "serde"], workspace = true, default-features = true } diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index 220929fdfd838532a84ef5d2256c562666583672..6b9080c773a0473727316243c6cc7e50100f54f1 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -1495,6 +1495,7 @@ impl pallet_revive::Config for Runtime { type ChainId = ConstU64<420_420_420>; type NativeToEthRatio = ConstU32<1_000_000>; // 10^(18 - 12) Eth is 10^18, Native is 10^12. type EthGasEncoder = (); + type FindAuthor = <Runtime as pallet_authorship::Config>::FindAuthor; } impl pallet_sudo::Config for Runtime { @@ -2459,7 +2460,8 @@ mod runtime { RuntimeHoldReason, RuntimeSlashReason, RuntimeLockId, - RuntimeTask + RuntimeTask, + RuntimeViewFunction )] pub struct Runtime; @@ -3013,6 +3015,12 @@ impl_runtime_apis! { } } + impl frame_support::view_functions::runtime_api::RuntimeViewFunction<Block> for Runtime { + fn execute_view_function(id: frame_support::view_functions::ViewFunctionId, input: Vec<u8>) -> Result<Vec<u8>, frame_support::view_functions::ViewFunctionDispatchError> { + Runtime::execute_view_function(id, input) + } + } + impl sp_block_builder::BlockBuilder<Block> for Runtime { fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult { Executive::apply_extrinsic(extrinsic) diff --git a/substrate/client/api/Cargo.toml b/substrate/client/api/Cargo.toml index fe961b4690fc69950baca77e9344e669c620ac90..dede50fc01e8cacec8063fb1b3fdeca8d29c381a 100644 --- a/substrate/client/api/Cargo.toml +++ b/substrate/client/api/Cargo.toml @@ -41,6 +41,5 @@ sp-storage = { workspace = true, default-features = true } sp-trie = { workspace = true, default-features = true } [dev-dependencies] -sp-test-primitives = { workspace = true } substrate-test-runtime = { workspace = true } thiserror = { workspace = true } diff --git a/substrate/client/db/Cargo.toml b/substrate/client/db/Cargo.toml index 7e02558e007c8bb901af7dc69389dec68e63cd51..9268ccf8a0645018126f1fb486da99daf78ef539 100644 --- a/substrate/client/db/Cargo.toml +++ b/substrate/client/db/Cargo.toml @@ -43,7 +43,6 @@ array-bytes = { workspace = true, default-features = true } criterion = { workspace = true, default-features = true } kitchensink-runtime = { workspace = true } kvdb-rocksdb = { workspace = true } -quickcheck = { workspace = true } rand = { workspace = true, default-features = true } sp-tracing = { workspace = true, default-features = true } substrate-test-runtime-client = { workspace = true } diff --git a/substrate/client/network-gossip/src/bridge.rs b/substrate/client/network-gossip/src/bridge.rs index bff258a9a011bbf9cb6b1bcee319044f54b830de..2daf1e49ee4b49c0e45f3efd0baeef1488b319c6 100644 --- a/substrate/client/network-gossip/src/bridge.rs +++ b/substrate/client/network-gossip/src/bridge.rs @@ -254,12 +254,10 @@ impl<B: BlockT> Future for GossipEngine<B> { match sync_event_stream { Poll::Ready(Some(event)) => match event { - SyncEvent::InitialPeers(peer_ids) => - this.network.add_set_reserved(peer_ids, this.protocol.clone()), - SyncEvent::PeerConnected(peer_id) => - this.network.add_set_reserved(vec![peer_id], this.protocol.clone()), - SyncEvent::PeerDisconnected(peer_id) => - this.network.remove_set_reserved(peer_id, this.protocol.clone()), + SyncEvent::PeerConnected(remote) => + this.network.add_set_reserved(remote, this.protocol.clone()), + SyncEvent::PeerDisconnected(remote) => + this.network.remove_set_reserved(remote, this.protocol.clone()), }, // The sync event stream closed. Do the same for [`GossipValidator`]. Poll::Ready(None) => { diff --git a/substrate/client/network-gossip/src/lib.rs b/substrate/client/network-gossip/src/lib.rs index 2ec573bf9e3ef8056f6fc6309110aa26d7e7e44b..20d9922200c2c3c6cf394692099a21c01b540bd0 100644 --- a/substrate/client/network-gossip/src/lib.rs +++ b/substrate/client/network-gossip/src/lib.rs @@ -82,18 +82,15 @@ mod validator; /// Abstraction over a network. pub trait Network<B: BlockT>: NetworkPeers + NetworkEventStream { - fn add_set_reserved(&self, peer_ids: Vec<PeerId>, protocol: ProtocolName) { - let addrs = peer_ids - .into_iter() - .map(|peer_id| Multiaddr::empty().with(Protocol::P2p(peer_id.into()))) - .collect(); - let result = self.add_peers_to_reserved_set(protocol, addrs); + fn add_set_reserved(&self, who: PeerId, protocol: ProtocolName) { + let addr = Multiaddr::empty().with(Protocol::P2p(*who.as_ref())); + let result = self.add_peers_to_reserved_set(protocol, iter::once(addr).collect()); if let Err(err) = result { log::error!(target: "gossip", "add_set_reserved failed: {}", err); } } - fn remove_set_reserved(&self, peer_id: PeerId, protocol: ProtocolName) { - let result = self.remove_peers_from_reserved_set(protocol, iter::once(peer_id).collect()); + fn remove_set_reserved(&self, who: PeerId, protocol: ProtocolName) { + let result = self.remove_peers_from_reserved_set(protocol, iter::once(who).collect()); if let Err(err) = result { log::error!(target: "gossip", "remove_set_reserved failed: {}", err); } diff --git a/substrate/client/network/common/Cargo.toml b/substrate/client/network/common/Cargo.toml index cd1bc1cfe8eb84454c17cb8f27ebdb2652b473a3..30407423da29aa6a7b122af215171bda50d42fb7 100644 --- a/substrate/client/network/common/Cargo.toml +++ b/substrate/client/network/common/Cargo.toml @@ -19,17 +19,11 @@ targets = ["x86_64-unknown-linux-gnu"] prost-build = { workspace = true } [dependencies] -async-trait = { workspace = true } bitflags = { workspace = true } codec = { features = [ "derive", ], workspace = true, default-features = true } futures = { workspace = true } -libp2p-identity = { features = ["peerid"], workspace = true } -sc-consensus = { workspace = true, default-features = true } -sc-network-types = { workspace = true, default-features = true } -sp-consensus = { workspace = true, default-features = true } -sp-consensus-grandpa = { workspace = true, default-features = true } sp-runtime = { workspace = true, default-features = true } [dev-dependencies] diff --git a/substrate/client/network/src/behaviour.rs b/substrate/client/network/src/behaviour.rs index e2a91e96166884df9626fc17c716f57a580194ec..0f6b1ab3450785bf0e41a727ead8a71491a88979 100644 --- a/substrate/client/network/src/behaviour.rs +++ b/substrate/client/network/src/behaviour.rs @@ -184,6 +184,7 @@ impl<B: BlockT> Behaviour<B> { request_response_protocols: Vec<ProtocolConfig>, peer_store_handle: Arc<dyn PeerStoreProvider>, external_addresses: Arc<Mutex<HashSet<Multiaddr>>>, + public_addresses: Vec<Multiaddr>, connection_limits: ConnectionLimits, ) -> Result<Self, request_responses::RegisterError> { Ok(Self { @@ -192,6 +193,7 @@ impl<B: BlockT> Behaviour<B> { user_agent, local_public_key, external_addresses, + public_addresses, ), discovery: disco_config.finish(), request_responses: request_responses::RequestResponsesBehaviour::new( diff --git a/substrate/client/network/src/lib.rs b/substrate/client/network/src/lib.rs index 9300cbccc9ad3054d9e8b3cdf0c5fa4801adece6..f19c4dd2191a1a4cd00ec0329efbe475910a361c 100644 --- a/substrate/client/network/src/lib.rs +++ b/substrate/client/network/src/lib.rs @@ -291,6 +291,9 @@ pub use service::{ }; pub use types::ProtocolName; +/// Log target for `sc-network`. +const LOG_TARGET: &str = "sub-libp2p"; + /// The maximum allowed number of established connections per peer. /// /// Typically, and by design of the network behaviours in this crate, diff --git a/substrate/client/network/src/litep2p/discovery.rs b/substrate/client/network/src/litep2p/discovery.rs index eb571804f30e61841ace4f985fe7a439bd9a43b7..48ec0684e763c1a0fe83f5083918e5108d06e35d 100644 --- a/substrate/client/network/src/litep2p/discovery.rs +++ b/substrate/client/network/src/litep2p/discovery.rs @@ -50,6 +50,7 @@ use schnellru::{ByLength, LruMap}; use std::{ cmp, collections::{HashMap, HashSet, VecDeque}, + iter, num::NonZeroUsize, pin::Pin, sync::Arc, @@ -72,11 +73,9 @@ const GET_RECORD_REDUNDANCY_FACTOR: usize = 4; /// The maximum number of tracked external addresses we allow. const MAX_EXTERNAL_ADDRESSES: u32 = 32; -/// Minimum number of confirmations received before an address is verified. -/// -/// Note: all addresses are confirmed by libp2p on the first encounter. This aims to make -/// addresses a bit more robust. -const MIN_ADDRESS_CONFIRMATIONS: usize = 2; +/// Number of times observed address is received from different peers before it is confirmed as +/// external. +const MIN_ADDRESS_CONFIRMATIONS: usize = 3; /// Discovery events. #[derive(Debug)] @@ -509,7 +508,7 @@ impl Discovery { .flatten() .flatten(); - self.address_confirmations.insert(address.clone(), Default::default()); + self.address_confirmations.insert(address.clone(), iter::once(peer).collect()); return (false, oldest) }, diff --git a/substrate/client/network/src/peer_info.rs b/substrate/client/network/src/peer_info.rs index a673f06fd62254dba8c35ac3f4dad50a3e65c24b..29544b8be70aad018a3e28e17e8fdc119e5654d6 100644 --- a/substrate/client/network/src/peer_info.rs +++ b/substrate/client/network/src/peer_info.rs @@ -19,7 +19,7 @@ //! [`PeerInfoBehaviour`] is implementation of `NetworkBehaviour` that holds information about peers //! in cache. -use crate::utils::interval; +use crate::{utils::interval, LOG_TARGET}; use either::Either; use fnv::FnvHashMap; @@ -31,24 +31,26 @@ use libp2p::{ Info as IdentifyInfo, }, identity::PublicKey, + multiaddr::Protocol, ping::{Behaviour as Ping, Config as PingConfig, Event as PingEvent}, swarm::{ behaviour::{ - AddressChange, ConnectionClosed, ConnectionEstablished, DialFailure, - ExternalAddrConfirmed, FromSwarm, ListenFailure, + AddressChange, ConnectionClosed, ConnectionEstablished, DialFailure, FromSwarm, + ListenFailure, }, ConnectionDenied, ConnectionHandler, ConnectionHandlerSelect, ConnectionId, - NetworkBehaviour, NewExternalAddrCandidate, THandler, THandlerInEvent, THandlerOutEvent, - ToSwarm, + NetworkBehaviour, THandler, THandlerInEvent, THandlerOutEvent, ToSwarm, }, Multiaddr, PeerId, }; -use log::{debug, error, trace}; +use log::{debug, error, trace, warn}; use parking_lot::Mutex; +use schnellru::{ByLength, LruMap}; use smallvec::SmallVec; use std::{ collections::{hash_map::Entry, HashSet, VecDeque}, + iter, pin::Pin, sync::Arc, task::{Context, Poll}, @@ -59,6 +61,11 @@ use std::{ const CACHE_EXPIRE: Duration = Duration::from_secs(10 * 60); /// Interval at which we perform garbage collection on the node info. const GARBAGE_COLLECT_INTERVAL: Duration = Duration::from_secs(2 * 60); +/// The maximum number of tracked external addresses we allow. +const MAX_EXTERNAL_ADDRESSES: u32 = 32; +/// Number of times observed address is received from different peers before it is confirmed as +/// external. +const MIN_ADDRESS_CONFIRMATIONS: usize = 3; /// Implementation of `NetworkBehaviour` that holds information about peers in cache. pub struct PeerInfoBehaviour { @@ -70,7 +77,16 @@ pub struct PeerInfoBehaviour { nodes_info: FnvHashMap<PeerId, NodeInfo>, /// Interval at which we perform garbage collection in `nodes_info`. garbage_collect: Pin<Box<dyn Stream<Item = ()> + Send>>, + /// PeerId of the local node. + local_peer_id: PeerId, + /// Public addresses supplied by the operator. Never expire. + public_addresses: Vec<Multiaddr>, + /// Listen addresses. External addresses matching listen addresses never expire. + listen_addresses: HashSet<Multiaddr>, + /// External address confirmations. + address_confirmations: LruMap<Multiaddr, HashSet<PeerId>>, /// Record keeping of external addresses. Data is queried by the `NetworkService`. + /// The addresses contain the `/p2p/...` part with local peer ID. external_addresses: ExternalAddresses, /// Pending events to emit to [`Swarm`](libp2p::swarm::Swarm). pending_actions: VecDeque<ToSwarm<PeerInfoEvent, THandlerInEvent<PeerInfoBehaviour>>>, @@ -106,13 +122,13 @@ pub struct ExternalAddresses { impl ExternalAddresses { /// Add an external address. - pub fn add(&mut self, addr: Multiaddr) { - self.addresses.lock().insert(addr); + pub fn add(&mut self, addr: Multiaddr) -> bool { + self.addresses.lock().insert(addr) } /// Remove an external address. - pub fn remove(&mut self, addr: &Multiaddr) { - self.addresses.lock().remove(addr); + pub fn remove(&mut self, addr: &Multiaddr) -> bool { + self.addresses.lock().remove(addr) } } @@ -122,9 +138,10 @@ impl PeerInfoBehaviour { user_agent: String, local_public_key: PublicKey, external_addresses: Arc<Mutex<HashSet<Multiaddr>>>, + public_addresses: Vec<Multiaddr>, ) -> Self { let identify = { - let cfg = IdentifyConfig::new("/substrate/1.0".to_string(), local_public_key) + let cfg = IdentifyConfig::new("/substrate/1.0".to_string(), local_public_key.clone()) .with_agent_version(user_agent) // We don't need any peer information cached. .with_cache_size(0); @@ -136,6 +153,10 @@ impl PeerInfoBehaviour { identify, nodes_info: FnvHashMap::default(), garbage_collect: Box::pin(interval(GARBAGE_COLLECT_INTERVAL)), + local_peer_id: local_public_key.to_peer_id(), + public_addresses, + listen_addresses: HashSet::new(), + address_confirmations: LruMap::new(ByLength::new(MAX_EXTERNAL_ADDRESSES)), external_addresses: ExternalAddresses { addresses: external_addresses }, pending_actions: Default::default(), } @@ -158,25 +179,137 @@ impl PeerInfoBehaviour { ping_time: Duration, connection: ConnectionId, ) { - trace!(target: "sub-libp2p", "Ping time with {:?} via {:?}: {:?}", peer_id, connection, ping_time); + trace!(target: LOG_TARGET, "Ping time with {:?} via {:?}: {:?}", peer_id, connection, ping_time); if let Some(entry) = self.nodes_info.get_mut(peer_id) { entry.latest_ping = Some(ping_time); } else { - error!(target: "sub-libp2p", + error!(target: LOG_TARGET, "Received ping from node we're not connected to {:?} via {:?}", peer_id, connection); } } - /// Inserts an identify record in the cache. Has no effect if we don't have any entry for that - /// node, which shouldn't happen. + /// Ensure address has the `/p2p/...` part with local peer id. Returns `Err` if the address + /// already contains a different peer id. + fn with_local_peer_id(&self, address: Multiaddr) -> Result<Multiaddr, Multiaddr> { + if let Some(Protocol::P2p(peer_id)) = address.iter().last() { + if peer_id == self.local_peer_id { + Ok(address) + } else { + Err(address) + } + } else { + Ok(address.with(Protocol::P2p(self.local_peer_id))) + } + } + + /// Inserts an identify record in the cache & discovers external addresses when multiple + /// peers report the same address as observed. fn handle_identify_report(&mut self, peer_id: &PeerId, info: &IdentifyInfo) { - trace!(target: "sub-libp2p", "Identified {:?} => {:?}", peer_id, info); + trace!(target: LOG_TARGET, "Identified {:?} => {:?}", peer_id, info); if let Some(entry) = self.nodes_info.get_mut(peer_id) { entry.client_version = Some(info.agent_version.clone()); } else { - error!(target: "sub-libp2p", - "Received pong from node we're not connected to {:?}", peer_id); + error!(target: LOG_TARGET, + "Received identify message from node we're not connected to {peer_id:?}"); + } + // Discover external addresses. + match self.with_local_peer_id(info.observed_addr.clone()) { + Ok(observed_addr) => { + let (is_new, expired) = self.is_new_external_address(&observed_addr, *peer_id); + if is_new && self.external_addresses.add(observed_addr.clone()) { + trace!( + target: LOG_TARGET, + "Observed address reported by Identify confirmed as external {}", + observed_addr, + ); + self.pending_actions.push_back(ToSwarm::ExternalAddrConfirmed(observed_addr)); + } + if let Some(expired) = expired { + trace!(target: LOG_TARGET, "Removing replaced external address: {expired}"); + self.external_addresses.remove(&expired); + self.pending_actions.push_back(ToSwarm::ExternalAddrExpired(expired)); + } + }, + Err(addr) => { + warn!( + target: LOG_TARGET, + "Identify reported observed address for a peer that is not us: {addr}", + ); + }, + } + } + + /// Check if addresses are equal taking into account they can contain or not contain + /// the `/p2p/...` part. + fn is_same_address(left: &Multiaddr, right: &Multiaddr) -> bool { + let mut left = left.iter(); + let mut right = right.iter(); + + loop { + match (left.next(), right.next()) { + (None, None) => return true, + (None, Some(Protocol::P2p(_))) => return true, + (Some(Protocol::P2p(_)), None) => return true, + (left, right) if left != right => return false, + _ => {}, + } + } + } + + /// Check if `address` can be considered a new external address. + /// + /// If this address replaces an older address, the expired address is returned. + fn is_new_external_address( + &mut self, + address: &Multiaddr, + peer_id: PeerId, + ) -> (bool, Option<Multiaddr>) { + trace!(target: LOG_TARGET, "Verify new external address: {address}"); + + // Public and listen addresses don't count towards discovered external addresses + // and are always confirmed. + // Because they are not kept in the LRU, they are never replaced by discovered + // external addresses. + if self + .listen_addresses + .iter() + .chain(self.public_addresses.iter()) + .any(|known_address| PeerInfoBehaviour::is_same_address(&known_address, &address)) + { + return (true, None) } + + match self.address_confirmations.get(address) { + Some(confirmations) => { + confirmations.insert(peer_id); + + if confirmations.len() >= MIN_ADDRESS_CONFIRMATIONS { + return (true, None) + } + }, + None => { + let oldest = (self.address_confirmations.len() >= + self.address_confirmations.limiter().max_length() as usize) + .then(|| { + self.address_confirmations.pop_oldest().map(|(address, peers)| { + if peers.len() >= MIN_ADDRESS_CONFIRMATIONS { + return Some(address) + } else { + None + } + }) + }) + .flatten() + .flatten(); + + self.address_confirmations + .insert(address.clone(), iter::once(peer_id).collect()); + + return (false, oldest) + }, + } + + (false, None) } } @@ -346,7 +479,7 @@ impl NetworkBehaviour for PeerInfoBehaviour { } entry.endpoints.retain(|ep| ep != endpoint) } else { - error!(target: "sub-libp2p", + error!(target: LOG_TARGET, "Unknown connection to {:?} closed: {:?}", peer_id, endpoint); } }, @@ -400,28 +533,36 @@ impl NetworkBehaviour for PeerInfoBehaviour { self.ping.on_swarm_event(FromSwarm::NewListener(e)); self.identify.on_swarm_event(FromSwarm::NewListener(e)); }, + FromSwarm::NewListenAddr(e) => { + self.ping.on_swarm_event(FromSwarm::NewListenAddr(e)); + self.identify.on_swarm_event(FromSwarm::NewListenAddr(e)); + self.listen_addresses.insert(e.addr.clone()); + }, FromSwarm::ExpiredListenAddr(e) => { self.ping.on_swarm_event(FromSwarm::ExpiredListenAddr(e)); self.identify.on_swarm_event(FromSwarm::ExpiredListenAddr(e)); - self.external_addresses.remove(e.addr); + self.listen_addresses.remove(e.addr); + // Remove matching external address. + match self.with_local_peer_id(e.addr.clone()) { + Ok(addr) => { + self.external_addresses.remove(&addr); + self.pending_actions.push_back(ToSwarm::ExternalAddrExpired(addr)); + }, + Err(addr) => { + warn!( + target: LOG_TARGET, + "Listen address expired with peer ID that is not us: {addr}", + ); + }, + } }, - FromSwarm::NewExternalAddrCandidate(e @ NewExternalAddrCandidate { addr }) => { + FromSwarm::NewExternalAddrCandidate(e) => { self.ping.on_swarm_event(FromSwarm::NewExternalAddrCandidate(e)); self.identify.on_swarm_event(FromSwarm::NewExternalAddrCandidate(e)); - - // Manually confirm all external address candidates. - // TODO: consider adding [AutoNAT protocol](https://docs.rs/libp2p/0.52.3/libp2p/autonat/index.html) - // (must go through the polkadot protocol spec) or implemeting heuristics for - // approving external address candidates. This can be done, for example, by - // approving only addresses reported by multiple peers. - // See also https://github.com/libp2p/rust-libp2p/pull/4721 introduced - // in libp2p v0.53 for heuristics approach. - self.pending_actions.push_back(ToSwarm::ExternalAddrConfirmed(addr.clone())); }, - FromSwarm::ExternalAddrConfirmed(e @ ExternalAddrConfirmed { addr }) => { + FromSwarm::ExternalAddrConfirmed(e) => { self.ping.on_swarm_event(FromSwarm::ExternalAddrConfirmed(e)); self.identify.on_swarm_event(FromSwarm::ExternalAddrConfirmed(e)); - self.external_addresses.add(addr.clone()); }, FromSwarm::AddressChange(e @ AddressChange { peer_id, old, new, .. }) => { self.ping.on_swarm_event(FromSwarm::AddressChange(e)); @@ -431,20 +572,16 @@ impl NetworkBehaviour for PeerInfoBehaviour { if let Some(endpoint) = entry.endpoints.iter_mut().find(|e| e == &old) { *endpoint = new.clone(); } else { - error!(target: "sub-libp2p", + error!(target: LOG_TARGET, "Unknown address change for peer {:?} from {:?} to {:?}", peer_id, old, new); } } else { - error!(target: "sub-libp2p", + error!(target: LOG_TARGET, "Unknown peer {:?} to change address from {:?} to {:?}", peer_id, old, new); } }, - FromSwarm::NewListenAddr(e) => { - self.ping.on_swarm_event(FromSwarm::NewListenAddr(e)); - self.identify.on_swarm_event(FromSwarm::NewListenAddr(e)); - }, event => { - debug!(target: "sub-libp2p", "New unknown `FromSwarm` libp2p event: {event:?}"); + debug!(target: LOG_TARGET, "New unknown `FromSwarm` libp2p event: {event:?}"); self.ping.on_swarm_event(event); self.identify.on_swarm_event(event); }, @@ -497,7 +634,7 @@ impl NetworkBehaviour for PeerInfoBehaviour { }, IdentifyEvent::Error { connection_id, peer_id, error } => { debug!( - target: "sub-libp2p", + target: LOG_TARGET, "Identification with peer {peer_id:?}({connection_id}) failed => {error}" ); }, diff --git a/substrate/client/network/src/protocol/message.rs b/substrate/client/network/src/protocol/message.rs index 5f2511fd6ddc93d4ef2018b43d7be9e3d138ba32..e9dc57a79356cb2813b7161b3b61140bccacd066 100644 --- a/substrate/client/network/src/protocol/message.rs +++ b/substrate/client/network/src/protocol/message.rs @@ -22,16 +22,6 @@ use codec::{Decode, Encode}; use sc_client_api::StorageProof; use sc_network_common::message::RequestId; -use sp_runtime::traits::{Block as BlockT, Header as HeaderT}; - -/// Type alias for using the message type using block type parameters. -#[allow(unused)] -pub type Message<B> = generic::Message< - <B as BlockT>::Header, - <B as BlockT>::Hash, - <<B as BlockT>::Header as HeaderT>::Number, - <B as BlockT>::Extrinsic, ->; /// Remote call response. #[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] @@ -53,17 +43,9 @@ pub struct RemoteReadResponse { /// Generic types. pub mod generic { - use super::{RemoteCallResponse, RemoteReadResponse}; use codec::{Decode, Encode, Input}; use sc_client_api::StorageProof; - use sc_network_common::{ - message::RequestId, - role::Roles, - sync::message::{ - generic::{BlockRequest, BlockResponse}, - BlockAnnounce, - }, - }; + use sc_network_common::{message::RequestId, role::Roles}; use sp_runtime::ConsensusEngineId; /// Consensus is mostly opaque to us @@ -75,47 +57,6 @@ pub mod generic { pub data: Vec<u8>, } - /// A network message. - #[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] - pub enum Message<Header, Hash, Number, Extrinsic> { - /// Status packet. - Status(Status<Hash, Number>), - /// Block request. - BlockRequest(BlockRequest<Hash, Number>), - /// Block response. - BlockResponse(BlockResponse<Header, Hash, Extrinsic>), - /// Block announce. - BlockAnnounce(BlockAnnounce<Header>), - /// Consensus protocol message. - // NOTE: index is incremented by 1 due to transaction-related - // message that was removed - #[codec(index = 6)] - Consensus(ConsensusMessage), - /// Remote method call request. - RemoteCallRequest(RemoteCallRequest<Hash>), - /// Remote method call response. - RemoteCallResponse(RemoteCallResponse), - /// Remote storage read request. - RemoteReadRequest(RemoteReadRequest<Hash>), - /// Remote storage read response. - RemoteReadResponse(RemoteReadResponse), - /// Remote header request. - RemoteHeaderRequest(RemoteHeaderRequest<Number>), - /// Remote header response. - RemoteHeaderResponse(RemoteHeaderResponse<Header>), - /// Remote changes request. - RemoteChangesRequest(RemoteChangesRequest<Hash>), - /// Remote changes response. - RemoteChangesResponse(RemoteChangesResponse<Number, Hash>), - /// Remote child storage read request. - RemoteReadChildRequest(RemoteReadChildRequest<Hash>), - /// Batch of consensus protocol messages. - // NOTE: index is incremented by 2 due to finality proof related - // messages that were removed. - #[codec(index = 17)] - ConsensusBatch(Vec<ConsensusMessage>), - } - /// Status sent on connection. // TODO https://github.com/paritytech/substrate/issues/4674: replace the `Status` // struct with this one, after waiting a few releases beyond `NetworkSpecialization`'s diff --git a/substrate/client/network/src/service.rs b/substrate/client/network/src/service.rs index 751183ae19a9d98eb0236d7568dcc59d1b02dacb..b4463ad480891eafe40199d9ff7c5ef23a111681 100644 --- a/substrate/client/network/src/service.rs +++ b/substrate/client/network/src/service.rs @@ -516,6 +516,7 @@ where request_response_protocols, Arc::clone(&peer_store_handle), external_addresses.clone(), + network_config.public_addresses.iter().cloned().map(Into::into).collect(), ConnectionLimits::default() .with_max_established_per_peer(Some(crate::MAX_CONNECTIONS_PER_PEER as u32)) .with_max_established_incoming(Some( diff --git a/substrate/client/network/statement/src/lib.rs b/substrate/client/network/statement/src/lib.rs index 586a15cadd68eeb8d0615c01c7bbf33177a5113a..df93788696e381b18e80cff73646bb1594636386 100644 --- a/substrate/client/network/statement/src/lib.rs +++ b/substrate/client/network/statement/src/lib.rs @@ -33,8 +33,7 @@ use futures::{channel::oneshot, prelude::*, stream::FuturesUnordered, FutureExt} use prometheus_endpoint::{register, Counter, PrometheusError, Registry, U64}; use sc_network::{ config::{NonReservedPeerMode, SetConfig}, - error, - multiaddr::{Multiaddr, Protocol}, + error, multiaddr, peer_store::PeerStoreProvider, service::{ traits::{NotificationEvent, NotificationService, ValidationResult}, @@ -297,19 +296,9 @@ where fn handle_sync_event(&mut self, event: SyncEvent) { match event { - SyncEvent::InitialPeers(peer_ids) => { - let addrs = peer_ids - .into_iter() - .map(|peer_id| Multiaddr::empty().with(Protocol::P2p(peer_id.into()))) - .collect(); - let result = - self.network.add_peers_to_reserved_set(self.protocol_name.clone(), addrs); - if let Err(err) = result { - log::error!(target: LOG_TARGET, "Add reserved peers failed: {}", err); - } - }, - SyncEvent::PeerConnected(peer_id) => { - let addr = Multiaddr::empty().with(Protocol::P2p(peer_id.into())); + SyncEvent::PeerConnected(remote) => { + let addr = iter::once(multiaddr::Protocol::P2p(remote.into())) + .collect::<multiaddr::Multiaddr>(); let result = self.network.add_peers_to_reserved_set( self.protocol_name.clone(), iter::once(addr).collect(), @@ -318,10 +307,10 @@ where log::error!(target: LOG_TARGET, "Add reserved peer failed: {}", err); } }, - SyncEvent::PeerDisconnected(peer_id) => { + SyncEvent::PeerDisconnected(remote) => { let result = self.network.remove_peers_from_reserved_set( self.protocol_name.clone(), - iter::once(peer_id).collect(), + iter::once(remote).collect(), ); if let Err(err) = result { log::error!(target: LOG_TARGET, "Failed to remove reserved peer: {err}"); diff --git a/substrate/client/network/sync/src/engine.rs b/substrate/client/network/sync/src/engine.rs index 4003361525e18c45d73cb95c20376c337251cade..3b9c5f38329b116144e56b484cc8e8d95aa7b500 100644 --- a/substrate/client/network/sync/src/engine.rs +++ b/substrate/client/network/sync/src/engine.rs @@ -657,8 +657,10 @@ where self.strategy.set_sync_fork_request(peers, &hash, number); }, ToServiceCommand::EventStream(tx) => { - let _ = tx - .unbounded_send(SyncEvent::InitialPeers(self.peers.keys().cloned().collect())); + // Let a new subscriber know about already connected peers. + for peer_id in self.peers.keys() { + let _ = tx.unbounded_send(SyncEvent::PeerConnected(*peer_id)); + } self.event_streams.push(tx); }, ToServiceCommand::RequestJustification(hash, number) => diff --git a/substrate/client/network/sync/src/types.rs b/substrate/client/network/sync/src/types.rs index a72a2f7c1ffe475fc4c78263a0766be484af7663..5745a34378df68f65446953b55c8a0ce39f3c3d0 100644 --- a/substrate/client/network/sync/src/types.rs +++ b/substrate/client/network/sync/src/types.rs @@ -127,10 +127,6 @@ where /// Syncing-related events that other protocols can subscribe to. pub enum SyncEvent { - /// All connected peers that the syncing implementation is tracking. - /// Always sent as the first message to the stream. - InitialPeers(Vec<PeerId>), - /// Peer that the syncing implementation is tracking connected. PeerConnected(PeerId), diff --git a/substrate/client/network/transactions/src/config.rs b/substrate/client/network/transactions/src/config.rs index 239b76b51485f128f2a374575c0ffee352929e48..42a335d7041ad14363a82863238ee86f44b6e3f5 100644 --- a/substrate/client/network/transactions/src/config.rs +++ b/substrate/client/network/transactions/src/config.rs @@ -22,7 +22,7 @@ use futures::prelude::*; use sc_network::MAX_RESPONSE_SIZE; use sc_network_common::ExHashT; use sp_runtime::traits::Block as BlockT; -use std::{collections::HashMap, future::Future, pin::Pin, time}; +use std::{collections::HashMap, future::Future, pin::Pin, sync::Arc, time}; /// Interval at which we propagate transactions; pub(crate) const PROPAGATE_TIMEOUT: time::Duration = time::Duration::from_millis(2900); @@ -57,7 +57,7 @@ pub type TransactionImportFuture = Pin<Box<dyn Future<Output = TransactionImport /// Transaction pool interface pub trait TransactionPool<H: ExHashT, B: BlockT>: Send + Sync { /// Get transactions from the pool that are ready to be propagated. - fn transactions(&self) -> Vec<(H, B::Extrinsic)>; + fn transactions(&self) -> Vec<(H, Arc<B::Extrinsic>)>; /// Get hash of transaction. fn hash_of(&self, transaction: &B::Extrinsic) -> H; /// Import a transaction into the pool. @@ -67,7 +67,7 @@ pub trait TransactionPool<H: ExHashT, B: BlockT>: Send + Sync { /// Notify the pool about transactions broadcast. fn on_broadcasted(&self, propagations: HashMap<H, Vec<String>>); /// Get transaction by hash. - fn transaction(&self, hash: &H) -> Option<B::Extrinsic>; + fn transaction(&self, hash: &H) -> Option<Arc<B::Extrinsic>>; } /// Dummy implementation of the [`TransactionPool`] trait for a transaction pool that is always @@ -79,7 +79,7 @@ pub trait TransactionPool<H: ExHashT, B: BlockT>: Send + Sync { pub struct EmptyTransactionPool; impl<H: ExHashT + Default, B: BlockT> TransactionPool<H, B> for EmptyTransactionPool { - fn transactions(&self) -> Vec<(H, B::Extrinsic)> { + fn transactions(&self) -> Vec<(H, Arc<B::Extrinsic>)> { Vec::new() } @@ -93,7 +93,7 @@ impl<H: ExHashT + Default, B: BlockT> TransactionPool<H, B> for EmptyTransaction fn on_broadcasted(&self, _: HashMap<H, Vec<String>>) {} - fn transaction(&self, _h: &H) -> Option<B::Extrinsic> { + fn transaction(&self, _h: &H) -> Option<Arc<B::Extrinsic>> { None } } diff --git a/substrate/client/network/transactions/src/lib.rs b/substrate/client/network/transactions/src/lib.rs index 49f429a04ee2e61861d3871cfc042df92e23c5c0..a6a95520794592b451b8147cf3471b67853a2cb0 100644 --- a/substrate/client/network/transactions/src/lib.rs +++ b/substrate/client/network/transactions/src/lib.rs @@ -35,8 +35,7 @@ use log::{debug, trace, warn}; use prometheus_endpoint::{register, Counter, PrometheusError, Registry, U64}; use sc_network::{ config::{NonReservedPeerMode, ProtocolId, SetConfig}, - error, - multiaddr::{Multiaddr, Protocol}, + error, multiaddr, peer_store::PeerStoreProvider, service::{ traits::{NotificationEvent, NotificationService, ValidationResult}, @@ -378,19 +377,9 @@ where fn handle_sync_event(&mut self, event: SyncEvent) { match event { - SyncEvent::InitialPeers(peer_ids) => { - let addrs = peer_ids - .into_iter() - .map(|peer_id| Multiaddr::empty().with(Protocol::P2p(peer_id.into()))) - .collect(); - let result = - self.network.add_peers_to_reserved_set(self.protocol_name.clone(), addrs); - if let Err(err) = result { - log::error!(target: LOG_TARGET, "Add reserved peers failed: {}", err); - } - }, - SyncEvent::PeerConnected(peer_id) => { - let addr = Multiaddr::empty().with(Protocol::P2p(peer_id.into())); + SyncEvent::PeerConnected(remote) => { + let addr = iter::once(multiaddr::Protocol::P2p(remote.into())) + .collect::<multiaddr::Multiaddr>(); let result = self.network.add_peers_to_reserved_set( self.protocol_name.clone(), iter::once(addr).collect(), @@ -399,10 +388,10 @@ where log::error!(target: LOG_TARGET, "Add reserved peer failed: {}", err); } }, - SyncEvent::PeerDisconnected(peer_id) => { + SyncEvent::PeerDisconnected(remote) => { let result = self.network.remove_peers_from_reserved_set( self.protocol_name.clone(), - iter::once(peer_id).collect(), + iter::once(remote).collect(), ); if let Err(err) = result { log::error!(target: LOG_TARGET, "Remove reserved peer failed: {}", err); @@ -480,7 +469,7 @@ where fn do_propagate_transactions( &mut self, - transactions: &[(H, B::Extrinsic)], + transactions: &[(H, Arc<B::Extrinsic>)], ) -> HashMap<H, Vec<String>> { let mut propagated_to = HashMap::<_, Vec<_>>::new(); let mut propagated_transactions = 0; diff --git a/substrate/client/service/src/lib.rs b/substrate/client/service/src/lib.rs index 2a3144a33e1aeceb88fad2d15adf8cefb7ee48b8..52a19da220c05be35edf336c46745e496b76d06d 100644 --- a/substrate/client/service/src/lib.rs +++ b/substrate/client/service/src/lib.rs @@ -40,7 +40,7 @@ use std::{ use codec::{Decode, Encode}; use futures::{pin_mut, FutureExt, StreamExt}; use jsonrpsee::RpcModule; -use log::{debug, error, warn}; +use log::{debug, error, trace, warn}; use sc_client_api::{blockchain::HeaderBackend, BlockBackend, BlockchainEvents, ProofProvider}; use sc_network::{ config::MultiaddrWithPeerId, service::traits::NetworkService, NetworkBackend, NetworkBlock, @@ -474,7 +474,7 @@ impl<C, P> TransactionPoolAdapter<C, P> { /// Get transactions for propagation. /// /// Function extracted to simplify the test and prevent creating `ServiceFactory`. -fn transactions_to_propagate<Pool, B, H, E>(pool: &Pool) -> Vec<(H, B::Extrinsic)> +fn transactions_to_propagate<Pool, B, H, E>(pool: &Pool) -> Vec<(H, Arc<B::Extrinsic>)> where Pool: TransactionPool<Block = B, Hash = H, Error = E>, B: BlockT, @@ -485,7 +485,7 @@ where .filter(|t| t.is_propagable()) .map(|t| { let hash = t.hash().clone(); - let ex: B::Extrinsic = (**t.data()).clone(); + let ex = t.data().clone(); (hash, ex) }) .collect() @@ -506,7 +506,7 @@ where H: std::hash::Hash + Eq + sp_runtime::traits::Member + sp_runtime::traits::MaybeSerialize, E: 'static + IntoPoolError + From<sc_transaction_pool_api::error::Error>, { - fn transactions(&self) -> Vec<(H, B::Extrinsic)> { + fn transactions(&self) -> Vec<(H, Arc<B::Extrinsic>)> { transactions_to_propagate(&*self.pool) } @@ -538,7 +538,7 @@ where { Ok(_) => { let elapsed = start.elapsed(); - debug!(target: sc_transaction_pool::LOG_TARGET, "import transaction: {elapsed:?}"); + trace!(target: sc_transaction_pool::LOG_TARGET, "import transaction: {elapsed:?}"); TransactionImport::NewGood }, Err(e) => match e.into_pool_error() { @@ -559,10 +559,10 @@ where self.pool.on_broadcasted(propagations) } - fn transaction(&self, hash: &H) -> Option<B::Extrinsic> { + fn transaction(&self, hash: &H) -> Option<Arc<B::Extrinsic>> { self.pool.ready_transaction(hash).and_then( // Only propagable transactions should be resolved for network service. - |tx| if tx.is_propagable() { Some((**tx.data()).clone()) } else { None }, + |tx| tx.is_propagable().then(|| tx.data().clone()), ) } } @@ -614,6 +614,6 @@ mod tests { // then assert_eq!(transactions.len(), 1); - assert!(TransferData::try_from(&transactions[0].1).is_ok()); + assert!(TransferData::try_from(&*transactions[0].1).is_ok()); } } diff --git a/substrate/client/telemetry/Cargo.toml b/substrate/client/telemetry/Cargo.toml index 4a41a6b6deca9d0ebf1c46bfb25194ebe4359093..1ebff618e0cef584b89a99bc44905ebb93ba50ab 100644 --- a/substrate/client/telemetry/Cargo.toml +++ b/substrate/client/telemetry/Cargo.toml @@ -24,7 +24,6 @@ log = { workspace = true, default-features = true } parking_lot = { workspace = true, default-features = true } pin-project = { workspace = true } rand = { workspace = true, default-features = true } -sc-network = { workspace = true, default-features = true } sc-utils = { workspace = true, default-features = true } serde = { features = ["derive"], workspace = true, default-features = true } serde_json = { workspace = true, default-features = true } diff --git a/substrate/client/transaction-pool/Cargo.toml b/substrate/client/transaction-pool/Cargo.toml index 72586b984920b12c36561749cd75cfacd8280243..26bbf58f1522d39ee854072d0f908ed29f7d2117 100644 --- a/substrate/client/transaction-pool/Cargo.toml +++ b/substrate/client/transaction-pool/Cargo.toml @@ -40,6 +40,7 @@ sp-transaction-pool = { workspace = true, default-features = true } thiserror = { workspace = true } tokio = { workspace = true, default-features = true, features = ["macros", "time"] } tokio-stream = { workspace = true } +tracing = { workspace = true, default-features = true } [dev-dependencies] array-bytes = { workspace = true, default-features = true } diff --git a/substrate/client/transaction-pool/src/common/mod.rs b/substrate/client/transaction-pool/src/common/mod.rs index fb280e8780ad4927cfc5f0045f1378363f06afe1..446a5c2ec0225b2494c50264cd6a3d7044d307ff 100644 --- a/substrate/client/transaction-pool/src/common/mod.rs +++ b/substrate/client/transaction-pool/src/common/mod.rs @@ -25,6 +25,7 @@ pub(crate) mod log_xt; pub(crate) mod metrics; #[cfg(test)] pub(crate) mod tests; +pub(crate) mod tracing_log_xt; use futures::StreamExt; use std::sync::Arc; diff --git a/substrate/client/transaction-pool/src/common/tracing_log_xt.rs b/substrate/client/transaction-pool/src/common/tracing_log_xt.rs new file mode 100644 index 0000000000000000000000000000000000000000..4d1c5d09cc7ac41219e1a532281cb1d51bba2640 --- /dev/null +++ b/substrate/client/transaction-pool/src/common/tracing_log_xt.rs @@ -0,0 +1,69 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +//! Utility for logging transaction collections with tracing crate. + +/// Logs every transaction from given `tx_collection` with given level. +macro_rules! log_xt { + (data: hash, target: $target:expr, $level:expr, $tx_collection:expr, $text_with_format:expr) => { + for tx in $tx_collection { + tracing::event!( + $level, + target = $target, + tx_hash = format!("{:?}", tx), + $text_with_format, + ); + } + }; + (data: hash, target: $target:expr, $level:expr, $tx_collection:expr, $text_with_format:expr, $($arg:expr),*) => { + for tx in $tx_collection { + tracing::event!( + $level, + target = $target, + tx_hash = format!("{:?}", tx), + $text_with_format, + $($arg),* + ); + } + }; + (data: tuple, target: $target:expr, $level:expr, $tx_collection:expr, $text_with_format:expr) => { + for tx in $tx_collection { + tracing::event!( + $level, + target = $target, + tx_hash = format!("{:?}", tx.0), + $text_with_format, + tx.1 + ); + } + }; +} +macro_rules! log_xt_trace { + (data: $datatype:ident, target: $target:expr, $($arg:tt)+) => { + $crate::common::tracing_log_xt::log_xt!(data: $datatype, target: $target, tracing::Level::TRACE, $($arg)+); + }; + (target: $target:expr, $tx_collection:expr, $text_with_format:expr) => { + $crate::common::tracing_log_xt::log_xt!(data: hash, target: $target, tracing::Level::TRACE, $tx_collection, $text_with_format); + }; + (target: $target:expr, $tx_collection:expr, $text_with_format:expr, $($arg:expr)*) => { + $crate::common::tracing_log_xt::log_xt!(data: hash, target: $target, tracing::Level::TRACE, $tx_collection, $text_with_format, $($arg)*); + }; +} + +pub(crate) use log_xt; +pub(crate) use log_xt_trace; diff --git a/substrate/client/transaction-pool/src/fork_aware_txpool/dropped_watcher.rs b/substrate/client/transaction-pool/src/fork_aware_txpool/dropped_watcher.rs index bf61558b00b0daf01c85e5a8ae4dec525615e7c4..be20a1608961945c8727e6e6feb24146ba64e9f5 100644 --- a/substrate/client/transaction-pool/src/fork_aware_txpool/dropped_watcher.rs +++ b/substrate/client/transaction-pool/src/fork_aware_txpool/dropped_watcher.rs @@ -22,13 +22,12 @@ //! by any view are detected and properly notified. use crate::{ - common::log_xt::log_xt_trace, + common::tracing_log_xt::log_xt_trace, fork_aware_txpool::stream_map_util::next_event, graph::{self, BlockHash, ExtrinsicHash}, LOG_TARGET, }; use futures::stream::StreamExt; -use log::{debug, trace}; use sc_transaction_pool_api::TransactionStatus; use sc_utils::mpsc; use sp_runtime::traits::Block as BlockT; @@ -41,6 +40,7 @@ use std::{ pin::Pin, }; use tokio_stream::StreamMap; +use tracing::{debug, trace}; /// Represents a transaction that was removed from the transaction pool, including the reason of its /// removal. @@ -74,7 +74,7 @@ pub enum DroppedReason<Hash> { } /// Dropped-logic related event from the single view. -pub type ViewStreamEvent<C> = crate::graph::DroppedByLimitsEvent<ExtrinsicHash<C>, BlockHash<C>>; +pub type ViewStreamEvent<C> = crate::graph::TransactionStatusEvent<ExtrinsicHash<C>, BlockHash<C>>; /// Dropped-logic stream of events coming from the single view. type ViewStream<C> = Pin<Box<dyn futures::Stream<Item = ViewStreamEvent<C>> + Send>>; @@ -225,7 +225,7 @@ where log_xt_trace!( target: LOG_TARGET, xts.clone(), - "[{:?}] dropped_watcher: finalized xt removed" + "dropped_watcher: finalized xt removed" ); xts.iter().for_each(|xt| { self.ready_transaction_views.remove(xt); @@ -279,7 +279,7 @@ where return Some(DroppedTransaction::new_enforced_by_limts(tx_hash)) } } else { - debug!("[{:?}] dropped_watcher: removing (non-tracked) tx", tx_hash); + debug!(target: LOG_TARGET, ?tx_hash, "dropped_watcher: removing (non-tracked) tx"); return Some(DroppedTransaction::new_enforced_by_limts(tx_hash)) } }, diff --git a/substrate/client/transaction-pool/src/fork_aware_txpool/fork_aware_txpool.rs b/substrate/client/transaction-pool/src/fork_aware_txpool/fork_aware_txpool.rs index 766045718252007455e4b781335d1c0261077a0f..ffe6c20d92b72d2c3aa5c444224f6c32f83aad8e 100644 --- a/substrate/client/transaction-pool/src/fork_aware_txpool/fork_aware_txpool.rs +++ b/substrate/client/transaction-pool/src/fork_aware_txpool/fork_aware_txpool.rs @@ -23,13 +23,13 @@ use super::{ import_notification_sink::MultiViewImportNotificationSink, metrics::MetricsLink as PrometheusMetrics, multi_view_listener::MultiViewListener, - tx_mem_pool::{InsertionInfo, TxInMemPool, TxMemPool, TXMEMPOOL_TRANSACTION_LIMIT_MULTIPLIER}, + tx_mem_pool::{InsertionInfo, TxMemPool, TXMEMPOOL_TRANSACTION_LIMIT_MULTIPLIER}, view::View, view_store::ViewStore, }; use crate::{ api::FullChainApi, - common::log_xt::log_xt_trace, + common::tracing_log_xt::log_xt_trace, enactment_state::{EnactmentAction, EnactmentState}, fork_aware_txpool::{ dropped_watcher::{DroppedReason, DroppedTransaction}, @@ -70,6 +70,7 @@ use std::{ time::Instant, }; use tokio::select; +use tracing::{debug, info, trace, warn}; /// Fork aware transaction pool task, that needs to be polled. pub type ForkAwareTxPoolTask = Pin<Box<dyn Future<Output = ()> + Send>>; @@ -105,10 +106,10 @@ where /// /// `ready_iterator` is a closure that generates the result data to be sent to the pollers. fn trigger(&mut self, at: Block::Hash, ready_iterator: impl Fn() -> T) { - log::trace!(target: LOG_TARGET, "fatp::trigger {at:?} pending keys: {:?}", self.pollers.keys()); + trace!(target: LOG_TARGET, ?at, keys = ?self.pollers.keys(), "fatp::trigger"); let Some(pollers) = self.pollers.remove(&at) else { return }; pollers.into_iter().for_each(|p| { - log::debug!(target: LOG_TARGET, "trigger ready signal at block {}", at); + debug!(target: LOG_TARGET, "trigger ready signal at block {}", at); let _ = p.send(ready_iterator()); }); } @@ -192,7 +193,9 @@ where future_limits: crate::PoolLimit, mempool_max_transactions_count: usize, ) -> (Self, ForkAwareTxPoolTask) { - let listener = Arc::from(MultiViewListener::new()); + let (listener, listener_task) = MultiViewListener::new_with_worker(); + let listener = Arc::new(listener); + let (import_notification_sink, import_notification_sink_task) = MultiViewImportNotificationSink::new_with_worker(); @@ -219,6 +222,7 @@ where let combined_tasks = async move { tokio::select! { + _ = listener_task => {}, _ = import_notification_sink_task => {}, _ = dropped_monitor_task => {} } @@ -265,36 +269,34 @@ where ) { loop { let Some(dropped) = dropped_stream.next().await else { - log::debug!(target: LOG_TARGET, "fatp::dropped_monitor_task: terminated..."); + debug!(target: LOG_TARGET, "fatp::dropped_monitor_task: terminated..."); break; }; - let dropped_tx_hash = dropped.tx_hash; - log::trace!(target: LOG_TARGET, "[{:?}] fatp::dropped notification {:?}, removing", dropped_tx_hash,dropped.reason); + let tx_hash = dropped.tx_hash; + trace!( + target: LOG_TARGET, + ?tx_hash, + reason = ?dropped.reason, + "fatp::dropped notification, removing" + ); match dropped.reason { DroppedReason::Usurped(new_tx_hash) => { if let Some(new_tx) = mempool.get_by_hash(new_tx_hash) { - view_store - .replace_transaction( - new_tx.source(), - new_tx.tx(), - dropped_tx_hash, - new_tx.is_watched(), - ) - .await; + view_store.replace_transaction(new_tx.source(), new_tx.tx(), tx_hash).await; } else { - log::trace!( - target:LOG_TARGET, - "error: dropped_monitor_task: no entry in mempool for new transaction {:?}", - new_tx_hash, + trace!( + target: LOG_TARGET, + tx_hash = ?new_tx_hash, + "error: dropped_monitor_task: no entry in mempool for new transaction" ); } }, DroppedReason::LimitsEnforced => {}, }; - mempool.remove_transaction(&dropped_tx_hash); + mempool.remove_transaction(&tx_hash); view_store.listener.transaction_dropped(dropped); - import_notification_sink.clean_notified_items(&[dropped_tx_hash]); + import_notification_sink.clean_notified_items(&[tx_hash]); } } @@ -312,7 +314,10 @@ where finalized_hash: Block::Hash, ) -> Self { let metrics = PrometheusMetrics::new(prometheus); - let listener = Arc::from(MultiViewListener::new()); + + let (listener, listener_task) = MultiViewListener::new_with_worker(); + let listener = Arc::new(listener); + let (revalidation_queue, revalidation_task) = revalidation_worker::RevalidationQueue::new_with_worker(); @@ -341,6 +346,7 @@ where let combined_tasks = async move { tokio::select! { + _ = listener_task => {} _ = revalidation_task => {}, _ = import_notification_sink_task => {}, _ = dropped_monitor_task => {} @@ -433,7 +439,11 @@ where pub async fn ready_at_light(&self, at: Block::Hash) -> ReadyIteratorFor<ChainApi> { let start = Instant::now(); let api = self.api.clone(); - log::trace!(target: LOG_TARGET, "fatp::ready_at_light {:?}", at); + trace!( + target: LOG_TARGET, + ?at, + "fatp::ready_at_light" + ); let Ok(block_number) = self.api.resolve_block_number(at) else { return Box::new(std::iter::empty()) @@ -465,8 +475,12 @@ where let extrinsics = api .block_body(h.hash) .await - .unwrap_or_else(|e| { - log::warn!(target: LOG_TARGET, "Compute ready light transactions: error request: {}", e); + .unwrap_or_else(|error| { + warn!( + target: LOG_TARGET, + %error, + "Compute ready light transactions: error request" + ); None }) .unwrap_or_default() @@ -487,19 +501,25 @@ where let _ = tmp_view.pool.validated_pool().prune_tags(tags); let after_count = tmp_view.pool.validated_pool().status().ready; - log::debug!(target: LOG_TARGET, - "fatp::ready_at_light {} from {} before: {} to be removed: {} after: {} took:{:?}", - at, - best_view.at.hash, + debug!( + target: LOG_TARGET, + ?at, + best_view_hash = ?best_view.at.hash, before_count, - all_extrinsics.len(), + to_be_removed = all_extrinsics.len(), after_count, - start.elapsed() + duration = ?start.elapsed(), + "fatp::ready_at_light" ); Box::new(tmp_view.pool.validated_pool().ready()) } else { let empty: ReadyIteratorFor<ChainApi> = Box::new(std::iter::empty()); - log::debug!(target: LOG_TARGET, "fatp::ready_at_light {} -> empty, took:{:?}", at, start.elapsed()); + debug!( + target: LOG_TARGET, + ?at, + duration = ?start.elapsed(), + "fatp::ready_at_light -> empty" + ); empty } } @@ -519,8 +539,12 @@ where at: Block::Hash, timeout: std::time::Duration, ) -> ReadyIteratorFor<ChainApi> { - log::debug!(target: LOG_TARGET, "fatp::ready_at_with_timeout at {:?} allowed delay: {:?}", at, timeout); - + debug!( + target: LOG_TARGET, + ?at, + ?timeout, + "fatp::ready_at_with_timeout" + ); let timeout = futures_timer::Delay::new(timeout); let (view_already_exists, ready_at) = self.ready_at_internal(at); @@ -532,10 +556,10 @@ where select! { ready = ready_at => Some(ready), _ = timeout => { - log::warn!(target: LOG_TARGET, - "Timeout fired waiting for transaction pool at block: ({:?}). \ - Proceeding with production.", - at, + warn!( + target: LOG_TARGET, + ?at, + "Timeout fired waiting for transaction pool at block. Proceeding with production." ); None } @@ -555,7 +579,12 @@ where let mut ready_poll = self.ready_poll.lock(); if let Some((view, inactive)) = self.view_store.get_view_at(at, true) { - log::debug!(target: LOG_TARGET, "fatp::ready_at_internal {at:?} (inactive:{inactive:?})"); + debug!( + target: LOG_TARGET, + ?at, + ?inactive, + "fatp::ready_at_internal" + ); let iterator: ReadyIteratorFor<ChainApi> = Box::new(view.pool.validated_pool().ready()); return (true, async move { iterator }.boxed()); } @@ -563,15 +592,21 @@ where let pending = ready_poll .add(at) .map(|received| { - received.unwrap_or_else(|e| { - log::warn!(target: LOG_TARGET, "Error receiving ready-set iterator: {:?}", e); + received.unwrap_or_else(|error| { + warn!( + target: LOG_TARGET, + %error, + "Error receiving ready-set iterator" + ); Box::new(std::iter::empty()) }) }) .boxed(); - log::debug!(target: LOG_TARGET, - "fatp::ready_at_internal {at:?} pending keys: {:?}", - ready_poll.pollers.keys() + debug!( + target: LOG_TARGET, + ?at, + pending_keys = ?ready_poll.pollers.keys(), + "fatp::ready_at_internal" ); (false, pending) } @@ -649,8 +684,13 @@ where xts: Vec<TransactionFor<Self>>, ) -> Result<Vec<Result<TxHash<Self>, Self::Error>>, Self::Error> { let view_store = self.view_store.clone(); - log::debug!(target: LOG_TARGET, "fatp::submit_at count:{} views:{}", xts.len(), self.active_views_count()); - log_xt_trace!(target: LOG_TARGET, xts.iter().map(|xt| self.tx_hash(xt)), "[{:?}] fatp::submit_at"); + debug!( + target: LOG_TARGET, + count = xts.len(), + active_views_count = self.active_views_count(), + "fatp::submit_at" + ); + log_xt_trace!(target: LOG_TARGET, xts.iter().map(|xt| self.tx_hash(xt)), "fatp::submit_at"); let xts = xts.into_iter().map(Arc::from).collect::<Vec<_>>(); let mempool_results = self.mempool.extend_unwatched(source, &xts); @@ -741,7 +781,12 @@ where source: TransactionSource, xt: TransactionFor<Self>, ) -> Result<TxHash<Self>, Self::Error> { - log::trace!(target: LOG_TARGET, "[{:?}] fatp::submit_one views:{}", self.tx_hash(&xt), self.active_views_count()); + trace!( + target: LOG_TARGET, + tx_hash = ?self.tx_hash(&xt), + active_views_count = self.active_views_count(), + "fatp::submit_one" + ); match self.submit_at(_at, source, vec![xt]).await { Ok(mut v) => v.pop().expect("There is exactly one element in result of submit_at. qed."), @@ -759,7 +804,12 @@ where source: TransactionSource, xt: TransactionFor<Self>, ) -> Result<Pin<Box<TransactionStatusStreamFor<Self>>>, Self::Error> { - log::trace!(target: LOG_TARGET, "[{:?}] fatp::submit_and_watch views:{}", self.tx_hash(&xt), self.active_views_count()); + trace!( + target: LOG_TARGET, + tx_hash = ?self.tx_hash(&xt), + views = self.active_views_count(), + "fatp::submit_and_watch" + ); let xt = Arc::from(xt); let InsertionInfo { hash: xt_hash, source: timed_source, .. } = @@ -791,8 +841,7 @@ where // useful for verification for debugging purposes). fn remove_invalid(&self, hashes: &[TxHash<Self>]) -> Vec<Arc<Self::InPoolTransaction>> { if !hashes.is_empty() { - log::debug!(target: LOG_TARGET, "fatp::remove_invalid {}", hashes.len()); - log_xt_trace!(target:LOG_TARGET, hashes, "[{:?}] fatp::remove_invalid"); + log_xt_trace!(target:LOG_TARGET, hashes, "fatp::remove_invalid"); self.metrics .report(|metrics| metrics.removed_invalid_txs.inc_by(hashes.len() as _)); } @@ -842,11 +891,12 @@ where let result = most_recent_view .map(|block_hash| self.view_store.ready_transaction(block_hash, tx_hash)) .flatten(); - log::trace!( + trace!( target: LOG_TARGET, - "[{tx_hash:?}] ready_transaction: {} {:?}", - result.is_some(), - most_recent_view + ?tx_hash, + is_ready = result.is_some(), + ?most_recent_view, + "ready_transaction" ); result } @@ -902,7 +952,11 @@ where _at: Block::Hash, xt: sc_transaction_pool_api::LocalTransactionFor<Self>, ) -> Result<Self::Hash, Self::Error> { - log::debug!(target: LOG_TARGET, "fatp::submit_local views:{}", self.active_views_count()); + debug!( + target: LOG_TARGET, + active_views_count = self.active_views_count(), + "fatp::submit_local" + ); let xt = Arc::from(xt); let result = @@ -947,20 +1001,20 @@ where let hash_and_number = match tree_route.last() { Some(hash_and_number) => hash_and_number, None => { - log::warn!( + warn!( target: LOG_TARGET, - "Skipping ChainEvent - no last block in tree route {:?}", - tree_route, + ?tree_route, + "Skipping ChainEvent - no last block in tree route" ); return }, }; if self.has_view(&hash_and_number.hash) { - log::trace!( + trace!( target: LOG_TARGET, - "view already exists for block: {:?}", - hash_and_number, + ?hash_and_number, + "view already exists for block" ); return } @@ -995,12 +1049,12 @@ where at: &HashAndNumber<Block>, tree_route: &TreeRoute<Block>, ) -> Option<Arc<View<ChainApi>>> { - log::debug!( + debug!( target: LOG_TARGET, - "build_new_view: for: {:?} from: {:?} tree_route: {:?}", - at, - origin_view.as_ref().map(|v| v.at.clone()), - tree_route + ?at, + origin_view_at = ?origin_view.as_ref().map(|v| v.at.clone()), + ?tree_route, + "build_new_view" ); let mut view = if let Some(origin_view) = origin_view { let mut view = View::new_from_other(&origin_view, at); @@ -1009,7 +1063,11 @@ where } view } else { - log::debug!(target: LOG_TARGET, "creating non-cloned view: for: {at:?}"); + debug!( + target: LOG_TARGET, + ?at, + "creating non-cloned view" + ); View::new( self.api.clone(), at.clone(), @@ -1019,6 +1077,7 @@ where ) }; + let start = Instant::now(); // 1. Capture all import notification from the very beginning, so first register all //the listeners. self.import_notification_sink.add_view( @@ -1031,27 +1090,40 @@ where view.pool.validated_pool().create_dropped_by_limits_stream().boxed(), ); - let start = Instant::now(); - let watched_xts = self.register_listeners(&mut view).await; - let duration = start.elapsed(); + self.view_store.listener.add_view_aggregated_stream( + view.at.hash, + view.pool.validated_pool().create_aggregated_stream().boxed(), + ); // sync the transactions statuses and referencing views in all the listeners with newly // cloned view. view.pool.validated_pool().retrigger_notifications(); - log::debug!(target: LOG_TARGET, "register_listeners: at {at:?} took {duration:?}"); + debug!( + target: LOG_TARGET, + ?at, + duration = ?start.elapsed(), + "register_listeners" + ); // 2. Handle transactions from the tree route. Pruning transactions from the view first // will make some space for mempool transactions in case we are at the view's limits. let start = Instant::now(); self.update_view_with_fork(&view, tree_route, at.clone()).await; - let duration = start.elapsed(); - log::debug!(target: LOG_TARGET, "update_view_with_fork: at {at:?} took {duration:?}"); + debug!( + target: LOG_TARGET, + ?at, + duration = ?start.elapsed(), + "update_view_with_fork" + ); // 3. Finally, submit transactions from the mempool. let start = Instant::now(); - self.update_view_with_mempool(&mut view, watched_xts).await; - let duration = start.elapsed(); - log::debug!(target: LOG_TARGET, "update_view_with_mempool: at {at:?} took {duration:?}"); - + self.update_view_with_mempool(&mut view).await; + debug!( + target: LOG_TARGET, + ?at, + duration= ?start.elapsed(), + "update_view_with_mempool" + ); let view = Arc::from(view); self.view_store.insert_new_view(view.clone(), tree_route).await; Some(view) @@ -1074,8 +1146,12 @@ where for h in tree_route.enacted().iter().rev() { api.block_body(h.hash) .await - .unwrap_or_else(|e| { - log::warn!(target: LOG_TARGET, "Compute ready light transactions: error request: {}", e); + .unwrap_or_else(|error| { + warn!( + target: LOG_TARGET, + %error, + "Compute ready light transactions: error request" + ); None }) .unwrap_or_default() @@ -1086,56 +1162,15 @@ where }); } - log::debug!(target: LOG_TARGET, - "fatp::extrinsics_included_since_finalized {} from {} count: {} took:{:?}", - at, - recent_finalized_block, - all_extrinsics.len(), - start.elapsed() - ); - all_extrinsics - } - - /// For every watched transaction in the mempool registers a transaction listener in the view. - /// - /// The transaction listener for a given view is also added to multi-view listener. This allows - /// to track aggreagated progress of the transaction within the transaction pool. - /// - /// Function returns a list of currently watched transactions in the mempool. - async fn register_listeners( - &self, - view: &View<ChainApi>, - ) -> Vec<(ExtrinsicHash<ChainApi>, Arc<TxInMemPool<ChainApi, Block>>)> { - log::debug!( + debug!( target: LOG_TARGET, - "register_listeners: {:?} xts:{:?} v:{}", - view.at, - self.mempool.unwatched_and_watched_count(), - self.active_views_count() + ?at, + ?recent_finalized_block, + extrinsics_count = all_extrinsics.len(), + duration = ?start.elapsed(), + "fatp::extrinsics_included_since_finalized" ); - - //todo [#5495]: maybe we don't need to register listener in view? We could use - // multi_view_listener.transaction_in_block - let results = self - .mempool - .clone_watched() - .into_iter() - .map(|(tx_hash, tx)| { - let watcher = view.create_watcher(tx_hash); - let at = view.at.clone(); - async move { - log::trace!(target: LOG_TARGET, "[{:?}] adding watcher {:?}", tx_hash, at.hash); - self.view_store.listener.add_view_watcher_for_tx( - tx_hash, - at.hash, - watcher.into_stream().boxed(), - ); - (tx_hash, tx) - } - }) - .collect::<Vec<_>>(); - - future::join_all(results).await + all_extrinsics } /// Updates the given view with the transactions from the internal mempol. @@ -1147,33 +1182,26 @@ where /// If there are no views, and mempool transaction is reported as invalid for the given view, /// the transaction is reported as invalid and removed from the mempool. This does not apply to /// stale and temporarily banned transactions. - /// - /// As the listeners for watched transactions were registered at the very beginning of maintain - /// procedure (`register_listeners`), this function accepts the list of watched transactions - /// from the mempool for which listener was actually registered to avoid submit/maintain races. - async fn update_view_with_mempool( - &self, - view: &View<ChainApi>, - watched_xts: Vec<(ExtrinsicHash<ChainApi>, Arc<TxInMemPool<ChainApi, Block>>)>, - ) { - log::debug!( + async fn update_view_with_mempool(&self, view: &View<ChainApi>) { + debug!( target: LOG_TARGET, - "update_view_with_mempool: {:?} xts:{:?} v:{}", - view.at, - self.mempool.unwatched_and_watched_count(), - self.active_views_count() + view_at = ?view.at, + xts_count = ?self.mempool.unwatched_and_watched_count(), + active_views_count = self.active_views_count(), + "update_view_with_mempool" ); let included_xts = self.extrinsics_included_since_finalized(view.at.hash).await; - let (hashes, xts_filtered): (Vec<_>, Vec<_>) = watched_xts + let (hashes, xts_filtered): (Vec<_>, Vec<_>) = self + .mempool + .clone_transactions() .into_iter() - .chain(self.mempool.clone_unwatched().into_iter()) .filter(|(hash, _)| !view.is_imported(hash)) .filter(|(hash, _)| !included_xts.contains(&hash)) .map(|(tx_hash, tx)| (tx_hash, (tx.source(), tx.tx()))) .unzip(); - let watched_results = view + let results = view .submit_many(xts_filtered) .await .into_iter() @@ -1185,14 +1213,14 @@ where }) .collect::<Vec<_>>(); - let submitted_count = watched_results.len(); + let submitted_count = results.len(); - log::debug!( + debug!( target: LOG_TARGET, - "update_view_with_mempool: at {:?} submitted {}/{}", - view.at.hash, + view_at_hash = ?view.at.hash, submitted_count, - self.mempool.len() + mempool_len = self.mempool.len(), + "update_view_with_mempool" ); self.metrics @@ -1201,9 +1229,9 @@ where // if there are no views yet, and a single newly created view is reporting error, just send // out the invalid event, and remove transaction. if self.view_store.is_empty() { - for result in watched_results { + for result in results { if let Err(tx_hash) = result { - self.view_store.listener.invalidate_transactions(&[tx_hash]); + self.view_store.listener.transactions_invalidated(&[tx_hash]); self.mempool.remove_transaction(&tx_hash); } } @@ -1220,7 +1248,12 @@ where tree_route: &TreeRoute<Block>, hash_and_number: HashAndNumber<Block>, ) { - log::debug!(target: LOG_TARGET, "update_view_with_fork tree_route: {:?} {tree_route:?}", view.at); + debug!( + target: LOG_TARGET, + ?tree_route, + at = ?view.at, + "update_view_with_fork" + ); let api = self.api.clone(); // We keep track of everything we prune so that later we won't add @@ -1249,8 +1282,12 @@ where let block_transactions = api .block_body(hash) .await - .unwrap_or_else(|e| { - log::warn!(target: LOG_TARGET, "Failed to fetch block body: {}", e); + .unwrap_or_else(|error| { + warn!( + target: LOG_TARGET, + %error, + "Failed to fetch block body" + ); None }) .unwrap_or_default() @@ -1269,11 +1306,11 @@ where resubmitted_to_report += 1; if !contains { - log::trace!( + trace!( target: LOG_TARGET, - "[{:?}]: Resubmitting from retracted block {:?}", - tx_hash, - hash, + ?tx_hash, + ?hash, + "Resubmitting from retracted block" ); } !contains @@ -1307,8 +1344,13 @@ where /// - purging finalized transactions from the mempool and triggering mempool revalidation, async fn handle_finalized(&self, finalized_hash: Block::Hash, tree_route: &[Block::Hash]) { let finalized_number = self.api.block_id_to_number(&BlockId::Hash(finalized_hash)); - log::debug!(target: LOG_TARGET, "handle_finalized {finalized_number:?} tree_route: {tree_route:?} views_count:{}", self.active_views_count()); - + debug!( + target: LOG_TARGET, + ?finalized_number, + ?tree_route, + active_views_count = self.active_views_count(), + "handle_finalized" + ); let finalized_xts = self.view_store.handle_finalized(finalized_hash, tree_route).await; self.mempool.purge_finalized_transactions(&finalized_xts).await; @@ -1325,11 +1367,19 @@ where ) .await; } else { - log::trace!(target: LOG_TARGET, "purge_transactions_later skipped, cannot find block number {finalized_number:?}"); + trace!( + target: LOG_TARGET, + ?finalized_number, + "purge_transactions_later skipped, cannot find block number" + ); } self.ready_poll.lock().remove_cancelled(); - log::trace!(target: LOG_TARGET, "handle_finalized after views_count:{:?}", self.active_views_count()); + trace!( + target: LOG_TARGET, + active_views_count = self.active_views_count(), + "handle_finalized after" + ); } /// Computes a hash of the provided transaction @@ -1443,7 +1493,11 @@ where /// Executes the maintainance for the given chain event. async fn maintain(&self, event: ChainEvent<Self::Block>) { let start = Instant::now(); - log::debug!(target: LOG_TARGET, "processing event: {event:?}"); + debug!( + target: LOG_TARGET, + ?event, + "processing event" + ); self.view_store.finish_background_revalidations().await; @@ -1467,8 +1521,12 @@ where .update(&event, &compute_tree_route, &block_id_to_number); match result { - Err(msg) => { - log::trace!(target: LOG_TARGET, "enactment_state::update error: {msg}"); + Err(error) => { + trace!( + target: LOG_TARGET, + %error, + "enactment_state::update error" + ); self.enactment_state.lock().force_update(&event); }, Ok(EnactmentAction::Skip) => return, @@ -1494,23 +1552,25 @@ where ChainEvent::Finalized { hash, ref tree_route } => { self.handle_finalized(hash, tree_route).await; - log::trace!( + trace!( target: LOG_TARGET, - "on-finalized enacted: {tree_route:?}, previously finalized: \ - {prev_finalized_block:?}", + ?tree_route, + ?prev_finalized_block, + "on-finalized enacted" ); }, } - let maintain_duration = start.elapsed(); + let duration = start.elapsed(); - log::info!( + info!( target: LOG_TARGET, - "maintain: txs:{:?} views:[{};{:?}] event:{event:?} took:{:?}", - self.mempool_len(), - self.active_views_count(), - self.views_stats(), - maintain_duration + txs = ?self.mempool_len(), + active_views_count = self.active_views_count(), + views = ?self.views_stats(), + ?event, + ?duration, + "maintain" ); self.metrics.report(|metrics| { @@ -1521,7 +1581,7 @@ where watched.try_into().map(|v| metrics.watched_txs.set(v)), unwatched.try_into().map(|v| metrics.unwatched_txs.set(v)), ); - metrics.maintain_duration.observe(maintain_duration.as_secs_f64()); + metrics.maintain_duration.observe(duration.as_secs_f64()); }); } } diff --git a/substrate/client/transaction-pool/src/fork_aware_txpool/import_notification_sink.rs b/substrate/client/transaction-pool/src/fork_aware_txpool/import_notification_sink.rs index f9a41673bb8fc9debbce9557621f7c291364b37f..1ca287fa237151e4a46f0e56110edb276148f5c1 100644 --- a/substrate/client/transaction-pool/src/fork_aware_txpool/import_notification_sink.rs +++ b/substrate/client/transaction-pool/src/fork_aware_txpool/import_notification_sink.rs @@ -27,7 +27,6 @@ use futures::{ stream::StreamExt, Future, FutureExt, }; -use log::trace; use parking_lot::RwLock; use sc_utils::mpsc; use std::{ @@ -38,6 +37,7 @@ use std::{ sync::Arc, }; use tokio_stream::StreamMap; +use tracing::trace; /// A type alias for a pinned, boxed stream of items of type `I`. /// This alias is particularly useful for defining the types of the incoming streams from various @@ -109,14 +109,22 @@ where cmd = ctx.command_receiver.next() => { match cmd? { Command::AddView(key,stream) => { - trace!(target: LOG_TARGET,"Command::AddView {key:?}"); + trace!( + target: LOG_TARGET, + ?key, + "Command::AddView" + ); ctx.stream_map.insert(key,stream); }, } }, Some(event) = next_event(&mut ctx.stream_map) => { - trace!(target: LOG_TARGET, "import_notification_sink: select_next_some -> {:?}", event); + trace!( + target: LOG_TARGET, + ?event, + "import_notification_sink: select_next_some" + ); return Some((event.1, ctx)); } } @@ -179,9 +187,17 @@ where async move { if already_notified_items.write().insert(event.clone()) { external_sinks.write().retain_mut(|sink| { - trace!(target: LOG_TARGET, "[{:?}] import_sink_worker sending out imported", event); - if let Err(e) = sink.try_send(event.clone()) { - trace!(target: LOG_TARGET, "import_sink_worker sending message failed: {e}"); + trace!( + target: LOG_TARGET, + ?event, + "import_sink_worker sending out imported" + ); + if let Err(error) = sink.try_send(event.clone()) { + trace!( + target: LOG_TARGET, + %error, + "import_sink_worker sending message failed" + ); false } else { true @@ -199,12 +215,17 @@ where /// The new view's stream is added to the internal aggregated stream context by sending command /// to its `command_receiver`. pub fn add_view(&self, key: K, view: StreamOf<I>) { - let _ = self - .controller - .unbounded_send(Command::AddView(key.clone(), view)) - .map_err(|e| { - trace!(target: LOG_TARGET, "add_view {key:?} send message failed: {e}"); - }); + let _ = + self.controller + .unbounded_send(Command::AddView(key.clone(), view)) + .map_err(|error| { + trace!( + target: LOG_TARGET, + ?key, + %error, + "add_view send message failed" + ); + }); } /// Creates and returns a new external stream of ready transactions hashes notifications. diff --git a/substrate/client/transaction-pool/src/fork_aware_txpool/mod.rs b/substrate/client/transaction-pool/src/fork_aware_txpool/mod.rs index 5f7294a24fd75df4d4bea38ee585eb744f2123ab..2c4da0182a2524431077ed3284b406bc6fc8869c 100644 --- a/substrate/client/transaction-pool/src/fork_aware_txpool/mod.rs +++ b/substrate/client/transaction-pool/src/fork_aware_txpool/mod.rs @@ -84,7 +84,8 @@ //! //! ### Multi-view listeners //! There is a number of event streams that are provided by individual views: -//! - [transaction status][`Watcher`], +//! - aggregated stream of [transactions statuses][`AggregatedStream`] for all the transactions +//! within the view in the form of `(transaction-hash, status)` tuple, //! - [ready notification][`vp::import_notification_stream`] (see [networking //! section](#networking)), //! - [dropped notification][`create_dropped_by_limits_stream`]. @@ -93,10 +94,9 @@ //! internally). Those aggregators are often referred as multi-view listeners and they implement //! stream-specific or event-specific logic. //! -//! The most important is [`MultiViewListener`] which is owned by view store. -//! More information about it is provided in [transaction -//! route](#transaction-route-submit_and_watch) section. -//! +//! The most important is [`MultiViewListener`] which is owned by view store. Some internal details +//! on events' flow is provided in [transaction status](#monitoring-the-status-of-a-transaction) +//! section. //! //! ### Intermediate transactions buffer: [`TxMemPool`] //! The main purpose of an internal [`TxMemPool`] (referred to as *mempool*) is to prevent a @@ -106,10 +106,11 @@ //! procedure. Additionally, it allows the pool to accept transactions when no blocks have been //! reported yet. //! -//! Since watched and non-watched transactions require a different treatment, the *mempool* keeps a -//! track on how the transaction was submitted. The [transaction source][`TransactionSource`] used -//! to submit transactions also needs to be kept in the *mempool*. The *mempool* transaction is a -//! simple [wrapper][`TxInMemPool`] around the [`Arc`] reference to the actual extrinsic body. +//! The *mempool* keeps a track on how the transaction was submitted - keeping number of watched and +//! non-watched transactions is useful for testing and metrics. The [transaction +//! source][`TransactionSource`] used to submit transactions also needs to be kept in the *mempool*. +//! The *mempool* transaction is a simple [wrapper][`TxInMemPool`] around the [`Arc`] reference to +//! the actual extrinsic body. //! //! Once the view is created, all transactions from *mempool* are submitted to and validated at this //! view. @@ -138,20 +139,37 @@ //! ### Transaction route: [`submit_and_watch`][`api_submit_and_watch`] //! //! The [`submit_and_watch`] function allows to submit the transaction and track its -//! [status][`TransactionStatus`] within the pool. Every view is providing an independent -//! [stream][`View::submit_and_watch`] of events, which needs to be merged into the single stream -//! exposed to the [external listener][`TransactionStatusStreamFor`]. For majority of events simple -//! forwarding of events would not work (e.g. we could get multiple [`Ready`] events, or [`Ready`] / -//! [`Future`] mix). Some additional stateful logic is required to filter and process the views' -//! events. It is also easier to trigger some events (e.g. [`Finalized`], [`Invalid`], and -//! [`Broadcast`]) using some side-channel and simply ignoring these events from the view. All the -//! before mentioned functionality is provided by the [`MultiViewListener`]. -//! -//! When watched transaction is submitted to the pool it is added the *mempool* with watched -//! flag. The external stream for the transaction is created in a [`MultiViewListener`]. Then -//! transaction is submitted to every active [`View`] (using -//! [`submit_and_watch`][`View::submit_and_watch`]) and the resulting -//! views' stream is connected to the [`MultiViewListener`]. +//! [status][`TransactionStatus`] within the pool. +//! +//! When a watched transaction is submitted to the pool it is added to the *mempool* with the +//! watched flag. The external stream for the transaction is created in a [`MultiViewListener`]. +//! Then a transaction is submitted to every active [`View`] (using +//! [`submit_many`][`View::submit_many`]). The view's [aggregated +//! stream][`create_aggregated_stream`] was already connected to the [`MultiViewListener`] when new +//! view was created, so no additional action is required upon the submission. The view will provide +//! the required updates for all the transactions over this single stream. +//! +//! +//! #### Monitoring the status of a transaction +//! +//! Transaction status monitoring and triggering events to [external +//! listener][`TransactionStatusStreamFor`] (e.g. to RPC client) is responsibility of the +//! [`MultiViewListener`]. +//! +//! Every view is providing an independent aggreagated [stream][`create_aggregated_stream`] of +//! events for all transactions in this view, which needs to be merged into the single stream +//! exposed to the [external listener][`TransactionStatusStreamFor`] (e.g. to RPC client). For +//! majority of events simple forwarding would not work (e.g. we could get multiple [`Ready`] +//! events, or [`Ready`] / [`Future`] mix). Some additional stateful logic (implemented by +//! [`MultiViewListener`]) is required to filter and process the views' events. +//! +//! It is not possible to trigger some external events (e.g., [`Dropped`], [`Finalized`], +//! [`Invalid`], and [`Broadcast`]) using only the view-aggregated streams. These events require a +//! pool-wide understanding of the transaction state. For example, dropping a transaction from a +//! single view does not mean it was dropped from other views. Broadcast and finalized notifications +//! are sent to the transaction pool API, not at the view level. These events are simply ignored +//! when they originate in the view. The pool uses a dedicated side channel exposed by +//! [`MultiViewListener`] to trigger the beforementioned events. //! //! ### Maintain //! The transaction pool exposes the [task][`notification_future`] that listens to the @@ -169,8 +187,8 @@ //! *mempool* //! - all transactions from the *mempool* (with some obvious filtering applied) are submitted to //! the view, -//! - for all watched transactions from the *mempool* the watcher is registered in the new view, -//! and it is connected to the multi-view-listener, +//! - the new [aggregated stream][`create_aggregated_stream`] of all transactions statuses is +//! created for the new view and it is connected to the multi-view-listener, //! - [update the view][ForkAwareTxPool::update_view_with_fork] with the transactions from the [tree //! route][`TreeRoute`] (which is computed from the recent best block to newly notified one by //! [enactment state][`EnactmentState`] helper): @@ -292,7 +310,7 @@ //! [`View`]: crate::fork_aware_txpool::view::View //! [`view::revalidate`]: crate::fork_aware_txpool::view::View::revalidate //! [`start_background_revalidation`]: crate::fork_aware_txpool::view::View::start_background_revalidation -//! [`View::submit_and_watch`]: crate::fork_aware_txpool::view::View::submit_and_watch +//! [`View::submit_many`]: crate::fork_aware_txpool::view::View::submit_many //! [`ViewStore`]: crate::fork_aware_txpool::view_store::ViewStore //! [`finish_background_revalidations`]: crate::fork_aware_txpool::view_store::ViewStore::finish_background_revalidations //! [find_best_view]: crate::fork_aware_txpool::view_store::ViewStore::find_best_view @@ -305,10 +323,12 @@ //! [`MultiViewListener`]: crate::fork_aware_txpool::multi_view_listener::MultiViewListener //! [`Pool`]: crate::graph::Pool //! [`Watcher`]: crate::graph::watcher::Watcher +//! [`AggregatedStream`]: crate::graph::AggregatedStream //! [`Options`]: crate::graph::Options //! [`vp::import_notification_stream`]: ../graph/validated_pool/struct.ValidatedPool.html#method.import_notification_stream //! [`vp::enforce_limits`]: ../graph/validated_pool/struct.ValidatedPool.html#method.enforce_limits //! [`create_dropped_by_limits_stream`]: ../graph/validated_pool/struct.ValidatedPool.html#method.create_dropped_by_limits_stream +//! [`create_aggregated_stream`]: ../graph/validated_pool/struct.ValidatedPool.html#method.create_aggregated_stream //! [`ChainEvent`]: sc_transaction_pool_api::ChainEvent //! [`TransactionStatusStreamFor`]: sc_transaction_pool_api::TransactionStatusStreamFor //! [`api_submit`]: sc_transaction_pool_api::TransactionPool::submit_at @@ -323,6 +343,7 @@ //! [`Invalid`]:sc_transaction_pool_api::TransactionStatus::Invalid //! [`InBlock`]:sc_transaction_pool_api::TransactionStatus::InBlock //! [`Finalized`]:sc_transaction_pool_api::TransactionStatus::Finalized +//! [`Dropped`]:sc_transaction_pool_api::TransactionStatus::Dropped //! [`ReadyTransactions`]:sc_transaction_pool_api::ReadyTransactions //! [`dropped_monitor_task`]: ForkAwareTxPool::dropped_monitor_task //! [`ready_poll`]: ForkAwareTxPool::ready_poll diff --git a/substrate/client/transaction-pool/src/fork_aware_txpool/multi_view_listener.rs b/substrate/client/transaction-pool/src/fork_aware_txpool/multi_view_listener.rs index a00234a99808238de77ec72a4e37531fcd4e3d6a..107c2941ec183470e91efb28d9d46e6156713aa0 100644 --- a/substrate/client/transaction-pool/src/fork_aware_txpool/multi_view_listener.rs +++ b/substrate/client/transaction-pool/src/fork_aware_txpool/multi_view_listener.rs @@ -21,20 +21,23 @@ //! aggregated streams of transaction events. use crate::{ + common::tracing_log_xt::log_xt_trace, fork_aware_txpool::stream_map_util::next_event, - graph::{self, BlockHash, ExtrinsicHash}, + graph::{self, BlockHash, ExtrinsicHash, TransactionStatusEvent}, LOG_TARGET, }; -use futures::StreamExt; -use log::{debug, trace}; +use futures::{Future, FutureExt, Stream, StreamExt}; +use parking_lot::RwLock; use sc_transaction_pool_api::{TransactionStatus, TransactionStatusStream, TxIndex}; use sc_utils::mpsc; use sp_runtime::traits::Block as BlockT; use std::{ collections::{hash_map::Entry, HashMap, HashSet}, pin::Pin, + sync::Arc, }; use tokio_stream::StreamMap; +use tracing::trace; use super::dropped_watcher::{DroppedReason, DroppedTransaction}; @@ -54,99 +57,202 @@ type CommandReceiver<T> = mpsc::TracingUnboundedReceiver<T>; /// It can represent both a single view's stream and an external watcher stream. pub type TxStatusStream<T> = Pin<Box<TransactionStatusStream<ExtrinsicHash<T>, BlockHash<T>>>>; -/// Commands to control the single external stream living within the multi view listener. -enum ControllerCommand<ChainApi: graph::ChainApi> { - /// Adds a new stream of transaction statuses originating in the view associated with a - /// specific block hash. - AddViewStream(BlockHash<ChainApi>, TxStatusStream<ChainApi>), +/// An aggregated stream providing events for all transactions from the view. +/// +/// This stream delivers updates for all transactions in the view, rather than for individual +/// transactions. +pub type ViewStatusStream<T> = + Pin<Box<dyn Stream<Item = TransactionStatusEvent<ExtrinsicHash<T>, BlockHash<T>>> + Send>>; +/// Commands to control / drive the task of the multi view listener. +enum ControllerCommand<ChainApi: graph::ChainApi> { + /// Requests transaction status updated. Sent by transaction pool implementation. + TransactionStatusRequest(TransactionStatusUpdate<ChainApi>), + /// Adds a new (aggregated) stream of transactions statuses originating in the view associated + /// with a specific block hash. + AddViewStream(BlockHash<ChainApi>, ViewStatusStream<ChainApi>), /// Removes an existing view's stream associated with a specific block hash. RemoveViewStream(BlockHash<ChainApi>), +} +/// Represents the transaction status update performed by transaction pool state machine. The +/// corresponding statuses coming from the view would typically be ignored in the external watcher. +enum TransactionStatusUpdate<ChainApi: graph::ChainApi> { /// Marks a transaction as invalidated. /// /// If all pre-conditions are met, an external invalid event will be sent out. - TransactionInvalidated, + TransactionInvalidated(ExtrinsicHash<ChainApi>), /// Notifies that a transaction was finalized in a specific block hash and transaction index. /// /// Send out an external finalized event. - FinalizeTransaction(BlockHash<ChainApi>, TxIndex), + TransactionFinalized(ExtrinsicHash<ChainApi>, BlockHash<ChainApi>, TxIndex), /// Notifies that a transaction was broadcasted with a list of peer addresses. /// /// Sends out an external broadcasted event. - TransactionBroadcasted(Vec<String>), + TransactionBroadcasted(ExtrinsicHash<ChainApi>, Vec<String>), /// Notifies that a transaction was dropped from the pool. /// /// If all preconditions are met, an external dropped event will be sent out. - TransactionDropped(DroppedReason<ExtrinsicHash<ChainApi>>), + TransactionDropped(ExtrinsicHash<ChainApi>, DroppedReason<ExtrinsicHash<ChainApi>>), } -impl<ChainApi> std::fmt::Debug for ControllerCommand<ChainApi> +impl<ChainApi> TransactionStatusUpdate<ChainApi> +where + ChainApi: graph::ChainApi, +{ + fn hash(&self) -> ExtrinsicHash<ChainApi> { + match self { + Self::TransactionInvalidated(hash) | + Self::TransactionFinalized(hash, _, _) | + Self::TransactionBroadcasted(hash, _) | + Self::TransactionDropped(hash, _) => *hash, + } + } +} + +impl<ChainApi> std::fmt::Debug for TransactionStatusUpdate<ChainApi> where ChainApi: graph::ChainApi, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - ControllerCommand::AddViewStream(h, _) => write!(f, "ListenerAction::AddView({h})"), - ControllerCommand::RemoveViewStream(h) => write!(f, "ListenerAction::RemoveView({h})"), - ControllerCommand::TransactionInvalidated => { - write!(f, "ListenerAction::TransactionInvalidated") + Self::TransactionInvalidated(h) => { + write!(f, "TransactionInvalidated({h})") }, - ControllerCommand::FinalizeTransaction(h, i) => { - write!(f, "ListenerAction::FinalizeTransaction({h},{i})") + Self::TransactionFinalized(h, b, i) => { + write!(f, "FinalizeTransaction({h},{b},{i})") }, - ControllerCommand::TransactionBroadcasted(_) => { - write!(f, "ListenerAction::TransactionBroadcasted(...)") + Self::TransactionBroadcasted(h, _) => { + write!(f, "TransactionBroadcasted({h})") }, - ControllerCommand::TransactionDropped(r) => { - write!(f, "ListenerAction::TransactionDropped {r:?}") + Self::TransactionDropped(h, r) => { + write!(f, "TransactionDropped({h},{r:?})") + }, + } + } +} + +impl<ChainApi> std::fmt::Debug for ControllerCommand<ChainApi> +where + ChainApi: graph::ChainApi, +{ + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ControllerCommand::AddViewStream(h, _) => write!(f, "AddView({h})"), + ControllerCommand::RemoveViewStream(h) => write!(f, "RemoveView({h})"), + ControllerCommand::TransactionStatusRequest(c) => { + write!(f, "TransactionStatusRequest({c:?})") }, } } } +impl<ChainApi> ControllerCommand<ChainApi> +where + ChainApi: graph::ChainApi, +{ + /// Creates new instance of a command requesting [`TransactionStatus::Invalid`] transaction + /// status. + fn new_transaction_invalidated(tx_hash: ExtrinsicHash<ChainApi>) -> Self { + ControllerCommand::TransactionStatusRequest( + TransactionStatusUpdate::TransactionInvalidated(tx_hash), + ) + } + /// Creates new instance of a command requesting [`TransactionStatus::Broadcast`] transaction + /// status. + fn new_transaction_broadcasted(tx_hash: ExtrinsicHash<ChainApi>, peers: Vec<String>) -> Self { + ControllerCommand::TransactionStatusRequest( + TransactionStatusUpdate::TransactionBroadcasted(tx_hash, peers), + ) + } + /// Creates new instance of a command requesting [`TransactionStatus::Finalized`] transaction + /// status. + fn new_transaction_finalized( + tx_hash: ExtrinsicHash<ChainApi>, + block_hash: BlockHash<ChainApi>, + index: TxIndex, + ) -> Self { + ControllerCommand::TransactionStatusRequest(TransactionStatusUpdate::TransactionFinalized( + tx_hash, block_hash, index, + )) + } + /// Creates new instance of a command requesting [`TransactionStatus::Dropped`] transaction + /// status. + fn new_transaction_dropped( + tx_hash: ExtrinsicHash<ChainApi>, + reason: DroppedReason<ExtrinsicHash<ChainApi>>, + ) -> Self { + ControllerCommand::TransactionStatusRequest(TransactionStatusUpdate::TransactionDropped( + tx_hash, reason, + )) + } +} /// This struct allows to create and control listener for multiple transactions. /// -/// For every transaction the view's stream generating its own events can be added. The events are -/// flattened and sent out to the external listener. (The *external* term here means that it can be -/// exposed to [`sc_transaction_pool_api::TransactionPool`] API client e.g. over RPC.) +/// For every view, an aggregated stream of transactions events can be added. The events are +/// flattened and sent out to the external listener for individual transactions. (The *external* +/// term here means that it can be exposed to [`sc_transaction_pool_api::TransactionPool`] API +/// client e.g. over RPC.) /// -/// The listener allows to add and remove view's stream (per transaction). +/// The listener allows to add and remove view's stream. /// /// The listener provides a side channel that allows triggering specific events (finalized, dropped, -/// invalid) independently of the view's stream. +/// invalid, broadcast) independently of the view's stream. pub struct MultiViewListener<ChainApi: graph::ChainApi> { - /// Provides the set of controllers for the events streams corresponding to individual - /// transactions identified by transaction hashes. - controllers: parking_lot::RwLock< - HashMap<ExtrinsicHash<ChainApi>, Controller<ControllerCommand<ChainApi>>>, - >, + /// Provides the controller for sending control commands to the listener's task. + controller: Controller<ControllerCommand<ChainApi>>, + + /// The map containing the sinks of the streams representing the external listeners of + /// the individual transactions. Hash of the transaction is used as a map's key. A map is + /// shared with listener's task. + external_controllers: + Arc<RwLock<HashMap<ExtrinsicHash<ChainApi>, Controller<ExternalWatcherCommand<ChainApi>>>>>, } +/// A type representing a `MultiViewListener` task. For more details refer to +/// [`MultiViewListener::task`]. +pub type MultiViewListenerTask = Pin<Box<dyn Future<Output = ()> + Send>>; + /// The external stream unfolding context. /// -/// This context is used to unfold the external events stream for a single transaction, it -/// facilitates the logic of converting single view's events to the external events stream. +/// This context is used to unfold the external events stream for a individual transaction, it +/// facilitates the logic of converting events incoming from numerous views into the external events +/// stream. struct ExternalWatcherContext<ChainApi: graph::ChainApi> { /// The hash of the transaction being monitored within this context. tx_hash: ExtrinsicHash<ChainApi>, - /// A stream map of transaction status streams coming from individual views, keyed by - /// block hash associated with view. - status_stream_map: StreamMap<BlockHash<ChainApi>, TxStatusStream<ChainApi>>, - /// A receiver for controller commands. - command_receiver: CommandReceiver<ControllerCommand<ChainApi>>, + /// A receiver for controller commands sent by [`MultiViewListener`]'s task. + command_receiver: CommandReceiver<ExternalWatcherCommand<ChainApi>>, /// A flag indicating whether the context should terminate. terminate: bool, /// A flag indicating if a `Future` status has been encountered. future_seen: bool, /// A flag indicating if a `Ready` status has been encountered. ready_seen: bool, - /// A hash set of block hashes from views that consider the transaction valid. views_keeping_tx_valid: HashSet<BlockHash<ChainApi>>, + /// The set of views (represented by block hashes) currently maintained by the transaction + /// pool. + known_views: HashSet<BlockHash<ChainApi>>, +} + +/// Commands to control the single external stream living within the multi view listener. These +/// commands are sent from listener's task to [`ExternalWatcherContext`]. +enum ExternalWatcherCommand<ChainApi: graph::ChainApi> { + /// Command for triggering some of the transaction states, that are decided by the pool logic. + PoolTransactionStatus(TransactionStatusUpdate<ChainApi>), + /// Transaction status updates coming from the individual views. + ViewTransactionStatus( + BlockHash<ChainApi>, + TransactionStatus<ExtrinsicHash<ChainApi>, BlockHash<ChainApi>>, + ), + /// Notification about new view being added. + AddView(BlockHash<ChainApi>), + /// Notification about view being removed. + RemoveView(BlockHash<ChainApi>), } impl<ChainApi: graph::ChainApi> ExternalWatcherContext<ChainApi> @@ -155,39 +261,85 @@ where { /// Creates new `ExternalWatcherContext` for particular transaction identified by `tx_hash` /// - /// The `command_receiver` is a side channel for receiving controller's commands. + /// The `command_receiver` is a side channel for receiving controller's + /// [commands][`ExternalWatcherCommand`]. fn new( tx_hash: ExtrinsicHash<ChainApi>, - command_receiver: CommandReceiver<ControllerCommand<ChainApi>>, + command_receiver: CommandReceiver<ExternalWatcherCommand<ChainApi>>, ) -> Self { Self { tx_hash, - status_stream_map: StreamMap::new(), command_receiver, terminate: false, future_seen: false, ready_seen: false, views_keeping_tx_valid: Default::default(), + known_views: Default::default(), } } - /// Handles various transaction status updates and manages internal states based on the status. + /// Handles transaction status updates from the pool and manages internal states based on the + /// input value. + /// + /// Function may set the context termination flag, which will close the stream. + /// + /// Returns `Some` with the `event` to be sent out or `None`. + fn handle_pool_transaction_status( + &mut self, + request: TransactionStatusUpdate<ChainApi>, + ) -> Option<TransactionStatus<ExtrinsicHash<ChainApi>, BlockHash<ChainApi>>> { + match request { + TransactionStatusUpdate::TransactionInvalidated(..) => + if self.handle_invalidate_transaction() { + log::trace!(target: LOG_TARGET, "[{:?}] mvl sending out: Invalid", self.tx_hash); + return Some(TransactionStatus::Invalid) + }, + TransactionStatusUpdate::TransactionFinalized(_, block, index) => { + log::trace!(target: LOG_TARGET, "[{:?}] mvl sending out: Finalized", self.tx_hash); + self.terminate = true; + return Some(TransactionStatus::Finalized((block, index))) + }, + TransactionStatusUpdate::TransactionBroadcasted(_, peers) => { + log::trace!(target: LOG_TARGET, "[{:?}] mvl sending out: Broadcasted", self.tx_hash); + return Some(TransactionStatus::Broadcast(peers)) + }, + TransactionStatusUpdate::TransactionDropped(_, DroppedReason::LimitsEnforced) => { + log::trace!(target: LOG_TARGET, "[{:?}] mvl sending out: Dropped", self.tx_hash); + self.terminate = true; + return Some(TransactionStatus::Dropped) + }, + TransactionStatusUpdate::TransactionDropped(_, DroppedReason::Usurped(by)) => { + log::trace!(target: LOG_TARGET, "[{:?}] mvl sending out: Usurped({:?})", self.tx_hash, by); + self.terminate = true; + return Some(TransactionStatus::Usurped(by)) + }, + }; + None + } + + /// Handles various transaction status updates from individual views and manages internal states + /// based on the input value. /// /// Function may set the context termination flag, which will close the stream. /// - /// Returns `Some` with the `event` to forward or `None`. - fn handle( + /// Returns `Some` with the `event` to be sent out or `None`. + fn handle_view_transaction_status( &mut self, + block_hash: BlockHash<ChainApi>, status: TransactionStatus<ExtrinsicHash<ChainApi>, BlockHash<ChainApi>>, - hash: BlockHash<ChainApi>, ) -> Option<TransactionStatus<ExtrinsicHash<ChainApi>, BlockHash<ChainApi>>> { trace!( - target: LOG_TARGET, "[{:?}] mvl handle event from {hash:?}: {status:?} views:{:?}", self.tx_hash, - self.status_stream_map.keys().collect::<Vec<_>>() + target: LOG_TARGET, + tx_hash = ?self.tx_hash, + ?block_hash, + ?status, + views = ?self.known_views.iter().collect::<Vec<_>>(), + "mvl handle event" ); + match status { TransactionStatus::Future => { - self.views_keeping_tx_valid.insert(hash); + self.views_keeping_tx_valid.insert(block_hash); if self.ready_seen || self.future_seen { None } else { @@ -196,7 +348,7 @@ where } }, TransactionStatus::Ready => { - self.views_keeping_tx_valid.insert(hash); + self.views_keeping_tx_valid.insert(block_hash); if self.ready_seen { None } else { @@ -204,9 +356,8 @@ where Some(status) } }, - TransactionStatus::Broadcast(_) => None, TransactionStatus::InBlock((..)) => { - self.views_keeping_tx_valid.insert(hash); + self.views_keeping_tx_valid.insert(block_hash); if !(self.ready_seen || self.future_seen) { self.ready_seen = true; Some(status) @@ -214,12 +365,13 @@ where Some(status) } }, - TransactionStatus::Retracted(_) => None, TransactionStatus::FinalityTimeout(_) => Some(status), TransactionStatus::Finalized(_) => { self.terminate = true; Some(status) }, + TransactionStatus::Retracted(_) | + TransactionStatus::Broadcast(_) | TransactionStatus::Usurped(_) | TransactionStatus::Dropped | TransactionStatus::Invalid => None, @@ -233,13 +385,12 @@ where /// Returns true if the event should be sent out, and false if the invalidation request should /// be skipped. fn handle_invalidate_transaction(&mut self) -> bool { - let keys = HashSet::<BlockHash<ChainApi>>::from_iter( - self.status_stream_map.keys().map(Clone::clone), - ); + let keys = self.known_views.clone(); trace!( target: LOG_TARGET, - "[{:?}] got invalidate_transaction: views:{:?}", self.tx_hash, - self.status_stream_map.keys().collect::<Vec<_>>() + tx_hash = ?self.tx_hash, + views = ?self.known_views.iter().collect::<Vec<_>>(), + "got invalidate_transaction" ); if self.views_keeping_tx_valid.is_disjoint(&keys) { self.terminate = true; @@ -255,23 +406,35 @@ where } } - /// Adds a new transaction status stream. + /// Adds a new aggragted transaction status stream. /// - /// Inserts a new view's transaction status stream associated with a specific block hash into - /// the stream map. - fn add_stream(&mut self, block_hash: BlockHash<ChainApi>, stream: TxStatusStream<ChainApi>) { - self.status_stream_map.insert(block_hash, stream); - trace!(target: LOG_TARGET, "[{:?}] AddView view: {:?} views:{:?}", self.tx_hash, block_hash, self.status_stream_map.keys().collect::<Vec<_>>()); + /// Inserts a new view's transaction status stream into the stream map. The view is represented + /// by `block_hash`. + fn add_view(&mut self, block_hash: BlockHash<ChainApi>) { + trace!( + target: LOG_TARGET, + tx_hash = ?self.tx_hash, + ?block_hash, + views = ?self.known_views.iter().collect::<Vec<_>>(), + "AddView view" + ); + self.known_views.insert(block_hash); } - /// Removes an existing transaction status stream. + /// Removes an existing aggreagated transaction status stream. /// - /// Removes a transaction status stream associated with a specific block hash from the - /// stream map. + /// Removes an aggregated transaction status stream associated with a specific block hash from + /// the stream map. fn remove_view(&mut self, block_hash: BlockHash<ChainApi>) { - self.status_stream_map.remove(&block_hash); + self.known_views.remove(&block_hash); self.views_keeping_tx_valid.remove(&block_hash); - trace!(target: LOG_TARGET, "[{:?}] RemoveView view: {:?} views:{:?}", self.tx_hash, block_hash, self.status_stream_map.keys().collect::<Vec<_>>()); + trace!( + target: LOG_TARGET, + tx_hash = ?self.tx_hash, + ?block_hash, + views = ?self.known_views.iter().collect::<Vec<_>>(), + "RemoveView view" + ); } } @@ -280,89 +443,180 @@ where ChainApi: graph::ChainApi + 'static, <<ChainApi as graph::ChainApi>::Block as BlockT>::Hash: Unpin, { - /// Creates new instance of `MultiViewListener`. - pub fn new() -> Self { - Self { controllers: Default::default() } + /// A worker task associated with `MultiViewListener` instance. + /// + /// An asynchronous listener's task responsible for dispatching: + /// - stream_map containing aggregated transaction status streams from multiple views, + /// - view add/remove requests, + /// - transaction commands, + /// to multiple individual per-transaction external watcher contexts. + /// + /// The future shall be polled by instantiator of `MultiViewListener`. + async fn task( + external_watchers_tx_hash_map: Arc< + RwLock<HashMap<ExtrinsicHash<ChainApi>, Controller<ExternalWatcherCommand<ChainApi>>>>, + >, + mut command_receiver: CommandReceiver<ControllerCommand<ChainApi>>, + ) { + let mut aggregated_streams_map: StreamMap<BlockHash<ChainApi>, ViewStatusStream<ChainApi>> = + Default::default(); + + loop { + tokio::select! { + biased; + Some((view_hash, (tx_hash, status))) = next_event(&mut aggregated_streams_map) => { + if let Entry::Occupied(mut ctrl) = external_watchers_tx_hash_map.write().entry(tx_hash) { + log::trace!( + target: LOG_TARGET, + "[{:?}] aggregated_stream_map event: view:{} status:{:?}", + tx_hash, + view_hash, + status + ); + if let Err(e) = ctrl + .get_mut() + .unbounded_send(ExternalWatcherCommand::ViewTransactionStatus(view_hash, status)) + { + trace!(target: LOG_TARGET, "[{:?}] send status failed: {:?}", tx_hash, e); + ctrl.remove(); + } + } + }, + cmd = command_receiver.next() => { + log::trace!(target: LOG_TARGET, "cmd {:?}", cmd); + match cmd { + Some(ControllerCommand::AddViewStream(h,stream)) => { + aggregated_streams_map.insert(h,stream); + // //todo: aysnc and join all? + external_watchers_tx_hash_map.write().retain(|tx_hash, ctrl| { + ctrl.unbounded_send(ExternalWatcherCommand::AddView(h)) + .inspect_err(|e| { + trace!(target: LOG_TARGET, "[{:?}] invalidate_transaction: send message failed: {:?}", tx_hash, e); + }) + .is_ok() + }) + }, + Some(ControllerCommand::RemoveViewStream(h)) => { + aggregated_streams_map.remove(&h); + //todo: aysnc and join all? + external_watchers_tx_hash_map.write().retain(|tx_hash, ctrl| { + ctrl.unbounded_send(ExternalWatcherCommand::RemoveView(h)) + .inspect_err(|e| { + trace!(target: LOG_TARGET, "[{:?}] invalidate_transaction: send message failed: {:?}", tx_hash, e); + }) + .is_ok() + }) + }, + + Some(ControllerCommand::TransactionStatusRequest(request)) => { + let tx_hash = request.hash(); + if let Entry::Occupied(mut ctrl) = external_watchers_tx_hash_map.write().entry(tx_hash) { + if let Err(e) = ctrl + .get_mut() + .unbounded_send(ExternalWatcherCommand::PoolTransactionStatus(request)) + { + trace!(target: LOG_TARGET, "[{:?}] send message failed: {:?}", tx_hash, e); + ctrl.remove(); + } + } + }, + None => {} + } + }, + }; + } } - /// Returns `true` if the listener contains a stream controller for the specified hash. - pub fn contains_tx(&self, tx_hash: &ExtrinsicHash<ChainApi>) -> bool { - self.controllers.read().contains_key(tx_hash) + /// Creates a new [`MultiViewListener`] instance along with its associated worker task. + /// + /// This function instansiates the new `MultiViewListener` and provides the worker task that + /// relays messages to the external transactions listeners. The task shall be polled by caller. + /// + /// Returns a tuple containing the [`MultiViewListener`] and the + /// [`MultiViewListenerTask`]. + pub fn new_with_worker() -> (Self, MultiViewListenerTask) { + let external_controllers = Arc::from(RwLock::from(HashMap::< + ExtrinsicHash<ChainApi>, + Controller<ExternalWatcherCommand<ChainApi>>, + >::default())); + + const CONTROLLER_QUEUE_WARN_SIZE: usize = 100_000; + let (tx, rx) = mpsc::tracing_unbounded( + "txpool-multi-view-listener-task-controller", + CONTROLLER_QUEUE_WARN_SIZE, + ); + let task = Self::task(external_controllers.clone(), rx); + + (Self { external_controllers, controller: tx }, task.boxed()) } - /// Creates an external aggregated stream of events for given transaction. + /// Creates an external tstream of events for given transaction. /// /// This method initializes an `ExternalWatcherContext` for the provided transaction hash, sets - /// up the necessary communication channels, and unfolds an external (meaning that it can be - /// exposed to [`sc_transaction_pool_api::TransactionPool`] API client e.g. rpc) stream of - /// transaction status events. If an external watcher is already present for the given - /// transaction, it returns `None`. + /// up the necessary communication channel with listener's task, and unfolds an external + /// (meaning that it can be exposed to [`sc_transaction_pool_api::TransactionPool`] API client + /// e.g. rpc) stream of transaction status events. If an external watcher is already present for + /// the given transaction, it returns `None`. pub(crate) fn create_external_watcher_for_tx( &self, tx_hash: ExtrinsicHash<ChainApi>, ) -> Option<TxStatusStream<ChainApi>> { - let mut controllers = self.controllers.write(); - if controllers.contains_key(&tx_hash) { - return None - } - - trace!(target: LOG_TARGET, "[{:?}] create_external_watcher_for_tx", tx_hash); - - let (tx, rx) = mpsc::tracing_unbounded("txpool-multi-view-listener", 32); - controllers.insert(tx_hash, tx); + let external_ctx = match self.external_controllers.write().entry(tx_hash) { + Entry::Occupied(_) => return None, + Entry::Vacant(entry) => { + const EXT_CONTROLLER_QUEUE_WARN_THRESHOLD: usize = 128; + let (tx, rx) = mpsc::tracing_unbounded( + "txpool-multi-view-listener", + EXT_CONTROLLER_QUEUE_WARN_THRESHOLD, + ); + entry.insert(tx); + ExternalWatcherContext::new(tx_hash, rx) + }, + }; - let ctx = ExternalWatcherContext::new(tx_hash, rx); + trace!( + target: LOG_TARGET, + ?tx_hash, + "create_external_watcher_for_tx" + ); Some( - futures::stream::unfold(ctx, |mut ctx| async move { + futures::stream::unfold(external_ctx, |mut ctx| async move { if ctx.terminate { + log::trace!(target: LOG_TARGET, "[{:?}] terminate", ctx.tx_hash); return None } loop { tokio::select! { - biased; - Some((view_hash, status)) = next_event(&mut ctx.status_stream_map) => { - if let Some(new_status) = ctx.handle(status, view_hash) { - log::trace!(target: LOG_TARGET, "[{:?}] mvl sending out: {new_status:?}", ctx.tx_hash); - return Some((new_status, ctx)) - } - }, cmd = ctx.command_receiver.next() => { - log::trace!(target: LOG_TARGET, "[{:?}] select::rx views:{:?}", - ctx.tx_hash, - ctx.status_stream_map.keys().collect::<Vec<_>>() - ); match cmd? { - ControllerCommand::AddViewStream(h,stream) => { - ctx.add_stream(h, stream); - }, - ControllerCommand::RemoveViewStream(h) => { - ctx.remove_view(h); - }, - ControllerCommand::TransactionInvalidated => { - if ctx.handle_invalidate_transaction() { - log::trace!(target: LOG_TARGET, "[{:?}] mvl sending out: Invalid", ctx.tx_hash); - return Some((TransactionStatus::Invalid, ctx)) + ExternalWatcherCommand::ViewTransactionStatus(view_hash, status) => { + if let Some(new_status) = ctx.handle_view_transaction_status(view_hash, status) { + trace!( + target: LOG_TARGET, + tx_hash = ?ctx.tx_hash, + ?new_status, + "mvl sending out" + ); + return Some((new_status, ctx)) } }, - ControllerCommand::FinalizeTransaction(block, index) => { - log::trace!(target: LOG_TARGET, "[{:?}] mvl sending out: Finalized", ctx.tx_hash); - ctx.terminate = true; - return Some((TransactionStatus::Finalized((block, index)), ctx)) - }, - ControllerCommand::TransactionBroadcasted(peers) => { - log::trace!(target: LOG_TARGET, "[{:?}] mvl sending out: Broadcasted", ctx.tx_hash); - return Some((TransactionStatus::Broadcast(peers), ctx)) - }, - ControllerCommand::TransactionDropped(DroppedReason::LimitsEnforced) => { - log::trace!(target: LOG_TARGET, "[{:?}] mvl sending out: Dropped", ctx.tx_hash); - ctx.terminate = true; - return Some((TransactionStatus::Dropped, ctx)) + ExternalWatcherCommand::PoolTransactionStatus(request) => { + if let Some(new_status) = ctx.handle_pool_transaction_status(request) { + trace!( + target: LOG_TARGET, + tx_hash = ?ctx.tx_hash, + ?new_status, + "mvl sending out" + ); + return Some((new_status, ctx)) + } + } + ExternalWatcherCommand::AddView(h) => { + ctx.add_view(h); }, - ControllerCommand::TransactionDropped(DroppedReason::Usurped(by)) => { - log::trace!(target: LOG_TARGET, "[{:?}] mvl sending out: Usurped({:?})", ctx.tx_hash, by); - ctx.terminate = true; - return Some((TransactionStatus::Usurped(by), ctx)) + ExternalWatcherCommand::RemoveView(h) => { + ctx.remove_view(h); }, } }, @@ -373,124 +627,142 @@ where ) } - /// Adds a view's transaction status stream for particular transaction. + /// Adds an aggregated view's transaction status stream. + /// + /// This method sends a `AddViewStream` command to the task, from where it is further dispatched + /// to the external watcher context for every watched transaction. /// - /// This method sends a `AddViewStream` command to the controller of each transaction to - /// remove the view's stream corresponding to the given block hash. - pub(crate) fn add_view_watcher_for_tx( + /// The stream is associated with a view represented by `block_hash`. + pub(crate) fn add_view_aggregated_stream( &self, - tx_hash: ExtrinsicHash<ChainApi>, block_hash: BlockHash<ChainApi>, - stream: TxStatusStream<ChainApi>, + stream: ViewStatusStream<ChainApi>, ) { - let mut controllers = self.controllers.write(); - - if let Entry::Occupied(mut tx) = controllers.entry(tx_hash) { - if let Err(e) = tx - .get_mut() - .unbounded_send(ControllerCommand::AddViewStream(block_hash, stream)) - { - trace!(target: LOG_TARGET, "[{:?}] add_view_watcher_for_tx: send message failed: {:?}", tx_hash, e); - tx.remove(); - } + trace!(target: LOG_TARGET, ?block_hash, "mvl::add_view_aggregated_stream"); + if let Err(error) = self + .controller + .unbounded_send(ControllerCommand::AddViewStream(block_hash, stream)) + { + trace!( + target: LOG_TARGET, + ?block_hash, + %error, + "add_view_aggregated_stream: send message failed" + ); } } - /// Removes a view's stream associated with a specific view hash across all transactions. + /// Removes a view's stream associated with a specific view hash. /// - /// This method sends a `RemoveViewStream` command to the controller of each transaction to - /// remove the view's stream corresponding to the given block hash. + /// This method sends a `RemoveViewStream` command to the listener's task, from where is further + /// dispatched to the external watcher context for every watched transaction. pub(crate) fn remove_view(&self, block_hash: BlockHash<ChainApi>) { - self.controllers.write().retain(|tx_hash, sender| { - sender - .unbounded_send(ControllerCommand::RemoveViewStream(block_hash)) - .map_err(|e| { - log::trace!(target: LOG_TARGET, "[{:?}] remove_view: send message failed: {:?}", tx_hash, e); - e - }) - .is_ok() - }); + trace!(target: LOG_TARGET, ?block_hash, "mvl::remove_view"); + if let Err(error) = + self.controller.unbounded_send(ControllerCommand::RemoveViewStream(block_hash)) + { + trace!( + target: LOG_TARGET, + ?block_hash, + %error, + "remove_view: send message failed" + ); + } } /// Invalidate given transaction. /// - /// This method sends a `TransactionInvalidated` command to the controller of each transaction - /// provided to process the invalidation request. + /// This method sends a `TransactionInvalidated` command to the task's controller of each + /// transaction provided to process the invalidation request. /// /// The external event will be sent if no view is referencing the transaction as `Ready` or /// `Future`. - pub(crate) fn invalidate_transactions(&self, invalid_hashes: &[ExtrinsicHash<ChainApi>]) { - let mut controllers = self.controllers.write(); - invalid_hashes.iter().for_each(|tx_hash| { - if let Entry::Occupied(mut tx) = controllers.entry(*tx_hash) { - trace!(target: LOG_TARGET, "[{:?}] invalidate_transaction", tx_hash); - if let Err(e) = - tx.get_mut().unbounded_send(ControllerCommand::TransactionInvalidated) - { - trace!(target: LOG_TARGET, "[{:?}] invalidate_transaction: send message failed: {:?}", tx_hash, e); - tx.remove(); - } + pub(crate) fn transactions_invalidated(&self, invalid_hashes: &[ExtrinsicHash<ChainApi>]) { + log_xt_trace!(target: LOG_TARGET, invalid_hashes, "transactions_invalidated"); + for tx_hash in invalid_hashes { + if let Err(error) = self + .controller + .unbounded_send(ControllerCommand::new_transaction_invalidated(*tx_hash)) + { + trace!( + target: LOG_TARGET, + ?tx_hash, + %error, + "transactions_invalidated: send message failed" + ); } - }); + } } /// Send `Broadcasted` event to listeners of all transactions. /// - /// This method sends a `TransactionBroadcasted` command to the controller of each transaction - /// provided prompting the external `Broadcasted` event. + /// This method sends a `TransactionBroadcasted` command to the task's controller for each + /// transaction provided. It will prompt the external `Broadcasted` event. pub(crate) fn transactions_broadcasted( &self, propagated: HashMap<ExtrinsicHash<ChainApi>, Vec<String>>, ) { - let mut controllers = self.controllers.write(); - propagated.into_iter().for_each(|(tx_hash, peers)| { - if let Entry::Occupied(mut tx) = controllers.entry(tx_hash) { - trace!(target: LOG_TARGET, "[{:?}] transaction_broadcasted", tx_hash); - if let Err(e) = tx.get_mut().unbounded_send(ControllerCommand::TransactionBroadcasted(peers)) { - trace!(target: LOG_TARGET, "[{:?}] transactions_broadcasted: send message failed: {:?}", tx_hash, e); - tx.remove(); - } + for (tx_hash, peers) in propagated { + if let Err(error) = self + .controller + .unbounded_send(ControllerCommand::new_transaction_broadcasted(tx_hash, peers)) + { + trace!( + target: LOG_TARGET, + ?tx_hash, + %error, + "transactions_broadcasted: send message failed" + ); } - }); + } } /// Send `Dropped` event to listeners of transactions. /// - /// This method sends a `TransactionDropped` command to the controller of each requested - /// transaction prompting and external `Broadcasted` event. + /// This method sends a `TransactionDropped` command to the task's controller. It will prompt + /// the external `Broadcasted` event. pub(crate) fn transaction_dropped(&self, dropped: DroppedTransaction<ExtrinsicHash<ChainApi>>) { - let mut controllers = self.controllers.write(); - debug!(target: LOG_TARGET, "mvl::transaction_dropped: {:?}", dropped); - if let Some(tx) = controllers.remove(&dropped.tx_hash) { - let DroppedTransaction { tx_hash, reason } = dropped; - debug!(target: LOG_TARGET, "[{:?}] transaction_dropped", tx_hash); - if let Err(e) = tx.unbounded_send(ControllerCommand::TransactionDropped(reason)) { - trace!(target: LOG_TARGET, "[{:?}] transaction_dropped: send message failed: {:?}", tx_hash, e); - }; + let DroppedTransaction { tx_hash, reason } = dropped; + trace!(target: LOG_TARGET, ?tx_hash, ?reason, "transaction_dropped"); + if let Err(error) = self + .controller + .unbounded_send(ControllerCommand::new_transaction_dropped(tx_hash, reason)) + { + trace!( + target: LOG_TARGET, + ?tx_hash, + %error, + "transaction_dropped: send message failed" + ); } } /// Send `Finalized` event for given transaction at given block. /// - /// This will send `Finalized` event to the external watcher. - pub(crate) fn finalize_transaction( + /// This will trigger `Finalized` event to the external watcher. + pub(crate) fn transaction_finalized( &self, tx_hash: ExtrinsicHash<ChainApi>, block: BlockHash<ChainApi>, idx: TxIndex, ) { - let mut controllers = self.controllers.write(); - if let Some(tx) = controllers.remove(&tx_hash) { - trace!(target: LOG_TARGET, "[{:?}] finalize_transaction", tx_hash); - if let Err(e) = tx.unbounded_send(ControllerCommand::FinalizeTransaction(block, idx)) { - trace!(target: LOG_TARGET, "[{:?}] finalize_transaction: send message failed: {:?}", tx_hash, e); - } + trace!(target: LOG_TARGET, ?tx_hash, "transaction_finalized"); + if let Err(error) = self + .controller + .unbounded_send(ControllerCommand::new_transaction_finalized(tx_hash, block, idx)) + { + trace!( + target: LOG_TARGET, + ?tx_hash, + %error, + "transaction_finalized: send message failed" + ); }; } /// Removes stale controllers. pub(crate) fn remove_stale_controllers(&self) { - self.controllers.write().retain(|_, c| !c.is_closed()); + self.external_controllers.write().retain(|_, c| !c.is_closed()); } } @@ -500,38 +772,60 @@ mod tests { use crate::common::tests::TestApi; use futures::{stream, StreamExt}; use sp_core::H256; + use tokio::{select, task::JoinHandle}; + use tracing::debug; type MultiViewListener = super::MultiViewListener<TestApi>; + fn create_multi_view_listener( + ) -> (MultiViewListener, tokio::sync::oneshot::Sender<()>, JoinHandle<()>) { + let (listener, listener_task) = MultiViewListener::new_with_worker(); + + let (tx, rx) = tokio::sync::oneshot::channel(); + + let listener_handle = tokio::spawn(async move { + select! { + _ = listener_task => {}, + _ = rx => { return; } + } + }); + + (listener, tx, listener_handle) + } + #[tokio::test] async fn test01() { sp_tracing::try_init_simple(); - let listener = MultiViewListener::new(); + let (listener, terminate_listener, listener_task) = create_multi_view_listener(); let block_hash = H256::repeat_byte(0x01); + let tx_hash = H256::repeat_byte(0x0a); let events = vec![ TransactionStatus::Ready, TransactionStatus::InBlock((block_hash, 0)), TransactionStatus::Finalized((block_hash, 0)), ]; - let tx_hash = H256::repeat_byte(0x0a); let external_watcher = listener.create_external_watcher_for_tx(tx_hash).unwrap(); let handle = tokio::spawn(async move { external_watcher.collect::<Vec<_>>().await }); - let view_stream = futures::stream::iter(events.clone()); + let view_stream = + futures::stream::iter(std::iter::repeat(tx_hash).zip(events.clone().into_iter())); - listener.add_view_watcher_for_tx(tx_hash, block_hash, view_stream.boxed()); + listener.add_view_aggregated_stream(block_hash, view_stream.boxed()); let out = handle.await.unwrap(); assert_eq!(out, events); - log::debug!("out: {:#?}", out); + debug!("out: {:#?}", out); + + let _ = terminate_listener.send(()); + let _ = listener_task.await.unwrap(); } #[tokio::test] async fn test02() { sp_tracing::try_init_simple(); - let listener = MultiViewListener::new(); + let (listener, terminate_listener, listener_task) = create_multi_view_listener(); let block_hash0 = H256::repeat_byte(0x01); let events0 = vec![ @@ -550,17 +844,19 @@ mod tests { let tx_hash = H256::repeat_byte(0x0a); let external_watcher = listener.create_external_watcher_for_tx(tx_hash).unwrap(); - let view_stream0 = futures::stream::iter(events0.clone()); - let view_stream1 = futures::stream::iter(events1.clone()); + let view_stream0 = + futures::stream::iter(std::iter::repeat(tx_hash).zip(events0.clone().into_iter())); + let view_stream1 = + futures::stream::iter(std::iter::repeat(tx_hash).zip(events1.clone().into_iter())); let handle = tokio::spawn(async move { external_watcher.collect::<Vec<_>>().await }); - listener.add_view_watcher_for_tx(tx_hash, block_hash0, view_stream0.boxed()); - listener.add_view_watcher_for_tx(tx_hash, block_hash1, view_stream1.boxed()); + listener.add_view_aggregated_stream(block_hash0, view_stream0.boxed()); + listener.add_view_aggregated_stream(block_hash1, view_stream1.boxed()); let out = handle.await.unwrap(); - log::debug!("out: {:#?}", out); + debug!("out: {:#?}", out); assert!(out.iter().all(|v| vec![ TransactionStatus::Future, TransactionStatus::Ready, @@ -570,12 +866,15 @@ mod tests { ] .contains(v))); assert_eq!(out.len(), 5); + + let _ = terminate_listener.send(()); + let _ = listener_task.await.unwrap(); } #[tokio::test] async fn test03() { sp_tracing::try_init_simple(); - let listener = MultiViewListener::new(); + let (listener, terminate_listener, listener_task) = create_multi_view_listener(); let block_hash0 = H256::repeat_byte(0x01); let events0 = vec![ @@ -591,16 +890,21 @@ mod tests { let external_watcher = listener.create_external_watcher_for_tx(tx_hash).unwrap(); let handle = tokio::spawn(async move { external_watcher.collect::<Vec<_>>().await }); - let view_stream0 = futures::stream::iter(events0.clone()); - let view_stream1 = futures::stream::iter(events1.clone()); + let view_stream0 = + futures::stream::iter(std::iter::repeat(tx_hash).zip(events0.clone().into_iter())); + let view_stream1 = + futures::stream::iter(std::iter::repeat(tx_hash).zip(events1.clone().into_iter())); - listener.add_view_watcher_for_tx(tx_hash, block_hash0, view_stream0.boxed()); - listener.add_view_watcher_for_tx(tx_hash, block_hash1, view_stream1.boxed()); + listener.add_view_aggregated_stream(block_hash0, view_stream0.boxed()); + listener.add_view_aggregated_stream(block_hash1, view_stream1.boxed()); - listener.invalidate_transactions(&[tx_hash]); + listener.remove_view(block_hash0); + listener.remove_view(block_hash1); + + listener.transactions_invalidated(&[tx_hash]); let out = handle.await.unwrap(); - log::debug!("out: {:#?}", out); + debug!("out: {:#?}", out); assert!(out.iter().all(|v| vec![ TransactionStatus::Future, TransactionStatus::Ready, @@ -609,12 +913,15 @@ mod tests { ] .contains(v))); assert_eq!(out.len(), 4); - } + let _ = terminate_listener.send(()); + let _ = listener_task.await.unwrap(); + } + // #[tokio::test] async fn test032() { sp_tracing::try_init_simple(); - let listener = MultiViewListener::new(); + let (listener, terminate_listener, listener_task) = create_multi_view_listener(); let block_hash0 = H256::repeat_byte(0x01); let events0_tx0 = vec![TransactionStatus::Future]; @@ -637,25 +944,32 @@ mod tests { let handle0 = tokio::spawn(async move { external_watcher_tx0.collect::<Vec<_>>().await }); let handle1 = tokio::spawn(async move { external_watcher_tx1.collect::<Vec<_>>().await }); - let view0_tx0_stream = futures::stream::iter(events0_tx0.clone()); - let view0_tx1_stream = futures::stream::iter(events0_tx1.clone()); + let view0_tx0_stream = + futures::stream::iter(std::iter::repeat(tx0_hash).zip(events0_tx0.clone())); + let view0_tx1_stream = + futures::stream::iter(std::iter::repeat(tx1_hash).zip(events0_tx1.clone())); + + let view1_tx0_stream = + futures::stream::iter(std::iter::repeat(tx0_hash).zip(events1_tx0.clone())); + let view1_tx1_stream = + futures::stream::iter(std::iter::repeat(tx1_hash).zip(events1_tx1.clone())); - let view1_tx0_stream = futures::stream::iter(events1_tx0.clone()); - let view1_tx1_stream = futures::stream::iter(events1_tx1.clone()); + listener.add_view_aggregated_stream(block_hash0, view0_tx0_stream.boxed()); + listener.add_view_aggregated_stream(block_hash1, view1_tx0_stream.boxed()); + listener.add_view_aggregated_stream(block_hash0, view0_tx1_stream.boxed()); + listener.add_view_aggregated_stream(block_hash1, view1_tx1_stream.boxed()); - listener.add_view_watcher_for_tx(tx0_hash, block_hash0, view0_tx0_stream.boxed()); - listener.add_view_watcher_for_tx(tx0_hash, block_hash1, view1_tx0_stream.boxed()); - listener.add_view_watcher_for_tx(tx1_hash, block_hash0, view0_tx1_stream.boxed()); - listener.add_view_watcher_for_tx(tx1_hash, block_hash1, view1_tx1_stream.boxed()); + listener.remove_view(block_hash0); + listener.remove_view(block_hash1); - listener.invalidate_transactions(&[tx0_hash]); - listener.invalidate_transactions(&[tx1_hash]); + listener.transactions_invalidated(&[tx0_hash]); + listener.transactions_invalidated(&[tx1_hash]); let out_tx0 = handle0.await.unwrap(); let out_tx1 = handle1.await.unwrap(); - log::debug!("out_tx0: {:#?}", out_tx0); - log::debug!("out_tx1: {:#?}", out_tx1); + debug!("out_tx0: {:#?}", out_tx0); + debug!("out_tx1: {:#?}", out_tx1); assert!(out_tx0.iter().all(|v| vec![ TransactionStatus::Future, TransactionStatus::Ready, @@ -672,12 +986,15 @@ mod tests { .contains(v))); assert_eq!(out_tx0.len(), 4); assert_eq!(out_tx1.len(), 3); + + let _ = terminate_listener.send(()); + let _ = listener_task.await.unwrap(); } #[tokio::test] async fn test04() { sp_tracing::try_init_simple(); - let listener = MultiViewListener::new(); + let (listener, terminate_listener, listener_task) = create_multi_view_listener(); let block_hash0 = H256::repeat_byte(0x01); let events0 = vec![ @@ -693,21 +1010,23 @@ mod tests { let external_watcher = listener.create_external_watcher_for_tx(tx_hash).unwrap(); //views will keep transaction valid, invalidation shall not happen - let view_stream0 = futures::stream::iter(events0.clone()).chain(stream::pending().boxed()); - let view_stream1 = futures::stream::iter(events1.clone()).chain(stream::pending().boxed()); + let view_stream0 = futures::stream::iter(std::iter::repeat(tx_hash).zip(events0.clone())) + .chain(stream::pending().boxed()); + let view_stream1 = futures::stream::iter(std::iter::repeat(tx_hash).zip(events1.clone())) + .chain(stream::pending().boxed()); let handle = tokio::spawn(async move { // views are still there, we need to fetch 3 events external_watcher.take(3).collect::<Vec<_>>().await }); - listener.add_view_watcher_for_tx(tx_hash, block_hash0, view_stream0.boxed()); - listener.add_view_watcher_for_tx(tx_hash, block_hash1, view_stream1.boxed()); + listener.add_view_aggregated_stream(block_hash0, view_stream0.boxed()); + listener.add_view_aggregated_stream(block_hash1, view_stream1.boxed()); - listener.invalidate_transactions(&[tx_hash]); + listener.transactions_invalidated(&[tx_hash]); let out = handle.await.unwrap(); - log::debug!("out: {:#?}", out); + debug!("out: {:#?}", out); // invalid shall not be sent assert!(out.iter().all(|v| vec![ @@ -717,12 +1036,14 @@ mod tests { ] .contains(v))); assert_eq!(out.len(), 3); + let _ = terminate_listener.send(()); + let _ = listener_task.await.unwrap(); } #[tokio::test] async fn test05() { sp_tracing::try_init_simple(); - let listener = MultiViewListener::new(); + let (listener, terminate_listener, listener_task) = create_multi_view_listener(); let block_hash0 = H256::repeat_byte(0x01); let events0 = vec![TransactionStatus::Invalid]; @@ -731,18 +1052,24 @@ mod tests { let external_watcher = listener.create_external_watcher_for_tx(tx_hash).unwrap(); let handle = tokio::spawn(async move { external_watcher.collect::<Vec<_>>().await }); - let view_stream0 = futures::stream::iter(events0.clone()).chain(stream::pending().boxed()); + let view_stream0 = futures::stream::iter(std::iter::repeat(tx_hash).zip(events0.clone())) + .chain(stream::pending().boxed()); // Note: this generates actual Invalid event. - // Invalid event from View's stream is intentionally ignored. - listener.invalidate_transactions(&[tx_hash]); + // Invalid event from View's stream is intentionally ignored . + // we need to explicitely remove the view + listener.remove_view(block_hash0); + listener.transactions_invalidated(&[tx_hash]); - listener.add_view_watcher_for_tx(tx_hash, block_hash0, view_stream0.boxed()); + listener.add_view_aggregated_stream(block_hash0, view_stream0.boxed()); let out = handle.await.unwrap(); - log::debug!("out: {:#?}", out); + debug!("out: {:#?}", out); assert!(out.iter().all(|v| vec![TransactionStatus::Invalid].contains(v))); assert_eq!(out.len(), 1); + + let _ = terminate_listener.send(()); + let _ = listener_task.await.unwrap(); } } diff --git a/substrate/client/transaction-pool/src/fork_aware_txpool/revalidation_worker.rs b/substrate/client/transaction-pool/src/fork_aware_txpool/revalidation_worker.rs index e1c65a08a70ba00c22c4b5c7a3d89e88e219399f..0025d3e9f2d42aad0db1c1747fe9e4cc9d7476ef 100644 --- a/substrate/client/transaction-pool/src/fork_aware_txpool/revalidation_worker.rs +++ b/substrate/client/transaction-pool/src/fork_aware_txpool/revalidation_worker.rs @@ -30,6 +30,7 @@ use sp_runtime::traits::Block as BlockT; use super::tx_mem_pool::TxMemPool; use futures::prelude::*; +use tracing::{trace, warn}; use super::view::{FinishRevalidationWorkerChannels, View}; @@ -131,18 +132,22 @@ where view: Arc<View<Api>>, finish_revalidation_worker_channels: FinishRevalidationWorkerChannels<Api>, ) { - log::trace!( + trace!( target: LOG_TARGET, - "revalidation_queue::revalidate_view: Sending view to revalidation queue at {}", - view.at.hash + view_at_hash = ?view.at.hash, + "revalidation_queue::revalidate_view: Sending view to revalidation queue" ); if let Some(ref to_worker) = self.background { - if let Err(e) = to_worker.unbounded_send(WorkerPayload::RevalidateView( + if let Err(error) = to_worker.unbounded_send(WorkerPayload::RevalidateView( view, finish_revalidation_worker_channels, )) { - log::warn!(target: LOG_TARGET, "revalidation_queue::revalidate_view: Failed to update background worker: {:?}", e); + warn!( + target: LOG_TARGET, + ?error, + "revalidation_queue::revalidate_view: Failed to update background worker" + ); } } else { view.revalidate(finish_revalidation_worker_channels).await @@ -161,17 +166,21 @@ where mempool: Arc<TxMemPool<Api, Block>>, finalized_hash: HashAndNumber<Block>, ) { - log::trace!( + trace!( target: LOG_TARGET, - "Sent mempool to revalidation queue at hash: {:?}", - finalized_hash + ?finalized_hash, + "Sent mempool to revalidation queue" ); if let Some(ref to_worker) = self.background { - if let Err(e) = + if let Err(error) = to_worker.unbounded_send(WorkerPayload::RevalidateMempool(mempool, finalized_hash)) { - log::warn!(target: LOG_TARGET, "Failed to update background worker: {:?}", e); + warn!( + target: LOG_TARGET, + ?error, + "Failed to update background worker" + ); } } else { mempool.revalidate(finalized_hash).await diff --git a/substrate/client/transaction-pool/src/fork_aware_txpool/tx_mem_pool.rs b/substrate/client/transaction-pool/src/fork_aware_txpool/tx_mem_pool.rs index c8a4d0c72dd36ab933f2713cf956e2752973c92c..e141016ccb28b39a1be816478c0f6da748d875ce 100644 --- a/substrate/client/transaction-pool/src/fork_aware_txpool/tx_mem_pool.rs +++ b/substrate/client/transaction-pool/src/fork_aware_txpool/tx_mem_pool.rs @@ -26,33 +26,38 @@ //! it), while on other forks tx can be valid. Depending on which view is chosen to be cloned, //! such transaction could not be present in the newly created view. -use super::{ - metrics::MetricsLink as PrometheusMetrics, multi_view_listener::MultiViewListener, - view_store::ViewStoreSubmitOutcome, -}; -use crate::{ - common::log_xt::log_xt_trace, - graph, - graph::{base_pool::TimedTransactionSource, tracked_map::Size, ExtrinsicFor, ExtrinsicHash}, - LOG_TARGET, +use std::{ + cmp::Ordering, + collections::HashMap, + sync::{ + atomic::{self, AtomicU64}, + Arc, + }, + time::Instant, }; + use futures::FutureExt; use itertools::Itertools; use parking_lot::RwLock; +use tracing::{debug, trace}; + use sc_transaction_pool_api::{TransactionPriority, TransactionSource}; use sp_blockchain::HashAndNumber; use sp_runtime::{ traits::Block as BlockT, transaction_validity::{InvalidTransaction, TransactionValidityError}, }; -use std::{ - cmp::Ordering, - collections::HashMap, - sync::{ - atomic::{self, AtomicU64}, - Arc, - }, - time::Instant, + +use crate::{ + common::tracing_log_xt::log_xt_trace, + graph, + graph::{base_pool::TimedTransactionSource, tracked_map::Size, ExtrinsicFor, ExtrinsicHash}, + LOG_TARGET, +}; + +use super::{ + metrics::MetricsLink as PrometheusMetrics, multi_view_listener::MultiViewListener, + view_store::ViewStoreSubmitOutcome, }; /// The minimum interval between single transaction revalidations. Given in blocks. @@ -72,10 +77,10 @@ where Block: BlockT, ChainApi: graph::ChainApi<Block = Block> + 'static, { - //todo: add listener for updating listeners with events [#5495] /// Is the progress of transaction watched. /// - /// Was transaction sent with `submit_and_watch`. + /// Indicates if transaction was sent with `submit_and_watch`. Serves only stats/testing + /// purposes. watched: bool, /// Extrinsic actual body. tx: ExtrinsicFor<ChainApi>, @@ -88,14 +93,6 @@ where /// Priority of transaction at some block. It is assumed it will not be changed often. None if /// not known. priority: RwLock<Option<TransactionPriority>>, - //todo: we need to add future / ready status at finalized block. - //If future transactions are stuck in tx_mem_pool (due to limits being hit), we need a means - // to replace them somehow with newly coming transactions. - // For sure priority is one of them, but some additional criteria maybe required. - // - // The other maybe simple solution for this could be just obeying 10% limit for future in - // tx_mem_pool. Oldest future transaction could be just dropped. *(Status at finalized would - // also be needed). Probably is_future_at_finalized:Option<bool> flag will be enought } impl<ChainApi, Block> TxInMemPool<ChainApi, Block> @@ -210,7 +207,6 @@ where /// A shared instance of the `MultiViewListener`. /// /// Provides a side-channel allowing to send per-transaction state changes notification. - //todo: could be removed after removing watched field (and adding listener into tx) [#5495] listener: Arc<MultiViewListener<ChainApi>>, /// A map that stores the transactions currently in the memory pool. @@ -272,7 +268,7 @@ where } /// Creates a new `TxMemPool` instance for testing purposes. - #[allow(dead_code)] + #[cfg(test)] fn new_test( api: Arc<ChainApi>, max_transactions_count: usize, @@ -280,7 +276,7 @@ where ) -> Self { Self { api, - listener: Arc::from(MultiViewListener::new()), + listener: Arc::from(MultiViewListener::new_with_worker().0), transactions: Default::default(), metrics: Default::default(), max_transactions_count, @@ -324,7 +320,7 @@ where /// exceed the maximum allowed transaction count. fn try_insert( &self, - hash: ExtrinsicHash<ChainApi>, + tx_hash: ExtrinsicHash<ChainApi>, tx: TxInMemPool<ChainApi, Block>, ) -> Result<InsertionInfo<ExtrinsicHash<ChainApi>>, sc_transaction_pool_api::error::Error> { let mut transactions = self.transactions.write(); @@ -333,19 +329,23 @@ where let result = match ( self.is_limit_exceeded(transactions.len() + 1, bytes + tx.bytes), - transactions.contains_key(&hash), + transactions.contains_key(&tx_hash), ) { (false, false) => { let source = tx.source(); - transactions.insert(hash, Arc::from(tx)); - Ok(InsertionInfo::new(hash, source)) + transactions.insert(tx_hash, Arc::from(tx)); + Ok(InsertionInfo::new(tx_hash, source)) }, (_, true) => - Err(sc_transaction_pool_api::error::Error::AlreadyImported(Box::new(hash))), + Err(sc_transaction_pool_api::error::Error::AlreadyImported(Box::new(tx_hash))), (true, _) => Err(sc_transaction_pool_api::error::Error::ImmediatelyDropped), }; - log::trace!(target: LOG_TARGET, "[{:?}] mempool::try_insert: {:?}", hash, result.as_ref().map(|r| r.hash)); - + trace!( + target: LOG_TARGET, + ?tx_hash, + result_hash = ?result.as_ref().map(|r| r.hash), + "mempool::try_insert" + ); result } @@ -460,43 +460,31 @@ where self.try_insert(hash, TxInMemPool::new_watched(source, xt.clone(), length)) } - /// Clones and returns a `HashMap` of references to all unwatched transactions in the memory - /// pool. - pub(super) fn clone_unwatched( - &self, - ) -> HashMap<ExtrinsicHash<ChainApi>, Arc<TxInMemPool<ChainApi, Block>>> { - self.transactions - .read() - .iter() - .filter_map(|(hash, tx)| (!tx.is_watched()).then(|| (*hash, tx.clone()))) - .collect::<HashMap<_, _>>() - } - - /// Clones and returns a `HashMap` of references to all watched transactions in the memory pool. - pub(super) fn clone_watched( + /// Clones and returns a `HashMap` of references to all transactions in the memory pool. + pub(super) fn clone_transactions( &self, ) -> HashMap<ExtrinsicHash<ChainApi>, Arc<TxInMemPool<ChainApi, Block>>> { - self.transactions - .read() - .iter() - .filter_map(|(hash, tx)| (tx.is_watched()).then(|| (*hash, tx.clone()))) - .collect::<HashMap<_, _>>() + self.transactions.clone_map() } /// Removes a transaction with given hash from the memory pool. pub(super) fn remove_transaction( &self, - hash: &ExtrinsicHash<ChainApi>, + tx_hash: &ExtrinsicHash<ChainApi>, ) -> Option<Arc<TxInMemPool<ChainApi, Block>>> { - log::debug!(target: LOG_TARGET, "[{hash:?}] mempool::remove_transaction"); - self.transactions.write().remove(hash) + debug!(target: LOG_TARGET, ?tx_hash, "mempool::remove_transaction"); + self.transactions.write().remove(tx_hash) } /// Revalidates a batch of transactions against the provided finalized block. /// /// Returns a vector of invalid transaction hashes. async fn revalidate_inner(&self, finalized_block: HashAndNumber<Block>) -> Vec<Block::Hash> { - log::trace!(target: LOG_TARGET, "mempool::revalidate at:{finalized_block:?}"); + trace!( + target: LOG_TARGET, + ?finalized_block, + "mempool::revalidate" + ); let start = Instant::now(); let (count, input) = { @@ -533,26 +521,31 @@ where let invalid_hashes = validation_results .into_iter() - .filter_map(|(xt_hash, validation_result)| match validation_result { + .filter_map(|(tx_hash, validation_result)| match validation_result { Ok(Ok(_)) | Ok(Err(TransactionValidityError::Invalid(InvalidTransaction::Future))) => None, Err(_) | Ok(Err(TransactionValidityError::Unknown(_))) | Ok(Err(TransactionValidityError::Invalid(_))) => { - log::trace!( + trace!( target: LOG_TARGET, - "[{:?}]: Purging: invalid: {:?}", - xt_hash, - validation_result, + ?tx_hash, + ?validation_result, + "Purging: invalid" ); - Some(xt_hash) + Some(tx_hash) }, }) .collect::<Vec<_>>(); - log::debug!( + debug!( target: LOG_TARGET, - "mempool::revalidate: at {finalized_block:?} count:{input_len}/{count} invalid_hashes:{} took {duration:?}", invalid_hashes.len(), + ?finalized_block, + input_len, + count, + invalid_hashes = invalid_hashes.len(), + ?duration, + "mempool::revalidate" ); invalid_hashes @@ -563,8 +556,12 @@ where &self, finalized_xts: &Vec<ExtrinsicHash<ChainApi>>, ) { - log::debug!(target: LOG_TARGET, "purge_finalized_transactions count:{:?}", finalized_xts.len()); - log_xt_trace!(target: LOG_TARGET, finalized_xts, "[{:?}] purged finalized transactions"); + debug!( + target: LOG_TARGET, + count = finalized_xts.len(), + "purge_finalized_transactions" + ); + log_xt_trace!(target: LOG_TARGET, finalized_xts, "purged finalized transactions"); let mut transactions = self.transactions.write(); finalized_xts.iter().for_each(|t| { transactions.remove(t); @@ -574,7 +571,11 @@ where /// Revalidates transactions in the memory pool against a given finalized block and removes /// invalid ones. pub(super) async fn revalidate(&self, finalized_block: HashAndNumber<Block>) { - log::trace!(target: LOG_TARGET, "purge_transactions at:{:?}", finalized_block); + trace!( + target: LOG_TARGET, + ?finalized_block, + "purge_transactions" + ); let invalid_hashes = self.revalidate_inner(finalized_block.clone()).await; self.metrics.report(|metrics| { @@ -585,7 +586,7 @@ where invalid_hashes.iter().for_each(|i| { transactions.remove(i); }); - self.listener.invalidate_transactions(&invalid_hashes); + self.listener.transactions_invalidated(&invalid_hashes); } /// Updates the priority of transaction stored in mempool using provided view_store submission @@ -602,10 +603,13 @@ where #[cfg(test)] mod tx_mem_pool_tests { - use super::*; - use crate::{common::tests::TestApi, graph::ChainApi}; use substrate_test_runtime::{AccountId, Extrinsic, ExtrinsicBuilder, Transfer, H256}; use substrate_test_runtime_client::Sr25519Keyring::*; + + use crate::{common::tests::TestApi, graph::ChainApi}; + + use super::*; + fn uxt(nonce: u64) -> Extrinsic { crate::common::tests::uxt(Transfer { from: Alice.into(), diff --git a/substrate/client/transaction-pool/src/fork_aware_txpool/view.rs b/substrate/client/transaction-pool/src/fork_aware_txpool/view.rs index a35d68120a3abf5eeb99b1589523e4b609825c32..555444956122b721d220b3754fa67d2308381e89 100644 --- a/substrate/client/transaction-pool/src/fork_aware_txpool/view.rs +++ b/substrate/client/transaction-pool/src/fork_aware_txpool/view.rs @@ -25,10 +25,10 @@ use super::metrics::MetricsLink as PrometheusMetrics; use crate::{ - common::log_xt::log_xt_trace, + common::tracing_log_xt::log_xt_trace, graph::{ - self, base_pool::TimedTransactionSource, watcher::Watcher, ExtrinsicFor, ExtrinsicHash, - IsValidator, ValidatedPoolSubmitOutcome, ValidatedTransaction, ValidatedTransactionFor, + self, base_pool::TimedTransactionSource, ExtrinsicFor, ExtrinsicHash, IsValidator, + ValidatedPoolSubmitOutcome, ValidatedTransaction, ValidatedTransactionFor, }, LOG_TARGET, }; @@ -40,6 +40,7 @@ use sp_runtime::{ SaturatedConversion, }; use std::{collections::HashMap, sync::Arc, time::Instant}; +use tracing::{debug, trace}; pub(super) struct RevalidationResult<ChainApi: graph::ChainApi> { revalidated: HashMap<ExtrinsicHash<ChainApi>, ValidatedTransactionFor<ChainApi>>, @@ -154,38 +155,48 @@ where } } + /// Imports single unvalidated extrinsic into the view. + pub(super) async fn submit_one( + &self, + source: TimedTransactionSource, + xt: ExtrinsicFor<ChainApi>, + ) -> Result<ValidatedPoolSubmitOutcome<ChainApi>, ChainApi::Error> { + self.submit_many(std::iter::once((source, xt))) + .await + .pop() + .expect("There is exactly one result, qed.") + } + /// Imports many unvalidated extrinsics into the view. pub(super) async fn submit_many( &self, xts: impl IntoIterator<Item = (TimedTransactionSource, ExtrinsicFor<ChainApi>)>, ) -> Vec<Result<ValidatedPoolSubmitOutcome<ChainApi>, ChainApi::Error>> { - if log::log_enabled!(target: LOG_TARGET, log::Level::Trace) { + if tracing::enabled!(target: LOG_TARGET, tracing::Level::TRACE) { let xts = xts.into_iter().collect::<Vec<_>>(); - log_xt_trace!(target: LOG_TARGET, xts.iter().map(|(_,xt)| self.pool.validated_pool().api().hash_and_length(xt).0), "[{:?}] view::submit_many at:{}", self.at.hash); + log_xt_trace!( + target: LOG_TARGET, + xts.iter().map(|(_,xt)| self.pool.validated_pool().api().hash_and_length(xt).0), + "view::submit_many at:{}", + self.at.hash); self.pool.submit_at(&self.at, xts).await } else { self.pool.submit_at(&self.at, xts).await } } - /// Import a single extrinsic and starts to watch its progress in the view. - pub(super) async fn submit_and_watch( - &self, - source: TimedTransactionSource, - xt: ExtrinsicFor<ChainApi>, - ) -> Result<ValidatedPoolSubmitOutcome<ChainApi>, ChainApi::Error> { - log::trace!(target: LOG_TARGET, "[{:?}] view::submit_and_watch at:{}", self.pool.validated_pool().api().hash_and_length(&xt).0, self.at.hash); - self.pool.submit_and_watch(&self.at, source, xt).await - } - /// Synchronously imports single unvalidated extrinsics into the view. pub(super) fn submit_local( &self, xt: ExtrinsicFor<ChainApi>, ) -> Result<ValidatedPoolSubmitOutcome<ChainApi>, ChainApi::Error> { - let (hash, length) = self.pool.validated_pool().api().hash_and_length(&xt); - log::trace!(target: LOG_TARGET, "[{:?}] view::submit_local at:{}", hash, self.at.hash); - + let (tx_hash, length) = self.pool.validated_pool().api().hash_and_length(&xt); + trace!( + target: LOG_TARGET, + ?tx_hash, + view_at_hash = ?self.at.hash, + "view::submit_local" + ); let validity = self .pool .validated_pool() @@ -212,7 +223,7 @@ where let validated = ValidatedTransaction::valid_at( block_number.saturated_into::<u64>(), - hash, + tx_hash, TimedTransactionSource::new_local(true), Arc::from(xt), length, @@ -227,18 +238,6 @@ where self.pool.validated_pool().status() } - /// Creates a watcher for given transaction. - /// - /// Intended to be called for the transaction that already exists in the pool - pub(super) fn create_watcher( - &self, - tx_hash: ExtrinsicHash<ChainApi>, - ) -> Watcher<ExtrinsicHash<ChainApi>, ExtrinsicHash<ChainApi>> { - //todo(minor): some assert could be added here - to make sure that transaction actually - // exists in the view. - self.pool.validated_pool().create_watcher(tx_hash) - } - /// Revalidates some part of transaction from the internal pool. /// /// Intended to be called from the revalidation worker. The revalidation process can be @@ -258,7 +257,11 @@ where revalidation_result_tx, } = finish_revalidation_worker_channels; - log::trace!(target:LOG_TARGET, "view::revalidate: at {} starting", self.at.hash); + trace!( + target: LOG_TARGET, + at_hash = ?self.at.hash, + "view::revalidate: at starting" + ); let start = Instant::now(); let validated_pool = self.pool.validated_pool(); let api = validated_pool.api(); @@ -279,7 +282,11 @@ where let mut should_break = false; tokio::select! { _ = finish_revalidation_request_rx.recv() => { - log::trace!(target: LOG_TARGET, "view::revalidate: finish revalidation request received at {}.", self.at.hash); + trace!( + target: LOG_TARGET, + at_hash = ?self.at.hash, + "view::revalidate: finish revalidation request received" + ); break } _ = async { @@ -302,16 +309,15 @@ where self.metrics.report(|metrics| { metrics.view_revalidation_duration.observe(revalidation_duration.as_secs_f64()); }); - log::debug!( - target:LOG_TARGET, - "view::revalidate: at {:?} count: {}/{} took {:?}", - self.at.hash, - validation_results.len(), + debug!( + target: LOG_TARGET, + at_hash = ?self.at.hash, + count = validation_results.len(), batch_len, - revalidation_duration + duration = ?revalidation_duration, + "view::revalidate" ); - log_xt_trace!(data:tuple, target:LOG_TARGET, validation_results.iter().map(|x| (x.1, &x.0)), "[{:?}] view::revalidateresult: {:?}"); - + log_xt_trace!(data:tuple, target:LOG_TARGET, validation_results.iter().map(|x| (x.1, &x.0)), "view::revalidate result: {:?}"); for (validation_result, tx_hash, tx) in validation_results { match validation_result { Ok(Err(TransactionValidityError::Invalid(_))) => { @@ -330,33 +336,42 @@ where ), ); }, - Ok(Err(TransactionValidityError::Unknown(e))) => { - log::trace!( + Ok(Err(TransactionValidityError::Unknown(error))) => { + trace!( target: LOG_TARGET, - "[{:?}]: Removing. Cannot determine transaction validity: {:?}", - tx_hash, - e + ?tx_hash, + ?error, + "Removing. Cannot determine transaction validity" ); invalid_hashes.push(tx_hash); }, - Err(validation_err) => { - log::trace!( + Err(error) => { + trace!( target: LOG_TARGET, - "[{:?}]: Removing due to error during revalidation: {}", - tx_hash, - validation_err + ?tx_hash, + %error, + "Removing due to error during revalidation" ); invalid_hashes.push(tx_hash); }, } } - log::trace!(target:LOG_TARGET, "view::revalidate: sending revalidation result at {}", self.at.hash); - if let Err(e) = revalidation_result_tx + trace!( + target: LOG_TARGET, + at_hash = ?self.at.hash, + "view::revalidate: sending revalidation result" + ); + if let Err(error) = revalidation_result_tx .send(RevalidationResult { invalid_hashes, revalidated }) .await { - log::trace!(target:LOG_TARGET, "view::revalidate: sending revalidation_result at {} failed {:?}", self.at.hash, e); + trace!( + target: LOG_TARGET, + at_hash = ?self.at.hash, + ?error, + "view::revalidate: sending revalidation_result failed" + ); } } @@ -374,7 +389,11 @@ where super::revalidation_worker::RevalidationQueue<ChainApi, ChainApi::Block>, >, ) { - log::trace!(target:LOG_TARGET,"view::start_background_revalidation: at {}", view.at.hash); + trace!( + target: LOG_TARGET, + at_hash = ?view.at.hash, + "view::start_background_revalidation" + ); let (finish_revalidation_request_tx, finish_revalidation_request_rx) = tokio::sync::mpsc::channel(1); let (revalidation_result_tx, revalidation_result_rx) = tokio::sync::mpsc::channel(1); @@ -404,10 +423,14 @@ where /// /// Refer to [*View revalidation*](../index.html#view-revalidation) for more details. pub(super) async fn finish_revalidation(&self) { - log::trace!(target:LOG_TARGET,"view::finish_revalidation: at {}", self.at.hash); + trace!( + target: LOG_TARGET, + at_hash = ?self.at.hash, + "view::finish_revalidation" + ); let Some(revalidation_worker_channels) = self.revalidation_worker_channels.lock().take() else { - log::trace!(target:LOG_TARGET, "view::finish_revalidation: no finish_revalidation_request_tx"); + trace!(target:LOG_TARGET, "view::finish_revalidation: no finish_revalidation_request_tx"); return }; @@ -417,8 +440,13 @@ where } = revalidation_worker_channels; if let Some(finish_revalidation_request_tx) = finish_revalidation_request_tx { - if let Err(e) = finish_revalidation_request_tx.send(()).await { - log::trace!(target:LOG_TARGET, "view::finish_revalidation: sending cancellation request at {} failed {:?}", self.at.hash, e); + if let Err(error) = finish_revalidation_request_tx.send(()).await { + trace!( + target: LOG_TARGET, + at_hash = ?self.at.hash, + %error, + "view::finish_revalidation: sending cancellation request failed" + ); } } @@ -444,13 +472,13 @@ where ); }); - log::debug!( - target:LOG_TARGET, - "view::finish_revalidation: applying revalidation result invalid: {} revalidated: {} at {:?} took {:?}", - revalidation_result.invalid_hashes.len(), - revalidated_len, - self.at.hash, - start.elapsed() + debug!( + target: LOG_TARGET, + invalid = revalidation_result.invalid_hashes.len(), + revalidated = revalidated_len, + at_hash = ?self.at.hash, + duration = ?start.elapsed(), + "view::finish_revalidation: applying revalidation result" ); } } diff --git a/substrate/client/transaction-pool/src/fork_aware_txpool/view_store.rs b/substrate/client/transaction-pool/src/fork_aware_txpool/view_store.rs index 43ed5bbf8869f360f641c1ae9590dfedd56dc89d..e534decf9b1ada3d692a1ed3392475b4983b56ae 100644 --- a/substrate/client/transaction-pool/src/fork_aware_txpool/view_store.rs +++ b/substrate/client/transaction-pool/src/fork_aware_txpool/view_store.rs @@ -31,7 +31,6 @@ use crate::{ }, ReadyIteratorFor, LOG_TARGET, }; -use futures::prelude::*; use itertools::Itertools; use parking_lot::RwLock; use sc_transaction_pool_api::{error::Error as PoolError, PoolStatus}; @@ -42,6 +41,7 @@ use std::{ sync::Arc, time::Instant, }; +use tracing::{trace, warn}; /// Helper struct to maintain the context for pending transaction submission, executed for /// newly inserted views. @@ -54,8 +54,6 @@ where xt: ExtrinsicFor<ChainApi>, /// Source of the transaction. source: TimedTransactionSource, - /// Inidicates if transaction is watched. - watched: bool, } /// Helper type representing the callback allowing to trigger per-transaction events on @@ -107,14 +105,10 @@ where ChainApi: graph::ChainApi, { /// Creates new unprocessed instance of pending transaction submission. - fn new_submission_action( - xt: ExtrinsicFor<ChainApi>, - source: TimedTransactionSource, - watched: bool, - ) -> Self { + fn new_submission_action(xt: ExtrinsicFor<ChainApi>, source: TimedTransactionSource) -> Self { Self { processed: false, - action: PreInsertAction::SubmitTx(PendingTxSubmission { xt, source, watched }), + action: PreInsertAction::SubmitTx(PendingTxSubmission { xt, source }), } } @@ -258,9 +252,14 @@ where .find_or_first(Result::is_ok); match result { - Some(Err(err)) => { - log::trace!(target: LOG_TARGET, "[{:?}] submit_local: err: {}", tx_hash, err); - Err(err) + Some(Err(error)) => { + trace!( + target: LOG_TARGET, + ?tx_hash, + %error, + "submit_local: err" + ); + Err(error) }, None => Ok(ViewStoreSubmitOutcome::new(tx_hash, None)), Some(Ok(r)) => Ok(r.into()), @@ -284,7 +283,7 @@ where let Some(external_watcher) = self.listener.create_external_watcher_for_tx(tx_hash) else { return Err(PoolError::AlreadyImported(Box::new(tx_hash)).into()) }; - let submit_and_watch_futures = { + let submit_futures = { let active_views = self.active_views.read(); active_views .iter() @@ -292,31 +291,24 @@ where let view = view.clone(); let xt = xt.clone(); let source = source.clone(); - async move { - match view.submit_and_watch(source, xt).await { - Ok(mut result) => { - self.listener.add_view_watcher_for_tx( - tx_hash, - view.at.hash, - result.expect_watcher().into_stream().boxed(), - ); - Ok(result) - }, - Err(e) => Err(e), - } - } + async move { view.submit_one(source, xt).await } }) .collect::<Vec<_>>() }; - let result = futures::future::join_all(submit_and_watch_futures) + let result = futures::future::join_all(submit_futures) .await .into_iter() .find_or_first(Result::is_ok); match result { - Some(Err(err)) => { - log::trace!(target: LOG_TARGET, "[{:?}] submit_and_watch: err: {}", tx_hash, err); - return Err(err); + Some(Err(error)) => { + trace!( + target: LOG_TARGET, + ?tx_hash, + %error, + "submit_and_watch: err" + ); + return Err(error); }, Some(Ok(result)) => Ok(ViewStoreSubmitOutcome::from(result).with_watcher(external_watcher)), @@ -422,8 +414,12 @@ where finalized_hash: Block::Hash, tree_route: &[Block::Hash], ) -> Vec<ExtrinsicHash<ChainApi>> { - log::trace!(target: LOG_TARGET, "finalize_route finalized_hash:{finalized_hash:?} tree_route: {tree_route:?}"); - + trace!( + target: LOG_TARGET, + ?finalized_hash, + ?tree_route, + "finalize_route" + ); let mut finalized_transactions = Vec::new(); for block in tree_route.iter().chain(std::iter::once(&finalized_hash)) { @@ -431,8 +427,12 @@ where .api .block_body(*block) .await - .unwrap_or_else(|e| { - log::warn!(target: LOG_TARGET, "Finalize route: error request: {}", e); + .unwrap_or_else(|error| { + warn!( + target: LOG_TARGET, + %error, + "Finalize route: error request" + ); None }) .unwrap_or_default() @@ -443,7 +443,7 @@ where extrinsics .iter() .enumerate() - .for_each(|(i, tx_hash)| self.listener.finalize_transaction(*tx_hash, *block, i)); + .for_each(|(i, tx_hash)| self.listener.transaction_finalized(*tx_hash, *block, i)); finalized_transactions.extend(extrinsics); } @@ -500,7 +500,11 @@ where active_views.insert(view.at.hash, view.clone()); most_recent_view_lock.replace(view.at.hash); }; - log::trace!(target:LOG_TARGET,"insert_new_view: inactive_views: {:?}", self.inactive_views.read().keys()); + trace!( + target: LOG_TARGET, + inactive_views = ?self.inactive_views.read().keys(), + "insert_new_view" + ); } /// Returns an optional reference to the view at given hash. @@ -557,8 +561,11 @@ where .for_each(drop); } - log::trace!(target:LOG_TARGET,"handle_pre_finalized: removed_views: {:?}", removed_views); - + trace!( + target: LOG_TARGET, + ?removed_views, + "handle_pre_finalized" + ); removed_views.iter().for_each(|view| { self.dropped_stream_controller.remove_view(*view); }); @@ -613,10 +620,18 @@ where retain }); - log::trace!(target:LOG_TARGET,"handle_finalized: inactive_views: {:?}", inactive_views.keys()); + trace!( + target: LOG_TARGET, + inactive_views = ?inactive_views.keys(), + "handle_finalized" + ); } - log::trace!(target:LOG_TARGET,"handle_finalized: dropped_views: {:?}", dropped_views); + trace!( + target: LOG_TARGET, + ?dropped_views, + "handle_finalized" + ); self.listener.remove_stale_controllers(); self.dropped_stream_controller.remove_finalized_txs(finalized_xts.clone()); @@ -647,7 +662,11 @@ where .collect::<Vec<_>>() }; futures::future::join_all(finish_revalidation_futures).await; - log::trace!(target:LOG_TARGET,"finish_background_revalidations took {:?}", start.elapsed()); + trace!( + target: LOG_TARGET, + duration = ?start.elapsed(), + "finish_background_revalidations" + ); } /// Replaces an existing transaction in the view_store with a new one. @@ -667,22 +686,21 @@ where source: TimedTransactionSource, xt: ExtrinsicFor<ChainApi>, replaced: ExtrinsicHash<ChainApi>, - watched: bool, ) { if let Entry::Vacant(entry) = self.pending_txs_tasks.write().entry(replaced) { - entry.insert(PendingPreInsertTask::new_submission_action( - xt.clone(), - source.clone(), - watched, - )); + entry.insert(PendingPreInsertTask::new_submission_action(xt.clone(), source.clone())); } else { return }; - let xt_hash = self.api.hash_and_length(&xt).0; - log::trace!(target:LOG_TARGET,"[{replaced:?}] replace_transaction wtih {xt_hash:?}, w:{watched}"); - - self.replace_transaction_in_views(source, xt, xt_hash, replaced, watched).await; + let tx_hash = self.api.hash_and_length(&xt).0; + trace!( + target: LOG_TARGET, + ?replaced, + ?tx_hash, + "replace_transaction" + ); + self.replace_transaction_in_views(source, xt, tx_hash, replaced).await; if let Some(replacement) = self.pending_txs_tasks.write().get_mut(&replaced) { replacement.mark_processed(); @@ -703,7 +721,6 @@ where submission.source.clone(), submission.xt.clone(), xt_hash, - submission.watched, )); }, PreInsertAction::RemoveSubtree(ref removal) => { @@ -723,34 +740,16 @@ where view: Arc<View<ChainApi>>, source: TimedTransactionSource, xt: ExtrinsicFor<ChainApi>, - xt_hash: ExtrinsicHash<ChainApi>, - watched: bool, + tx_hash: ExtrinsicHash<ChainApi>, ) { - if watched { - match view.submit_and_watch(source, xt).await { - Ok(mut result) => { - self.listener.add_view_watcher_for_tx( - xt_hash, - view.at.hash, - result.expect_watcher().into_stream().boxed(), - ); - }, - Err(e) => { - log::trace!( - target:LOG_TARGET, - "[{:?}] replace_transaction: submit_and_watch to {} failed {}", - xt_hash, view.at.hash, e - ); - }, - } - } else { - if let Some(Err(e)) = view.submit_many(std::iter::once((source, xt))).await.pop() { - log::trace!( - target:LOG_TARGET, - "[{:?}] replace_transaction: submit to {} failed {}", - xt_hash, view.at.hash, e - ); - } + if let Err(error) = view.submit_one(source, xt).await { + trace!( + target: LOG_TARGET, + ?tx_hash, + at_hash = ?view.at.hash, + %error, + "replace_transaction: submit failed" + ); } } @@ -762,19 +761,9 @@ where &self, source: TimedTransactionSource, xt: ExtrinsicFor<ChainApi>, - xt_hash: ExtrinsicHash<ChainApi>, + tx_hash: ExtrinsicHash<ChainApi>, replaced: ExtrinsicHash<ChainApi>, - watched: bool, ) { - if watched && !self.listener.contains_tx(&xt_hash) { - log::trace!( - target:LOG_TARGET, - "error: replace_transaction_in_views: no listener for watched transaction {:?}", - xt_hash, - ); - return; - } - let submit_futures = { let active_views = self.active_views.read(); let inactive_views = self.inactive_views.read(); @@ -787,8 +776,7 @@ where view.clone(), source.clone(), xt.clone(), - xt_hash, - watched, + tx_hash, ) }) .collect::<Vec<_>>() diff --git a/substrate/client/transaction-pool/src/graph/future.rs b/substrate/client/transaction-pool/src/graph/future.rs index 2c1e64c04b7f2d72fb4e6a073b04fa40b828b538..848893b026c5cbb345ed481e197666774e717cc0 100644 --- a/substrate/client/transaction-pool/src/graph/future.rs +++ b/substrate/client/transaction-pool/src/graph/future.rs @@ -27,7 +27,7 @@ use sp_runtime::transaction_validity::TransactionTag as Tag; use std::time::Instant; use super::base_pool::Transaction; -use crate::{common::log_xt::log_xt_trace, LOG_TARGET}; +use crate::{common::tracing_log_xt::log_xt_trace, LOG_TARGET}; /// Transaction with partially satisfied dependencies. pub struct WaitingTransaction<Hash, Ex> { @@ -184,7 +184,7 @@ impl<Hash: hash::Hash + Eq + Clone + std::fmt::Debug, Ex: std::fmt::Debug> }) .collect::<Vec<_>>(); - log_xt_trace!(target: LOG_TARGET, &pruned, "[{:?}] FutureTransactions: removed while pruning tags."); + log_xt_trace!(target: LOG_TARGET, &pruned, "FutureTransactions: removed while pruning tags."); self.remove(&pruned) } diff --git a/substrate/client/transaction-pool/src/graph/listener.rs b/substrate/client/transaction-pool/src/graph/listener.rs index 7b09ee4c640958736d8acfddd5baab572e1bf530..0e70334ea0e2485967e35e533dc7281a3cef9421 100644 --- a/substrate/client/transaction-pool/src/graph/listener.rs +++ b/substrate/client/transaction-pool/src/graph/listener.rs @@ -29,10 +29,13 @@ use super::{watcher, BlockHash, ChainApi, ExtrinsicHash}; static LOG_TARGET: &str = "txpool::watcher"; -/// Single event used in dropped by limits stream. It is one of Ready/Future/Dropped. -pub type DroppedByLimitsEvent<H, BH> = (H, TransactionStatus<H, BH>); -/// Stream of events used to determine if a transaction was dropped. -pub type DroppedByLimitsStream<H, BH> = TracingUnboundedReceiver<DroppedByLimitsEvent<H, BH>>; +/// Single event used in aggregated stream. Tuple containing hash of transactions and its status. +pub type TransactionStatusEvent<H, BH> = (H, TransactionStatus<H, BH>); +/// Stream of events providing statuses of all the transactions within the pool. +pub type AggregatedStream<H, BH> = TracingUnboundedReceiver<TransactionStatusEvent<H, BH>>; + +/// Warning threshold for (unbounded) channel used in aggregated stream. +const AGGREGATED_STREAM_WARN_THRESHOLD: usize = 100_000; /// Extrinsic pool default listener. pub struct Listener<H: hash::Hash + Eq, C: ChainApi> { @@ -40,10 +43,15 @@ pub struct Listener<H: hash::Hash + Eq, C: ChainApi> { watchers: HashMap<H, watcher::Sender<H, BlockHash<C>>>, finality_watchers: LinkedHashMap<ExtrinsicHash<C>, Vec<H>>, - /// The sink used to notify dropped-by-enforcing-limits transactions. Also ready and future - /// statuses are reported via this channel to allow consumer of the stream tracking actual - /// drops. - dropped_by_limits_sink: Option<TracingUnboundedSender<DroppedByLimitsEvent<H, BlockHash<C>>>>, + /// The sink used to notify dropped by enforcing limits or by being usurped transactions. + /// + /// Note: Ready and future statuses are alse communicated through this channel, enabling the + /// stream consumer to track views that reference the transaction. + dropped_stream_sink: Option<TracingUnboundedSender<TransactionStatusEvent<H, BlockHash<C>>>>, + + /// The sink of the single, merged stream providing updates for all the transactions in the + /// associated pool. + aggregated_stream_sink: Option<TracingUnboundedSender<TransactionStatusEvent<H, BlockHash<C>>>>, } /// Maximum number of blocks awaiting finality at any time. @@ -54,7 +62,8 @@ impl<H: hash::Hash + Eq + Debug, C: ChainApi> Default for Listener<H, C> { Self { watchers: Default::default(), finality_watchers: Default::default(), - dropped_by_limits_sink: None, + dropped_stream_sink: None, + aggregated_stream_sink: None, } } } @@ -84,21 +93,60 @@ impl<H: hash::Hash + traits::Member + Serialize + Clone, C: ChainApi> Listener<H sender.new_watcher(hash) } - /// Creates a new single stream for entire pool. + /// Creates a new single stream intended to watch dropped transactions only. /// - /// The stream can be used to subscribe to life-cycle events of all extrinsics in the pool. - pub fn create_dropped_by_limits_stream(&mut self) -> DroppedByLimitsStream<H, BlockHash<C>> { - let (sender, single_stream) = tracing_unbounded("mpsc_txpool_watcher", 100_000); - self.dropped_by_limits_sink = Some(sender); + /// The stream can be used to subscribe to events related to dropping of all extrinsics in the + /// pool. + pub fn create_dropped_by_limits_stream(&mut self) -> AggregatedStream<H, BlockHash<C>> { + let (sender, single_stream) = + tracing_unbounded("mpsc_txpool_watcher", AGGREGATED_STREAM_WARN_THRESHOLD); + self.dropped_stream_sink = Some(sender); single_stream } - /// Notify the listeners about extrinsic broadcast. + /// Creates a new single merged stream for all extrinsics in the associated pool. + /// + /// The stream can be used to subscribe to life-cycle events of all extrinsics in the pool. For + /// some implementations (e.g. fork-aware pool) this approach may be more efficient than using + /// individual streams for every transaction. + /// + /// Note: some of the events which are currently ignored on the other side of this channel + /// (external watcher) are not sent. + pub fn create_aggregated_stream(&mut self) -> AggregatedStream<H, BlockHash<C>> { + let (sender, aggregated_stream) = + tracing_unbounded("mpsc_txpool_aggregated_stream", AGGREGATED_STREAM_WARN_THRESHOLD); + self.aggregated_stream_sink = Some(sender); + aggregated_stream + } + + /// Notify the listeners about the extrinsic broadcast. pub fn broadcasted(&mut self, hash: &H, peers: Vec<String>) { trace!(target: LOG_TARGET, "[{:?}] Broadcasted", hash); self.fire(hash, |watcher| watcher.broadcast(peers)); } + /// Sends given event to the `dropped_stream_sink`. + fn send_to_dropped_stream_sink(&mut self, tx: &H, status: TransactionStatus<H, BlockHash<C>>) { + if let Some(ref sink) = self.dropped_stream_sink { + if let Err(e) = sink.unbounded_send((tx.clone(), status.clone())) { + trace!(target: LOG_TARGET, "[{:?}] dropped_sink: {:?} send message failed: {:?}", tx, status, e); + } + } + } + + /// Sends given event to the `aggregated_stream_sink`. + fn send_to_aggregated_stream_sink( + &mut self, + tx: &H, + status: TransactionStatus<H, BlockHash<C>>, + ) { + if let Some(ref sink) = self.aggregated_stream_sink { + if let Err(e) = sink.unbounded_send((tx.clone(), status.clone())) { + trace!(target: LOG_TARGET, "[{:?}] aggregated_stream {:?} send message failed: {:?}", tx, status, e); + } + } + } + /// New transaction was added to the ready pool or promoted from the future pool. pub fn ready(&mut self, tx: &H, old: Option<&H>) { trace!(target: LOG_TARGET, "[{:?}] Ready (replaced with {:?})", tx, old); @@ -107,22 +155,17 @@ impl<H: hash::Hash + traits::Member + Serialize + Clone, C: ChainApi> Listener<H self.fire(old, |watcher| watcher.usurped(tx.clone())); } - if let Some(ref sink) = self.dropped_by_limits_sink { - if let Err(e) = sink.unbounded_send((tx.clone(), TransactionStatus::Ready)) { - trace!(target: LOG_TARGET, "[{:?}] dropped_sink/ready: send message failed: {:?}", tx, e); - } - } + self.send_to_dropped_stream_sink(tx, TransactionStatus::Ready); + self.send_to_aggregated_stream_sink(tx, TransactionStatus::Ready); } /// New transaction was added to the future pool. pub fn future(&mut self, tx: &H) { trace!(target: LOG_TARGET, "[{:?}] Future", tx); self.fire(tx, |watcher| watcher.future()); - if let Some(ref sink) = self.dropped_by_limits_sink { - if let Err(e) = sink.unbounded_send((tx.clone(), TransactionStatus::Future)) { - trace!(target: LOG_TARGET, "[{:?}] dropped_sink: send message failed: {:?}", tx, e); - } - } + + self.send_to_dropped_stream_sink(tx, TransactionStatus::Future); + self.send_to_aggregated_stream_sink(tx, TransactionStatus::Future); } /// Transaction was dropped from the pool because of enforcing the limit. @@ -130,11 +173,7 @@ impl<H: hash::Hash + traits::Member + Serialize + Clone, C: ChainApi> Listener<H trace!(target: LOG_TARGET, "[{:?}] Dropped (limits enforced)", tx); self.fire(tx, |watcher| watcher.limit_enforced()); - if let Some(ref sink) = self.dropped_by_limits_sink { - if let Err(e) = sink.unbounded_send((tx.clone(), TransactionStatus::Dropped)) { - trace!(target: LOG_TARGET, "[{:?}] dropped_sink: send message failed: {:?}", tx, e); - } - } + self.send_to_dropped_stream_sink(tx, TransactionStatus::Dropped); } /// Transaction was replaced with other extrinsic. @@ -142,13 +181,7 @@ impl<H: hash::Hash + traits::Member + Serialize + Clone, C: ChainApi> Listener<H trace!(target: LOG_TARGET, "[{:?}] Dropped (replaced with {:?})", tx, by); self.fire(tx, |watcher| watcher.usurped(by.clone())); - if let Some(ref sink) = self.dropped_by_limits_sink { - if let Err(e) = - sink.unbounded_send((tx.clone(), TransactionStatus::Usurped(by.clone()))) - { - trace!(target: LOG_TARGET, "[{:?}] dropped_sink: send message failed: {:?}", tx, e); - } - } + self.send_to_dropped_stream_sink(tx, TransactionStatus::Usurped(by.clone())); } /// Transaction was dropped from the pool because of the failure during the resubmission of @@ -174,11 +207,17 @@ impl<H: hash::Hash + traits::Member + Serialize + Clone, C: ChainApi> Listener<H let tx_index = txs.len() - 1; self.fire(tx, |watcher| watcher.in_block(block_hash, tx_index)); + self.send_to_aggregated_stream_sink(tx, TransactionStatus::InBlock((block_hash, tx_index))); while self.finality_watchers.len() > MAX_FINALITY_WATCHERS { if let Some((hash, txs)) = self.finality_watchers.pop_front() { for tx in txs { self.fire(&tx, |watcher| watcher.finality_timeout(hash)); + //todo: do we need this? [related issue: #5482] + self.send_to_aggregated_stream_sink( + &tx, + TransactionStatus::FinalityTimeout(hash), + ); } } } @@ -188,7 +227,8 @@ impl<H: hash::Hash + traits::Member + Serialize + Clone, C: ChainApi> Listener<H pub fn retracted(&mut self, block_hash: BlockHash<C>) { if let Some(hashes) = self.finality_watchers.remove(&block_hash) { for hash in hashes { - self.fire(&hash, |watcher| watcher.retracted(block_hash)) + self.fire(&hash, |watcher| watcher.retracted(block_hash)); + // note: [#5479], we do not send to aggregated stream. } } } diff --git a/substrate/client/transaction-pool/src/graph/mod.rs b/substrate/client/transaction-pool/src/graph/mod.rs index 2114577f4dee74bf51e25a1375b8650cf8f4acf7..c3161799785a97f668c93c8773257e57d3dfe91d 100644 --- a/substrate/client/transaction-pool/src/graph/mod.rs +++ b/substrate/client/transaction-pool/src/graph/mod.rs @@ -46,7 +46,9 @@ pub use validated_pool::{ }; pub(crate) use self::pool::CheckBannedBeforeVerify; -pub(crate) use listener::DroppedByLimitsEvent; +pub(crate) use listener::TransactionStatusEvent; +#[cfg(doc)] +pub(crate) use listener::AggregatedStream; #[cfg(doc)] pub(crate) use validated_pool::ValidatedPool; diff --git a/substrate/client/transaction-pool/src/graph/pool.rs b/substrate/client/transaction-pool/src/graph/pool.rs index 403712662adae418c0e640824ac1599cf5a5248d..52b12e3fabae6c0ed883427d36111401fe9c9b13 100644 --- a/substrate/client/transaction-pool/src/graph/pool.rs +++ b/substrate/client/transaction-pool/src/graph/pool.rs @@ -16,7 +16,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see <https://www.gnu.org/licenses/>. -use crate::{common::log_xt::log_xt_trace, LOG_TARGET}; +use crate::{common::tracing_log_xt::log_xt_trace, LOG_TARGET}; use futures::{channel::mpsc::Receiver, Future}; use indexmap::IndexMap; use sc_transaction_pool_api::error; @@ -395,7 +395,7 @@ impl<B: ChainApi> Pool<B> { let pruned_hashes = reverified_transactions.keys().map(Clone::clone).collect::<Vec<_>>(); log::debug!(target: LOG_TARGET, "Pruning at {:?}. Resubmitting transactions: {}, reverification took: {:?}", &at, reverified_transactions.len(), now.elapsed()); - log_xt_trace!(data: tuple, target: LOG_TARGET, &reverified_transactions, "[{:?}] Resubmitting transaction: {:?}"); + log_xt_trace!(data: tuple, target: LOG_TARGET, &reverified_transactions, "Resubmitting transaction: {:?}"); // And finally - submit reverified transactions back to the pool self.validated_pool.resubmit_pruned( diff --git a/substrate/client/transaction-pool/src/graph/tracked_map.rs b/substrate/client/transaction-pool/src/graph/tracked_map.rs index fe15c6eca308084f18261b8d7ebc003509d3d735..ca1ee035cf37e1e5b8834ed8df49fcd818d37b51 100644 --- a/substrate/client/transaction-pool/src/graph/tracked_map.rs +++ b/substrate/client/transaction-pool/src/graph/tracked_map.rs @@ -120,11 +120,6 @@ where pub fn len(&self) -> usize { self.inner_guard.len() } - - /// Returns an iterator over all key-value pairs. - pub fn iter(&self) -> Iter<'_, K, V> { - self.inner_guard.iter() - } } pub struct TrackedMapWriteAccess<'a, K, V> { diff --git a/substrate/client/transaction-pool/src/graph/validated_pool.rs b/substrate/client/transaction-pool/src/graph/validated_pool.rs index bc2b07896dba09b51c4cff506883c89d37e702be..9631a27ead93416b4fbc52aa35d2f0b2c036bfad 100644 --- a/substrate/client/transaction-pool/src/graph/validated_pool.rs +++ b/substrate/client/transaction-pool/src/graph/validated_pool.rs @@ -21,7 +21,7 @@ use std::{ sync::Arc, }; -use crate::{common::log_xt::log_xt_trace, LOG_TARGET}; +use crate::{common::tracing_log_xt::log_xt_trace, LOG_TARGET}; use futures::channel::mpsc::{channel, Sender}; use parking_lot::{Mutex, RwLock}; use sc_transaction_pool_api::{error, PoolStatus, ReadyTransactions, TransactionPriority}; @@ -706,7 +706,7 @@ impl<B: ChainApi> ValidatedPool<B> { let invalid = self.pool.write().remove_subtree(hashes); log::trace!(target: LOG_TARGET, "Removed invalid transactions: {:?}", invalid.len()); - log_xt_trace!(target: LOG_TARGET, invalid.iter().map(|t| t.hash), "{:?} Removed invalid transaction"); + log_xt_trace!(target: LOG_TARGET, invalid.iter().map(|t| t.hash), "Removed invalid transaction"); let mut listener = self.listener.write(); for tx in &invalid { @@ -747,12 +747,20 @@ impl<B: ChainApi> ValidatedPool<B> { self.listener.write().retracted(block_hash) } + /// Refer to [`Listener::create_dropped_by_limits_stream`] for details. pub fn create_dropped_by_limits_stream( &self, - ) -> super::listener::DroppedByLimitsStream<ExtrinsicHash<B>, BlockHash<B>> { + ) -> super::listener::AggregatedStream<ExtrinsicHash<B>, BlockHash<B>> { self.listener.write().create_dropped_by_limits_stream() } + /// Refer to [`Listener::create_aggregated_stream`] + pub fn create_aggregated_stream( + &self, + ) -> super::listener::AggregatedStream<ExtrinsicHash<B>, BlockHash<B>> { + self.listener.write().create_aggregated_stream() + } + /// Resends ready and future events for all the ready and future transactions that are already /// in the pool. /// diff --git a/substrate/client/transaction-pool/tests/fatp_common/mod.rs b/substrate/client/transaction-pool/tests/fatp_common/mod.rs index 530c25caf88e7973b6c877f8370fc77fa1a203b2..20178fdc7c4e36837f414c5762c1796e3c09a9cd 100644 --- a/substrate/client/transaction-pool/tests/fatp_common/mod.rs +++ b/substrate/client/transaction-pool/tests/fatp_common/mod.rs @@ -203,8 +203,8 @@ macro_rules! assert_future_iterator { ($hash:expr, $pool:expr, [$( $xt:expr ),*]) => {{ let futures = $pool.futures_at($hash).unwrap(); let expected = vec![ $($pool.api().hash_and_length(&$xt).0),*]; - log::debug!(target:LOG_TARGET, "expected: {:#?}", futures); - log::debug!(target:LOG_TARGET, "output: {:#?}", expected); + log::debug!(target:LOG_TARGET, "expected: {:#?}", expected); + log::debug!(target:LOG_TARGET, "output: {:#?}", futures); assert_eq!(expected.len(), futures.len()); let hsf = futures.iter().map(|a| a.hash).collect::<std::collections::HashSet<_>>(); let hse = expected.into_iter().collect::<std::collections::HashSet<_>>(); diff --git a/substrate/client/transaction-pool/tests/fatp_limits.rs b/substrate/client/transaction-pool/tests/fatp_limits.rs index fb02b21ebc2b0426def3f9a98227f9d179fbe952..50e75e1e28e776c8e14be4cc9ca627b986b46aa6 100644 --- a/substrate/client/transaction-pool/tests/fatp_limits.rs +++ b/substrate/client/transaction-pool/tests/fatp_limits.rs @@ -377,12 +377,11 @@ fn fatp_limits_watcher_view_can_drop_transcation() { assert_eq!(xt0_status, vec![TransactionStatus::Ready, TransactionStatus::Dropped,]); assert_ready_iterator!(header01.hash(), pool, [xt1, xt2]); + let xt3_watcher = block_on(pool.submit_and_watch(invalid_hash(), SOURCE, xt3.clone())).unwrap(); let header02 = api.push_block_with_parent(header01.hash(), vec![], true); block_on(pool.maintain(finalized_block_event(&pool, api.genesis_hash(), header02.hash()))); - let xt3_watcher = block_on(pool.submit_and_watch(invalid_hash(), SOURCE, xt3.clone())).unwrap(); - let xt1_status = futures::executor::block_on_stream(xt1_watcher).take(2).collect::<Vec<_>>(); assert_eq!(xt1_status, vec![TransactionStatus::Ready, TransactionStatus::Dropped]); diff --git a/substrate/frame/balances/src/benchmarking.rs b/substrate/frame/balances/src/benchmarking.rs index c825300218d462a8465df2e80afda4e02c951cf3..a761f8e2af828ccbf4b4bedfdbe69bc09aba8f68 100644 --- a/substrate/frame/balances/src/benchmarking.rs +++ b/substrate/frame/balances/src/benchmarking.rs @@ -65,7 +65,12 @@ mod benchmarks { #[extrinsic_call] _(RawOrigin::Signed(caller.clone()), recipient_lookup, transfer_amount); - assert_eq!(Balances::<T, I>::free_balance(&caller), Zero::zero()); + if cfg!(feature = "insecure_zero_ed") { + assert_eq!(Balances::<T, I>::free_balance(&caller), balance - transfer_amount); + } else { + assert_eq!(Balances::<T, I>::free_balance(&caller), Zero::zero()); + } + assert_eq!(Balances::<T, I>::free_balance(&recipient), transfer_amount); } @@ -173,7 +178,12 @@ mod benchmarks { #[extrinsic_call] _(RawOrigin::Root, source_lookup, recipient_lookup, transfer_amount); - assert_eq!(Balances::<T, I>::free_balance(&source), Zero::zero()); + if cfg!(feature = "insecure_zero_ed") { + assert_eq!(Balances::<T, I>::free_balance(&source), balance - transfer_amount); + } else { + assert_eq!(Balances::<T, I>::free_balance(&source), Zero::zero()); + } + assert_eq!(Balances::<T, I>::free_balance(&recipient), transfer_amount); } @@ -208,7 +218,12 @@ mod benchmarks { #[extrinsic_call] transfer_allow_death(RawOrigin::Signed(caller.clone()), recipient_lookup, transfer_amount); - assert_eq!(Balances::<T, I>::free_balance(&caller), Zero::zero()); + if cfg!(feature = "insecure_zero_ed") { + assert_eq!(Balances::<T, I>::free_balance(&caller), balance - transfer_amount); + } else { + assert_eq!(Balances::<T, I>::free_balance(&caller), Zero::zero()); + } + assert_eq!(Balances::<T, I>::free_balance(&recipient), transfer_amount); } @@ -308,7 +323,7 @@ mod benchmarks { /// Benchmark `burn` extrinsic with the worst possible condition - burn kills the account. #[benchmark] fn burn_allow_death() { - let existential_deposit = T::ExistentialDeposit::get(); + let existential_deposit: T::Balance = minimum_balance::<T, I>(); let caller = whitelisted_caller(); // Give some multiple of the existential deposit @@ -321,13 +336,17 @@ mod benchmarks { #[extrinsic_call] burn(RawOrigin::Signed(caller.clone()), burn_amount, false); - assert_eq!(Balances::<T, I>::free_balance(&caller), Zero::zero()); + if cfg!(feature = "insecure_zero_ed") { + assert_eq!(Balances::<T, I>::free_balance(&caller), balance - burn_amount); + } else { + assert_eq!(Balances::<T, I>::free_balance(&caller), Zero::zero()); + } } // Benchmark `burn` extrinsic with the case where account is kept alive. #[benchmark] fn burn_keep_alive() { - let existential_deposit = T::ExistentialDeposit::get(); + let existential_deposit: T::Balance = minimum_balance::<T, I>(); let caller = whitelisted_caller(); // Give some multiple of the existential deposit diff --git a/substrate/frame/balances/src/impl_currency.rs b/substrate/frame/balances/src/impl_currency.rs index bc7e77c191db86dd2805f200c3ceb17a293fce73..f453b23420c400dddd01fe1013f358c3199c1ff2 100644 --- a/substrate/frame/balances/src/impl_currency.rs +++ b/substrate/frame/balances/src/impl_currency.rs @@ -674,8 +674,10 @@ where Reserves::<T, I>::try_mutate(who, |reserves| -> DispatchResult { match reserves.binary_search_by_key(id, |data| data.id) { Ok(index) => { - // this add can't overflow but just to be defensive. - reserves[index].amount = reserves[index].amount.defensive_saturating_add(value); + reserves[index].amount = reserves[index] + .amount + .checked_add(&value) + .ok_or(ArithmeticError::Overflow)?; }, Err(index) => { reserves diff --git a/substrate/frame/balances/src/tests/currency_tests.rs b/substrate/frame/balances/src/tests/currency_tests.rs index a6377c3ad72e8b5185422ebf2e2caefd045b9251..0e5d7ccb46dee87d82bc3183d4c34922e00b0f7f 100644 --- a/substrate/frame/balances/src/tests/currency_tests.rs +++ b/substrate/frame/balances/src/tests/currency_tests.rs @@ -24,7 +24,7 @@ use frame_support::{ BalanceStatus::{Free, Reserved}, Currency, ExistenceRequirement::{self, AllowDeath, KeepAlive}, - Hooks, InspectLockableCurrency, LockIdentifier, LockableCurrency, NamedReservableCurrency, + InspectLockableCurrency, LockIdentifier, LockableCurrency, NamedReservableCurrency, ReservableCurrency, WithdrawReasons, }, StorageNoopGuard, @@ -1136,7 +1136,9 @@ fn operations_on_dead_account_should_not_change_state() { #[test] #[should_panic = "The existential deposit must be greater than zero!"] +#[cfg(not(feature = "insecure_zero_ed"))] fn zero_ed_is_prohibited() { + use frame_support::traits::Hooks; // These functions all use `mutate_account` which may introduce a storage change when // the account never existed to begin with, and shouldn't exist in the end. ExtBuilder::default().existential_deposit(0).build_and_execute_with(|| { diff --git a/substrate/frame/contracts/Cargo.toml b/substrate/frame/contracts/Cargo.toml index 5784e6dd1553382e9ad2a27261243e7dd987fdf9..88404803fe0f3b805ba6f86e80bf34f944d5b612 100644 --- a/substrate/frame/contracts/Cargo.toml +++ b/substrate/frame/contracts/Cargo.toml @@ -65,10 +65,8 @@ wat = { workspace = true } xcm-builder = { workspace = true, default-features = true } # Substrate Dependencies -pallet-assets = { workspace = true, default-features = true } pallet-balances = { workspace = true, default-features = true } pallet-insecure-randomness-collective-flip = { workspace = true, default-features = true } -pallet-message-queue = { workspace = true, default-features = true } pallet-proxy = { workspace = true, default-features = true } pallet-timestamp = { workspace = true, default-features = true } pallet-utility = { workspace = true, default-features = true } @@ -106,9 +104,7 @@ runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", - "pallet-assets/runtime-benchmarks", "pallet-balances/runtime-benchmarks", - "pallet-message-queue/runtime-benchmarks", "pallet-proxy/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", "pallet-utility/runtime-benchmarks", @@ -122,10 +118,8 @@ runtime-benchmarks = [ try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", - "pallet-assets/try-runtime", "pallet-balances/try-runtime", "pallet-insecure-randomness-collective-flip/try-runtime", - "pallet-message-queue/try-runtime", "pallet-proxy/try-runtime", "pallet-timestamp/try-runtime", "pallet-utility/try-runtime", diff --git a/substrate/frame/contracts/mock-network/Cargo.toml b/substrate/frame/contracts/mock-network/Cargo.toml index a7423b33abc17f02491fcbd41da04a698f9f378d..84aa95694b5090fd7aeea408d858f5837639f625 100644 --- a/substrate/frame/contracts/mock-network/Cargo.toml +++ b/substrate/frame/contracts/mock-network/Cargo.toml @@ -21,11 +21,8 @@ pallet-balances = { workspace = true, default-features = true } pallet-contracts = { workspace = true, default-features = true } pallet-contracts-proc-macro = { workspace = true, default-features = true } pallet-contracts-uapi = { workspace = true } -pallet-insecure-randomness-collective-flip = { workspace = true, default-features = true } pallet-message-queue = { workspace = true, default-features = true } -pallet-proxy = { workspace = true, default-features = true } pallet-timestamp = { workspace = true, default-features = true } -pallet-utility = { workspace = true, default-features = true } pallet-xcm = { workspace = true } polkadot-parachain-primitives = { workspace = true, default-features = true } polkadot-primitives = { workspace = true, default-features = true } @@ -43,9 +40,7 @@ xcm-executor = { workspace = true } xcm-simulator = { workspace = true, default-features = true } [dev-dependencies] -assert_matches = { workspace = true } pallet-contracts-fixtures = { workspace = true } -pretty_assertions = { workspace = true } [features] default = ["std"] @@ -55,10 +50,7 @@ std = [ "frame-system/std", "pallet-balances/std", "pallet-contracts/std", - "pallet-insecure-randomness-collective-flip/std", - "pallet-proxy/std", "pallet-timestamp/std", - "pallet-utility/std", "pallet-xcm/std", "scale-info/std", "sp-api/std", @@ -77,9 +69,7 @@ runtime-benchmarks = [ "pallet-balances/runtime-benchmarks", "pallet-contracts/runtime-benchmarks", "pallet-message-queue/runtime-benchmarks", - "pallet-proxy/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", - "pallet-utility/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", "polkadot-parachain-primitives/runtime-benchmarks", "polkadot-primitives/runtime-benchmarks", diff --git a/substrate/frame/conviction-voting/Cargo.toml b/substrate/frame/conviction-voting/Cargo.toml index 2d23f493ea0132a742691fe9f3179177d310c951..e2d483609769d3f8a7b995d23402b2cb1a8ac38a 100644 --- a/substrate/frame/conviction-voting/Cargo.toml +++ b/substrate/frame/conviction-voting/Cargo.toml @@ -31,7 +31,6 @@ sp-runtime = { workspace = true } [dev-dependencies] pallet-balances = { workspace = true, default-features = true } -pallet-scheduler = { workspace = true, default-features = true } sp-core = { workspace = true, default-features = true } [features] @@ -42,7 +41,6 @@ std = [ "frame-support/std", "frame-system/std", "pallet-balances/std", - "pallet-scheduler/std", "scale-info/std", "serde", "sp-core/std", @@ -54,13 +52,11 @@ runtime-benchmarks = [ "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-balances/runtime-benchmarks", - "pallet-scheduler/runtime-benchmarks", "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "pallet-balances/try-runtime", - "pallet-scheduler/try-runtime", "sp-runtime/try-runtime", ] diff --git a/substrate/frame/delegated-staking/Cargo.toml b/substrate/frame/delegated-staking/Cargo.toml index 576276dced5212c47d85777a6a9606a3822a0dbb..3a2498fb99128d68b18a62c79505a77516974d9e 100644 --- a/substrate/frame/delegated-staking/Cargo.toml +++ b/substrate/frame/delegated-staking/Cargo.toml @@ -31,7 +31,6 @@ pallet-timestamp = { workspace = true, default-features = true } sp-core = { workspace = true, default-features = true } sp-io = { workspace = true, default-features = true } sp-tracing = { workspace = true, default-features = true } -substrate-test-utils = { workspace = true } [features] default = ["std"] diff --git a/substrate/frame/examples/Cargo.toml b/substrate/frame/examples/Cargo.toml index 9eac53f0d98b064c3b271357db6c0bf6b4f3a005..40d6959378b8799e3b1e6e655373bf4e5409652e 100644 --- a/substrate/frame/examples/Cargo.toml +++ b/substrate/frame/examples/Cargo.toml @@ -26,6 +26,7 @@ pallet-example-offchain-worker = { workspace = true } pallet-example-single-block-migrations = { workspace = true } pallet-example-split = { workspace = true } pallet-example-tasks = { workspace = true } +pallet-example-view-functions = { workspace = true } [features] default = ["std"] @@ -40,6 +41,7 @@ std = [ "pallet-example-single-block-migrations/std", "pallet-example-split/std", "pallet-example-tasks/std", + "pallet-example-view-functions/std", ] try-runtime = [ "pallet-default-config-example/try-runtime", @@ -51,4 +53,5 @@ try-runtime = [ "pallet-example-single-block-migrations/try-runtime", "pallet-example-split/try-runtime", "pallet-example-tasks/try-runtime", + "pallet-example-view-functions/try-runtime", ] diff --git a/substrate/frame/examples/src/lib.rs b/substrate/frame/examples/src/lib.rs index d0d30830f2f04d1bfd4c4afa5a39be91ee549a54..200e92112a3f3b4ba9552a8de68401fc290469e4 100644 --- a/substrate/frame/examples/src/lib.rs +++ b/substrate/frame/examples/src/lib.rs @@ -48,6 +48,9 @@ //! //! - [`pallet_example_tasks`]: This pallet demonstrates the use of `Tasks` to execute service work. //! +//! - [`pallet_example_view_functions`]: This pallet demonstrates the use of view functions to query +//! pallet state. +//! //! - [`pallet_example_authorization_tx_extension`]: An example `TransactionExtension` that //! authorizes a custom origin through signature validation, along with two support pallets to //! showcase the usage. diff --git a/substrate/frame/examples/view-functions/Cargo.toml b/substrate/frame/examples/view-functions/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..b52ad4e06e9fa9c32b3f0ad422198789825c4a4e --- /dev/null +++ b/substrate/frame/examples/view-functions/Cargo.toml @@ -0,0 +1,61 @@ +[package] +name = "pallet-example-view-functions" +version = "1.0.0" +authors.workspace = true +edition.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true +description = "Pallet to demonstrate the usage of view functions to query pallet state" + +[lints] +workspace = true + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { package = "parity-scale-codec", default-features = false, workspace = true } +frame-metadata = { features = ["current"], workspace = true } +log = { workspace = true } +scale-info = { default-features = false, features = ["derive"], workspace = true } + +frame-support = { default-features = false, workspace = true } +frame-system = { default-features = false, workspace = true } + +sp-core = { default-features = false, workspace = true } +sp-io = { default-features = false, workspace = true } +sp-metadata-ir = { default-features = false, workspace = true } +sp-runtime = { default-features = false, workspace = true } + +frame-benchmarking = { default-features = false, optional = true, workspace = true } + +[dev-dependencies] +pretty_assertions = { workspace = true } + +[features] +default = ["std"] +std = [ + "codec/std", + "frame-benchmarking?/std", + "frame-metadata/std", + "frame-support/std", + "frame-system/std", + "log/std", + "scale-info/std", + "sp-core/std", + "sp-io/std", + "sp-metadata-ir/std", + "sp-runtime/std", +] +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", +] +try-runtime = [ + "frame-support/try-runtime", + "frame-system/try-runtime", + "sp-runtime/try-runtime", +] diff --git a/substrate/frame/examples/view-functions/src/lib.rs b/substrate/frame/examples/view-functions/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..e842a718ad33442b1f83a88963d637b2e6ca77bf --- /dev/null +++ b/substrate/frame/examples/view-functions/src/lib.rs @@ -0,0 +1,114 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! This pallet demonstrates the use of the `pallet::view_functions_experimental` api for service +//! work. +#![cfg_attr(not(feature = "std"), no_std)] + +pub mod tests; + +use frame_support::Parameter; +use scale_info::TypeInfo; + +pub struct SomeType1; +impl From<SomeType1> for u64 { + fn from(_t: SomeType1) -> Self { + 0u64 + } +} + +pub trait SomeAssociation1 { + type _1: Parameter + codec::MaxEncodedLen + TypeInfo; +} +impl SomeAssociation1 for u64 { + type _1 = u64; +} + +#[frame_support::pallet] +pub mod pallet { + use super::*; + use frame_support::pallet_prelude::*; + + #[pallet::error] + pub enum Error<T> {} + + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::pallet] + pub struct Pallet<T>(_); + + #[pallet::storage] + pub type SomeValue<T: Config> = StorageValue<_, u32>; + + #[pallet::storage] + pub type SomeMap<T: Config> = StorageMap<_, Twox64Concat, u32, u32, OptionQuery>; + + #[pallet::view_functions_experimental] + impl<T: Config> Pallet<T> + where + T::AccountId: From<SomeType1> + SomeAssociation1, + { + /// Query value no args. + pub fn get_value() -> Option<u32> { + SomeValue::<T>::get() + } + + /// Query value with args. + pub fn get_value_with_arg(key: u32) -> Option<u32> { + SomeMap::<T>::get(key) + } + } +} + +#[frame_support::pallet] +pub mod pallet2 { + use super::*; + use frame_support::pallet_prelude::*; + + #[pallet::error] + pub enum Error<T, I = ()> {} + + #[pallet::config] + pub trait Config<I: 'static = ()>: frame_system::Config {} + + #[pallet::pallet] + pub struct Pallet<T, I = ()>(PhantomData<(T, I)>); + + #[pallet::storage] + pub type SomeValue<T: Config<I>, I: 'static = ()> = StorageValue<_, u32>; + + #[pallet::storage] + pub type SomeMap<T: Config<I>, I: 'static = ()> = + StorageMap<_, Twox64Concat, u32, u32, OptionQuery>; + + #[pallet::view_functions_experimental] + impl<T: Config<I>, I: 'static> Pallet<T, I> + where + T::AccountId: From<SomeType1> + SomeAssociation1, + { + /// Query value no args. + pub fn get_value() -> Option<u32> { + SomeValue::<T, I>::get() + } + + /// Query value with args. + pub fn get_value_with_arg(key: u32) -> Option<u32> { + SomeMap::<T, I>::get(key) + } + } +} diff --git a/substrate/frame/examples/view-functions/src/tests.rs b/substrate/frame/examples/view-functions/src/tests.rs new file mode 100644 index 0000000000000000000000000000000000000000..25f5f094651d6a085c041702118a8e69a5f7e4c1 --- /dev/null +++ b/substrate/frame/examples/view-functions/src/tests.rs @@ -0,0 +1,188 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Tests for `pallet-example-view-functions`. +#![cfg(test)] + +use crate::{ + pallet::{self, Pallet}, + pallet2, +}; +use codec::{Decode, Encode}; +use scale_info::{form::PortableForm, meta_type}; + +use frame_support::{derive_impl, pallet_prelude::PalletInfoAccess, view_functions::ViewFunction}; +use sp_io::hashing::twox_128; +use sp_metadata_ir::{ViewFunctionArgMetadataIR, ViewFunctionGroupIR, ViewFunctionMetadataIR}; +use sp_runtime::testing::TestXt; + +pub type AccountId = u32; +pub type Balance = u32; + +type Block = frame_system::mocking::MockBlock<Runtime>; +frame_support::construct_runtime!( + pub enum Runtime { + System: frame_system, + ViewFunctionsExample: pallet, + ViewFunctionsInstance: pallet2, + ViewFunctionsInstance1: pallet2::<Instance1>, + } +); + +pub type Extrinsic = TestXt<RuntimeCall, ()>; + +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] +impl frame_system::Config for Runtime { + type Block = Block; +} + +impl pallet::Config for Runtime {} +impl pallet2::Config<pallet2::Instance1> for Runtime {} + +impl pallet2::Config for Runtime {} + +pub fn new_test_ext() -> sp_io::TestExternalities { + use sp_runtime::BuildStorage; + + let t = RuntimeGenesisConfig { system: Default::default() }.build_storage().unwrap(); + t.into() +} + +#[test] +fn pallet_get_value_query() { + new_test_ext().execute_with(|| { + let some_value = Some(99); + pallet::SomeValue::<Runtime>::set(some_value); + assert_eq!(some_value, Pallet::<Runtime>::get_value()); + + let query = pallet::GetValueViewFunction::<Runtime>::new(); + test_dispatch_view_function(&query, some_value); + }); +} + +#[test] +fn pallet_get_value_with_arg_query() { + new_test_ext().execute_with(|| { + let some_key = 1u32; + let some_value = Some(123); + pallet::SomeMap::<Runtime>::set(some_key, some_value); + assert_eq!(some_value, Pallet::<Runtime>::get_value_with_arg(some_key)); + + let query = pallet::GetValueWithArgViewFunction::<Runtime>::new(some_key); + test_dispatch_view_function(&query, some_value); + }); +} + +#[test] +fn pallet_multiple_instances() { + use pallet2::Instance1; + + new_test_ext().execute_with(|| { + let instance_value = Some(123); + let instance1_value = Some(456); + + pallet2::SomeValue::<Runtime>::set(instance_value); + pallet2::SomeValue::<Runtime, Instance1>::set(instance1_value); + + let query = pallet2::GetValueViewFunction::<Runtime>::new(); + test_dispatch_view_function(&query, instance_value); + + let query_instance1 = pallet2::GetValueViewFunction::<Runtime, Instance1>::new(); + test_dispatch_view_function(&query_instance1, instance1_value); + }); +} + +#[test] +fn metadata_ir_definitions() { + new_test_ext().execute_with(|| { + let metadata_ir = Runtime::metadata_ir(); + let pallet1 = metadata_ir + .view_functions + .groups + .iter() + .find(|pallet| pallet.name == "ViewFunctionsExample") + .unwrap(); + + fn view_fn_id(preifx_hash: [u8; 16], view_fn_signature: &str) -> [u8; 32] { + let mut id = [0u8; 32]; + id[..16].copy_from_slice(&preifx_hash); + id[16..].copy_from_slice(&twox_128(view_fn_signature.as_bytes())); + id + } + + let get_value_id = view_fn_id( + <ViewFunctionsExample as PalletInfoAccess>::name_hash(), + "get_value() -> Option<u32>", + ); + + let get_value_with_arg_id = view_fn_id( + <ViewFunctionsExample as PalletInfoAccess>::name_hash(), + "get_value_with_arg(u32) -> Option<u32>", + ); + + pretty_assertions::assert_eq!( + pallet1.view_functions, + vec![ + ViewFunctionMetadataIR { + name: "get_value", + id: get_value_id, + args: vec![], + output: meta_type::<Option<u32>>(), + docs: vec![" Query value no args."], + }, + ViewFunctionMetadataIR { + name: "get_value_with_arg", + id: get_value_with_arg_id, + args: vec![ViewFunctionArgMetadataIR { name: "key", ty: meta_type::<u32>() },], + output: meta_type::<Option<u32>>(), + docs: vec![" Query value with args."], + }, + ] + ); + }); +} + +#[test] +fn metadata_encoded_to_custom_value() { + new_test_ext().execute_with(|| { + let metadata = sp_metadata_ir::into_latest(Runtime::metadata_ir()); + // metadata is currently experimental so lives as a custom value. + let frame_metadata::RuntimeMetadata::V15(v15) = metadata.1 else { + panic!("Expected metadata v15") + }; + let custom_value = v15 + .custom + .map + .get("view_functions_experimental") + .expect("Expected custom value"); + let view_function_groups: Vec<ViewFunctionGroupIR<PortableForm>> = + Decode::decode(&mut &custom_value.value[..]).unwrap(); + assert_eq!(view_function_groups.len(), 4); + }); +} + +fn test_dispatch_view_function<Q, V>(query: &Q, expected: V) +where + Q: ViewFunction + Encode, + V: Decode + Eq + PartialEq + std::fmt::Debug, +{ + let input = query.encode(); + let output = Runtime::execute_view_function(Q::id(), input).unwrap(); + let query_result = V::decode(&mut &output[..]).unwrap(); + + assert_eq!(expected, query_result,); +} diff --git a/substrate/frame/fast-unstake/Cargo.toml b/substrate/frame/fast-unstake/Cargo.toml index 98a9655074e7c3f46340271af0108bfeab1fd2fc..209406dc3f99ad411855d8c0824c2e4ff53ce96f 100644 --- a/substrate/frame/fast-unstake/Cargo.toml +++ b/substrate/frame/fast-unstake/Cargo.toml @@ -38,7 +38,6 @@ pallet-staking-reward-curve = { workspace = true, default-features = true } pallet-timestamp = { workspace = true, default-features = true } sp-core = { workspace = true } sp-tracing = { workspace = true, default-features = true } -substrate-test-utils = { workspace = true } [features] default = ["std"] diff --git a/substrate/frame/glutton/Cargo.toml b/substrate/frame/glutton/Cargo.toml index 317a9ea8b7604275830c21d22b20529e5ca3bf9c..7f7b24c12117bdfd34f4e91cfd27b0d0a67bedaf 100644 --- a/substrate/frame/glutton/Cargo.toml +++ b/substrate/frame/glutton/Cargo.toml @@ -28,9 +28,6 @@ sp-inherents = { workspace = true } sp-io = { workspace = true } sp-runtime = { workspace = true } -[dev-dependencies] -pallet-balances = { workspace = true, default-features = true } - [features] default = ["std"] std = [ @@ -40,7 +37,6 @@ std = [ "frame-support/std", "frame-system/std", "log/std", - "pallet-balances/std", "scale-info/std", "sp-core/std", "sp-inherents/std", @@ -50,7 +46,6 @@ std = [ try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", - "pallet-balances/try-runtime", "sp-runtime/try-runtime", ] @@ -58,6 +53,5 @@ runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", - "pallet-balances/runtime-benchmarks", "sp-runtime/runtime-benchmarks", ] diff --git a/substrate/frame/indices/Cargo.toml b/substrate/frame/indices/Cargo.toml index a0030b5b0edf82728cca7e9322cee4d364de4737..fdc1753e44fcb988df639c81356e38d4da84d5a0 100644 --- a/substrate/frame/indices/Cargo.toml +++ b/substrate/frame/indices/Cargo.toml @@ -23,7 +23,6 @@ frame-system = { workspace = true } scale-info = { features = ["derive"], workspace = true } sp-core = { workspace = true } sp-io = { workspace = true } -sp-keyring = { optional = true, workspace = true } sp-runtime = { workspace = true } [dev-dependencies] @@ -40,8 +39,6 @@ std = [ "scale-info/std", "sp-core/std", "sp-io/std", - "sp-keyring", - "sp-keyring?/std", "sp-runtime/std", ] runtime-benchmarks = [ diff --git a/substrate/frame/migrations/Cargo.toml b/substrate/frame/migrations/Cargo.toml index 469592780beb8855691ca4a8b1438f5abf4c9d40..f05db314ae57ee201a7d715c4e642a3d06c9e5cf 100644 --- a/substrate/frame/migrations/Cargo.toml +++ b/substrate/frame/migrations/Cargo.toml @@ -18,17 +18,18 @@ impl-trait-for-tuples = { workspace = true } log = { workspace = true, default-features = true } scale-info = { features = ["derive"], workspace = true } +frame = { workspace = true, features = ["runtime"] } frame-benchmarking = { optional = true, workspace = true } frame-support = { workspace = true } frame-system = { workspace = true } sp-core = { workspace = true } +sp-io = { workspace = true } sp-runtime = { workspace = true } [dev-dependencies] frame-executive = { workspace = true, default-features = true } sp-api = { features = ["std"], workspace = true, default-features = true } sp-block-builder = { features = ["std"], workspace = true, default-features = true } -sp-io = { features = ["std"], workspace = true, default-features = true } sp-tracing = { features = ["std"], workspace = true, default-features = true } sp-version = { features = ["std"], workspace = true, default-features = true } @@ -42,9 +43,11 @@ std = [ "frame-benchmarking?/std", "frame-support/std", "frame-system/std", + "frame/std", "log/std", "scale-info/std", "sp-core/std", + "sp-io/std", "sp-runtime/std", ] @@ -52,6 +55,7 @@ runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", + "frame/runtime-benchmarks", "sp-runtime/runtime-benchmarks", ] @@ -59,5 +63,6 @@ try-runtime = [ "frame-executive/try-runtime", "frame-support/try-runtime", "frame-system/try-runtime", + "frame/try-runtime", "sp-runtime/try-runtime", ] diff --git a/substrate/frame/migrations/src/benchmarking.rs b/substrate/frame/migrations/src/benchmarking.rs index c076d40bb05cddebef31bfed7e597ba607b0de86..f06870fa9502c86c892cff4fdcad5539062ec9ae 100644 --- a/substrate/frame/migrations/src/benchmarking.rs +++ b/substrate/frame/migrations/src/benchmarking.rs @@ -19,8 +19,11 @@ use super::*; +use core::array; use frame_benchmarking::{v2::*, BenchmarkError}; use frame_system::{Pallet as System, RawOrigin}; +use sp_core::{twox_128, Get}; +use sp_io::{storage, KillStorageResult}; use sp_runtime::traits::One; fn assert_last_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) { @@ -204,6 +207,40 @@ mod benches { ); } + #[benchmark(skip_meta, pov_mode = Measured)] + fn reset_pallet_migration(n: Linear<0, 2048>) -> Result<(), BenchmarkError> { + let prefix: [u8; 16] = twox_128(b"__ResetPalletBenchmarkPrefix__"); + + for i in 0..n { + // we need to avoid allocations here + let mut iter = prefix.into_iter().chain(i.to_le_bytes()); + let key: [u8; 20] = array::from_fn(|_| iter.next().unwrap()); + // 32 byte will trigger the worst case where the value is + // no longer stored inline + storage::set(&key, &[0u8; 32]); + } + + let result; + #[block] + { + result = storage::clear_prefix(&prefix, None); + } + + // It will always reports no keys removed because they are still in the overlay. + // However, the benchmarking PoV results are correctly dependent on the amount of + // keys removed. + match result { + KillStorageResult::AllRemoved(_i) => { + // during the test the storage is not comitted and `i` will always be 0 + #[cfg(not(test))] + ensure!(_i == n, "Not all keys are removed"); + }, + _ => Err("Not all keys were removed")?, + } + + Ok(()) + } + fn cursor<T: Config>() -> CursorOf<T> { // Note: The weight of a function can depend on the weight of reading the `inner_cursor`. // `Cursor` is a user provided type. Now instead of requiring something like `Cursor: diff --git a/substrate/frame/migrations/src/lib.rs b/substrate/frame/migrations/src/lib.rs index d9490e7dcfe99fed3cc70560f6f25e61f4fc190f..fef61468e6e4ebe6c70626d13e23800f3e65f84e 100644 --- a/substrate/frame/migrations/src/lib.rs +++ b/substrate/frame/migrations/src/lib.rs @@ -145,6 +145,7 @@ #![cfg_attr(not(feature = "std"), no_std)] mod benchmarking; +pub mod migrations; mod mock; pub mod mock_helpers; mod tests; @@ -298,7 +299,11 @@ type PreUpgradeBytes<T: Config> = pub mod pallet { use super::*; + /// The in-code storage version. + const STORAGE_VERSION: StorageVersion = StorageVersion::new(0); + #[pallet::pallet] + #[pallet::storage_version(STORAGE_VERSION)] pub struct Pallet<T>(_); #[pallet::config(with_default)] diff --git a/substrate/frame/migrations/src/migrations.rs b/substrate/frame/migrations/src/migrations.rs new file mode 100644 index 0000000000000000000000000000000000000000..796ff0f956599d959a78dadcbf65e068ff95b996 --- /dev/null +++ b/substrate/frame/migrations/src/migrations.rs @@ -0,0 +1,135 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Generic multi block migrations not specific to any pallet. + +use crate::{weights::WeightInfo, Config}; +use codec::Encode; +use core::marker::PhantomData; +use frame_support::{ + migrations::{SteppedMigration, SteppedMigrationError, StoreInCodeStorageVersion}, + traits::{GetStorageVersion, PalletInfoAccess}, + weights::WeightMeter, +}; +use sp_core::{twox_128, Get}; +use sp_io::{storage::clear_prefix, KillStorageResult}; +use sp_runtime::SaturatedConversion; + +/// Remove all of a pallet's state and re-initializes it to the current in-code storage version. +/// +/// It uses the multi block migration frame. Hence it is safe to use even on +/// pallets that contain a lot of storage. +/// +/// # Parameters +/// +/// - T: The runtime. Used to access the weight definition. +/// - P: The pallet to resetted as defined in construct runtime +/// +/// # Note +/// +/// If your pallet does rely of some state in genesis you need to take care of that +/// separately. This migration only sets the storage version after wiping. +pub struct ResetPallet<T, P>(PhantomData<(T, P)>); + +impl<T, P> ResetPallet<T, P> +where + P: PalletInfoAccess, +{ + #[cfg(feature = "try-runtime")] + fn num_keys() -> u64 { + let prefix = P::name_hash().to_vec(); + crate::storage::KeyPrefixIterator::new(prefix.clone(), prefix, |_| Ok(())).count() as _ + } +} + +impl<T, P, V> SteppedMigration for ResetPallet<T, P> +where + T: Config, + P: PalletInfoAccess + GetStorageVersion<InCodeStorageVersion = V>, + V: StoreInCodeStorageVersion<P>, +{ + type Cursor = bool; + type Identifier = [u8; 16]; + + fn id() -> Self::Identifier { + ("RemovePallet::", P::name()).using_encoded(twox_128) + } + + fn step( + cursor: Option<Self::Cursor>, + meter: &mut WeightMeter, + ) -> Result<Option<Self::Cursor>, SteppedMigrationError> { + // we write the storage version in a seperate block + if cursor.unwrap_or(false) { + let required = T::DbWeight::get().writes(1); + meter + .try_consume(required) + .map_err(|_| SteppedMigrationError::InsufficientWeight { required })?; + V::store_in_code_storage_version(); + return Ok(None); + } + + let base_weight = T::WeightInfo::reset_pallet_migration(0); + let weight_per_key = T::WeightInfo::reset_pallet_migration(1).saturating_sub(base_weight); + let key_budget = meter + .remaining() + .saturating_sub(base_weight) + .checked_div_per_component(&weight_per_key) + .unwrap_or_default() + .saturated_into(); + + if key_budget == 0 { + return Err(SteppedMigrationError::InsufficientWeight { + required: T::WeightInfo::reset_pallet_migration(1), + }) + } + + let (keys_removed, is_done) = match clear_prefix(&P::name_hash(), Some(key_budget)) { + KillStorageResult::AllRemoved(value) => (value, true), + KillStorageResult::SomeRemaining(value) => (value, false), + }; + + meter.consume(T::WeightInfo::reset_pallet_migration(keys_removed)); + + Ok(Some(is_done)) + } + + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result<alloc::vec::Vec<u8>, sp_runtime::TryRuntimeError> { + let num_keys: u64 = Self::num_keys(); + log::info!("ResetPallet<{}>: Trying to remove {num_keys} keys.", P::name()); + Ok(num_keys.encode()) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(state: alloc::vec::Vec<u8>) -> Result<(), sp_runtime::TryRuntimeError> { + use codec::Decode; + let keys_before = u64::decode(&mut state.as_ref()).expect("We encoded as u64 above; qed"); + let keys_now = Self::num_keys(); + log::info!("ResetPallet<{}>: Keys remaining after migration: {keys_now}", P::name()); + + if keys_before <= keys_now { + log::error!("ResetPallet<{}>: Did not remove any keys.", P::name()); + Err("ResetPallet failed")?; + } + + if keys_now != 1 { + log::error!("ResetPallet<{}>: Should have a single key after reset", P::name()); + Err("ResetPallet failed")?; + } + + Ok(()) + } +} diff --git a/substrate/frame/migrations/src/weights.rs b/substrate/frame/migrations/src/weights.rs index 49ae379dba020a39d12c6252c032e8f74ab2f494..10dfd82cbd8132358f82baf17340c62cbd26a5d3 100644 --- a/substrate/frame/migrations/src/weights.rs +++ b/substrate/frame/migrations/src/weights.rs @@ -18,36 +18,38 @@ //! Autogenerated weights for `pallet_migrations` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-11-08, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2025-01-27, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-wiukf8gn-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `17938671047b`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate-node +// frame-omni-bencher +// v1 // benchmark // pallet -// --chain=dev +// --extrinsic=* +// --runtime=target/production/wbuild/kitchensink-runtime/kitchensink_runtime.wasm +// --pallet=pallet_migrations +// --header=/__w/polkadot-sdk/polkadot-sdk/substrate/HEADER-APACHE2 +// --output=/__w/polkadot-sdk/polkadot-sdk/substrate/frame/migrations/src/weights.rs +// --wasm-execution=compiled // --steps=50 // --repeat=20 -// --pallet=pallet_migrations +// --heap-pages=4096 +// --template=substrate/.maintain/frame-weight-template.hbs // --no-storage-info -// --no-median-slopes // --no-min-squares -// --extrinsic=* -// --wasm-execution=compiled -// --heap-pages=4096 -// --output=./substrate/frame/migrations/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --no-median-slopes +// --genesis-builder-policy=none +// --exclude-pallets=pallet_xcm,pallet_xcm_benchmarks::fungible,pallet_xcm_benchmarks::generic,pallet_nomination_pools,pallet_remark,pallet_transaction_storage #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] #![allow(unused_imports)] #![allow(missing_docs)] -use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; -use core::marker::PhantomData; +use frame::weights_prelude::*; /// Weight functions needed for `pallet_migrations`. pub trait WeightInfo { @@ -63,6 +65,7 @@ pub trait WeightInfo { fn force_set_active_cursor() -> Weight; fn force_onboard_mbms() -> Weight; fn clear_historic(n: u32, ) -> Weight; + fn reset_pallet_migration(n: u32, ) -> Weight; } /// Weights for `pallet_migrations` using the Substrate node and recommended hardware. @@ -74,10 +77,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) fn onboard_new_mbms() -> Weight { // Proof Size summary in bytes: - // Measured: `309` + // Measured: `0` // Estimated: `67035` - // Minimum execution time: 9_520_000 picoseconds. - Weight::from_parts(9_934_000, 67035) + // Minimum execution time: 4_422_000 picoseconds. + Weight::from_parts(4_560_000, 67035) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -85,10 +88,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) fn progress_mbms_none() -> Weight { // Proof Size summary in bytes: - // Measured: `142` + // Measured: `0` // Estimated: `67035` - // Minimum execution time: 2_993_000 picoseconds. - Weight::from_parts(3_088_000, 67035) + // Minimum execution time: 678_000 picoseconds. + Weight::from_parts(751_000, 67035) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -97,10 +100,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) fn exec_migration_completed() -> Weight { // Proof Size summary in bytes: - // Measured: `167` - // Estimated: `3632` - // Minimum execution time: 7_042_000 picoseconds. - Weight::from_parts(7_272_000, 3632) + // Measured: `0` + // Estimated: `3465` + // Minimum execution time: 3_791_000 picoseconds. + Weight::from_parts(3_930_000, 3465) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -110,10 +113,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) fn exec_migration_skipped_historic() -> Weight { // Proof Size summary in bytes: - // Measured: `363` - // Estimated: `3828` - // Minimum execution time: 16_522_000 picoseconds. - Weight::from_parts(17_082_000, 3828) + // Measured: `34` + // Estimated: `3731` + // Minimum execution time: 7_375_000 picoseconds. + Weight::from_parts(7_630_000, 3731) .saturating_add(T::DbWeight::get().reads(2_u64)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -122,10 +125,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) fn exec_migration_advance() -> Weight { // Proof Size summary in bytes: - // Measured: `309` - // Estimated: `3774` - // Minimum execution time: 12_445_000 picoseconds. - Weight::from_parts(12_797_000, 3774) + // Measured: `0` + // Estimated: `3731` + // Minimum execution time: 6_771_000 picoseconds. + Weight::from_parts(6_894_000, 3731) .saturating_add(T::DbWeight::get().reads(2_u64)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -134,10 +137,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) fn exec_migration_complete() -> Weight { // Proof Size summary in bytes: - // Measured: `309` - // Estimated: `3774` - // Minimum execution time: 14_057_000 picoseconds. - Weight::from_parts(14_254_000, 3774) + // Measured: `0` + // Estimated: `3731` + // Minimum execution time: 8_223_000 picoseconds. + Weight::from_parts(8_406_000, 3731) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -149,10 +152,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) fn exec_migration_fail() -> Weight { // Proof Size summary in bytes: - // Measured: `309` - // Estimated: `3774` - // Minimum execution time: 14_578_000 picoseconds. - Weight::from_parts(14_825_000, 3774) + // Measured: `0` + // Estimated: `3731` + // Minimum execution time: 8_907_000 picoseconds. + Weight::from_parts(9_168_000, 3731) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -160,8 +163,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 169_000 picoseconds. - Weight::from_parts(197_000, 0) + // Minimum execution time: 143_000 picoseconds. + Weight::from_parts(174_000, 0) } /// Storage: `MultiBlockMigrations::Cursor` (r:0 w:1) /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) @@ -169,8 +172,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_634_000 picoseconds. - Weight::from_parts(2_798_000, 0) + // Minimum execution time: 2_172_000 picoseconds. + Weight::from_parts(2_259_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `MultiBlockMigrations::Cursor` (r:0 w:1) @@ -179,8 +182,8 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_069_000 picoseconds. - Weight::from_parts(3_293_000, 0) + // Minimum execution time: 2_600_000 picoseconds. + Weight::from_parts(2_728_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `MultiBlockMigrations::Cursor` (r:1 w:0) @@ -189,10 +192,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) fn force_onboard_mbms() -> Weight { // Proof Size summary in bytes: - // Measured: `284` + // Measured: `0` // Estimated: `67035` - // Minimum execution time: 7_674_000 picoseconds. - Weight::from_parts(8_000_000, 67035) + // Minimum execution time: 2_949_000 picoseconds. + Weight::from_parts(3_106_000, 67035) .saturating_add(T::DbWeight::get().reads(2_u64)) } /// Storage: `MultiBlockMigrations::Historic` (r:256 w:256) @@ -200,17 +203,32 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { /// The range of component `n` is `[0, 256]`. fn clear_historic(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1122 + n * (271 ±0)` + // Measured: `960 + n * (271 ±0)` // Estimated: `3834 + n * (2740 ±0)` - // Minimum execution time: 16_937_000 picoseconds. - Weight::from_parts(15_713_121, 3834) - // Standard Error: 2_580 - .saturating_add(Weight::from_parts(1_424_239, 0).saturating_mul(n.into())) + // Minimum execution time: 15_122_000 picoseconds. + Weight::from_parts(27_397_644, 3834) + // Standard Error: 6_050 + .saturating_add(Weight::from_parts(1_454_904, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) .saturating_add(Weight::from_parts(0, 2740).saturating_mul(n.into())) } + /// Storage: `Skipped::Metadata` (r:0 w:0) + /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// The range of component `n` is `[0, 2048]`. + fn reset_pallet_migration(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1605 + n * (38 ±0)` + // Estimated: `686 + n * (39 ±0)` + // Minimum execution time: 1_128_000 picoseconds. + Weight::from_parts(1_180_000, 686) + // Standard Error: 2_597 + .saturating_add(Weight::from_parts(916_593, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 39).saturating_mul(n.into())) + } } // For backwards compatibility and tests. @@ -221,10 +239,10 @@ impl WeightInfo for () { /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) fn onboard_new_mbms() -> Weight { // Proof Size summary in bytes: - // Measured: `309` + // Measured: `0` // Estimated: `67035` - // Minimum execution time: 9_520_000 picoseconds. - Weight::from_parts(9_934_000, 67035) + // Minimum execution time: 4_422_000 picoseconds. + Weight::from_parts(4_560_000, 67035) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -232,10 +250,10 @@ impl WeightInfo for () { /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) fn progress_mbms_none() -> Weight { // Proof Size summary in bytes: - // Measured: `142` + // Measured: `0` // Estimated: `67035` - // Minimum execution time: 2_993_000 picoseconds. - Weight::from_parts(3_088_000, 67035) + // Minimum execution time: 678_000 picoseconds. + Weight::from_parts(751_000, 67035) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -244,10 +262,10 @@ impl WeightInfo for () { /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) fn exec_migration_completed() -> Weight { // Proof Size summary in bytes: - // Measured: `167` - // Estimated: `3632` - // Minimum execution time: 7_042_000 picoseconds. - Weight::from_parts(7_272_000, 3632) + // Measured: `0` + // Estimated: `3465` + // Minimum execution time: 3_791_000 picoseconds. + Weight::from_parts(3_930_000, 3465) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -257,10 +275,10 @@ impl WeightInfo for () { /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) fn exec_migration_skipped_historic() -> Weight { // Proof Size summary in bytes: - // Measured: `363` - // Estimated: `3828` - // Minimum execution time: 16_522_000 picoseconds. - Weight::from_parts(17_082_000, 3828) + // Measured: `34` + // Estimated: `3731` + // Minimum execution time: 7_375_000 picoseconds. + Weight::from_parts(7_630_000, 3731) .saturating_add(RocksDbWeight::get().reads(2_u64)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -269,10 +287,10 @@ impl WeightInfo for () { /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) fn exec_migration_advance() -> Weight { // Proof Size summary in bytes: - // Measured: `309` - // Estimated: `3774` - // Minimum execution time: 12_445_000 picoseconds. - Weight::from_parts(12_797_000, 3774) + // Measured: `0` + // Estimated: `3731` + // Minimum execution time: 6_771_000 picoseconds. + Weight::from_parts(6_894_000, 3731) .saturating_add(RocksDbWeight::get().reads(2_u64)) } /// Storage: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) @@ -281,10 +299,10 @@ impl WeightInfo for () { /// Proof: `MultiBlockMigrations::Historic` (`max_values`: None, `max_size`: Some(266), added: 2741, mode: `MaxEncodedLen`) fn exec_migration_complete() -> Weight { // Proof Size summary in bytes: - // Measured: `309` - // Estimated: `3774` - // Minimum execution time: 14_057_000 picoseconds. - Weight::from_parts(14_254_000, 3774) + // Measured: `0` + // Estimated: `3731` + // Minimum execution time: 8_223_000 picoseconds. + Weight::from_parts(8_406_000, 3731) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -296,10 +314,10 @@ impl WeightInfo for () { /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) fn exec_migration_fail() -> Weight { // Proof Size summary in bytes: - // Measured: `309` - // Estimated: `3774` - // Minimum execution time: 14_578_000 picoseconds. - Weight::from_parts(14_825_000, 3774) + // Measured: `0` + // Estimated: `3731` + // Minimum execution time: 8_907_000 picoseconds. + Weight::from_parts(9_168_000, 3731) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -307,8 +325,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 169_000 picoseconds. - Weight::from_parts(197_000, 0) + // Minimum execution time: 143_000 picoseconds. + Weight::from_parts(174_000, 0) } /// Storage: `MultiBlockMigrations::Cursor` (r:0 w:1) /// Proof: `MultiBlockMigrations::Cursor` (`max_values`: Some(1), `max_size`: Some(65550), added: 66045, mode: `MaxEncodedLen`) @@ -316,8 +334,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_634_000 picoseconds. - Weight::from_parts(2_798_000, 0) + // Minimum execution time: 2_172_000 picoseconds. + Weight::from_parts(2_259_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `MultiBlockMigrations::Cursor` (r:0 w:1) @@ -326,8 +344,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_069_000 picoseconds. - Weight::from_parts(3_293_000, 0) + // Minimum execution time: 2_600_000 picoseconds. + Weight::from_parts(2_728_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `MultiBlockMigrations::Cursor` (r:1 w:0) @@ -336,10 +354,10 @@ impl WeightInfo for () { /// Proof: UNKNOWN KEY `0x583359fe0e84d953a9dd84e8addb08a5` (r:1 w:0) fn force_onboard_mbms() -> Weight { // Proof Size summary in bytes: - // Measured: `284` + // Measured: `0` // Estimated: `67035` - // Minimum execution time: 7_674_000 picoseconds. - Weight::from_parts(8_000_000, 67035) + // Minimum execution time: 2_949_000 picoseconds. + Weight::from_parts(3_106_000, 67035) .saturating_add(RocksDbWeight::get().reads(2_u64)) } /// Storage: `MultiBlockMigrations::Historic` (r:256 w:256) @@ -347,15 +365,30 @@ impl WeightInfo for () { /// The range of component `n` is `[0, 256]`. fn clear_historic(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1122 + n * (271 ±0)` + // Measured: `960 + n * (271 ±0)` // Estimated: `3834 + n * (2740 ±0)` - // Minimum execution time: 16_937_000 picoseconds. - Weight::from_parts(15_713_121, 3834) - // Standard Error: 2_580 - .saturating_add(Weight::from_parts(1_424_239, 0).saturating_mul(n.into())) + // Minimum execution time: 15_122_000 picoseconds. + Weight::from_parts(27_397_644, 3834) + // Standard Error: 6_050 + .saturating_add(Weight::from_parts(1_454_904, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) .saturating_add(Weight::from_parts(0, 2740).saturating_mul(n.into())) } + /// Storage: `Skipped::Metadata` (r:0 w:0) + /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// The range of component `n` is `[0, 2048]`. + fn reset_pallet_migration(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1605 + n * (38 ±0)` + // Estimated: `686 + n * (39 ±0)` + // Minimum execution time: 1_128_000 picoseconds. + Weight::from_parts(1_180_000, 686) + // Standard Error: 2_597 + .saturating_add(Weight::from_parts(916_593, 0).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) + .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) + .saturating_add(Weight::from_parts(0, 39).saturating_mul(n.into())) + } } diff --git a/substrate/frame/multisig/src/benchmarking.rs b/substrate/frame/multisig/src/benchmarking.rs index ccaa1ceab66e54cd68774bb7ea244563c3f6fe59..3f75d92fe0ed378d2e76e87dbfba4c6a21048727 100644 --- a/substrate/frame/multisig/src/benchmarking.rs +++ b/substrate/frame/multisig/src/benchmarking.rs @@ -194,14 +194,14 @@ mod benchmarks { Ok(()) } - /// `z`: Transaction Length, not a component /// `s`: Signatories, need at least 2 people #[benchmark] fn approve_as_multi_create( s: Linear<2, { T::MaxSignatories::get() }>, - z: Linear<0, 10_000>, ) -> Result<(), BenchmarkError> { - let (mut signatories, call) = setup_multi::<T>(s, z)?; + // The call is neither in storage or an argument, so just use any: + let call_len = 10_000; + let (mut signatories, call) = setup_multi::<T>(s, call_len)?; let multi_account_id = Multisig::<T>::multi_account_id(&signatories, s.try_into().unwrap()); let caller = signatories.pop().ok_or("signatories should have len 2 or more")?; let call_hash = call.using_encoded(blake2_256); @@ -225,14 +225,14 @@ mod benchmarks { Ok(()) } - /// `z`: Transaction Length, not a component /// `s`: Signatories, need at least 2 people #[benchmark] fn approve_as_multi_approve( s: Linear<2, { T::MaxSignatories::get() }>, - z: Linear<0, 10_000>, ) -> Result<(), BenchmarkError> { - let (mut signatories, call) = setup_multi::<T>(s, z)?; + // The call is neither in storage or an argument, so just use any: + let call_len = 10_000; + let (mut signatories, call) = setup_multi::<T>(s, call_len)?; let mut signatories2 = signatories.clone(); let multi_account_id = Multisig::<T>::multi_account_id(&signatories, s.try_into().unwrap()); let caller = signatories.pop().ok_or("signatories should have len 2 or more")?; @@ -270,14 +270,12 @@ mod benchmarks { Ok(()) } - /// `z`: Transaction Length, not a component /// `s`: Signatories, need at least 2 people #[benchmark] - fn cancel_as_multi( - s: Linear<2, { T::MaxSignatories::get() }>, - z: Linear<0, 10_000>, - ) -> Result<(), BenchmarkError> { - let (mut signatories, call) = setup_multi::<T>(s, z)?; + fn cancel_as_multi(s: Linear<2, { T::MaxSignatories::get() }>) -> Result<(), BenchmarkError> { + // The call is neither in storage or an argument, so just use any: + let call_len = 10_000; + let (mut signatories, call) = setup_multi::<T>(s, call_len)?; let multi_account_id = Multisig::<T>::multi_account_id(&signatories, s.try_into().unwrap()); let caller = signatories.pop().ok_or("signatories should have len 2 or more")?; let call_hash = call.using_encoded(blake2_256); diff --git a/substrate/frame/multisig/src/weights.rs b/substrate/frame/multisig/src/weights.rs index 5c14922e0ef00d2d0e05a1b13af7bb469d63f728..0f8167a07a1c8229016cd2ba5f087d6f8a7d5684 100644 --- a/substrate/frame/multisig/src/weights.rs +++ b/substrate/frame/multisig/src/weights.rs @@ -18,36 +18,39 @@ //! Autogenerated weights for `pallet_multisig` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-04-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2025-01-28, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-anb7yjbi-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `fff8f38555b9`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` // Executed Command: -// ./target/production/substrate-node +// frame-omni-bencher +// v1 // benchmark // pallet -// --chain=dev +// --extrinsic=* +// --runtime=target/production/wbuild/kitchensink-runtime/kitchensink_runtime.wasm +// --pallet=pallet_multisig +// --header=/__w/polkadot-sdk/polkadot-sdk/substrate/HEADER-APACHE2 +// --output=/__w/polkadot-sdk/polkadot-sdk/substrate/frame/multisig/src/weights.rs +// --wasm-execution=compiled // --steps=50 // --repeat=20 -// --pallet=pallet_multisig +// --heap-pages=4096 +// --template=substrate/.maintain/frame-umbrella-weight-template.hbs // --no-storage-info -// --no-median-slopes // --no-min-squares -// --extrinsic=* -// --wasm-execution=compiled -// --heap-pages=4096 -// --output=./substrate/frame/multisig/src/weights.rs -// --header=./substrate/HEADER-APACHE2 -// --template=./substrate/.maintain/frame-weight-template.hbs +// --no-median-slopes +// --genesis-builder-policy=none +// --exclude-pallets=pallet_xcm,pallet_xcm_benchmarks::fungible,pallet_xcm_benchmarks::generic,pallet_nomination_pools,pallet_remark,pallet_transaction_storage #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] #![allow(unused_imports)] #![allow(missing_docs)] -// TODO update this in frame-weight-template.hbs use frame::weights_prelude::*; + /// Weight functions needed for `pallet_multisig`. pub trait WeightInfo { fn as_multi_threshold_1(z: u32, ) -> Weight; @@ -69,12 +72,12 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { /// The range of component `z` is `[0, 10000]`. fn as_multi_threshold_1(z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `145` + // Measured: `0` // Estimated: `3997` - // Minimum execution time: 20_302_000 picoseconds. - Weight::from_parts(21_362_808, 3997) - // Standard Error: 4 - .saturating_add(Weight::from_parts(432, 0).saturating_mul(z.into())) + // Minimum execution time: 18_665_000 picoseconds. + Weight::from_parts(19_157_181, 3997) + // Standard Error: 6 + .saturating_add(Weight::from_parts(590, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) } /// Storage: `Multisig::Multisigs` (r:1 w:1) @@ -83,14 +86,14 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { /// The range of component `z` is `[0, 10000]`. fn as_multi_create(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `301 + s * (2 ±0)` + // Measured: `229 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 41_140_000 picoseconds. - Weight::from_parts(31_518_927, 6811) - // Standard Error: 754 - .saturating_add(Weight::from_parts(115_804, 0).saturating_mul(s.into())) - // Standard Error: 7 - .saturating_add(Weight::from_parts(1_442, 0).saturating_mul(z.into())) + // Minimum execution time: 42_388_000 picoseconds. + Weight::from_parts(29_499_967, 6811) + // Standard Error: 1_563 + .saturating_add(Weight::from_parts(145_538, 0).saturating_mul(s.into())) + // Standard Error: 15 + .saturating_add(Weight::from_parts(2_016, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -100,14 +103,14 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { /// The range of component `z` is `[0, 10000]`. fn as_multi_approve(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `320` + // Measured: `185` // Estimated: `6811` - // Minimum execution time: 27_375_000 picoseconds. - Weight::from_parts(17_806_361, 6811) - // Standard Error: 501 - .saturating_add(Weight::from_parts(107_042, 0).saturating_mul(s.into())) - // Standard Error: 4 - .saturating_add(Weight::from_parts(1_491, 0).saturating_mul(z.into())) + // Minimum execution time: 27_231_000 picoseconds. + Weight::from_parts(16_755_689, 6811) + // Standard Error: 866 + .saturating_add(Weight::from_parts(119_094, 0).saturating_mul(s.into())) + // Standard Error: 8 + .saturating_add(Weight::from_parts(1_927, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -123,14 +126,14 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { /// The range of component `z` is `[0, 10000]`. fn as_multi_complete(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `571 + s * (33 ±0)` + // Measured: `288 + s * (33 ±0)` // Estimated: `6811` - // Minimum execution time: 54_427_000 picoseconds. - Weight::from_parts(43_677_970, 6811) - // Standard Error: 1_342 - .saturating_add(Weight::from_parts(154_697, 0).saturating_mul(s.into())) - // Standard Error: 13 - .saturating_add(Weight::from_parts(1_534, 0).saturating_mul(z.into())) + // Minimum execution time: 50_448_000 picoseconds. + Weight::from_parts(34_504_261, 6811) + // Standard Error: 2_070 + .saturating_add(Weight::from_parts(189_586, 0).saturating_mul(s.into())) + // Standard Error: 20 + .saturating_add(Weight::from_parts(2_116, 0).saturating_mul(z.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -139,12 +142,12 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { /// The range of component `s` is `[2, 100]`. fn approve_as_multi_create(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `301 + s * (2 ±0)` + // Measured: `233 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 29_102_000 picoseconds. - Weight::from_parts(30_317_105, 6811) - // Standard Error: 903 - .saturating_add(Weight::from_parts(109_792, 0).saturating_mul(s.into())) + // Minimum execution time: 26_020_000 picoseconds. + Weight::from_parts(28_229_601, 6811) + // Standard Error: 1_282 + .saturating_add(Weight::from_parts(133_221, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -153,12 +156,12 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { /// The range of component `s` is `[2, 100]`. fn approve_as_multi_approve(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `320` + // Measured: `185` // Estimated: `6811` - // Minimum execution time: 16_300_000 picoseconds. - Weight::from_parts(17_358_877, 6811) - // Standard Error: 522 - .saturating_add(Weight::from_parts(99_194, 0).saturating_mul(s.into())) + // Minimum execution time: 13_660_000 picoseconds. + Weight::from_parts(14_317_629, 6811) + // Standard Error: 1_188 + .saturating_add(Weight::from_parts(125_599, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -167,12 +170,12 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { /// The range of component `s` is `[2, 100]`. fn cancel_as_multi(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `492 + s * (1 ±0)` + // Measured: `357 + s * (1 ±0)` // Estimated: `6811` - // Minimum execution time: 30_147_000 picoseconds. - Weight::from_parts(32_003_421, 6811) - // Standard Error: 1_077 - .saturating_add(Weight::from_parts(108_567, 0).saturating_mul(s.into())) + // Minimum execution time: 27_827_000 picoseconds. + Weight::from_parts(28_980_511, 6811) + // Standard Error: 822 + .saturating_add(Weight::from_parts(130_315, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -187,12 +190,12 @@ impl WeightInfo for () { /// The range of component `z` is `[0, 10000]`. fn as_multi_threshold_1(z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `145` + // Measured: `0` // Estimated: `3997` - // Minimum execution time: 20_302_000 picoseconds. - Weight::from_parts(21_362_808, 3997) - // Standard Error: 4 - .saturating_add(Weight::from_parts(432, 0).saturating_mul(z.into())) + // Minimum execution time: 18_665_000 picoseconds. + Weight::from_parts(19_157_181, 3997) + // Standard Error: 6 + .saturating_add(Weight::from_parts(590, 0).saturating_mul(z.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) } /// Storage: `Multisig::Multisigs` (r:1 w:1) @@ -201,14 +204,14 @@ impl WeightInfo for () { /// The range of component `z` is `[0, 10000]`. fn as_multi_create(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `301 + s * (2 ±0)` + // Measured: `229 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 41_140_000 picoseconds. - Weight::from_parts(31_518_927, 6811) - // Standard Error: 754 - .saturating_add(Weight::from_parts(115_804, 0).saturating_mul(s.into())) - // Standard Error: 7 - .saturating_add(Weight::from_parts(1_442, 0).saturating_mul(z.into())) + // Minimum execution time: 42_388_000 picoseconds. + Weight::from_parts(29_499_967, 6811) + // Standard Error: 1_563 + .saturating_add(Weight::from_parts(145_538, 0).saturating_mul(s.into())) + // Standard Error: 15 + .saturating_add(Weight::from_parts(2_016, 0).saturating_mul(z.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -218,14 +221,14 @@ impl WeightInfo for () { /// The range of component `z` is `[0, 10000]`. fn as_multi_approve(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `320` + // Measured: `185` // Estimated: `6811` - // Minimum execution time: 27_375_000 picoseconds. - Weight::from_parts(17_806_361, 6811) - // Standard Error: 501 - .saturating_add(Weight::from_parts(107_042, 0).saturating_mul(s.into())) - // Standard Error: 4 - .saturating_add(Weight::from_parts(1_491, 0).saturating_mul(z.into())) + // Minimum execution time: 27_231_000 picoseconds. + Weight::from_parts(16_755_689, 6811) + // Standard Error: 866 + .saturating_add(Weight::from_parts(119_094, 0).saturating_mul(s.into())) + // Standard Error: 8 + .saturating_add(Weight::from_parts(1_927, 0).saturating_mul(z.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -241,14 +244,14 @@ impl WeightInfo for () { /// The range of component `z` is `[0, 10000]`. fn as_multi_complete(s: u32, z: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `571 + s * (33 ±0)` + // Measured: `288 + s * (33 ±0)` // Estimated: `6811` - // Minimum execution time: 54_427_000 picoseconds. - Weight::from_parts(43_677_970, 6811) - // Standard Error: 1_342 - .saturating_add(Weight::from_parts(154_697, 0).saturating_mul(s.into())) - // Standard Error: 13 - .saturating_add(Weight::from_parts(1_534, 0).saturating_mul(z.into())) + // Minimum execution time: 50_448_000 picoseconds. + Weight::from_parts(34_504_261, 6811) + // Standard Error: 2_070 + .saturating_add(Weight::from_parts(189_586, 0).saturating_mul(s.into())) + // Standard Error: 20 + .saturating_add(Weight::from_parts(2_116, 0).saturating_mul(z.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -257,12 +260,12 @@ impl WeightInfo for () { /// The range of component `s` is `[2, 100]`. fn approve_as_multi_create(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `301 + s * (2 ±0)` + // Measured: `233 + s * (2 ±0)` // Estimated: `6811` - // Minimum execution time: 29_102_000 picoseconds. - Weight::from_parts(30_317_105, 6811) - // Standard Error: 903 - .saturating_add(Weight::from_parts(109_792, 0).saturating_mul(s.into())) + // Minimum execution time: 26_020_000 picoseconds. + Weight::from_parts(28_229_601, 6811) + // Standard Error: 1_282 + .saturating_add(Weight::from_parts(133_221, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -271,12 +274,12 @@ impl WeightInfo for () { /// The range of component `s` is `[2, 100]`. fn approve_as_multi_approve(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `320` + // Measured: `185` // Estimated: `6811` - // Minimum execution time: 16_300_000 picoseconds. - Weight::from_parts(17_358_877, 6811) - // Standard Error: 522 - .saturating_add(Weight::from_parts(99_194, 0).saturating_mul(s.into())) + // Minimum execution time: 13_660_000 picoseconds. + Weight::from_parts(14_317_629, 6811) + // Standard Error: 1_188 + .saturating_add(Weight::from_parts(125_599, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -285,13 +288,13 @@ impl WeightInfo for () { /// The range of component `s` is `[2, 100]`. fn cancel_as_multi(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `492 + s * (1 ±0)` + // Measured: `357 + s * (1 ±0)` // Estimated: `6811` - // Minimum execution time: 30_147_000 picoseconds. - Weight::from_parts(32_003_421, 6811) - // Standard Error: 1_077 - .saturating_add(Weight::from_parts(108_567, 0).saturating_mul(s.into())) + // Minimum execution time: 27_827_000 picoseconds. + Weight::from_parts(28_980_511, 6811) + // Standard Error: 822 + .saturating_add(Weight::from_parts(130_315, 0).saturating_mul(s.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } -} \ No newline at end of file +} diff --git a/substrate/frame/nfts/runtime-api/Cargo.toml b/substrate/frame/nfts/runtime-api/Cargo.toml index 4d004875468db1222289f2aab268c8ce58813e52..36f85fbf61128a8fcea6cea9374c3cf1d7e56883 100644 --- a/substrate/frame/nfts/runtime-api/Cargo.toml +++ b/substrate/frame/nfts/runtime-api/Cargo.toml @@ -17,9 +17,8 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] codec = { features = ["derive"], workspace = true } -pallet-nfts = { workspace = true } sp-api = { workspace = true } [features] default = ["std"] -std = ["codec/std", "pallet-nfts/std", "sp-api/std"] +std = ["codec/std", "sp-api/std"] diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index dc82bf3a37c6e06430b6be9a318e7dd12fce342e..04736e6c1aad1cb04fcfe51c470929bf93f2e307 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -18,7 +18,7 @@ //! # Nomination Pools for Staking Delegation //! //! A pallet that allows members to delegate their stake to nominating pools. A nomination pool acts -//! as nominator and nominates validators on the members behalf. +//! as nominator and nominates validators on the members' behalf. //! //! # Index //! @@ -178,7 +178,7 @@ //! //! ### Pool Members //! -//! * In general, whenever a pool member changes their total point, the chain will automatically +//! * In general, whenever a pool member changes their total points, the chain will automatically //! claim all their pending rewards for them. This is not optional, and MUST happen for the reward //! calculation to remain correct (see the documentation of `bond` as an example). So, make sure //! you are warning your users about it. They might be surprised if they see that they bonded an @@ -1865,6 +1865,24 @@ pub mod pallet { MinBalanceDeficitAdjusted { pool_id: PoolId, amount: BalanceOf<T> }, /// Claimed excess frozen ED of af the reward pool. MinBalanceExcessAdjusted { pool_id: PoolId, amount: BalanceOf<T> }, + /// A pool member's claim permission has been updated. + MemberClaimPermissionUpdated { member: T::AccountId, permission: ClaimPermission }, + /// A pool's metadata was updated. + MetadataUpdated { pool_id: PoolId, caller: T::AccountId }, + /// A pool's nominating account (or the pool's root account) has nominated a validator set + /// on behalf of the pool. + PoolNominationMade { pool_id: PoolId, caller: T::AccountId }, + /// The pool is chilled i.e. no longer nominating. + PoolNominatorChilled { pool_id: PoolId, caller: T::AccountId }, + /// Global parameters regulating nomination pools have been updated. + GlobalParamsUpdated { + min_join_bond: BalanceOf<T>, + min_create_bond: BalanceOf<T>, + max_pools: Option<u32>, + max_members: Option<u32>, + max_members_per_pool: Option<u32>, + global_max_commission: Option<Perbill>, + }, } #[pallet::error] @@ -2509,13 +2527,13 @@ pub mod pallet { /// The dispatch origin of this call must be signed by the pool nominator or the pool /// root role. /// - /// This directly forward the call to the staking pallet, on behalf of the pool bonded - /// account. + /// This directly forwards the call to an implementation of `StakingInterface` (e.g., + /// `pallet-staking`) through [`Config::StakeAdapter`], on behalf of the bonded pool. /// /// # Note /// - /// In addition to a `root` or `nominator` role of `origin`, pool's depositor needs to have - /// at least `depositor_min_bond` in the pool to start nominating. + /// In addition to a `root` or `nominator` role of `origin`, the pool's depositor needs to + /// have at least `depositor_min_bond` in the pool to start nominating. #[pallet::call_index(8)] #[pallet::weight(T::WeightInfo::nominate(validators.len() as u32))] pub fn nominate( @@ -2538,7 +2556,9 @@ pub mod pallet { Error::<T>::MinimumBondNotMet ); - T::StakeAdapter::nominate(Pool::from(bonded_pool.bonded_account()), validators) + T::StakeAdapter::nominate(Pool::from(bonded_pool.bonded_account()), validators).map( + |_| Self::deposit_event(Event::<T>::PoolNominationMade { pool_id, caller: who }), + ) } /// Set a new state for the pool. @@ -2603,6 +2623,8 @@ pub mod pallet { Metadata::<T>::mutate(pool_id, |pool_meta| *pool_meta = metadata); + Self::deposit_event(Event::<T>::MetadataUpdated { pool_id, caller: who }); + Ok(()) } @@ -2646,6 +2668,16 @@ pub mod pallet { config_op_exp!(MaxPoolMembers::<T>, max_members); config_op_exp!(MaxPoolMembersPerPool::<T>, max_members_per_pool); config_op_exp!(GlobalMaxCommission::<T>, global_max_commission); + + Self::deposit_event(Event::<T>::GlobalParamsUpdated { + min_join_bond: MinJoinBond::<T>::get(), + min_create_bond: MinCreateBond::<T>::get(), + max_pools: MaxPools::<T>::get(), + max_members: MaxPoolMembers::<T>::get(), + max_members_per_pool: MaxPoolMembersPerPool::<T>::get(), + global_max_commission: GlobalMaxCommission::<T>::get(), + }); + Ok(()) } @@ -2710,17 +2742,18 @@ pub mod pallet { /// The dispatch origin of this call can be signed by the pool nominator or the pool /// root role, same as [`Pallet::nominate`]. /// + /// This directly forwards the call to an implementation of `StakingInterface` (e.g., + /// `pallet-staking`) through [`Config::StakeAdapter`], on behalf of the bonded pool. + /// /// Under certain conditions, this call can be dispatched permissionlessly (i.e. by any /// account). /// /// # Conditions for a permissionless dispatch: - /// * When pool depositor has less than `MinNominatorBond` staked, otherwise pool members + /// * When pool depositor has less than `MinNominatorBond` staked, otherwise pool members /// are unable to unbond. /// /// # Conditions for permissioned dispatch: - /// * The caller has a nominator or root role of the pool. - /// This directly forward the call to the staking pallet, on behalf of the pool bonded - /// account. + /// * The caller is the pool's nominator or root. #[pallet::call_index(13)] #[pallet::weight(T::WeightInfo::chill())] pub fn chill(origin: OriginFor<T>, pool_id: PoolId) -> DispatchResult { @@ -2739,7 +2772,9 @@ pub mod pallet { ensure!(bonded_pool.can_nominate(&who), Error::<T>::NotNominator); } - T::StakeAdapter::chill(Pool::from(bonded_pool.bonded_account())) + T::StakeAdapter::chill(Pool::from(bonded_pool.bonded_account())).map(|_| { + Self::deposit_event(Event::<T>::PoolNominatorChilled { pool_id, caller: who }) + }) } /// `origin` bonds funds from `extra` for some pool member `member` into their respective @@ -2794,10 +2829,15 @@ pub mod pallet { Error::<T>::NotMigrated ); - ClaimPermissions::<T>::mutate(who, |source| { + ClaimPermissions::<T>::mutate(who.clone(), |source| { *source = permission; }); + Self::deposit_event(Event::<T>::MemberClaimPermissionUpdated { + member: who, + permission, + }); + Ok(()) } @@ -2913,9 +2953,20 @@ pub mod pallet { /// Claim pending commission. /// - /// The dispatch origin of this call must be signed by the `root` role of the pool. Pending - /// commission is paid out and added to total claimed commission`. Total pending commission - /// is reset to zero. the current. + /// The `root` role of the pool is _always_ allowed to claim the pool's commission. + /// + /// If the pool has set `CommissionClaimPermission::Permissionless`, then any account can + /// trigger the process of claiming the pool's commission. + /// + /// If the pool has set its `CommissionClaimPermission` to `Account(acc)`, then only + /// accounts + /// * `acc`, and + /// * the pool's root account + /// + /// may call this extrinsic on behalf of the pool. + /// + /// Pending commissions are paid out and added to the total claimed commission. + /// The total pending commission is reset to zero. #[pallet::call_index(20)] #[pallet::weight(T::WeightInfo::claim_commission())] pub fn claim_commission(origin: OriginFor<T>, pool_id: PoolId) -> DispatchResult { diff --git a/substrate/frame/nomination-pools/src/tests.rs b/substrate/frame/nomination-pools/src/tests.rs index c46638d2f8f7bb474088b967e491c54d12bc3105..e2922e22fa98949c219d377b53cd2f0aba3c4964 100644 --- a/substrate/frame/nomination-pools/src/tests.rs +++ b/substrate/frame/nomination-pools/src/tests.rs @@ -17,7 +17,7 @@ use super::*; use crate::{mock::*, Event}; -use frame_support::{assert_err, assert_noop, assert_ok, assert_storage_noop}; +use frame_support::{assert_err, assert_noop, assert_ok}; use pallet_balances::Event as BEvent; use sp_runtime::{ bounded_btree_map, @@ -661,6 +661,7 @@ mod join { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Bonded { member: 11, pool_id: 1, bonded: 2, joined: true }, ] ); @@ -817,6 +818,7 @@ mod join { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Bonded { member: 101, pool_id: 1, bonded: 100, joined: true }, Event::Bonded { member: 102, pool_id: 1, bonded: 100, joined: true } ] @@ -1089,6 +1091,7 @@ mod claim_payout { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Bonded { member: 11, pool_id: 1, bonded: 11, joined: true }, Event::Unbonded { member: 11, pool_id: 1, points: 11, balance: 11, era: 3 } ] @@ -1121,6 +1124,7 @@ mod claim_payout { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::PoolCommissionUpdated { pool_id: 1, current: Some((Perbill::from_percent(75), 2)) @@ -1184,6 +1188,7 @@ mod claim_payout { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::PaidOut { member: 10, pool_id: 1, payout: 5 } ] ); @@ -1259,6 +1264,7 @@ mod claim_payout { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Bonded { member: 40, pool_id: 1, bonded: 40, joined: true }, Event::Bonded { member: 50, pool_id: 1, bonded: 50, joined: true } ] @@ -1514,6 +1520,7 @@ mod claim_payout { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Bonded { member: 20, pool_id: 1, bonded: 10, joined: true }, Event::PaidOut { member: 10, pool_id: 1, payout: 20 }, Event::PaidOut { member: 20, pool_id: 1, payout: 10 }, @@ -1557,6 +1564,7 @@ mod claim_payout { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Bonded { member: 20, pool_id: 1, bonded: 10, joined: true }, Event::PaidOut { member: 10, pool_id: 1, payout: 3 + 3 }, Event::PaidOut { member: 20, pool_id: 1, payout: 3 }, @@ -1620,6 +1628,7 @@ mod claim_payout { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Bonded { member: 20, pool_id: 1, bonded: 10, joined: true }, Event::Bonded { member: 30, pool_id: 1, bonded: 10, joined: true }, Event::PaidOut { member: 10, pool_id: 1, payout: 30 + 100 / 2 + 60 / 3 }, @@ -1721,6 +1730,7 @@ mod claim_payout { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Bonded { member: 20, pool_id: 1, bonded: 20, joined: true }, Event::Bonded { member: 30, pool_id: 1, bonded: 10, joined: true }, Event::PaidOut { member: 10, pool_id: 1, payout: 10 }, @@ -1770,6 +1780,7 @@ mod claim_payout { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Bonded { member: 20, pool_id: 1, bonded: 20, joined: true }, Event::PaidOut { member: 10, pool_id: 1, payout: 10 }, Event::PaidOut { member: 20, pool_id: 1, payout: 20 } @@ -1818,6 +1829,7 @@ mod claim_payout { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Bonded { member: 20, pool_id: 1, bonded: 20, joined: true }, Event::Bonded { member: 30, pool_id: 1, bonded: 10, joined: true }, Event::PaidOut { member: 10, pool_id: 1, payout: 10 }, @@ -1884,6 +1896,7 @@ mod claim_payout { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Bonded { member: 20, pool_id: 1, bonded: 20, joined: true }, Event::PaidOut { member: 10, pool_id: 1, payout: 10 } ] @@ -1983,6 +1996,7 @@ mod claim_payout { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Created { depositor: 20, pool_id: 2 }, Event::Bonded { member: 20, pool_id: 2, bonded: 10, joined: true }, Event::Created { depositor: 30, pool_id: 3 }, @@ -2052,6 +2066,7 @@ mod claim_payout { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Bonded { member: 20, pool_id: 1, bonded: 10, joined: true }, Event::Bonded { member: 30, pool_id: 1, bonded: 10, joined: true }, Event::Bonded { member: 40, pool_id: 1, bonded: 10, joined: true } @@ -2132,6 +2147,7 @@ mod claim_payout { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Bonded { member: 20, pool_id: 1, bonded: 20, joined: true }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: false }, Event::PaidOut { member: 10, pool_id: 1, payout: 15 }, @@ -2277,6 +2293,7 @@ mod claim_payout { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Bonded { member: 20, pool_id: 1, bonded: 20, joined: true }, Event::Bonded { member: 30, pool_id: 1, bonded: 20, joined: true }, Event::Unbonded { member: 20, pool_id: 1, balance: 10, points: 10, era: 3 }, @@ -2315,6 +2332,7 @@ mod claim_payout { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Bonded { member: 20, pool_id: 1, bonded: 20, joined: true }, Event::PaidOut { member: 10, pool_id: 1, payout: 13 }, Event::PaidOut { member: 20, pool_id: 1, payout: 26 } @@ -2385,6 +2403,7 @@ mod claim_payout { bonded: 1000000000000000, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Bonded { member: 20, pool_id: 1, @@ -2584,6 +2603,7 @@ mod unbond { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Bonded { member: 20, pool_id: 1, bonded: 20, joined: true }, Event::PaidOut { member: 20, pool_id: 1, payout: 6 }, Event::Unbonded { member: 20, pool_id: 1, balance: 20, points: 20, era: 3 } @@ -2833,6 +2853,7 @@ mod unbond { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Bonded { member: 40, pool_id: 1, bonded: 40, joined: true }, Event::Bonded { member: 550, pool_id: 1, bonded: 550, joined: true }, Event::PoolSlashed { pool_id: 1, balance: 100 }, @@ -2975,6 +2996,7 @@ mod unbond { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Unbonded { member: 10, pool_id: 1, points: 10, balance: 10, era: 9 } ] ); @@ -3009,6 +3031,7 @@ mod unbond { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Bonded { member: 100, pool_id: 1, bonded: 100, joined: true }, Event::Bonded { member: 200, pool_id: 1, bonded: 200, joined: true }, Event::Unbonded { @@ -3102,6 +3125,7 @@ mod unbond { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Bonded { member: 100, pool_id: 1, bonded: 100, joined: true }, Event::Unbonded { member: 100, pool_id: 1, points: 100, balance: 100, era: 3 } ] @@ -3258,6 +3282,7 @@ mod unbond { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Unbonded { member: 10, pool_id: 1, points: 1, balance: 1, era: 3 } ] ); @@ -3390,6 +3415,7 @@ mod unbond { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Bonded { member: 20, pool_id: 1, bonded: 20, joined: true }, Event::Unbonded { member: 20, pool_id: 1, points: 2, balance: 2, era: 3 }, Event::Unbonded { member: 20, pool_id: 1, points: 3, balance: 3, era: 4 }, @@ -3426,6 +3452,7 @@ mod unbond { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Unbonded { member: 10, pool_id: 1, points: 3, balance: 3, era: 3 } ] ); @@ -3467,6 +3494,7 @@ mod unbond { // 2/3 of ed, which is 20's share. Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Bonded { member: 20, pool_id: 1, bonded: 20, joined: true }, Event::PaidOut { member: 20, pool_id: 1, payout: 10 }, Event::Unbonded { member: 20, pool_id: 1, balance: 2, points: 2, era: 3 } @@ -3641,6 +3669,7 @@ mod withdraw_unbonded { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Bonded { member: 40, pool_id: 1, bonded: 40, joined: true }, Event::Bonded { member: 550, pool_id: 1, bonded: 550, joined: true }, Event::Unbonded { @@ -3750,6 +3779,7 @@ mod withdraw_unbonded { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Bonded { member: 40, pool_id: 1, bonded: 40, joined: true }, Event::Bonded { member: 550, pool_id: 1, bonded: 550, joined: true }, Event::PoolSlashed { pool_id: 1, balance: 300 }, @@ -3827,6 +3857,7 @@ mod withdraw_unbonded { pool_events_since_last_call(), vec![ Event::Unbonded { member: 10, pool_id: 1, points: 5, balance: 5, era: 6 }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Withdrawn { member: 10, pool_id: 1, points: 5, balance: 5 }, Event::MemberRemoved { pool_id: 1, member: 10, released_balance: 0 }, Event::Destroyed { pool_id: 1 } @@ -3915,6 +3946,7 @@ mod withdraw_unbonded { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Bonded { member: 100, pool_id: 1, bonded: 100, joined: true }, Event::Bonded { member: 200, pool_id: 1, bonded: 200, joined: true }, Event::Unbonded { @@ -4008,6 +4040,7 @@ mod withdraw_unbonded { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Bonded { member: 100, pool_id: 1, bonded: 100, joined: true }, Event::Unbonded { member: 100, pool_id: 1, points: 100, balance: 100, era: 3 }, Event::Withdrawn { member: 100, pool_id: 1, points: 100, balance: 100 }, @@ -4048,6 +4081,7 @@ mod withdraw_unbonded { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: false }, Event::Unbonded { member: 10, pool_id: 1, points: 6, balance: 6, era: 3 }, Event::Unbonded { member: 10, pool_id: 1, points: 1, balance: 1, era: 4 } @@ -4135,6 +4169,7 @@ mod withdraw_unbonded { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Bonded { member: 11, pool_id: 1, bonded: 10, joined: true }, Event::Unbonded { member: 11, pool_id: 1, points: 6, balance: 6, era: 3 }, Event::Unbonded { member: 11, pool_id: 1, points: 1, balance: 1, era: 4 } @@ -4231,6 +4266,7 @@ mod withdraw_unbonded { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Bonded { member: 100, pool_id: 1, bonded: 100, joined: true }, Event::Unbonded { member: 100, pool_id: 1, points: 75, balance: 75, era: 3 }, Event::Unbonded { member: 100, pool_id: 1, points: 25, balance: 25, era: 4 }, @@ -4469,6 +4505,7 @@ mod withdraw_unbonded { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: false }, Event::Unbonded { member: 10, pool_id: 1, balance: 7, points: 7, era: 3 }, Event::Unbonded { member: 10, pool_id: 1, balance: 3, points: 3, era: 4 }, @@ -4515,6 +4552,7 @@ mod withdraw_unbonded { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Bonded { member: 20, pool_id: 1, bonded: 20, joined: true }, Event::Unbonded { member: 20, pool_id: 1, balance: 20, points: 20, era: 4 }, ] @@ -4555,6 +4593,7 @@ mod withdraw_unbonded { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Unbonded { member: 10, pool_id: 1, balance: 10, points: 10, era: 4 }, ] ); @@ -4597,6 +4636,7 @@ mod withdraw_unbonded { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Unbonded { member: 10, pool_id: 1, balance: 10, points: 10, era: 4 }, ] ); @@ -4699,6 +4739,7 @@ mod create { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Created { depositor: 11, pool_id: 2 }, Event::Bonded { member: 11, pool_id: 2, bonded: 10, joined: true } ] @@ -4829,6 +4870,7 @@ fn set_claim_permission_works() { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Bonded { member: 11, pool_id: 1, bonded: 2, joined: true }, ] ); @@ -4844,6 +4886,14 @@ fn set_claim_permission_works() { ClaimPermission::Permissioned )); + assert_eq!( + pool_events_since_last_call(), + vec![Event::MemberClaimPermissionUpdated { + member: 11, + permission: ClaimPermission::Permissioned + },] + ); + // then assert_eq!(ClaimPermissions::<Runtime>::get(11), ClaimPermission::Permissioned); }); @@ -4883,10 +4933,21 @@ mod nominate { assert_ok!(Pools::nominate(RuntimeOrigin::signed(900), 1, vec![21])); assert_eq!(Nominations::get().unwrap(), vec![21]); + // Check event + System::assert_last_event(tests::RuntimeEvent::Pools(Event::PoolNominationMade { + pool_id: 1, + caller: 900, + })); + // Nominator can nominate assert_ok!(Pools::nominate(RuntimeOrigin::signed(901), 1, vec![31])); assert_eq!(Nominations::get().unwrap(), vec![31]); + System::assert_last_event(tests::RuntimeEvent::Pools(Event::PoolNominationMade { + pool_id: 1, + caller: 901, + })); + // Can't nominate for a pool that doesn't exist assert_noop!( Pools::nominate(RuntimeOrigin::signed(902), 123, vec![21]), @@ -4923,6 +4984,7 @@ mod set_state { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::StateChanged { pool_id: 1, new_state: PoolState::Blocked } ] ); @@ -4999,10 +5061,20 @@ mod set_metadata { assert_ok!(Pools::set_metadata(RuntimeOrigin::signed(900), 1, vec![1, 1])); assert_eq!(Metadata::<Runtime>::get(1), vec![1, 1]); + System::assert_last_event(tests::RuntimeEvent::Pools(Event::MetadataUpdated { + pool_id: 1, + caller: 900, + })); + // bouncer can set metadata assert_ok!(Pools::set_metadata(RuntimeOrigin::signed(902), 1, vec![2, 2])); assert_eq!(Metadata::<Runtime>::get(1), vec![2, 2]); + System::assert_last_event(tests::RuntimeEvent::Pools(Event::MetadataUpdated { + pool_id: 1, + caller: 902, + })); + // Depositor can't set metadata assert_noop!( Pools::set_metadata(RuntimeOrigin::signed(10), 1, vec![3, 3]), @@ -5061,8 +5133,18 @@ mod set_configs { assert_eq!(MaxPoolMembersPerPool::<Runtime>::get(), Some(5)); assert_eq!(GlobalMaxCommission::<Runtime>::get(), Some(Perbill::from_percent(6))); + // Check events + System::assert_last_event(tests::RuntimeEvent::Pools(Event::GlobalParamsUpdated { + min_join_bond: 1, + min_create_bond: 2, + max_pools: Some(3), + max_members: Some(4), + max_members_per_pool: Some(5), + global_max_commission: Some(Perbill::from_percent(6)), + })); + // Noop does nothing - assert_storage_noop!(assert_ok!(Pools::set_configs( + assert_ok!(Pools::set_configs( RuntimeOrigin::signed(42), ConfigOp::Noop, ConfigOp::Noop, @@ -5070,7 +5152,23 @@ mod set_configs { ConfigOp::Noop, ConfigOp::Noop, ConfigOp::Noop, - ))); + )); + + assert_eq!(MinJoinBond::<Runtime>::get(), 1); + assert_eq!(MinCreateBond::<Runtime>::get(), 2); + assert_eq!(MaxPools::<Runtime>::get(), Some(3)); + assert_eq!(MaxPoolMembers::<Runtime>::get(), Some(4)); + assert_eq!(MaxPoolMembersPerPool::<Runtime>::get(), Some(5)); + assert_eq!(GlobalMaxCommission::<Runtime>::get(), Some(Perbill::from_percent(6))); + + System::assert_last_event(tests::RuntimeEvent::Pools(Event::GlobalParamsUpdated { + min_join_bond: 1, + min_create_bond: 2, + max_pools: Some(3), + max_members: Some(4), + max_members_per_pool: Some(5), + global_max_commission: Some(Perbill::from_percent(6)), + })); // Removing works assert_ok!(Pools::set_configs( @@ -5088,6 +5186,15 @@ mod set_configs { assert_eq!(MaxPoolMembers::<Runtime>::get(), None); assert_eq!(MaxPoolMembersPerPool::<Runtime>::get(), None); assert_eq!(GlobalMaxCommission::<Runtime>::get(), None); + + System::assert_last_event(tests::RuntimeEvent::Pools(Event::GlobalParamsUpdated { + min_join_bond: 0, + min_create_bond: 0, + max_pools: None, + max_members: None, + max_members_per_pool: None, + global_max_commission: None, + })); }); } } @@ -5120,6 +5227,7 @@ mod bond_extra { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: false } ] ); @@ -5168,6 +5276,7 @@ mod bond_extra { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::PaidOut { member: 10, pool_id: 1, payout: claimable_reward }, Event::Bonded { member: 10, @@ -5229,6 +5338,7 @@ mod bond_extra { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Bonded { member: 20, pool_id: 1, bonded: 20, joined: true }, Event::PaidOut { member: 10, pool_id: 1, payout: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 1, joined: false }, @@ -5372,6 +5482,7 @@ mod update_roles { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::RolesUpdated { root: Some(5), bouncer: Some(7), nominator: Some(6) } ] ); @@ -5485,7 +5596,8 @@ mod reward_counter_precision { pool_id: 1, bonded: 1173908528796953165005, joined: true, - } + }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, ] ); @@ -5518,7 +5630,8 @@ mod reward_counter_precision { pool_events_since_last_call(), vec![ Event::Created { depositor: 10, pool_id: 1 }, - Event::Bonded { member: 10, pool_id: 1, bonded: 10000000000000, joined: true } + Event::Bonded { member: 10, pool_id: 1, bonded: 10000000000000, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, ] ); @@ -5557,7 +5670,8 @@ mod reward_counter_precision { pool_id: 1, bonded: 12_968_712_300_500_000_000, joined: true, - } + }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, ] ); @@ -5623,7 +5737,8 @@ mod reward_counter_precision { pool_id: 1, bonded: 12_968_712_300_500_000_000, joined: true, - } + }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, ] ); @@ -5658,7 +5773,8 @@ mod reward_counter_precision { pool_id: 1, bonded: 2500000000000000000, joined: true, - } + }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, ] ); @@ -5726,7 +5842,8 @@ mod reward_counter_precision { pool_id: 1, bonded: 2500000000000000000, joined: true, - } + }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, ] ); @@ -5794,6 +5911,7 @@ mod commission { vec![ Event::Created { depositor: 10, pool_id }, Event::Bonded { member: 10, pool_id, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::PoolCommissionUpdated { pool_id, current: Some((Perbill::from_percent(50), root)) @@ -6087,6 +6205,7 @@ mod commission { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::PoolCommissionUpdated { pool_id: 1, current: Some((Perbill::from_percent(10), 900)) @@ -6109,6 +6228,7 @@ mod commission { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, ] ); @@ -6396,6 +6516,7 @@ mod commission { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::PoolMaxCommissionUpdated { pool_id: 1, max_commission: Perbill::from_percent(80) @@ -6463,6 +6584,7 @@ mod commission { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::PoolCommissionChangeRateUpdated { pool_id: 1, change_rate: CommissionChangeRate { @@ -6623,6 +6745,7 @@ mod commission { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::PoolCommissionUpdated { pool_id: 1, current: Some((Perbill::from_percent(10), 900)) @@ -6759,6 +6882,7 @@ mod commission { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::PoolCommissionChangeRateUpdated { pool_id: 1, change_rate: CommissionChangeRate { @@ -6792,6 +6916,7 @@ mod commission { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::PoolCommissionUpdated { pool_id: 1, current: Some((Perbill::from_percent(33), 2)) @@ -6882,6 +7007,7 @@ mod commission { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::PoolCommissionUpdated { pool_id: 1, current: Some((Perbill::from_percent(10), 2)) @@ -6948,6 +7074,7 @@ mod commission { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::PoolCommissionUpdated { pool_id: 1, current: Some((Perbill::from_percent(10), 2)) @@ -7007,6 +7134,7 @@ mod commission { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::PoolCommissionUpdated { pool_id: 1, current: Some((Perbill::from_percent(100), 2)) @@ -7052,6 +7180,7 @@ mod commission { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, ] ); @@ -7112,6 +7241,7 @@ mod commission { vec![ Event::Created { depositor: 10, pool_id }, Event::Bonded { member: 10, pool_id, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::PoolCommissionUpdated { pool_id, current: Some((Perbill::from_percent(50), 900)) @@ -7294,6 +7424,7 @@ mod commission { vec![ Event::Created { depositor: 10, pool_id }, Event::Bonded { member: 10, pool_id, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, ] ); @@ -7349,6 +7480,7 @@ mod slash { vec![ Event::Created { depositor: 10, pool_id: 1 }, Event::Bonded { member: 10, pool_id: 1, bonded: 10, joined: true }, + Event::MetadataUpdated { pool_id: 1, caller: 900 }, Event::Bonded { member: 11, pool_id: 1, bonded: 2, joined: true }, ] ); @@ -7404,11 +7536,28 @@ mod chill { // root can chill and re-nominate assert_ok!(Pools::chill(RuntimeOrigin::signed(900), 1)); + // Check that chill now emits an event + System::assert_last_event(tests::RuntimeEvent::Pools(Event::PoolNominatorChilled { + pool_id: 1, + caller: 900, + })); assert_ok!(Pools::nominate(RuntimeOrigin::signed(900), 1, vec![31])); + System::assert_last_event(tests::RuntimeEvent::Pools(Event::PoolNominationMade { + pool_id: 1, + caller: 900, + })); // nominator can chill and re-nominate assert_ok!(Pools::chill(RuntimeOrigin::signed(901), 1)); + System::assert_last_event(tests::RuntimeEvent::Pools(Event::PoolNominatorChilled { + pool_id: 1, + caller: 901, + })); assert_ok!(Pools::nominate(RuntimeOrigin::signed(901), 1, vec![31])); + System::assert_last_event(tests::RuntimeEvent::Pools(Event::PoolNominationMade { + pool_id: 1, + caller: 901, + })); // if `depositor` stake is less than the `MinimumNominatorBond`, then this call // becomes permissionless; diff --git a/substrate/frame/nomination-pools/test-delegate-stake/src/lib.rs b/substrate/frame/nomination-pools/test-delegate-stake/src/lib.rs index 54783332aa3ef245bced9e737ed5c8a89265e7d8..b43a41cd0f980dbe19916e104a8d3b51551e2154 100644 --- a/substrate/frame/nomination-pools/test-delegate-stake/src/lib.rs +++ b/substrate/frame/nomination-pools/test-delegate-stake/src/lib.rs @@ -62,6 +62,7 @@ fn pool_lifecycle_e2e() { vec![ PoolsEvent::Created { depositor: 10, pool_id: 1 }, PoolsEvent::Bonded { member: 10, pool_id: 1, bonded: 50, joined: true }, + PoolsEvent::PoolNominationMade { pool_id: 1, caller: 10 }, ] ); @@ -180,7 +181,10 @@ fn pool_lifecycle_e2e() { ); assert_eq!( pool_events_since_last_call(), - vec![PoolsEvent::Unbonded { member: 10, pool_id: 1, points: 50, balance: 50, era: 6 }] + vec![ + PoolsEvent::PoolNominatorChilled { pool_id: 1, caller: 10 }, + PoolsEvent::Unbonded { member: 10, pool_id: 1, points: 50, balance: 50, era: 6 } + ] ); // waiting another bonding duration: @@ -225,6 +229,7 @@ fn pool_chill_e2e() { vec![ PoolsEvent::Created { depositor: 10, pool_id: 1 }, PoolsEvent::Bonded { member: 10, pool_id: 1, bonded: 50, joined: true }, + PoolsEvent::PoolNominationMade { pool_id: 1, caller: 10 }, ] ); @@ -968,6 +973,7 @@ fn pool_migration_e2e() { vec![ PoolsEvent::Created { depositor: 10, pool_id: 1 }, PoolsEvent::Bonded { member: 10, pool_id: 1, bonded: 50, joined: true }, + PoolsEvent::PoolNominationMade { pool_id: 1, caller: 10 } ] ); @@ -1252,6 +1258,7 @@ fn disable_pool_operations_on_non_migrated() { vec![ PoolsEvent::Created { depositor: 10, pool_id: 1 }, PoolsEvent::Bonded { member: 10, pool_id: 1, bonded: 50, joined: true }, + PoolsEvent::PoolNominationMade { pool_id: 1, caller: 10 } ] ); diff --git a/substrate/frame/offences/Cargo.toml b/substrate/frame/offences/Cargo.toml index 4dd9d7f10c9f231ab019d31c0ef2254848b82755..221a4918a511f21bcf865e4de0295ea0c26c712a 100644 --- a/substrate/frame/offences/Cargo.toml +++ b/substrate/frame/offences/Cargo.toml @@ -20,7 +20,6 @@ codec = { features = ["derive"], workspace = true } frame-support = { workspace = true } frame-system = { workspace = true } log = { workspace = true } -pallet-balances = { workspace = true } scale-info = { features = ["derive"], workspace = true } serde = { optional = true, workspace = true, default-features = true } sp-runtime = { workspace = true } @@ -37,7 +36,6 @@ std = [ "frame-support/std", "frame-system/std", "log/std", - "pallet-balances/std", "scale-info/std", "serde", "sp-core/std", @@ -48,13 +46,11 @@ std = [ runtime-benchmarks = [ "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", - "pallet-balances/runtime-benchmarks", "sp-runtime/runtime-benchmarks", "sp-staking/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", - "pallet-balances/try-runtime", "sp-runtime/try-runtime", ] diff --git a/substrate/frame/paged-list/Cargo.toml b/substrate/frame/paged-list/Cargo.toml index da029bdd7423f1a093933f9865ab48b0c4892012..07755c351e288206380b0e3192041717fd32be29 100644 --- a/substrate/frame/paged-list/Cargo.toml +++ b/substrate/frame/paged-list/Cargo.toml @@ -19,7 +19,6 @@ codec = { features = ["derive"], workspace = true } docify = { workspace = true } scale-info = { features = ["derive"], workspace = true } -frame-benchmarking = { optional = true, workspace = true } frame-support = { workspace = true } frame-system = { workspace = true } @@ -33,7 +32,6 @@ default = ["std"] std = [ "codec/std", - "frame-benchmarking?/std", "frame-support/std", "frame-system/std", "scale-info/std", @@ -44,7 +42,6 @@ std = [ ] runtime-benchmarks = [ - "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", "sp-runtime/runtime-benchmarks", diff --git a/substrate/frame/parameters/src/tests/mock.rs b/substrate/frame/parameters/src/tests/mock.rs index 53a3b3e394c4b7c5d8410ba6e1af758d78cbf8ae..8d6f7d25ceac5e02ee4a067d77e4b8a5f88c1599 100644 --- a/substrate/frame/parameters/src/tests/mock.rs +++ b/substrate/frame/parameters/src/tests/mock.rs @@ -75,7 +75,7 @@ pub mod dynamic_params { } #[dynamic_pallet_params] - #[codec(index = 3)] + #[codec(index = 4)] pub mod somE_weird_SPElLInG_s { #[codec(index = 0)] pub static V: u64 = 0; diff --git a/substrate/frame/revive/Cargo.toml b/substrate/frame/revive/Cargo.toml index 0959cc50638ba51a671c3ad8311d7e5745ef086f..4faa9205378fed4e0f4eb550b09539951ac3989b 100644 --- a/substrate/frame/revive/Cargo.toml +++ b/substrate/frame/revive/Cargo.toml @@ -44,6 +44,9 @@ pallet-revive-uapi = { workspace = true, features = ["scale"] } pallet-transaction-payment = { workspace = true } sp-api = { workspace = true } sp-arithmetic = { workspace = true } +sp-consensus-aura = { workspace = true, optional = true } +sp-consensus-babe = { workspace = true, optional = true } +sp-consensus-slots = { workspace = true, optional = true } sp-core = { workspace = true } sp-io = { workspace = true } sp-runtime = { workspace = true } @@ -96,6 +99,9 @@ std = [ "serde_json/std", "sp-api/std", "sp-arithmetic/std", + "sp-consensus-aura/std", + "sp-consensus-babe/std", + "sp-consensus-slots/std", "sp-core/std", "sp-io/std", "sp-keystore/std", @@ -114,6 +120,9 @@ runtime-benchmarks = [ "pallet-timestamp/runtime-benchmarks", "pallet-transaction-payment/runtime-benchmarks", "pallet-utility/runtime-benchmarks", + "sp-consensus-aura", + "sp-consensus-babe", + "sp-consensus-slots", "sp-runtime/runtime-benchmarks", "xcm-builder/runtime-benchmarks", "xcm/runtime-benchmarks", diff --git a/substrate/frame/revive/fixtures/contracts/block_author.rs b/substrate/frame/revive/fixtures/contracts/block_author.rs new file mode 100644 index 0000000000000000000000000000000000000000..59886a19cc6198756248a40b6779216f29ec4906 --- /dev/null +++ b/substrate/frame/revive/fixtures/contracts/block_author.rs @@ -0,0 +1,37 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![no_std] +#![no_main] + +use common::input; +use uapi::{HostFn, HostFnImpl as api}; + +#[no_mangle] +#[polkavm_derive::polkavm_export] +pub extern "C" fn deploy() {} + +#[no_mangle] +#[polkavm_derive::polkavm_export] +pub extern "C" fn call() { + input!(expected: &[u8; 20],); + + let mut received = [0; 20]; + api::block_author(&mut received); + + assert_eq!(expected, &received); +} diff --git a/substrate/frame/revive/fixtures/contracts/call_diverging_out_len.rs b/substrate/frame/revive/fixtures/contracts/call_diverging_out_len.rs index 9a8fe5f5f6cc536d39a255db7a9d803e3b4bd70e..d084c4aed6df750152c417f3c4a6c3d06b6c09a1 100644 --- a/substrate/frame/revive/fixtures/contracts/call_diverging_out_len.rs +++ b/substrate/frame/revive/fixtures/contracts/call_diverging_out_len.rs @@ -66,12 +66,11 @@ fn assert_instantiate<const N: usize>(expected_output: [u8; BUF_SIZE]) { let output_buf_capped = &mut &mut output_buf[..N]; api::instantiate( - &code_hash, u64::MAX, u64::MAX, &[u8::MAX; 32], &[0; 32], - &[0; 32], + &code_hash, None, Some(output_buf_capped), None, diff --git a/substrate/frame/revive/fixtures/contracts/caller_contract.rs b/substrate/frame/revive/fixtures/contracts/caller_contract.rs index d042dc2c22a2508fafdeecf75e2003006b75a117..b6a9bf2895fa6d48b3032c5b4e9b3839e93bb6ae 100644 --- a/substrate/frame/revive/fixtures/contracts/caller_contract.rs +++ b/substrate/frame/revive/fixtures/contracts/caller_contract.rs @@ -21,6 +21,9 @@ use common::{input, u256_bytes}; use uapi::{HostFn, HostFnImpl as api, ReturnErrorCode}; +const INPUT: [u8; 8] = [0u8, 1, 34, 51, 68, 85, 102, 119]; +const REVERTED_INPUT: [u8; 7] = [1u8, 34, 51, 68, 85, 102, 119]; + #[no_mangle] #[polkavm_derive::polkavm_export] pub extern "C" fn deploy() {} @@ -36,17 +39,21 @@ pub extern "C" fn call() { let salt = [0u8; 32]; // Callee will use the first 4 bytes of the input to return an exit status. - let input = [0u8, 1, 34, 51, 68, 85, 102, 119]; - let reverted_input = [1u8, 34, 51, 68, 85, 102, 119]; + let mut input_deploy = [0; 32 + INPUT.len()]; + input_deploy[..32].copy_from_slice(code_hash); + input_deploy[32..].copy_from_slice(&INPUT); + + let mut reverted_input_deploy = [0; 32 + REVERTED_INPUT.len()]; + reverted_input_deploy[..32].copy_from_slice(code_hash); + reverted_input_deploy[32..].copy_from_slice(&REVERTED_INPUT); // Fail to deploy the contract since it returns a non-zero exit status. let res = api::instantiate( - code_hash, u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. &[u8::MAX; 32], // No deposit limit. &value, - &reverted_input, + &reverted_input_deploy, None, None, Some(&salt), @@ -55,12 +62,11 @@ pub extern "C" fn call() { // Fail to deploy the contract due to insufficient ref_time weight. let res = api::instantiate( - code_hash, 1u64, // too little ref_time weight u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. &[u8::MAX; 32], // No deposit limit. &value, - &input, + &input_deploy, None, None, Some(&salt), @@ -69,12 +75,11 @@ pub extern "C" fn call() { // Fail to deploy the contract due to insufficient proof_size weight. let res = api::instantiate( - code_hash, u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. 1u64, // Too little proof_size weight &[u8::MAX; 32], // No deposit limit. &value, - &input, + &input_deploy, None, None, Some(&salt), @@ -85,12 +90,11 @@ pub extern "C" fn call() { let mut callee = [0u8; 20]; api::instantiate( - code_hash, u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. &[u8::MAX; 32], // No deposit limit. &value, - &input, + &input_deploy, Some(&mut callee), None, Some(&salt), @@ -101,11 +105,11 @@ pub extern "C" fn call() { let res = api::call( uapi::CallFlags::empty(), &callee, - u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. - u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. &[u8::MAX; 32], // No deposit limit. &value, - &reverted_input, + &REVERTED_INPUT, None, ); assert!(matches!(res, Err(ReturnErrorCode::CalleeReverted))); @@ -118,7 +122,7 @@ pub extern "C" fn call() { u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. &[u8::MAX; 32], // No deposit limit. &value, - &input, + &INPUT, None, ); assert!(matches!(res, Err(ReturnErrorCode::OutOfResources))); @@ -127,11 +131,11 @@ pub extern "C" fn call() { let res = api::call( uapi::CallFlags::empty(), &callee, - u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. - 1u64, // too little proof_size weight + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. + 1u64, // too little proof_size weight &[u8::MAX; 32], // No deposit limit. &value, - &input, + &INPUT, None, ); assert!(matches!(res, Err(ReturnErrorCode::OutOfResources))); @@ -141,13 +145,13 @@ pub extern "C" fn call() { api::call( uapi::CallFlags::empty(), &callee, - u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. - u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. &[u8::MAX; 32], // No deposit limit. &value, - &input, + &INPUT, Some(&mut &mut output[..]), ) .unwrap(); - assert_eq!(&output, &input[4..]) + assert_eq!(&output, &INPUT[4..]) } diff --git a/substrate/frame/revive/fixtures/contracts/create1_with_value.rs b/substrate/frame/revive/fixtures/contracts/create1_with_value.rs index 3554f8f620a29f08e4855ef5b77a2be3a3f6c887..a694a9b09189872ec54bf511548685979f20706a 100644 --- a/substrate/frame/revive/fixtures/contracts/create1_with_value.rs +++ b/substrate/frame/revive/fixtures/contracts/create1_with_value.rs @@ -34,16 +34,6 @@ pub extern "C" fn call() { api::value_transferred(&mut value); // Deploy the contract with no salt (equivalent to create1). - let ret = api::instantiate( - code_hash, - u64::MAX, - u64::MAX, - &[u8::MAX; 32], - &value, - &[], - None, - None, - None - ); - assert!(ret.is_ok()); + api::instantiate(u64::MAX, u64::MAX, &[u8::MAX; 32], &value, code_hash, None, None, None) + .unwrap(); } diff --git a/substrate/frame/revive/fixtures/contracts/create_storage_and_instantiate.rs b/substrate/frame/revive/fixtures/contracts/create_storage_and_instantiate.rs index f627bc8ba6c418b4d36a42eda2ea49daf382e82e..0ee0bd70db97c0b85fcd52070b20ec992db124da 100644 --- a/substrate/frame/revive/fixtures/contracts/create_storage_and_instantiate.rs +++ b/substrate/frame/revive/fixtures/contracts/create_storage_and_instantiate.rs @@ -20,7 +20,9 @@ #![no_main] use common::{input, u256_bytes}; -use uapi::{HostFn, HostFnImpl as api}; +use uapi::{HostFn, HostFnImpl as api, StorageFlags}; + +static BUFFER: [u8; 16 * 1024 + 1] = [0u8; 16 * 1024 + 1]; #[no_mangle] #[polkavm_derive::polkavm_export] @@ -30,22 +32,30 @@ pub extern "C" fn deploy() {} #[polkavm_derive::polkavm_export] pub extern "C" fn call() { input!( - input: [u8; 4], code_hash: &[u8; 32], + input: [u8; 4], deposit_limit: &[u8; 32], ); + let len = u32::from_le_bytes(input.try_into().unwrap()); + let data = &BUFFER[..len as usize]; + let mut key = [0u8; 32]; + key[0] = 1; + api::set_storage(StorageFlags::empty(), &key, data); + let value = u256_bytes(10_000u64); let salt = [0u8; 32]; let mut address = [0u8; 20]; + let mut deploy_input = [0; 32 + 4]; + deploy_input[..32].copy_from_slice(code_hash); + deploy_input[32..].copy_from_slice(&input); let ret = api::instantiate( - code_hash, u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. deposit_limit, &value, - input, + &deploy_input, Some(&mut address), None, Some(&salt), diff --git a/substrate/frame/revive/fixtures/contracts/create_transient_storage_and_call.rs b/substrate/frame/revive/fixtures/contracts/create_transient_storage_and_call.rs index 660db84028dbdd5b7c990beaa26b5a82dfe4f8dc..0244967a0556531f2579b41ffb63fa489f5ded82 100644 --- a/substrate/frame/revive/fixtures/contracts/create_transient_storage_and_call.rs +++ b/substrate/frame/revive/fixtures/contracts/create_transient_storage_and_call.rs @@ -22,7 +22,7 @@ use common::input; use uapi::{HostFn, HostFnImpl as api, StorageFlags}; -static BUFFER: [u8; 448] = [0u8; 448]; +static BUFFER: [u8; 416] = [0u8; 416]; #[no_mangle] #[polkavm_derive::polkavm_export] diff --git a/substrate/frame/revive/fixtures/contracts/destroy_and_transfer.rs b/substrate/frame/revive/fixtures/contracts/destroy_and_transfer.rs index c2c7da528ba7c92939facce5dfcb9cb2b82b6ffd..b5face97e236048190cc5a0b2e3a6d964fbd352f 100644 --- a/substrate/frame/revive/fixtures/contracts/destroy_and_transfer.rs +++ b/substrate/frame/revive/fixtures/contracts/destroy_and_transfer.rs @@ -29,17 +29,15 @@ const VALUE: [u8; 32] = u256_bytes(65536); pub extern "C" fn deploy() { input!(code_hash: &[u8; 32],); - let input = [0u8; 0]; let mut address = [0u8; 20]; let salt = [47u8; 32]; api::instantiate( - code_hash, u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. &[u8::MAX; 32], // No deposit limit. &VALUE, - &input, + code_hash, Some(&mut address), None, Some(&salt), diff --git a/substrate/frame/revive/fixtures/contracts/instantiate_return_code.rs b/substrate/frame/revive/fixtures/contracts/instantiate_return_code.rs index f7cbd75be5aaaf3fcf0ac01bfd33fdd2e83bc387..a3643bdedbdbd90eb1e6862ffe1f0c74b760df54 100644 --- a/substrate/frame/revive/fixtures/contracts/instantiate_return_code.rs +++ b/substrate/frame/revive/fixtures/contracts/instantiate_return_code.rs @@ -28,16 +28,14 @@ pub extern "C" fn deploy() {} #[no_mangle] #[polkavm_derive::polkavm_export] pub extern "C" fn call() { - input!(buffer, 36, code_hash: &[u8; 32],); - let input = &buffer[32..]; + input!(buffer: &[u8; 36],); let err_code = match api::instantiate( - code_hash, - u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. - u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. - &[u8::MAX; 32], // No deposit limit. + u64::MAX, // How much ref_time weight to devote for the execution. u64::MAX = use all. + u64::MAX, // How much proof_size weight to devote for the execution. u64::MAX = use all. + &[u8::MAX; 32], // No deposit limit. &u256_bytes(10_000u64), // Value to transfer. - input, + buffer, None, None, Some(&[0u8; 32]), // Salt. diff --git a/substrate/frame/revive/fixtures/contracts/locking_delegate_dependency.rs b/substrate/frame/revive/fixtures/contracts/locking_delegate_dependency.rs deleted file mode 100644 index 6be5d5c72f9ac7b94cbb191419796c68be4c52cc..0000000000000000000000000000000000000000 --- a/substrate/frame/revive/fixtures/contracts/locking_delegate_dependency.rs +++ /dev/null @@ -1,77 +0,0 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! This contract tests the behavior of locking / unlocking delegate_dependencies when delegate -//! calling into a contract. -#![no_std] -#![no_main] - -use common::input; -use uapi::{HostFn, HostFnImpl as api}; - -const ALICE_FALLBACK: [u8; 20] = [1u8; 20]; - -/// Load input data and perform the action specified by the input. -/// If `delegate_call` is true, then delegate call into the contract. -fn load_input(delegate_call: bool) { - input!( - action: u32, - address: &[u8; 20], - code_hash: &[u8; 32], - ); - - match action { - // 1 = Lock delegate dependency - 1 => { - api::lock_delegate_dependency(code_hash); - }, - // 2 = Unlock delegate dependency - 2 => { - api::unlock_delegate_dependency(code_hash); - }, - // 3 = Terminate - 3 => { - api::terminate(&ALICE_FALLBACK); - }, - // Everything else is a noop - _ => {}, - } - - if delegate_call { - api::delegate_call( - uapi::CallFlags::empty(), - address, - u64::MAX, - u64::MAX, - &[u8::MAX; 32], - &[], - None - ).unwrap(); - } -} - -#[no_mangle] -#[polkavm_derive::polkavm_export] -pub extern "C" fn deploy() { - load_input(false); -} - -#[no_mangle] -#[polkavm_derive::polkavm_export] -pub extern "C" fn call() { - load_input(true); -} diff --git a/substrate/frame/revive/fixtures/contracts/return_data_api.rs b/substrate/frame/revive/fixtures/contracts/return_data_api.rs index 1407e5323ea18989bcf5efec8867e48d75ff9710..e8aeeea44bde77e0ceac70910dfad40055cda960 100644 --- a/substrate/frame/revive/fixtures/contracts/return_data_api.rs +++ b/substrate/frame/revive/fixtures/contracts/return_data_api.rs @@ -88,8 +88,9 @@ fn assert_balance_transfer_does_reset() { &[u8::MAX; 32], &u256_bytes(128), &[], - None - ).unwrap(); + None, + ) + .unwrap(); assert_return_data_size_of(0); } @@ -117,13 +118,16 @@ pub extern "C" fn call() { input }; let mut instantiate = |exit_flag| { + let input = construct_input(exit_flag); + let mut deploy_input = [0; 32 + INPUT_BUF_SIZE]; + deploy_input[..32].copy_from_slice(code_hash); + deploy_input[32..].copy_from_slice(&input); api::instantiate( - code_hash, u64::MAX, u64::MAX, &[u8::MAX; 32], &[0; 32], - &construct_input(exit_flag), + &deploy_input, Some(&mut address_buf), None, None, diff --git a/substrate/frame/revive/fixtures/contracts/self_destruct.rs b/substrate/frame/revive/fixtures/contracts/self_destruct.rs index 053e545deb19e0c9ecb322ec38f023d566f3b726..eed7f40ddfed7b3518fad29e058c90f457fd2a9e 100644 --- a/substrate/frame/revive/fixtures/contracts/self_destruct.rs +++ b/substrate/frame/revive/fixtures/contracts/self_destruct.rs @@ -25,7 +25,10 @@ const DJANGO_FALLBACK: [u8; 20] = [4u8; 20]; #[no_mangle] #[polkavm_derive::polkavm_export] -pub extern "C" fn deploy() {} +pub extern "C" fn deploy() { + // make sure that the deposit for the immutable data is refunded + api::set_immutable_data(&[1, 2, 3, 4, 5]) +} #[no_mangle] #[polkavm_derive::polkavm_export] diff --git a/substrate/frame/revive/proc-macro/src/lib.rs b/substrate/frame/revive/proc-macro/src/lib.rs index 6e38063d20a674c6c567835ced35def5c0858ac2..6f087c86b5ffdc89604daf6d1dcd6e6d100e874f 100644 --- a/substrate/frame/revive/proc-macro/src/lib.rs +++ b/substrate/frame/revive/proc-macro/src/lib.rs @@ -355,6 +355,11 @@ where { const ALLOWED_REGISTERS: usize = 6; + // too many arguments + if param_names.clone().count() > ALLOWED_REGISTERS { + panic!("Syscalls take a maximum of {ALLOWED_REGISTERS} arguments"); + } + // all of them take one register but we truncate them before passing into the function // it is important to not allow any type which has illegal bit patterns like 'bool' if !param_types.clone().all(|ty| { @@ -369,39 +374,7 @@ where panic!("Only primitive unsigned integers are allowed as arguments to syscalls"); } - // too many arguments: pass as pointer to a struct in memory - if param_names.clone().count() > ALLOWED_REGISTERS { - let fields = param_names.clone().zip(param_types.clone()).map(|(name, ty)| { - quote! { - #name: #ty, - } - }); - return quote! { - #[derive(Default)] - #[repr(C)] - struct Args { - #(#fields)* - } - let Args { #(#param_names,)* } = { - let len = ::core::mem::size_of::<Args>(); - let mut args = Args::default(); - let ptr = &mut args as *mut Args as *mut u8; - // Safety - // 1. The struct is initialized at all times. - // 2. We only allow primitive integers (no bools) as arguments so every bit pattern is safe. - // 3. The reference doesn't outlive the args field. - // 4. There is only the single reference to the args field. - // 5. The length of the generated slice is the same as the struct. - let reference = unsafe { - ::core::slice::from_raw_parts_mut(ptr, len) - }; - memory.read_into_buf(__a0__ as _, reference)?; - args - }; - } - } - - // otherwise: one argument per register + // one argument per register let bindings = param_names.zip(param_types).enumerate().map(|(idx, (name, ty))| { let reg = quote::format_ident!("__a{}__", idx); quote! { diff --git a/substrate/frame/revive/rpc/Cargo.toml b/substrate/frame/revive/rpc/Cargo.toml index 9d822f5ff8e2771a3bdb421698eacea5339b2803..014231f7f3e55c9a296e4519e6d9ea95215061bd 100644 --- a/substrate/frame/revive/rpc/Cargo.toml +++ b/substrate/frame/revive/rpc/Cargo.toml @@ -17,34 +17,33 @@ path = "src/main.rs" name = "eth-indexer" path = "src/eth-indexer.rs" +[[bin]] +name = "eth-rpc-tester" +path = "src/eth-rpc-tester.rs" + [[example]] name = "deploy" path = "examples/rust/deploy.rs" -required-features = ["example"] [[example]] name = "transfer" path = "examples/rust/transfer.rs" -required-features = ["example"] [[example]] name = "rpc-playground" path = "examples/rust/rpc-playground.rs" -required-features = ["example"] [[example]] name = "extrinsic" path = "examples/rust/extrinsic.rs" -required-features = ["example"] [[example]] name = "remark-extrinsic" path = "examples/rust/remark-extrinsic.rs" -required-features = ["example"] [dependencies] anyhow = { workspace = true } -clap = { workspace = true, features = ["derive"] } +clap = { workspace = true, features = ["derive", "env"] } codec = { workspace = true, features = ["derive"] } ethabi = { version = "18.0.0" } futures = { workspace = true, features = ["thread-pool"] } @@ -52,8 +51,9 @@ hex = { workspace = true } jsonrpsee = { workspace = true, features = ["full"] } log = { workspace = true } pallet-revive = { workspace = true, default-features = true } +pallet-revive-fixtures = { workspace = true, default-features = true } prometheus-endpoint = { workspace = true, default-features = true } -rlp = { workspace = true, optional = true } +rlp = { workspace = true } sc-cli = { workspace = true, default-features = true } sc-rpc = { workspace = true, default-features = true } sc-rpc-api = { workspace = true, default-features = true } @@ -62,24 +62,18 @@ sp-arithmetic = { workspace = true, default-features = true } sp-core = { workspace = true, default-features = true } sp-crypto-hashing = { workspace = true } sp-weights = { workspace = true, default-features = true } -sqlx = { version = "0.8.2", features = [ - "macros", - "runtime-tokio", - "sqlite", +sqlx = { version = "0.8.2", features = ["macros", "runtime-tokio", "sqlite"] } +subxt = { workspace = true, default-features = true, features = [ + "reconnecting-rpc-client", ] } -subxt = { workspace = true, default-features = true, features = ["reconnecting-rpc-client"] } -subxt-signer = { workspace = true, optional = true, features = [ +subxt-signer = { workspace = true, features = [ "unstable-eth", ] } thiserror = { workspace = true } tokio = { workspace = true, features = ["full"] } -[features] -example = ["rlp", "subxt-signer"] - [dev-dependencies] env_logger = { workspace = true } -pallet-revive-fixtures = { workspace = true, default-features = true } static_init = { workspace = true } substrate-cli-test-utils = { workspace = true } subxt-signer = { workspace = true, features = ["unstable-eth"] } diff --git a/substrate/frame/revive/rpc/examples/README.md b/substrate/frame/revive/rpc/examples/README.md index b9a2756b381d26cb7155b11c0aa1968eb2836256..1079c254b9c2070fb798c7b8362aa8788d89ab79 100644 --- a/substrate/frame/revive/rpc/examples/README.md +++ b/substrate/frame/revive/rpc/examples/README.md @@ -42,7 +42,7 @@ RUST_LOG="info,eth-rpc=debug" cargo run -p pallet-revive-eth-rpc -- --dev Run one of the examples from the `examples` directory to send a transaction to the node: ```bash -RUST_LOG="info,eth-rpc=debug" cargo run -p pallet-revive-eth-rpc --features example --example deploy +RUST_LOG="info,eth-rpc=debug" cargo run -p pallet-revive-eth-rpc --example deploy ``` ## JS examples diff --git a/substrate/frame/revive/rpc/examples/js/pvm/FlipperCaller.polkavm b/substrate/frame/revive/rpc/examples/js/pvm/FlipperCaller.polkavm index 29efafd8722db556b949b04c47c88eeec07535a6..b7b037c1c7b31018fccc0d7bfc0e058d05b68588 100644 Binary files a/substrate/frame/revive/rpc/examples/js/pvm/FlipperCaller.polkavm and b/substrate/frame/revive/rpc/examples/js/pvm/FlipperCaller.polkavm differ diff --git a/substrate/frame/revive/rpc/examples/js/pvm/PiggyBank.polkavm b/substrate/frame/revive/rpc/examples/js/pvm/PiggyBank.polkavm index 78455fcdd7c64a3a1f5e93b6d62cd03b46eb5953..2fc5e139825aa174d85127c3f29543fd7ebe05fc 100644 Binary files a/substrate/frame/revive/rpc/examples/js/pvm/PiggyBank.polkavm and b/substrate/frame/revive/rpc/examples/js/pvm/PiggyBank.polkavm differ diff --git a/substrate/frame/revive/rpc/src/cli.rs b/substrate/frame/revive/rpc/src/cli.rs index d63d596ab7a8b87cd37e944da954819f58cd5b9b..b6c57d2c3b0bfcb50f024aee5521d9b1edf4d1c2 100644 --- a/substrate/frame/revive/rpc/src/cli.rs +++ b/substrate/frame/revive/rpc/src/cli.rs @@ -19,7 +19,7 @@ use crate::{ client::{connect, Client}, BlockInfoProvider, BlockInfoProviderImpl, CacheReceiptProvider, DBReceiptProvider, EthRpcServer, EthRpcServerImpl, ReceiptProvider, SystemHealthRpcServer, - SystemHealthRpcServerImpl, + SystemHealthRpcServerImpl, LOG_TARGET, }; use clap::Parser; use futures::{pin_mut, FutureExt}; @@ -52,7 +52,7 @@ pub struct CliCommand { /// The database used to store Ethereum transaction hashes. /// This is only useful if the node needs to act as an archive node and respond to Ethereum RPC /// queries for transactions that are not in the in memory cache. - #[clap(long)] + #[clap(long, env = "DATABASE_URL")] pub database_url: Option<String>, /// If true, we will only read from the database and not write to it. @@ -148,6 +148,7 @@ pub fn run(cmd: CliCommand) -> anyhow::Result<()> { Arc::new(BlockInfoProviderImpl::new(cache_size, api.clone(), rpc.clone())); let receipt_provider: Arc<dyn ReceiptProvider> = if let Some(database_url) = database_url.as_ref() { + log::info!(target: LOG_TARGET, "🔗 Connecting to provided database"); Arc::new(( CacheReceiptProvider::default(), DBReceiptProvider::new( @@ -158,6 +159,7 @@ pub fn run(cmd: CliCommand) -> anyhow::Result<()> { .await?, )) } else { + log::info!(target: LOG_TARGET, "🔌 No database provided, using in-memory cache"); Arc::new(CacheReceiptProvider::default()) }; diff --git a/substrate/frame/revive/rpc/src/client.rs b/substrate/frame/revive/rpc/src/client.rs index 440972c7a681b58dbd6cd3dfdc9040a099c1d17e..47e439f068513f9ef5184bd40fcc57ffbdc11d46 100644 --- a/substrate/frame/revive/rpc/src/client.rs +++ b/substrate/frame/revive/rpc/src/client.rs @@ -646,9 +646,9 @@ impl Client { &self, block: Arc<SubstrateBlock>, hydrated_transactions: bool, - ) -> Result<Block, ClientError> { + ) -> Block { let runtime_api = self.api.runtime_api().at(block.hash()); - let gas_limit = Self::block_gas_limit(&runtime_api).await?; + let gas_limit = Self::block_gas_limit(&runtime_api).await.unwrap_or_default(); let header = block.header(); let timestamp = extract_block_timestamp(&block).await.unwrap_or_default(); @@ -658,7 +658,7 @@ impl Client { let state_root = header.state_root.0.into(); let extrinsics_root = header.extrinsics_root.0.into(); - let receipts = extract_receipts_from_block(&block).await?; + let receipts = extract_receipts_from_block(&block).await.unwrap_or_default(); let gas_used = receipts.iter().fold(U256::zero(), |acc, (_, receipt)| acc + receipt.gas_used); let transactions = if hydrated_transactions { @@ -675,7 +675,7 @@ impl Client { .into() }; - Ok(Block { + Block { hash: block.hash(), parent_hash, state_root, @@ -689,7 +689,7 @@ impl Client { receipts_root: extrinsics_root, transactions, ..Default::default() - }) + } } /// Convert a weight to a fee. @@ -697,7 +697,6 @@ impl Client { runtime_api: &subxt::runtime_api::RuntimeApi<SrcChainConfig, OnlineClient<SrcChainConfig>>, ) -> Result<U256, ClientError> { let payload = subxt_client::apis().revive_api().block_gas_limit(); - let gas_limit = runtime_api.call(payload).await?; Ok(*gas_limit) } diff --git a/substrate/frame/revive/rpc/src/eth-indexer.rs b/substrate/frame/revive/rpc/src/eth-indexer.rs index 3e7f6b6fa91b88554203386ca00ebbe5e9b577a0..894143be0a525a581a32301dc12070b3bbc9143b 100644 --- a/substrate/frame/revive/rpc/src/eth-indexer.rs +++ b/substrate/frame/revive/rpc/src/eth-indexer.rs @@ -37,7 +37,7 @@ pub struct CliCommand { pub oldest_block: Option<SubstrateBlockNumber>, /// The database used to store Ethereum transaction hashes. - #[clap(long)] + #[clap(long, env = "DATABASE_URL")] pub database_url: String, #[allow(missing_docs)] diff --git a/substrate/frame/revive/rpc/src/eth-rpc-tester.rs b/substrate/frame/revive/rpc/src/eth-rpc-tester.rs new file mode 100644 index 0000000000000000000000000000000000000000..0ddad6874dfd5b188508d59a4dacf31ee40f85ca --- /dev/null +++ b/substrate/frame/revive/rpc/src/eth-rpc-tester.rs @@ -0,0 +1,157 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +use clap::Parser; +use jsonrpsee::http_client::HttpClientBuilder; +use pallet_revive::evm::{Account, BlockTag, ReceiptInfo}; +use pallet_revive_eth_rpc::{ + example::{wait_for_receipt, TransactionBuilder}, + EthRpcClient, +}; +use tokio::{ + io::{AsyncBufReadExt, BufReader}, + process::{Child, ChildStderr, Command}, + signal::unix::{signal, SignalKind}, +}; + +const DOCKER_CONTAINER_NAME: &str = "eth-rpc-test"; + +#[derive(Parser, Debug)] +#[clap(author, about, version)] +pub struct CliCommand { + /// The parity docker image e.g eth-rpc:master-fb2e414f + #[clap(long, default_value = "eth-rpc:master-fb2e414f")] + docker_image: String, + + /// The docker binary + /// Either docker or podman + #[clap(long, default_value = "docker")] + docker_bin: String, +} + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + let CliCommand { docker_bin, docker_image, .. } = CliCommand::parse(); + + let mut docker_process = start_docker(&docker_bin, &docker_image)?; + let stderr = docker_process.stderr.take().unwrap(); + + tokio::select! { + result = docker_process.wait() => { + println!("docker failed: {result:?}"); + } + _ = interrupt() => { + kill_docker().await?; + } + _ = test_eth_rpc(stderr) => { + kill_docker().await?; + } + } + + Ok(()) +} + +async fn interrupt() { + let mut sigint = signal(SignalKind::interrupt()).expect("failed to listen for SIGINT"); + let mut sigterm = signal(SignalKind::terminate()).expect("failed to listen for SIGTERM"); + + tokio::select! { + _ = sigint.recv() => {}, + _ = sigterm.recv() => {}, + } +} + +fn start_docker(docker_bin: &str, docker_image: &str) -> anyhow::Result<Child> { + let docker_process = Command::new(docker_bin) + .args([ + "run", + "--name", + DOCKER_CONTAINER_NAME, + "--rm", + "-p", + "8545:8545", + &format!("docker.io/paritypr/{docker_image}"), + "--node-rpc-url", + "wss://westend-asset-hub-rpc.polkadot.io", + "--rpc-cors", + "all", + "--unsafe-rpc-external", + "--log=sc_rpc_server:info", + ]) + .stderr(std::process::Stdio::piped()) + .kill_on_drop(true) + .spawn()?; + + Ok(docker_process) +} + +async fn kill_docker() -> anyhow::Result<()> { + Command::new("docker").args(["kill", DOCKER_CONTAINER_NAME]).output().await?; + Ok(()) +} + +async fn test_eth_rpc(stderr: ChildStderr) -> anyhow::Result<()> { + let mut reader = BufReader::new(stderr).lines(); + while let Some(line) = reader.next_line().await? { + println!("{line}"); + if line.contains("Running JSON-RPC server") { + break; + } + } + + let account = Account::default(); + let data = vec![]; + let (bytes, _) = pallet_revive_fixtures::compile_module("dummy")?; + let input = bytes.into_iter().chain(data).collect::<Vec<u8>>(); + + println!("Account:"); + println!("- address: {:?}", account.address()); + let client = HttpClientBuilder::default().build("http://localhost:8545")?; + + let nonce = client.get_transaction_count(account.address(), BlockTag::Latest.into()).await?; + let balance = client.get_balance(account.address(), BlockTag::Latest.into()).await?; + println!("- nonce: {nonce:?}"); + println!("- balance: {balance:?}"); + + println!("\n\n=== Deploying dummy contract ===\n\n"); + let hash = TransactionBuilder::default().input(input).send(&client).await?; + + println!("Hash: {hash:?}"); + println!("Waiting for receipt..."); + let ReceiptInfo { block_number, gas_used, contract_address, .. } = + wait_for_receipt(&client, hash).await?; + + let contract_address = contract_address.unwrap(); + println!("\nReceipt:"); + println!("Block explorer: https://westend-asset-hub-eth-explorer.parity.io/{hash:?}"); + println!("- Block number: {block_number}"); + println!("- Gas used: {gas_used}"); + println!("- Address: {contract_address:?}"); + + println!("\n\n=== Calling dummy contract ===\n\n"); + let hash = TransactionBuilder::default().to(contract_address).send(&client).await?; + + println!("Hash: {hash:?}"); + println!("Waiting for receipt..."); + + let ReceiptInfo { block_number, gas_used, to, .. } = wait_for_receipt(&client, hash).await?; + println!("\nReceipt:"); + println!("Block explorer: https://westend-asset-hub-eth-explorer.parity.io/{hash:?}"); + println!("- Block number: {block_number}"); + println!("- Gas used: {gas_used}"); + println!("- To: {to:?}"); + Ok(()) +} diff --git a/substrate/frame/revive/rpc/src/example.rs b/substrate/frame/revive/rpc/src/example.rs index 3b9a33296ef4d9073c52e44bdb895cbe57875dc5..aad5b4fbc344d511088d0a73ee99fab3de042749 100644 --- a/substrate/frame/revive/rpc/src/example.rs +++ b/substrate/frame/revive/rpc/src/example.rs @@ -15,8 +15,6 @@ // See the License for the specific language governing permissions and // limitations under the License. //! Example utilities -#![cfg(any(feature = "example", test))] - use crate::{EthRpcClient, ReceiptInfo}; use anyhow::Context; use pallet_revive::evm::{ diff --git a/substrate/frame/revive/rpc/src/lib.rs b/substrate/frame/revive/rpc/src/lib.rs index 5e1341e2a29ab85b394241414cc70e112bf3e3b0..fcf93fa6c0d2e3dba86d079e6639a5cdd0942941 100644 --- a/substrate/frame/revive/rpc/src/lib.rs +++ b/substrate/frame/revive/rpc/src/lib.rs @@ -214,7 +214,7 @@ impl EthRpcServer for EthRpcServerImpl { let Some(block) = self.client.block_by_hash(&block_hash).await? else { return Ok(None); }; - let block = self.client.evm_block(block, hydrated_transactions).await?; + let block = self.client.evm_block(block, hydrated_transactions).await; Ok(Some(block)) } @@ -254,7 +254,7 @@ impl EthRpcServer for EthRpcServerImpl { let Some(block) = self.client.block_by_number_or_tag(&block).await? else { return Ok(None); }; - let block = self.client.evm_block(block, hydrated_transactions).await?; + let block = self.client.evm_block(block, hydrated_transactions).await; Ok(Some(block)) } diff --git a/substrate/frame/revive/src/benchmarking/mod.rs b/substrate/frame/revive/src/benchmarking/mod.rs index a19ed28dd9b0992906e4de55ab26481172330dc9..94d8edef7772ba1e2a8156ffea196fd30394008a 100644 --- a/substrate/frame/revive/src/benchmarking/mod.rs +++ b/substrate/frame/revive/src/benchmarking/mod.rs @@ -24,7 +24,7 @@ mod code; use self::{call_builder::CallSetup, code::WasmModule}; use crate::{ evm::runtime::GAS_PRICE, - exec::{Key, MomentOf}, + exec::{Ext, Key, MomentOf}, limits, storage::WriteOutcome, ConversionPrecision, Pallet as Contracts, *, @@ -39,8 +39,17 @@ use frame_support::{ weights::{Weight, WeightMeter}, }; use frame_system::RawOrigin; -use pallet_revive_uapi::{CallFlags, ReturnErrorCode, StorageFlags}; -use sp_runtime::traits::{Bounded, Hash}; +use pallet_revive_uapi::{pack_hi_lo, CallFlags, ReturnErrorCode, StorageFlags}; +use sp_consensus_aura::AURA_ENGINE_ID; +use sp_consensus_babe::{ + digests::{PreDigest, PrimaryPreDigest}, + BABE_ENGINE_ID, +}; +use sp_consensus_slots::Slot; +use sp_runtime::{ + generic::{Digest, DigestItem}, + traits::{Bounded, Hash}, +}; /// How many runs we do per API benchmark. /// @@ -886,6 +895,59 @@ mod benchmarks { assert_eq!(U256::from_little_endian(&memory[..]), runtime.ext().block_number()); } + #[benchmark(pov_mode = Measured)] + fn seal_block_author() { + build_runtime!(runtime, memory: [[123u8; 20], ]); + + let mut digest = Digest::default(); + + // The pre-runtime digest log is unbounded; usually around 3 items but it can vary. + // To get safe benchmark results despite that, populate it with a bunch of random logs to + // ensure iteration over many items (we just overestimate the cost of the API). + for i in 0..16 { + digest.push(DigestItem::PreRuntime([i, i, i, i], vec![i; 128])); + digest.push(DigestItem::Consensus([i, i, i, i], vec![i; 128])); + digest.push(DigestItem::Seal([i, i, i, i], vec![i; 128])); + digest.push(DigestItem::Other(vec![i; 128])); + } + + // The content of the pre-runtime digest log depends on the configured consensus. + // However, mismatching logs are simply ignored. Thus we construct fixtures which will + // let the API to return a value in both BABE and AURA consensus. + + // Construct a `Digest` log fixture returning some value in BABE + let primary_pre_digest = vec![0; <PrimaryPreDigest as MaxEncodedLen>::max_encoded_len()]; + let pre_digest = + PreDigest::Primary(PrimaryPreDigest::decode(&mut &primary_pre_digest[..]).unwrap()); + digest.push(DigestItem::PreRuntime(BABE_ENGINE_ID, pre_digest.encode())); + digest.push(DigestItem::Seal(BABE_ENGINE_ID, pre_digest.encode())); + + // Construct a `Digest` log fixture returning some value in AURA + let slot = Slot::default(); + digest.push(DigestItem::PreRuntime(AURA_ENGINE_ID, slot.encode())); + digest.push(DigestItem::Seal(AURA_ENGINE_ID, slot.encode())); + + frame_system::Pallet::<T>::initialize( + &BlockNumberFor::<T>::from(1u32), + &Default::default(), + &digest, + ); + + let result; + #[block] + { + result = runtime.bench_block_author(memory.as_mut_slice(), 0); + } + assert_ok!(result); + + let block_author = runtime + .ext() + .block_author() + .map(|account| T::AddressMapper::to_address(&account)) + .unwrap_or(H160::zero()); + assert_eq!(&memory[..], block_author.as_bytes()); + } + #[benchmark(pov_mode = Measured)] fn seal_block_hash() { let mut memory = vec![0u8; 64]; @@ -1011,24 +1073,11 @@ mod benchmarks { } #[benchmark(pov_mode = Measured)] - fn seal_terminate( - n: Linear<0, { limits::DELEGATE_DEPENDENCIES }>, - ) -> Result<(), BenchmarkError> { + fn seal_terminate() -> Result<(), BenchmarkError> { let beneficiary = account::<T::AccountId>("beneficiary", 0, 0); - let caller = whitelisted_caller(); - T::Currency::set_balance(&caller, caller_funding::<T>()); - let origin = RawOrigin::Signed(caller); - let storage_deposit = default_deposit_limit::<T>(); build_runtime!(runtime, memory: [beneficiary.encode(),]); - (0..n).for_each(|i| { - let new_code = WasmModule::dummy_unique(65 + i); - Contracts::<T>::bare_upload_code(origin.clone().into(), new_code.code, storage_deposit) - .unwrap(); - runtime.ext().lock_delegate_dependency(new_code.hash).unwrap(); - }); - let result; #[block] { @@ -1650,16 +1699,12 @@ mod benchmarks { { result = runtime.bench_call( memory.as_mut_slice(), - CallFlags::CLONE_INPUT.bits(), // flags - 0, // callee_ptr - u64::MAX, // ref_time_limit - u64::MAX, // proof_size_limit - callee_len, // deposit_ptr - callee_len + deposit_len, // value_ptr - 0, // input_data_ptr - 0, // input_data_len - SENTINEL, // output_ptr - 0, // output_len_ptr + pack_hi_lo(CallFlags::CLONE_INPUT.bits(), 0), // flags + callee + u64::MAX, // ref_time_limit + u64::MAX, // proof_size_limit + pack_hi_lo(callee_len, callee_len + deposit_len), // deposit_ptr + value_pr + pack_hi_lo(0, 0), // input len + data ptr + pack_hi_lo(0, SENTINEL), // output len + data ptr ); } @@ -1690,15 +1735,12 @@ mod benchmarks { { result = runtime.bench_delegate_call( memory.as_mut_slice(), - 0, // flags - 0, // address_ptr - u64::MAX, // ref_time_limit - u64::MAX, // proof_size_limit - address_len, // deposit_ptr - 0, // input_data_ptr - 0, // input_data_len - SENTINEL, // output_ptr - 0, + pack_hi_lo(0, 0), // flags + address ptr + u64::MAX, // ref_time_limit + u64::MAX, // proof_size_limit + address_len, // deposit_ptr + pack_hi_lo(0, 0), // input len + data ptr + pack_hi_lo(0, SENTINEL), // output len + ptr ); } @@ -1713,7 +1755,6 @@ mod benchmarks { let code = WasmModule::dummy(); let hash = Contract::<T>::with_index(1, WasmModule::dummy(), vec![])?.info()?.code_hash; let hash_bytes = hash.encode(); - let hash_len = hash_bytes.len() as u32; let value: BalanceOf<T> = 1_000_000u32.into(); let value_bytes = Into::<U256>::into(value).encode(); @@ -1732,11 +1773,12 @@ mod benchmarks { let mut runtime = crate::wasm::Runtime::<_, [u8]>::new(&mut ext, vec![]); let input = vec![42u8; i as _]; + let input_len = hash_bytes.len() as u32 + input.len() as u32; let salt = [42u8; 32]; let deployer = T::AddressMapper::to_address(&account_id); let addr = crate::address::create2(&deployer, &code.code, &input, &salt); let account_id = T::AddressMapper::to_fallback_account_id(&addr); - let mut memory = memory!(hash_bytes, deposit_bytes, value_bytes, input, salt,); + let mut memory = memory!(hash_bytes, input, deposit_bytes, value_bytes, salt,); let mut offset = { let mut current = 0u32; @@ -1753,17 +1795,12 @@ mod benchmarks { { result = runtime.bench_instantiate( memory.as_mut_slice(), - 0, // code_hash_ptr - u64::MAX, // ref_time_limit - u64::MAX, // proof_size_limit - offset(hash_len), // deposit_ptr - offset(deposit_len), // value_ptr - offset(value_len), // input_data_ptr - i, // input_data_len - SENTINEL, // address_ptr - SENTINEL, // output_ptr - 0, // output_len_ptr - offset(i), // salt_ptr + u64::MAX, // ref_time_limit + u64::MAX, // proof_size_limit + pack_hi_lo(offset(input_len), offset(deposit_len)), // deopsit_ptr + value_ptr + pack_hi_lo(input_len, 0), // input_data_len + input_data + pack_hi_lo(0, SENTINEL), // output_len_ptr + output_ptr + pack_hi_lo(SENTINEL, offset(value_len)), // address_ptr + salt_ptr ); } @@ -1932,43 +1969,6 @@ mod benchmarks { Ok(()) } - #[benchmark(pov_mode = Measured)] - fn lock_delegate_dependency() -> Result<(), BenchmarkError> { - let code_hash = Contract::<T>::with_index(1, WasmModule::dummy_unique(1), vec![])? - .info()? - .code_hash; - - build_runtime!(runtime, memory: [ code_hash.encode(),]); - - let result; - #[block] - { - result = runtime.bench_lock_delegate_dependency(memory.as_mut_slice(), 0); - } - - assert_ok!(result); - Ok(()) - } - - #[benchmark] - fn unlock_delegate_dependency() -> Result<(), BenchmarkError> { - let code_hash = Contract::<T>::with_index(1, WasmModule::dummy_unique(1), vec![])? - .info()? - .code_hash; - - build_runtime!(runtime, memory: [ code_hash.encode(),]); - runtime.bench_lock_delegate_dependency(memory.as_mut_slice(), 0).unwrap(); - - let result; - #[block] - { - result = runtime.bench_unlock_delegate_dependency(memory.as_mut_slice(), 0); - } - - assert_ok!(result); - Ok(()) - } - // Benchmark the execution of instructions. #[benchmark(pov_mode = Ignored)] fn instr(r: Linear<0, INSTR_BENCHMARK_RUNS>) { diff --git a/substrate/frame/revive/src/exec.rs b/substrate/frame/revive/src/exec.rs index 14ab917c0d4f909a12f34c9301fc60e0eaa08484..dc91c6f301009da44c5c07a99a1d0c4c25418df8 100644 --- a/substrate/frame/revive/src/exec.rs +++ b/substrate/frame/revive/src/exec.rs @@ -32,12 +32,11 @@ use core::{fmt::Debug, marker::PhantomData, mem}; use frame_support::{ crypto::ecdsa::ECDSAExt, dispatch::{DispatchResult, DispatchResultWithPostInfo}, - ensure, storage::{with_transaction, TransactionOutcome}, traits::{ fungible::{Inspect, Mutate}, tokens::{Fortitude, Preservation}, - Contains, OriginTrait, Time, + Contains, FindAuthor, OriginTrait, Time, }, weights::Weight, Blake2_128Concat, BoundedVec, StorageHasher, @@ -49,7 +48,7 @@ use frame_system::{ use sp_core::{ ecdsa::Public as ECDSAPublic, sr25519::{Public as SR25519Public, Signature as SR25519Signature}, - ConstU32, Get, H160, H256, U256, + ConstU32, H160, H256, U256, }; use sp_io::{crypto::secp256k1_ecdsa_recover_compressed, hashing::blake2_256}; use sp_runtime::{ @@ -323,6 +322,12 @@ pub trait Ext: sealing::Sealed { <Self::T as Config>::AddressMapper::to_address(self.account_id()) } + /// Get the length of the immutable data. + /// + /// This query is free as it does not need to load the immutable data from storage. + /// Useful when we need a constant time lookup of the length. + fn immutable_data_len(&mut self) -> u32; + /// Returns the immutable data of the current contract. /// /// Returns `Err(InvalidImmutableAccess)` if called from a constructor. @@ -366,6 +371,9 @@ pub trait Ext: sealing::Sealed { /// `block_number` isn't within the range of the previous 256 blocks. fn block_hash(&self, block_number: U256) -> Option<H256>; + /// Returns the author of the current block. + fn block_author(&self) -> Option<AccountIdOf<Self::T>>; + /// Returns the maximum allowed size of a storage item. fn max_value_size(&self) -> u32; @@ -406,51 +414,6 @@ pub trait Ext: sealing::Sealed { /// Sets new code hash and immutable data for an existing contract. fn set_code_hash(&mut self, hash: H256) -> DispatchResult; - /// Returns the number of times the specified contract exists on the call stack. Delegated calls - /// Increment the reference count of a of a stored code by one. - /// - /// # Errors - /// - /// [`Error::CodeNotFound`] is returned if no stored code found having the specified - /// `code_hash`. - fn increment_refcount(code_hash: H256) -> DispatchResult; - - /// Decrement the reference count of a stored code by one. - /// - /// # Note - /// - /// A contract whose reference count dropped to zero isn't automatically removed. A - /// `remove_code` transaction must be submitted by the original uploader to do so. - fn decrement_refcount(code_hash: H256); - - /// Adds a delegate dependency to [`ContractInfo`]'s `delegate_dependencies` field. - /// - /// This ensures that the delegated contract is not removed while it is still in use. It - /// increases the reference count of the code hash and charges a fraction (see - /// [`Config::CodeHashLockupDepositPercent`]) of the code deposit. - /// - /// # Errors - /// - /// - [`Error::MaxDelegateDependenciesReached`] - /// - [`Error::CannotAddSelfAsDelegateDependency`] - /// - [`Error::DelegateDependencyAlreadyExists`] - fn lock_delegate_dependency(&mut self, code_hash: H256) -> DispatchResult; - - /// Removes a delegate dependency from [`ContractInfo`]'s `delegate_dependencies` field. - /// - /// This is the counterpart of [`Self::lock_delegate_dependency`]. It decreases the reference - /// count and refunds the deposit that was charged by [`Self::lock_delegate_dependency`]. - /// - /// # Errors - /// - /// - [`Error::DelegateDependencyNotFound`] - fn unlock_delegate_dependency(&mut self, code_hash: &H256) -> DispatchResult; - - /// Returns the number of locked delegate dependencies. - /// - /// Note: Requires &mut self to access the contract info. - fn locked_delegate_dependencies_count(&mut self) -> usize; - /// Check if running in read-only context. fn is_read_only(&self) -> bool; @@ -1061,23 +1024,33 @@ where let value_transferred = frame.value_transferred; let account_id = &frame.account_id.clone(); - // We need to charge the storage deposit before the initial transfer so that - // it can create the account in case the initial transfer is < ed. + // We need to make sure that the contract's account exists before calling its + // constructor. if entry_point == ExportedFunction::Constructor { // Root origin can't be used to instantiate a contract, so it is safe to assume that // if we reached this point the origin has an associated account. let origin = &self.origin.account_id()?; - frame.nested_storage.charge_instantiate( - origin, - &account_id, - frame.contract_info.get(&account_id), - executable.code_info(), - self.skip_transfer, - )?; + let ed = <Contracts<T>>::min_balance(); + frame.nested_storage.record_charge(&StorageDeposit::Charge(ed)); + if self.skip_transfer { + T::Currency::set_balance(account_id, ed); + } else { + T::Currency::transfer(origin, account_id, ed, Preservation::Preserve)?; + } + + // A consumer is added at account creation and removed it on termination, otherwise + // the runtime could remove the account. As long as a contract exists its + // account must exist. With the consumer, a correct runtime cannot remove the + // account. + <System<T>>::inc_consumers(account_id)?; + // Needs to be incremented before calling into the code so that it is visible // in case of recursion. <System<T>>::inc_account_nonce(caller.account_id()?); + + // The incremented refcount should be visible to the constructor. + <CodeInfo<T>>::increment_refcount(*executable.code_hash())?; } // Every non delegate call or instantiate also optionally transfers the balance. @@ -1094,6 +1067,7 @@ where let contract_address = T::AddressMapper::to_address(account_id); let maybe_caller_address = caller.account_id().map(T::AddressMapper::to_address); + let code_deposit = executable.code_info().deposit(); if_tracing(|tracer| { tracer.enter_child_span( @@ -1128,6 +1102,15 @@ where let frame = self.top_frame_mut(); + // The deposit we charge for a contract depends on the size of the immutable data. + // Hence we need to delay charging the base deposit after execution. + if entry_point == ExportedFunction::Constructor { + let deposit = frame.contract_info().update_base_deposit(code_deposit); + frame + .nested_storage + .charge_deposit(frame.account_id.clone(), StorageDeposit::Charge(deposit)); + } + // The storage deposit is only charged at the end of every call stack. // To make sure that no sub call uses more than it is allowed to, // the limit is manually enforced here. @@ -1137,13 +1120,6 @@ where .enforce_limit(contract) .map_err(|e| ExecError { error: e, origin: ErrorOrigin::Callee })?; - // It is not allowed to terminate a contract inside its constructor. - if entry_point == ExportedFunction::Constructor && - matches!(frame.contract_info, CachedContract::Terminated) - { - return Err(Error::<T>::TerminatedInConstructor.into()); - } - Ok(output) }; @@ -1531,6 +1507,9 @@ where return Err(Error::<T>::TerminatedWhileReentrant.into()); } let frame = self.top_frame_mut(); + if frame.entry_point == ExportedFunction::Constructor { + return Err(Error::<T>::TerminatedInConstructor.into()); + } let info = frame.terminate(); let beneficiary_account = T::AddressMapper::to_account_id(beneficiary); frame.nested_storage.terminate(&info, beneficiary_account); @@ -1539,14 +1518,7 @@ where let account_address = T::AddressMapper::to_address(&frame.account_id); ContractInfoOf::<T>::remove(&account_address); ImmutableDataOf::<T>::remove(&account_address); - Self::decrement_refcount(info.code_hash); - - for (code_hash, deposit) in info.delegate_dependencies() { - Self::decrement_refcount(*code_hash); - frame - .nested_storage - .charge_deposit(frame.account_id.clone(), StorageDeposit::Refund(*deposit)); - } + <CodeInfo<T>>::decrement_refcount(info.code_hash)?; Ok(()) } @@ -1652,6 +1624,10 @@ where self.caller_is_origin() && self.origin == Origin::Root } + fn immutable_data_len(&mut self) -> u32 { + self.top_frame_mut().contract_info().immutable_data_len() + } + fn get_immutable_data(&mut self) -> Result<ImmutableData, DispatchError> { if self.top_frame().entry_point == ExportedFunction::Constructor { return Err(Error::<T>::InvalidImmutableAccess.into()); @@ -1668,17 +1644,12 @@ where } fn set_immutable_data(&mut self, data: ImmutableData) -> Result<(), DispatchError> { - if self.top_frame().entry_point == ExportedFunction::Call { + let frame = self.top_frame_mut(); + if frame.entry_point == ExportedFunction::Call || data.is_empty() { return Err(Error::<T>::InvalidImmutableAccess.into()); } - - let account_id = self.account_id().clone(); - let len = data.len() as u32; - let amount = self.top_frame_mut().contract_info().set_immutable_data_len(len)?; - self.top_frame_mut().nested_storage.charge_deposit(account_id.clone(), amount); - - <ImmutableDataOf<T>>::insert(T::AddressMapper::to_address(&account_id), &data); - + frame.contract_info().set_immutable_data_len(data.len() as u32); + <ImmutableDataOf<T>>::insert(T::AddressMapper::to_address(&frame.account_id), &data); Ok(()) } @@ -1718,6 +1689,13 @@ where self.block_hash(block_number) } + fn block_author(&self) -> Option<AccountIdOf<Self::T>> { + let digest = <frame_system::Pallet<T>>::digest(); + let pre_runtime_digests = digest.logs.iter().filter_map(|d| d.as_pre_runtime()); + + T::FindAuthor::find_author(pre_runtime_digests) + } + fn max_value_size(&self) -> u32 { limits::PAYLOAD_BYTES } @@ -1796,68 +1774,17 @@ where let code_info = CodeInfoOf::<T>::get(hash).ok_or(Error::<T>::CodeNotFound)?; let old_base_deposit = info.storage_base_deposit(); - let new_base_deposit = info.update_base_deposit(&code_info); + let new_base_deposit = info.update_base_deposit(code_info.deposit()); let deposit = StorageDeposit::Charge(new_base_deposit) .saturating_sub(&StorageDeposit::Charge(old_base_deposit)); frame.nested_storage.charge_deposit(frame.account_id.clone(), deposit); - Self::increment_refcount(hash)?; - Self::decrement_refcount(prev_hash); + <CodeInfo<T>>::increment_refcount(hash)?; + <CodeInfo<T>>::decrement_refcount(prev_hash)?; Ok(()) } - fn increment_refcount(code_hash: H256) -> DispatchResult { - <CodeInfoOf<Self::T>>::mutate(code_hash, |existing| -> Result<(), DispatchError> { - if let Some(info) = existing { - *info.refcount_mut() = info.refcount().saturating_add(1); - Ok(()) - } else { - Err(Error::<T>::CodeNotFound.into()) - } - }) - } - - fn decrement_refcount(code_hash: H256) { - <CodeInfoOf<T>>::mutate(code_hash, |existing| { - if let Some(info) = existing { - *info.refcount_mut() = info.refcount().saturating_sub(1); - } - }); - } - - fn lock_delegate_dependency(&mut self, code_hash: H256) -> DispatchResult { - let frame = self.top_frame_mut(); - let info = frame.contract_info.get(&frame.account_id); - ensure!(code_hash != info.code_hash, Error::<T>::CannotAddSelfAsDelegateDependency); - - let code_info = CodeInfoOf::<T>::get(code_hash).ok_or(Error::<T>::CodeNotFound)?; - let deposit = T::CodeHashLockupDepositPercent::get().mul_ceil(code_info.deposit()); - - info.lock_delegate_dependency(code_hash, deposit)?; - Self::increment_refcount(code_hash)?; - frame - .nested_storage - .charge_deposit(frame.account_id.clone(), StorageDeposit::Charge(deposit)); - Ok(()) - } - - fn unlock_delegate_dependency(&mut self, code_hash: &H256) -> DispatchResult { - let frame = self.top_frame_mut(); - let info = frame.contract_info.get(&frame.account_id); - - let deposit = info.unlock_delegate_dependency(code_hash)?; - Self::decrement_refcount(*code_hash); - frame - .nested_storage - .charge_deposit(frame.account_id.clone(), StorageDeposit::Refund(deposit)); - Ok(()) - } - - fn locked_delegate_dependencies_count(&mut self) -> usize { - self.top_frame_mut().contract_info().delegate_dependencies_count() - } - fn is_read_only(&self) -> bool { self.top_frame().read_only } @@ -1932,7 +1859,7 @@ mod tests { #[derive(Clone)] struct MockExecutable { func: Rc<dyn for<'a> Fn(MockCtx<'a>, &Self) -> ExecResult + 'static>, - func_type: ExportedFunction, + constructor: Rc<dyn for<'a> Fn(MockCtx<'a>, &Self) -> ExecResult + 'static>, code_hash: H256, code_info: CodeInfo<Test>, } @@ -1951,6 +1878,39 @@ mod tests { fn insert( func_type: ExportedFunction, f: impl Fn(MockCtx, &MockExecutable) -> ExecResult + 'static, + ) -> H256 { + Loader::mutate(|loader| { + // Generate code hashes from contract index value. + let hash = H256(keccak_256(&loader.counter.to_le_bytes())); + loader.counter += 1; + if func_type == ExportedFunction::Constructor { + loader.map.insert( + hash, + MockExecutable { + func: Rc::new(|_, _| exec_success()), + constructor: Rc::new(f), + code_hash: hash, + code_info: CodeInfo::<Test>::new(ALICE), + }, + ); + } else { + loader.map.insert( + hash, + MockExecutable { + func: Rc::new(f), + constructor: Rc::new(|_, _| exec_success()), + code_hash: hash, + code_info: CodeInfo::<Test>::new(ALICE), + }, + ); + } + hash + }) + } + + fn insert_both( + constructor: impl Fn(MockCtx, &MockExecutable) -> ExecResult + 'static, + call: impl Fn(MockCtx, &MockExecutable) -> ExecResult + 'static, ) -> H256 { Loader::mutate(|loader| { // Generate code hashes from contract index value. @@ -1959,8 +1919,8 @@ mod tests { loader.map.insert( hash, MockExecutable { - func: Rc::new(f), - func_type, + func: Rc::new(call), + constructor: Rc::new(constructor), code_hash: hash, code_info: CodeInfo::<Test>::new(ALICE), }, @@ -1986,9 +1946,6 @@ mod tests { function: ExportedFunction, input_data: Vec<u8>, ) -> ExecResult { - if let Constructor = function { - E::increment_refcount(self.code_hash).unwrap(); - } // # Safety // // We know that we **always** call execute with a `MockStack` in this test. @@ -1999,10 +1956,10 @@ mod tests { // `E: Ext`. However, `MockExecutable` can't be generic over `E` as it would // constitute a cycle. let ext = unsafe { mem::transmute(ext) }; - if function == self.func_type { - (self.func)(MockCtx { ext, input_data }, &self) + if function == ExportedFunction::Constructor { + (self.constructor)(MockCtx { ext, input_data }, &self) } else { - exec_success() + (self.func)(MockCtx { ext, input_data }, &self) } } @@ -3156,7 +3113,7 @@ mod tests { #[test] fn termination_from_instantiate_fails() { let terminate_ch = MockLoader::insert(Constructor, |ctx, _| { - ctx.ext.terminate(&ALICE_ADDR).unwrap(); + ctx.ext.terminate(&ALICE_ADDR)?; exec_success() }); @@ -3184,7 +3141,10 @@ mod tests { Some(&[0; 32]), false, ), - Err(Error::<Test>::TerminatedInConstructor.into()) + Err(ExecError { + error: Error::<Test>::TerminatedInConstructor.into(), + origin: ErrorOrigin::Callee + }) ); assert_eq!(&events(), &[]); @@ -4696,41 +4656,46 @@ mod tests { } #[test] - fn immutable_data_set_works_only_once() { - let dummy_ch = MockLoader::insert(Constructor, move |ctx, _| { - // Calling `set_immutable_data` the first time should work - assert_ok!(ctx.ext.set_immutable_data(vec![0, 1, 2, 3].try_into().unwrap())); - // Calling `set_immutable_data` the second time should error out - assert_eq!( - ctx.ext.set_immutable_data(vec![0, 1, 2, 3].try_into().unwrap()), - Err(Error::<Test>::InvalidImmutableAccess.into()) - ); - exec_success() - }); - let instantiator_ch = MockLoader::insert(Call, { + fn immutable_data_set_overrides() { + let hash = MockLoader::insert_both( move |ctx, _| { - let value = <Test as Config>::Currency::minimum_balance().into(); - ctx.ext - .instantiate(Weight::MAX, U256::MAX, dummy_ch, value, vec![], None) - .unwrap(); - + // Calling `set_immutable_data` the first time should work + assert_ok!(ctx.ext.set_immutable_data(vec![0, 1, 2, 3].try_into().unwrap())); + // Calling `set_immutable_data` the second time overrides the original one + assert_ok!(ctx.ext.set_immutable_data(vec![7, 5].try_into().unwrap())); exec_success() - } - }); + }, + move |ctx, _| { + assert_eq!(ctx.ext.get_immutable_data().unwrap().into_inner(), vec![7, 5]); + exec_success() + }, + ); ExtBuilder::default() .with_code_hashes(MockLoader::code_hashes()) .existential_deposit(15) .build() .execute_with(|| { set_balance(&ALICE, 1000); - set_balance(&BOB, 100); - place_contract(&BOB, instantiator_ch); let origin = Origin::from_account_id(ALICE); let mut storage_meter = storage::meter::Meter::new(&origin, 200, 0).unwrap(); + let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT); + + let addr = MockStack::run_instantiate( + ALICE, + MockExecutable::from_storage(hash, &mut gas_meter).unwrap(), + &mut gas_meter, + &mut storage_meter, + U256::zero(), + vec![], + None, + false, + ) + .unwrap() + .0; MockStack::run_call( origin, - BOB_ADDR, + addr, &mut GasMeter::<Test>::new(GAS_LIMIT), &mut storage_meter, U256::zero(), diff --git a/substrate/frame/revive/src/lib.rs b/substrate/frame/revive/src/lib.rs index 7f4565a9f08847eaa72d01cb5ad78ec06fdb75c4..c54b13c27e902c1fc0c9d99cc1608e3c60dc7d5a 100644 --- a/substrate/frame/revive/src/lib.rs +++ b/substrate/frame/revive/src/lib.rs @@ -42,7 +42,7 @@ pub mod weights; use crate::{ evm::{runtime::GAS_PRICE, GasEncoder, GenericTransaction}, - exec::{AccountIdOf, ExecError, Executable, Ext, Key, Stack as ExecStack}, + exec::{AccountIdOf, ExecError, Executable, Key, Stack as ExecStack}, gas::GasMeter, storage::{meter::Meter as StorageMeter, ContractInfo, DeletionQueueManager}, wasm::{CodeInfo, RuntimeCosts, WasmBlob}, @@ -114,7 +114,7 @@ const LOG_TARGET: &str = "runtime::revive"; #[frame_support::pallet] pub mod pallet { use super::*; - use frame_support::pallet_prelude::*; + use frame_support::{pallet_prelude::*, traits::FindAuthor}; use frame_system::pallet_prelude::*; use sp_core::U256; use sp_runtime::Perbill; @@ -189,6 +189,9 @@ pub mod pallet { #[pallet::no_default_bounds] type ChainExtension: chain_extension::ChainExtension<Self> + Default; + /// Find the author of the current block. + type FindAuthor: FindAuthor<Self::AccountId>; + /// The amount of balance a caller has to pay for each byte of storage. /// /// # Note @@ -208,9 +211,8 @@ pub mod pallet { type DepositPerItem: Get<BalanceOf<Self>>; /// The percentage of the storage deposit that should be held for using a code hash. - /// Instantiating a contract, or calling [`chain_extension::Ext::lock_delegate_dependency`] - /// protects the code from being removed. In order to prevent abuse these actions are - /// protected with a percentage of the code deposit. + /// Instantiating a contract, protects the code from being removed. In order to prevent + /// abuse these actions are protected with a percentage of the code deposit. #[pallet::constant] type CodeHashLockupDepositPercent: Get<Perbill>; @@ -362,6 +364,7 @@ pub mod pallet { type ChainId = ConstU64<0>; type NativeToEthRatio = ConstU32<1>; type EthGasEncoder = (); + type FindAuthor = (); } } @@ -489,6 +492,8 @@ pub mod pallet { AccountAlreadyMapped, /// The transaction used to dry-run a contract is invalid. InvalidGenericTransaction, + /// The refcount of a code either over or underflowed. + RefcountOverOrUnderflow, } /// A reason for the pallet contracts placing a hold on funds. @@ -904,8 +909,8 @@ pub mod pallet { } else { return Err(<Error<T>>::ContractNotFound.into()); }; - <ExecStack<T, WasmBlob<T>>>::increment_refcount(code_hash)?; - <ExecStack<T, WasmBlob<T>>>::decrement_refcount(contract.code_hash); + <CodeInfo<T>>::increment_refcount(code_hash)?; + <CodeInfo<T>>::decrement_refcount(contract.code_hash)?; contract.code_hash = code_hash; Ok(()) }) diff --git a/substrate/frame/revive/src/limits.rs b/substrate/frame/revive/src/limits.rs index f101abf0ea7e9478be157c693b4f251d80af4df7..a4060cf6cc91cf030a869af8abd0bc608b2055ac 100644 --- a/substrate/frame/revive/src/limits.rs +++ b/substrate/frame/revive/src/limits.rs @@ -43,11 +43,8 @@ pub const CALL_STACK_DEPTH: u32 = 5; /// We set it to the same limit that ethereum has. It is unlikely to change. pub const NUM_EVENT_TOPICS: u32 = 4; -/// The maximum number of code hashes a contract can lock. -pub const DELEGATE_DEPENDENCIES: u32 = 32; - /// Maximum size of events (including topics) and storage values. -pub const PAYLOAD_BYTES: u32 = 448; +pub const PAYLOAD_BYTES: u32 = 416; /// The maximum size of the transient storage in bytes. /// diff --git a/substrate/frame/revive/src/storage.rs b/substrate/frame/revive/src/storage.rs index b7156588d44c659243e3bde3a2b8d19968ebe926..a761223aadfdde5e9f8936860d2aa25ba04cfb40 100644 --- a/substrate/frame/revive/src/storage.rs +++ b/substrate/frame/revive/src/storage.rs @@ -22,11 +22,10 @@ pub mod meter; use crate::{ address::AddressMapper, exec::{AccountIdOf, Key}, - limits, storage::meter::Diff, weights::WeightInfo, - BalanceOf, CodeInfo, Config, ContractInfoOf, DeletionQueue, DeletionQueueCounter, Error, - StorageDeposit, TrieId, SENTINEL, + BalanceOf, Config, ContractInfoOf, DeletionQueue, DeletionQueueCounter, Error, TrieId, + SENTINEL, }; use alloc::vec::Vec; use codec::{Decode, Encode, MaxEncodedLen}; @@ -36,18 +35,14 @@ use frame_support::{ weights::{Weight, WeightMeter}, CloneNoBound, DefaultNoBound, }; -use meter::DepositOf; use scale_info::TypeInfo; -use sp_core::{ConstU32, Get, H160}; +use sp_core::{Get, H160}; use sp_io::KillStorageResult; use sp_runtime::{ traits::{Hash, Saturating, Zero}, - BoundedBTreeMap, DispatchError, DispatchResult, RuntimeDebug, + DispatchError, RuntimeDebug, }; -type DelegateDependencyMap<T> = - BoundedBTreeMap<sp_core::H256, BalanceOf<T>, ConstU32<{ limits::DELEGATE_DEPENDENCIES }>>; - /// Information for managing an account and its sub trie abstraction. /// This is the required info to cache for an account. #[derive(Encode, Decode, CloneNoBound, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)] @@ -70,12 +65,6 @@ pub struct ContractInfo<T: Config> { /// We need to store this information separately so it is not used when calculating any refunds /// since the base deposit can only ever be refunded on contract termination. storage_base_deposit: BalanceOf<T>, - /// Map of code hashes and deposit balances. - /// - /// Tracks the code hash and deposit held for locking delegate dependencies. Dependencies added - /// to the map can not be removed from the chain state and can be safely used for delegate - /// calls. - delegate_dependencies: DelegateDependencyMap<T>, /// The size of the immutable data of this contract. immutable_data_len: u32, } @@ -110,18 +99,12 @@ impl<T: Config> ContractInfo<T> { storage_byte_deposit: Zero::zero(), storage_item_deposit: Zero::zero(), storage_base_deposit: Zero::zero(), - delegate_dependencies: Default::default(), immutable_data_len: 0, }; Ok(contract) } - /// Returns the number of locked delegate dependencies. - pub fn delegate_dependencies_count(&self) -> usize { - self.delegate_dependencies.len() - } - /// Associated child trie unique id is built from the hash part of the trie id. pub fn child_trie_info(&self) -> ChildInfo { ChildInfo::new_default(self.trie_id.as_ref()) @@ -240,58 +223,27 @@ impl<T: Config> ContractInfo<T> { /// Sets and returns the contract base deposit. /// /// The base deposit is updated when the `code_hash` of the contract changes, as it depends on - /// the deposit paid to upload the contract's code. - pub fn update_base_deposit(&mut self, code_info: &CodeInfo<T>) -> BalanceOf<T> { - let info_deposit = - Diff { bytes_added: self.encoded_size() as u32, items_added: 1, ..Default::default() } - .update_contract::<T>(None) - .charge_or_zero(); + /// the deposit paid to upload the contract's code. It also depends on the size of immutable + /// storage which is also changed when the code hash of a contract is changed. + pub fn update_base_deposit(&mut self, code_deposit: BalanceOf<T>) -> BalanceOf<T> { + let contract_deposit = Diff { + bytes_added: (self.encoded_size() as u32).saturating_add(self.immutable_data_len), + items_added: if self.immutable_data_len == 0 { 1 } else { 2 }, + ..Default::default() + } + .update_contract::<T>(None) + .charge_or_zero(); // Instantiating the contract prevents its code to be deleted, therefore the base deposit // includes a fraction (`T::CodeHashLockupDepositPercent`) of the original storage deposit // to prevent abuse. - let upload_deposit = T::CodeHashLockupDepositPercent::get().mul_ceil(code_info.deposit()); + let code_deposit = T::CodeHashLockupDepositPercent::get().mul_ceil(code_deposit); - let deposit = info_deposit.saturating_add(upload_deposit); + let deposit = contract_deposit.saturating_add(code_deposit); self.storage_base_deposit = deposit; deposit } - /// Adds a new delegate dependency to the contract. - /// The `amount` is the amount of funds that will be reserved for the dependency. - /// - /// Returns an error if the maximum number of delegate_dependencies is reached or if - /// the delegate dependency already exists. - pub fn lock_delegate_dependency( - &mut self, - code_hash: sp_core::H256, - amount: BalanceOf<T>, - ) -> DispatchResult { - self.delegate_dependencies - .try_insert(code_hash, amount) - .map_err(|_| Error::<T>::MaxDelegateDependenciesReached)? - .map_or(Ok(()), |_| Err(Error::<T>::DelegateDependencyAlreadyExists)) - .map_err(Into::into) - } - - /// Removes the delegate dependency from the contract and returns the deposit held for this - /// dependency. - /// - /// Returns an error if the entry doesn't exist. - pub fn unlock_delegate_dependency( - &mut self, - code_hash: &sp_core::H256, - ) -> Result<BalanceOf<T>, DispatchError> { - self.delegate_dependencies - .remove(code_hash) - .ok_or(Error::<T>::DelegateDependencyNotFound.into()) - } - - /// Returns the delegate_dependencies of the contract. - pub fn delegate_dependencies(&self) -> &DelegateDependencyMap<T> { - &self.delegate_dependencies - } - /// Push a contract's trie to the deletion queue for lazy removal. /// /// You must make sure that the contract is also removed when queuing the trie for deletion. @@ -367,27 +319,8 @@ impl<T: Config> ContractInfo<T> { } /// Set the number of immutable bytes of this contract. - /// - /// On success, returns the storage deposit to be charged. - /// - /// Returns `Err(InvalidImmutableAccess)` if: - /// - The immutable bytes of this contract are not 0. This indicates that the immutable data - /// have already been set; it is only valid to set the immutable data exactly once. - /// - The provided `immutable_data_len` value was 0; it is invalid to set empty immutable data. - pub fn set_immutable_data_len( - &mut self, - immutable_data_len: u32, - ) -> Result<DepositOf<T>, DispatchError> { - if self.immutable_data_len != 0 || immutable_data_len == 0 { - return Err(Error::<T>::InvalidImmutableAccess.into()); - } - + pub fn set_immutable_data_len(&mut self, immutable_data_len: u32) { self.immutable_data_len = immutable_data_len; - - let amount = T::DepositPerByte::get() - .saturating_mul(immutable_data_len.into()) - .saturating_add(T::DepositPerItem::get()); - Ok(StorageDeposit::Charge(amount)) } } diff --git a/substrate/frame/revive/src/storage/meter.rs b/substrate/frame/revive/src/storage/meter.rs index cd390c86f63ae94a30d065def82e628a0091b653..ddd4a3bae87f0d65614132fde12cd5ee4f301505 100644 --- a/substrate/frame/revive/src/storage/meter.rs +++ b/substrate/frame/revive/src/storage/meter.rs @@ -18,8 +18,8 @@ //! This module contains functions to meter the storage deposit. use crate::{ - storage::ContractInfo, AccountIdOf, BalanceOf, CodeInfo, Config, Error, HoldReason, Inspect, - Origin, Pallet, StorageDeposit as Deposit, System, LOG_TARGET, + storage::ContractInfo, AccountIdOf, BalanceOf, Config, Error, HoldReason, Inspect, Origin, + StorageDeposit as Deposit, System, LOG_TARGET, }; use alloc::vec::Vec; use core::{fmt::Debug, marker::PhantomData}; @@ -404,49 +404,26 @@ impl<T: Config, E: Ext<T>> RawMeter<T, E, Nested> { }; } - /// Adds a deposit charge. + /// Adds a charge without recording it in the contract info. /// /// Use this method instead of [`Self::charge`] when the charge is not the result of a storage - /// change. This is the case when a `delegate_dependency` is added or removed, or when the - /// `code_hash` is updated. [`Self::charge`] cannot be used here because we keep track of the - /// deposit charge separately from the storage charge. + /// change within the contract's child trie. This is the case when when the `code_hash` is + /// updated. [`Self::charge`] cannot be used here because we keep track of the deposit charge + /// separately from the storage charge. + /// + /// If this functions is used the amount of the charge has to be stored by the caller somewhere + /// alese in order to be able to refund it. pub fn charge_deposit(&mut self, contract: T::AccountId, amount: DepositOf<T>) { - self.total_deposit = self.total_deposit.saturating_add(&amount); + self.record_charge(&amount); self.charges.push(Charge { contract, amount, state: ContractState::Alive }); } - /// Charges from `origin` a storage deposit for contract instantiation. + /// Record a charge that has taken place externally. /// - /// This immediately transfers the balance in order to create the account. - pub fn charge_instantiate( - &mut self, - origin: &T::AccountId, - contract: &T::AccountId, - contract_info: &mut ContractInfo<T>, - code_info: &CodeInfo<T>, - skip_transfer: bool, - ) -> Result<(), DispatchError> { - debug_assert!(matches!(self.contract_state(), ContractState::Alive)); - - // We need to make sure that the contract's account exists. - let ed = Pallet::<T>::min_balance(); - self.total_deposit = Deposit::Charge(ed); - if skip_transfer { - T::Currency::set_balance(contract, ed); - } else { - T::Currency::transfer(origin, contract, ed, Preservation::Preserve)?; - } - - // A consumer is added at account creation and removed it on termination, otherwise the - // runtime could remove the account. As long as a contract exists its account must exist. - // With the consumer, a correct runtime cannot remove the account. - System::<T>::inc_consumers(contract)?; - - let deposit = contract_info.update_base_deposit(&code_info); - let deposit = Deposit::Charge(deposit); - - self.charge_deposit(contract.clone(), deposit); - Ok(()) + /// This will not perform a charge. It just records it to reflect it in the + /// total amount of storage required for a transaction. + pub fn record_charge(&mut self, amount: &DepositOf<T>) { + self.total_deposit = self.total_deposit.saturating_add(&amount); } /// Call to tell the meter that the currently executing contract was terminated. @@ -660,7 +637,6 @@ mod tests { storage_byte_deposit: info.bytes_deposit, storage_item_deposit: info.items_deposit, storage_base_deposit: Default::default(), - delegate_dependencies: Default::default(), immutable_data_len: info.immutable_data_len, } } diff --git a/substrate/frame/revive/src/tests.rs b/substrate/frame/revive/src/tests.rs index d8b60e38da5efe3201c1cddc229292428130677b..adbbb752be6e80deaa448487bcbbe44def7bf3e5 100644 --- a/substrate/frame/revive/src/tests.rs +++ b/substrate/frame/revive/src/tests.rs @@ -28,7 +28,6 @@ use crate::{ evm::{runtime::GAS_PRICE, CallTrace, CallTracer, CallType, GenericTransaction}, exec::Key, limits, - primitives::CodeUploadReturnValue, storage::DeletionQueueManager, test_utils::*, tests::test_utils::{get_contract, get_contract_checked}, @@ -52,12 +51,12 @@ use frame_support::{ traits::{ fungible::{BalancedHold, Inspect, Mutate, MutateHold}, tokens::Preservation, - ConstU32, ConstU64, Contains, OnIdle, OnInitialize, StorageVersion, + ConstU32, ConstU64, Contains, FindAuthor, OnIdle, OnInitialize, StorageVersion, }, weights::{constants::WEIGHT_REF_TIME_PER_SECOND, FixedFee, IdentityFee, Weight, WeightMeter}, }; use frame_system::{EventRecord, Phase}; -use pallet_revive_fixtures::{bench::dummy_unique, compile_module}; +use pallet_revive_fixtures::compile_module; use pallet_revive_uapi::ReturnErrorCode as RuntimeReturnCode; use pallet_transaction_payment::{ConstFeeMultiplier, Multiplier}; use pretty_assertions::{assert_eq, assert_ne}; @@ -100,7 +99,7 @@ macro_rules! assert_refcount { } pub mod test_utils { - use super::{Contracts, DepositPerByte, DepositPerItem, Test}; + use super::{CodeHashLockupDepositPercent, Contracts, DepositPerByte, DepositPerItem, Test}; use crate::{ address::AddressMapper, exec::AccountIdOf, BalanceOf, CodeInfo, CodeInfoOf, Config, ContractInfo, ContractInfoOf, PristineCode, @@ -138,20 +137,26 @@ pub mod test_utils { pub fn get_code_deposit(code_hash: &sp_core::H256) -> BalanceOf<Test> { crate::CodeInfoOf::<Test>::get(code_hash).unwrap().deposit() } - pub fn contract_info_storage_deposit(addr: &H160) -> BalanceOf<Test> { + pub fn lockup_deposit(code_hash: &sp_core::H256) -> BalanceOf<Test> { + CodeHashLockupDepositPercent::get().mul_ceil(get_code_deposit(code_hash)).into() + } + pub fn contract_base_deposit(addr: &H160) -> BalanceOf<Test> { let contract_info = self::get_contract(&addr); let info_size = contract_info.encoded_size() as u64; - let info_deposit = DepositPerByte::get() + let code_deposit = CodeHashLockupDepositPercent::get() + .mul_ceil(get_code_deposit(&contract_info.code_hash)); + let deposit = DepositPerByte::get() .saturating_mul(info_size) - .saturating_add(DepositPerItem::get()); + .saturating_add(DepositPerItem::get()) + .saturating_add(code_deposit); let immutable_size = contract_info.immutable_data_len() as u64; if immutable_size > 0 { let immutable_deposit = DepositPerByte::get() .saturating_mul(immutable_size) .saturating_add(DepositPerItem::get()); - info_deposit.saturating_add(immutable_deposit) + deposit.saturating_add(immutable_deposit) } else { - info_deposit + deposit } } pub fn expected_deposit(code_len: usize) -> u64 { @@ -435,7 +440,7 @@ impl pallet_dummy::Config for Test {} parameter_types! { pub static DepositPerByte: BalanceOf<Test> = 1; pub const DepositPerItem: BalanceOf<Test> = 2; - pub static CodeHashLockupDepositPercent: Perbill = Perbill::from_percent(0); + pub const CodeHashLockupDepositPercent: Perbill = Perbill::from_percent(30); pub static ChainId: u64 = 448; } @@ -506,6 +511,15 @@ parameter_types! { pub static UnstableInterface: bool = true; } +impl FindAuthor<<Test as frame_system::Config>::AccountId> for Test { + fn find_author<'a, I>(_digests: I) -> Option<<Test as frame_system::Config>::AccountId> + where + I: 'a + IntoIterator<Item = (frame_support::ConsensusEngineId, &'a [u8])>, + { + Some(EVE) + } +} + #[derive_impl(crate::config_preludes::TestDefaultConfig)] impl Config for Test { type Time = Timestamp; @@ -521,6 +535,7 @@ impl Config for Test { type InstantiateOrigin = EnsureAccount<Self, InstantiateAccount>; type CodeHashLockupDepositPercent = CodeHashLockupDepositPercent; type ChainId = ChainId; + type FindAuthor = Test; } impl TryFrom<RuntimeCall> for crate::Call<Test> { @@ -1187,7 +1202,7 @@ fn transfer_expendable_cannot_kill_account() { assert_eq!( test_utils::get_balance_on_hold(&HoldReason::StorageDepositReserve.into(), &account), - test_utils::contract_info_storage_deposit(&addr) + test_utils::contract_base_deposit(&addr) ); // Some or the total balance is held, so it can't be transferred. @@ -1229,7 +1244,7 @@ fn cannot_self_destruct_through_draining() { // Make sure the account wasn't remove by sending all free balance away. assert_eq!( <Test as Config>::Currency::total_balance(&account), - value + test_utils::contract_info_storage_deposit(&addr) + min_balance, + value + test_utils::contract_base_deposit(&addr) + min_balance, ); }); } @@ -1243,7 +1258,7 @@ fn cannot_self_destruct_through_storage_refund_after_price_change() { // Instantiate the BOB contract. let contract = builder::bare_instantiate(Code::Upload(wasm)).build_and_unwrap_contract(); - let info_deposit = test_utils::contract_info_storage_deposit(&contract.addr); + let info_deposit = test_utils::contract_base_deposit(&contract.addr); // Check that the contract has been instantiated and has the minimum balance assert_eq!(get_contract(&contract.addr).total_deposit(), info_deposit); @@ -1584,13 +1599,13 @@ fn instantiate_return_code() { // Contract has only the minimal balance so any transfer will fail. <Test as Config>::Currency::set_balance(&contract.account_id, min_balance); let result = builder::bare_call(contract.addr) - .data(callee_hash.clone()) + .data(callee_hash.iter().chain(&0u32.to_le_bytes()).cloned().collect()) .build_and_unwrap_result(); assert_return_code!(result, RuntimeReturnCode::TransferFailed); // Contract has enough balance but the passed code hash is invalid <Test as Config>::Currency::set_balance(&contract.account_id, min_balance + 10_000); - let result = builder::bare_call(contract.addr).data(vec![0; 33]).build(); + let result = builder::bare_call(contract.addr).data(vec![0; 36]).build(); assert_err!(result.result, <Error<Test>>::CodeNotFound); // Contract has enough balance but callee reverts because "1" is passed. @@ -1604,6 +1619,18 @@ fn instantiate_return_code() { .data(callee_hash.iter().chain(&2u32.to_le_bytes()).cloned().collect()) .build_and_unwrap_result(); assert_return_code!(result, RuntimeReturnCode::CalleeTrapped); + + // Contract instantiation succeeds + let result = builder::bare_call(contract.addr) + .data(callee_hash.iter().chain(&0u32.to_le_bytes()).cloned().collect()) + .build_and_unwrap_result(); + assert_return_code!(result, 0); + + // Contract instantiation fails because the same salt is being used again. + let result = builder::bare_call(contract.addr) + .data(callee_hash.iter().chain(&0u32.to_le_bytes()).cloned().collect()) + .build_and_unwrap_result(); + assert_return_code!(result, RuntimeReturnCode::DuplicateContractAddress); }); } @@ -2572,7 +2599,7 @@ fn instantiate_with_zero_balance_works() { assert_eq!(<Test as Config>::Currency::free_balance(&account_id), min_balance); assert_eq!( <Test as Config>::Currency::total_balance(&account_id), - min_balance + test_utils::contract_info_storage_deposit(&addr) + min_balance + test_utils::contract_base_deposit(&addr) ); assert_eq!( @@ -2629,7 +2656,7 @@ fn instantiate_with_below_existential_deposit_works() { assert_eq!(<Test as Config>::Currency::free_balance(&account_id), min_balance + value); assert_eq!( <Test as Config>::Currency::total_balance(&account_id), - min_balance + value + test_utils::contract_info_storage_deposit(&addr) + min_balance + value + test_utils::contract_base_deposit(&addr) ); assert_eq!( @@ -2682,7 +2709,7 @@ fn storage_deposit_works() { let Contract { addr, account_id } = builder::bare_instantiate(Code::Upload(wasm)).build_and_unwrap_contract(); - let mut deposit = test_utils::contract_info_storage_deposit(&addr); + let mut deposit = test_utils::contract_base_deposit(&addr); // Drop previous events initialize_block(2); @@ -2744,7 +2771,7 @@ fn storage_deposit_callee_works() { assert_eq!(test_utils::get_balance(&account_id), min_balance); assert_eq!( callee.total_deposit(), - deposit + test_utils::contract_info_storage_deposit(&addr_callee) + deposit + test_utils::contract_base_deposit(&addr_callee) ); }); } @@ -2828,7 +2855,7 @@ fn slash_cannot_kill_account() { // Drop previous events initialize_block(2); - let info_deposit = test_utils::contract_info_storage_deposit(&addr); + let info_deposit = test_utils::contract_base_deposit(&addr); assert_eq!( test_utils::get_balance_on_hold(&HoldReason::StorageDepositReserve.into(), &account_id), @@ -2967,7 +2994,7 @@ fn storage_deposit_limit_is_enforced() { let Contract { addr, account_id } = builder::bare_instantiate(Code::Upload(wasm)).build_and_unwrap_contract(); - let info_deposit = test_utils::contract_info_storage_deposit(&addr); + let info_deposit = test_utils::contract_base_deposit(&addr); // Check that the BOB contract has been instantiated and has the minimum balance assert_eq!(get_contract(&addr).total_deposit(), info_deposit); assert_eq!( @@ -3080,7 +3107,7 @@ fn deposit_limit_in_nested_calls() { // Require more than the sender's balance. // Limit the sub call to little balance so it should fail in there let ret = builder::bare_call(addr_caller) - .data((448, &addr_callee, U256::from(1u64)).encode()) + .data((416, &addr_callee, U256::from(1u64)).encode()) .build_and_unwrap_result(); assert_return_code!(ret, RuntimeReturnCode::OutOfResources); @@ -3113,73 +3140,82 @@ fn deposit_limit_in_nested_instantiate() { .data(vec![0, 0, 0, 0]) .build_and_unwrap_contract(); - let callee_info_len = ContractInfoOf::<Test>::get(&addr).unwrap().encoded_size() as u64; - - // We don't set a special deposit limit for the nested instantiation. + // This is the deposit we expect to be charged just for instantiatiting the callee. // - // The deposit limit set for the parent is insufficient for the instantiation, which - // requires: - // - callee_info_len + 2 for storing the new contract info, - // - ED for deployed contract account, + // - callee_info_len + 2 for storing the new contract info + // - the deposit for depending on a code hash + // - ED for deployed contract account // - 2 for the storage item of 0 bytes being created in the callee constructor - // or (callee_info_len + 2 + ED + 2) Balance in total. + let callee_min_deposit = { + let callee_info_len = ContractInfoOf::<Test>::get(&addr).unwrap().encoded_size() as u64; + let code_deposit = test_utils::lockup_deposit(&code_hash_callee); + callee_info_len + code_deposit + 2 + ED + 2 + }; + + // The parent just stores an item of the passed size so at least + // we need to pay for the item itself. + let caller_min_deposit = callee_min_deposit + 2; + + // Fail in callee. // - // Provided the limit is set to be 1 Balance less, - // this call should fail on the return from the caller contract. + // We still fail in the sub call because we enforce limits on return from a contract. + // Sub calls return first to they are checked first. let ret = builder::bare_call(addr_caller) .origin(RuntimeOrigin::signed(BOB)) - .storage_deposit_limit(DepositLimit::Balance(callee_info_len + 2 + ED + 1)) - .data((0u32, &code_hash_callee, &U256::MAX.to_little_endian()).encode()) + .storage_deposit_limit(DepositLimit::Balance(0)) + .data((&code_hash_callee, 100u32, &U256::MAX.to_little_endian()).encode()) .build_and_unwrap_result(); assert_return_code!(ret, RuntimeReturnCode::OutOfResources); // The charges made on instantiation should be rolled back. assert_eq!(<Test as Config>::Currency::free_balance(&BOB), 1_000_000); - // Now we give enough limit for the instantiation itself, but require for 1 more storage - // byte in the constructor. Hence +1 Balance to the limit is needed. This should fail on - // the return from constructor. + // Fail in the caller. + // + // For that we need to supply enough storage deposit so that the sub call + // succeeds but the parent call runs out of storage. let ret = builder::bare_call(addr_caller) .origin(RuntimeOrigin::signed(BOB)) - .storage_deposit_limit(DepositLimit::Balance(callee_info_len + 2 + ED + 2)) - .data((1u32, &code_hash_callee, U256::from(0u64)).encode()) - .build_and_unwrap_result(); - assert_return_code!(ret, RuntimeReturnCode::OutOfResources); + .storage_deposit_limit(DepositLimit::Balance(callee_min_deposit)) + .data((&code_hash_callee, 0u32, &U256::MAX.to_little_endian()).encode()) + .build(); + assert_err!(ret.result, <Error<Test>>::StorageDepositLimitExhausted); // The charges made on the instantiation should be rolled back. assert_eq!(<Test as Config>::Currency::free_balance(&BOB), 1_000_000); - // Now we set enough limit in parent call, but an insufficient limit for child - // instantiate. This should fail during the charging for the instantiation in - // `RawMeter::charge_instantiate()` + // Fail in the callee with bytes. + // + // Same as above but stores one byte in both caller and callee. let ret = builder::bare_call(addr_caller) .origin(RuntimeOrigin::signed(BOB)) - .storage_deposit_limit(DepositLimit::Balance(callee_info_len + 2 + ED + 2)) - .data((0u32, &code_hash_callee, U256::from(callee_info_len + 2 + ED + 1)).encode()) + .storage_deposit_limit(DepositLimit::Balance(caller_min_deposit + 1)) + .data((&code_hash_callee, 1u32, U256::from(callee_min_deposit)).encode()) .build_and_unwrap_result(); assert_return_code!(ret, RuntimeReturnCode::OutOfResources); // The charges made on the instantiation should be rolled back. assert_eq!(<Test as Config>::Currency::free_balance(&BOB), 1_000_000); - // Same as above but requires for single added storage - // item of 1 byte to be covered by the limit, which implies 3 more Balance. - // Now we set enough limit for the parent call, but insufficient limit for child - // instantiate. This should fail right after the constructor execution. + // Fail in the caller with bytes. + // + // Same as above but stores one byte in both caller and callee. let ret = builder::bare_call(addr_caller) .origin(RuntimeOrigin::signed(BOB)) - .storage_deposit_limit(DepositLimit::Balance(callee_info_len + 2 + ED + 3)) // enough parent limit - .data((1u32, &code_hash_callee, U256::from(callee_info_len + 2 + ED + 2)).encode()) - .build_and_unwrap_result(); - assert_return_code!(ret, RuntimeReturnCode::OutOfResources); + .storage_deposit_limit(DepositLimit::Balance(callee_min_deposit + 1)) + .data((&code_hash_callee, 1u32, U256::from(callee_min_deposit + 1)).encode()) + .build(); + assert_err!(ret.result, <Error<Test>>::StorageDepositLimitExhausted); // The charges made on the instantiation should be rolled back. assert_eq!(<Test as Config>::Currency::free_balance(&BOB), 1_000_000); // Set enough deposit limit for the child instantiate. This should succeed. let result = builder::bare_call(addr_caller) .origin(RuntimeOrigin::signed(BOB)) - .storage_deposit_limit((callee_info_len + 2 + ED + 4 + 2).into()) - .data((1u32, &code_hash_callee, U256::from(callee_info_len + 2 + ED + 3 + 2)).encode()) + .storage_deposit_limit((caller_min_deposit + 2).into()) + .data((&code_hash_callee, 1u32, U256::from(callee_min_deposit + 1)).encode()) .build(); let returned = result.result.unwrap(); + assert!(!returned.did_revert()); + // All balance of the caller except ED has been transferred to the callee. // No deposit has been taken from it. assert_eq!(<Test as Config>::Currency::free_balance(&caller_id), ED); @@ -3189,17 +3225,12 @@ fn deposit_limit_in_nested_instantiate() { // 10_000 should be sent to callee from the caller contract, plus ED to be sent from the // origin. assert_eq!(<Test as Config>::Currency::free_balance(&callee_account_id), 10_000 + ED); - // The origin should be charged with: - // - callee instantiation deposit = (callee_info_len + 2) - // - callee account ED - // - for writing an item of 1 byte to storage = 3 Balance - // - Immutable data storage item deposit + // The origin should be charged with what the outer call consumed assert_eq!( <Test as Config>::Currency::free_balance(&BOB), - 1_000_000 - (callee_info_len + 2 + ED + 3) + 1_000_000 - (caller_min_deposit + 2), ); - // Check that deposit due to be charged still includes these 3 Balance - assert_eq!(result.storage_deposit.charge_or_zero(), (callee_info_len + 2 + ED + 3)) + assert_eq!(result.storage_deposit.charge_or_zero(), (caller_min_deposit + 2)) }); } @@ -3216,7 +3247,7 @@ fn deposit_limit_honors_liquidity_restrictions() { let Contract { addr, account_id } = builder::bare_instantiate(Code::Upload(wasm)).build_and_unwrap_contract(); - let info_deposit = test_utils::contract_info_storage_deposit(&addr); + let info_deposit = test_utils::contract_base_deposit(&addr); // Check that the contract has been instantiated and has the minimum balance assert_eq!(get_contract(&addr).total_deposit(), info_deposit); assert_eq!( @@ -3255,7 +3286,7 @@ fn deposit_limit_honors_existential_deposit() { let Contract { addr, account_id } = builder::bare_instantiate(Code::Upload(wasm)).build_and_unwrap_contract(); - let info_deposit = test_utils::contract_info_storage_deposit(&addr); + let info_deposit = test_utils::contract_base_deposit(&addr); // Check that the contract has been instantiated and has the minimum balance assert_eq!(get_contract(&addr).total_deposit(), info_deposit); @@ -3289,7 +3320,7 @@ fn deposit_limit_honors_min_leftover() { let Contract { addr, account_id } = builder::bare_instantiate(Code::Upload(wasm)).build_and_unwrap_contract(); - let info_deposit = test_utils::contract_info_storage_deposit(&addr); + let info_deposit = test_utils::contract_base_deposit(&addr); // Check that the contract has been instantiated and has the minimum balance and the // storage deposit @@ -3316,195 +3347,11 @@ fn deposit_limit_honors_min_leftover() { }); } -#[test] -fn locking_delegate_dependency_works() { - // set hash lock up deposit to 30%, to test deposit calculation. - CODE_HASH_LOCKUP_DEPOSIT_PERCENT.with(|c| *c.borrow_mut() = Perbill::from_percent(30)); - - let (wasm_caller, self_code_hash) = compile_module("locking_delegate_dependency").unwrap(); - let callee_codes: Vec<_> = - (0..limits::DELEGATE_DEPENDENCIES + 1).map(|idx| dummy_unique(idx)).collect(); - let callee_hashes: Vec<_> = callee_codes - .iter() - .map(|c| sp_core::H256(sp_io::hashing::keccak_256(c))) - .collect(); - - let hash2addr = |code_hash: &H256| { - let mut addr = H160::zero(); - addr.as_bytes_mut().copy_from_slice(&code_hash.as_ref()[..20]); - addr - }; - - // Define inputs with various actions to test locking / unlocking delegate_dependencies. - // See the contract for more details. - let noop_input = (0u32, callee_hashes[0]); - let lock_delegate_dependency_input = (1u32, callee_hashes[0]); - let unlock_delegate_dependency_input = (2u32, callee_hashes[0]); - let terminate_input = (3u32, callee_hashes[0]); - - // Instantiate the caller contract with the given input. - let instantiate = |input: &(u32, H256)| { - let (action, code_hash) = input; - builder::bare_instantiate(Code::Upload(wasm_caller.clone())) - .origin(RuntimeOrigin::signed(ALICE_FALLBACK)) - .data((action, hash2addr(code_hash), code_hash).encode()) - .build() - }; - - // Call contract with the given input. - let call = |addr_caller: &H160, input: &(u32, H256)| { - let (action, code_hash) = input; - builder::bare_call(*addr_caller) - .origin(RuntimeOrigin::signed(ALICE_FALLBACK)) - .data((action, hash2addr(code_hash), code_hash).encode()) - .build() - }; - const ED: u64 = 2000; - ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { - let _ = Balances::set_balance(&ALICE_FALLBACK, 1_000_000); - - // Instantiate with lock_delegate_dependency should fail since the code is not yet on - // chain. - assert_err!( - instantiate(&lock_delegate_dependency_input).result, - Error::<Test>::CodeNotFound - ); - - // Upload all the delegated codes (they all have the same size) - let mut deposit = Default::default(); - for code in callee_codes.iter() { - let CodeUploadReturnValue { deposit: deposit_per_code, code_hash } = - Contracts::bare_upload_code( - RuntimeOrigin::signed(ALICE_FALLBACK), - code.clone(), - deposit_limit::<Test>(), - ) - .unwrap(); - deposit = deposit_per_code; - // Mock contract info by using first 20 bytes of code_hash as address. - let addr = hash2addr(&code_hash); - ContractInfoOf::<Test>::set(&addr, ContractInfo::new(&addr, 0, code_hash).ok()); - } - - // Instantiate should now work. - let addr_caller = instantiate(&lock_delegate_dependency_input).result.unwrap().addr; - let caller_account_id = <Test as Config>::AddressMapper::to_account_id(&addr_caller); - - // There should be a dependency and a deposit. - let contract = test_utils::get_contract(&addr_caller); - - let dependency_deposit = &CodeHashLockupDepositPercent::get().mul_ceil(deposit); - assert_eq!( - contract.delegate_dependencies().get(&callee_hashes[0]), - Some(dependency_deposit) - ); - assert_eq!( - test_utils::get_balance_on_hold( - &HoldReason::StorageDepositReserve.into(), - &caller_account_id - ), - dependency_deposit + contract.storage_base_deposit() - ); - - // Removing the code should fail, since we have added a dependency. - assert_err!( - Contracts::remove_code(RuntimeOrigin::signed(ALICE_FALLBACK), callee_hashes[0]), - <Error<Test>>::CodeInUse - ); - - // Locking an already existing dependency should fail. - assert_err!( - call(&addr_caller, &lock_delegate_dependency_input).result, - Error::<Test>::DelegateDependencyAlreadyExists - ); - - // Locking self should fail. - assert_err!( - builder::bare_call(addr_caller) - .origin(RuntimeOrigin::signed(ALICE_FALLBACK)) - .data((1u32, &addr_caller, self_code_hash).encode()) - .build() - .result, - Error::<Test>::CannotAddSelfAsDelegateDependency - ); - - // Locking more than the maximum allowed delegate_dependencies should fail. - for hash in &callee_hashes[1..callee_hashes.len() - 1] { - call(&addr_caller, &(1u32, *hash)).result.unwrap(); - } - assert_err!( - call(&addr_caller, &(1u32, *callee_hashes.last().unwrap())).result, - Error::<Test>::MaxDelegateDependenciesReached - ); - - // Unlocking all dependency should work. - for hash in &callee_hashes[..callee_hashes.len() - 1] { - call(&addr_caller, &(2u32, *hash)).result.unwrap(); - } - - // Dependency should be removed, and deposit should be returned. - let contract = test_utils::get_contract(&addr_caller); - assert!(contract.delegate_dependencies().is_empty()); - assert_eq!( - test_utils::get_balance_on_hold( - &HoldReason::StorageDepositReserve.into(), - &caller_account_id - ), - contract.storage_base_deposit() - ); - - // Removing a nonexistent dependency should fail. - assert_err!( - call(&addr_caller, &unlock_delegate_dependency_input).result, - Error::<Test>::DelegateDependencyNotFound - ); - - // Locking a dependency with a storage limit too low should fail. - assert_err!( - builder::bare_call(addr_caller) - .storage_deposit_limit((dependency_deposit - 1).into()) - .data((1u32, hash2addr(&callee_hashes[0]), callee_hashes[0]).encode()) - .build() - .result, - Error::<Test>::StorageDepositLimitExhausted - ); - - // Since we unlocked the dependency we should now be able to remove the code. - assert_ok!(Contracts::remove_code(RuntimeOrigin::signed(ALICE_FALLBACK), callee_hashes[0])); - - // Calling should fail since the delegated contract is not on chain anymore. - assert_err!(call(&addr_caller, &noop_input).result, Error::<Test>::CodeNotFound); - - // Add the dependency back. - Contracts::upload_code( - RuntimeOrigin::signed(ALICE_FALLBACK), - callee_codes[0].clone(), - deposit_limit::<Test>(), - ) - .unwrap(); - call(&addr_caller, &lock_delegate_dependency_input).result.unwrap(); - - // Call terminate should work, and return the deposit. - let balance_before = test_utils::get_balance(&ALICE_FALLBACK); - assert_ok!(call(&addr_caller, &terminate_input).result); - assert_eq!( - test_utils::get_balance(&ALICE_FALLBACK), - ED + balance_before + contract.storage_base_deposit() + dependency_deposit - ); - - // Terminate should also remove the dependency, so we can remove the code. - assert_ok!(Contracts::remove_code(RuntimeOrigin::signed(ALICE_FALLBACK), callee_hashes[0])); - }); -} - #[test] fn native_dependency_deposit_works() { let (wasm, code_hash) = compile_module("set_code_hash").unwrap(); let (dummy_wasm, dummy_code_hash) = compile_module("dummy").unwrap(); - // Set hash lock up deposit to 30%, to test deposit calculation. - CODE_HASH_LOCKUP_DEPOSIT_PERCENT.with(|c| *c.borrow_mut() = Perbill::from_percent(30)); - // Test with both existing and uploaded code for code in [Code::Upload(wasm.clone()), Code::Existing(code_hash)] { ExtBuilder::default().build().execute_with(|| { @@ -3538,33 +3385,34 @@ fn native_dependency_deposit_works() { let addr = res.result.unwrap().addr; let account_id = <Test as Config>::AddressMapper::to_account_id(&addr); - let base_deposit = test_utils::contract_info_storage_deposit(&addr); + let base_deposit = test_utils::contract_base_deposit(&addr); let upload_deposit = test_utils::get_code_deposit(&code_hash); let extra_deposit = add_upload_deposit.then(|| upload_deposit).unwrap_or_default(); - // Check initial storage_deposit - // The base deposit should be: contract_info_storage_deposit + 30% * deposit - let deposit = - extra_deposit + base_deposit + lockup_deposit_percent.mul_ceil(upload_deposit); - - assert_eq!(res.storage_deposit.charge_or_zero(), deposit + Contracts::min_balance()); + assert_eq!( + res.storage_deposit.charge_or_zero(), + extra_deposit + base_deposit + Contracts::min_balance() + ); // call set_code_hash builder::bare_call(addr) .data(dummy_code_hash.encode()) .build_and_unwrap_result(); - // Check updated storage_deposit - let code_deposit = test_utils::get_code_deposit(&dummy_code_hash); - let deposit = base_deposit + lockup_deposit_percent.mul_ceil(code_deposit); - assert_eq!(test_utils::get_contract(&addr).storage_base_deposit(), deposit); + // Check updated storage_deposit due to code size changes + let deposit_diff = lockup_deposit_percent + .mul_ceil(test_utils::get_code_deposit(&code_hash)) - + lockup_deposit_percent.mul_ceil(test_utils::get_code_deposit(&dummy_code_hash)); + let new_base_deposit = test_utils::contract_base_deposit(&addr); + assert_ne!(deposit_diff, 0); + assert_eq!(base_deposit - new_base_deposit, deposit_diff); assert_eq!( test_utils::get_balance_on_hold( &HoldReason::StorageDepositReserve.into(), &account_id ), - deposit + new_base_deposit ); }); } @@ -3595,6 +3443,21 @@ fn block_hash_works() { }); } +#[test] +fn block_author_works() { + let (code, _) = compile_module("block_author").unwrap(); + + ExtBuilder::default().existential_deposit(1).build().execute_with(|| { + let _ = <Test as Config>::Currency::set_balance(&ALICE, 1_000_000); + + let Contract { addr, .. } = + builder::bare_instantiate(Code::Upload(code)).build_and_unwrap_contract(); + + // The fixture asserts the input to match the find_author API method output. + assert_ok!(builder::call(addr).data(EVE_ADDR.encode()).build()); + }); +} + #[test] fn root_cannot_upload_code() { let (wasm, _) = compile_module("dummy").unwrap(); @@ -4158,15 +4021,21 @@ fn immutable_data_works() { .data(data.to_vec()) .build_and_unwrap_contract(); + let contract = test_utils::get_contract(&addr); + let account = <Test as Config>::AddressMapper::to_account_id(&addr); + let actual_deposit = + test_utils::get_balance_on_hold(&HoldReason::StorageDepositReserve.into(), &account); + + assert_eq!(contract.immutable_data_len(), data.len() as u32); + // Storing immmutable data charges storage deposit; verify it explicitly. + assert_eq!(actual_deposit, test_utils::contract_base_deposit(&addr)); + + // make sure it is also recorded in the base deposit assert_eq!( - test_utils::get_balance_on_hold( - &HoldReason::StorageDepositReserve.into(), - &<Test as Config>::AddressMapper::to_account_id(&addr) - ), - test_utils::contract_info_storage_deposit(&addr) + test_utils::get_balance_on_hold(&HoldReason::StorageDepositReserve.into(), &account), + contract.storage_base_deposit(), ); - assert_eq!(test_utils::get_contract(&addr).immutable_data_len(), data.len() as u32); // Call the contract: Asserts the input to equal the immutable data assert_ok!(builder::call(addr).data(data.to_vec()).build()); @@ -4573,6 +4442,7 @@ fn tracing_works_for_transfers() { } #[test] +#[ignore = "does not collect the gas_used properly"] fn tracing_works() { use crate::evm::*; use CallType::*; diff --git a/substrate/frame/revive/src/wasm/mod.rs b/substrate/frame/revive/src/wasm/mod.rs index 527cf16309540c3edacf626bb7e222f82677f3d9..dc49fae26fdaa36509bdc1e9beffeb7188ef027e 100644 --- a/substrate/frame/revive/src/wasm/mod.rs +++ b/substrate/frame/revive/src/wasm/mod.rs @@ -214,15 +214,11 @@ impl<T: Config> CodeInfo<T> { } /// Returns reference count of the module. + #[cfg(test)] pub fn refcount(&self) -> u64 { self.refcount } - /// Return mutable reference to the refcount of the module. - pub fn refcount_mut(&mut self) -> &mut u64 { - &mut self.refcount - } - /// Returns the deposit of the module. pub fn deposit(&self) -> BalanceOf<T> { self.deposit @@ -232,6 +228,47 @@ impl<T: Config> CodeInfo<T> { pub fn code_len(&self) -> u64 { self.code_len.into() } + + /// Returns the number of times the specified contract exists on the call stack. Delegated calls + /// Increment the reference count of a stored code by one. + /// + /// # Errors + /// + /// [`Error::CodeNotFound`] is returned if no stored code found having the specified + /// `code_hash`. + pub fn increment_refcount(code_hash: H256) -> DispatchResult { + <CodeInfoOf<T>>::mutate(code_hash, |existing| -> Result<(), DispatchError> { + if let Some(info) = existing { + info.refcount = info + .refcount + .checked_add(1) + .ok_or_else(|| <Error<T>>::RefcountOverOrUnderflow)?; + Ok(()) + } else { + Err(Error::<T>::CodeNotFound.into()) + } + }) + } + + /// Decrement the reference count of a stored code by one. + /// + /// # Note + /// + /// A contract whose reference count dropped to zero isn't automatically removed. A + /// `remove_code` transaction must be submitted by the original uploader to do so. + pub fn decrement_refcount(code_hash: H256) -> DispatchResult { + <CodeInfoOf<T>>::mutate(code_hash, |existing| { + if let Some(info) = existing { + info.refcount = info + .refcount + .checked_sub(1) + .ok_or_else(|| <Error<T>>::RefcountOverOrUnderflow)?; + Ok(()) + } else { + Err(Error::<T>::CodeNotFound.into()) + } + }) + } } pub struct PreparedCall<'a, E: Ext> { @@ -287,15 +324,6 @@ impl<T: Config> WasmBlob<T> { Error::<T>::CodeRejected })?; - // This is checked at deploy time but we also want to reject pre-existing - // 32bit programs. - // TODO: Remove when we reset the test net. - // https://github.com/paritytech/contract-issues/issues/11 - if !module.is_64_bit() { - log::debug!(target: LOG_TARGET, "32bit programs are not supported."); - Err(Error::<T>::CodeRejected)?; - } - let entry_program_counter = module .exports() .find(|export| export.symbol().as_bytes() == entry_point.identifier().as_bytes()) @@ -309,11 +337,6 @@ impl<T: Config> WasmBlob<T> { Error::<T>::CodeRejected })?; - // Increment before execution so that the constructor sees the correct refcount - if let ExportedFunction::Constructor = entry_point { - E::increment_refcount(self.code_hash)?; - } - instance.set_gas(gas_limit_polkavm); instance.prepare_call_untyped(entry_program_counter, &[]); diff --git a/substrate/frame/revive/src/wasm/runtime.rs b/substrate/frame/revive/src/wasm/runtime.rs index 4fbcfe1b47f5b1866e745ab11e599de6e0ce5f99..279d72b97ee1a546bed2c517ac3a5a0f4ba9229f 100644 --- a/substrate/frame/revive/src/wasm/runtime.rs +++ b/substrate/frame/revive/src/wasm/runtime.rs @@ -327,6 +327,8 @@ pub enum RuntimeCosts { BlockNumber, /// Weight of calling `seal_block_hash`. BlockHash, + /// Weight of calling `seal_block_author`. + BlockAuthor, /// Weight of calling `seal_gas_price`. GasPrice, /// Weight of calling `seal_base_fee`. @@ -337,8 +339,8 @@ pub enum RuntimeCosts { GasLimit, /// Weight of calling `seal_weight_to_fee`. WeightToFee, - /// Weight of calling `seal_terminate`, passing the number of locked dependencies. - Terminate(u32), + /// Weight of calling `seal_terminate`. + Terminate, /// Weight of calling `seal_deposit_event` with the given number of topics and event size. DepositEvent { num_topic: u32, len: u32 }, /// Weight of calling `seal_set_storage` for the given storage item sizes. @@ -393,10 +395,6 @@ pub enum RuntimeCosts { SetCodeHash, /// Weight of calling `ecdsa_to_eth_address` EcdsaToEthAddress, - /// Weight of calling `lock_delegate_dependency` - LockDelegateDependency, - /// Weight of calling `unlock_delegate_dependency` - UnlockDelegateDependency, /// Weight of calling `get_immutable_dependency` GetImmutableData(u32), /// Weight of calling `set_immutable_dependency` @@ -483,12 +481,13 @@ impl<T: Config> Token<T> for RuntimeCosts { MinimumBalance => T::WeightInfo::seal_minimum_balance(), BlockNumber => T::WeightInfo::seal_block_number(), BlockHash => T::WeightInfo::seal_block_hash(), + BlockAuthor => T::WeightInfo::seal_block_author(), GasPrice => T::WeightInfo::seal_gas_price(), BaseFee => T::WeightInfo::seal_base_fee(), Now => T::WeightInfo::seal_now(), GasLimit => T::WeightInfo::seal_gas_limit(), WeightToFee => T::WeightInfo::seal_weight_to_fee(), - Terminate(locked_dependencies) => T::WeightInfo::seal_terminate(locked_dependencies), + Terminate => T::WeightInfo::seal_terminate(), DepositEvent { num_topic, len } => T::WeightInfo::seal_deposit_event(num_topic, len), SetStorage { new_bytes, old_bytes } => { cost_storage!(write, seal_set_storage, new_bytes, old_bytes) @@ -526,8 +525,6 @@ impl<T: Config> Token<T> for RuntimeCosts { ChainExtension(weight) | CallRuntime(weight) | CallXcmExecute(weight) => weight, SetCodeHash => T::WeightInfo::seal_set_code_hash(), EcdsaToEthAddress => T::WeightInfo::seal_ecdsa_to_eth_address(), - LockDelegateDependency => T::WeightInfo::lock_delegate_dependency(), - UnlockDelegateDependency => T::WeightInfo::unlock_delegate_dependency(), GetImmutableData(len) => T::WeightInfo::seal_get_immutable_data(len), SetImmutableData(len) => T::WeightInfo::seal_set_immutable_data(len), } @@ -569,6 +566,11 @@ fn already_charged(_: u32) -> Option<RuntimeCosts> { None } +/// Helper to extract two `u32` values from a given `u64` register. +fn extract_hi_lo(reg: u64) -> (u32, u32) { + ((reg >> 32) as u32, reg as u32) +} + /// Can only be used for one call. pub struct Runtime<'a, E: Ext, M: ?Sized> { ext: &'a mut E, @@ -784,10 +786,12 @@ impl<'a, E: Ext, M: ?Sized + Memory<E::T>> Runtime<'a, E, M> { let transfer_failed = Error::<E::T>::TransferFailed.into(); let out_of_gas = Error::<E::T>::OutOfGas.into(); let out_of_deposit = Error::<E::T>::StorageDepositLimitExhausted.into(); + let duplicate_contract = Error::<E::T>::DuplicateContract.into(); // errors in the callee do not trap the caller match (from.error, from.origin) { (err, _) if err == transfer_failed => Ok(TransferFailed), + (err, _) if err == duplicate_contract => Ok(DuplicateContractAddress), (err, Callee) if err == out_of_gas || err == out_of_deposit => Ok(OutOfResources), (_, Callee) => Ok(CalleeTrapped), (err, _) => Err(err), @@ -1132,15 +1136,6 @@ impl<'a, E: Ext, M: ?Sized + Memory<E::T>> Runtime<'a, E, M> { Err(err) => Ok(Self::exec_error_into_return_code(err)?), } } - - fn terminate(&mut self, memory: &M, beneficiary_ptr: u32) -> Result<(), TrapReason> { - let count = self.ext.locked_delegate_dependencies_count() as _; - self.charge_gas(RuntimeCosts::Terminate(count))?; - - let beneficiary = memory.read_h160(beneficiary_ptr)?; - self.ext.terminate(&beneficiary)?; - Err(TrapReason::Termination) - } } // This is the API exposed to contracts. @@ -1199,17 +1194,18 @@ pub mod env { fn call( &mut self, memory: &mut M, - flags: u32, - callee_ptr: u32, + flags_and_callee: u64, ref_time_limit: u64, proof_size_limit: u64, - deposit_ptr: u32, - value_ptr: u32, - input_data_ptr: u32, - input_data_len: u32, - output_ptr: u32, - output_len_ptr: u32, + deposit_and_value: u64, + input_data: u64, + output_data: u64, ) -> Result<ReturnErrorCode, TrapReason> { + let (flags, callee_ptr) = extract_hi_lo(flags_and_callee); + let (deposit_ptr, value_ptr) = extract_hi_lo(deposit_and_value); + let (input_data_len, input_data_ptr) = extract_hi_lo(input_data); + let (output_len_ptr, output_ptr) = extract_hi_lo(output_data); + self.call( memory, CallFlags::from_bits(flags).ok_or(Error::<E::T>::InvalidCallFlags)?, @@ -1230,16 +1226,17 @@ pub mod env { fn delegate_call( &mut self, memory: &mut M, - flags: u32, - address_ptr: u32, + flags_and_callee: u64, ref_time_limit: u64, proof_size_limit: u64, deposit_ptr: u32, - input_data_ptr: u32, - input_data_len: u32, - output_ptr: u32, - output_len_ptr: u32, + input_data: u64, + output_data: u64, ) -> Result<ReturnErrorCode, TrapReason> { + let (flags, address_ptr) = extract_hi_lo(flags_and_callee); + let (input_data_len, input_data_ptr) = extract_hi_lo(input_data); + let (output_len_ptr, output_ptr) = extract_hi_lo(output_data); + self.call( memory, CallFlags::from_bits(flags).ok_or(Error::<E::T>::InvalidCallFlags)?, @@ -1261,18 +1258,24 @@ pub mod env { fn instantiate( &mut self, memory: &mut M, - code_hash_ptr: u32, ref_time_limit: u64, proof_size_limit: u64, - deposit_ptr: u32, - value_ptr: u32, - input_data_ptr: u32, - input_data_len: u32, - address_ptr: u32, - output_ptr: u32, - output_len_ptr: u32, - salt_ptr: u32, + deposit_and_value: u64, + input_data: u64, + output_data: u64, + address_and_salt: u64, ) -> Result<ReturnErrorCode, TrapReason> { + let (deposit_ptr, value_ptr) = extract_hi_lo(deposit_and_value); + let (input_data_len, code_hash_ptr) = extract_hi_lo(input_data); + let (output_len_ptr, output_ptr) = extract_hi_lo(output_data); + let (address_ptr, salt_ptr) = extract_hi_lo(address_and_salt); + let Some(input_data_ptr) = code_hash_ptr.checked_add(32) else { + return Err(Error::<E::T>::OutOfBounds.into()); + }; + let Some(input_data_len) = input_data_len.checked_sub(32) else { + return Err(Error::<E::T>::OutOfBounds.into()); + }; + self.instantiate( memory, code_hash_ptr, @@ -1475,9 +1478,10 @@ pub mod env { out_ptr: u32, out_len_ptr: u32, ) -> Result<(), TrapReason> { - let charged = self.charge_gas(RuntimeCosts::GetImmutableData(limits::IMMUTABLE_BYTES))?; + // quering the length is free as it is stored with the contract metadata + let len = self.ext.immutable_data_len(); + self.charge_gas(RuntimeCosts::GetImmutableData(len))?; let data = self.ext.get_immutable_data()?; - self.adjust_gas(charged, RuntimeCosts::GetImmutableData(data.len() as u32)); self.write_sandbox_output(memory, out_ptr, out_len_ptr, &data, false, already_charged)?; Ok(()) } @@ -1676,6 +1680,25 @@ pub mod env { )?) } + /// Stores the current block author into the supplied buffer. + /// See [`pallet_revive_uapi::HostFn::block_author`]. + #[stable] + fn block_author(&mut self, memory: &mut M, out_ptr: u32) -> Result<(), TrapReason> { + self.charge_gas(RuntimeCosts::BlockAuthor)?; + let block_author = self + .ext + .block_author() + .map(|account| <E::T as Config>::AddressMapper::to_address(&account)) + .unwrap_or(H160::zero()); + Ok(self.write_fixed_sandbox_output( + memory, + out_ptr, + &block_author.as_bytes(), + false, + already_charged, + )?) + } + /// Computes the KECCAK 256-bit hash on the given input buffer. /// See [`pallet_revive_uapi::HostFn::hash_keccak_256`]. #[stable] @@ -1933,20 +1956,6 @@ pub mod env { Ok(self.ext.is_contract(&address) as u32) } - /// Adds a new delegate dependency to the contract. - /// See [`pallet_revive_uapi::HostFn::lock_delegate_dependency`]. - #[mutating] - fn lock_delegate_dependency( - &mut self, - memory: &mut M, - code_hash_ptr: u32, - ) -> Result<(), TrapReason> { - self.charge_gas(RuntimeCosts::LockDelegateDependency)?; - let code_hash = memory.read_h256(code_hash_ptr)?; - self.ext.lock_delegate_dependency(code_hash)?; - Ok(()) - } - /// Stores the minimum balance (a.k.a. existential deposit) into the supplied buffer. /// See [`pallet_revive_uapi::HostFn::minimum_balance`]. fn minimum_balance(&mut self, memory: &mut M, out_ptr: u32) -> Result<(), TrapReason> { @@ -2014,20 +2023,6 @@ pub mod env { } } - /// Removes the delegate dependency from the contract. - /// see [`pallet_revive_uapi::HostFn::unlock_delegate_dependency`]. - #[mutating] - fn unlock_delegate_dependency( - &mut self, - memory: &mut M, - code_hash_ptr: u32, - ) -> Result<(), TrapReason> { - self.charge_gas(RuntimeCosts::UnlockDelegateDependency)?; - let code_hash = memory.read_h256(code_hash_ptr)?; - self.ext.unlock_delegate_dependency(&code_hash)?; - Ok(()) - } - /// Retrieve and remove the value under the given key from storage. /// See [`pallet_revive_uapi::HostFn::take_storage`] #[mutating] @@ -2047,7 +2042,10 @@ pub mod env { /// See [`pallet_revive_uapi::HostFn::terminate`]. #[mutating] fn terminate(&mut self, memory: &mut M, beneficiary_ptr: u32) -> Result<(), TrapReason> { - self.terminate(memory, beneficiary_ptr) + self.charge_gas(RuntimeCosts::Terminate)?; + let beneficiary = memory.read_h160(beneficiary_ptr)?; + self.ext.terminate(&beneficiary)?; + Err(TrapReason::Termination) } /// Stores the amount of weight left into the supplied buffer. diff --git a/substrate/frame/revive/src/weights.rs b/substrate/frame/revive/src/weights.rs index 52153d74ca758c429a4982e393b7d211d79ab5b4..42b8a9e5e722f8aaaf2d8302d870bba0ba9d9da2 100644 --- a/substrate/frame/revive/src/weights.rs +++ b/substrate/frame/revive/src/weights.rs @@ -18,17 +18,18 @@ //! Autogenerated weights for `pallet_revive` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-12-19, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2025-02-04, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `19e0eeaa3bc2`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` -//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: `1024` +//! HOSTNAME: `11670a4f427b`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` // Executed Command: -// target/production/substrate-node +// frame-omni-bencher +// v1 // benchmark // pallet // --extrinsic=* -// --chain=dev +// --runtime=target/production/wbuild/kitchensink-runtime/kitchensink_runtime.wasm // --pallet=pallet_revive // --header=/__w/polkadot-sdk/polkadot-sdk/substrate/HEADER-APACHE2 // --output=/__w/polkadot-sdk/polkadot-sdk/substrate/frame/revive/src/weights.rs @@ -40,11 +41,14 @@ // --no-storage-info // --no-min-squares // --no-median-slopes +// --genesis-builder-policy=none +// --exclude-pallets=pallet_xcm,pallet_xcm_benchmarks::fungible,pallet_xcm_benchmarks::generic,pallet_nomination_pools,pallet_remark,pallet_transaction_storage #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] #![allow(unused_imports)] #![allow(missing_docs)] +#[allow(dead_code)] use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use core::marker::PhantomData; @@ -88,6 +92,7 @@ pub trait WeightInfo { fn seal_gas_price() -> Weight; fn seal_base_fee() -> Weight; fn seal_block_number() -> Weight; + fn seal_block_author() -> Weight; fn seal_block_hash() -> Weight; fn seal_now() -> Weight; fn seal_weight_to_fee() -> Weight; @@ -95,7 +100,7 @@ pub trait WeightInfo { fn seal_call_data_load() -> Weight; fn seal_call_data_copy(n: u32, ) -> Weight; fn seal_return(n: u32, ) -> Weight; - fn seal_terminate(n: u32, ) -> Weight; + fn seal_terminate() -> Weight; fn seal_deposit_event(t: u32, n: u32, ) -> Weight; fn get_storage_empty() -> Weight; fn get_storage_full() -> Weight; @@ -127,8 +132,6 @@ pub trait WeightInfo { fn seal_ecdsa_recover() -> Weight; fn seal_ecdsa_to_eth_address() -> Weight; fn seal_set_code_hash() -> Weight; - fn lock_delegate_dependency() -> Weight; - fn unlock_delegate_dependency() -> Weight; fn instr(r: u32, ) -> Weight; } @@ -139,10 +142,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { /// Proof: `Revive::DeletionQueueCounter` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) fn on_process_deletion_queue_batch() -> Weight { // Proof Size summary in bytes: - // Measured: `109` - // Estimated: `1594` - // Minimum execution time: 2_859_000 picoseconds. - Weight::from_parts(3_007_000, 1594) + // Measured: `0` + // Estimated: `1485` + // Minimum execution time: 695_000 picoseconds. + Weight::from_parts(750_000, 1485) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -150,12 +153,12 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { /// The range of component `k` is `[0, 1024]`. fn on_initialize_per_trie_key(k: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `425 + k * (69 ±0)` - // Estimated: `415 + k * (70 ±0)` - // Minimum execution time: 15_640_000 picoseconds. - Weight::from_parts(1_609_026, 415) - // Standard Error: 1_359 - .saturating_add(Weight::from_parts(1_204_420, 0).saturating_mul(k.into())) + // Measured: `230 + k * (69 ±0)` + // Estimated: `222 + k * (70 ±0)` + // Minimum execution time: 10_509_000 picoseconds. + Weight::from_parts(10_896_000, 222) + // Standard Error: 2_549 + .saturating_add(Weight::from_parts(1_264_033, 0).saturating_mul(k.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(k.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) @@ -165,7 +168,7 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { /// Storage: `Revive::AddressSuffix` (r:2 w:0) /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) /// Storage: `Revive::ContractInfoOf` (r:1 w:1) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) + /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) /// Storage: `Revive::CodeInfoOf` (r:1 w:0) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:1 w:0) @@ -177,21 +180,21 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { /// The range of component `c` is `[0, 262144]`. fn call_with_code_per_byte(_c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1463` - // Estimated: `7403` - // Minimum execution time: 89_437_000 picoseconds. - Weight::from_parts(94_285_182, 7403) + // Measured: `1194` + // Estimated: `7134` + // Minimum execution time: 84_008_000 picoseconds. + Weight::from_parts(91_138_296, 7134) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Balances::Holds` (r:2 w:2) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(355), added: 2830, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(409), added: 2884, mode: `Measured`) /// Storage: `Revive::AddressSuffix` (r:1 w:0) /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) /// Storage: `Revive::ContractInfoOf` (r:1 w:1) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) + /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) /// Storage: `Timestamp::Now` (r:1 w:0) /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `System::Account` (r:1 w:1) @@ -200,16 +203,14 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) /// The range of component `c` is `[0, 262144]`. /// The range of component `i` is `[0, 262144]`. - fn instantiate_with_code(c: u32, i: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `364` - // Estimated: `6327` - // Minimum execution time: 187_904_000 picoseconds. - Weight::from_parts(153_252_081, 6327) - // Standard Error: 11 - .saturating_add(Weight::from_parts(49, 0).saturating_mul(c.into())) - // Standard Error: 11 - .saturating_add(Weight::from_parts(4_528, 0).saturating_mul(i.into())) + fn instantiate_with_code(_c: u32, i: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `93` + // Estimated: `6033` + // Minimum execution time: 172_907_000 picoseconds. + Weight::from_parts(153_592_465, 6033) + // Standard Error: 12 + .saturating_add(Weight::from_parts(4_544, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } @@ -220,29 +221,29 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { /// Storage: `Revive::AddressSuffix` (r:1 w:0) /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) /// Storage: `Revive::ContractInfoOf` (r:1 w:1) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) + /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) /// Storage: `Timestamp::Now` (r:1 w:0) /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(355), added: 2830, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(409), added: 2884, mode: `Measured`) /// The range of component `i` is `[0, 262144]`. fn instantiate(i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1296` - // Estimated: `4758` - // Minimum execution time: 154_656_000 picoseconds. - Weight::from_parts(139_308_398, 4758) + // Measured: `987` + // Estimated: `4452` + // Minimum execution time: 143_169_000 picoseconds. + Weight::from_parts(120_653_436, 4452) // Standard Error: 16 - .saturating_add(Weight::from_parts(4_421, 0).saturating_mul(i.into())) + .saturating_add(Weight::from_parts(4_444, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } /// Storage: `Revive::AddressSuffix` (r:2 w:0) /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) /// Storage: `Revive::ContractInfoOf` (r:1 w:1) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) + /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) /// Storage: `Revive::CodeInfoOf` (r:1 w:0) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:1 w:0) @@ -253,82 +254,80 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) fn call() -> Weight { // Proof Size summary in bytes: - // Measured: `1463` - // Estimated: `7403` - // Minimum execution time: 138_815_000 picoseconds. - Weight::from_parts(149_067_000, 7403) + // Measured: `1194` + // Estimated: `7134` + // Minimum execution time: 138_392_000 picoseconds. + Weight::from_parts(143_329_000, 7134) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(355), added: 2830, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(409), added: 2884, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:0 w:1) /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) /// The range of component `c` is `[0, 262144]`. - fn upload_code(c: u32, ) -> Weight { + fn upload_code(_c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `109` - // Estimated: `3574` - // Minimum execution time: 49_978_000 picoseconds. - Weight::from_parts(51_789_325, 3574) - // Standard Error: 0 - .saturating_add(Weight::from_parts(1, 0).saturating_mul(c.into())) + // Measured: `0` + // Estimated: `3465` + // Minimum execution time: 43_420_000 picoseconds. + Weight::from_parts(45_143_767, 3465) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(355), added: 2830, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(409), added: 2884, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:0 w:1) /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) fn remove_code() -> Weight { // Proof Size summary in bytes: - // Measured: `285` - // Estimated: `3750` - // Minimum execution time: 43_833_000 picoseconds. - Weight::from_parts(44_660_000, 3750) + // Measured: `181` + // Estimated: `3646` + // Minimum execution time: 35_828_000 picoseconds. + Weight::from_parts(36_853_000, 3646) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `Revive::ContractInfoOf` (r:1 w:1) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) + /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) /// Storage: `Revive::CodeInfoOf` (r:2 w:2) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) fn set_code() -> Weight { // Proof Size summary in bytes: - // Measured: `529` - // Estimated: `6469` - // Minimum execution time: 26_717_000 picoseconds. - Weight::from_parts(28_566_000, 6469) + // Measured: `424` + // Estimated: `6364` + // Minimum execution time: 19_678_000 picoseconds. + Weight::from_parts(21_266_000, 6364) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `Revive::AddressSuffix` (r:1 w:1) /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(355), added: 2830, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(409), added: 2884, mode: `Measured`) fn map_account() -> Weight { // Proof Size summary in bytes: - // Measured: `109` - // Estimated: `3574` - // Minimum execution time: 39_401_000 picoseconds. - Weight::from_parts(40_542_000, 3574) + // Measured: `0` + // Estimated: `3465` + // Minimum execution time: 37_024_000 picoseconds. + Weight::from_parts(37_440_000, 3465) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(355), added: 2830, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(409), added: 2884, mode: `Measured`) /// Storage: `Revive::AddressSuffix` (r:0 w:1) /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) fn unmap_account() -> Weight { // Proof Size summary in bytes: // Measured: `56` // Estimated: `3521` - // Minimum execution time: 31_570_000 picoseconds. - Weight::from_parts(32_302_000, 3521) + // Minimum execution time: 31_228_000 picoseconds. + Weight::from_parts(32_183_000, 3521) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -338,10 +337,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `Measured`) fn dispatch_as_fallback_account() -> Weight { // Proof Size summary in bytes: - // Measured: `145` - // Estimated: `3610` - // Minimum execution time: 13_607_000 picoseconds. - Weight::from_parts(13_903_000, 3610) + // Measured: `0` + // Estimated: `3465` + // Minimum execution time: 6_241_000 picoseconds. + Weight::from_parts(6_467_000, 3465) .saturating_add(T::DbWeight::get().reads(2_u64)) } /// The range of component `r` is `[0, 1600]`. @@ -349,115 +348,115 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_400_000 picoseconds. - Weight::from_parts(8_388_251, 0) - // Standard Error: 283 - .saturating_add(Weight::from_parts(165_630, 0).saturating_mul(r.into())) + // Minimum execution time: 6_397_000 picoseconds. + Weight::from_parts(7_159_300, 0) + // Standard Error: 173 + .saturating_add(Weight::from_parts(167_265, 0).saturating_mul(r.into())) } fn seal_caller() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 275_000 picoseconds. - Weight::from_parts(305_000, 0) + // Minimum execution time: 267_000 picoseconds. + Weight::from_parts(296_000, 0) } fn seal_origin() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 224_000 picoseconds. - Weight::from_parts(265_000, 0) + // Minimum execution time: 227_000 picoseconds. + Weight::from_parts(252_000, 0) } /// Storage: `Revive::ContractInfoOf` (r:1 w:0) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) + /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) fn seal_is_contract() -> Weight { // Proof Size summary in bytes: - // Measured: `306` - // Estimated: `3771` - // Minimum execution time: 10_004_000 picoseconds. - Weight::from_parts(10_336_000, 3771) + // Measured: `202` + // Estimated: `3667` + // Minimum execution time: 6_591_000 picoseconds. + Weight::from_parts(6_770_000, 3667) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Revive::AddressSuffix` (r:1 w:0) /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) fn seal_to_account_id() -> Weight { // Proof Size summary in bytes: - // Measured: `212` - // Estimated: `3677` - // Minimum execution time: 4_000_000 picoseconds. - Weight::from_parts(4_000_000, 3677) + // Measured: `144` + // Estimated: `3609` + // Minimum execution time: 6_182_000 picoseconds. + Weight::from_parts(6_372_000, 3609) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Revive::ContractInfoOf` (r:1 w:0) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) + /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) fn seal_code_hash() -> Weight { // Proof Size summary in bytes: - // Measured: `403` - // Estimated: `3868` - // Minimum execution time: 11_054_000 picoseconds. - Weight::from_parts(11_651_000, 3868) + // Measured: `298` + // Estimated: `3763` + // Minimum execution time: 7_327_000 picoseconds. + Weight::from_parts(7_612_000, 3763) .saturating_add(T::DbWeight::get().reads(1_u64)) } fn seal_own_code_hash() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 252_000 picoseconds. - Weight::from_parts(305_000, 0) + // Minimum execution time: 232_000 picoseconds. + Weight::from_parts(287_000, 0) } /// Storage: `Revive::ContractInfoOf` (r:1 w:0) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) + /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) /// Storage: `Revive::CodeInfoOf` (r:1 w:0) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) fn seal_code_size() -> Weight { // Proof Size summary in bytes: - // Measured: `473` - // Estimated: `3938` - // Minimum execution time: 14_461_000 picoseconds. - Weight::from_parts(15_049_000, 3938) + // Measured: `368` + // Estimated: `3833` + // Minimum execution time: 10_918_000 picoseconds. + Weight::from_parts(11_323_000, 3833) .saturating_add(T::DbWeight::get().reads(2_u64)) } fn seal_caller_is_origin() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 312_000 picoseconds. - Weight::from_parts(338_000, 0) + // Minimum execution time: 310_000 picoseconds. + Weight::from_parts(340_000, 0) } fn seal_caller_is_root() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 243_000 picoseconds. - Weight::from_parts(299_000, 0) + // Minimum execution time: 257_000 picoseconds. + Weight::from_parts(292_000, 0) } fn seal_address() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 231_000 picoseconds. - Weight::from_parts(271_000, 0) + // Minimum execution time: 240_000 picoseconds. + Weight::from_parts(249_000, 0) } fn seal_weight_left() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 683_000 picoseconds. - Weight::from_parts(732_000, 0) + // Minimum execution time: 599_000 picoseconds. + Weight::from_parts(645_000, 0) } fn seal_ref_time_left() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 226_000 picoseconds. - Weight::from_parts(273_000, 0) + // Minimum execution time: 208_000 picoseconds. + Weight::from_parts(244_000, 0) } fn seal_balance() -> Weight { // Proof Size summary in bytes: // Measured: `102` // Estimated: `0` - // Minimum execution time: 4_626_000 picoseconds. - Weight::from_parts(4_842_000, 0) + // Minimum execution time: 4_534_000 picoseconds. + Weight::from_parts(4_689_000, 0) } /// Storage: `Revive::AddressSuffix` (r:1 w:0) /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) @@ -465,10 +464,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) fn seal_balance_of() -> Weight { // Proof Size summary in bytes: - // Measured: `264` - // Estimated: `3729` - // Minimum execution time: 12_309_000 picoseconds. - Weight::from_parts(12_653_000, 3729) + // Measured: `160` + // Estimated: `3625` + // Minimum execution time: 8_640_000 picoseconds. + Weight::from_parts(8_971_000, 3625) .saturating_add(T::DbWeight::get().reads(2_u64)) } /// Storage: `Revive::ImmutableDataOf` (r:1 w:0) @@ -476,12 +475,12 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { /// The range of component `n` is `[1, 4096]`. fn seal_get_immutable_data(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `238 + n * (1 ±0)` - // Estimated: `3703 + n * (1 ±0)` - // Minimum execution time: 5_838_000 picoseconds. - Weight::from_parts(9_570_778, 3703) - // Standard Error: 19 - .saturating_add(Weight::from_parts(721, 0).saturating_mul(n.into())) + // Measured: `134 + n * (1 ±0)` + // Estimated: `3599 + n * (1 ±0)` + // Minimum execution time: 4_875_000 picoseconds. + Weight::from_parts(6_212_863, 3599) + // Standard Error: 7 + .saturating_add(Weight::from_parts(671, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -492,195 +491,199 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_910_000 picoseconds. - Weight::from_parts(2_205_396, 0) + // Minimum execution time: 1_678_000 picoseconds. + Weight::from_parts(1_883_150, 0) // Standard Error: 2 - .saturating_add(Weight::from_parts(538, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(579, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().writes(1_u64)) } fn seal_value_transferred() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 224_000 picoseconds. - Weight::from_parts(274_000, 0) + // Minimum execution time: 238_000 picoseconds. + Weight::from_parts(273_000, 0) } fn seal_minimum_balance() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 231_000 picoseconds. - Weight::from_parts(279_000, 0) + // Minimum execution time: 244_000 picoseconds. + Weight::from_parts(260_000, 0) } fn seal_return_data_size() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 229_000 picoseconds. - Weight::from_parts(267_000, 0) + // Minimum execution time: 249_000 picoseconds. + Weight::from_parts(265_000, 0) } fn seal_call_data_size() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 218_000 picoseconds. - Weight::from_parts(267_000, 0) + // Minimum execution time: 243_000 picoseconds. + Weight::from_parts(269_000, 0) } fn seal_gas_limit() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 225_000 picoseconds. - Weight::from_parts(280_000, 0) + // Minimum execution time: 228_000 picoseconds. + Weight::from_parts(268_000, 0) } fn seal_gas_price() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 274_000 picoseconds. - Weight::from_parts(323_000, 0) + // Minimum execution time: 222_000 picoseconds. + Weight::from_parts(251_000, 0) } fn seal_base_fee() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 239_000 picoseconds. - Weight::from_parts(290_000, 0) + // Minimum execution time: 226_000 picoseconds. + Weight::from_parts(250_000, 0) } fn seal_block_number() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 224_000 picoseconds. - Weight::from_parts(274_000, 0) + // Minimum execution time: 228_000 picoseconds. + Weight::from_parts(270_000, 0) + } + /// Storage: `Session::Validators` (r:1 w:0) + /// Proof: `Session::Validators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + fn seal_block_author() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `1485` + // Minimum execution time: 13_597_000 picoseconds. + Weight::from_parts(13_770_000, 1485) + .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `System::BlockHash` (r:1 w:0) /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `Measured`) fn seal_block_hash() -> Weight { // Proof Size summary in bytes: - // Measured: `30` - // Estimated: `3495` - // Minimum execution time: 3_430_000 picoseconds. - Weight::from_parts(3_692_000, 3495) + // Measured: `0` + // Estimated: `3465` + // Minimum execution time: 2_199_000 picoseconds. + Weight::from_parts(2_402_000, 3465) .saturating_add(T::DbWeight::get().reads(1_u64)) } fn seal_now() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 241_000 picoseconds. - Weight::from_parts(290_000, 0) + // Minimum execution time: 230_000 picoseconds. + Weight::from_parts(256_000, 0) } fn seal_weight_to_fee() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_355_000 picoseconds. - Weight::from_parts(1_493_000, 0) + // Minimum execution time: 1_214_000 picoseconds. + Weight::from_parts(1_283_000, 0) } /// The range of component `n` is `[0, 262140]`. fn seal_copy_to_contract(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 348_000 picoseconds. - Weight::from_parts(1_004_890, 0) + // Minimum execution time: 376_000 picoseconds. + Weight::from_parts(569_136, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(202, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(236, 0).saturating_mul(n.into())) } fn seal_call_data_load() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 222_000 picoseconds. - Weight::from_parts(256_000, 0) + // Minimum execution time: 243_000 picoseconds. + Weight::from_parts(260_000, 0) } /// The range of component `n` is `[0, 262144]`. fn seal_call_data_copy(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 240_000 picoseconds. - Weight::from_parts(330_609, 0) + // Minimum execution time: 231_000 picoseconds. + Weight::from_parts(379_088, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(114, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(148, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 262140]`. fn seal_return(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 232_000 picoseconds. - Weight::from_parts(264_000, 0) + // Minimum execution time: 227_000 picoseconds. + Weight::from_parts(400_572, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(208, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(237, 0).saturating_mul(n.into())) } /// Storage: `Revive::AddressSuffix` (r:1 w:0) /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) /// Storage: `Revive::DeletionQueueCounter` (r:1 w:1) /// Proof: `Revive::DeletionQueueCounter` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) - /// Storage: `Revive::CodeInfoOf` (r:33 w:33) + /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Revive::DeletionQueue` (r:0 w:1) /// Proof: `Revive::DeletionQueue` (`max_values`: None, `max_size`: Some(142), added: 2617, mode: `Measured`) /// Storage: `Revive::ImmutableDataOf` (r:0 w:1) /// Proof: `Revive::ImmutableDataOf` (`max_values`: None, `max_size`: Some(4118), added: 6593, mode: `Measured`) - /// The range of component `n` is `[0, 32]`. - fn seal_terminate(n: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `322 + n * (88 ±0)` - // Estimated: `3787 + n * (2563 ±0)` - // Minimum execution time: 21_920_000 picoseconds. - Weight::from_parts(21_725_868, 3787) - // Standard Error: 11_165 - .saturating_add(Weight::from_parts(4_317_986, 0).saturating_mul(n.into())) + fn seal_terminate() -> Weight { + // Proof Size summary in bytes: + // Measured: `215` + // Estimated: `3680` + // Minimum execution time: 14_216_000 picoseconds. + Weight::from_parts(14_533_000, 3680) .saturating_add(T::DbWeight::get().reads(3_u64)) - .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(4_u64)) - .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) - .saturating_add(Weight::from_parts(0, 2563).saturating_mul(n.into())) } /// The range of component `t` is `[0, 4]`. - /// The range of component `n` is `[0, 448]`. + /// The range of component `n` is `[0, 416]`. fn seal_deposit_event(t: u32, n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_140_000 picoseconds. - Weight::from_parts(4_259_301, 0) - // Standard Error: 3_362 - .saturating_add(Weight::from_parts(194_546, 0).saturating_mul(t.into())) - // Standard Error: 34 - .saturating_add(Weight::from_parts(774, 0).saturating_mul(n.into())) + // Minimum execution time: 3_877_000 picoseconds. + Weight::from_parts(3_856_832, 0) + // Standard Error: 2_622 + .saturating_add(Weight::from_parts(201_206, 0).saturating_mul(t.into())) + // Standard Error: 28 + .saturating_add(Weight::from_parts(1_128, 0).saturating_mul(n.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) fn get_storage_empty() -> Weight { // Proof Size summary in bytes: - // Measured: `680` - // Estimated: `680` - // Minimum execution time: 10_747_000 picoseconds. - Weight::from_parts(11_276_000, 680) + // Measured: `552` + // Estimated: `552` + // Minimum execution time: 5_806_000 picoseconds. + Weight::from_parts(6_037_000, 552) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) fn get_storage_full() -> Weight { // Proof Size summary in bytes: - // Measured: `10690` - // Estimated: `10690` - // Minimum execution time: 42_076_000 picoseconds. - Weight::from_parts(43_381_000, 10690) + // Measured: `10562` + // Estimated: `10562` + // Minimum execution time: 39_517_000 picoseconds. + Weight::from_parts(40_698_000, 10562) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) fn set_storage_empty() -> Weight { // Proof Size summary in bytes: - // Measured: `680` - // Estimated: `680` - // Minimum execution time: 11_703_000 picoseconds. - Weight::from_parts(12_308_000, 680) + // Measured: `552` + // Estimated: `552` + // Minimum execution time: 6_747_000 picoseconds. + Weight::from_parts(7_003_000, 552) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -688,85 +691,85 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) fn set_storage_full() -> Weight { // Proof Size summary in bytes: - // Measured: `10690` - // Estimated: `10690` - // Minimum execution time: 43_460_000 picoseconds. - Weight::from_parts(45_165_000, 10690) + // Measured: `10562` + // Estimated: `10562` + // Minimum execution time: 40_158_000 picoseconds. + Weight::from_parts(41_394_000, 10562) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `n` is `[0, 448]`. - /// The range of component `o` is `[0, 448]`. + /// The range of component `n` is `[0, 416]`. + /// The range of component `o` is `[0, 416]`. fn seal_set_storage(n: u32, o: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `248 + o * (1 ±0)` - // Estimated: `247 + o * (1 ±0)` - // Minimum execution time: 9_087_000 picoseconds. - Weight::from_parts(11_787_486, 247) - // Standard Error: 179 - .saturating_add(Weight::from_parts(976, 0).saturating_mul(n.into())) - // Standard Error: 179 - .saturating_add(Weight::from_parts(3_151, 0).saturating_mul(o.into())) + // Measured: `152 + o * (1 ±0)` + // Estimated: `151 + o * (1 ±0)` + // Minimum execution time: 6_360_000 picoseconds. + Weight::from_parts(7_335_152, 151) + // Standard Error: 80 + .saturating_add(Weight::from_parts(716, 0).saturating_mul(n.into())) + // Standard Error: 80 + .saturating_add(Weight::from_parts(1_127, 0).saturating_mul(o.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(o.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `n` is `[0, 448]`. + /// The range of component `n` is `[0, 416]`. fn seal_clear_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `248 + n * (1 ±0)` - // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 8_611_000 picoseconds. - Weight::from_parts(11_791_390, 247) - // Standard Error: 308 - .saturating_add(Weight::from_parts(3_943, 0).saturating_mul(n.into())) + // Measured: `152 + n * (1 ±0)` + // Estimated: `151 + n * (1 ±0)` + // Minimum execution time: 5_980_000 picoseconds. + Weight::from_parts(7_164_266, 151) + // Standard Error: 130 + .saturating_add(Weight::from_parts(1_893, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `n` is `[0, 448]`. + /// The range of component `n` is `[0, 416]`. fn seal_get_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `248 + n * (1 ±0)` - // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 8_389_000 picoseconds. - Weight::from_parts(11_625_480, 247) - // Standard Error: 315 - .saturating_add(Weight::from_parts(4_487, 0).saturating_mul(n.into())) + // Measured: `152 + n * (1 ±0)` + // Estimated: `151 + n * (1 ±0)` + // Minimum execution time: 5_823_000 picoseconds. + Weight::from_parts(7_045_557, 151) + // Standard Error: 123 + .saturating_add(Weight::from_parts(2_222, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `n` is `[0, 448]`. + /// The range of component `n` is `[0, 416]`. fn seal_contains_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `248 + n * (1 ±0)` - // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 7_947_000 picoseconds. - Weight::from_parts(10_970_587, 247) - // Standard Error: 310 - .saturating_add(Weight::from_parts(3_675, 0).saturating_mul(n.into())) + // Measured: `152 + n * (1 ±0)` + // Estimated: `151 + n * (1 ±0)` + // Minimum execution time: 5_349_000 picoseconds. + Weight::from_parts(6_506_216, 151) + // Standard Error: 127 + .saturating_add(Weight::from_parts(1_605, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `n` is `[0, 448]`. + /// The range of component `n` is `[0, 416]`. fn seal_take_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `248 + n * (1 ±0)` - // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 9_071_000 picoseconds. - Weight::from_parts(12_525_027, 247) - // Standard Error: 328 - .saturating_add(Weight::from_parts(4_427, 0).saturating_mul(n.into())) + // Measured: `152 + n * (1 ±0)` + // Estimated: `151 + n * (1 ±0)` + // Minimum execution time: 6_151_000 picoseconds. + Weight::from_parts(7_812_180, 151) + // Standard Error: 159 + .saturating_add(Weight::from_parts(2_277, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -775,94 +778,94 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_487_000 picoseconds. - Weight::from_parts(1_611_000, 0) + // Minimum execution time: 1_344_000 picoseconds. + Weight::from_parts(1_462_000, 0) } fn set_transient_storage_full() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_852_000 picoseconds. - Weight::from_parts(1_982_000, 0) + // Minimum execution time: 1_680_000 picoseconds. + Weight::from_parts(1_785_000, 0) } fn get_transient_storage_empty() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_467_000 picoseconds. - Weight::from_parts(1_529_000, 0) + // Minimum execution time: 1_380_000 picoseconds. + Weight::from_parts(1_502_000, 0) } fn get_transient_storage_full() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_630_000 picoseconds. - Weight::from_parts(1_712_000, 0) + // Minimum execution time: 1_506_000 picoseconds. + Weight::from_parts(1_604_000, 0) } fn rollback_transient_storage() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_188_000 picoseconds. - Weight::from_parts(1_268_000, 0) + // Minimum execution time: 972_000 picoseconds. + Weight::from_parts(1_054_000, 0) } - /// The range of component `n` is `[0, 448]`. - /// The range of component `o` is `[0, 448]`. + /// The range of component `n` is `[0, 416]`. + /// The range of component `o` is `[0, 416]`. fn seal_set_transient_storage(n: u32, o: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_197_000 picoseconds. - Weight::from_parts(2_464_654, 0) + // Minimum execution time: 2_048_000 picoseconds. + Weight::from_parts(2_304_120, 0) // Standard Error: 17 - .saturating_add(Weight::from_parts(296, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(254, 0).saturating_mul(n.into())) // Standard Error: 17 - .saturating_add(Weight::from_parts(342, 0).saturating_mul(o.into())) + .saturating_add(Weight::from_parts(321, 0).saturating_mul(o.into())) } - /// The range of component `n` is `[0, 448]`. + /// The range of component `n` is `[0, 416]`. fn seal_clear_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_005_000 picoseconds. - Weight::from_parts(2_381_053, 0) - // Standard Error: 23 - .saturating_add(Weight::from_parts(322, 0).saturating_mul(n.into())) + // Minimum execution time: 1_790_000 picoseconds. + Weight::from_parts(2_141_874, 0) + // Standard Error: 31 + .saturating_add(Weight::from_parts(378, 0).saturating_mul(n.into())) } - /// The range of component `n` is `[0, 448]`. + /// The range of component `n` is `[0, 416]`. fn seal_get_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_853_000 picoseconds. - Weight::from_parts(2_082_772, 0) - // Standard Error: 20 - .saturating_add(Weight::from_parts(322, 0).saturating_mul(n.into())) + // Minimum execution time: 1_662_000 picoseconds. + Weight::from_parts(1_938_172, 0) + // Standard Error: 14 + .saturating_add(Weight::from_parts(316, 0).saturating_mul(n.into())) } - /// The range of component `n` is `[0, 448]`. + /// The range of component `n` is `[0, 416]`. fn seal_contains_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_711_000 picoseconds. - Weight::from_parts(1_899_649, 0) - // Standard Error: 16 - .saturating_add(Weight::from_parts(208, 0).saturating_mul(n.into())) + // Minimum execution time: 1_570_000 picoseconds. + Weight::from_parts(1_769_617, 0) + // Standard Error: 13 + .saturating_add(Weight::from_parts(152, 0).saturating_mul(n.into())) } - /// The range of component `n` is `[0, 448]`. + /// The range of component `n` is `[0, 416]`. fn seal_take_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_460_000 picoseconds. - Weight::from_parts(2_684_364, 0) - // Standard Error: 22 - .saturating_add(Weight::from_parts(56, 0).saturating_mul(n.into())) + // Minimum execution time: 2_266_000 picoseconds. + Weight::from_parts(2_497_430, 0) + // Standard Error: 21 + .saturating_add(Weight::from_parts(38, 0).saturating_mul(n.into())) } /// Storage: `Revive::AddressSuffix` (r:1 w:0) /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) /// Storage: `Revive::ContractInfoOf` (r:1 w:0) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) + /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) /// Storage: `Revive::CodeInfoOf` (r:1 w:0) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:1 w:0) @@ -873,31 +876,31 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { /// The range of component `i` is `[0, 262144]`. fn seal_call(t: u32, i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1292 + t * (203 ±0)` - // Estimated: `4757 + t * (2480 ±0)` - // Minimum execution time: 40_031_000 picoseconds. - Weight::from_parts(41_527_691, 4757) - // Standard Error: 50_351 - .saturating_add(Weight::from_parts(1_112_950, 0).saturating_mul(t.into())) + // Measured: `1163 + t * (206 ±0)` + // Estimated: `4628 + t * (2417 ±0)` + // Minimum execution time: 30_368_000 picoseconds. + Weight::from_parts(31_023_429, 4628) + // Standard Error: 43_250 + .saturating_add(Weight::from_parts(5_949_452, 0).saturating_mul(t.into())) // Standard Error: 0 - .saturating_add(Weight::from_parts(1, 0).saturating_mul(i.into())) + .saturating_add(Weight::from_parts(2, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(t.into()))) .saturating_add(T::DbWeight::get().writes(1_u64)) - .saturating_add(Weight::from_parts(0, 2480).saturating_mul(t.into())) + .saturating_add(Weight::from_parts(0, 2417).saturating_mul(t.into())) } /// Storage: `Revive::ContractInfoOf` (r:1 w:0) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) + /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) /// Storage: `Revive::CodeInfoOf` (r:1 w:0) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:1 w:0) /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) fn seal_delegate_call() -> Weight { // Proof Size summary in bytes: - // Measured: `1237` - // Estimated: `4702` - // Minimum execution time: 35_759_000 picoseconds. - Weight::from_parts(37_086_000, 4702) + // Measured: `1108` + // Estimated: `4573` + // Minimum execution time: 24_707_000 picoseconds. + Weight::from_parts(25_410_000, 4573) .saturating_add(T::DbWeight::get().reads(3_u64)) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) @@ -905,18 +908,18 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { /// Storage: `Revive::PristineCode` (r:1 w:0) /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) /// Storage: `Revive::ContractInfoOf` (r:1 w:1) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) + /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) /// The range of component `i` is `[0, 262144]`. fn seal_instantiate(i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1271` - // Estimated: `4710` - // Minimum execution time: 116_485_000 picoseconds. - Weight::from_parts(108_907_717, 4710) - // Standard Error: 12 - .saturating_add(Weight::from_parts(4_125, 0).saturating_mul(i.into())) + // Measured: `1094` + // Estimated: `4579` + // Minimum execution time: 107_232_000 picoseconds. + Weight::from_parts(94_844_854, 4579) + // Standard Error: 10 + .saturating_add(Weight::from_parts(4_159, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -925,95 +928,73 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 651_000 picoseconds. - Weight::from_parts(3_867_609, 0) - // Standard Error: 3 - .saturating_add(Weight::from_parts(1_384, 0).saturating_mul(n.into())) + // Minimum execution time: 617_000 picoseconds. + Weight::from_parts(3_460_054, 0) + // Standard Error: 2 + .saturating_add(Weight::from_parts(1_374, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 262144]`. fn seal_hash_keccak_256(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_090_000 picoseconds. - Weight::from_parts(5_338_460, 0) - // Standard Error: 3 - .saturating_add(Weight::from_parts(3_601, 0).saturating_mul(n.into())) + // Minimum execution time: 1_040_000 picoseconds. + Weight::from_parts(3_026_644, 0) + // Standard Error: 2 + .saturating_add(Weight::from_parts(3_607, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 262144]`. fn seal_hash_blake2_256(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 717_000 picoseconds. - Weight::from_parts(2_629_461, 0) - // Standard Error: 3 - .saturating_add(Weight::from_parts(1_528, 0).saturating_mul(n.into())) + // Minimum execution time: 633_000 picoseconds. + Weight::from_parts(3_375_104, 0) + // Standard Error: 2 + .saturating_add(Weight::from_parts(1_494, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 262144]`. fn seal_hash_blake2_128(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 660_000 picoseconds. - Weight::from_parts(4_807_814, 0) - // Standard Error: 3 - .saturating_add(Weight::from_parts(1_509, 0).saturating_mul(n.into())) + // Minimum execution time: 601_000 picoseconds. + Weight::from_parts(3_802_060, 0) + // Standard Error: 2 + .saturating_add(Weight::from_parts(1_493, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 261889]`. fn seal_sr25519_verify(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 42_829_000 picoseconds. - Weight::from_parts(24_650_992, 0) - // Standard Error: 14 - .saturating_add(Weight::from_parts(5_212, 0).saturating_mul(n.into())) + // Minimum execution time: 42_419_000 picoseconds. + Weight::from_parts(26_760_986, 0) + // Standard Error: 12 + .saturating_add(Weight::from_parts(5_421, 0).saturating_mul(n.into())) } fn seal_ecdsa_recover() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 46_902_000 picoseconds. - Weight::from_parts(48_072_000, 0) + // Minimum execution time: 48_672_000 picoseconds. + Weight::from_parts(49_840_000, 0) } fn seal_ecdsa_to_eth_address() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 12_713_000 picoseconds. - Weight::from_parts(12_847_000, 0) + // Minimum execution time: 12_307_000 picoseconds. + Weight::from_parts(12_500_000, 0) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) fn seal_set_code_hash() -> Weight { // Proof Size summary in bytes: - // Measured: `300` - // Estimated: `3765` - // Minimum execution time: 17_657_000 picoseconds. - Weight::from_parts(18_419_000, 3765) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - /// Storage: `Revive::CodeInfoOf` (r:1 w:1) - /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) - fn lock_delegate_dependency() -> Weight { - // Proof Size summary in bytes: - // Measured: `338` - // Estimated: `3803` - // Minimum execution time: 13_650_000 picoseconds. - Weight::from_parts(14_209_000, 3803) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - /// Storage: `Revive::CodeInfoOf` (r:1 w:1) - /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `MaxEncodedLen`) - fn unlock_delegate_dependency() -> Weight { - // Proof Size summary in bytes: - // Measured: `338` - // Estimated: `3561` - // Minimum execution time: 12_341_000 picoseconds. - Weight::from_parts(13_011_000, 3561) + // Measured: `196` + // Estimated: `3661` + // Minimum execution time: 10_142_000 picoseconds. + Weight::from_parts(10_458_000, 3661) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -1022,10 +1003,10 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 8_899_000 picoseconds. - Weight::from_parts(10_489_171, 0) - // Standard Error: 104 - .saturating_add(Weight::from_parts(73_814, 0).saturating_mul(r.into())) + // Minimum execution time: 7_893_000 picoseconds. + Weight::from_parts(9_362_667, 0) + // Standard Error: 84 + .saturating_add(Weight::from_parts(74_272, 0).saturating_mul(r.into())) } } @@ -1035,10 +1016,10 @@ impl WeightInfo for () { /// Proof: `Revive::DeletionQueueCounter` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) fn on_process_deletion_queue_batch() -> Weight { // Proof Size summary in bytes: - // Measured: `109` - // Estimated: `1594` - // Minimum execution time: 2_859_000 picoseconds. - Weight::from_parts(3_007_000, 1594) + // Measured: `0` + // Estimated: `1485` + // Minimum execution time: 695_000 picoseconds. + Weight::from_parts(750_000, 1485) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -1046,12 +1027,12 @@ impl WeightInfo for () { /// The range of component `k` is `[0, 1024]`. fn on_initialize_per_trie_key(k: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `425 + k * (69 ±0)` - // Estimated: `415 + k * (70 ±0)` - // Minimum execution time: 15_640_000 picoseconds. - Weight::from_parts(1_609_026, 415) - // Standard Error: 1_359 - .saturating_add(Weight::from_parts(1_204_420, 0).saturating_mul(k.into())) + // Measured: `230 + k * (69 ±0)` + // Estimated: `222 + k * (70 ±0)` + // Minimum execution time: 10_509_000 picoseconds. + Weight::from_parts(10_896_000, 222) + // Standard Error: 2_549 + .saturating_add(Weight::from_parts(1_264_033, 0).saturating_mul(k.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(k.into()))) .saturating_add(RocksDbWeight::get().writes(2_u64)) @@ -1061,7 +1042,7 @@ impl WeightInfo for () { /// Storage: `Revive::AddressSuffix` (r:2 w:0) /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) /// Storage: `Revive::ContractInfoOf` (r:1 w:1) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) + /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) /// Storage: `Revive::CodeInfoOf` (r:1 w:0) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:1 w:0) @@ -1073,21 +1054,21 @@ impl WeightInfo for () { /// The range of component `c` is `[0, 262144]`. fn call_with_code_per_byte(_c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1463` - // Estimated: `7403` - // Minimum execution time: 89_437_000 picoseconds. - Weight::from_parts(94_285_182, 7403) + // Measured: `1194` + // Estimated: `7134` + // Minimum execution time: 84_008_000 picoseconds. + Weight::from_parts(91_138_296, 7134) .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Balances::Holds` (r:2 w:2) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(355), added: 2830, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(409), added: 2884, mode: `Measured`) /// Storage: `Revive::AddressSuffix` (r:1 w:0) /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) /// Storage: `Revive::ContractInfoOf` (r:1 w:1) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) + /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) /// Storage: `Timestamp::Now` (r:1 w:0) /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `System::Account` (r:1 w:1) @@ -1096,16 +1077,14 @@ impl WeightInfo for () { /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) /// The range of component `c` is `[0, 262144]`. /// The range of component `i` is `[0, 262144]`. - fn instantiate_with_code(c: u32, i: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `364` - // Estimated: `6327` - // Minimum execution time: 187_904_000 picoseconds. - Weight::from_parts(153_252_081, 6327) - // Standard Error: 11 - .saturating_add(Weight::from_parts(49, 0).saturating_mul(c.into())) - // Standard Error: 11 - .saturating_add(Weight::from_parts(4_528, 0).saturating_mul(i.into())) + fn instantiate_with_code(_c: u32, i: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `93` + // Estimated: `6033` + // Minimum execution time: 172_907_000 picoseconds. + Weight::from_parts(153_592_465, 6033) + // Standard Error: 12 + .saturating_add(Weight::from_parts(4_544, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } @@ -1116,29 +1095,29 @@ impl WeightInfo for () { /// Storage: `Revive::AddressSuffix` (r:1 w:0) /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) /// Storage: `Revive::ContractInfoOf` (r:1 w:1) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) + /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) /// Storage: `Timestamp::Now` (r:1 w:0) /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(355), added: 2830, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(409), added: 2884, mode: `Measured`) /// The range of component `i` is `[0, 262144]`. fn instantiate(i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1296` - // Estimated: `4758` - // Minimum execution time: 154_656_000 picoseconds. - Weight::from_parts(139_308_398, 4758) + // Measured: `987` + // Estimated: `4452` + // Minimum execution time: 143_169_000 picoseconds. + Weight::from_parts(120_653_436, 4452) // Standard Error: 16 - .saturating_add(Weight::from_parts(4_421, 0).saturating_mul(i.into())) + .saturating_add(Weight::from_parts(4_444, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } /// Storage: `Revive::AddressSuffix` (r:2 w:0) /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) /// Storage: `Revive::ContractInfoOf` (r:1 w:1) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) + /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) /// Storage: `Revive::CodeInfoOf` (r:1 w:0) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:1 w:0) @@ -1149,82 +1128,80 @@ impl WeightInfo for () { /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) fn call() -> Weight { // Proof Size summary in bytes: - // Measured: `1463` - // Estimated: `7403` - // Minimum execution time: 138_815_000 picoseconds. - Weight::from_parts(149_067_000, 7403) + // Measured: `1194` + // Estimated: `7134` + // Minimum execution time: 138_392_000 picoseconds. + Weight::from_parts(143_329_000, 7134) .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(355), added: 2830, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(409), added: 2884, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:0 w:1) /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) /// The range of component `c` is `[0, 262144]`. - fn upload_code(c: u32, ) -> Weight { + fn upload_code(_c: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `109` - // Estimated: `3574` - // Minimum execution time: 49_978_000 picoseconds. - Weight::from_parts(51_789_325, 3574) - // Standard Error: 0 - .saturating_add(Weight::from_parts(1, 0).saturating_mul(c.into())) + // Measured: `0` + // Estimated: `3465` + // Minimum execution time: 43_420_000 picoseconds. + Weight::from_parts(45_143_767, 3465) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(355), added: 2830, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(409), added: 2884, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:0 w:1) /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) fn remove_code() -> Weight { // Proof Size summary in bytes: - // Measured: `285` - // Estimated: `3750` - // Minimum execution time: 43_833_000 picoseconds. - Weight::from_parts(44_660_000, 3750) + // Measured: `181` + // Estimated: `3646` + // Minimum execution time: 35_828_000 picoseconds. + Weight::from_parts(36_853_000, 3646) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// Storage: `Revive::ContractInfoOf` (r:1 w:1) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) + /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) /// Storage: `Revive::CodeInfoOf` (r:2 w:2) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) fn set_code() -> Weight { // Proof Size summary in bytes: - // Measured: `529` - // Estimated: `6469` - // Minimum execution time: 26_717_000 picoseconds. - Weight::from_parts(28_566_000, 6469) + // Measured: `424` + // Estimated: `6364` + // Minimum execution time: 19_678_000 picoseconds. + Weight::from_parts(21_266_000, 6364) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// Storage: `Revive::AddressSuffix` (r:1 w:1) /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(355), added: 2830, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(409), added: 2884, mode: `Measured`) fn map_account() -> Weight { // Proof Size summary in bytes: - // Measured: `109` - // Estimated: `3574` - // Minimum execution time: 39_401_000 picoseconds. - Weight::from_parts(40_542_000, 3574) + // Measured: `0` + // Estimated: `3465` + // Minimum execution time: 37_024_000 picoseconds. + Weight::from_parts(37_440_000, 3465) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } /// Storage: `Balances::Holds` (r:1 w:1) - /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(355), added: 2830, mode: `Measured`) + /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(409), added: 2884, mode: `Measured`) /// Storage: `Revive::AddressSuffix` (r:0 w:1) /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) fn unmap_account() -> Weight { // Proof Size summary in bytes: // Measured: `56` // Estimated: `3521` - // Minimum execution time: 31_570_000 picoseconds. - Weight::from_parts(32_302_000, 3521) + // Minimum execution time: 31_228_000 picoseconds. + Weight::from_parts(32_183_000, 3521) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1234,10 +1211,10 @@ impl WeightInfo for () { /// Proof: `TxPause::PausedCalls` (`max_values`: None, `max_size`: Some(532), added: 3007, mode: `Measured`) fn dispatch_as_fallback_account() -> Weight { // Proof Size summary in bytes: - // Measured: `145` - // Estimated: `3610` - // Minimum execution time: 13_607_000 picoseconds. - Weight::from_parts(13_903_000, 3610) + // Measured: `0` + // Estimated: `3465` + // Minimum execution time: 6_241_000 picoseconds. + Weight::from_parts(6_467_000, 3465) .saturating_add(RocksDbWeight::get().reads(2_u64)) } /// The range of component `r` is `[0, 1600]`. @@ -1245,115 +1222,115 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_400_000 picoseconds. - Weight::from_parts(8_388_251, 0) - // Standard Error: 283 - .saturating_add(Weight::from_parts(165_630, 0).saturating_mul(r.into())) + // Minimum execution time: 6_397_000 picoseconds. + Weight::from_parts(7_159_300, 0) + // Standard Error: 173 + .saturating_add(Weight::from_parts(167_265, 0).saturating_mul(r.into())) } fn seal_caller() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 275_000 picoseconds. - Weight::from_parts(305_000, 0) + // Minimum execution time: 267_000 picoseconds. + Weight::from_parts(296_000, 0) } fn seal_origin() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 224_000 picoseconds. - Weight::from_parts(265_000, 0) + // Minimum execution time: 227_000 picoseconds. + Weight::from_parts(252_000, 0) } /// Storage: `Revive::ContractInfoOf` (r:1 w:0) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) + /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) fn seal_is_contract() -> Weight { // Proof Size summary in bytes: - // Measured: `306` - // Estimated: `3771` - // Minimum execution time: 10_004_000 picoseconds. - Weight::from_parts(10_336_000, 3771) + // Measured: `202` + // Estimated: `3667` + // Minimum execution time: 6_591_000 picoseconds. + Weight::from_parts(6_770_000, 3667) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `Revive::AddressSuffix` (r:1 w:0) /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) fn seal_to_account_id() -> Weight { // Proof Size summary in bytes: - // Measured: `212` - // Estimated: `3677` - // Minimum execution time: 4_000_000 picoseconds. - Weight::from_parts(4_000_000, 3677) + // Measured: `144` + // Estimated: `3609` + // Minimum execution time: 6_182_000 picoseconds. + Weight::from_parts(6_372_000, 3609) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `Revive::ContractInfoOf` (r:1 w:0) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) + /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) fn seal_code_hash() -> Weight { // Proof Size summary in bytes: - // Measured: `403` - // Estimated: `3868` - // Minimum execution time: 11_054_000 picoseconds. - Weight::from_parts(11_651_000, 3868) + // Measured: `298` + // Estimated: `3763` + // Minimum execution time: 7_327_000 picoseconds. + Weight::from_parts(7_612_000, 3763) .saturating_add(RocksDbWeight::get().reads(1_u64)) } fn seal_own_code_hash() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 252_000 picoseconds. - Weight::from_parts(305_000, 0) + // Minimum execution time: 232_000 picoseconds. + Weight::from_parts(287_000, 0) } /// Storage: `Revive::ContractInfoOf` (r:1 w:0) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) + /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) /// Storage: `Revive::CodeInfoOf` (r:1 w:0) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) fn seal_code_size() -> Weight { // Proof Size summary in bytes: - // Measured: `473` - // Estimated: `3938` - // Minimum execution time: 14_461_000 picoseconds. - Weight::from_parts(15_049_000, 3938) + // Measured: `368` + // Estimated: `3833` + // Minimum execution time: 10_918_000 picoseconds. + Weight::from_parts(11_323_000, 3833) .saturating_add(RocksDbWeight::get().reads(2_u64)) } fn seal_caller_is_origin() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 312_000 picoseconds. - Weight::from_parts(338_000, 0) + // Minimum execution time: 310_000 picoseconds. + Weight::from_parts(340_000, 0) } fn seal_caller_is_root() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 243_000 picoseconds. - Weight::from_parts(299_000, 0) + // Minimum execution time: 257_000 picoseconds. + Weight::from_parts(292_000, 0) } fn seal_address() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 231_000 picoseconds. - Weight::from_parts(271_000, 0) + // Minimum execution time: 240_000 picoseconds. + Weight::from_parts(249_000, 0) } fn seal_weight_left() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 683_000 picoseconds. - Weight::from_parts(732_000, 0) + // Minimum execution time: 599_000 picoseconds. + Weight::from_parts(645_000, 0) } fn seal_ref_time_left() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 226_000 picoseconds. - Weight::from_parts(273_000, 0) + // Minimum execution time: 208_000 picoseconds. + Weight::from_parts(244_000, 0) } fn seal_balance() -> Weight { // Proof Size summary in bytes: // Measured: `102` // Estimated: `0` - // Minimum execution time: 4_626_000 picoseconds. - Weight::from_parts(4_842_000, 0) + // Minimum execution time: 4_534_000 picoseconds. + Weight::from_parts(4_689_000, 0) } /// Storage: `Revive::AddressSuffix` (r:1 w:0) /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) @@ -1361,10 +1338,10 @@ impl WeightInfo for () { /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) fn seal_balance_of() -> Weight { // Proof Size summary in bytes: - // Measured: `264` - // Estimated: `3729` - // Minimum execution time: 12_309_000 picoseconds. - Weight::from_parts(12_653_000, 3729) + // Measured: `160` + // Estimated: `3625` + // Minimum execution time: 8_640_000 picoseconds. + Weight::from_parts(8_971_000, 3625) .saturating_add(RocksDbWeight::get().reads(2_u64)) } /// Storage: `Revive::ImmutableDataOf` (r:1 w:0) @@ -1372,12 +1349,12 @@ impl WeightInfo for () { /// The range of component `n` is `[1, 4096]`. fn seal_get_immutable_data(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `238 + n * (1 ±0)` - // Estimated: `3703 + n * (1 ±0)` - // Minimum execution time: 5_838_000 picoseconds. - Weight::from_parts(9_570_778, 3703) - // Standard Error: 19 - .saturating_add(Weight::from_parts(721, 0).saturating_mul(n.into())) + // Measured: `134 + n * (1 ±0)` + // Estimated: `3599 + n * (1 ±0)` + // Minimum execution time: 4_875_000 picoseconds. + Weight::from_parts(6_212_863, 3599) + // Standard Error: 7 + .saturating_add(Weight::from_parts(671, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -1388,195 +1365,199 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_910_000 picoseconds. - Weight::from_parts(2_205_396, 0) + // Minimum execution time: 1_678_000 picoseconds. + Weight::from_parts(1_883_150, 0) // Standard Error: 2 - .saturating_add(Weight::from_parts(538, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(579, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().writes(1_u64)) } fn seal_value_transferred() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 224_000 picoseconds. - Weight::from_parts(274_000, 0) + // Minimum execution time: 238_000 picoseconds. + Weight::from_parts(273_000, 0) } fn seal_minimum_balance() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 231_000 picoseconds. - Weight::from_parts(279_000, 0) + // Minimum execution time: 244_000 picoseconds. + Weight::from_parts(260_000, 0) } fn seal_return_data_size() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 229_000 picoseconds. - Weight::from_parts(267_000, 0) + // Minimum execution time: 249_000 picoseconds. + Weight::from_parts(265_000, 0) } fn seal_call_data_size() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 218_000 picoseconds. - Weight::from_parts(267_000, 0) + // Minimum execution time: 243_000 picoseconds. + Weight::from_parts(269_000, 0) } fn seal_gas_limit() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 225_000 picoseconds. - Weight::from_parts(280_000, 0) + // Minimum execution time: 228_000 picoseconds. + Weight::from_parts(268_000, 0) } fn seal_gas_price() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 274_000 picoseconds. - Weight::from_parts(323_000, 0) + // Minimum execution time: 222_000 picoseconds. + Weight::from_parts(251_000, 0) } fn seal_base_fee() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 239_000 picoseconds. - Weight::from_parts(290_000, 0) + // Minimum execution time: 226_000 picoseconds. + Weight::from_parts(250_000, 0) } fn seal_block_number() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 224_000 picoseconds. - Weight::from_parts(274_000, 0) + // Minimum execution time: 228_000 picoseconds. + Weight::from_parts(270_000, 0) + } + /// Storage: `Session::Validators` (r:1 w:0) + /// Proof: `Session::Validators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + fn seal_block_author() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `1485` + // Minimum execution time: 13_597_000 picoseconds. + Weight::from_parts(13_770_000, 1485) + .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `System::BlockHash` (r:1 w:0) /// Proof: `System::BlockHash` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `Measured`) fn seal_block_hash() -> Weight { // Proof Size summary in bytes: - // Measured: `30` - // Estimated: `3495` - // Minimum execution time: 3_430_000 picoseconds. - Weight::from_parts(3_692_000, 3495) + // Measured: `0` + // Estimated: `3465` + // Minimum execution time: 2_199_000 picoseconds. + Weight::from_parts(2_402_000, 3465) .saturating_add(RocksDbWeight::get().reads(1_u64)) } fn seal_now() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 241_000 picoseconds. - Weight::from_parts(290_000, 0) + // Minimum execution time: 230_000 picoseconds. + Weight::from_parts(256_000, 0) } fn seal_weight_to_fee() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_355_000 picoseconds. - Weight::from_parts(1_493_000, 0) + // Minimum execution time: 1_214_000 picoseconds. + Weight::from_parts(1_283_000, 0) } /// The range of component `n` is `[0, 262140]`. fn seal_copy_to_contract(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 348_000 picoseconds. - Weight::from_parts(1_004_890, 0) + // Minimum execution time: 376_000 picoseconds. + Weight::from_parts(569_136, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(202, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(236, 0).saturating_mul(n.into())) } fn seal_call_data_load() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 222_000 picoseconds. - Weight::from_parts(256_000, 0) + // Minimum execution time: 243_000 picoseconds. + Weight::from_parts(260_000, 0) } /// The range of component `n` is `[0, 262144]`. fn seal_call_data_copy(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 240_000 picoseconds. - Weight::from_parts(330_609, 0) + // Minimum execution time: 231_000 picoseconds. + Weight::from_parts(379_088, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(114, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(148, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 262140]`. fn seal_return(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 232_000 picoseconds. - Weight::from_parts(264_000, 0) + // Minimum execution time: 227_000 picoseconds. + Weight::from_parts(400_572, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(208, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(237, 0).saturating_mul(n.into())) } /// Storage: `Revive::AddressSuffix` (r:1 w:0) /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) /// Storage: `Revive::DeletionQueueCounter` (r:1 w:1) /// Proof: `Revive::DeletionQueueCounter` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `Measured`) - /// Storage: `Revive::CodeInfoOf` (r:33 w:33) + /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Revive::DeletionQueue` (r:0 w:1) /// Proof: `Revive::DeletionQueue` (`max_values`: None, `max_size`: Some(142), added: 2617, mode: `Measured`) /// Storage: `Revive::ImmutableDataOf` (r:0 w:1) /// Proof: `Revive::ImmutableDataOf` (`max_values`: None, `max_size`: Some(4118), added: 6593, mode: `Measured`) - /// The range of component `n` is `[0, 32]`. - fn seal_terminate(n: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `322 + n * (88 ±0)` - // Estimated: `3787 + n * (2563 ±0)` - // Minimum execution time: 21_920_000 picoseconds. - Weight::from_parts(21_725_868, 3787) - // Standard Error: 11_165 - .saturating_add(Weight::from_parts(4_317_986, 0).saturating_mul(n.into())) + fn seal_terminate() -> Weight { + // Proof Size summary in bytes: + // Measured: `215` + // Estimated: `3680` + // Minimum execution time: 14_216_000 picoseconds. + Weight::from_parts(14_533_000, 3680) .saturating_add(RocksDbWeight::get().reads(3_u64)) - .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(RocksDbWeight::get().writes(4_u64)) - .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) - .saturating_add(Weight::from_parts(0, 2563).saturating_mul(n.into())) } /// The range of component `t` is `[0, 4]`. - /// The range of component `n` is `[0, 448]`. + /// The range of component `n` is `[0, 416]`. fn seal_deposit_event(t: u32, n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_140_000 picoseconds. - Weight::from_parts(4_259_301, 0) - // Standard Error: 3_362 - .saturating_add(Weight::from_parts(194_546, 0).saturating_mul(t.into())) - // Standard Error: 34 - .saturating_add(Weight::from_parts(774, 0).saturating_mul(n.into())) + // Minimum execution time: 3_877_000 picoseconds. + Weight::from_parts(3_856_832, 0) + // Standard Error: 2_622 + .saturating_add(Weight::from_parts(201_206, 0).saturating_mul(t.into())) + // Standard Error: 28 + .saturating_add(Weight::from_parts(1_128, 0).saturating_mul(n.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) fn get_storage_empty() -> Weight { // Proof Size summary in bytes: - // Measured: `680` - // Estimated: `680` - // Minimum execution time: 10_747_000 picoseconds. - Weight::from_parts(11_276_000, 680) + // Measured: `552` + // Estimated: `552` + // Minimum execution time: 5_806_000 picoseconds. + Weight::from_parts(6_037_000, 552) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) fn get_storage_full() -> Weight { // Proof Size summary in bytes: - // Measured: `10690` - // Estimated: `10690` - // Minimum execution time: 42_076_000 picoseconds. - Weight::from_parts(43_381_000, 10690) + // Measured: `10562` + // Estimated: `10562` + // Minimum execution time: 39_517_000 picoseconds. + Weight::from_parts(40_698_000, 10562) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) fn set_storage_empty() -> Weight { // Proof Size summary in bytes: - // Measured: `680` - // Estimated: `680` - // Minimum execution time: 11_703_000 picoseconds. - Weight::from_parts(12_308_000, 680) + // Measured: `552` + // Estimated: `552` + // Minimum execution time: 6_747_000 picoseconds. + Weight::from_parts(7_003_000, 552) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1584,85 +1565,85 @@ impl WeightInfo for () { /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) fn set_storage_full() -> Weight { // Proof Size summary in bytes: - // Measured: `10690` - // Estimated: `10690` - // Minimum execution time: 43_460_000 picoseconds. - Weight::from_parts(45_165_000, 10690) + // Measured: `10562` + // Estimated: `10562` + // Minimum execution time: 40_158_000 picoseconds. + Weight::from_parts(41_394_000, 10562) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `n` is `[0, 448]`. - /// The range of component `o` is `[0, 448]`. + /// The range of component `n` is `[0, 416]`. + /// The range of component `o` is `[0, 416]`. fn seal_set_storage(n: u32, o: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `248 + o * (1 ±0)` - // Estimated: `247 + o * (1 ±0)` - // Minimum execution time: 9_087_000 picoseconds. - Weight::from_parts(11_787_486, 247) - // Standard Error: 179 - .saturating_add(Weight::from_parts(976, 0).saturating_mul(n.into())) - // Standard Error: 179 - .saturating_add(Weight::from_parts(3_151, 0).saturating_mul(o.into())) + // Measured: `152 + o * (1 ±0)` + // Estimated: `151 + o * (1 ±0)` + // Minimum execution time: 6_360_000 picoseconds. + Weight::from_parts(7_335_152, 151) + // Standard Error: 80 + .saturating_add(Weight::from_parts(716, 0).saturating_mul(n.into())) + // Standard Error: 80 + .saturating_add(Weight::from_parts(1_127, 0).saturating_mul(o.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(o.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `n` is `[0, 448]`. + /// The range of component `n` is `[0, 416]`. fn seal_clear_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `248 + n * (1 ±0)` - // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 8_611_000 picoseconds. - Weight::from_parts(11_791_390, 247) - // Standard Error: 308 - .saturating_add(Weight::from_parts(3_943, 0).saturating_mul(n.into())) + // Measured: `152 + n * (1 ±0)` + // Estimated: `151 + n * (1 ±0)` + // Minimum execution time: 5_980_000 picoseconds. + Weight::from_parts(7_164_266, 151) + // Standard Error: 130 + .saturating_add(Weight::from_parts(1_893, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `n` is `[0, 448]`. + /// The range of component `n` is `[0, 416]`. fn seal_get_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `248 + n * (1 ±0)` - // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 8_389_000 picoseconds. - Weight::from_parts(11_625_480, 247) - // Standard Error: 315 - .saturating_add(Weight::from_parts(4_487, 0).saturating_mul(n.into())) + // Measured: `152 + n * (1 ±0)` + // Estimated: `151 + n * (1 ±0)` + // Minimum execution time: 5_823_000 picoseconds. + Weight::from_parts(7_045_557, 151) + // Standard Error: 123 + .saturating_add(Weight::from_parts(2_222, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `n` is `[0, 448]`. + /// The range of component `n` is `[0, 416]`. fn seal_contains_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `248 + n * (1 ±0)` - // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 7_947_000 picoseconds. - Weight::from_parts(10_970_587, 247) - // Standard Error: 310 - .saturating_add(Weight::from_parts(3_675, 0).saturating_mul(n.into())) + // Measured: `152 + n * (1 ±0)` + // Estimated: `151 + n * (1 ±0)` + // Minimum execution time: 5_349_000 picoseconds. + Weight::from_parts(6_506_216, 151) + // Standard Error: 127 + .saturating_add(Weight::from_parts(1_605, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) - /// The range of component `n` is `[0, 448]`. + /// The range of component `n` is `[0, 416]`. fn seal_take_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `248 + n * (1 ±0)` - // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 9_071_000 picoseconds. - Weight::from_parts(12_525_027, 247) - // Standard Error: 328 - .saturating_add(Weight::from_parts(4_427, 0).saturating_mul(n.into())) + // Measured: `152 + n * (1 ±0)` + // Estimated: `151 + n * (1 ±0)` + // Minimum execution time: 6_151_000 picoseconds. + Weight::from_parts(7_812_180, 151) + // Standard Error: 159 + .saturating_add(Weight::from_parts(2_277, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -1671,94 +1652,94 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_487_000 picoseconds. - Weight::from_parts(1_611_000, 0) + // Minimum execution time: 1_344_000 picoseconds. + Weight::from_parts(1_462_000, 0) } fn set_transient_storage_full() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_852_000 picoseconds. - Weight::from_parts(1_982_000, 0) + // Minimum execution time: 1_680_000 picoseconds. + Weight::from_parts(1_785_000, 0) } fn get_transient_storage_empty() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_467_000 picoseconds. - Weight::from_parts(1_529_000, 0) + // Minimum execution time: 1_380_000 picoseconds. + Weight::from_parts(1_502_000, 0) } fn get_transient_storage_full() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_630_000 picoseconds. - Weight::from_parts(1_712_000, 0) + // Minimum execution time: 1_506_000 picoseconds. + Weight::from_parts(1_604_000, 0) } fn rollback_transient_storage() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_188_000 picoseconds. - Weight::from_parts(1_268_000, 0) + // Minimum execution time: 972_000 picoseconds. + Weight::from_parts(1_054_000, 0) } - /// The range of component `n` is `[0, 448]`. - /// The range of component `o` is `[0, 448]`. + /// The range of component `n` is `[0, 416]`. + /// The range of component `o` is `[0, 416]`. fn seal_set_transient_storage(n: u32, o: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_197_000 picoseconds. - Weight::from_parts(2_464_654, 0) + // Minimum execution time: 2_048_000 picoseconds. + Weight::from_parts(2_304_120, 0) // Standard Error: 17 - .saturating_add(Weight::from_parts(296, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(254, 0).saturating_mul(n.into())) // Standard Error: 17 - .saturating_add(Weight::from_parts(342, 0).saturating_mul(o.into())) + .saturating_add(Weight::from_parts(321, 0).saturating_mul(o.into())) } - /// The range of component `n` is `[0, 448]`. + /// The range of component `n` is `[0, 416]`. fn seal_clear_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_005_000 picoseconds. - Weight::from_parts(2_381_053, 0) - // Standard Error: 23 - .saturating_add(Weight::from_parts(322, 0).saturating_mul(n.into())) + // Minimum execution time: 1_790_000 picoseconds. + Weight::from_parts(2_141_874, 0) + // Standard Error: 31 + .saturating_add(Weight::from_parts(378, 0).saturating_mul(n.into())) } - /// The range of component `n` is `[0, 448]`. + /// The range of component `n` is `[0, 416]`. fn seal_get_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_853_000 picoseconds. - Weight::from_parts(2_082_772, 0) - // Standard Error: 20 - .saturating_add(Weight::from_parts(322, 0).saturating_mul(n.into())) + // Minimum execution time: 1_662_000 picoseconds. + Weight::from_parts(1_938_172, 0) + // Standard Error: 14 + .saturating_add(Weight::from_parts(316, 0).saturating_mul(n.into())) } - /// The range of component `n` is `[0, 448]`. + /// The range of component `n` is `[0, 416]`. fn seal_contains_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_711_000 picoseconds. - Weight::from_parts(1_899_649, 0) - // Standard Error: 16 - .saturating_add(Weight::from_parts(208, 0).saturating_mul(n.into())) + // Minimum execution time: 1_570_000 picoseconds. + Weight::from_parts(1_769_617, 0) + // Standard Error: 13 + .saturating_add(Weight::from_parts(152, 0).saturating_mul(n.into())) } - /// The range of component `n` is `[0, 448]`. + /// The range of component `n` is `[0, 416]`. fn seal_take_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_460_000 picoseconds. - Weight::from_parts(2_684_364, 0) - // Standard Error: 22 - .saturating_add(Weight::from_parts(56, 0).saturating_mul(n.into())) + // Minimum execution time: 2_266_000 picoseconds. + Weight::from_parts(2_497_430, 0) + // Standard Error: 21 + .saturating_add(Weight::from_parts(38, 0).saturating_mul(n.into())) } /// Storage: `Revive::AddressSuffix` (r:1 w:0) /// Proof: `Revive::AddressSuffix` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `Measured`) /// Storage: `Revive::ContractInfoOf` (r:1 w:0) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) + /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) /// Storage: `Revive::CodeInfoOf` (r:1 w:0) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:1 w:0) @@ -1769,31 +1750,31 @@ impl WeightInfo for () { /// The range of component `i` is `[0, 262144]`. fn seal_call(t: u32, i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1292 + t * (203 ±0)` - // Estimated: `4757 + t * (2480 ±0)` - // Minimum execution time: 40_031_000 picoseconds. - Weight::from_parts(41_527_691, 4757) - // Standard Error: 50_351 - .saturating_add(Weight::from_parts(1_112_950, 0).saturating_mul(t.into())) + // Measured: `1163 + t * (206 ±0)` + // Estimated: `4628 + t * (2417 ±0)` + // Minimum execution time: 30_368_000 picoseconds. + Weight::from_parts(31_023_429, 4628) + // Standard Error: 43_250 + .saturating_add(Weight::from_parts(5_949_452, 0).saturating_mul(t.into())) // Standard Error: 0 - .saturating_add(Weight::from_parts(1, 0).saturating_mul(i.into())) + .saturating_add(Weight::from_parts(2, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(t.into()))) .saturating_add(RocksDbWeight::get().writes(1_u64)) - .saturating_add(Weight::from_parts(0, 2480).saturating_mul(t.into())) + .saturating_add(Weight::from_parts(0, 2417).saturating_mul(t.into())) } /// Storage: `Revive::ContractInfoOf` (r:1 w:0) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) + /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) /// Storage: `Revive::CodeInfoOf` (r:1 w:0) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:1 w:0) /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) fn seal_delegate_call() -> Weight { // Proof Size summary in bytes: - // Measured: `1237` - // Estimated: `4702` - // Minimum execution time: 35_759_000 picoseconds. - Weight::from_parts(37_086_000, 4702) + // Measured: `1108` + // Estimated: `4573` + // Minimum execution time: 24_707_000 picoseconds. + Weight::from_parts(25_410_000, 4573) .saturating_add(RocksDbWeight::get().reads(3_u64)) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) @@ -1801,18 +1782,18 @@ impl WeightInfo for () { /// Storage: `Revive::PristineCode` (r:1 w:0) /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: Some(262180), added: 264655, mode: `Measured`) /// Storage: `Revive::ContractInfoOf` (r:1 w:1) - /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(1779), added: 4254, mode: `Measured`) + /// Proof: `Revive::ContractInfoOf` (`max_values`: None, `max_size`: Some(242), added: 2717, mode: `Measured`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) /// The range of component `i` is `[0, 262144]`. fn seal_instantiate(i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1271` - // Estimated: `4710` - // Minimum execution time: 116_485_000 picoseconds. - Weight::from_parts(108_907_717, 4710) - // Standard Error: 12 - .saturating_add(Weight::from_parts(4_125, 0).saturating_mul(i.into())) + // Measured: `1094` + // Estimated: `4579` + // Minimum execution time: 107_232_000 picoseconds. + Weight::from_parts(94_844_854, 4579) + // Standard Error: 10 + .saturating_add(Weight::from_parts(4_159, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -1821,95 +1802,73 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 651_000 picoseconds. - Weight::from_parts(3_867_609, 0) - // Standard Error: 3 - .saturating_add(Weight::from_parts(1_384, 0).saturating_mul(n.into())) + // Minimum execution time: 617_000 picoseconds. + Weight::from_parts(3_460_054, 0) + // Standard Error: 2 + .saturating_add(Weight::from_parts(1_374, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 262144]`. fn seal_hash_keccak_256(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_090_000 picoseconds. - Weight::from_parts(5_338_460, 0) - // Standard Error: 3 - .saturating_add(Weight::from_parts(3_601, 0).saturating_mul(n.into())) + // Minimum execution time: 1_040_000 picoseconds. + Weight::from_parts(3_026_644, 0) + // Standard Error: 2 + .saturating_add(Weight::from_parts(3_607, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 262144]`. fn seal_hash_blake2_256(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 717_000 picoseconds. - Weight::from_parts(2_629_461, 0) - // Standard Error: 3 - .saturating_add(Weight::from_parts(1_528, 0).saturating_mul(n.into())) + // Minimum execution time: 633_000 picoseconds. + Weight::from_parts(3_375_104, 0) + // Standard Error: 2 + .saturating_add(Weight::from_parts(1_494, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 262144]`. fn seal_hash_blake2_128(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 660_000 picoseconds. - Weight::from_parts(4_807_814, 0) - // Standard Error: 3 - .saturating_add(Weight::from_parts(1_509, 0).saturating_mul(n.into())) + // Minimum execution time: 601_000 picoseconds. + Weight::from_parts(3_802_060, 0) + // Standard Error: 2 + .saturating_add(Weight::from_parts(1_493, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 261889]`. fn seal_sr25519_verify(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 42_829_000 picoseconds. - Weight::from_parts(24_650_992, 0) - // Standard Error: 14 - .saturating_add(Weight::from_parts(5_212, 0).saturating_mul(n.into())) + // Minimum execution time: 42_419_000 picoseconds. + Weight::from_parts(26_760_986, 0) + // Standard Error: 12 + .saturating_add(Weight::from_parts(5_421, 0).saturating_mul(n.into())) } fn seal_ecdsa_recover() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 46_902_000 picoseconds. - Weight::from_parts(48_072_000, 0) + // Minimum execution time: 48_672_000 picoseconds. + Weight::from_parts(49_840_000, 0) } fn seal_ecdsa_to_eth_address() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 12_713_000 picoseconds. - Weight::from_parts(12_847_000, 0) + // Minimum execution time: 12_307_000 picoseconds. + Weight::from_parts(12_500_000, 0) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) fn seal_set_code_hash() -> Weight { // Proof Size summary in bytes: - // Measured: `300` - // Estimated: `3765` - // Minimum execution time: 17_657_000 picoseconds. - Weight::from_parts(18_419_000, 3765) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - /// Storage: `Revive::CodeInfoOf` (r:1 w:1) - /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `Measured`) - fn lock_delegate_dependency() -> Weight { - // Proof Size summary in bytes: - // Measured: `338` - // Estimated: `3803` - // Minimum execution time: 13_650_000 picoseconds. - Weight::from_parts(14_209_000, 3803) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - /// Storage: `Revive::CodeInfoOf` (r:1 w:1) - /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(96), added: 2571, mode: `MaxEncodedLen`) - fn unlock_delegate_dependency() -> Weight { - // Proof Size summary in bytes: - // Measured: `338` - // Estimated: `3561` - // Minimum execution time: 12_341_000 picoseconds. - Weight::from_parts(13_011_000, 3561) + // Measured: `196` + // Estimated: `3661` + // Minimum execution time: 10_142_000 picoseconds. + Weight::from_parts(10_458_000, 3661) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1918,9 +1877,9 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 8_899_000 picoseconds. - Weight::from_parts(10_489_171, 0) - // Standard Error: 104 - .saturating_add(Weight::from_parts(73_814, 0).saturating_mul(r.into())) + // Minimum execution time: 7_893_000 picoseconds. + Weight::from_parts(9_362_667, 0) + // Standard Error: 84 + .saturating_add(Weight::from_parts(74_272, 0).saturating_mul(r.into())) } } diff --git a/substrate/frame/revive/uapi/src/host.rs b/substrate/frame/revive/uapi/src/host.rs index 3e5cf0eb0c243d44c19368bd9cf7305fb418b829..8e14eefc636455c6280208b1ec94586bd5ab7cbb 100644 --- a/substrate/frame/revive/uapi/src/host.rs +++ b/substrate/frame/revive/uapi/src/host.rs @@ -144,18 +144,6 @@ pub trait HostFn: private::Sealed { /// - `output`: A reference to the output data buffer to write the origin's address. fn origin(output: &mut [u8; 20]); - /// Retrieve the account id for a specified address. - /// - /// # Parameters - /// - /// - `addr`: A `H160` address. - /// - `output`: A reference to the output data buffer to write the account id. - /// - /// # Note - /// - /// If no mapping exists for `addr`, the fallback account id will be returned. - fn to_account_id(addr: &[u8; 20], output: &mut [u8]); - /// Retrieve the code hash for a specified contract address. /// /// # Parameters @@ -300,14 +288,14 @@ pub trait HostFn: private::Sealed { /// /// # Parameters /// - /// - `code_hash`: The hash of the code to be instantiated. /// - `ref_time_limit`: how much *ref_time* Weight to devote to the execution. /// - `proof_size_limit`: how much *proof_size* Weight to devote to the execution. /// - `deposit`: The storage deposit limit for instantiation. Passing `None` means setting no /// specific limit for the call, which implies storage usage up to the limit of the parent /// call. /// - `value`: The value to transfer into the contract. - /// - `input`: The input data buffer. + /// - `input`: The code hash and constructor input data buffer. The first 32 bytes are the code + /// hash of the code to be instantiated. The remaining bytes are the constructor call data. /// - `address`: A reference to the address buffer to write the address of the contract. If /// `None` is provided then the output buffer is not copied. /// - `output`: A reference to the return value buffer to write the constructor output buffer. @@ -327,7 +315,6 @@ pub trait HostFn: private::Sealed { /// - [TransferFailed][`crate::ReturnErrorCode::TransferFailed] /// - [OutOfResources][`crate::ReturnErrorCode::OutOfResources] fn instantiate( - code_hash: &[u8; 32], ref_time_limit: u64, proof_size_limit: u64, deposit: &[u8; 32], @@ -410,14 +397,33 @@ pub trait HostFn: private::Sealed { /// Returns the amount of ref_time left. fn ref_time_left() -> u64; + /// Stores the current block author of into the supplied buffer. + /// + /// # Parameters + /// + /// - `output`: A reference to the output data buffer to write the block author. + fn block_author(output: &mut [u8; 20]); + /// Stores the current block number of the current contract into the supplied buffer. /// /// # Parameters /// /// - `output`: A reference to the output data buffer to write the block number. - #[unstable_hostfn] fn block_number(output: &mut [u8; 32]); + /// Retrieve the account id for a specified address. + /// + /// # Parameters + /// + /// - `addr`: A `H160` address. + /// - `output`: A reference to the output data buffer to write the account id. + /// + /// # Note + /// + /// If no mapping exists for `addr`, the fallback account id will be returned. + #[unstable_hostfn] + fn to_account_id(addr: &[u8; 20], output: &mut [u8]); + /// Stores the block hash of the given block number into the supplied buffer. /// /// # Parameters @@ -615,18 +621,6 @@ pub trait HostFn: private::Sealed { #[unstable_hostfn] fn is_contract(address: &[u8; 20]) -> bool; - /// Lock a new delegate dependency to the contract. - /// - /// Traps if the maximum number of delegate_dependencies is reached or if - /// the delegate dependency already exists. - /// - /// # Parameters - /// - /// - `code_hash`: The code hash of the dependency. Should be decodable as an `T::Hash`. Traps - /// otherwise. - #[unstable_hostfn] - fn lock_delegate_dependency(code_hash: &[u8; 32]); - /// Stores the minimum balance (a.k.a. existential deposit) into the supplied buffer. /// /// # Parameters @@ -717,17 +711,6 @@ pub trait HostFn: private::Sealed { #[unstable_hostfn] fn terminate(beneficiary: &[u8; 20]) -> !; - /// Removes the delegate dependency from the contract. - /// - /// Traps if the delegate dependency does not exist. - /// - /// # Parameters - /// - /// - `code_hash`: The code hash of the dependency. Should be decodable as an `T::Hash`. Traps - /// otherwise. - #[unstable_hostfn] - fn unlock_delegate_dependency(code_hash: &[u8; 32]); - /// Stores the amount of weight left into the supplied buffer. /// The data is encoded as Weight. /// diff --git a/substrate/frame/revive/uapi/src/host/riscv64.rs b/substrate/frame/revive/uapi/src/host/riscv64.rs index 3726564e26ebaea2982912e63ad08924774790ed..588579dc83ebfb7287f516e324a0e792f9c4d181 100644 --- a/substrate/frame/revive/uapi/src/host/riscv64.rs +++ b/substrate/frame/revive/uapi/src/host/riscv64.rs @@ -16,7 +16,7 @@ use crate::{ host::{CallFlags, HostFn, HostFnImpl, Result, StorageFlags}, - ReturnFlags, + pack_hi_lo, ReturnFlags, }; use pallet_revive_proc_macro::unstable_hostfn; @@ -59,9 +59,30 @@ mod sys { out_ptr: *mut u8, out_len_ptr: *mut u32, ) -> ReturnCode; - pub fn call(ptr: *const u8) -> ReturnCode; - pub fn delegate_call(ptr: *const u8) -> ReturnCode; - pub fn instantiate(ptr: *const u8) -> ReturnCode; + pub fn call( + flags_and_callee: u64, + ref_time_limit: u64, + proof_size_limit: u64, + deposit_and_value: u64, + input_data: u64, + output_data: u64, + ) -> ReturnCode; + pub fn delegate_call( + flags_and_callee: u64, + ref_time_limit: u64, + proof_size_limit: u64, + deposit_ptr: *const u8, + input_data: u64, + output_data: u64, + ) -> ReturnCode; + pub fn instantiate( + ref_time_limit: u64, + proof_size_limit: u64, + deposit_and_value: u64, + input_data: u64, + output_data: u64, + address_and_salt: u64, + ) -> ReturnCode; pub fn terminate(beneficiary_ptr: *const u8); pub fn call_data_copy(out_ptr: *mut u8, out_len: u32, offset: u32); pub fn call_data_load(out_ptr: *mut u8, offset: u32); @@ -99,6 +120,7 @@ mod sys { pub fn call_data_size() -> u64; pub fn block_number(out_ptr: *mut u8); pub fn block_hash(block_number_ptr: *const u8, out_ptr: *mut u8); + pub fn block_author(out_ptr: *mut u8); pub fn hash_sha2_256(input_ptr: *const u8, input_len: u32, out_ptr: *mut u8); pub fn hash_keccak_256(input_ptr: *const u8, input_len: u32, out_ptr: *mut u8); pub fn hash_blake2_256(input_ptr: *const u8, input_len: u32, out_ptr: *mut u8); @@ -125,8 +147,6 @@ mod sys { pub fn set_code_hash(code_hash_ptr: *const u8); pub fn ecdsa_to_eth_address(key_ptr: *const u8, out_ptr: *mut u8) -> ReturnCode; pub fn instantiation_nonce() -> u64; - pub fn lock_delegate_dependency(code_hash_ptr: *const u8); - pub fn unlock_delegate_dependency(code_hash_ptr: *const u8); pub fn xcm_execute(msg_ptr: *const u8, msg_len: u32) -> ReturnCode; pub fn xcm_send( dest_ptr: *const u8, @@ -165,7 +185,6 @@ fn ptr_or_sentinel(data: &Option<&[u8; 32]>) -> *const u8 { impl HostFn for HostFnImpl { fn instantiate( - code_hash: &[u8; 32], ref_time_limit: u64, proof_size_limit: u64, deposit_limit: &[u8; 32], @@ -179,42 +198,28 @@ impl HostFn for HostFnImpl { Some(ref mut data) => data.as_mut_ptr(), None => crate::SENTINEL as _, }; - let (output_ptr, mut output_len) = ptr_len_or_sentinel(&mut output); + let (output_ptr, mut output_len_ptr) = ptr_len_or_sentinel(&mut output); let deposit_limit_ptr = deposit_limit.as_ptr(); let salt_ptr = ptr_or_sentinel(&salt); - #[repr(C)] - #[allow(dead_code)] - struct Args { - code_hash: u32, - ref_time_limit: u64, - proof_size_limit: u64, - deposit_limit: u32, - value: u32, - input: u32, - input_len: u32, - address: u32, - output: u32, - output_len: u32, - salt: u32, - } - let args = Args { - code_hash: code_hash.as_ptr() as _, - ref_time_limit, - proof_size_limit, - deposit_limit: deposit_limit_ptr as _, - value: value.as_ptr() as _, - input: input.as_ptr() as _, - input_len: input.len() as _, - address: address as _, - output: output_ptr as _, - output_len: &mut output_len as *mut _ as _, - salt: salt_ptr as _, - }; - let ret_code = { unsafe { sys::instantiate(&args as *const Args as *const _) } }; + let deposit_and_value = pack_hi_lo(deposit_limit_ptr as _, value.as_ptr() as _); + let address_and_salt = pack_hi_lo(address as _, salt_ptr as _); + let input_data = pack_hi_lo(input.len() as _, input.as_ptr() as _); + let output_data = pack_hi_lo(&mut output_len_ptr as *mut _ as _, output_ptr as _); + + let ret_code = unsafe { + sys::instantiate( + ref_time_limit, + proof_size_limit, + deposit_and_value, + input_data, + output_data, + address_and_salt, + ) + }; if let Some(ref mut output) = output { - extract_from_slice(output, output_len as usize); + extract_from_slice(output, output_len_ptr as usize); } ret_code.into() @@ -232,34 +237,22 @@ impl HostFn for HostFnImpl { ) -> Result { let (output_ptr, mut output_len) = ptr_len_or_sentinel(&mut output); let deposit_limit_ptr = deposit_limit.as_ptr(); - #[repr(C)] - #[allow(dead_code)] - struct Args { - flags: u32, - callee: u32, - ref_time_limit: u64, - proof_size_limit: u64, - deposit_limit: u32, - value: u32, - input: u32, - input_len: u32, - output: u32, - output_len: u32, - } - let args = Args { - flags: flags.bits(), - callee: callee.as_ptr() as _, - ref_time_limit, - proof_size_limit, - deposit_limit: deposit_limit_ptr as _, - value: value.as_ptr() as _, - input: input.as_ptr() as _, - input_len: input.len() as _, - output: output_ptr as _, - output_len: &mut output_len as *mut _ as _, - }; - let ret_code = { unsafe { sys::call(&args as *const Args as *const _) } }; + let flags_and_callee = pack_hi_lo(flags.bits(), callee.as_ptr() as _); + let deposit_and_value = pack_hi_lo(deposit_limit_ptr as _, value.as_ptr() as _); + let input_data = pack_hi_lo(input.len() as _, input.as_ptr() as _); + let output_data = pack_hi_lo(&mut output_len as *mut _ as _, output_ptr as _); + + let ret_code = unsafe { + sys::call( + flags_and_callee, + ref_time_limit, + proof_size_limit, + deposit_and_value, + input_data, + output_data, + ) + }; if let Some(ref mut output) = output { extract_from_slice(output, output_len as usize); @@ -279,32 +272,21 @@ impl HostFn for HostFnImpl { ) -> Result { let (output_ptr, mut output_len) = ptr_len_or_sentinel(&mut output); let deposit_limit_ptr = deposit_limit.as_ptr(); - #[repr(C)] - #[allow(dead_code)] - struct Args { - flags: u32, - address: u32, - ref_time_limit: u64, - proof_size_limit: u64, - deposit_limit: u32, - input: u32, - input_len: u32, - output: u32, - output_len: u32, - } - let args = Args { - flags: flags.bits(), - address: address.as_ptr() as _, - ref_time_limit, - proof_size_limit, - deposit_limit: deposit_limit_ptr as _, - input: input.as_ptr() as _, - input_len: input.len() as _, - output: output_ptr as _, - output_len: &mut output_len as *mut _ as _, - }; - let ret_code = { unsafe { sys::delegate_call(&args as *const Args as *const _) } }; + let flags_and_callee = pack_hi_lo(flags.bits(), address.as_ptr() as u32); + let input_data = pack_hi_lo(input.len() as u32, input.as_ptr() as u32); + let output_data = pack_hi_lo(&mut output_len as *mut _ as u32, output_ptr as u32); + + let ret_code = unsafe { + sys::delegate_call( + flags_and_callee, + ref_time_limit, + proof_size_limit, + deposit_limit_ptr as _, + input_data, + output_data, + ) + }; if let Some(ref mut output) = output { extract_from_slice(output, output_len as usize); @@ -411,6 +393,10 @@ impl HostFn for HostFnImpl { unsafe { sys::block_number(output.as_mut_ptr()) } } + fn block_author(output: &mut [u8; 20]) { + unsafe { sys::block_author(output.as_mut_ptr()) } + } + fn weight_to_fee(ref_time_limit: u64, proof_size_limit: u64, output: &mut [u8; 32]) { unsafe { sys::weight_to_fee(ref_time_limit, proof_size_limit, output.as_mut_ptr()) }; } @@ -563,11 +549,6 @@ impl HostFn for HostFnImpl { ret_val.into_bool() } - #[unstable_hostfn] - fn lock_delegate_dependency(code_hash: &[u8; 32]) { - unsafe { sys::lock_delegate_dependency(code_hash.as_ptr()) } - } - #[unstable_hostfn] fn minimum_balance(output: &mut [u8; 32]) { unsafe { sys::minimum_balance(output.as_mut_ptr()) } @@ -620,11 +601,6 @@ impl HostFn for HostFnImpl { panic!("terminate does not return"); } - #[unstable_hostfn] - fn unlock_delegate_dependency(code_hash: &[u8; 32]) { - unsafe { sys::unlock_delegate_dependency(code_hash.as_ptr()) } - } - #[unstable_hostfn] fn weight_left(output: &mut &mut [u8]) { let mut output_len = output.len() as u32; diff --git a/substrate/frame/revive/uapi/src/lib.rs b/substrate/frame/revive/uapi/src/lib.rs index 867f356339876a433f01248780c9cdab6c8ebb7e..744a2f0bca5d194c1b78c9369b36aa57bbf3321f 100644 --- a/substrate/frame/revive/uapi/src/lib.rs +++ b/substrate/frame/revive/uapi/src/lib.rs @@ -98,6 +98,9 @@ define_error_codes! { XcmExecutionFailed = 9, /// The `xcm_send` call failed. XcmSendFailed = 10, + /// Contract instantiation failed because the address already exists. + /// Occurs when instantiating the same contract with the same salt more than once. + DuplicateContractAddress = 11, } /// The raw return code returned by the host side. @@ -131,3 +134,14 @@ impl ReturnCode { } type Result = core::result::Result<(), ReturnErrorCode>; + +/// Helper to pack two `u32` values into a `u64` register. +/// +/// Pointers to PVM memory are always 32 bit in size. Thus contracts can pack two +/// pointers into a single register when calling a syscall API method. +/// +/// This is done in syscall API methods where the number of arguments is exceeding +/// the available registers. +pub fn pack_hi_lo(hi: u32, lo: u32) -> u64 { + ((hi as u64) << 32) | lo as u64 +} diff --git a/substrate/frame/staking/src/pallet/mod.rs b/substrate/frame/staking/src/pallet/mod.rs index 7d5da9ea0c49753e0db14092b978d0c88b6dcd63..9d8914627397fcc1bc19249e49f65b81b8e4d7e9 100644 --- a/substrate/frame/staking/src/pallet/mod.rs +++ b/substrate/frame/staking/src/pallet/mod.rs @@ -1552,7 +1552,7 @@ pub mod pallet { let _ = ledger .set_payee(payee) - .defensive_proof("ledger was retrieved from storage, thus its bonded; qed.")?; + .defensive_proof("ledger was retrieved from storage, thus it's bonded; qed.")?; Ok(()) } diff --git a/substrate/frame/support/procedural/examples/proc_main/main.rs b/substrate/frame/support/procedural/examples/proc_main/main.rs index 4bdfc76dd92f0821865fbe7a74fbf0bea77f35e3..946bd5ff03ed298824ec7edd0ba31c8885d5df0f 100644 --- a/substrate/frame/support/procedural/examples/proc_main/main.rs +++ b/substrate/frame/support/procedural/examples/proc_main/main.rs @@ -234,7 +234,8 @@ mod runtime { RuntimeHoldReason, RuntimeSlashReason, RuntimeLockId, - RuntimeTask + RuntimeTask, + RuntimeViewFunction )] pub struct Runtime; diff --git a/substrate/frame/support/procedural/examples/proc_main/runtime.rs b/substrate/frame/support/procedural/examples/proc_main/runtime.rs index 109ca4f6dc488228cc596c2d3ff2447aa4cacff4..8de560555895bf64b3e21d8c0e892b77d6e77d4a 100644 --- a/substrate/frame/support/procedural/examples/proc_main/runtime.rs +++ b/substrate/frame/support/procedural/examples/proc_main/runtime.rs @@ -99,7 +99,8 @@ mod runtime { RuntimeHoldReason, RuntimeSlashReason, RuntimeLockId, - RuntimeTask + RuntimeTask, + RuntimeViewFunction )] pub struct Runtime; diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/call.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/call.rs index f055e8ce28e904639dba11f9f7639bf64c934d95..411d74ecbb3d23c84e5b62c14e10a1b047e49248 100644 --- a/substrate/frame/support/procedural/src/construct_runtime/expand/call.rs +++ b/substrate/frame/support/procedural/src/construct_runtime/expand/call.rs @@ -18,7 +18,6 @@ use crate::construct_runtime::Pallet; use proc_macro2::TokenStream; use quote::quote; -use std::str::FromStr; use syn::Ident; pub fn expand_outer_dispatch( @@ -40,15 +39,7 @@ pub fn expand_outer_dispatch( let name = &pallet_declaration.name; let path = &pallet_declaration.path; let index = pallet_declaration.index; - let attr = - pallet_declaration.cfg_pattern.iter().fold(TokenStream::new(), |acc, pattern| { - let attr = TokenStream::from_str(&format!("#[cfg({})]", pattern.original())) - .expect("was successfully parsed before; qed"); - quote! { - #acc - #attr - } - }); + let attr = pallet_declaration.get_attributes(); variant_defs.extend(quote! { #attr diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/config.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/config.rs index dbbe6ba6e6c32ec09a8514033108617883075243..7a51ba6ecf1da9c9f9af5abe83f85fee59323995 100644 --- a/substrate/frame/support/procedural/src/construct_runtime/expand/config.rs +++ b/substrate/frame/support/procedural/src/construct_runtime/expand/config.rs @@ -19,7 +19,6 @@ use crate::construct_runtime::Pallet; use inflector::Inflector; use proc_macro2::TokenStream; use quote::{format_ident, quote, ToTokens}; -use std::str::FromStr; use syn::Ident; pub fn expand_outer_config( @@ -41,14 +40,7 @@ pub fn expand_outer_config( let field_name = &Ident::new(&pallet_name.to_string().to_snake_case(), decl.name.span()); let part_is_generic = !pallet_entry.generics.params.is_empty(); - let attr = &decl.cfg_pattern.iter().fold(TokenStream::new(), |acc, pattern| { - let attr = TokenStream::from_str(&format!("#[cfg({})]", pattern.original())) - .expect("was successfully parsed before; qed"); - quote! { - #acc - #attr - } - }); + let attr = &decl.get_attributes(); types.extend(expand_config_types(attr, runtime, decl, &config, part_is_generic)); fields.extend(quote!(#attr pub #field_name: #config,)); diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/inherent.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/inherent.rs index e34c6ac5016a9f8597fae03f6012f1e7d2f79659..e25492802c3293d02321b2b1fcc0f26aabe8dce4 100644 --- a/substrate/frame/support/procedural/src/construct_runtime/expand/inherent.rs +++ b/substrate/frame/support/procedural/src/construct_runtime/expand/inherent.rs @@ -18,7 +18,6 @@ use crate::construct_runtime::Pallet; use proc_macro2::TokenStream; use quote::quote; -use std::str::FromStr; use syn::Ident; pub fn expand_outer_inherent( @@ -36,14 +35,7 @@ pub fn expand_outer_inherent( if pallet_decl.exists_part("Inherent") { let name = &pallet_decl.name; let path = &pallet_decl.path; - let attr = pallet_decl.cfg_pattern.iter().fold(TokenStream::new(), |acc, pattern| { - let attr = TokenStream::from_str(&format!("#[cfg({})]", pattern.original())) - .expect("was successfully parsed before; qed"); - quote! { - #acc - #attr - } - }); + let attr = pallet_decl.get_attributes(); pallet_names.push(name); pallet_attrs.push(attr); diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/metadata.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/metadata.rs index 0b3bd516886513faee90ea367aaf0ed86593e9a3..d246c00628640d8dfd27a133a2c06637b3953eb8 100644 --- a/substrate/frame/support/procedural/src/construct_runtime/expand/metadata.rs +++ b/substrate/frame/support/procedural/src/construct_runtime/expand/metadata.rs @@ -18,7 +18,6 @@ use crate::construct_runtime::{parse::PalletPath, Pallet}; use proc_macro2::TokenStream; use quote::quote; -use std::str::FromStr; use syn::Ident; pub fn expand_runtime_metadata( @@ -51,14 +50,7 @@ pub fn expand_runtime_metadata( let errors = expand_pallet_metadata_errors(runtime, decl); let associated_types = expand_pallet_metadata_associated_types(runtime, decl); let docs = expand_pallet_metadata_docs(runtime, decl); - let attr = decl.cfg_pattern.iter().fold(TokenStream::new(), |acc, pattern| { - let attr = TokenStream::from_str(&format!("#[cfg({})]", pattern.original())) - .expect("was successfully parsed before; qed"); - quote! { - #acc - #attr - } - }); + let attr = decl.get_attributes(); let deprecation_info = expand_pallet_metadata_deprecation(runtime, decl); quote! { #attr @@ -78,6 +70,20 @@ pub fn expand_runtime_metadata( }) .collect::<Vec<_>>(); + let view_functions = pallet_declarations.iter().map(|decl| { + let name = &decl.name; + let path = &decl.path; + let instance = decl.instance.as_ref().into_iter(); + let attr = decl.get_attributes(); + + quote! { + #attr + #path::Pallet::<#runtime #(, #path::#instance)*>::pallet_view_functions_metadata( + ::core::stringify!(#name) + ) + } + }); + quote! { impl #runtime { fn metadata_ir() -> #scrate::__private::metadata_ir::MetadataIR { @@ -149,6 +155,10 @@ pub fn expand_runtime_metadata( >(), event_enum_ty: #scrate::__private::scale_info::meta_type::<RuntimeEvent>(), error_enum_ty: #scrate::__private::scale_info::meta_type::<RuntimeError>(), + }, + view_functions: #scrate::__private::metadata_ir::RuntimeViewFunctionsIR { + ty: #scrate::__private::scale_info::meta_type::<RuntimeViewFunction>(), + groups: #scrate::__private::sp_std::vec![ #(#view_functions),* ], } } } diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/mod.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/mod.rs index 88f9a3c6e33fd3fc99b2f4e511d5a6c0afd9263a..823aa69dbdf2b1a4d725f8b33c28a231a1699977 100644 --- a/substrate/frame/support/procedural/src/construct_runtime/expand/mod.rs +++ b/substrate/frame/support/procedural/src/construct_runtime/expand/mod.rs @@ -28,6 +28,7 @@ mod outer_enums; mod slash_reason; mod task; mod unsigned; +mod view_function; pub use call::expand_outer_dispatch; pub use config::expand_outer_config; @@ -41,3 +42,4 @@ pub use outer_enums::{expand_outer_enum, OuterEnumType}; pub use slash_reason::expand_outer_slash_reason; pub use task::expand_outer_task; pub use unsigned::expand_outer_validate_unsigned; +pub use view_function::expand_outer_query; diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/origin.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/origin.rs index 1c4ab436ad92aaee824a7f2916c32483fe443f6f..aada9f7af75b73a0d4b8166e0cbb47f899f8045e 100644 --- a/substrate/frame/support/procedural/src/construct_runtime/expand/origin.rs +++ b/substrate/frame/support/procedural/src/construct_runtime/expand/origin.rs @@ -18,7 +18,6 @@ use crate::construct_runtime::{Pallet, SYSTEM_PALLET_NAME}; use proc_macro2::TokenStream; use quote::quote; -use std::str::FromStr; use syn::{Generics, Ident}; pub fn expand_outer_origin( @@ -210,6 +209,7 @@ pub fn expand_outer_origin( system(#system_path::Origin<#runtime>), #caller_variants #[allow(dead_code)] + #[codec(skip)] Void(#scrate::__private::Void) } @@ -335,14 +335,7 @@ fn expand_origin_caller_variant( let part_is_generic = !generics.params.is_empty(); let variant_name = &pallet.name; let path = &pallet.path; - let attr = pallet.cfg_pattern.iter().fold(TokenStream::new(), |acc, pattern| { - let attr = TokenStream::from_str(&format!("#[cfg({})]", pattern.original())) - .expect("was successfully parsed before; qed"); - quote! { - #acc - #attr - } - }); + let attr = pallet.get_attributes(); match instance { Some(inst) if part_is_generic => quote! { @@ -387,14 +380,7 @@ fn expand_origin_pallet_conversions( }; let doc_string = get_intra_doc_string(" Convert to runtime origin using", &path.module_name()); - let attr = pallet.cfg_pattern.iter().fold(TokenStream::new(), |acc, pattern| { - let attr = TokenStream::from_str(&format!("#[cfg({})]", pattern.original())) - .expect("was successfully parsed before; qed"); - quote! { - #acc - #attr - } - }); + let attr = pallet.get_attributes(); quote! { #attr diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/outer_enums.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/outer_enums.rs index 80b242ccbe493607a59e672b7f0958fc9d0a213c..80d3a5af26627f9cdcdb58cd1ef6645c523dbf86 100644 --- a/substrate/frame/support/procedural/src/construct_runtime/expand/outer_enums.rs +++ b/substrate/frame/support/procedural/src/construct_runtime/expand/outer_enums.rs @@ -18,7 +18,6 @@ use crate::construct_runtime::Pallet; use proc_macro2::{Span, TokenStream}; use quote::{quote, ToTokens}; -use std::str::FromStr; use syn::{Generics, Ident}; /// Represents the types supported for creating an outer enum. @@ -185,14 +184,7 @@ fn expand_enum_variant( let path = &pallet.path; let variant_name = &pallet.name; let part_is_generic = !generics.params.is_empty(); - let attr = pallet.cfg_pattern.iter().fold(TokenStream::new(), |acc, pattern| { - let attr = TokenStream::from_str(&format!("#[cfg({})]", pattern.original())) - .expect("was successfully parsed before; qed"); - quote! { - #acc - #attr - } - }); + let attr = pallet.get_attributes(); match instance { Some(inst) if part_is_generic => quote! { @@ -224,14 +216,7 @@ fn expand_enum_conversion( enum_name_ident: &Ident, ) -> TokenStream { let variant_name = &pallet.name; - let attr = pallet.cfg_pattern.iter().fold(TokenStream::new(), |acc, pattern| { - let attr = TokenStream::from_str(&format!("#[cfg({})]", pattern.original())) - .expect("was successfully parsed before; qed"); - quote! { - #acc - #attr - } - }); + let attr = pallet.get_attributes(); quote! { #attr diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/task.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/task.rs index 1302f86455f2ceeb7af58e46e30b05afccbc44cf..b9b8efb8c006364dc48e25926c158664066a9d65 100644 --- a/substrate/frame/support/procedural/src/construct_runtime/expand/task.rs +++ b/substrate/frame/support/procedural/src/construct_runtime/expand/task.rs @@ -16,7 +16,6 @@ // limitations under the License use crate::construct_runtime::Pallet; -use core::str::FromStr; use proc_macro2::{Ident, TokenStream as TokenStream2}; use quote::quote; @@ -42,14 +41,7 @@ pub fn expand_outer_task( let instance = decl.instance.as_ref().map(|instance| quote!(, #path::#instance)); let task_type = quote!(#path::Task<#runtime_name #instance>); - let attr = decl.cfg_pattern.iter().fold(TokenStream2::new(), |acc, pattern| { - let attr = TokenStream2::from_str(&format!("#[cfg({})]", pattern.original())) - .expect("was successfully parsed before; qed"); - quote! { - #acc - #attr - } - }); + let attr = decl.get_attributes(); from_impls.push(quote! { #attr diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/unsigned.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/unsigned.rs index 33aadba0d1f1c522aae13fb647b9fe8a918d8e24..737a39ea681e0d1c09c458c4b59229f5159136d4 100644 --- a/substrate/frame/support/procedural/src/construct_runtime/expand/unsigned.rs +++ b/substrate/frame/support/procedural/src/construct_runtime/expand/unsigned.rs @@ -18,7 +18,6 @@ use crate::construct_runtime::Pallet; use proc_macro2::TokenStream; use quote::quote; -use std::str::FromStr; use syn::Ident; pub fn expand_outer_validate_unsigned( @@ -34,14 +33,7 @@ pub fn expand_outer_validate_unsigned( if pallet_decl.exists_part("ValidateUnsigned") { let name = &pallet_decl.name; let path = &pallet_decl.path; - let attr = pallet_decl.cfg_pattern.iter().fold(TokenStream::new(), |acc, pattern| { - let attr = TokenStream::from_str(&format!("#[cfg({})]", pattern.original())) - .expect("was successfully parsed before; qed"); - quote! { - #acc - #attr - } - }); + let attr = pallet_decl.get_attributes(); pallet_names.push(name); pallet_attrs.push(attr); diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/view_function.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/view_function.rs new file mode 100644 index 0000000000000000000000000000000000000000..094dcca4a5b5249cfe3026790d9938a84f5649fe --- /dev/null +++ b/substrate/frame/support/procedural/src/construct_runtime/expand/view_function.rs @@ -0,0 +1,78 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License + +use crate::construct_runtime::Pallet; +use proc_macro2::{Ident, Span, TokenStream as TokenStream2}; + +/// Expands implementation of runtime level `DispatchViewFunction`. +pub fn expand_outer_query( + runtime_name: &Ident, + pallet_decls: &[Pallet], + scrate: &TokenStream2, +) -> TokenStream2 { + let runtime_view_function = syn::Ident::new("RuntimeViewFunction", Span::call_site()); + + let prefix_conditionals = pallet_decls.iter().map(|pallet| { + let pallet_name = &pallet.name; + let attr = pallet.get_attributes(); + quote::quote! { + #attr + if id.prefix == <#pallet_name as #scrate::view_functions::ViewFunctionIdPrefix>::prefix() { + return <#pallet_name as #scrate::view_functions::DispatchViewFunction>::dispatch_view_function(id, input, output) + } + } + }); + + quote::quote! { + /// Runtime query type. + #[derive( + Clone, PartialEq, Eq, + #scrate::__private::codec::Encode, + #scrate::__private::codec::Decode, + #scrate::__private::scale_info::TypeInfo, + #scrate::__private::RuntimeDebug, + )] + pub enum #runtime_view_function {} + + const _: () = { + impl #scrate::view_functions::DispatchViewFunction for #runtime_view_function { + fn dispatch_view_function<O: #scrate::__private::codec::Output>( + id: & #scrate::view_functions::ViewFunctionId, + input: &mut &[u8], + output: &mut O + ) -> Result<(), #scrate::view_functions::ViewFunctionDispatchError> + { + #( #prefix_conditionals )* + Err(#scrate::view_functions::ViewFunctionDispatchError::NotFound(id.clone())) + } + } + + impl #runtime_name { + /// Convenience function for query execution from the runtime API. + pub fn execute_view_function( + id: #scrate::view_functions::ViewFunctionId, + input: #scrate::__private::Vec<::core::primitive::u8>, + ) -> Result<#scrate::__private::Vec<::core::primitive::u8>, #scrate::view_functions::ViewFunctionDispatchError> + { + let mut output = #scrate::__private::vec![]; + <#runtime_view_function as #scrate::view_functions::DispatchViewFunction>::dispatch_view_function(&id, &mut &input[..], &mut output)?; + Ok(output) + } + } + }; + } +} diff --git a/substrate/frame/support/procedural/src/construct_runtime/mod.rs b/substrate/frame/support/procedural/src/construct_runtime/mod.rs index 087faf37252de9fc32f8b1ca691c32d52e612982..c6018e048f2f8c15acdc5264a52c35df52c6aa7a 100644 --- a/substrate/frame/support/procedural/src/construct_runtime/mod.rs +++ b/substrate/frame/support/procedural/src/construct_runtime/mod.rs @@ -400,6 +400,7 @@ fn construct_runtime_final_expansion( let dispatch = expand::expand_outer_dispatch(&name, system_pallet, &pallets, &scrate); let tasks = expand::expand_outer_task(&name, &pallets, &scrate); + let query = expand::expand_outer_query(&name, &pallets, &scrate); let metadata = expand::expand_runtime_metadata( &name, &pallets, @@ -492,6 +493,8 @@ fn construct_runtime_final_expansion( #tasks + #query + #metadata #outer_config @@ -650,16 +653,7 @@ pub(crate) fn decl_pallet_runtime_setup( .collect::<Vec<_>>(); let pallet_attrs = pallet_declarations .iter() - .map(|pallet| { - pallet.cfg_pattern.iter().fold(TokenStream2::new(), |acc, pattern| { - let attr = TokenStream2::from_str(&format!("#[cfg({})]", pattern.original())) - .expect("was successfully parsed before; qed"); - quote! { - #acc - #attr - } - }) - }) + .map(|pallet| pallet.get_attributes()) .collect::<Vec<_>>(); quote!( diff --git a/substrate/frame/support/procedural/src/construct_runtime/parse.rs b/substrate/frame/support/procedural/src/construct_runtime/parse.rs index 729a803a302ed7451f890ab6a81b666379d68d07..2df08123821a3972d5053aeb0ce9e6a7e3477a79 100644 --- a/substrate/frame/support/procedural/src/construct_runtime/parse.rs +++ b/substrate/frame/support/procedural/src/construct_runtime/parse.rs @@ -15,6 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +use core::str::FromStr; use frame_support_procedural_tools::syn_ext as ext; use proc_macro2::{Span, TokenStream}; use quote::ToTokens; @@ -609,6 +610,18 @@ impl Pallet { pub fn exists_part(&self, name: &str) -> bool { self.find_part(name).is_some() } + + // Get runtime attributes for the pallet, mostly used for macros + pub fn get_attributes(&self) -> TokenStream { + self.cfg_pattern.iter().fold(TokenStream::new(), |acc, pattern| { + let attr = TokenStream::from_str(&format!("#[cfg({})]", pattern.original())) + .expect("was successfully parsed before; qed"); + quote::quote! { + #acc + #attr + } + }) + } } /// Result of a conversion of a declaration of pallets. diff --git a/substrate/frame/support/procedural/src/lib.rs b/substrate/frame/support/procedural/src/lib.rs index c2f546d92048ac2bc259138b27ac5820227fefd6..26703a2438ef9ad368c3718bc497c9563bb407fe 100644 --- a/substrate/frame/support/procedural/src/lib.rs +++ b/substrate/frame/support/procedural/src/lib.rs @@ -817,6 +817,7 @@ pub fn inject_runtime_type(_: TokenStream, tokens: TokenStream) -> TokenStream { if item.ident != "RuntimeCall" && item.ident != "RuntimeEvent" && item.ident != "RuntimeTask" && + item.ident != "RuntimeViewFunction" && item.ident != "RuntimeOrigin" && item.ident != "RuntimeHoldReason" && item.ident != "RuntimeFreezeReason" && @@ -826,7 +827,7 @@ pub fn inject_runtime_type(_: TokenStream, tokens: TokenStream) -> TokenStream { return syn::Error::new_spanned( item, "`#[inject_runtime_type]` can only be attached to `RuntimeCall`, `RuntimeEvent`, \ - `RuntimeTask`, `RuntimeOrigin`, `RuntimeParameters` or `PalletInfo`", + `RuntimeTask`, `RuntimeViewFunction`, `RuntimeOrigin`, `RuntimeParameters` or `PalletInfo`", ) .to_compile_error() .into(); diff --git a/substrate/frame/support/procedural/src/pallet/expand/mod.rs b/substrate/frame/support/procedural/src/pallet/expand/mod.rs index 3f9b50f79c0ccf8ea37e23cd79d1bd1aead2064f..439ec55e269d43aaab8ec91296c48df970ca6985 100644 --- a/substrate/frame/support/procedural/src/pallet/expand/mod.rs +++ b/substrate/frame/support/procedural/src/pallet/expand/mod.rs @@ -35,6 +35,7 @@ mod tasks; mod tt_default_parts; mod type_value; mod validate_unsigned; +mod view_functions; mod warnings; use crate::pallet::Def; @@ -66,6 +67,7 @@ pub fn expand(mut def: Def) -> proc_macro2::TokenStream { let error = error::expand_error(&mut def); let event = event::expand_event(&mut def); let storages = storage::expand_storages(&mut def); + let view_functions = view_functions::expand_view_functions(&def); let inherents = inherent::expand_inherents(&mut def); let instances = instances::expand_instances(&mut def); let hooks = hooks::expand_hooks(&mut def); @@ -108,6 +110,7 @@ storage item. Otherwise, all storage items are listed among [*Type Definitions*] #error #event #storages + #view_functions #inherents #instances #hooks diff --git a/substrate/frame/support/procedural/src/pallet/expand/view_functions.rs b/substrate/frame/support/procedural/src/pallet/expand/view_functions.rs new file mode 100644 index 0000000000000000000000000000000000000000..587e74a2ac182f2dc817db9bb6058e2c93611bc2 --- /dev/null +++ b/substrate/frame/support/procedural/src/pallet/expand/view_functions.rs @@ -0,0 +1,263 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::pallet::{parse::view_functions::ViewFunctionDef, Def}; +use proc_macro2::{Span, TokenStream}; +use syn::spanned::Spanned; + +pub fn expand_view_functions(def: &Def) -> TokenStream { + let (span, where_clause, view_fns, docs) = match def.view_functions.as_ref() { + Some(view_fns) => ( + view_fns.attr_span, + view_fns.where_clause.clone(), + view_fns.view_functions.clone(), + view_fns.docs.clone(), + ), + None => (def.item.span(), def.config.where_clause.clone(), Vec::new(), Vec::new()), + }; + + let view_function_prefix_impl = + expand_view_function_prefix_impl(def, span, where_clause.as_ref()); + + let view_fn_impls = view_fns + .iter() + .map(|view_fn| expand_view_function(def, span, where_clause.as_ref(), view_fn)); + let impl_dispatch_view_function = + impl_dispatch_view_function(def, span, where_clause.as_ref(), &view_fns); + let impl_view_function_metadata = + impl_view_function_metadata(def, span, where_clause.as_ref(), &view_fns, &docs); + + quote::quote! { + #view_function_prefix_impl + #( #view_fn_impls )* + #impl_dispatch_view_function + #impl_view_function_metadata + } +} + +fn expand_view_function_prefix_impl( + def: &Def, + span: Span, + where_clause: Option<&syn::WhereClause>, +) -> TokenStream { + let pallet_ident = &def.pallet_struct.pallet; + let frame_support = &def.frame_support; + let frame_system = &def.frame_system; + let type_impl_gen = &def.type_impl_generics(span); + let type_use_gen = &def.type_use_generics(span); + + quote::quote! { + impl<#type_impl_gen> #frame_support::view_functions::ViewFunctionIdPrefix for #pallet_ident<#type_use_gen> #where_clause { + fn prefix() -> [::core::primitive::u8; 16usize] { + < + <T as #frame_system::Config>::PalletInfo + as #frame_support::traits::PalletInfo + >::name_hash::<Pallet<#type_use_gen>>() + .expect("No name_hash found for the pallet in the runtime! This usually means that the pallet wasn't added to `construct_runtime!`.") + } + } + } +} + +fn expand_view_function( + def: &Def, + span: Span, + where_clause: Option<&syn::WhereClause>, + view_fn: &ViewFunctionDef, +) -> TokenStream { + let frame_support = &def.frame_support; + let pallet_ident = &def.pallet_struct.pallet; + let type_impl_gen = &def.type_impl_generics(span); + let type_decl_bounded_gen = &def.type_decl_bounded_generics(span); + let type_use_gen = &def.type_use_generics(span); + let capture_docs = if cfg!(feature = "no-metadata-docs") { "never" } else { "always" }; + + let view_function_struct_ident = view_fn.view_function_struct_ident(); + let view_fn_name = &view_fn.name; + let (arg_names, arg_types) = match view_fn.args_names_types() { + Ok((arg_names, arg_types)) => (arg_names, arg_types), + Err(e) => return e.into_compile_error(), + }; + let return_type = &view_fn.return_type; + let docs = &view_fn.docs; + + let view_function_id_suffix_bytes_raw = match view_fn.view_function_id_suffix_bytes() { + Ok(view_function_id_suffix_bytes_raw) => view_function_id_suffix_bytes_raw, + Err(e) => return e.into_compile_error(), + }; + let view_function_id_suffix_bytes = view_function_id_suffix_bytes_raw + .map(|byte| syn::LitInt::new(&format!("0x{:X}_u8", byte), Span::call_site())); + + quote::quote! { + #( #[doc = #docs] )* + #[allow(missing_docs)] + #[derive( + #frame_support::RuntimeDebugNoBound, + #frame_support::CloneNoBound, + #frame_support::EqNoBound, + #frame_support::PartialEqNoBound, + #frame_support::__private::codec::Encode, + #frame_support::__private::codec::Decode, + #frame_support::__private::scale_info::TypeInfo, + )] + #[codec(encode_bound())] + #[codec(decode_bound())] + #[scale_info(skip_type_params(#type_use_gen), capture_docs = #capture_docs)] + pub struct #view_function_struct_ident<#type_decl_bounded_gen> #where_clause { + #( + pub #arg_names: #arg_types, + )* + _marker: ::core::marker::PhantomData<(#type_use_gen,)>, + } + + impl<#type_impl_gen> #view_function_struct_ident<#type_use_gen> #where_clause { + /// Create a new [`#view_function_struct_ident`] instance. + pub fn new(#( #arg_names: #arg_types, )*) -> Self { + Self { + #( #arg_names, )* + _marker: ::core::default::Default::default() + } + } + } + + impl<#type_impl_gen> #frame_support::view_functions::ViewFunctionIdSuffix for #view_function_struct_ident<#type_use_gen> #where_clause { + const SUFFIX: [::core::primitive::u8; 16usize] = [ #( #view_function_id_suffix_bytes ),* ]; + } + + impl<#type_impl_gen> #frame_support::view_functions::ViewFunction for #view_function_struct_ident<#type_use_gen> #where_clause { + fn id() -> #frame_support::view_functions::ViewFunctionId { + #frame_support::view_functions::ViewFunctionId { + prefix: <#pallet_ident<#type_use_gen> as #frame_support::view_functions::ViewFunctionIdPrefix>::prefix(), + suffix: <Self as #frame_support::view_functions::ViewFunctionIdSuffix>::SUFFIX, + } + } + + type ReturnType = #return_type; + + fn invoke(self) -> Self::ReturnType { + let Self { #( #arg_names, )* _marker } = self; + #pallet_ident::<#type_use_gen> :: #view_fn_name( #( #arg_names, )* ) + } + } + } +} + +fn impl_dispatch_view_function( + def: &Def, + span: Span, + where_clause: Option<&syn::WhereClause>, + view_fns: &[ViewFunctionDef], +) -> TokenStream { + let frame_support = &def.frame_support; + let pallet_ident = &def.pallet_struct.pallet; + let type_impl_gen = &def.type_impl_generics(span); + let type_use_gen = &def.type_use_generics(span); + + let query_match_arms = view_fns.iter().map(|view_fn| { + let view_function_struct_ident = view_fn.view_function_struct_ident(); + quote::quote! { + <#view_function_struct_ident<#type_use_gen> as #frame_support::view_functions::ViewFunctionIdSuffix>::SUFFIX => { + <#view_function_struct_ident<#type_use_gen> as #frame_support::view_functions::ViewFunction>::execute(input, output) + } + } + }); + + quote::quote! { + impl<#type_impl_gen> #frame_support::view_functions::DispatchViewFunction + for #pallet_ident<#type_use_gen> #where_clause + { + #[deny(unreachable_patterns)] + fn dispatch_view_function<O: #frame_support::__private::codec::Output>( + id: & #frame_support::view_functions::ViewFunctionId, + input: &mut &[u8], + output: &mut O + ) -> Result<(), #frame_support::view_functions::ViewFunctionDispatchError> + { + match id.suffix { + #( #query_match_arms )* + _ => Err(#frame_support::view_functions::ViewFunctionDispatchError::NotFound(id.clone())), + } + } + } + } +} + +fn impl_view_function_metadata( + def: &Def, + span: Span, + where_clause: Option<&syn::WhereClause>, + view_fns: &[ViewFunctionDef], + docs: &[syn::Expr], +) -> TokenStream { + let frame_support = &def.frame_support; + let pallet_ident = &def.pallet_struct.pallet; + let type_impl_gen = &def.type_impl_generics(span); + let type_use_gen = &def.type_use_generics(span); + + let view_functions = view_fns.iter().map(|view_fn| { + let view_function_struct_ident = view_fn.view_function_struct_ident(); + let name = &view_fn.name; + let args = view_fn.args.iter().filter_map(|fn_arg| { + match fn_arg { + syn::FnArg::Receiver(_) => None, + syn::FnArg::Typed(typed) => { + let pat = &typed.pat; + let ty = &typed.ty; + Some(quote::quote! { + #frame_support::__private::metadata_ir::ViewFunctionArgMetadataIR { + name: ::core::stringify!(#pat), + ty: #frame_support::__private::scale_info::meta_type::<#ty>(), + } + }) + } + } + }); + + let no_docs = vec![]; + let doc = if cfg!(feature = "no-metadata-docs") { &no_docs } else { &view_fn.docs }; + + quote::quote! { + #frame_support::__private::metadata_ir::ViewFunctionMetadataIR { + name: ::core::stringify!(#name), + id: <#view_function_struct_ident<#type_use_gen> as #frame_support::view_functions::ViewFunction>::id().into(), + args: #frame_support::__private::sp_std::vec![ #( #args ),* ], + output: #frame_support::__private::scale_info::meta_type::< + <#view_function_struct_ident<#type_use_gen> as #frame_support::view_functions::ViewFunction>::ReturnType + >(), + docs: #frame_support::__private::sp_std::vec![ #( #doc ),* ], + } + } + }); + + let no_docs = vec![]; + let doc = if cfg!(feature = "no-metadata-docs") { &no_docs } else { docs }; + + quote::quote! { + impl<#type_impl_gen> #pallet_ident<#type_use_gen> #where_clause { + #[doc(hidden)] + pub fn pallet_view_functions_metadata(name: &'static ::core::primitive::str) + -> #frame_support::__private::metadata_ir::ViewFunctionGroupIR + { + #frame_support::__private::metadata_ir::ViewFunctionGroupIR { + name, + view_functions: #frame_support::__private::sp_std::vec![ #( #view_functions ),* ], + docs: #frame_support::__private::sp_std::vec![ #( #doc ),* ], + } + } + } + } +} diff --git a/substrate/frame/support/procedural/src/pallet/parse/mod.rs b/substrate/frame/support/procedural/src/pallet/parse/mod.rs index c9a150effccbee6ecf7ebb308837556828c1c071..89875974b8b5d023c161600a96518ad65cb855fd 100644 --- a/substrate/frame/support/procedural/src/pallet/parse/mod.rs +++ b/substrate/frame/support/procedural/src/pallet/parse/mod.rs @@ -36,6 +36,7 @@ pub mod storage; pub mod tasks; pub mod type_value; pub mod validate_unsigned; +pub mod view_functions; #[cfg(test)] pub mod tests; @@ -70,6 +71,7 @@ pub struct Def { pub frame_system: syn::Path, pub frame_support: syn::Path, pub dev_mode: bool, + pub view_functions: Option<view_functions::ViewFunctionsImplDef>, } impl Def { @@ -103,6 +105,7 @@ impl Def { let mut storages = vec![]; let mut type_values = vec![]; let mut composites: Vec<CompositeDef> = vec![]; + let mut view_functions = None; for (index, item) in items.iter_mut().enumerate() { let pallet_attr: Option<PalletAttr> = helper::take_first_item_pallet_attr(item)?; @@ -205,6 +208,9 @@ impl Def { } composites.push(composite); }, + Some(PalletAttr::ViewFunctions(span)) => { + view_functions = Some(view_functions::ViewFunctionsImplDef::try_from(span, item)?); + } Some(attr) => { let msg = "Invalid duplicated attribute"; return Err(syn::Error::new(attr.span(), msg)) @@ -250,6 +256,7 @@ impl Def { frame_system, frame_support, dev_mode, + view_functions, }; def.check_instance_usage()?; @@ -563,6 +570,7 @@ mod keyword { syn::custom_keyword!(pallet); syn::custom_keyword!(extra_constants); syn::custom_keyword!(composite_enum); + syn::custom_keyword!(view_functions_experimental); } /// The possible values for the `#[pallet::config]` attribute. @@ -652,6 +660,7 @@ enum PalletAttr { TypeValue(proc_macro2::Span), ExtraConstants(proc_macro2::Span), Composite(proc_macro2::Span), + ViewFunctions(proc_macro2::Span), } impl PalletAttr { @@ -677,6 +686,7 @@ impl PalletAttr { Self::TypeValue(span) => *span, Self::ExtraConstants(span) => *span, Self::Composite(span) => *span, + Self::ViewFunctions(span) => *span, } } } @@ -778,6 +788,10 @@ impl syn::parse::Parse for PalletAttr { Ok(PalletAttr::ExtraConstants(content.parse::<keyword::extra_constants>()?.span())) } else if lookahead.peek(keyword::composite_enum) { Ok(PalletAttr::Composite(content.parse::<keyword::composite_enum>()?.span())) + } else if lookahead.peek(keyword::view_functions_experimental) { + Ok(PalletAttr::ViewFunctions( + content.parse::<keyword::view_functions_experimental>()?.span(), + )) } else { Err(lookahead.error()) } diff --git a/substrate/frame/support/procedural/src/pallet/parse/view_functions.rs b/substrate/frame/support/procedural/src/pallet/parse/view_functions.rs new file mode 100644 index 0000000000000000000000000000000000000000..766bcb13da8b3cbddc164a8fdd2a2ecab066f6d4 --- /dev/null +++ b/substrate/frame/support/procedural/src/pallet/parse/view_functions.rs @@ -0,0 +1,155 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governsing permissions and +// limitations under the License. + +use frame_support_procedural_tools::get_doc_literals; +use inflector::Inflector; +use syn::spanned::Spanned; + +/// Parsed representation of an impl block annotated with `pallet::view_functions_experimental`. +pub struct ViewFunctionsImplDef { + /// The where_clause used. + pub where_clause: Option<syn::WhereClause>, + /// The span of the pallet::view_functions_experimental attribute. + pub attr_span: proc_macro2::Span, + /// Docs, specified on the impl Block. + pub docs: Vec<syn::Expr>, + /// The view function definitions. + pub view_functions: Vec<ViewFunctionDef>, +} + +impl ViewFunctionsImplDef { + pub fn try_from(attr_span: proc_macro2::Span, item: &mut syn::Item) -> syn::Result<Self> { + let syn::Item::Impl(item_impl) = item else { + return Err(syn::Error::new( + item.span(), + "Invalid pallet::view_functions_experimental, expected item impl", + )) + }; + let mut view_functions = Vec::new(); + for item in &mut item_impl.items { + if let syn::ImplItem::Fn(method) = item { + if !matches!(method.vis, syn::Visibility::Public(_)) { + let msg = "Invalid pallet::view_functions_experimental, view function must be public: \ + `pub fn`"; + + let span = match method.vis { + syn::Visibility::Inherited => method.sig.span(), + _ => method.vis.span(), + }; + + return Err(syn::Error::new(span, msg)) + } + + let view_fn_def = ViewFunctionDef::try_from(method.clone())?; + view_functions.push(view_fn_def) + } else { + return Err(syn::Error::new( + item.span(), + "Invalid pallet::view_functions_experimental, expected a function", + )) + } + } + Ok(Self { + view_functions, + attr_span, + where_clause: item_impl.generics.where_clause.clone(), + docs: get_doc_literals(&item_impl.attrs), + }) + } +} + +/// Parsed representation of a view function definition. +#[derive(Clone)] +pub struct ViewFunctionDef { + pub name: syn::Ident, + pub docs: Vec<syn::Expr>, + pub args: Vec<syn::FnArg>, + pub return_type: syn::Type, +} + +impl TryFrom<syn::ImplItemFn> for ViewFunctionDef { + type Error = syn::Error; + fn try_from(method: syn::ImplItemFn) -> Result<Self, Self::Error> { + let syn::ReturnType::Type(_, type_) = method.sig.output else { + return Err(syn::Error::new(method.sig.span(), "view functions must return a value")) + }; + + Ok(Self { + name: method.sig.ident.clone(), + docs: get_doc_literals(&method.attrs), + args: method.sig.inputs.iter().cloned().collect::<Vec<_>>(), + return_type: *type_.clone(), + }) + } +} + +impl ViewFunctionDef { + pub fn view_function_struct_ident(&self) -> syn::Ident { + syn::Ident::new( + &format!("{}ViewFunction", self.name.to_string().to_pascal_case()), + self.name.span(), + ) + } + + pub fn view_function_id_suffix_bytes(&self) -> Result<[u8; 16], syn::Error> { + let mut output = [0u8; 16]; + + // concatenate the signature string + let arg_types = self + .args_names_types()? + .1 + .iter() + .map(|ty| quote::quote!(#ty).to_string().replace(" ", "")) + .collect::<Vec<_>>() + .join(","); + let return_type = &self.return_type; + let return_type = quote::quote!(#return_type).to_string().replace(" ", ""); + let view_fn_signature = format!( + "{view_function_name}({arg_types}) -> {return_type}", + view_function_name = &self.name, + ); + + // hash the signature string + let hash = sp_crypto_hashing::twox_128(view_fn_signature.as_bytes()); + output.copy_from_slice(&hash[..]); + Ok(output) + } + + pub fn args_names_types(&self) -> Result<(Vec<syn::Ident>, Vec<syn::Type>), syn::Error> { + Ok(self + .args + .iter() + .map(|arg| { + let syn::FnArg::Typed(pat_type) = arg else { + return Err(syn::Error::new( + arg.span(), + "Unsupported argument in view function", + )); + }; + let syn::Pat::Ident(ident) = &*pat_type.pat else { + return Err(syn::Error::new( + pat_type.pat.span(), + "Unsupported pattern in view function argument", + )); + }; + Ok((ident.ident.clone(), *pat_type.ty.clone())) + }) + .collect::<Result<Vec<(syn::Ident, syn::Type)>, syn::Error>>()? + .into_iter() + .unzip()) + } +} diff --git a/substrate/frame/support/procedural/src/runtime/expand/mod.rs b/substrate/frame/support/procedural/src/runtime/expand/mod.rs index 666bc03aa415df6b495cd479e62cb929f8767cd8..005b109c0eb5fe2a1c79f44f664d2dad47a5bf84 100644 --- a/substrate/frame/support/procedural/src/runtime/expand/mod.rs +++ b/substrate/frame/support/procedural/src/runtime/expand/mod.rs @@ -182,6 +182,7 @@ fn construct_runtime_final_expansion( let mut slash_reason = None; let mut lock_id = None; let mut task = None; + let mut query = None; for runtime_type in runtime_types.iter() { match runtime_type { @@ -224,6 +225,9 @@ fn construct_runtime_final_expansion( RuntimeType::RuntimeTask(_) => { task = Some(expand::expand_outer_task(&name, &pallets, &scrate)); }, + RuntimeType::RuntimeViewFunction(_) => { + query = Some(expand::expand_outer_query(&name, &pallets, &scrate)); + }, } } @@ -301,6 +305,8 @@ fn construct_runtime_final_expansion( #task + #query + #metadata #outer_config diff --git a/substrate/frame/support/procedural/src/runtime/parse/runtime_types.rs b/substrate/frame/support/procedural/src/runtime/parse/runtime_types.rs index a4480e2a1fd32622bea3a7f20294b4c2bee88309..9a385146a811e85211aa0bf6791154ac76276687 100644 --- a/substrate/frame/support/procedural/src/runtime/parse/runtime_types.rs +++ b/substrate/frame/support/procedural/src/runtime/parse/runtime_types.rs @@ -32,6 +32,7 @@ mod keyword { custom_keyword!(RuntimeSlashReason); custom_keyword!(RuntimeLockId); custom_keyword!(RuntimeTask); + custom_keyword!(RuntimeViewFunction); } #[derive(Debug, Clone, PartialEq)] @@ -45,6 +46,7 @@ pub enum RuntimeType { RuntimeSlashReason(keyword::RuntimeSlashReason), RuntimeLockId(keyword::RuntimeLockId), RuntimeTask(keyword::RuntimeTask), + RuntimeViewFunction(keyword::RuntimeViewFunction), } impl Parse for RuntimeType { @@ -69,6 +71,8 @@ impl Parse for RuntimeType { Ok(Self::RuntimeLockId(input.parse()?)) } else if lookahead.peek(keyword::RuntimeTask) { Ok(Self::RuntimeTask(input.parse()?)) + } else if lookahead.peek(keyword::RuntimeViewFunction) { + Ok(Self::RuntimeViewFunction(input.parse()?)) } else { Err(lookahead.error()) } diff --git a/substrate/frame/support/src/lib.rs b/substrate/frame/support/src/lib.rs index a6969260e6a26bedef86f55e7b27689978891aa7..97d16e2a06d23349fe4ea653be73428dde976a68 100644 --- a/substrate/frame/support/src/lib.rs +++ b/substrate/frame/support/src/lib.rs @@ -87,6 +87,7 @@ pub mod storage; #[cfg(test)] mod tests; pub mod traits; +pub mod view_functions; pub mod weights; #[doc(hidden)] pub mod unsigned { diff --git a/substrate/frame/support/src/tests/mod.rs b/substrate/frame/support/src/tests/mod.rs index 7c90a12d4167e376841cb0c5a683d56d36559c5c..b10e719b9ac36caaa7e283de1c9e415d00c9edef 100644 --- a/substrate/frame/support/src/tests/mod.rs +++ b/substrate/frame/support/src/tests/mod.rs @@ -237,7 +237,8 @@ mod runtime { RuntimeHoldReason, RuntimeSlashReason, RuntimeLockId, - RuntimeTask + RuntimeTask, + RuntimeViewFunction )] pub struct Runtime; diff --git a/substrate/frame/support/src/traits/hooks.rs b/substrate/frame/support/src/traits/hooks.rs index 012a74d0ae92f1dcc9c3797f62d2ffc9d137485c..51209cb542467822c51465b6fe4c779aedaf4246 100644 --- a/substrate/frame/support/src/traits/hooks.rs +++ b/substrate/frame/support/src/traits/hooks.rs @@ -584,6 +584,10 @@ pub trait BuildGenesisConfig: sp_runtime::traits::MaybeSerializeDeserialize { fn build(&self); } +impl BuildGenesisConfig for () { + fn build(&self) {} +} + /// A trait to define the build function of a genesis config, T and I are placeholder for pallet /// trait and pallet instance. #[deprecated( diff --git a/substrate/frame/support/src/view_functions.rs b/substrate/frame/support/src/view_functions.rs new file mode 100644 index 0000000000000000000000000000000000000000..dd23fad94a4fd578bdc3d63f86bcb1a1750fe064 --- /dev/null +++ b/substrate/frame/support/src/view_functions.rs @@ -0,0 +1,128 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License fsor the specific language governing permissions and +// limitations under the License. + +//! Traits for querying pallet view functions. + +use alloc::vec::Vec; +use codec::{Decode, DecodeAll, Encode, Output}; +use scale_info::TypeInfo; +use sp_runtime::RuntimeDebug; + +/// The unique identifier for a view function. +#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] +pub struct ViewFunctionId { + /// The part of the id for dispatching view functions from the top level of the runtime. + /// + /// Specifies which view function grouping this view function belongs to. This could be a group + /// of view functions associated with a pallet, or a pallet agnostic group of view functions. + pub prefix: [u8; 16], + /// The part of the id for dispatching to a view function within a group. + pub suffix: [u8; 16], +} + +impl From<ViewFunctionId> for [u8; 32] { + fn from(value: ViewFunctionId) -> Self { + let mut output = [0u8; 32]; + output[..16].copy_from_slice(&value.prefix); + output[16..].copy_from_slice(&value.suffix); + output + } +} + +/// Error type for view function dispatching. +#[derive(Encode, Decode, RuntimeDebug, TypeInfo)] +pub enum ViewFunctionDispatchError { + /// View functions are not implemented for this runtime. + NotImplemented, + /// A view function with the given `ViewFunctionId` was not found + NotFound(ViewFunctionId), + /// Failed to decode the view function input. + Codec, +} + +impl From<codec::Error> for ViewFunctionDispatchError { + fn from(_: codec::Error) -> Self { + ViewFunctionDispatchError::Codec + } +} + +/// Implemented by both pallets and the runtime. The runtime is dispatching by prefix using the +/// pallet implementation of `ViewFunctionIdPrefix` then the pallet is dispatching by suffix using +/// the methods implementation of `ViewFunctionIdSuffix`. +pub trait DispatchViewFunction { + fn dispatch_view_function<O: Output>( + id: &ViewFunctionId, + input: &mut &[u8], + output: &mut O, + ) -> Result<(), ViewFunctionDispatchError>; +} + +impl DispatchViewFunction for () { + fn dispatch_view_function<O: Output>( + _id: &ViewFunctionId, + _input: &mut &[u8], + _output: &mut O, + ) -> Result<(), ViewFunctionDispatchError> { + Err(ViewFunctionDispatchError::NotImplemented) + } +} + +/// Automatically implemented for each pallet by the macro [`pallet`](crate::pallet). +pub trait ViewFunctionIdPrefix { + fn prefix() -> [u8; 16]; +} + +/// Automatically implemented for each pallet view function method by the macro +/// [`pallet`](crate::pallet). +pub trait ViewFunctionIdSuffix { + const SUFFIX: [u8; 16]; +} + +/// Automatically implemented for each pallet view function method by the macro +/// [`pallet`](crate::pallet). +pub trait ViewFunction: DecodeAll { + fn id() -> ViewFunctionId; + type ReturnType: Encode; + + fn invoke(self) -> Self::ReturnType; + + fn execute<O: Output>( + input: &mut &[u8], + output: &mut O, + ) -> Result<(), ViewFunctionDispatchError> { + let view_function = Self::decode_all(input)?; + let result = view_function.invoke(); + Encode::encode_to(&result, output); + Ok(()) + } +} + +pub mod runtime_api { + use super::*; + + sp_api::decl_runtime_apis! { + #[api_version(1)] + /// Runtime API for executing view functions + pub trait RuntimeViewFunction { + /// Execute a view function query. + fn execute_view_function( + query_id: ViewFunctionId, + input: Vec<u8>, + ) -> Result<Vec<u8>, ViewFunctionDispatchError>; + } + } +} diff --git a/substrate/frame/support/test/tests/construct_runtime_ui/deprecated_where_block.stderr b/substrate/frame/support/test/tests/construct_runtime_ui/deprecated_where_block.stderr index 726b09cf54c997b04ffa17a6256cae25e4c17886..faa9cb558c262f09111a488a4e2f4bf114a74375 100644 --- a/substrate/frame/support/test/tests/construct_runtime_ui/deprecated_where_block.stderr +++ b/substrate/frame/support/test/tests/construct_runtime_ui/deprecated_where_block.stderr @@ -561,6 +561,15 @@ note: the trait `Config` must be implemented | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `frame_support::construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info) +error[E0277]: the trait bound `Runtime: Config` is not satisfied + --> tests/construct_runtime_ui/deprecated_where_block.rs:26:3 + | +26 | System: frame_system::{Pallet, Call, Storage, Config<T>, Event<T>}, + | ^^^^^^ the trait `Config` is not implemented for `Runtime`, which is required by `Pallet<Runtime>: ViewFunctionIdPrefix` + | + = help: the trait `ViewFunctionIdPrefix` is implemented for `Pallet<T>` + = note: required for `Pallet<Runtime>` to implement `ViewFunctionIdPrefix` + error[E0599]: the function or associated item `storage_metadata` exists for struct `Pallet<Runtime>`, but its trait bounds were not satisfied --> tests/construct_runtime_ui/deprecated_where_block.rs:20:1 | @@ -736,6 +745,31 @@ note: the trait `Config` must be implemented | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `frame_support::construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info) +error[E0599]: the function or associated item `pallet_view_functions_metadata` exists for struct `Pallet<Runtime>`, but its trait bounds were not satisfied + --> tests/construct_runtime_ui/deprecated_where_block.rs:20:1 + | +20 | construct_runtime! { + | __^ + | | _| + | || +21 | || pub struct Runtime where + | ||______________________- doesn't satisfy `Runtime: Config` +22 | | Block = Block, +23 | | NodeBlock = Block, +... | +27 | | } +28 | | } + | |__^ function or associated item cannot be called on `Pallet<Runtime>` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `Runtime: Config` +note: the trait `Config` must be implemented + --> $WORKSPACE/substrate/frame/system/src/lib.rs + | + | pub trait Config: 'static + Eq + Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the macro `frame_support::construct_runtime` (in Nightly builds, run with -Z macro-backtrace for more info) + error[E0277]: the trait bound `Runtime: Config` is not satisfied --> tests/construct_runtime_ui/deprecated_where_block.rs:20:1 | diff --git a/substrate/frame/support/test/tests/derive_impl_ui/inject_runtime_type_invalid.stderr b/substrate/frame/support/test/tests/derive_impl_ui/inject_runtime_type_invalid.stderr index c7159b34afb3d22737fb5d8ed6662027f04a3bd6..aafc6b5a2c874a7a1ba219fa4b442d5da6114bb3 100644 --- a/substrate/frame/support/test/tests/derive_impl_ui/inject_runtime_type_invalid.stderr +++ b/substrate/frame/support/test/tests/derive_impl_ui/inject_runtime_type_invalid.stderr @@ -1,4 +1,4 @@ -error: `#[inject_runtime_type]` can only be attached to `RuntimeCall`, `RuntimeEvent`, `RuntimeTask`, `RuntimeOrigin`, `RuntimeParameters` or `PalletInfo` +error: `#[inject_runtime_type]` can only be attached to `RuntimeCall`, `RuntimeEvent`, `RuntimeTask`, `RuntimeViewFunction`, `RuntimeOrigin`, `RuntimeParameters` or `PalletInfo` --> tests/derive_impl_ui/inject_runtime_type_invalid.rs:32:5 | 32 | type RuntimeInfo = (); diff --git a/substrate/frame/support/test/tests/enum_deprecation.rs b/substrate/frame/support/test/tests/enum_deprecation.rs index c1167dfe339ce0a013c0d9e7cb742a8161ddab75..72b14dad962917ce0ea0fe21530aaa66cf769bb7 100644 --- a/substrate/frame/support/test/tests/enum_deprecation.rs +++ b/substrate/frame/support/test/tests/enum_deprecation.rs @@ -85,6 +85,7 @@ pub mod pallet { T::AccountId: SomeAssociation1 + From<SomeType1>, { #[deprecated = "second"] + #[codec(index = 1)] A, #[deprecated = "first"] #[codec(index = 0)] @@ -157,20 +158,13 @@ fn pallet_metadata() { // Example pallet events are partially and fully deprecated let meta = example.event.unwrap(); assert_eq!( - // Result should be this, but instead we get the result below - // see: https://github.com/paritytech/parity-scale-codec/issues/507 - // - // DeprecationInfoIR::VariantsDeprecated(BTreeMap::from([ - // (codec::Compact(0), DeprecationStatusIR::Deprecated { note: "first", since: None - // }), ( - // codec::Compact(1), - // DeprecationStatusIR::Deprecated { note: "second", since: None } - // ) - // ])), - DeprecationInfoIR::VariantsDeprecated(BTreeMap::from([( - codec::Compact(0), - DeprecationStatusIR::Deprecated { note: "first", since: None } - ),])), + DeprecationInfoIR::VariantsDeprecated(BTreeMap::from([ + (codec::Compact(0), DeprecationStatusIR::Deprecated { note: "first", since: None }), + ( + codec::Compact(1), + DeprecationStatusIR::Deprecated { note: "second", since: None } + ) + ])), meta.deprecation_info ); } diff --git a/substrate/frame/support/test/tests/pallet.rs b/substrate/frame/support/test/tests/pallet.rs index 9df1f461bba2511538da7ff1f3455c9a36653163..e45ff64e4c26eda45147fb9d65b688914735bfca 100644 --- a/substrate/frame/support/test/tests/pallet.rs +++ b/substrate/frame/support/test/tests/pallet.rs @@ -461,6 +461,22 @@ pub mod pallet { _myfield: u32, } + #[pallet::view_functions_experimental] + impl<T: Config> Pallet<T> + where + T::AccountId: From<SomeType1> + SomeAssociation1, + { + /// Query value no args. + pub fn get_value() -> Option<u32> { + Value::<T>::get() + } + + /// Query value with args. + pub fn get_value_with_arg(key: u16) -> Option<u32> { + Map2::<T>::get(key) + } + } + #[pallet::genesis_build] impl<T: Config> BuildGenesisConfig for GenesisConfig<T> where @@ -814,7 +830,8 @@ mod runtime { RuntimeHoldReason, RuntimeSlashReason, RuntimeLockId, - RuntimeTask + RuntimeTask, + RuntimeViewFunction )] pub struct Runtime; diff --git a/substrate/frame/support/test/tests/runtime.rs b/substrate/frame/support/test/tests/runtime.rs index 5335e08837e4adb2735fd3beecd21f8023be7778..cbcdf8d27b39a6e3f48f7cbef5e02c350d56a943 100644 --- a/substrate/frame/support/test/tests/runtime.rs +++ b/substrate/frame/support/test/tests/runtime.rs @@ -296,7 +296,8 @@ mod runtime { RuntimeHoldReason, RuntimeSlashReason, RuntimeLockId, - RuntimeTask + RuntimeTask, + RuntimeViewFunction )] pub struct Runtime; diff --git a/substrate/frame/support/test/tests/runtime_legacy_ordering.rs b/substrate/frame/support/test/tests/runtime_legacy_ordering.rs index 7b92073a82b1a789ca2b33296893fcb8d62a3a62..1594356ad8fe846b329818634c2a235fd2cae77e 100644 --- a/substrate/frame/support/test/tests/runtime_legacy_ordering.rs +++ b/substrate/frame/support/test/tests/runtime_legacy_ordering.rs @@ -296,7 +296,8 @@ mod runtime { RuntimeHoldReason, RuntimeSlashReason, RuntimeLockId, - RuntimeTask + RuntimeTask, + RuntimeViewFunction )] pub struct Runtime; diff --git a/substrate/frame/support/test/tests/runtime_ui/invalid_runtime_type_derive.stderr b/substrate/frame/support/test/tests/runtime_ui/invalid_runtime_type_derive.stderr index 0b128c3dd4579ba93f7950f42f0ff97440eadd38..daa6721ff051dac23d66cde5f56c4b1e023b5e97 100644 --- a/substrate/frame/support/test/tests/runtime_ui/invalid_runtime_type_derive.stderr +++ b/substrate/frame/support/test/tests/runtime_ui/invalid_runtime_type_derive.stderr @@ -1,4 +1,4 @@ -error: expected one of: `RuntimeCall`, `RuntimeEvent`, `RuntimeError`, `RuntimeOrigin`, `RuntimeFreezeReason`, `RuntimeHoldReason`, `RuntimeSlashReason`, `RuntimeLockId`, `RuntimeTask` +error: expected one of: `RuntimeCall`, `RuntimeEvent`, `RuntimeError`, `RuntimeOrigin`, `RuntimeFreezeReason`, `RuntimeHoldReason`, `RuntimeSlashReason`, `RuntimeLockId`, `RuntimeTask`, `RuntimeViewFunction` --> tests/runtime_ui/invalid_runtime_type_derive.rs:21:23 | 21 | #[runtime::derive(RuntimeInfo)] diff --git a/substrate/frame/support/test/tests/runtime_ui/pass/basic.rs b/substrate/frame/support/test/tests/runtime_ui/pass/basic.rs index 514f150180153692caf55ba9b3ecb171ca4e1a2a..8350211335a5251ec7ef1356dd491dbe7034cc18 100644 --- a/substrate/frame/support/test/tests/runtime_ui/pass/basic.rs +++ b/substrate/frame/support/test/tests/runtime_ui/pass/basic.rs @@ -27,7 +27,7 @@ impl frame_system::Config for Runtime { #[frame_support::runtime] mod runtime { #[runtime::runtime] - #[runtime::derive(RuntimeCall, RuntimeEvent, RuntimeOrigin, RuntimeError, RuntimeTask)] + #[runtime::derive(RuntimeCall, RuntimeEvent, RuntimeOrigin, RuntimeError, RuntimeTask, RuntimeViewFunction)] pub struct Runtime; #[runtime::pallet_index(0)] diff --git a/substrate/frame/system/src/lib.rs b/substrate/frame/system/src/lib.rs index f2bb5e290c94378a9afa9381e51720b2e724aa4f..8980c6d6c8f427eedd924a8d2cfb555635b18cf7 100644 --- a/substrate/frame/system/src/lib.rs +++ b/substrate/frame/system/src/lib.rs @@ -2062,11 +2062,18 @@ impl<T: Config> Pallet<T> { /// /// NOTE: Events not registered at the genesis block and quietly omitted. #[cfg(any(feature = "std", feature = "runtime-benchmarks", test))] + #[track_caller] pub fn assert_has_event(event: T::RuntimeEvent) { + let warn = if Self::block_number().is_zero() { + "WARNING: block number is zero, and events are not registered at block number zero.\n" + } else { + "" + }; + let events = Self::events(); assert!( events.iter().any(|record| record.event == event), - "expected event {event:?} not found in events {events:?}", + "{warn}expected event {event:?} not found in events {events:?}", ); } @@ -2074,11 +2081,22 @@ impl<T: Config> Pallet<T> { /// /// NOTE: Events not registered at the genesis block and quietly omitted. #[cfg(any(feature = "std", feature = "runtime-benchmarks", test))] + #[track_caller] pub fn assert_last_event(event: T::RuntimeEvent) { - let last_event = Self::events().last().expect("events expected").event.clone(); + let warn = if Self::block_number().is_zero() { + "WARNING: block number is zero, and events are not registered at block number zero.\n" + } else { + "" + }; + + let last_event = Self::events() + .last() + .expect(&alloc::format!("{warn}events expected")) + .event + .clone(); assert_eq!( last_event, event, - "expected event {event:?} is not equal to the last event {last_event:?}", + "{warn}expected event {event:?} is not equal to the last event {last_event:?}", ); } diff --git a/substrate/frame/verify-signature/Cargo.toml b/substrate/frame/verify-signature/Cargo.toml index 37cc6c0b30659a31c9913196f429e255e632c698..453424bbec7a8696b1013d1d2ba847857c427179 100644 --- a/substrate/frame/verify-signature/Cargo.toml +++ b/substrate/frame/verify-signature/Cargo.toml @@ -27,10 +27,6 @@ sp-runtime = { workspace = true } sp-weights = { features = ["serde"], workspace = true } [dev-dependencies] -pallet-balances = { workspace = true, default-features = true } -pallet-collective = { workspace = true, default-features = true } -pallet-root-testing = { workspace = true, default-features = true } -pallet-timestamp = { workspace = true, default-features = true } sp-core = { workspace = true, default-features = true } [features] @@ -40,10 +36,6 @@ std = [ "frame-benchmarking?/std", "frame-support/std", "frame-system/std", - "pallet-balances/std", - "pallet-collective/std", - "pallet-root-testing/std", - "pallet-timestamp/std", "scale-info/std", "sp-core/std", "sp-io/std", @@ -54,17 +46,10 @@ runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", - "pallet-balances/runtime-benchmarks", - "pallet-collective/runtime-benchmarks", - "pallet-timestamp/runtime-benchmarks", "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", - "pallet-balances/try-runtime", - "pallet-collective/try-runtime", - "pallet-root-testing/try-runtime", - "pallet-timestamp/try-runtime", "sp-runtime/try-runtime", ] diff --git a/substrate/primitives/metadata-ir/src/lib.rs b/substrate/primitives/metadata-ir/src/lib.rs index dc01f7eaadb3337f1a4ff42322417d2e353ba299..e048010a34b75a7facb2cd0abe019eb305734096 100644 --- a/substrate/primitives/metadata-ir/src/lib.rs +++ b/substrate/primitives/metadata-ir/src/lib.rs @@ -122,6 +122,7 @@ mod test { event_enum_ty: meta_type::<()>(), error_enum_ty: meta_type::<()>(), }, + view_functions: RuntimeViewFunctionsIR { ty: meta_type::<()>(), groups: vec![] }, } } diff --git a/substrate/primitives/metadata-ir/src/types.rs b/substrate/primitives/metadata-ir/src/types.rs index af217ffe16eeb829cdbbf42f6483a09505709fd0..0617fc7dfb94f7d8c397d4ccbcd4219d400c488d 100644 --- a/substrate/primitives/metadata-ir/src/types.rs +++ b/substrate/primitives/metadata-ir/src/types.rs @@ -15,7 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use codec::{Compact, Encode}; +use codec::{Compact, Decode, Encode}; use scale_info::{ form::{Form, MetaForm, PortableForm}, prelude::{collections::BTreeMap, vec::Vec}, @@ -41,6 +41,8 @@ pub struct MetadataIR<T: Form = MetaForm> { pub apis: Vec<RuntimeApiMetadataIR<T>>, /// The outer enums types as found in the runtime. pub outer_enums: OuterEnumsIR<T>, + /// Metadata of view function queries + pub view_functions: RuntimeViewFunctionsIR<T>, } /// Metadata of a runtime trait. @@ -118,6 +120,89 @@ impl IntoPortable for RuntimeApiMethodParamMetadataIR { } } +/// Metadata of the top level runtime view function dispatch. +#[derive(Clone, PartialEq, Eq, Encode, Decode, Debug)] +pub struct RuntimeViewFunctionsIR<T: Form = MetaForm> { + /// The type implementing the runtime query dispatch. + pub ty: T::Type, + /// The view function groupings metadata. + pub groups: Vec<ViewFunctionGroupIR<T>>, +} + +/// Metadata of a runtime view function group. +/// +/// For example, view functions associated with a pallet would form a view function group. +#[derive(Clone, PartialEq, Eq, Encode, Decode, Debug)] +pub struct ViewFunctionGroupIR<T: Form = MetaForm> { + /// Name of the view function group. + pub name: T::String, + /// View functions belonging to the group. + pub view_functions: Vec<ViewFunctionMetadataIR<T>>, + /// View function group documentation. + pub docs: Vec<T::String>, +} + +impl IntoPortable for ViewFunctionGroupIR { + type Output = ViewFunctionGroupIR<PortableForm>; + + fn into_portable(self, registry: &mut Registry) -> Self::Output { + ViewFunctionGroupIR { + name: self.name.into_portable(registry), + view_functions: registry.map_into_portable(self.view_functions), + docs: registry.map_into_portable(self.docs), + } + } +} + +/// Metadata of a runtime view function. +#[derive(Clone, PartialEq, Eq, Encode, Decode, Debug)] +pub struct ViewFunctionMetadataIR<T: Form = MetaForm> { + /// Query name. + pub name: T::String, + /// Query id. + pub id: [u8; 32], + /// Query args. + pub args: Vec<ViewFunctionArgMetadataIR<T>>, + /// Query output. + pub output: T::Type, + /// Query documentation. + pub docs: Vec<T::String>, +} + +impl IntoPortable for ViewFunctionMetadataIR { + type Output = ViewFunctionMetadataIR<PortableForm>; + + fn into_portable(self, registry: &mut Registry) -> Self::Output { + ViewFunctionMetadataIR { + name: self.name.into_portable(registry), + id: self.id, + args: registry.map_into_portable(self.args), + output: registry.register_type(&self.output), + docs: registry.map_into_portable(self.docs), + } + } +} + +/// Metadata of a runtime method argument. +#[derive(Clone, PartialEq, Eq, Encode, Decode, Debug)] +pub struct ViewFunctionArgMetadataIR<T: Form = MetaForm> { + /// Query argument name. + pub name: T::String, + /// Query argument type. + pub ty: T::Type, +} + +impl IntoPortable for ViewFunctionArgMetadataIR { + type Output = ViewFunctionArgMetadataIR<PortableForm>; + + fn into_portable(self, registry: &mut Registry) -> Self::Output { + ViewFunctionArgMetadataIR { + name: self.name.into_portable(registry), + ty: registry.register_type(&self.ty), + } + } +} + /// The intermediate representation for a pallet metadata. #[derive(Clone, PartialEq, Eq, Encode, Debug)] pub struct PalletMetadataIR<T: Form = MetaForm> { diff --git a/substrate/primitives/metadata-ir/src/v15.rs b/substrate/primitives/metadata-ir/src/v15.rs index ed315a31e6dc9f4f9e1c4af9142818756a64ab56..7bc76f22b58d004507c900bd139c9c58f1e8dbf3 100644 --- a/substrate/primitives/metadata-ir/src/v15.rs +++ b/substrate/primitives/metadata-ir/src/v15.rs @@ -17,31 +17,39 @@ //! Convert the IR to V15 metadata. -use crate::OuterEnumsIR; - use super::types::{ - ExtrinsicMetadataIR, MetadataIR, PalletMetadataIR, RuntimeApiMetadataIR, + ExtrinsicMetadataIR, MetadataIR, OuterEnumsIR, PalletMetadataIR, RuntimeApiMetadataIR, RuntimeApiMethodMetadataIR, RuntimeApiMethodParamMetadataIR, TransactionExtensionMetadataIR, }; use frame_metadata::v15::{ - CustomMetadata, ExtrinsicMetadata, OuterEnums, PalletMetadata, RuntimeApiMetadata, - RuntimeApiMethodMetadata, RuntimeApiMethodParamMetadata, RuntimeMetadataV15, - SignedExtensionMetadata, + CustomMetadata, CustomValueMetadata, ExtrinsicMetadata, OuterEnums, PalletMetadata, + RuntimeApiMetadata, RuntimeApiMethodMetadata, RuntimeApiMethodParamMetadata, + RuntimeMetadataV15, SignedExtensionMetadata, }; +use scale_info::{IntoPortable, Registry}; impl From<MetadataIR> for RuntimeMetadataV15 { fn from(ir: MetadataIR) -> Self { - RuntimeMetadataV15::new( - ir.pallets.into_iter().map(Into::into).collect(), - ir.extrinsic.into(), - ir.ty, - ir.apis.into_iter().map(Into::into).collect(), - ir.outer_enums.into(), - // Substrate does not collect yet the custom metadata fields. - // This allows us to extend the V15 easily. - CustomMetadata { map: Default::default() }, - ) + let mut registry = Registry::new(); + let pallets = + registry.map_into_portable(ir.pallets.into_iter().map(Into::<PalletMetadata>::into)); + let extrinsic = Into::<ExtrinsicMetadata>::into(ir.extrinsic).into_portable(&mut registry); + let ty = registry.register_type(&ir.ty); + let apis = + registry.map_into_portable(ir.apis.into_iter().map(Into::<RuntimeApiMetadata>::into)); + let outer_enums = Into::<OuterEnums>::into(ir.outer_enums).into_portable(&mut registry); + + let view_function_groups = registry.map_into_portable(ir.view_functions.groups.into_iter()); + let view_functions_custom_metadata = CustomValueMetadata { + ty: ir.view_functions.ty, + value: codec::Encode::encode(&view_function_groups), + }; + let mut custom_map = alloc::collections::BTreeMap::new(); + custom_map.insert("view_functions_experimental", view_functions_custom_metadata); + let custom = CustomMetadata { map: custom_map }.into_portable(&mut registry); + + Self { types: registry.into(), pallets, extrinsic, ty, apis, outer_enums, custom } } } diff --git a/substrate/test-utils/Cargo.toml b/substrate/test-utils/Cargo.toml index 87c9cb731e3a46ac1149bd45bc4d59b14ef20a91..75eab46cb217acd60f2cf686302a1961d93905b1 100644 --- a/substrate/test-utils/Cargo.toml +++ b/substrate/test-utils/Cargo.toml @@ -14,11 +14,3 @@ workspace = true [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] - -[dependencies] -futures = { workspace = true } -tokio = { features = ["macros", "time"], workspace = true, default-features = true } - -[dev-dependencies] -sc-service = { workspace = true, default-features = true } -trybuild = { features = ["diff"], workspace = true } diff --git a/substrate/test-utils/client/Cargo.toml b/substrate/test-utils/client/Cargo.toml index e7ab4c8c8367d6ec9376b5849093d0a187c0020c..b0709f4e244d96ef097848dde3ccd3bc86e02451 100644 --- a/substrate/test-utils/client/Cargo.toml +++ b/substrate/test-utils/client/Cargo.toml @@ -26,7 +26,6 @@ sc-client-db = { features = [ ], workspace = true } sc-consensus = { workspace = true, default-features = true } sc-executor = { workspace = true, default-features = true } -sc-offchain = { workspace = true, default-features = true } sc-service = { workspace = true } serde = { workspace = true, default-features = true } serde_json = { workspace = true, default-features = true } diff --git a/substrate/utils/frame/benchmarking-cli/src/storage/README.md b/substrate/utils/frame/benchmarking-cli/src/storage/README.md index 95c83d2edbc5c68a00589951b0b83acd7a4adbb3..955b52a248c6e05a42f2419327785e2bfe88f34a 100644 --- a/substrate/utils/frame/benchmarking-cli/src/storage/README.md +++ b/substrate/utils/frame/benchmarking-cli/src/storage/README.md @@ -13,7 +13,7 @@ Running the command on Substrate itself is not verify meaningful, since the gene used. The output for the Polkadot client with a recent chain snapshot will give you a better impression. A recent snapshot can -be downloaded from [Polkachu]. +be downloaded from [Polkadot Snapshots]. Then run (remove the `--db=paritydb` if you have a RocksDB snapshot): ```sh cargo run --profile=production -- benchmark storage --dev --state-version=0 --db=paritydb --weight-path runtime/polkadot/constants/src/weights @@ -106,6 +106,6 @@ write: 71_347 * constants::WEIGHT_REF_TIME_PER_NANOS, License: Apache-2.0 <!-- LINKS --> -[Polkachu]: https://polkachu.com/snapshots +[Polkadot Snapshots]: https://snapshots.polkadot.io [paritydb_weights.rs]: https://github.com/paritytech/polkadot/blob/c254e5975711a6497af256f6831e9a6c752d28f5/runtime/polkadot/constants/src/weights/paritydb_weights.rs#L60 diff --git a/templates/minimal/README.md b/templates/minimal/README.md index 22f396c243ef332cec34feb0c40db54667979ea9..4cf3fd2a44bb44289c3a2a1e7b255f6ba0d1ee47 100644 --- a/templates/minimal/README.md +++ b/templates/minimal/README.md @@ -42,6 +42,7 @@ such as a [Balances pallet](https://paritytech.github.io/polkadot-sdk/master/pal - 👤 The template has no consensus configured - it is best for experimenting with a single node network. + ## Template Structure A Polkadot SDK based project such as this one consists of: @@ -61,7 +62,7 @@ compiled unless building the entire workspace). - ðŸ› ï¸ Depending on your operating system and Rust version, there might be additional packages required to compile this template - please take note of the Rust compiler output. -Fetch minimal template code: +Fetch minimal template code. ```sh git clone https://github.com/paritytech/polkadot-sdk-minimal-template.git minimal-template @@ -147,11 +148,13 @@ docker run --rm polkadot-sdk-minimal-template We can install `zombienet` as described [here](https://paritytech.github.io/zombienet/install.html#installation), and `zombienet-omni-node.toml` contains the network specification we want to start. + #### Update `zombienet-omni-node.toml` with a valid chain spec path -Before starting the network with zombienet we must update the network specification -with a valid chain spec path. If we need to generate one, we can look up at the previous -section for chain spec creation [here](#use-chain-spec-builder-to-generate-the-chain_specjson-file). +To simplify the process of starting the minimal template with ZombieNet and Omni Node, we've included a +pre-configured development chain spec (dev_chain_spec.json) in the minimal template. The zombienet-omni-node.toml +file in this template points to it, but you can update it to a new path for the chain spec generated on your machine. +To generate a chain spec refer to [staging-chain-spec-builder](https://crates.io/crates/staging-chain-spec-builder) Then make the changes in the network specification like so: diff --git a/templates/minimal/dev_chain_spec.json b/templates/minimal/dev_chain_spec.json new file mode 100644 index 0000000000000000000000000000000000000000..91d703c6fd5bd0bdb1793bc4b208dd1e71ac055c --- /dev/null +++ b/templates/minimal/dev_chain_spec.json @@ -0,0 +1,85 @@ +{ + "bootNodes": [], + "chainType": "Live", + "codeSubstitutes": {}, + "genesis": { + "runtimeGenesis": { + "code": "0x52bc537646db8e0528b52ffd0058bc49057eb84632144d10784894742c8bde903e277d4efa9ca4a5f0e2c7b95fe173920d2da637ed48cf23dbde08721d93d1ee93927f0102b631505ddb8ea0b7b14774f612445415d300fa8db44608216493bdf7965b064c159913b313096873c0d17b6e346bb3af5a029e75557bc411556f2ba2ca5e9ad86212d0f07087ae3d5d198eaeed1243c2d34ca1707fc049eb76aaa5caaceb92189407aafbc3c594d60975bb7b688f583fb47b6c09d87695bbc6769f302219c8da27fe84dd441facc8c231b5d69a74ad3d6e2d9240ed9309ac29cddf13d175b79bb5737b8918ef3dab86bbefa39046d142880dbc14169b2d78a6a5f93f2e206435a7f7325d5bba6e1a9888023fdb164ce213c96adba2f975d3d0fcd27be662eef0c51170700433e2f0f1b1817787736ddcf4793fe0420726c8c1126ca26821c4c65d0a8bcd8ba205dbc44b59808d3b9c521660532aa309f712132e86efda683e7ca98c26e2212dd5b8187ea4a5329a8077b47417c38754a6eecf8f7bdd36160f27a082187008830fccb08537fffa41b6363d3060630937b88113de18421d6cd6e6bdcaf47d7c6cdc163c43849beb62a6f40ac1f37a1a3f1f6c1146bff4fe6c21a58f7022d3d3efed5688efb09baa759c3be4e907e5684775a6c7579eaeeeed136d12294e0e6df2f8fa682db53b9cf10fc962614a472a86847f112767e5e878d864b130a5e12bf78bb4c9cad1b08902a2fc34a46258c153c4179e50c4179e406b15eddee67e310c14f185275450bfc32986153c2b870df5d57155aab4183e4056b0832ea8f0105482b086cfa362e568317c8af8c2137ca202a2fc489fc5c294ca042b870d457d560e9b7dbdfa7d3701bb45d4fd49c14fefb416c38707198480051b7c7c6c965ac123a9cffed1ea1cad54b46b42640632f0e00f519660697e0df3700fe43886b55164fb8302321af6fe4861a35734467b8f4aba304e045691b586ec3704218cb4350e2c76eb806cb107f4f47bb4dd6ab3486bd966eb9ed6844002c3e97b8b677d6f87737404bec3699aa6f6699a265adf197e9ab1450869757f144705304218638c31c2181fdbe1c469f44a021492382f9cb57bc694e8699cdd577edbac31c172f1551e3e4e1cf978374747288ebcfbb6bbe2746fd3e2186fc568b9ab4ddf81dd6ebd69a6c6f3db1f7c23d2b6d12acf140aece9356cc1abcde9703274b3ba4b8a03cf9f627478b0da9b15febdcdd191f6f84871e0dbb72d9e4e748074fc0e6c7ecb10775d3ca3333514ee788933fd495adba7b7e6378c08b7346337fbe3e3e3d34c2bfc44a1c08eb7e0e5663bcff8c59278e7d668758714e7316c3c45ca18bd3f2780a36ba8df05d0fb738237bc432b4eb74c6acba4fa9a1fa7bbe499dad34ce50f086f410889b8d7309cadad76fd783b9cf36149b486af61c933a322ade121958d732501521d9ee6f6284ef684054076f56b2bf460737f309e3f625a84efeee21b3c8e8b973cc31dafaee11aee69adad61ad03322b24058da7444fa39249efef56e8003a3cfdfedebead1fed80b56c6defb32e9e191d7155aab43bce0ef707a054eddeae6820edda15d6f28cfb103277fe737fb7de6cddb0e7dc6bb8f562ee35bcc472df5fd35a98ba3fed7e82309cbb3bc9d138194713a58c8a44bb43aac56dcaa8da1d09b67127e8a2dd7b9595ff24cfe0f0db9769328e71fc47abec9ab5fbb26899f4fe98d45eb3febb5a95dd5afb8f1673d0349bfdb55811fea3f2e219befbc2388ab33fcc2c05abf7278b7592ed4f0acce8e6d35f98da7c9a6fd1b46be703321cf7edda7cb8f727056474eb76c68e349f5e5a9b4fbb5b8b1179df09e5f5fecd9bacf76ed69e76df3d627453f57bdd2ff4bb13997e5427d4fbba55babaf36bdc5cbe7696b2f6d6cb07d8374ce7edbe984ed68ebe341fce021cfd1e69560d1f1f9bfdb3428f67e2f758f4deda3d0274cbeab90e9abb422e5aadeb70c75bb4725b6fbf66e5e9ab35a83ee169ebefd5778fa00e5a21205aadbb63a7e6ae108cd6ebee35ced299aa54a9f2877ebf66ed29d2fabd86adb95d4d9c47a1b48ebfe18e77d89177a6b5a7f9dbd6dbacaddb1d56241e746b8e6ebac624aeef0a69af71357c4d9d56a5e541738425319da2b535f56ad6d6d5ad386beb78ec0f43f21ebf1891eb356c2d08b2fdc9e20dfd1e6fadc5d7624960b7687d6d3986221b74106dd8cdeb78cb5a0c446b4f837e4d28b2af5bb3b6b6be7bc445ebf59c237a578875eb35ce9ad6745f0c44755c63b3c6bb2f76e43dae1a3e26689eb1be7f3c537ddfb0245a95bee8ae906a519d56a5adc35b743708e5aa769f15023fcd1a7ba8164d60ddd16411fabfd3b3e0f17821fc2c7c1cf401b8678182769717f1753459f8a0a595bb1fcf22885bdf4b4793854c163deee37b174793050f5ae2f150e83e440fcdf37889072d8960eee3251ebf1e7a168e96a47c464bd927f792a3254951d05e9207e2a263df678e268b8a96aa33dff2414bf4931027e23cddc74b7c1fb404e1335aaa9ebde4e3d6b378ff414b2d2d5fa125778a96a84feba5798b969c7bc9fae82c59f68b96207c454b8e9680bc7ae69ebd743da325c8f2127ccc877829fb10b4d4d2f21db4b4e3d3742068a90588ef98767c8897a60f414b40500e889728188a02120b2db17cc78e8f5876eca017a2aa0e0490aab22a6aeef0c143e4b289a98a8793d60e189af062e943146239a7cc65d5b4c382170f1f3ce40c89604551cecaa61da22be3415d3e44134bae4213ee7070870f278908406671685a178068888a0822587c588e8a8979891f1343f1e0414fcae449570002f052f50004604e53e8f43157f5184822bd344f228224433bb2d307c087e801b8005ee27101c4c4bc643d6688980be0250a124184354f4f823b4e6222882022002f4d0f002d114184c85d00430c01e4a5eb40a8d3c700712042f010c0635ef2f1181209001f829648176288c7bc545d8897320a731616f6717a228000b9104000f1d1810871202f890e449e88077929f4204de6e5027829740134980b2180077989c78578493e86f4f242ff12f39797e65fda4bd65f3ec468742180a02520b404e4427c04c4472f5d1fb597e08738e9a5eca40600225e9a4e042d018088535a02c08100e2a497dce94bd483d052000270185a1ad1d2e82c2c7fa1a51f3f3ea2a597b3b07cf4d28e8f68e9c7e83f5eba68cdc6b4c35c00425c2b07424b3f68e9c781fcba4e5faa4e69694588d3972c4ac5c6b4af5c002f55b48a8d6917002d0580a2a0c5581f8296aaea2db4d4726b885b2f51d4098b962aeb2fb454fda27ebd3429131bd3fef2d20e6a6463da49b444c48e038096282dd10f310f434b42fc9496b60d51f4c046151bd4c105526ca6164ed04516f620071a64a1059b2ce66b7c50b931ed93964ecf83eec6b40741d7c5ec8100e2e32fb43472f90f5aea510211dcd0c61b3cf001169460e3a3a7062608430b9e00063dbc81031b1f2f89a8cbc6b4fba02517ba2ea6085a49bd2f8568b631ed3da874317b1e2f39ca6463da79d0d20e8a82669385e82db4143a0b45818c4d16ee2bb424023d444b3d3b10c30f62eca00e3bc0610e366ec540071174d0821ad4f1043dd864e11e7a29a34336a63d444b20ba2e6600b40ee97d69a2321bd38e511717b32f3155b231ed172d591405249b2ce22b5a42e20869c4210876e0021d3fb0a1280a6e9345104ec043119a10062df6e0069b2cf8d34b929236a67da2a548d7c508a155a6f72548bf31ed8f662e66bfef713c312ca4ca26c9f6270a1dbd3f587cd135d4fcf542ef0f1664b4155a98e599655295cd5fa6598ee1efad866111a5a7c7f374f81aa764125fcec724feb3e9db1c6f261a5fc30d83b7da155b330679269eff78469e2fa7b96dc5b92d676b0bb678794bced60e93346e0dcb196fc5b9d3746eb28e67ccc876a417931aa4b5a7a18c72d6d7d57dc7f5f4c588c0d7b0652d96c444ebebe9d4e5ac6ff9386bad3532a1a256d1f2cb24f91a474d9d52bfcb595f7a9adb71be7e3aaedf1723f2e863929bb23d2eac6d2dc8f6ed5b590b4517935c98d40e7b7f4cd0876e6152fbfa7869afb5d6dadf61736f8ddf1cc3f72efbd1d111f877486b6bfea33badf92e899e66ba4cda065b5382b53cf3e06be4c729fbf10cfcde82b3f59bdb44dee11cbdb77eb71a4684dfe1dfbc8690c5c3bb378c88a36f6ec3b97cbdb94d4464055398b4cdff41840b9f15b2ed3022fcc5225d8cc86392c38c6c7b0dc7f91aceed375bf7b8d6e6b0160059fbdeda20b2c558ac85a96ff7c733fcfdf24cfb9ea7b533cb98e47e31c97d31229249ee354cb3dad2aeca7677e1997777ab8567de5f7806dedd6ad79bdb8bc14309a29ff4c86e97dde8e808bf9ddfe84e6b48df6c6dedccb6b799567e7b0d2f8c73ad29c1046fe82a7b9f31cdb3d94b9ed99f2be8e8fdc533adf72e3cb3bd5f98a538ef15a2a7350458db816c7fae60c35a28b2fdb9228dde76e1994a6a3e9fe468dcf92f4cd36cf819cfec8f4f1acd6fe11926c2c5152b64bb86dd8c528616b72903f6c5337bbe4caf103cada771c381b5bd30356bbed5eedaebd5dc9ad526ff607c499ea9adf70821b2fd6249382a2dbeda7c7ded114e1a1dad3335949590e5ae365d6350e2154743b9407b8493e6d33a0ce876fe62489e8f4fb7d770c36e329f6ebf78669bbfd84df3e985618a93f50ad1c38db360b9f6ea9c3b8ea39249fb9ed61c6059bb22222b90c2a4ed8711a9e17db16eb2f6bd15da963c537f5c43c8f8eeb5fd31696fb52999b47fc66fdf2f8684e963121fa751c9a4fd3269efe63289e932a9bd617cab5d6eb6e6b9dda664d29e31bee5da32e831a9bd866bb8866b98e7c5a4f61e6ead8b2b07456c7183eadac105c645e5b2c18583eb06961dae2b2e1fab8ac5076b0fd717561fac3a587ab85a706521dfb856706971b1e0c2c2fac3b5854507ab0ecb0f540d281a5033a0bca0824001812a83a242d980c2017503ea0bea0c8a08d4102832a817505328165042a0cca07e40f980ea0135062506c5036a075418940ea81c50605052282ca82c28145051641c241db20fb20ea907690749078907ea0a3907b907c907e9072907f907b905c905a9054904d9862c8234821c82cc825c82c4823c431e41f640064102418a21c76828903c6842fe8027027207f20b5983690e931aa41753179e19130d9e101e10a6379c1ea62f4c69906080714c3e8862886f4437a216a628530e22179e1a261d4034241c2637b83d383c4c319864e0e8307901e5806f806e8863805198bce0fac052380accc26486298ec70687856785c90d788257c6f30114038e017b0075e0f20073007920c9783f7865806abc38c82e5e1b8f8d778528834886490c08c7b4c6540548063886298c4bcab4034a05540a60196217ae294e0b4f0c2f0c0f0c970a1c17220ca2176f088f8c870604e321e1254122e11521c6e19d5124c6409621d1707c78519c1fde15b18b9e58067804c70637c7c503b786f885290bb7854b06ee0df7057806e785690cd7854905ce0d8804f70777059705578763e37de18ae2c200992061c038b8c6b872c061c035700c5806110c318e6b06d316ae8a150e092f081318cf079a61a20254c21404c986a98de805de62fa99cc902f786b805ac02c261e5c2790549c14de1c4e0d39830908118e498be9043009d3192e144c6f885b7051786860185c5c4433c028310cf20d52064c06ff807dc054f805dc02ee82a7b00b580b3e01e740c6e01243b68051c029602cd804ecd34ed0ae683e4da6a0c004768c58a0020db0e91a0608510012093802010ba09931c2000520804c1141868821c194e007909711c3c16abd0d168162b7e4c9131d4842c5134b982449623517459325499254b18d7db204044f3449328a59d89d254f9638a122c9ce920ff88858d8253b4fec3c4912458e1421e8c013299e2c69b224891ff10a4c763ed064490e1bbb648907924cb1936487c907a45822829868857d9223c5133b4ba248b2648907888855d8293cd0448a242370b224043a49a4a0a2779a2c01c1089e60e2910abb048a26533449f2441229a8e82550349902023b4d42300514503490b846145340b1248a20e214f6c90896e024799264c9ce134e963459f281244f46b0e4489329a478f264c9046694c28a20c91449a4a0a29d2cc1713285059a48f10413283ce0012433466197ec3c118514394f4049b224044b42108126a258f2810f3cd18400a21afb04078a254ca080c23ed969b2c4c912264da4787c4213293c308a4e5828a478d2440a273b552c4932821c2aa8782289932551e44811021b1c28a6c8b179893ffbe4476cc23e91e42532614190e4899d27a2786267c912a2b804124891f384143b52349162474c6371a09822a7034996ec84008a25552c59894a58275334e0dab624a7034fec3409810792ec40b1c489145134912249121f3ee20aa62951e0628bde1e6b7f7c7cbaf5381f91e3c0716854b4e9adc0951598ad6430cb569677e3c2c7eb769f73cebd4751ee2d8649f9ae8bafeb3dea516d6237bd1727e95e6cfce2732e3a574927a3731bafe8a2dc8d6f0de09cdb7def718471638ccfc1189f8bb072f12dc3085b8b710be0228c0f937141cb4fc6ddeb72ceed7b8f1d01648a587e6e3742f738eef21bc0dbddc8c33917e3bef7282af2d8ddb7ceedb638f79c5cf7a27cbb6eaddde5c7bb3b39d7844c6ea5dce85e74cead73948b1445518fa2a8dde81c3bb791da6db9ae0bc6785dbbd15d4fb6d62294419e48241245e822bc9c94b1b96d020840cc9246448c441bddbee8f6edbaf69e8b6e638cebe03ae75e8b2e42aa45182386ed6edcf81ee4756e59de7b2fc6e8dc42ec391eceb15be76204c59d5e73cf4dd1bde93de6f7765f7bcfc9f6f8b15c1777dfe36ddbe266ce39c7bcbbece4c618e3eec618dd2ee5761fbb5d7e8b619894eebdd71af6f839e72045b9f6dee59c7bce39775d975bf7dee3f7dc63e79a8f186504c01010b6441863848930bef836beb71be31342b294987cefb99de48f1f58931c61f44161842d13c6173fb5c7cc8f992f7e8d995f8c172842e7e22ebb37b908375e39b8c2702bcb237032050896802016c08910d61660c993274b9c50018229a048e264099429a058e224c9134fa28062491202e0cc1ca0005440b1e4098d8b07a470b2044a120410e000072840144b924cb143c5089c40214403c12e019638f140122753ec3c01c51439394fbc2c0181143b4d42e084b27860270440963049b2d3440a27542481e28914207809228a254e9644e1648a24330728c012299cec04c0c9133b4f88e8f1c407105b8029a670f203078a273a9093338593008c60094e929d2a96340162c7ce920ff8083dd9792245154b5ea625409329a4d881e289274d9e70b29364470a1080600a12902d401552786089132a288b932796e44031ea114593255450f14492251f78c2c9143b4f5e8c980152c51422d80162e60005080d29000192146009ce13391d60f2e40926af729640599293a48a2740100494264bdccb1220499329a478e2640994241f982227c9079a48f1810f4c919364a78a253ea03459e246720b5e1e9e9e9e9ec84ab68787797878781a0f0f0f0f0f0f4fe429f5b8520f8fa394f4b490929eb63d3d3c8e95f0b49ea684a7f1f0b092e5e9e971a51ea9a4a7f5b41e9e1ea7647978b8472ae1693c4d494fe3e1e9e1e1e1694a9687a7a7e7f54c4ab6272ae159253dad072ad965253dadc729d99e1e56b23d3d3d3d4f494feb694ab6a72931c2f9b4dd6d2078f2c40654ca6de2a5dc86a23c12c2c34fd159f023ebf164b2945501e9c83a846f8d8e2c487ba8346344dc1b849227b27cc37ab738741e276cb20a60e769e115ec2b2b3e8ec52fe604f6957935f9bd13252b6c8668826db2bf6ec28a1ebf6e45f61e5fac891ebf6809f40c7e3127b2f730821bed6e0435da7d2f8835e1e3a25f133b685ae1e3a0430c033f8e3dce267c5c444ba0b750b7e0759897403f8ed1928f5fa0b9362ed38aeb3f0e33adf8711f6f995694aefb38356b4fd77d22db1f239cd1169c4daa86a7e64dd5105e6fb965350c03a0b73c34ad003d74d12c812e7a364ba0675f0c033e5a662974985fb3a7ad57b7a60b2e868192e8d84ba1bb7cb1267cfc072d65c744d38a1fb782de8af9128f15417ce52d2f65173d344b7fe9077d897ede655a512a5dc75eda71112db9bcc4e32c5f1b986945a9843d2bbd1c88b30dc49a005d74883991dd072df5d884de63969a4d88c2d904085e44adc82eba355d0eabc0f51fd40aeca04f58a44df8b815d7435f9925ec20ca63458fc33871512c7efc7a88f25436a26393a7b2c9768f80b4cab4185240bf284f65733d5e3443cf26f61a87cd6653818c96ae63540bd0cb881427079e7abce8356cd12ad3d42b5a999a4d5cc3e2c745b4d46c86a05694462f0179e9e5401ce6724ebf26163f0ef31eb3e4f21eb7e20aa8f462614a5c01958e677cd1ab856e1ec8f6070a687475e9f7f77e87c2184fe8c20861d8a18b204711ce38c2174690e308721c818c228451042967d471c61b67ac7106196d5d179ca3891ea13abe75d5d31cbd724c73745c393a2a20cacf3b43193e1d3f756c0b74c139829fe608d29b8ea75af66237457ce1093e1776a380283f1db1300574185a6a36252128167a89521e8cb6bc34a994db84284f10bf7eca13841652186093458f4de8a1b7bc86db7441b70331a5dc467420f365f2606ff988f2646fc932ca835129b7c97efdc72cf5d8f8d06140e3d46d45d4fde9c1946ecdc6654ab94d49965e92721b1ed0af8bde639678501e10c522d4f2d20ecab3f2162ae536d859a894db8828cf0a95721bd02f8a4588ae8ba9fbd30329dde8ce5b2d74a320c8b0d0158a6146e76c1bfd1e2a4d6112b88e3d73341895821d44b5c028160cb001ada3f9bbc424805df4ccd188a814d033aa058896118ffd7dc294e8e908290e057a6c426c03fae3c964a9f9f86455eccf081e742d6e037a7ca5a2231d41da44d65e95b4a3c1a815d8afbfcb9680461f310cdc07fb758735711d444ba05f20ecfad1233983a36d08b2776b9f64fb33461d1dcf9289cb09258f076dbc76c2d1e11a9e348467eaaed1f0109e0998864234bc1324daf04aaac333713451caa828124c036de06578667fc430a3e18de019d8f04178069e6435e7ee68742bc4ad8bdf9d4e7418d0bc42dc77626f6b189ed16955ba1d4e27fb9d7824894e10ddbe538701dd56886b7437c83aac08c492686fd803669d662d41c797acb08247f238775e8a56771c496b2c12cf374cab15edbe1d696deddc6b9867fb79668e1ec0770d3be2deee8eb8f0cc74f8176b9964eff1ade3dcf669ee0f0fc6e83861673cb391d6e6878e7fd820fb566583ece3037a9ad0ecb341f6351c6ff80a7690251eac9582ffd9d38d30f17820e5f5f4c34b59b3aeef29beee1b3d5d09cfd4213d7dfa10979ea6d74c461c4d9432249d1e05d3389be94eb8d1d335c033fbc23373faa2d1a0276e179ed99f1d78c16ddd663ce33ebd8567dea769e97027b0f603d9bbdb9f1d48e92a1b7e1b0fa9b2ebef68a294f1dc1f756fa9a3dd2f9e61626d0732be737179914cf36c5cb7737779d923b6dd81ec11edce49c05a2a06d9be9dffd212d0f8ebb2ded7ac8fb430d2e8d6da17a6cd8431450751deab4bc39f67aa4cc3c3cbc837fc90ac61100d0fc3346c03ef9283311afe256be1197708e1f78704560ebae8217a7fc078433b4a89ea1495690390af610c64d5a96ae264151dddb08f4fbbf3f8f83465c411788ad61d0de5750ef591916daa3aec9dae618bdf7a0befeac23adeebae2faad3aa606f6d591606bab29515111c2cfa4a96658c31b172ebaddc822ba115d04519081402dd724b6891e31f64c5d4f7d61bdd5ac718e3a9c94dcdc724790d64d3e3dd655a11f24198244f6292bcbc45723446708cbcac46b47c955d497d0192114c923583f2d5882eb88b9aadb97504630b1d3bde6aec9a03d59e1edd389e233e94a9759a4f5f6f5dcd117f54b51e55f4013d7d51314ec0001becfb03461bbd3f6068a1298b569ea65ec3748fa02e2f1d4de8f299a36936f22e8e4674f9b7045497b744b3d954b38ae00a5d81f103c69406c3c75dd5acd547d645c0468bc00a4dcd27adc5c82e9a23ebcd866d427364d108c8d0b56836a1df721813a25bf0a2e6eb86116142742b5ed474bd98044412581b906862b155eac09e4d2c9a4d888e2aaa13aad2624831c2063b16a13fd868d16cb047913e3e3e208ac554c506bbf52e6a722ff644c3e612da1bb644b684ebe912f640866e7843d335d0e8207a7fa878d154a4f4ecfdc1c11ada0abdaea486876909d8e64e71dcf9f58eb70f5d5f1abec625dc99e2604bb06b9c78f8d2f00dff78667fa8f8a15d5a02b8dbe46ed8fbbad7ace125cff0e1af9680bde13bea5abbb704f0126e0999de15d25c195e4469f8857632b043cfe65b219dd6b0d1da1a76e49d699d81178d1569770dbfd0ed6fe2f0eb939e6e87d7d92a55aa4c690727941d5de4cd875fe836a1ece865d2a38eeef09137f3dfddc4613aba6987e73f3a3ad220ddb1da8b2e7a87dbd1ca87d2dabdc6cd767336ef58bdef818dad108330dabd8a3f0dbf3cd36675eea2ddab0a897bf5862931d110645d9f8f4fef5455c5328c21a95e5be3b457b2e228edee309ddaced69f5b06e9b42a1ddfb053c7ce6dc0464110500c2584eca8f37d1cc3463150a3ddab8f8ec5e08c7677d875fdc24097658d8000f19b10102042cd8c11866118364720898d4e7d34a25880b01b4046a3d16834816411c8791c08193c03e4f0564b102357c728880b63b91ecf54383f5e5da6eb8fff78f51a7ed811f7ead65a6ee53dcd403e01c1dee3d82d6c8ec8e099d1e1278cc8755d2faf6120d774727301f12bf40b087a852ecc1a8dfe32fa85843bfe6a281afd8db0bb1cbbf5bac9e663d6d63fbe189298c67e4c1f3e5c7a4ce80593e0794c67072689662df5caaca56cd61268d65237e805cf345747c337670776c36a58454737ee38f1edeeefd3173312dfc9e019ecf016866167ecafe136416fa3de9f26ac21066ec4400e18d8010672c0c00debcaa4dce6d75fbd3a2dfdba1a193cb30d8f61af618a3ae8d441a0c35b2010086455d515baae67d574725355d6e5abea55655d6d563a0b68d0b72b5068eab406818e218969101d1dc1de8ed1460693e0ff59bd86abf8e927a53eff9cf26dca567d96112f5b831891fd61c11add6e62bad1980693e0195b82ea8a561174756b79013eb7dae4e9f8366b15ddfed9aec56dace099ff7d1c1c6ee8c2c7e634caf201e4b5b8cd2f697d9f6b131f5fe117f2a2b551afa6bb356b154d7db125484ddd54d5748f69f00c7558e1170d4f4d6e8349b05e0d9b190d4790c1731bcd0cd8ce68d8d2f0d9bf0ddfc838fcc50bf8e1c39a98ff1dd6c45fa23f9d871427ba9e11939a602d08cea8a8f4fb8fef654bc074248c76ff312bf7e8a02f86c4fdc705846c7499ae53a6657ab111019a09d08bfd0042162fd30d43f2e3951b6bdd686dcdb7162b8280de1522df26466b0f3fce861589b3a7db1c1d34eb8ff312073d88208208c20511c42d770511c46b38cb800002885bedca2610409c3122408040d7755d5d74d15ede2e2051fce8fd6982196dfdb87cc82711a9a43ddd662dd576d0e3acedd841ee0d57845bf40b85ae8730229dcd6d6b7435acfdc56a1804e0a311f890ec43f5f21e7f798f97979797eae54080bcbcbc86fff2f2225fe8e84810bf1ec47559a1500be3c7acad479f80f87520aeef1e5165fae57574be8515711fb57eb90cb93784aeebbaae09046248627a1cc87b1c48652091e50ac1292120402e204080cc5005e40e4312d340e8e888cb437779e8d6cb74f2fae5a1d772c533ae5028147a0d83bed812ad23157a888e8ef838e83eaebf4cd98d0acf5c3b803ce9e938ebf4c63b365b83ae6b1bc8d4697d1dbb5ac7bfcced76ebfa68fe788dfb31b77dccc90d26bdbbcc680693de7b4cb8c5f4462d55b396bac22947487dd1d1111e079d07957530e91d4477cc1164aeebf446bfcb3aa6375ae60832eec90d9e69f10c963982ac7534836740154ee977cbcdc1332251551d2b42eaea165f6e0e9ea9fe98798dea8c11a9ce6af04c7b9665d917abe1cc72eeaa2d8cceee3022d9dbdc162189e98cb21a4c7a6f542c8a6ad41f25c67c9b35dcbe20b0de459416d2fbf30237bae843d3f4fe74a1060cd4e899de1f186cf102355e30c60bbc6820bd3f2ea8a35d30870bd8686be59a666d96752d26692db57c9b35ebf639a5dc665e6dd2d23c4f65b37c00296f59d79c6bd3e6bb6cd67551d4e1e347eddb3d3d3a221f9f84a4d5bda1df5b6db496babda79b9b3bdced124312631d74eb200ab760d2b3fe6e75dde1b6245684d4d6172362b5f886bd45ba4c6a74871b748168a8ca8ec7a6931becf2372bc7be4e6ee445bfc92e8fd11abf429749d8315a5f8b68d5698d5dd2ba4c8acf406d62733b347516d0a06deb35dc96852189698b8e8e54a75e51370793dea9575ff00cf547a5dfabec43bf53b35161d2bbf5c3894cc709279cc81a9dbe3f4690e1c86f57f7065ee3c708b2f67749db4390f54ed6918a21e536253e83ca15c0f0b1e179733881064fb0b16204a51e1b989f40c6460b199b32dae1163ce3dec033adbfe8edeae8685ea3df990d21dc1c42f01abc00216a0ba3dfdb1894d5a02d0c5e00fd6b5ef47695fdfe7866142f8694dbcc6fbf372a3c338ab489ccc7c7c7c7669ebb2d60bab422dae1fcb141da21b644d6ee0f6b827ede614d7c9eb108ac8d10347331ed0d8bc0da502a5d4cfb6211589b49d7c5b457548070116b84f6233818d4fb33258c5e9fa9f7678a94de9f57c77f9020e3de1f16d0d1fbcce2e93ceb93729be99a265a9ace334d96bbdcdc5e426aabb9d7d6aeee70bb22a4761743be86792e460436814a93da95fa9da79c526e232f29e536f191d6b700494bf23cd3970fc0af0fcd732fe7da2c86c4359feab8692e1fa0ee0f0ba8f40e3753e1996d2431ed68a3c25467ea16074b89ec45d1c5a4c7a416e768761daded4d29cfe6ddcd26329bf75df7ba5f68772732eda84ea8c5787b7ebb189f3058ad4d1725b2fd6bec0241590961adaf3d627777cf670cc96bfb25e264e73287613937378a6e35789c7d6885f0eb52d00ae1778bdb99afe86512bfd18c499012d18fb630a9b55e187ead75613ddaf0b171e1d37cf956a49dcf6f9812ccad5d8c2971842f6f2d936c7f564047832edf2eab5d0e2372511cebd8ab59f9212a27e816688e6e9e8f4f87fedaf5860e9adca1d73068b6b6f83857bd2868853838bd610b45207a3129bef271e4abc35b0fabd4419812af1508f41ab61e9644bbbc05e5b75dcad7b0c38e549738a015e21e5a21cea7df0a714964cfe78a0ebdbeaeaf410f4d273a4b878f4fefac74f69dabb35fcec94eeccbc9f59dd8d9173b92a443e7063d9b3a4174e8d7d46140bb42a110dd0d029ad6bb78d6ead7adc592e0220b4711daa137eca681517baee810659edbd8acd76cb7e61ea77d5bb66f144d346352a4b421a8c53a584a64aff767056c502283bd3f2b9063578810d3ad9d56e8867115ba85495ca5b11532f1944c9adea6ef6c58342cb277f7c733dbd3b13d82087f9a7eed11d317665283b50fdddad9fbf3a346b7fc44a15b1e954c0acdd6496cebb42ad80a095d2b0474ecd7adead4e5a71fcd04593cacb2430ffdda23f8a1637bc476e83c61426bb0e00fa9db26b504d31ca5262b47b31554545d9da295a7e5172b42bdcac6c9a9baa24d2a49eb7b95cc7f8ff9353c9da7f5da631264be45e4c8fe34d35ad37c8bba168adef7a7f7678b337abf4e68a68f49709af5759c35e7ea77482f2661cb241d58f030e31979f32cbee07c0f02193ff25d98b46bbd2b9e7a8d6bb3c5055a6f42690d2794d611567f33529c25e2a375a75fbd1ade92a3adbbe6b646378b85296d1df69ba32dcaad0808cf24786b1baf036d2b02ba3773ae1671a829d355841302597b0b93aa399d9af20dd391fdb242f6922e7d543289671ebddc7c61b06ee083b0869f7c0dbfd95a3e7e3a6344e474c92c08a5bd437e14e7dd5d2ef1eee47cf36f7a3bfc93525ed2f71aa773353f8efcf8f11bff85b6c5cde956c392e04fb7f86ad8f436fdb851d2ef7437882c022f239d669d8ef32e6fbd3b2a18899296afe1dafa49ba1be4315604fe51f91ad73e457a31692bbf397954c606dbe06037ccdd6ad86111b6b16a4fb7876ee263bb0eaf57d7a957d56c9994152794d6505a5fd7e3dcb678dbf20335fa1512e74571e2a98c67ac4f56a8b5b518918da28c49d565fa7ac388345a7bbacdda1a279efa1ed17a9a5f21fb8c67647a6fcd8c492b7b3a124fd16785aac3bf5f6fd811f98aba30697fd19665d2c6378ad69ea67ecd36df5ee3ae59ab5315adafab5b6fd3716d7dbd3ea0a709bd1be4a2b59a3a5735b79ba3a68e6bf74d41e69eb57b0db3ceebc98ab3c2b7cb396a54a7f54405d056bbe414d2d37c61d21e7eb1f6a9413f58ed0b5365dadd6a0d2382e4455adff19269dd71bd4ca2dec233d5dd5d2acba2d53a756b9ad6dd339e99ee6e59b3b575bd618f49d4adb97d4dabf136076adbd35c26915c82bcbc64dd688d77adc5b94d4dc980b903bbd1162671a4b58a5965afdc2822c130c97dfa3269a2355ce376be595bebb42a55aa54e9dad3fb38775cef975e4ce22f0669c624fed5729ed9bbc3f04cbb3b8967b6dd0bcfbcdd83ec11ae7baa06b7b06eb27d4b66a9b14bb2fd61c194aebadd72cd7ad7ee11cda7b7c81aa6f37c7c160b4474386e1c131a120e4a8eeada16f0ee0dc7bd1dd7f08f04c3a41726b52c64ed3548c3d7f7e034b242f6f21dbe41f80edf71e0a30e60d2d630691f9b83a3eedd1ebe3ab7777b1cb754b6753463d25e4ce2aeeeceb9d6f6aff57ef7b9c0dac68ebe1fef15fec13947c381ad3566fa073290810c6428438f5fb3c78eeb228bc79c7ecd9689669f44bf567e9dc7ac2ecd83078f95ecbaa65fe7d1728baf6bb67cb1eb35dc5299f475c68af0f8947dba084a10bd7251461fd0d32b74941d67e52ccfa665926856262dba446f115d1f89cee3138f8b8e442b67f9cab5a30c2b2b3ccac083c78e6b07ad2b578f1ea3977ef0782b038f1e3d78f05869e1c1e3a2ff68c9321e5fe1f1e359c6e32bffb1c2a3c75b6eb5f4c0187b404f0fee315bef982de731b3f798d5a57bdc613b8ec3e3d977f078761e3dbee32db4470f8c1ad91ef5380ecb79bc07bd90908d6e58cee32c54741e54f46592e83be832a985569736c2e7c78f16beb88d8eb71ae8d6144da2d787bd8a2cd1bc5ab7fc9a2d173969fde31a4286337de5d3459fe68ffbb8888a563e5597beae6b7a365df4ebc78f1f5ff9342b939ece5811243c9e5df41d5f616161a1a31df48607cde8ae9095af5011ad4c5af4c9e58b216179f61aae2bff41af21642b34c7a5a78f567e5d44273a5aa1372ccfcef24c34edb4ee71ab5dd99dce9305f44e6361f9257a0d5f3d6e39992efa6247dc7bd09a51160aa5b5a8e5f5dd60df15525b2a73d1f135cec7aca2ef5d6615ddb01823c8e265e040693c2f2f8d6819d6cba8d6a1acbc8d2183dfde153aba79affcbd72d1775a8f6e562ebf72e9a4f54e6b96165a7bbae5a2959616f55859b948d483d6ac45e7f11d7399c483d6ac579ecd952fd38cce8307adb2579e7d34976344af712bb33269f9caad159c160aa535cbb76b8e4bb35c748b2f1696ef386337f22cb758e6ca2d8b312496bb5a66eb95595d5af4c592e05e790db34c6e165a5bb37ce5d9ac2e373cde42778564e7d1f21ac732b9b359b3577f5811ee95b3eca037bb42446fa12e2b44f41a66992b5f915fa138d65bcd688e4b5b5f7ac47a6b35ee9a6a65324737fbd313c581d2ba4928d3db77260aa535cebbf56237bfa2db7d462f31a0ca8896d11e290eb7b183ad1458d61b35484cd9f59eac71c05f483046c8183144a60d8c484b262798ec7a2f67d234c13069fa90ec8294c4a42908932618264df49d6a91d4a5be66f7606c43561df06098045d5a5c5e8ce8e97232c2a4a60409860d591dd2adb556c50e1349cd2af3d22e4f3ef2f4b61c4ac5aee1000dec5001d34aa29009c224e886acba34ec96bdb5f3cb46efe56e4b75e9168549f04d0a93e06b7869f36112a42f6352cb41d66ead9c227c8e9b04d52a7a64e459d72a7c7c7ca4f4d2ed428f6c2b34b016060e34d7d5e09055179786b48e1240648be0571fdd5ebac1740b52d10ab3f69e1e52afcb08134d383135c0246e7dcdba53683e9cdb4a30895f5d9af92e2e2e2e57d6625996bc6559cf7ad57459217c6a1e66926610263db8fd22fc6b4847ef3dfddad11726f1e5c8daab8bd5200bacf7da1baa4b4ec353d1b0ee34ac55b806834c2609f92858116a62d21abbd68620e166906e33e3ec7cc95575c933d3ab5f4c63bdaa60148ee12301e8820fbad032c7a5293a3af25afeb5a423f89efe1bb21f1f1f9944153e538291c130a99d89a3a9714b874bdd39e0ceb17134ef1c43907082499c86acbd0e698e5a180283041248205191687e153224fa5dca2cab2eef95245342630e681803668814a4747fb46e1b3deb90768263f85266998bcb4f22759369996e6f45c8e08f573d6392555514f5c58e94c008701003958639433afe75936da31fa59afbc2b21c7d7109d2ef56c3889098d42c1a630d5fd8a5d31e9322ad39303ddd7a0d5b158949ef90d61dd8f271a2d4e18469f886305ef214d109c2a47719263d7eaf2d04c1ac90f78c49ef62d2db210d6b500796d3c01ec1d204cf88424af08c75de7107903276b4ca60b49242b4be2ba97907ad2e5d49d30e1f9ee1717e8bd2f21de737293c43adcbac38a412479359715471844075349f7a153c033abfc433d8ad2f6773f0d0809215e2809a7df2629291acb2b866bd7518d1c3a3c52d2c978ed588662355d2606723988de657239aef44a504134df08c2561663517b3687d338924e3b27158ec66d0461bb5f958a1f9b4f4693e6db4e1a6342a71d2d146c8266e73f41cdda8b829bd42f4c4d6aee03324f41a84f48e221a234caa58668d8ba9be3287b898ea4c1c8d882ec74cafce84a3c9a80638a6fa45ab39ba7a5d38bafa0ecf30c9e119ecd5a9e019d0ab57c133d4ab8366102655c7a60c93aa5fd38875315535af21643c04632705eb6e5a8fb3c29c267b75a95947501cb2ba70347f72eefc2898847278a63a3f348d6012ff9a4198c4777388a361101f9b128c8c7a9551f2a255c6aaa85965fdaa0103629705ea6e5257f56a72ee7cc90d0fedc7a9d1528d8e6f6b64d3e5ebf6a1a59bd7103235a6d6d6a0a3c7ddecf138ebb23183bd0691e9588de8588734121d635d353abeee1a1d5f492fafe7f1fa225d0cbfb674fccaeb6b9696d7ab775cc6d1bcd01a8ee1fba0cba416872878a6eeb8fe711f671f3ece57c2332ee733e11959fd381ad234a4867acdfa9a128c4cde099eb9ced700cf5895a3717131fce9a3b9b342dc7f4c2a7ccc9cc984491ae018d783d6ada3dd9707dd319d60927bcb6c826532b1329530c224f76c3a8049eea159c32477d0c4e69bd2c5d150954b73cd5a4eb3caaefb46e72c1b3f3812c1e25b0bab38ad4b30b2e9d4ebd5f16e4a303279ead2d15832cb5c5ca64aea2a5d4c95a1173f42fa98d4f68e29662d584b6bd67bb93f26f13447d61ecf3891496e64fc7a5158775e37286c6b5de4b8f44d00bae0032fe4b874a4a3238f0a93c87b7b73d79bed72501445518fa7601873f1c3537e24d3b07c9a265a77da191d23732185b9e0293f2c85b9e029146fc152786679ca0f7341512c85ca7e2a1a61188f8afb82bd681d2977c1a4e92c85b7a03c8549d37ff094185faf38dd55d931d20afa54b16fbc689946f47816eb71c7b53c3f0b6575c7b5f518a275e7b53c9ce635840c44775e4fd4e11f46775c4fd4996efbeb89e250d3db797dfdedb86edfd71dd7cd0ce6e2fa7473519c76d813b4286c6f3aa495a774642e5a11315627bd1c978e9f66298a7edbfe6685b971e9ca243671e94771a622d3a92bda1d2352dd611712327831441290721bd15bee5a2e8e992e9a2b61e0251d8de84950d71463e5708ab1729699710cbc352f26419fae1ebf524dc9a478186a658a5ecdf66956e1e3e393513388684a17e3a46cb2ca2adbf114e602c4221ed0d1effdd9421b1c1f998654bd668dd64647bfb616001953e9d734435c8c7331f135bb3efd4d7fd3f4f816c7346144a61af730222dbe9d21363aacc733f0bbfddee8e099e98fca1491588dc8bbb17aa2431ccdca0a55e262dcddf72f0e69f775342b745d0cf68abaa5a3d169be8fd1241f2ec4d144f4fe70018ddec24ffbe8fdd142186db90b46793d51f6717de03a5a4fb4d98149efdbe26809d89e68a383490f7eaaaf772aa4d3eb9657d935eb89d6d011a2d7eba04f97b4b6b05c7ee5eae92dd5a7af3c1fbba8569fb0afa361a1d8abcc28466b4e4bcb63f31a4216a2392d7d59c7ae2164d7ab75c692c0897f7d511c8b5e392d1dbfaf392d0dbff4c795842c1e7b85c7686d72c07e6f676809b84ebd613790e2c4c3bea8ca61486047bac34d474f6f6768454c2e4c723aad4a5367ac88eb76a659b9fcf2b43225c74c9fa6bff04ca4eeaea7d7b01247b372b7329763dcbce67be1998956978e771705a7fc62455eb76ac2cc1726b975b4ca2c73e9f6ead2eedd265a4b3dfd4d0aff261ded0cad88f7f7094e91eab886908e1087e4602d1019e5b6d7d14caf59bcd8614498d69e52194d4c8f135d17e3de2c1e61807a7c13f293fca34d50ef14bd8b71af8978494b998b718f745d0cbc04d6c6c5c5b857fde2ebdb55366b33bd12e1d738d2dac059652399ef86365f00eda28bcb0ce2cb38763fd6c25499261d0de520849069ed2995011d74566902b0ed111c01240ec29baa610dcb7531ef70be334684a77963b550c3f384b762db235c2f91277cea16e5e262deab99b998376144e06535baa93d38687eec413375f28eefe9b816755951069fa73a75a40c6a1b17d9fe68a18b764526509da25650af4e81b5a168197c3831099c80013615bd8b7927b998770b43e2ceb432217f0206d850a75edfef9593b30c778bb11b515f3ce12376236a778bba78663d4dae4e837357c8e54095020da905ba9ac56d19c4af610d74cd40bbc75208d6b61564eddb81acbd8d2f9adfd254907119bd3f5718423395de1f2bb8a049bd3f5578c2cd0e167474ed4923760d410ba4d01b6a2ac8dc137a7fa6e0d34d8dde9f28a4d1417a7fd490a36149545788a37594d07183d6e10175dd390319425d77c6c0014b0ebaeee82007d619baeea8e00cb0eb133014a117890092d046d72768b4d12b7d7cb0add26f16c3d2693ddd829fe693d653a338fcb63f6aa8d1951b9ea793b642e07764eb6c95c65e5518d35d21b06a736fcd1a0fa31a981a6e34f6ea16ac56484f7375876145e4f56a6267ec08f5d6e8ae90cab4ad90f6ead7ac6c4191ade3fee0d37b396beb9ea9b11c2c7959f9fb9a1d375a5fe3744add2e5b7b6bd779b9a24a43e1e93189a7d6745a1f3afe4d879275cef3b9a22b5f67eac315551a8a6c3e352bb4de28cfab3253be8e8c62822bda0994d8d4a14cfda4a7a977ae3a131d0dbfc33aae231dddb49f7667aa41e17eb79837089f72df362b35bda6de989969a5be6fd412a5961487bf9f68913dffe6f5a338ee8ee2ec79dfde221baca645c6772d8bec6d9d00f6cca4f652eb697cc413a2f45b62877ea76e2d08dea313dce805811afd8e39418e7eb7b0ef5b5c5e0e43e299f8f74751d7dd755d5e974ea92febdb56c8c2191d990e3f4d933555a0e9f216557d9baa681179ead475395bc7569dc2693d5515852179af280e7c7d7fd2d3f11243f24e5dc7897f9f688dbf28f59e86137b357bdaeae92b34e3acd61d357130eaa119254a9428a16bb14b80c61ddf6cb4d82540751d69b3a9716b63cdedda735d48c8b03b87dd588fb462b7e8c8fa748c8e2c2a1f67f5494e387209272749516bd6eb23eadbd6e31c51b408bc758b56164ef51a9158745708d56955a83bab63eb6db88e666daee8edbd8c114390e0996d9ed653b145876d7c2bd47cb2edc6ed4c581c47bbf35c22abdbc606b2d7a2aea1762d8e1af9d3ef6e2e9155690607b2d755faf4bbf4e92acde877f9c300f7de6c1384f1ee138430ce97c6460dbbc0bf47fac22448f73d66369adc235c7d69f7e6e45dbc8b771f22a3bb73f1ce5991d7d818dfe247efadb9476f0af170b6481f935652c1dac3bf3d227e0ff788d6463009fe092dc324f8c55cbd7caeae57439aeaf048ec115f21f21993e4e187c4c8c3308de4185947467c41d3c231f2f0a33da235b4a8f9c22479d7841a8e522ea1e547d35d738fa6e9fbf38346efcf8f12ba65b6a6e80b93e434e10a5921ad1d0fac8da2ec45aa6eec76f6704362ad93a5b07afc4e6b1629228f23afde9f9f331aae90c897dfc9afa6e44fd397d6e9d62d5e5a5befad59f5a95de2fad2665954e7494f63af22e0831faaf4936d638c2e52d018b568ddad557475e4a2b58aaebe38d4772965b9c65891aa7785d4b8774dd379ea8ae24ce73a4d97737b923b7bacf6806095b2760af4d8f0ad70cfc2d11330c086cf94875b104b80f788e80a2b75534131e4a2a12115434e79382b50c4179c50c566ffa01856f02c16a6d848eab35898524b0da97644b4d5160b536cf644f4c2b82c588b352aede812070278812a78551ce3a57c5549525772b657f37a9c53bc554d48e3b424c48a60afeea6fc35add73869ddda61d0ac6d879b97c853d41baddea6a4f52d935a91e8b6dbc44e5177b45a969b9343426a472bbc95bd86dd456ba9afca65cb0bc8688927f4d2f201dcb3bb3f0c09a9dbbe4debd7e467736d42b38ceb9acb240a2b12ab5b53bec65592dae659db1b8624a621bc8090352abd8d7b2e8e527a7adad9e16e77b3969c409177df798f670c09a92b8f9bb50a9d2090c025ae095568b704de82d7041d24a2211147a1483a4d78871d21a21d0d2d7cbf79379d20ba395a7b1a3ece5aea78c68e10d1d5c5ca7787fb1d76d811d8954fb7bb38ac7d128ed6d698918d523d4a19ee1635f787d9e26be3c094781812b7366cc1e5760fe861414b24324b07046a5ade614738d4d3ad064195678a919a9698919a249ab40ecfcd15c4037a70d0122bd243a57594b405812a0f1539dbade98a93bc2a49cdb5b1a8ab9a6b43cdb5b1aacad369f8a0e3336adee7e6dd5187e95411c50457f8b4135a1d63489e8e6b1c37d110b8f48e4b47f7e670da754a5ddde8481d41f323c33bc8dc647bf8da62ed16efbcd218a31f4b3e4fe789f25d1c4d94321ad3381bfe4f946617262d14457a5dbd3f697c21c327702e8d2edabd455e17b8007a7f94a0865e9073efbdc724f7f800dcfba30439dc7e81c803329cf7dcbbe5269479f32a4dc33b9169487542edde9bdb6e2e63449ccea1196ef800408d99f617d16d886e6f619a96042a32a02a48b0832329814a7b5f379a975003097234df85666dd5a93ff8f78721e1bbbf69fdb88090c974e55eb5cac1ca5577d72ff7aabab3668b5805e4ad90d40a2b5e0e3bc277b7e4d5b00a480c68d16ce4add0a2d9c4782ba213f2564827e4a7d7dc0cac33dabd14312484d1ee0ebe7a145df438b1908f8793a7b281df3d627aa43c954d7c6d481c1352a843389b0d35cbd061404e565d8be96558f7a96ce0df43df4642176d59b349d5d6af795381feb022ed2bd7ebc4c9b17e1dbbc38acc26d6b1afccdad3a2f650e8d9bcbe98128d86da4173646168c071043ba0c146c3f4fea031061a5ec0cb9a231086456cbaac39b240736461109bb023d8d198a377f848d5ee91622169a9c7a6a25a4c6f36109b6248992e6abda6212d45f8e954a43c103ebec4231f03af71342d14e651be6c77c8f6a7c6014676e963d2102619515515b62ba45e5d572e22d2fe9061b75e594e9d7a36e5ac59cb5badba75ea2c0d2bb242b3875ee344f4edbc065159abef3c4b56e78a88cc08a68c381a1e675ec319cd5c59556555542e269944d195e1195973de93f25d8c962f86014e4233c07bcbc5688952469509d23ba616b7294300dd32338eb9debc56584ec15ab9198b886c51475f3ce34444b6408349db4e943169f446f3478f16e17edf1f39d0d1ee17d3503e2d2e2f4c33844d3b4c1834f7f1f151824dbb0c1ddd6e04cf0cd1ed4378667fd2f045b72371854dbb03de24c2451437896c11c624b2c518d80d37112e28ab2063e9fd91838cde36beb0e2ade864e7a2a295f4aec392d019ddfce8da83039d2d43c35b3ca1bc83f2137c0d4ffc9dd853652793849f18c243ba1b84efb60cfde6a3f1ce41082b3b81f11dae4eabd2adb1226d8ab53cf3acf79ef55eac6215ab5855af9291ab73dc55eb57d14aab73f1138e3b0e9fabe6fc10e15f83e99b1734e62047bf473a3af2a8d05e6bada5a18734fc9055986b3ac7b6870ccaf105a4b09bea90d6eaeee1b8c73f8c081abce87ad13c1bfe39c3164d498a2f49ddc8e3b8cb89f32e59e573326058bbbbbbebdc6bfdd6b975ceed4a192fac85b16a8687ac35be24912cb2eb2508cfc40769d6d2da9fe3f61e04ed0ae113e1dd922efdb68ac86930698a11b6098669b0bfbb389aebcfe28324132ee62dc730ad3b8f925c13039956f83827a4b5b54f93d16845f01bc3b7c94968453035822201e71026bd33e168606a1c8d4b907e97f4bdd9219319d394a8d0e2369c846680f6f7cbb24ab4a7d5381dd7dca6b44336d1b771488e6c08431f7af6fe84e18d7e830e9797efa6c1a4c68f31224b60a267199ddab349fe70755955d324b34b1dd7b57588e2b48b2aa74177b89bbcc392c059b9e813e8a25aeeb8946559f51a57512c59463d14caa88e6b9ce92daf6196ec2d6f09b1bc62a175877ba21476597de532f4ea8d8aab40151517e3ce32b1acbc92215a5b68a83acb1b1596ea9a6895a2cb5ba1299a15b442076bbada1c321cd061d75d91077d876764a5a88cd69e9c2a1a68565f99a06373ba9cd81b86e46a11add5f489f20f93a8bb368567b0bbb72e1a9531c8a0d24213f68651aac65d13f5660693e0bbe8c645ef0f19a2f4db20ed8e4c8fb7dcd5e81064a2338df28f44c2013c63dd9ad79475c86ad6aecab7cf216bb5756d54c755a922a505c3b046d716a55d6d694c619ab571fb03861f8c93d08a685f8ca28c462b02ca66c691d7d3046bd604d3d485a3a2958246e47437512a97aeb48c4a19dae800f4fe94218c5dd0ad09210882402090dbe186d32104c183ac2164ef923909b76e5d07cd9ab5e3521518b6460b612090f5ac3d03bdc681acebb8ce5ec3a159791a07f4ebfcd3184669dd79aeb59a35836e1dab391bc242ad3ee9a9eda7db43a1764ea31b88ca6377bf2627a1156155f3495adb3bd426258cc10eadbdf81deec99aa631c8318634c6404617a0f7078e3a26ba9319d3d7bdc64dfb6d17e527d74b8bf4b49cdaa3d5f5f4b606ab515bffa4d18dd6bd5becc6f5f4bee9efe7e9b8ef378baf9c4667998b94d933ebf1d5899e4d3813ad6dc7a7f7b01d530b36619f5ace21d05b40a0b3cc155a4534a32110365dd344ab45775e57b4f650b4cae6966b85e513e098038e9f7e95d3e8ea1eade8268633c4b0051c663411bd3f70486931d4d106e8fd11831a6dadf5ba365a5fcf9a754f8967dde5198d96806a45b7cb365dbf89a3536a795ee3c635e434b636bab4721aed1e3122920893d685492d2cd3dd9729be7477342d54b6cc1e3acb79457416d1ad49abb5426b4ba345b4e65c9dd11005d1f3d7d1baf330eaa68ae6e45cd44471aa9deb8c8677e724b404481a3f5d0d696d7f9493d08a705446c4b10b161418697dbd0bd360a0c3b730b21aa4f941648c1872dd3a1f896bcac7a475e1981813e38fc5dc84264634ce7b9c46d0800e4faa0e1f846942872f342b87f092694487cf78c63accb8e9e0e530249e89c7ce0fc233f265ba58533425c7c4670fcd202426c583e639263649af9d52e662a683b54f46b1693db29facb33e3a9daaceb3bed9c5a5dfe3f3a7ad661f9a291dd74c47471a4e118aa38f568dc5887f33c608f9f17b74c438c1085f8c7731b638302231c217a38330ceda13237cf0bdc7538370b00ee734cde5b9fd69e9e89a436a2929396b9cced4b2f27484d374175fc3d3f418217c53de74d0f10c7c5e3009bae8e4936ea916676059d6626fefeddb5db8fbe07b6b077e67e0f75a1cb3d101dffeed3e334879bc054f5981f537db19422fac36ddd5dadc8ead4dadb5f73dcfdae0dc26a515d1ce1891a5ae3d4e7ee3c60c679bf2412e5cb0ed0c2e3dc9d78c7aa5babd6d6bb4be5bb49a7e78decdb6824534bf2106cc020c3bd836f82f4c7a4146e20f41a2c6013cc37f69716129cc454bc0767bab61291bf5e6d2d5fabbae9c6eafdecea42deb357c92f5277fc7537b758bb6576f159386a7dcdffb42e676d4cd4273cb1a0fb2fae6ffe7b7d104eb3cf3a650e77d83d4eff07df1ba78535e0c9e17cf8bc73330f49886fad6ab1ff3abab39a6bee6d6fee3861d7a9a6ea696ce4d93a33a53579e76678cc8c470c2c3bff384bccc7f2b99666dda2d8b9d7beec9f7ce33ad8a86e74607848fea4ced1cbda6e4657a1eee99381681a23bdc7b9c27778baba9af175fa4404a0a9a175e50121ea1096434337ae7314fe12e780b96c25cf0941e9e025ff375d5a08dfe421c72df7b538eae392def1dc2a92b086b9cced4aff2c84fb5d9a1eb0ecbefa9bf16472be2418cc84e5f24db55343a98247b7ab3d1c1248aea4c3da728e723125f12cf65ef0a65f08118ae46061186592c3d16a4b28c85a5aaaaec22161616f8ac86b6217561d7c4c130a6588e5dd73562a10fe8e9eb3acb555915954d11ad21ecba300bb3308b8585e52db7ac6358666556c6f2d0ab4b5b9675abc75940976f59b95844df711e2bd7cac4b9debe437489aa4b5b59265ab945a104d12c1886b1d0510bf616ec2c9895652bb4e6dc124dead90cd10afaf5809e1e61c7b96e1dbb6efdb29649555551b43d21fb811894602d8c55b53164f1d39fb5486675b8722f90d1edd61743725d17cb8e10863dbb2e1008849de5baae1dc75a7478da77ccbaf27dd576c56a21cbaaaaca42b22b84ca42d764a1b5c50b5f7475e96733dd0b5df4f41752b3ac1eea22c2e3a053d39a9589b6288aa7afafbcba3465511645cd1ebfaae8f2a0a9c3d37accdaf21dcdd270aab7ef98d710b216ead2d4595ec32017ec156551af595bd42d5a4718bda17e559619fa3557683b9f9afbea883b925d2130cb28a53e8d9edc804e1dfbe849757351745f7ddf9c6051df571485d2832cbeb563d20c4716ef3ebb4da266e540c63a865dd7454712c342c7ce7384047491f56bd651f66d267dddddd151466f4054442f2947217a5351948fd16acd8a1d6bc956ba0acdcaa443b75a5eb3b6342ef2665708955d97129ba25f33741747d376632a45b31b63bde58b2161d22069eda89ebdc655335e34335a9d4befc056e808abb2e1ad4f67c16e71b7cc4ac4368b942d15c3d808e630eb75dfa0194247d7450fdd25fb8a73d5af63bb424474447d541dbb75f96cee0ab919511412796b44b91b5921ee327d49eab2424034c7a5a9cb6397e1218e8eae577777b1768554777484557444611f5d77c76875ea7b49eb486217bdd915e26edd541475b9a37524e98dcc0ad91b59210ca57593c14c60adb54a322b04ab4bc3927067be44e2ce971876e3ce77c1a6ddeb494f5bbfee2c1a8220bae5ee92ba3c4fc6b007f4740b1db1b0586e77b4833ea0a7a9965ba75a6ebdc5927ccd7ad58b56269d73372b939677a067b332e9ec2bb778bc669db918787755cac8baebae8976bf9868f71d6f99d5a55b8ecdcaa431d129cb7acd2c5a993475ac6566c7e6ca33472339c69d07a4d8af63d82f8c5626edbe838ad1e3355c650bad590fba1c13a2358e4544ab4b876675203abab0eaf13a3677f8a2f035ce715713677a3b35735cb4b84d199394eef2cbccaf5b18b23064bcc4e4688e4b1f812b2cd760b56d37222f3304defddd858ea0759cbfbb6d4b47d3f7f0d61c4d1fc9f3484a49779ae899d61c977674f48ee3fef838eb287ed76899dec35947713a4e3cfc44e321a46cacb16bf4fef11dd39eaa3d1ef8c0073de8814fbb5bcd07ed0719ff669dd0ed6fe376c1075df841b7f87e30ba69210306ddfe2894e69386555bb393f69d37bad9bbbb7dcf5935daed2eac9aea2364dbdac8ea3b32b523cdd8168c93a4667ddd1a1c2e3460d615422d84f86a6c64f56a90c3de05ad584d94bc5adea32d577d69fe0bbd98d4e48cecfa9e31895b98c4fdfa7a6dada4dea3dbc233eff5ee0c1378b6dc7b7474f30e0f697dfd68f342d6ded36c01c1da9d79776752757467de73ecaa544900bf2ef72ee33869bd55aaf4ee1ec1afbbbbcb805ea705841042a18edd7541484ac8c818718044c119dce8e535b850830493f66a18b142d68c36b6d0c6e38106e42b857dbdd15395dfd3141ddd54a74e51af2a8961971865a2665eb6c4a8c42427498d3069ff9e03608491ca3089dfbb7b94d49af9b1a16ba630dc3d587b6cf0f53ab9c97dd7b975c3d26aa477881a3b7386f4ee56a16685b4c00721cc340013851c985ff261216b87300d0689214c8a628841f697f715b287e93df7a4b16a5c61d5904f893da2b442da3748154c6a3454b89826630412350e30a2036b615a2e9797f3ccd6203b0c2948d6e2f222dfbec3c850c9a626984603469460a28d9e98e098e97b984ac6883d027b9b645ccc647d9aecd0d3a73fac7391b6284c9a445f268e46caac66222b5e3dad010e33be202376e1059d2cfa9814a940f8c0c8e0eb45471b5f78c15ce38515622b63c22456120593f82029535dd8cc59217c1947d3cee098e9d3f48683acb62d7a7add397aaa57dba24d695d30c9e119ead3a9981a3bf509fb747d9a2e9ab36d3446047b4d5dd35bce346b333d889cdb0b335161b06af6082a56c80a1f14c2b247c372aa8a708d95d95a033ce300238e46c60d59a3463a9a28ac2fae4974f792752947bfa0310734c0e430290a26d99460b003782608939a4bcd10921572691d84675a98e442729b6173db62994ca20023abcd67e9f079438bd2a4b42d4a73b4752a76aa888249ce10279468a009268c2891f12405c290f688a9bdf71ea504939e1126bd75a3dfa73face4577f724a17cd0b9ea968144cfac2fa76f577234f3ecba57a6ec8102f8c28c1441315cb3f09cf24181726f1abf94272345470ccfb6b34c8eaf6a1df7bed2f8a11257826fe9d89262a2a76968e7e54e80450304357ab4657d56b395f4ff1bd779846257ee1b9bfb8e42093cfc5882eecee5e0a59bb64d28b8b156ae2d2383bfa28ba4777eb874f1a1d51c7716fa73e9a3e596fb72a3a3dce3d356993fb96b371bc5973da18adbda1c11a3db98977871f3db989745708df3ceae8ae907582139ce05a8b628d3edaf7fd6b7fe2e848fea3781c78f748e1dd21efbbfba36ea24b97f9fcf63edb4fe65e21cd6963d44773368e76148a93edda1bfe32b5e8dc1ef13ec40a818f89bcbf2033efafdd5be3b8e7ba3ae7dca4019825e4c0f47b6c96bc943c0dd8efce39b71204b342f654644ad879f07d9aa6697ad1593ed8dd5d07e1bb92a7b1031bcaf7e282868b6f31c6e8761b115a88d0daf0f63d7e97e4130c013eae52aaa27db142f64c5c84e04245ce1aab86038c0c09c29086512861d25e26c84f1026ede3c896616d798f562b3a36a42d6734fc7b6f40c81a844d4a8b32650b26ed1eb1cda779d1ba0861c10c59db37dc60258c4882114a189141d68290d0f0de7b87f385278e7e5490d0a8b45896913aa4dd1b13b276f7217206d6e866e7f5d22898b4d54d3bafab373aba697474c36ff11cb1b6263aba919f3ed1fa7abaa44e5ee70c6999634453efe99eee690b5ed7e1459d60d2ce9a6a06518249774d3069e183940926b966c41cdd3cb7c456a9f2d38eca3069fb6a2e0d66b4dbf17db6c3343cbe2f4926bcf2bd11a61932939d4492634644538774936385b0c1a4761eb3a9c1317130a97dc76c6fb898f696d9da7031ed249e0902fabef9b4284cd3f27ddb8267a6b42ebc30e268380ca6542c8b45a6e5c3e099317866ba388c6bba688e4bfb61990d0d6bb63486642c194b1c6fb8c1b28246d6861b4c5342c3d128695bc8d1a2c031071a74ac51453663931ccd902abbd9e09a32eb72baaee9ba56c2a0820ba69c21d319d96c6498e1e2826166b4315a18a229c1c85c184ca34493e26864168e33d68d4646bbaf94763fdd5e9b1746a4a3696fe01877d7ecd0ee1668c26e73bc81b7e0198b26b1fd05cf8ce4b733394de982bde099898a5507cf341f071addb88b562bdaaa42ce9d1068baa66287695ed809172408c3c0b8b6a80b93626333b6d53291e018e7de6690d5d687766f7de099ba3fecc351ecc0333567eb68eb73bcc1c27eddba2e0cfb6247b034da70435bafe12b67d968cba28d0a935a1ba385d1be6052c392685e4ce982cd10b188093acd0826359a1a17d38cfc4c1384635a0bd34867441019be74342d1c69ab412663c410240e430ac2332d3c23efeed2d2aefaebc5a88ae65c2d179394c4a433a9bdf9609c6c1c87b5339bfeda0ac537c8d17b0d304d0ec7c4ef99688267aeef9de099e700a651c2fb21f1d27a46ea35f62e4c63c4c5c4dad27b8983ccbd5405936e90d516a5e3a73f6cf57858d124b6f990b62e9814a918587c158ee6714cbc94d1d1ead2f475ac430d6ff8619ac4a6c13323feb66412e49fc133fc860634e3c93c0946f65e9f1ce2e8986344f323d37d13dcd275d7f0a2baae21cdbfb89ae8ce6b668249ac841126f187381a99f8241819df88a3418263f8510d92a3696a704c7cbb4156db171d5fb78e8e6f63f04c7ded0b9ea1124615f2917a7c8bc23335a7cdd1d7d5e0998b67a81a1d9bd5b02391083360a3af9c46a5afd73ef1970bd3ac4d3c4c6b63e24a05efbdf7de7bcdd16d79686664ed2f4cdabbc804e12d2c8470dd7b2dd9c5695cbd5530a25726480f5a1959fbbe29a6afa8a4a9156a84a19e441d5308cdd048830002831400303824148b4703f24819661f14000faeba544c1ac9b32087520819638821840003044060406486004d00be28462c28a2f6a0a610a761374be6040d6f85fe866efb38d9846c6f50a36c3692030ab77989c490c3d599539b2367acc9ee78376b35db38b11f3022bbcdd0d7371409efbbfcaa7d7d4aa3cbc64767915124db2f65f80c2bb40bea2112f58f71c45e2e805c403c15d3ba53e0302e8b98cc80089a97357470cc6359cf2b9e930a19a80380e685fd157e9b0c09ee32fcc33f1a0f73a7d4af0b54ceb009a198fbe0d7b56861c41cf61f65c766392069e1e56347be940fbf7191528e2624cf961e68560d4ac7e3cab8a0fc85a6699c85163b49863afb2d237e88c969a0526caf548b6e6598a88febded86d82eb69726906f4164d977e7397ca73095c66b059d3be2184ee95252ab7ca778b1cc98bee6a6dbf182c09821e54d08a520739d4b8d497612089ed27268ce59a7c4ea418c92521f41cf6e8defcd4bda5ee6a56fe3b3228275a53e6c912dd4dddc6cb68bbaa85f938d7efa586396f292b728524e5444b5fcedac8e5a053b054f421a9689cfcd19c0d9060bc4042de8229a1834f68b0b20d270dc2f696f3053c8419fe694159a5ec96f472babff7eae48d67e79bd6ab504b252a980657eeb701e75ac260129e422bfc5b5d795c61c3b47c84051684ff4d4a8cb8fc8870451645510ee0eafc80d78f9556ed2d934c415b443306799a6e9303cc1e1ce0f15188cf2d02d79c40c8e1641bac5472b63fb533a8c9391570530937f16acae7cdc17a997d642369ae3bcb7249136fcd8452d933caac278bd2161939a3fa4d8d34a4a02a0303b272d4a1e9f2b810639149e285566d19e53fd0d4b34bb83a010d2dc035aa3b94a6d7a4d42ae83c0f996297b2f44e76d8f6c69e4b24419256c156d03a1907b109bc6b3c2308340b25f0529b39a74bf68a6548b908ecfaebfbb7d5797eaa250c660903c1efd81b20f8dab7a641ef7ff007ee7a493e35b8849ea7fbdac1cc1e8805256422976286a5db42a09666700d75b3721f046b5669d0a29000aab575ab53e0d24756791bc920fe29cb1441b907cb92f278622194cac86679a20531233065d7be23b010b5fdc8ba63bef52f141d02c25b7cccad8191482b5f0622e583660188ead0dc16a2db4afdfd2954edba293ad83960e91f8cb6ba11d472b4c3f226cd7577d80e053d4fcc4070151733a5496c8d7b57c701665a2b415a6434e4761ebd9e61383c6e0142d8d1c2da054e04ebb0903b0bd95d402303d5129265f7b6669a462e24784c71db10f4d05847632a521f0ab10937ec2c543bc84d3c224836e5f2945566db65e5c035807848eed0c147fcbb2cb6c093f7b8a6f592f7c625aaac6e12db762a45483d5a5e711fecf58acc63074eaf798483e335a0e6243f2a075d23494b1e8e7a49af6e7836a17a98547bcef6ececce792a8d4d6574903199036bb7458960ea0c0ee465d582feae412c6632cfb2789bf44372fbcf7b8be77f0809b0d0ac9718e165ea3eb3cde224b7a127c63d604a3eb76533d07356409bf48dfe3512e439252b46fe3ba3564534163fba63187621855e992f6487c3e3e72f2e76183372e6a274671235c8e257b26091e6f7b1cfada501d999ba3fe4dc875fc39e8773311986e81b461ddf074667f824a808d9f5e55bfef178a84586bf636977d0cf0e02cb1224bcf014ab91d88c2304955a41cec2f470619f81828a585b6daeaf88288212ec1badbd517540205a735443d8c4c0b2ae3709c68ce193774ad68bad8686a39027238987a249871c8c8ebab66d63339f43ae325f6dad06e447ac0fb7fd1c6a5ff2cb39e08a35bd4d49db863bd2f00240cb9a5e0a9318e3c841f928265a7048e5b10b112ba49c92e2994b44991e1c6cdd7a5dafd3ed44ccd3ef49f4fe410563d50485ca001fbcdd313644af4d6701d5682f7aca318931f4cdb4df21240525b878aba868fb054a1982e095efbccca34474ff2c2f6c2d801a3ad3b87d3e1a7c3780332482e8ed10076b4093caf0f95a321257078cb2ba82162367df5c44dff36d123294a234c39d92d2e99bcad214e314e399dd67e1f847ef7684d59533bdf5ea63da4b7b7dbcf5613e2a39df6454e4acc7a145be830123fa57bd44301f8b1c24b39b54881fdb5ca0ee1a69ef850deb1600fb8684fecbe8c9f5b3b843fad4eb0152b4530baf98a56e9b18a1f67d8b2e888aa7ac03a392b5b6fdb9dd76125cd0cda3cf40d12fd21a3dbc6723b0e8c8adfc1e5b2bf4dd54e27a0052bfa80b546dc0074562bfab87367123de85ae43100a973b955b6c40ea2d8aa4ac21c3099b91b99497e7939e0756a0ba2b386e9962f5116819dadc26b9496cd2a444e2b51f8c6eee09ffffbaa457c408c5f46bf6782eaceeb7b40a5444531a9c40af7d2e3839e5f07d034a2e7a19fab0788819eab059726e0568971eaee84bb88a52bb678bc8106614e8f00979fbdafada57eb1bdca04f8811b863a60e027b7601731757bdb69a177bc026bd0f9ff5b0e7e80b3157822183103e41d5c036c110d5f8ff410138959cb060ba3d27cd541a25cc5277df2a752f231c173bf64388e7f24ef06a37fe5a16a9761e7a02b10fdfac435ba9b731c6293ac87b3e325e2c77d7d20b1a5a4392aefaf1d2e4b62afcf193281ea2b0aced940cc3c631e70064c1e3787dbc123b3284a7c2045767614832dc079cbc9f5649990394213d6e8563dbe98072834b15c545560335d15c778b0c10e53a95d612fbdeb953d438ef64a9eefa1581b368a1d9dc4ba4a59ad2c3c83032974c0b1221cf5e21c6ba2fcb6bc33bad49add125f3dde2cf35806d7ab8cf745d2c4ec6e8ffa1a04a653a77861561803e5717d2e61a84d2e7ecf615584f4ed91b5a5d3464b3b3fc8d97b955bd29152ce759c9dcad4f6e41ef0550fabdf0d743a3ba33a436d911fc8ce92d83c1fcd1bd2c155bf4556d83eaad1d46bf1172360e8b87b523d23d2aa4f1c630c0b778710f044df25b72ce10d39e2e46b3ed11583fbc3b08b341370c351ccb6c06381ee5885abd3635d765d2d3d4e3d53602e878c4dc13df8b89740f741f6cbf3931c430b43dc2501458de23406396dd26260678eb80cb3c0d4682a66e61b8da9e80512f7095da522fd66df587a8a00d9e293c9889646d66db31d8c089595c976d0b5d17285eb246733595c21d50a20ef19343aba5649c2d51fe8492e96c100da53290aec36eb23b2fa0e7e737e4871c40441cb5e92d190d6820d482a87b065b1e37692df7504e7735d0e95ebf56b4e4b706f144ba874b03036c3b74c3cb64e11887a7cebedb432e0f8ec50e35251d64769dacb5c20ce737dbdbaef867ae501afe450161ae070fa8b7d517537de560e8f12dce55879f572dbb8f8686dad51149b0d96e799ef7fd0d871bcb2374f0ec1be491c1ff7313f1f9e7a2892a006ea12aa4f5a26350bea1de6323fe0dbc2c9910f71931201ac9db4d56df67d88d61fbf56b47623ac7b9202126b51ae56236585ca0a894c49d0bbdb4d81c3b61144565a1455b3b6599aae3e85cdfab13abe786399667700f9b8ed9a85e8e581ed7a892aadfb4ea11682f4d77ea89c5dd36859f9eef514c9a5f8aa3d672a9fd5c3bcbf61512c714ce9ea82a6e77b4c47c7bf4c1f7e224019f274ebd0aeacb71de7ba8d587b110d711d476aba402dc0389a3e4131173dcc005f41abafc1f5ab4ced996b42d11e5a976c73f24d8976fd761f3c279a5b936ddffa46d954f0fb2bec88faeb292f9de3e73d3a90dd3959365a1a4d6ebbbca12ed674d0cf1f4dca4c15e8c230267557e7e47a0d0130cdc76215413e7e4d12b5e55d0893ab406d5e1b2f72894b223c9a3f45e9fde1ed2ea4af01400e19f24e571dce0545114a60901fa2a73a22c4b791894bfb0dc3ea767072f0cb5075a244e19bbb47f33059c9374b6e3e0ca0064a274b18ac4fb6146a3d418c6035aade5433b53d4fdb8224549646b1a0b6be44cf03ace5612ed4218b0d42a0e771588a6ebd5d0088476113b0da970c57ceb1510f6204c934cfeab38db4f725012589d434e0aca54473bf52f1887e145b4f00207459da412b5e359802622c74355f245d0d95f0f745718875ee35f9745b6879bc30bfe29276fa63bf76cf0e65fff01b4f177de957439b98c2ef8812b3cacfdf71503ba5dfaacdbc3b2dc95715ceb06064c67cf2f6eedcfa59b5a0be27bbb082d305dcd1212ae5fd952b8a929e0fb25e81e53b5db52d181669f40dcd966dac808b555dce81e26d5e3f654f4ccca819720ee56ccc030225c157b960e04600631ab269429decb3673ff253d4ef5a4f6fd9047d0ba5b7202d237b57d85142174df550602d646110c212d57e5ee87de13b0f9340a80bef77b0167aac9aae6db7588758248c5c54aa071acf74212dbb1e0a592cff58f12f6492599ba6873c0475197030d2513f80da0c9196e679cf9891e4765c37abf1dde8bc2fa3d8749653fa39342f29232cf4a5e7adac47e08a87079ca8a3db81d41e6fa0133d63ebca5ed945f00c75677e739ebae6e127b0e4385190ef009b1416f5e8686e09443c603418344659433c0625baac6b2b5024812c3895d9f8aabf6b829994c3d5248243e003cf3101f7c83238c9d82dfb3b56c8dfe0e6782bba1a639c0ef47b2a2477e4b7906ea9fdda1dfa16a7830360776dec2e0e7897d113124c531a6f103f329b2908d92f9cbc248ee91f788234a0247e170ac6baeb72089f2ef35294509b1fd620c757bd259fe0f5cfde5101799349f7b0b915b48e4baa169fb2f7b860898694a5acb13c7cddb2de4cdbd952c8973d97fb631b7177403147f0cfaf008ebd4721c8277113a79cd3161f49f36106c6538d0a4850c7dd487b2d7cbf29de0a05fe0721bb54bed2588223d76cb889e8f2087fa12278de7c33fcc9db14003f8b88735749a11eec0e364707ed5bb7400246e03f7540ffadd079052001845f50aa64e20d9389067d28fc1287a7e0d02f6a2a26c0dc9ac3459e87085ae62bd9f5516ea61fa963adedc84e19f3a7dc8aec6e22d2ec8655ca8c800a5bc8378fafab729b8f9a1fc2e28651c8ba75bb8b4cd8f5b7164e4d3425433b73c094888b4fd4c82b11386571b1732effe3985bb076c7a37acb70c51a91b6c40ef5e60bd1bb1746df0db59ddfb5980def8f49bdc8e115fc08a092357cb6dd58ad1fb596c264d446ec2978904d92caf4acaa223b2aa3c7f5fec2856a9d50b1ce7dbb18bcdf45b25f1d06be13d928b189320e315eaa2c29bdc859bc9d662f56e017d3368e4cb564efe4f907019e450d2a1d84fc5ea02d80af785221da2c558b5d6e141f62ea4f620a4086ed978502eb69516331cf65ea82db57ec934c1cf433682b01ed2f0562424c8dd033fbf686dd869e8cd952e919a97a76b554afa9b83f8458cfb35e0e0fed849a458c758e3530d0e6ef6a3e26ccd9c658e0dcbbb26e558e34ba07b926e43f921fd9036c20a54fa62d144bf74c235577e15b2b837fa12f1d3e2bce84a5d5b460c59edac42f895082d184e6c7dae0c2a009e4bffce30608a2c3a0727b7e1aa496cca9b965cde9bfe81fdc4729da3c1b7fe568a074d1e340178d3defd226da3c8dffa2b4cc7a101739494da9b448f8f9aed684f742ea8f155e4d9cd6993a2f65613e31f58ac60679a451438e7dfdff992ee05bcb235da53ac0cd0cd35af227e57116dc901428141e19515b88adb6f71f3e980144ed98f374475e734e91d3e7d0fc51e852b21d65fec478e492bec9f84482fb14bde37a4d0b3809317397a49ee483d781c3483d03bbb8c79830fbc468d15084dcfb15b640c217cfb2f5d52bc32f508229bf535c1f6b4733da196ca8455540c226e43f0d064c6832b3360d022c42537ab69ba8415732f57d1500386b42350546cd5848cbe0c0769ba517208fc690fa3e05fa4bd21664d7b487dc9711360af1eaffd289016290bae5461d622703aacebd57da603160ba36fc0c3213b4b659698fc1737421f4c5cff24a5fd2bcda83f230e894e57c1a4eef7b33f9401c4d8850c68ae6c7bfd20accaa85300bc6799cf1023c4c4d86cca4678eb9cd2a16595f4a07ffcf069926f57454629213d7ce4a5786ee355cac2c3ca25b9102c62aecd9fde9405d94d5502fc12fb56e14fb4c4002f97fdb1840137b5d77593389ccd5007a19617fe268b736aec480f83069c8c4f3eb55f258f7437a645362f16e41d970e4fc929775687ff02e8202cd26824cce56d398939df8886d4cab5e3f4f74e262ccb006af5d1ed55d6fa2baa4b53f521be3a336e72326e1f87fb16ba07a008b7d531cd970468d58f2690475cbd2a923e668a11ab1067027e52fab45a9065951d7013c8b661c09267adfc54f5679009969c5680bf01d4a9a6ca85ed40c0c5c38d9582d8e612d6562c0889f31cc2dd51f357bb90106a1888418caada8a99886b033fadd09a63aa976d0a067054c7427547bca61239482559ec64bb7496e47a4454302a97e3840453eb5c28d54ce84f309221152e2383e18be3ec6a8069c44a1d2abd9edd389b94ea94eabc785dd6c7f6653eeb6ef7553820d266abcc77c26cc4cb041fa4b72e36084b76f69862700b050deb657dd09d333aa7bcae81855f42b3bd145a1956bd026ef792af1365f2b15baba052119e1d26fde4a1d65aa2ee884d32794fe5d6625a10eaf3626676483c6081b49df0958e4b26133a3db874fcde69fc007512afb86c64e24946eb208e56f25a740208239aa58e16f013db500d44ef243f2173bf76e3f08517a795083457d4df03f96c6e8ae4900f7d4df78fe260ad07d437d92108487dd9bc449c8c79c36331658e3d6f9461ed07a3fce6cc0ab03e53dd4429473b943eb722374e690878340c31704f152f8d31f2a0f602637dec39816236304370e423f6d0411e2e0164f64e00a12fe748369d7d4dbee3f5d65d1c9bbd7cab55718f29808671a4ebd89c33148a5d03f7c4e2c1dafb088d8daa3d86ef68294f2830548d001b72dec9d07f8f7a208451dc2c71a7c7748805ac58902dbdfc7e1413d2382ceaa0f643fb5d8079d4a39005ea75b65b6e3301e0a06df132af3e3e95a56007e6239be1300b84277ff6f7a98ddd03346abffcadaafdfe1f66c0d5ab580c85ca50bf6cb50f904a067e4f4c808dec6a8d539fc25800ce111b331d37d55eeb2d44b5168a9b037380a50033be796d4985d10c46deac0bfdbd996947ff7996b180250f25eac3556792632f41f32b7a0654735be6b88e928e2189cdd5f458aa6949bd1ed06b0bfc7097bd12c5bc85b1beae6647a9dd96237125423326052c16e9677e2d6666a77fcc7bb65540d48307c1eb48bd83f4ab5cfcd0f98c8d3bf75d77ef047d25b83de010f4ce739f2329eed5d6eece6fac4e7828cd69a2486afddffbc6879f11c391b6b1fe654ee81e1f82e89214bf736248a34b957d1640d51b031981c45f8a7a7f756fae476d6bfb918f2d773f6fc8d24963ab637164bb8183079c3ca3079cc0aa7714ba401f4da2b3e2505358d8675874008a03868ae2550b5590d9238748c82cc8f4c97e4c60390bd1109a89023aa89a912b964fc60053d417adcee7518682345f0d520cdaf0bd12d73f367a31fc796bdc674a84af99be2f6b921e9739696539d5a03cbd13806d52f559e81b06447b004dfc8aa307c650549dc397e4db9d8db3706923a2ee6c21ee500ea222dc6c1cb691ad0b24f49748d21f2b8bb33b40f1f95918563f4ed69275e527735d356cdf6db7c5e13523826f2428e22ff2720edf902f3f4db944834b546f514217b74cacffded8c5e0321368ad4e65a3d3e92a92b4afe6a0e8591f88dd430b15569ee28f2597a1735829c0f4ebb97deea0730260763d5a7107641e5afefffefa484b56c50747b648c875685de1e40761c93c8810205635bba8e3e2250a1c54c610eeeb9a7bc0bc2a6efae701b474de72c2481ff3a0095f2461b0fe5927694252b8b51c4b1d85c5aa5a5a0d428bf6fa6911a873c0845cd45c49ed9bb1487009faf1c145172b6b941772bad782a969973a65866a9adf4b3cfce75e4e68ed30e66d079b121a201586b9563bb53afb2916aadd268b6636d4445b12b93213f6f75ad115d0f4991b1d9d42845da4530c66aec35a1096e5113982bd8f50f8b459c4645569fbae39f8fe8189b096fbe40036214336db5b7326251cc2c00aa5e5ea871ea65acc2a15680753280a4e2d737a8d61c6fc4598b35364c569eb62d7af4369310714ba5416fd5f29a0b953789efe8cb4baab9744e6f2d62fc6b96da6e9173842dc72af3d8452b91825061f87bd8be2536f321d0c0a7628a331381e85aa0ac9ae84920f1da55abb8f9cf33247f8779be37e97bd98fb6704ad788db189e6433b2f0ec40d395ea551b0db180562bf1d8a4ea45f22984ef0dda1feb43b14bb5c10e9643c1de9e082d719b9a04a9ce9f01d62c480dc8201fe908ce9759a08296b2c88afc2c993fe5a87924431be91bc10d5e28e3af08e47c3b4c4fc4129dfb88c3f337184f47e63a27a5bd71210ce8742eb8f4ef79077a89ea81ba0fa5e164dca552dcba5ed8bd00d47478d0377eaa5e21e493f72e0dd7916e1f2a0c97bcd7eb4fc47f71bffe1f586fb70b9711f2e37fdc70b6eea164fbf34a3fcb00d023a22e30e44331debe9a043509ab55cdf68a9e5be1def914fce98cf3757a8cc1c76e2afd4fd87817c5309a71fad6fd2e3d05760deef776a654f4bb7c6f2484e2a0eda2615c485d1de103bdeac81d9d3cc8cfdbb3e4e0cdac75c5a343cbcaae22b3e29990d00a7d836a10d4227da67d0fb2b3ce64f8d6d867a7b75b2c3ee030bac10aa1e1b7a0126458fc7a762807c29391372da839c65178b1ac87260499136029a1e0e6a487a5b7de1d704f19234c18d38bb3289b1061537e4be1616bea1a29bff736cb0891d6c4b0f9e051ef4b0641f30de07c52449fc90569ee5dffdb4876473ea4db27a74b83861d0ea589498d431b43258f999de05e4c8507441ba68858a12e98f787f9c1cd13adf444cc44bb3bb64d38be8f64d9235a29f209ea20a9cd48bf850ee167c9b865466dfb9d7626077c9a2c230e12d01b16aeafb7af3acc67b67791387bc53f8ac7048e73a28e0774b8d4a2cf1e226a393c60bdb9487e5e4280cfec435852937d5ad8cbf0f763defe1b29050dffec6372b6cf831d0d88c1ee884608fea9254cfed8694454fedadd7b66773d4616b3fadf6646edf3487ce2de0b2faed810c602941b03d7a14152aa0b509de63a4dc289222e9ec8f025f2a962e69c5701b8aaf3a1fecc16f7834f9602a3ef0485e667a158e028c5aac567126b197c4cffa961373fafc2944ab48c8fab98748b1c03bc078a44728129ff523719d7ac954c20c01f236efd19fb10ab0e2c79189f32240457b00096e18f7a17ce8a40419c0c9acc79cf021955f167c52ae0b5c49b653b4ae71ef3535901121402ee0b4fce0fc8ca73b1bb7c5b56762e87185b417b7bc0e53219831028aecf61570242ea7ed62d5119f6223dd81eaca5674b316b44ea9e91cac5a1ad4d4a51e973e2fc7dc00fda240674cd3d8da9bfd758ca6217895f074c200fd150286d7e162588e570aa812617a55490f0cbacca5fbbd6afb7892cce455fbe78654b34c2fa8a80bfdea8214385e351be8dcdcb85093b4833ad7a836fd9973bfaae5afce82d230c2d53b4e0929fcb739393a6f5c6ee43a691f120dcaf3976a04d3599952d53a98344081fe5fbca625f5f5f347bced397b1242a3b1b701c056d68d4e150220fb766b959f180df32359065757c5fdcfa58354e46d246dc48550598d513d149f88cb42f869d59370c6216e78f3c790b3715756381066d7af3f7cc3e5dcb808aa999575fae0ec122aac96241998227d07b565e69811c9cae263a1f1c5cfb1b71a78cadea4098455d7ce1c637e2bb876e20043cc4fe6cc802b891548b3c414cf16f3ccea62953a15ccef0552fe486d2f2cf3b0baaac5faa6b7c64c23fb41a59fe3906b87ef6019d2978d344e8853aca69af1059c24414c533fcfea3b0190ae626e46bb94298b9c369be68811a790475a712d02b3b920265ec85a99520661ebf25238828f103dd6dee50c494b1b6e9d6eca28e27e7a65d99d0427877ac8b9f8a5a005fe4d25d354448876f31d346375847cf2becf06498f15d07e686b7cec45ffc59b1e59837322bb23a1c623588e9c8ef819f408fb227972c3f98e4a18dc20511e9558c92d0591c118c1dcd846b838b6f28275cab004cf27eb419b52ddc25acfe26979dc167b7fddb2a659f5c66b51a7951ffdb17b8d77aa39e77a81d505cf53a2d11bfa928a6c4f9015c014a8f5c1d2eb123dec322e76f1cbaee3ec227bb42b40ed626fbbb475bbdea02f6c79335af09cd32b3ca318fba8acab168d2f1738f2f965fe68a1309b1e93fbe3348224b6a0bbc1ca6ca75c669386e1e0ae4b374bcd569d134c269847eeaffc355b641322cf333a6b3648bc39171b31c134dbddb4ef6469e49b31643a38b344f86fd37c90039df5576a6d1fd5e6a0c3b425f9311f4c6409195417d9eafdc8ae8a67405a887d5ce651bb8bc473b72337484c27bcc2e81a88d4207dd24c5eb0bd61e52fa437f214b23aa19bfa742389c5c03ff0d26c767b0a8f4563d589e298ddec5473492c79bd8c9d7e48a104dcd22b9026394ebfa20cfa0347897c30af67d2d60a45427ca4d55c98c92464a7fbc0bc4e4d33f83e4180a494a04ace19559549b398d02e8990293a644424d6c97c7ef6b12ab56138a4dc15ae618bb35da4a7383456d9f8329d12514f0e113cb44cfcea348c3dc8574dc7b248b31c87298885a850bd292dacfad67df25dbbf1290b3d02900ad5149c8225699a4083e972c60552088c0af0b569a3b82303023d6492570b8f49843b2edfbcbb55823875725d5bcf4ffa93ce225712f8801622d1976044cd27fd09375609f5fadfe4c409b37962af0d0750272858fbd430fbd7f6c47e8ddca6a8dc8c12b365d997896555f681747da62f3cd954c16ebc92bc5984c3f583597a313d4186171c6062ee7a24950da5de2cb2e788dda794f28bd978c93172a9086972ca6919f67bf37cdab7c7901f19e08736cc227c0b9a3c2113d8ec084884241d3b319b0c91aed67c7dd9a0404f48d5b50003ee882d1b2be381ea96a57860417d1fd7c8158d43ff5378d2826a4f4719433bd46b742ed7d9c30cf2649657a9e07865a668100380e19fe795ae6e05e20db67d658ec404d8efb3314e7a85e43355ab21963c0d16e1834e01429a28b8ef07e00e5124764ae4409dd4179f476e27123a501589ce480ffc00312ac68734f9661d03e5479933966bce2dcea73d77e14e2ac519513c630b770800e59eec6631c0fd07015937334254dbff9ef00a282aae2d03599c546d1551409fa6605a19c9a45c70a03b80b7390901e339a79bdfe622eb0e85bdcff4b2f74600dbe84e814dca7c0364bd2c0c82bd0268660239b6300a2253068ed10d376f23617caa26335aa5ea538d1be1f4d3c346517eae52fb4f5544975413d7f91e83a91193aa95267fdc10072dbdfece422fa8c5087f2f78c1fa4b637d2d26270c49fd1a44a09666a7c35051ff63bc4bfec6f60d6caa05df9aa65d8d2a2a4a7e425187751d9c7efbfbdc1d61891ee73b3872a5023ce7014f7f43283354cfc5b76d385e41b035e044c63e2cc9b0ae994d9a48bac691d95a2123c178f4efb5495fe317614e46aa5fa2de0dcc01acd4bca469913d7ff8d6dae4aff9d9b63a8481b5cda085089800e06619a4c775da4126d345ab50f3a115f7719e4103ec40fafea8445f17b9964909b8dd6e2c63b370b2f3d36a0e4430e81ca5508a99fa572adfd5d820f53df0e7078f3aeba494214f695cc36e7bf5b150e5ec193da042046309ad59fbb63d5087197faf29017e8d9b2147c6ba16bfbfcbcf25859258605cb693473fe35175802139c2b4e7501f645daa2346b989e2cff817f11c7ebe846b49b63ff01631dc983d44525dd9f243388029a3efc58d12b9f39a3b090d75e4232462a7187051353c5552e5d76063d39a8c5394178c7ef17c33d7400b0c34b4fd63115a318d8baba2d6fc2e08226f4e361ab16b3e48b11e18a66788621bfd383b38023ad68727b3a42928cd075fed55892ddb8c4b0dd1cc6ad2d90403a44eb338259fc5a152a0eb57872b97d1b2f44c2f39d64525f5223187e448957bdcbba9f5c9c16d7f3cee02707a95e54573bd0b184629335f1025417dc16e9adfea8386f1c20095a347866635b6b47150b41af8060a4d04c216057a00fec5c2e4d53dff94a4b1dab02ae8937783b1e3ce3e5528533b74e298b6dc07d1fa454200ddef5e7e50294a2cb120865e86dff16e7367a4d89543babbc71ae43cc667561cdd1363aed905b13abda7930d619718cba8f0908ab08779a65dae4c32cb5ed127bfd16bf29bdc8170eaea5528d37b383d176959232c329c5f64bb479d61be3816704cdfa97f9553dda0b7dfe6f1af6b3165d5b0b05d158ff406b1d5016a9f433bd6b4548004ee8b4a710eac699d580a1b6f1c2944a0c41bb4b6bc3b0ba9554e8b1f7a40c92771a49a1691d26aba67051bf0b2379d94a0477ecfcfb94398336af9b8fecd3d5247999b48350d6a41183f094ff59f7a3049511285f7bbfcfc08342bf03c7bb4f90b3655ba1bbc196ac355af1f71ea84972e988d1e884b9b3f5fcc47274e02259ef34861c9eace6cef57aab32f8fec68145abe4326136d272187bb8842f66c929bb5b6ef78a026247239adfcac8091cd60fb28d799343b56927c26a1bd2634919dac5b4364ffa421614c29d52a104012407ee5e883307c12123fcadc6f59853ff80ba68ca5ab8ed49d139b5d29e59c17629c22142c4728587cccdcd6279a2020977b1096794861d3fa3f3c204493a07a6b776378cd7f369e5e6446512be9cae7224cfe0e7c930d09693873edab5f9d2487afd25e9ff85cb068faabcb797be67f7df30969b1c16dcd5440c97984f72c26536ec099ece4361e8c4e89efb2bfac73308238add8c049a1b23810a2b0e00597f72a6b2b325bc280c7953799f179418a498bb95785f7f0961d51e082da618a072d86ebbe55e80ec31c7c1ed23375bcbe5fa298d3a9d9e18f6d95b151fa046c90df76453b8e287f908c4892b8837275102377f74ab56d16705b0bb450745115b739eac193d7fd2a2c0a042c54d02836501733c8662c1408660aa83bc3f4e2799044110a931db2c478b772516eb5126d17946f78cc74b03cd0252ba1dfc3ffc7f03aabb05a73c52059bcefa01dd77ab4d2f85ece22cca8be675b3ffe736cec4ca0e9d9e47b2cbea3e1b2878544ce8aa0fccfb131547bc98f874947c189f4615fb38c13ff66942f0cb1e94b684c4637ddeff7b2b11c7a2b756caae7ff9e4b347a089018c5620edbfacfcf6e00100b086a630b74edfdb07fd9317a0ae835e8740295520de2cabdcfe79126d13b14de6ed41fd5867c44f2234629e45ae4f14174f10d4205967c529f0b9cfd89482e33374e36b8b281e4bd76dc6720d9835c138516af682bb001f3060f5eed70d4ecf3dace026d437eaf71b2a2930308a3c9eb85c2a5d4e4634cbe4b10462dfe10fc0be7fa91c1126b9c21c60924a50445c6af50d50b285ddb1bcb9e631c9440c98f8a4d826d2890af93466234ced822546fa57d8c5a08af9a9058069fdab474b2040b3f32ffce6ba83234e2a727141b3fefb938baad8875b4d7085474495681eb7b00ecc2dc8d754904158933ca4fbda69375d89518e01867b32ac16d93aaa973df754afbe9e447e87d253423d626091e5cf1bb7168dfa5a07cc070165a03ce52c97c6bc3128747b24f326bea753eecb55a0f0a45062d10022e5246847d6a86c952049424aabf170b8cedc093395e07eed93671de2740e68b372ac35a63c95877290f7b8922db9ddc5204be9291d0be75ed35e6f961bec1987dfb902c5a5b91e1f1ff8d9c39394288d30990cd0c448f59e8b1c0e54959048f263541473c64ac2860be3ec04895d7c21418b9176c77d61d8cca2badf3dd62bdff66a59e06265eec45ef92b2af94ae71b4f1351c0d908bf626bb96d57f9c2a0c9d1e34ecf26aa344f163c8951db4113fa2339f5c0222677e7a8b98ae9998cacf922157144235544d7a445cec180b3ac156f356a7b65825141ebc799a5699c03d9206e83ca7560163f88807b336bfcd3c0048f7396c35b6f448cd7c730c735b595b49cf7981fe58a0121a62ea277a3e6ed70363586bf89605b155689582ddfd8e2dab05e742b3524411220410a2d620a3c378fd853c9a24258ea2ffee3bc7149e8683f779e3767751a91e514f9e60173ea2290a1bf855f50ab9a860e324f1f99a930790a114cecc0d058a84b79039e1d94c7da0e375f26ba03c4e2dd0212844413dd037d168fae7c3b2c1d2dbade33f889f47d1bd64be25a199173261f3a5ad1772168ddb16d9b7c400f49bf916822d6014093db6ce9c451b07d33a2d246bc248d1bfc25577706916b607703e5783d28cf51a8f36c8230a3a8b5248091aa40113543909b6042a1dd9a29ad1e5c223aee4380bc26959de1c974ced229da1fea6ea318f5847d33b9b79c87a0e89f503448125a518580df6a101e01e9d10f0e055f1119da1f1d3362957aa56b8a652311ad191085aec3e03ade7e2c7e8d54798280c061271206a3d5e5bc3bc05da8f912bce7e3fe0486c4962cbc11a9465918fce6c4615af8174513ec22df96fda54106d38ae7dc8c7f8003ca6c3d97573608835f1b3070c82b235cb202f533569368880ca6b436d829b81722801779edeb622c101f0ddd48df58b3a5abe685b1096e417c8b5a835068c4ef417b29ab122a069e76b110cdfebe0150b10be3e11ae6c9c83e4446a01e605fccd34e8a0070710b5fff3c6edb8a02df18f0fcb895fb118ef021b8a8cc29865df9e5dc77d397d6df3e0a1c39aa833aece9ec0f64b7d06672a946f6900554bce4f5033a62902c490b6b326700830ad04256e11515fad7f3045be7b9634278857b8c6894b3def989e6e192d8b779665d23ece511f0f6c08ba9b18676615d3ccdf522e42108bf60a6f5a40f6dd5df63b4608d7ec5f7b40e64eac6d80de60dc6bcf0d338b07fe88845fa7597c653717aba0379f9bf8edec9c7a0b120ce562b57a4ae8fc88481f22d1b4455d30bdf8328dd7bab2cb6dd6a53968ba3d4ecbd76fe41a33de94c5a880d7a71ab93b8694090494d7056298cfdf6e1b0cf73b650d7fc4effcd01b52944360f547612842bb907aba6e5eb09328fc6c9fabd033ba518fb18f1e1340e04e3d1f8305183d345f44b52aab0534ce85ec1d37401c827509892e1c08e87c219c73c750644afc00f19291211a41f6d1ff00aa869b872f90427311844ed23c533ceaa4509de78ef0d2ac952fba9a73941430c2ebc3f737df713236ca892696450deafbb26badba9490ae7c5d78910f11ce0c1f3c26f85a6c6fa9ecfc9cd86e2633b74044e2d664415dfeb11d82a9478a47446ef050d527ee64b4db60ac4ddeae918b6e15c814398b2f656750f6beb417ea04610af63c8229862f9fe542ea9fd5aa5b8d73f55766e71a1dfadcd3c3a910ea71f1bed12c96f25148b695fb27af31d86f57c8c63b9d67ad25c06a7738bc637e829e31da1c41885b1653502b66bedcaca0394b3f43d0c275a908a72591b698b5f1d62300a0de3879f2e766b03aef792fe9a0d20e56e98121e9e1033283ca3dc07630093d6f44e8fdea382b353763314d489a51c51edede03ada9a04ab6bbeba349c96e3ea07594c636c61c82d68be3020259b87449a71a34c8d2628682a69948b20d21005b89e0670b4cf04ea0c22be2628f8a28591c3b0b54a51481906951c8e907511aa7baccb66dd580664c2aeb7de9bb3fa90f9db32ea6e769afad32508ef54904197148cedaef4072edcc993a640ca090e88fbdb6a8a2d7cbd3b383ded1210b4a06b952156cad85540fc1a68ecb557e25044fc70f0de5ef41495dbfaf06ab5528bfec6613beb3aa4f099585e2acb2a279a2fd1c7fd37a42f6476319af0b78d1d0d3e03fd76d69b23ddee4356197af7884a21ebdd5f791e33715bf6d5d00ba0c83846b45c7dc22a2ae4c4b7dc4f8bb661a5b567d78a59a748ba30fc6f7bfc180bde1e4fe3a4e4bb4a0219a756fa78e651ec0036a6eabd5569eba93778723efcca652393cb997fc0f85f85d0d99a74c4ff182d685d81346a56ba7d86c6d9d34fb5a9677aec6bdbea1e5398ef5a08f55cbbe48bca76ced3139d998ad48decbe49dc0489aa7702138ca619e9acc3926a0f693f673ac45398d433ff884b6b0e9d2539f339fa59361c7623836a274be1a479dfdd704278da10384ff1f981cd172f63b9674a49635a548414382b2d0cf414d3a186648396b5951dfb4896407161743e0f8040d359457db4aadf5161b18530b283a73eab873d52248390fc6eab5ca42bdc47ec7b251c48ea146f5059dad73fd4e1a43af64f634f92df85032f218f319b46d2da7c96efbad476928d420b6c26b5a972d12424e082af9047b9498a11950c873af1f430c2bed9a26108e882d2dbc9e0ceb3e9e2263575a54508f90e8e51603546c2071eaf2c09895d11d0e2b01465976d5e5cc16eb0be4b286fb313c003712ec69776d93dbfea1b44f46a8bd26d4c1477f163564fc82a3460c6d411ad16571b02a979589746c04d6922d38718ecd9f1c95fb077b502f095d3e6e27eb63e77a58e33f427e9fd3175490e981918d851d724a979e6ccaf9d3fc77e1986747b5cb1f1f5bc7d2ea9ca60095ec006fbe19cdee029ab47d958588d0d36d4d4159123c3b5b195d439bb9bc89445e02503cbcee3045e37462f8e610cc833da61869c528588be08e2c55352e1292aec64f974509e567fa1dabfdab2757e4c62d6acf4a374c777dcfaeb3db15126c6557d97a81a5c7850a91925b2549ffeff42fd3eb6f2325828e740a27f1a62c688804d00cbaee7e73517f244f255e3eee3bac0fd6c4c20a0e4090963c7439e896e606cff0ae92407236598b18ac4c15e654d26157c89d4b07ae7bd7b494b2a3c31be29a000b56329a69b5d3804d1a30c3aad1de9ab6a3f782b62d43b1b9437f381e19f36d5f3c68de51d921e4d71f5f3f10106b5174d764b3d58ea831c62823ce021789b7126cc6dbe83c67e401bc8adc93465c04c56e6b1ff6a39f69c0bf4c32c8cc6c4738085b91b0b03d48bb4c22fed446cf0173062f995cfb317b4b463c444eb37e30873f13c5fab98e1551bd8641128f135c486d5921d7ab9591520389560bd90bf84bc32d4a6b3a09e141d3360294d2f8c6295c693bdf7c78f82ed89ceb778c074d70487a967ebe556a40a167fb2bcf3e9c9da2cc9cf814c0f744e0b7b3e81239762320d82a001b44c54e588f379e0044c1428e012bc8b15898c0b19a20d8d2ca775b12acd9cf2ae2afa39ff3b77778300cc76e5c554192eb5d87bdb409c46d3928e5f254d4a26ef6f95a6615481390abb24d002d6c4a16e71416015414413674f2a006ae54630a683b2f3c8d4d6e5e8a754df33a2950d391718f5247deead8d061a2a39024401445ec80167904ac06ba3260e11f21710d5e053bd4bbc66b49ab52fcdf1966dfc2f499f4ff5dff470fd861f5ab6848008272ad4c2468444897c86da323885cbb408142fa6d2520168137e204ed0784354ebac76c05831f58d840778295389a91fd80d0d11c5f5c90c62fd1e6f3c1d3d63ae260efbc4f88125a0c55013ec0aaf6f0f106585eb6860fcd7f576e83ea0f8d250860d338e0a374ebaa59f9d1a63b5f71d45d58ca7d134084dd4b2c97284b1bd8e030f177a3e398f3330a1b8494093906896a369bda2c5f74a6e9ba6857fba8d49a832fea66e3e57e7a329d1ef0dd9b6652431e4c86035f545eb1c98e2111033711c892e4c20011d45151d1be2f4628205d5eff325fc410f2fa8deac42a5d0714c6256cbc056aa410e0f71cb82c402d2196148049d2a16ffc2f1172c22782168397417fbeaef7a75e58c13460611b77308097b5dd77a111be9b0b1c8d0bea825608cec9448da5b55762f846ce5d263fca486119ebedbf75f90900a61559adb90ccc35d4fd6577458461697b1b27cf875b77d87a5456d6d81a843fe07fde8b629740cbb5ba505c36138d13d0dde063f44ed08086d766d4ac7816bc08f8442f201488b3a55744af53b94b659f9801b0f8c63523354d99ab219b324ff05361e1914c34af43462ad2e3525fe3e1736e4f26c2f0616bdb84eee49e1b244e540da5527716db9b346aef00f203d8d57d2ab85efdd0770c72787dd03a2199473c031d2f5c1b21b4ff91d36ed80835d46256e767d21fc36e905ed5d40e32cfacee03dab88ab4030082f37b38b69eb31ba1d44864d35448256bc72e92d0bedac1bc20c25fad01ec058963b914299a76029a45a1b1d5aa0064880841d981499bd9c032d709c35774288a5da4200a8a29db5c32971fba28c486b2d05068c760728259fa9741b6b110434185e689fb2dd94cf01c69a691d90e74239469c71db2f1a7844b336154fe00863ad5d9656f721613958fce88ebfa1ea4a8926799ab35449a2862b3dc4b812670f99e3a1369714f6972958a9f0e1529e021f61c3982e9c4e6e24d2389fd662138b10a0364e58ea30456bc76dcb397b43ff1368274200c69918641b302df36f2a03083fa8a4dcc1ca17cf5febfca8a80da7a0c69635a1c604fcaebdf50ab7be333a782b9c6a69b847c435c6fd8aa81a53f7a6aa037029cba1835033d349d5055bdbbe33e46967da93e4076007172b6f03e31e3d110a9483f88fc136ca5f44f070689b2f04806f026675303a4ad17599a023cffd16377b740c8d2ab8a82dcb444f301cbbbaee8013ac8a98c1e04dfc91891311934dd816535861c1ed26a98113cf84d01c6291d431a681f01560e2d76acd6964d9d9349d85b98abfb996660ac5358a9a1f6be9cc5d928d77e7d5cbaad3792a1bfeebe5f232b3343ad6d9c3600a0d76d9b7769fecea0e652f8c183881dfe448e0addd9fde9d549a13b6bdcd86c93cf3501f1a3d57d7c94974c859cfd197a9772ba5f49e3a8f608b6df0c5f5d9e3b2191a9530150f7a10f124ab8a2c360eefc78bf2cec6ccd238dde2f25b367ff41070380efe4bbb58cff29f70e2b3c0df803b1c76f852ec0405261d9977712e33d8934ee4e1855a3bfe9862c6457bcf025d22b641fafa9fab550122f878c2c103c261c13b298d26ae2eed621ee5a437c8c232148793ad07702f4dc08cd2b2ea525a4158c428e0a9f3df8b3f1ef0a8cad1bf0a3219186f997ef8b42794c2234513a03ecf9efb6281fe26d6adf1868d54996d495cb8577854fd7c63c38d34ad9ff3fcaf505f76743dd43023266a76b360604e486e4de7a0c5440e85024c143d8413a65e393a602a4dac8e68f9bb0ec0964fe1079b9424e1f076ceb97c667d4aea8b9f8b05c361b10bfec021515b4150157884061bc69d7d28f99d5c2406c3aca8241b2a37f7da967a7404352227313152c919258239e13bf3d6229b6e21830d82d4a3c1c012c4ca46ff15da98e1beb3a46bf155ad7dc6412c706a95019fb2fe245ecd7bf0241f10129f929b0817142da258f6e101aa35004792f04d13af55aa2f221c04ebea881df720a271d1aea752ab2d61041b61d767fc179cc650c9024d7ffb25d6a541744a7ca9b06fcefbe384a7d137d6178877b90951c616e627376afd3cf27876d61cd020aa68ff765222a6e0c1b97ec084b8bd0b54ebba66d81910d6646d5d4241a02e00d69d20c302f6b0d7889872b2c383da71f623f98a5f849844f96a1edb16b4a4951be6815a98e71488c185241493734d404a27cc22d0caaa8394e824e6b8e33945c959ff03d3951fefd347eec5174f046ce1fedecbed2293f288967e226f82742c2d65c3a1c781792ea9294cf2098b90dbcb6ecb9e72321809b26e5d1738c6cfc9917a1381bc19e25502304a6734be3b15d2f804669c0b3da5e822d3d243194f416f930436cd177404a6618b28de71a0f0845f3799ab3771a0ac1d0e059f7b499a846fbeb7a344c52706f10610885f5dac67984bba29182103daea6500155658569b462c415f2b5375aeef7ecb81c0741b6c0d7495e669ccc90cfb966274ee96ec3f4e1ac7fa082868f23cdd5cba09636d02cbe932d921fc48f37d2d042ae5f31620d94f8bb35bfd5aab0e4ffdd2d5f97f696fab38c23ec2acdc2f52dd8a8572e123c7b54059090ef2456eec4cd70f07002a4c35d4e5e7e8b2d10e37c0db4994dc40ecdda2782c3e3ccc44a7fb122a1d288770519a7eedac434464c34bd2b7da03f627101e37be01d529896de121e58d01b38114285bd3fb992c991e3240b9c0fd2c7c3622a14b13be4a83dfc8c6bdc7fe2345b441dce586aea867979691c2c87395144b96dde12035c582d93c4bf015800789602809a58e4c86e4be64adf8d28bf936a34af8e37a0c8d8a0a0ed6ad1b3ad5db9dd9ba562d9297258a2005b4848e883db955ae21e15431218337c2c2d2cb3c9e82c050aea844e303444cb5167e41faf3c0866e4bcea31cc56165bc9528aa3dde69a94436521bb9089955130a66a13da5610b48bc8970a4df578f695f1376ef275b0bb64858a05eeac6cee170d1a2a4162c87874c06bf0b81048941004de5f77164491cded9ea2d20e188f37d6cc506c0436fd4536ce339f003bb484f14c069fa4b70c01e7b03acd3f3ebb9e1663e1b6728fbb90c9af4543e606d365c61028f37f28a3c9b58dce068d2aa255c802a70298f005781dfb985179390f638c985761261da05b4787c62ea07ae8b230518870d874692b9a8f2af0b62e890172e66290cca34466d13052c6e108540aef9e60a6e359a519768841011919cf1d2ee755748622f24968c127131bc7edbe4cd64bc503f8d3ab22582d1c778bdd5358332918c0203625d6d5098b95f69305499b20037e143f0ddb3579619de739868cb4fb14ed880a880895f553b7ec34d3078986fa16b1edfced45a7c2d7c7a282432800591df9976b750a4b7924084f82f22bb9b3fd6a240e81fd20e4d64bc37cd0e5a4921db076154bea0c105c68a5243b4947da3c530bab1c7d2d6a9cf49f1c6dd41e9e9a8fee5e11e6329e5c817240151f5318da4bb7912a5ac3f29723c63e2c6c5a6c02293c4e680779636527c081d3ec5644b6727ce4003a423837d32913bd050d0409c0e5e8cd2bc5a1311f0a3d4cef4896728c9349897afafd1264659077271928b913538fe80ad3514c13f922753ef0acbb573653403809bae13adfe18576fd593877e42c5d53bc321179c216253105ee9008a82c39339a8d4dc16da7ebfa77fc81e1c137d08b4a68433944b30ed3073eadaf2c7cf644fb76804b723829aaa5349b2217fcd9f4d1e962922cb20dd21d786d3f52dca682c9462c482e27d4d288611eec05545dc61390321cc44c2bacc24c5226585526d1a478a95043c29698bf44baf7dd9200c2c60330bbdeaf016ce37a72fb0ca78dd6d48ab3edb426c276dc4bedd9555edf69262b686acb33ac1eb09270bbbcf28d2a00eca8c7d62a3153790537ce5cf5d33a16ef6fca54e47930dc21a69e86d0132af4591f3eccb3e704b5f45fe7c9468bf370847ef58f3087e6efc72fc2b65a31e04be5326e623ab7ca9b6ac375a18b9262605d99c1720b81b6694150cb8bac586ef7b26bc4a9c0ba0ad3dd3e1c5541f70a4ce8f9939dc8702042b8edb808fc0c4fa3a8152ecd83a4e571b068d2c7a2eb61def0f449d69596788866eba3d02b568d5400a1c98cdb9049e37d418c1b3b90313a9c3a115445982c785a1cb2ff93cf7de5d4d205621ab1516a019190be846932ba26704226c725135859247f773a2d4c73766b668ef20dbd614b8ec20a650dbd920bf398a2845e99a00cfa280ce12b6d8c302fe24c8c2ecd2404abed1c988ec29f9f70daaa14900a3ad7843a0098f2eb3948f71adac7fa9cf3bbf0a41700c3c3d817292b586d1f355ad66343d486d8765d2bf4acec02ec3dc1ed667b442f5ae78f9a8166ac9fd118c59a09abcf03007e3fb65ac33f87fe00cadfb8343441d48916b02d0c1e143e76004785043545d38b3f4622907aa0da0150b9cc874b358a3e131dc50024f8a78e9227bf583377e5170e9973f22e7fbcc8b41dd7737a5a2e08d2debeb5237d0ddea10584a66bb796ba509fe24d28430950f7a767ee78425504513e05ca344e2830a238ce6960d4c48664ea1c571840e75d084a66e5d1cb90303d0e99b46e01621e945805e0e9d6487ab97dd201fd478ba83d57052440fb14fdc5d893595ceb0d6a4900347e0a4cb0ae0279d3a8bdcd25bbfcdc1d546dd197fca41d1239d8c0b2411061f53887a7424392c0c00018f1c74b140f1e3658d297bbdd65fd35fb4a3f68abd19487162fc41dc2df5d50e0a564416f14baa10df3a0cfeca54c8bb75a740cd5594a63afab8c49351486d7ae57316927ac209791b08761e91f70b93e69faf8e4425dc33ab8092dff6a06d61e084dee51b59758d9235f12be5fdd66f183d3d164a6ab60f6ea5bb991eca7f650abe2eb2a7167e4b2bd1fc071568676ff9cd2d72348abe223d13e6ad851a61db7411030808230c807a18dd2e4d280dfc64a8d74c0d7440df0429773be06b4012668727afdb747171296de2ca8acf5295a1087e96d0d0cf9c6d20631d6ba17544a99b827cde06c4c0b99894e573e15320d5d5eba9cbbbd893a525f5d7c4475bb8b82ec8c09822dd9296dbe17d06f48094141b55073628d322a6cf548dfdb06921d624e4087dc1e367723b96a9d5e8ea87666424c8e7cbff352c107f4ef2cac62ff5c986f0562ea028a4def00aff5a8b7ec4a3756bbc2ecde4af5779be98b7bd4bb25bb9ae8cf413ed77bb4801d05ff92850380ebb193725b7d4c9517cd8e4176bb9ed7367f2b52389fef4020982347651536f36c43964dddbf4c2367c59fbf890c1d86349d9f1dae176ae7d9865f8017c39d30e22073c40b3bd4898f95c7a4d2ac87107a23cb0f0cfea879972569b9d0e381132cef66c4af14f59a67e9b440855bbd770e06561e5dcc0d5cf4e33557530de88d3acd009e38972549841a531389a181e9f1fb46d73bd3e9d77e5c4300994cfbc70187bc03be9dd626a6176ddfe5e2222226f2ad191bfdb2a923cd2966685e22cdc5292e47b7a0d098b23271518e0a8f89c3b782b007dfc1c3d59de02e376758297ec4c163c0bd222e03573bf807b65cf37307d9cf7a65debc0ec2365ca7ea371ff94363e03a588c0c14fbfe0ae8932d10f99c0f601f5b57b632e59c25f742750575d748ceb25a3f21e4d4cbbc13b277df543329f541e706c36cc44e2105dea6f9a225f87a098ead8e8320cf3bc65ad220d80e1cbb0d8f416ca2d0f7f702c1774117149fc2a92bd6b8a80f81c0058ce16fe0c2c78289e90dbe53b35e8b2f7435419ff3089abc65593aa6601cb5a01a04689bdb6b890d12239bc7dbc3c9bbe2b2499c6251b2367e756e548664c13d372db4b98a5584d30168ef6fdf363e19585e043fb780e85bb6d6fa9375409bc5884b5e097a84a8145b38fbbb096a0e96aef3ecda34f011c660d5313d492ba2b1fc8c6c1c7a1077aab15d749e99d318c97f386c933842c530bc395749220498220560845bc3d833a6206a21aa7816075290f2098c94262b8b072c13e0743a235b9e6e00e2d435d4e01a395962e8a8c534173660004434a78089a7643d5533ac9cf3a4e6ac22ea5264ba348843f888b7546594939418311e71f070fd7c3725902392574fb5d31cf7892c6f700a14f28384382e307833b0bf6dc64b7d748be4ea365f97abd5cd39197527ee29b232c20d2c0d25e82feebb95b685bde0cb138c01260fbdce09941a63b0d9d982996ace76a12662bde2bc965e34866830f5a4d7b636dbc8ffa50b5194123d9ae40ac2fe2d3b7918069f23cf07dde4cec4243c3992f08c86ee2b35eef2b5559f12b4d5ec95fa394778bea7ea54df16832763e78f8c7d81ffdd9780612eea0fd23b02c7e7c4fa16eea15d10a98c113589ec84d40116ccac14c055b44b259d7ee46f9a32741c92427c825a3dff8a4dc30e2432fbb32b6a8b9b01b1e8725fefe20e229b375788d7a14ccdcbb505b2eb3b24804e78ff7dad2aaf67c7efcaefcfdf75cf101b3bdd203837a2bd0db2c19ed3ed0fa0896198c21005021a176d40922e4f3359564dab9d9b6b457c8c7ec0dbfd2dd9968940006700cdce109fbe004dab39043988fde3cc2692c3d0e23a3421a4dc885ab0729235adc9f18c1c9426af70f1243ee0721c9e625682061eb2f63e98ff658941097b6cd171ae6d01ba420c07ae0f1ac0c3cba788dce7c1674fe6a46562c17bdcc50ba11642ea9e16f21b748b85faf9a332c76c823f19e7a4b11ad53dda3c3960f7cd3222fa28a97560882a6be65dc4b577fe813f98761e91a542951601c7cb79bdd6ee9285aeb744134286741f17ca52fe270832ec2804f1873ec91086a3abe1906ae0336594350e610a95b36980781205395accc282852a896848353f3b1a4d2354f9732c023b5103a44c202e9205c8548a88abbd6c89484ade915c82fb0a3b05e4195255e1ba5d654094ef31706567a9736263270d754b5569650340c1ab10e3d894f81ce083222a7d19024d9fa2431942af65923f5b3a61cd68d364a303d7a659ab807df3920fab8742ac9224ee825b832be0aea177c6b080323b8f96206f2c2ade520ecff1d2a5bcf25e2a4ca00ee1dcc6e707770de2ba437a105ce01e19d81f476e0d5084966665f6063e7d18f426dec8a908e066b8437d833e8feccc18f9afbb945bb58eee3e2be515f07ae9dc4c7816d4de6a5dc372ebe6f003db09248d9c6bbda5e9d208c8bef7c1521ef7f67bf3464e44cfa72c6d8ce2e9a4cb091fdfddad741ba6ea735fde9fa9a2eb40d11b2ceb61d537953e28b7ee42f5b691c9486d139b2e361bb8a20d4da1029320c2c7b735622e197527f9f8a2df1f319f4a6f461168b00e3af5f3d5c258e89d47941495da0dc66d6e4ef0399fe1df544909ec3b597e01458879353557bdef923cbead4891cc3ad7f4a416536cc89909374cf8dca298a665c229397742d6915c6fb6c8660d11bdfae16d65a23616aab1f3c27ea74813a23724b0b5893fdf72aebebf67e2ba7d4b2e0b3f3ccf4639a76451153606fb0b2e83c4d2b1a4f42c60706b31aa0884c013019cc13b4a405cec6b68668f2800ab27a82031c716089a43eacd18f1e3902a2b5aa6f29cbd93eec43c1a432b2796fcdd0072e42052b4d2b61b2eee4763a44dfd433b01011854f94476b1dcca10d38ba54ec14adc77bb155796a9e0fb936cda0cd1e9cc58fb7f9ad859260036b1298f6990e6ad36b31f2d7890f1e40ae8173dd1513bd1e92cf897866cdc9ef61190acc7c2694e6255617520dbea15312569b8dc12deb9d881c8b18d6222fa11dcc49fb67a68cc62f2918bb2e572ed4058eff18338c8f433d6bd506c8e6834f8c2209a5116c462ddd91c86618a6d349ef65abe0e692b64dc3498c0e57b220d065f6194217f7b701ff7e3d06f394e89597a2e1ae9cef5cb9dcc7a4ce1e5aacd940dcbcb2f20f63ac238f8e0638b48efcb1b00472164bc86819cfe3f313967a180dfd1fa21209471b9d3156f50ac6f3179d37f02751f851964745690ce5c19a4031a3c9206d7331ea4dcb5c6d3e14444be5d128f8ef5e2a47652512dfbf6b84b427eb3b507f1fd637c8a67cc91cc8601cd636d2b5d274e1d312d20795551886d782d07a831ba30e6de44873c9586e2af45d09144d987beaf8c1f1672d9667767da1d4f5a4d2d006044dcacad0d9301824aa6922053bd68691c9de52aade5429ea2b7386a8512d04966488c2596adf2ce262e3ffba800a520d54cd0202bb75cec50a9b4e09c7ff6cc76cfbd4ffd60056ad0a6877ed3f02cc4d35a27c4fa4a664020ee35f02b855fa5fb2b9dadf018ee3cd8744a8748b9af849cf9efc43ab80f105b573a7db607b3b5c8ebaee02d9ac78c16fdc2603365007c6988cc0cb54e826dc09b0ce4767d972162c71eba288bca6305d9c1622c9d30f7d4dcbbdb6c14771fb088ff0f8deb263f683b46c95b113791594517f960346e7707184615246a19d091b33e4a2a4190a21211c222b1fd4bf29c9230766857ed6c9f2ad933d9d68ac3863b5cb6f9a2e8a670c8b7dd7a41c420ec67947d292b4a5bf83619214d1d3da2b5d0c1afcb93f4b634aa42697b76c9f212547fc9cbaacc80dd4f427ef5237c8136ca77cb239e0e0551ae5394fcf916468b51119a4faeb4fcba777b6a06a08c4dd9890885c6336547b290099098d77ee6e687cb11c7e9c6cf27af73cf841d9cf6aced5c09375a06885de401ddc7e26dd9d84b0137de29a780a5f6860c0b4a6eb0e8cbf6a8f63e39afa721cd79128f56d13181a6f9b1d745f1740b5c1a0cd0185cc3945ca67548be7054881cf11e09ac2c1613c63c7ddf74077ac1a9e2f33b5550590376f11a412dd2abb573a8f685f3481db3226652a2e6357e775a0e1c3729552a120cbb509d23e37dff70d219006890dc96f888dc99ab86ca6e9388b312d3d1da998443ee890e3b76449a974a8796634fdf0effa751ffa5d5286a739e58b70c93e0ff70158e30165096043a7dfc91a492b090e1eedef333b3c8445c433c7126e11da1087d8e647d6f86f27382b97bd2c6e720fa738a83203e9f55f366fcf16a66488bf1ffc28ad0a2f6fae6d99133dedf84df23021494d61d98baead2ce6f7272d84775b4a57f060feb0f9e22f9046c843f81396a7f26af4ba366f006b16016704e58bd14816b877fd01d2432c5b69b20d0680560a65902c690b9bbbb1135c5280d5ac338b42943fc90639311d1ce1de215098b235e672cc3c9fc061f1d83bb1bb47d14a54765850dd65d4b55133fe44815f413435c9ba4df82c74deebf33a14347a4f75557bab78622e5b4f7db44cd0ebd74088cbcf7a3a7e5809f61acf57ef1c3db6ba821f71916bec182a14f4984d8679eeb332e0c8947e94f87b53e1b0aad24cd22fb44d1c7705d87945771c2bb7b83b1e45bf2cf9b1be2afea8cd468b4d77f4eae5a03ea8b77273810c28b7a026143febecf3918274d1747d83041f9870b807affcf2973f6991c6c0ae36fc096a851834401872a7e3886a1aad8cad581dec602906eb0e47fd692c46bd5681179e6a8c8b8ad961d5ba71206237ae0d68e5900f8d1c607c32a16417baf8ce2cdc8f0502e9e12c3c3c6cf5629483a8dcd24cd94f3e01a1a8c84a5c7808f3e661221620cab499102cc85625e4ecadd32724542848d29a8d68717a169169db269c301c84ce4b585e0b6f33db009658664c8819fed14167cf3a7efd01358bd8b9d08c5c9879d5f5cc9c7d3c392a3850ce88790f26a039cfdc05485b37b2978e49092e847bdb24a9ff05b6578962696789f75f8ccc17dda55342b5e2f709db2ec09387f8ab1a7639cc4355e452fcee0066d16853680319dfbddf011c0aabc34934b45bb9f354eba5573bb85dd808511acb8653aec5acc7952ce8f2a2590b88bd147d11d5e32c3a392be544acde48bdbd132018364c89461aad7be6ec9f7ee14bf9ff18ffe1324c4c8454f7de56d3d76d5f088ac2dc14b0410f9a02f5670a5b93327bc6165bc4fc256e08903232541215f90d26994b405b3a2f646d731137c0f3a76def4e4144e784bfe052165a48e067d9a9f59504c3125b679fdb33ad803ba0e230793d24f25aba2348ac407a2f76ff7b46662b0f6a5826531524045fe7fcab449a302f2cc092d40dec112d918387f51cdadf39ceeea1615ba3863896882c489c9106971c5813378922d0bff67ca8d1c1fcf93e78d580789f6de15d66089613236def1e8cd1d477e15f3bf99c16abaeb0f4005d6773a74ee88fe61f2cdb2bc632d44562e96fcd7af498c3f135908ac039bfa2061040c82f0a74191d4c03d0b84e24accb56233562504f83b82d08de658417c96619b1dc9c13c467788db4f8f5bfae0d91e20f90590a1bcca437ae113a06f0b717193d508f8ffa7035adc31149114952a19b6afa7ac690f5cfadd4c91e25aad3370d4ae30c336e11d0216cd8ea103ce23e51fe1f7cd5b4a169c702c5c45693fd2a1ce7bfc2b5d7763b2ee0129f36d3e8c49451bc04f92748022989d3d86ad1fc04174a95fff8ed2dda5fb9e526634c135593bbc0f3ef1707076e6780bc079fe036dcd9bfea3f577d548bc3990c5cb194e9b57071b090e76bd62ef90c61442c08bcedd834000aeab09580afe23c5e53d7780276d5a0c760474af107546538b35a80a9276b6eef71c4140301bc1e883c29b3d3f9fba37603f342ce1e7e4f804d28d51d6c75535019ec175355be0b7f0e2dd1d1aebb7f74522fca17c2c7e200e779413a36a9422b567f8bf9d8d4e2c90ab7a7f3e8f9633a4fcab477d180bdda3f41337bcc6519ec92352a09b9d52a3fbc032ca1d464e76001a2857c5daefa766efbd9e3ebc5e6344c08ce81a8ced0b5746bc9593ba0405adace5ec54ec510ea368c38bf2f673c4655856c2a1c5fd2cc6a61b228e31a92450695cdae85a281cc448585f4e2dbd98ed582e606eb25df9acf57eefeb500037eda579c24608f6f4acf6744e679cf36604f90d0937541d706e262333011c8b0ddf671ba1fe693a649b53a2978a794b4353e7de9840d83a7d13b2cc543cc38a11a50fd75d55d0c119fb7d7790d37a99f333b2e40de6eab10e092c2fa119c1ea4ac5efbaa8bdb17f40569bd877d320a50d014fd0a095e1b940f857b09ea15002d605708ff2d4b7b0609c9352a2eb72bd66ff459c3df08c1135f8b9f604ccc15956c60cc054496441c8e725de84da221af08733753480cfbc08d13c42db674d2314be78e0d1435ffb68044453f1300868d620ab3cc0a494fd735f7e8d4c7fb3cf74e23dd5f8ffe6e47553c6562555f28dea8c6215ce01167f78e73a1c821316e60ab03d79b64b10583713b7b3776435062253c82ea6458cd2cfd2ec5b76b6dc1fc4beb1d699d751febf7abaf7ae17ae8bf7814f741b44b8ac3e8949487bd746dc958087b055b228bc5eecdbad8f76ab3cd70d72f942269d165b131395e41781a90606024c3b65c9db264aa883e4ad64d7474f3c98c7a32f6b0a8db2833391548daaecd31919adcef3d7e433fecaafc6a8c1aba144325fdf1b2dcfa94868c6f3e5c454133f6c009c4b4609c967d6941aef575737d1b0070c0df3050831eab558053c3c856e3c2b054116b62ab8c44049968af5bc47b63994279e4e704736bf1d6d9d9a196192e106f35991c0ba74c0c55ed48d955e07d9165e062f1529cc6d5b48d381441d09f67035560db4353bea60ec641861985af1d2077c2b21efb9b0d6a4d2ae5d886726d44713b99e709b565c9879d911f0f751e2761e402caf9c4d1a96f395a58d9e235a9f03cc8d812e59b6686adc58b81cc787538ce80fd1fa59d6b3204fce5136dc0fa2c39ac4d56493e33e61a9861e33d911125e8c6d146efdcfb0e17b512e873e4feb8ae9a8e40639063d1f00eefcfd5027bc4815b688bf888183ff986cc857ab40e57c2ad9a0178310408b62751509fb921e340bc4f625382affc8ae74258c30a0461990d8a60128905191e867b0599e2176f1791275bafb721e5980a12ccfc27688246601b51089d527fe7f75f0db3a64c8890b048c5ec40cae6ac8589458a6c5e6c34e8a7e9b7e691ac281fae4ca114884ba0202ffa205fe3590e29f4af83ced73068486c363d39e37defcc68f45bf70efb0df33c030b78f9d3306b27b71650178db31216d10eed01828f48b93bfc82f3cb48ddb5056b6c17c8a49f9c83131b3a4752df7b1cc13110d66b19e8d9d0ed9a23b4da5f46c21998b939f5c0d449f04028794e75c79139d3ee10768e44f4ae3bec42090fd0a87e03aaef1d390062626e1535719a856d42a771835b3095488098026a40173a33f93d6081f5f126f9457a1a37530cd96093d0ed921f7c20ef759e5220c8d9d841771fc69ae42fc1d49f2e79cc5f69f53f9b5bef017ef7d56b0cc31a6ff991a08ebc8911b2ac5ef68200f3b63b71138dd8c6ee1d5dde975a9e8002bebf52d4adc7e9852e5803f71de6a952a9f5ba3e813d7ef782c8f246b68cba9d490459ee5ee190f225e01e586e3427d51e9b835091cb968ce45a0c5aed59f5823ba6534294f3aab622a3aef6f6b00ebf0e945625abea830149a911cc836fdec2b1dba1782d256e830565998d4aaa1918a4dc00feee0d5c7e50882b9c56b5995f46cba0c89b860b6a4fa3a164001bc0f131c0d6efb0ecc8d9301c5024a408e11c0065f2a1035cc1ed189b0818ea6b786718573e0ccd973804cae0cb2e5384fbfa382db85faea9f30c7aa6a11e2d6929427f6c1e9e67b18ba92fa5206b8c96e7186cdebabf352999bc18d1bd87c85ba5e8ebbc96e7b074356a997d281dbd9ed67987cadba5682b91ddc7c02cb57abf3f25937c94d2e9864b5fa523eba99dd7e0ac3d6515f05f07030bbfd0c8baf55cfca013783b30877286cbe5a5dad980ba3349bebf3e0a2420f03b382f0389deb8d2b69336b9390d8d45d1e0533308c5b2fe84871cd2dec27e5fae831800a54e0fa1b1989af59f5ec9f330012d8c7942e2e33c4ddb325fb534ec32dc19d18f8b0b6b8455540131361e2778106706841650a82a5e0d4b4f99c17664888d5a1d8b99c3122b8b38417ec1084f0874d339000a1c59bc6817d853d73a146a46012a0ebb64a622aa3750f0e1a1a80f523b0526cae0e69e15d91ca1782df74958a71bd7bf3aa5786a7f56ed8b981d4a6dfd8c7d895f95447ec1660b53044c7556218a8b7a808431e0dcd0adc8b59f21e6dff5814595e05cb9c963d38dce6f0db04a2634d991536a68d15cc3ee64b6577c41f5c95d27cad63bf943ee37f9520dc539cded8d66353ff216b0ff6a1c6fdf8034f5bba855ae43bd264c0cbe4871d834c032dccd050cd19add082056b492242d51835c0da02acfe86f8af3a4c89d041d9b011d957a09261ebc0e8356d7702db3e844d3a576842417001bede3cae6cd49d3b558cc5be3f3da95f7634dfd61038e0331e1d7e46b8c5e220403abb8819eb2b39c378dfefd727e2896996e5de9c6a378cdd7fc695d676b8b5f404164fd754946484cedb21e36e73fa701bb74fa47726840670235602c5be5d3969607593142cc792d17bef419b64f573ff645b3cfb14319d2542af6908b371f958d0cff0661de4f9f7295630cc8344cacea6a229db5560c875cea6cca6e3d3bf94cac1f30239cf0c59b9eebe5a04d230377eb87cf0d1c9e7d699d39a1045935508ca3611fd3712cd2b1cf4447164cd0c07d22c3f26e65868f04506a862f49e1d3c03dcbb83f53411cf1f1ea890f50def4167a0c64b8d6802f740a8616ebd1a6ff9150ff102895065e7afc6e8068592b11019dcf7525a03d44f55ad29c655a61d9288c3ded98d98f032d6484b97e6466914ee9f5bcbfd77ed062a744a5c7930a77c1969c303d51504784fc7d9bc21f5258c7435e5ee906a5d2add33cbef7c0d5a9ff1e8425db34a08e67154ffe4f27cdc2022b25f724a6ee1b8df3fa11e3dccb82d284e1828a717bb9ad9c53e7c134516b81a7fb58f69e2357f3a07175f92b1213ed8a8389f5eda2751e2a317c503b858f4ca1777a843a862c0e3fcf82d456381bdab1601ae8d4330c5da85dab67f3c446ca7b8cd853ee1ea1b63663c78dea1d7a7f99f55e211eb633451c12169c4685a782b0aec087ea52158c036f0f88421b1a03f0636341a41b26dba174554703ef42f885edac08d51b6ed5e60c87a895facbc922110817533f0025ed83eb8d06c6680c4590b852ca2ea89354d7010f00ff51413f35a30cda38bc6eaa107173965727a1500e4c88a0e16ea1388adde6bd70a8348d5b03a0f4e3b406ad7c85ef9a99bb7dc36b06984a5c550762130607b69e27b78b51a10aea73d2bc6da1b07bff659cc10407730446b7a059cde033aab0fc258200eda4a0749824964ba0b049c4a5a44b1909f2333bc848f774dde597243edfed8a79320f582a469ee220d0d1d74a49ce8a4fe9880e497dbe33503d6afec195eea38550ab6ecdcab4d94ea4854354bf6265b6e29a54c5206880cd90bef0b679204e1c1245a1fbaf2fc90230a172b5188f64c171899ca49d1074cf9814b0d4f6cb8e01c7104ee284e62c862ca03e70a0c6b39eef53a727524ebc8d6112e1a6c3428d1b064612cd925fba45a242a7e787139f1bae999a22f9ba541b8c107322cc441b304172b306c32504055191b94f002831c2137dc75d3d679c6df755d87b18e29ab83caeab0b23aaeac8e2cab636bf6560717d1db1d3618b78ea33ce02156b0bbe546b7c07cb6349cac1d443c59c3039b2666846410812d304b4d5c69eab2a447171f5de24451e5244a19191342f094c903c40d0db63056a6bed8f034f990a60549439a20d1d4022d2a406cd55b6badcd51a9a8de726f3f29c795765d145c4d9336a52579468d1163a06c69e9e1c6083060e89d31543fa0d85cf5502750e58a112a3dac9c6842660c4e82c22686a516bab0a8387d3fc8275953e24c8182a50c92315fbc383180288a60a9f2c389ca9c4bf1ebc56449d32413289809549645c151a2e02b79c30e516ea420910316145509424ca1a1a2618c951a68521078d2a829226b8a520d628600d2c6cc1c344d00d18ae28b14cb8369c614c54c1049941942a5881f4af507108c45085492a517a282d8b9f6f5e26a6a9a747a8a32e2ba5d8e48071ea54b04d7540d9381c49344a98917a628994941105d9044c9e189993979640c4a40f9de7bbfebb17befebf5058afd02d5346973ee59ad4e63b90b15bd31279e17d6f05ea92f585e525db8dc4a91642edf7befbd2ec37bc358aed98a01aad2d4610edffba240c828b54d783401d284c895e18ebb61e88d0b4eac0450518ae082c70d1dac149a94a27cc9bab2868734368627ce9ba85c9b1bc40c779cfd6b5f2f26db6552ba4c4b9789e93235f9df3bc3dd8be3e1890d38f86032d5e489681d0d9d3b3c1471553565054c9430f6c57987b921a28ce9a29c49111ee18a3284122a608c102d9c19864013840f5074f0ec911a589da96262eb2a061984904b58f1e21424093a504ac8a96ea97bafeba65e4ab500f5d6caa923550897b7da3d354d46e15bd3b04f354dfe28732944971d1d519c70b821c8d45b28a6bc8522cb8c2e4d7ce9d251e60d113998ebba1f368c7f10e90fe0ecc024082f33a891e1cb6dce129cc40a12048839505b71a044212f00c58a5697114ae059c2cb104fb0e0009e2194b4c83083d21214b8880e5ade1ce126c9941e5d6ca84a7c5ec490e64d191f63947e284d224c4046a06041c7ed081eec4c11ad971e7bd0382111c4152e45e2c08a74016d2962c647aac81658112e748de99202c48b17d12291e187ada81e3ab2eca0a5eed84a7ad244151d6630628ad2122d60a8de8ec048d690198c648121b3651aedb1fa61c5fe0882f61112312801e7a908229a442bf556881be41b2b64ee10c1014b9e293b29a29662549e5e50565eee382167071d98a498116d78c7883c4bdcb8c981ca667da0f2a26efeeabad70b8b53d761f0c3ef16875fcf6aec01373c30d05b17d337bf0419ba747842c6894d8c681dd31aec0628334b58a5412287684359ecabc76acc2b109e0433fefade4f9743c46e73479b3ad9b59f424569f231c6af419a23436cd0414d1b26a275c05b29195e782b15a5c82bc9062d2f50b8100488520c148916cf7a537fee769e5bd780a86b5f0de6d68d42e85a6e9a744b930e033fd00365d3300d87f952394ed66e6179eb990555fbf064cf3bbbe79c73ce39bb29f54abd3e0d852250e7b4d7daea42d866f230be56fa22042d112206186f6b28848c85b4f3829222ce349146089658b96c2951ba6265cc535703def8e8dec400b290c98c28d19b1c5d977be7154708278444984f2fbd3b491ea55527c9728649ef514a9b6a659a73c9b60d5b698b34f2a067330eae960b65744de7636d03a8709119020d569d21a056963560885ced1005430b0c4ccbca478b8a8f953ade287d1cfbdefbb214863c4222a23449679452a732cf7616acd9d697ad20c5948624296d4e244a937e020ae83b5101e7dd4b980c19d366133919f22672610894b6c24cba5db1fcbcbcc501d293d624185ea083e60c95325049d4be6addf0b56a29f9aa42ac2e7e2003e507132b2725628d517068d661ece52d4e93f75edee2d0f0e35017385d2f6f70887c8b97373862be9f648c2c5b54af5eafbeb668d48d248ffdf4d5e914ada960fd466b2a5cb7a2359b87abc9569d46d1275a73a2b5a67aa335294e517df5a6a2b5db39e6bcbbdc6c2b5ab321be6e1ddf300a75dbfd446b72ea8ad6a658bdb9a82817adc925275a5b80104f534f51b436896043f564456d4cd5463b8bd6a47845959aaad25771ecad7a35bbcae0611963b628ddfba991c20c20c73ee37a901f3981b98471cecd1be7dc8c9a4f41e1a4e26a1b2c9c53389c565b5759269430a367d99344af3a2cbcd1349d6a88844314286d6670324da5a51a29d42001c83927e13acc4190ef047b8d19383e7f3990cfc0f1e39e5ff7b2dbecd66b504fa10609422474a28fd740f20933a54dcf8010093e1ee441a10a228e241104264a9b0e047613a54dcfa050fbf524d1a36005a4c8a3731ff7268c849777b0199efbb884cdf866fc84ad4469d37d4221eab0d07b89d2a67b60089436fd052251daf40e14a221120e6594369d0b6717b4a05087484494363d495cc12789f6ed6aef1af2889fd63a6f9fb739d5b5adb36aa5ab6e46515abb578209284ca7699b4f5349c2aa8b25505abfbc3dcbbc1738450e447af92b54a1732e9c617046284402e7d871a882e79c28456f7eaf238a843bc78e6385ce397f852b74ce8138a29030e14c19c2267ace398e15c2153a57618517e75c37d11af6f676a235aea13403acae28ad912615a5753bf56cfab44d254a6ba41b94d6a01009b80b674224705d4844698de494d64d603b515a3bfdf411f7d31502034613fc306a179960e84fa8ded74523e7d89bc69087c10f3bc99ccba7b56bf2f6e109a0800b4d30f4373cc1daf01bea0e2237b0a2a2750d64d714adb5d662af32acd6bacc6f44b67efd86ea9e14df8fac1149794196d58fe845073990b8b95085490e54b1228008d12488205578287a9307ce0ea0fa82a832e00d9aef0d9b14a112476e48e2a94c112a78c42417cc702141226a86214f8834ccd3f6cd8656bcbcb971e2c7a19a8337675ba123433f527783840f0d690c7df558be99d66ef8a2dd8cf92675184ff2f8e2450746dc6cf931cb9b063337597e9cfdac5d89787dabf55a6b12d4125170edb1d2f4430b6d2aaa0e15a9344d8478110657555b2b1d420f1ead1cc27cd10a225600007913e6cb99a52c59625dc0d73756bedaaf6f82f80a136bb5d6d637505f6b97af57acd556c7f57b797323c54d127b65830d36e80da8329009c99a51d326aedc009a863cca8646d9e4d1dd9005768a43234a9b9688178e1eb4531ee5cde82ae0a9160c4fe94deb85a73ea401754c4316d3665f346d624ac371682e11c7872d4fc8c9a106a1383fdc6e9853a505220a186ae9c6c7e797b736796edf274fca183705961dd4dca8947864890e40338318a920608430234a9775d1062f1d89d6e46d060c6a446b52c4a274a9012aa389ef913ce6db0b181d30e5faf2d6c6ce8ff256cb6de6d41bca271913c124e696c4151e27b2ec5519aa396de4984942745fdeda68fd38ab489ca8e3c412efc902647f7cc194b52c53c8da8b1ea5957df1d38310baa8dd9b86f1c5cfe9b219ab9ebbc8c5579711c91ac69c729e74d67064f1d369289df8f9f24b131fd84c79238410714469c4d4115771b22461078ae8e2dbdfa8590ce12599bebcb5c9fa7176c3e3c9210a820ca43bb9dd9b5346cf907a567d0334ba68723e637e09213001051b37ba880b6584483dab23b4073d738271887b280fe5c8e3f7b5ba2763d17dfb5e97b02bc72f562b96366b839767ea19b22e5fd36b10fd0c53f8f9d9306421116693996faf41f41da2a0b6a030645b2fbd8ef11cbb06beb71dcfee0edb27feeee538ffb1ddc6fc4aa1b42902b719a20ee0e5ad8d933647a857a0dcb3a1efa64053e84ac7917b2674c30ffa2fbdb523c9c8f3ed33bae6627b0950df1e821fc4761a6ebebfdd4617c95bd6926fbfd145b62be72c01df4e3483b4f8f6cefaf163077f0483927c39ab1e3ae15c46b9b0021d01b1ea196dcaea512555c6b45e190b28ba662173c2b975a396d11a171a511b52afb5cef9ea7dad1ec81badc96ad5fa7abfd65a431632fa8288c25eded82861bb32598d13a96585e1d336421749a217120559de96c87aa097b725aa9eb2e1e129750f471a433fff45571e898888a64f974179fad45de230775970060e511cb2fcfa17bcbcb199fafaf2c686cb8f43f409f60b620c72dce5eaadb7fb0aebb24142dd9318638c31eeba5707ce7fe1aeebbe9e593b2fec883a073ba28e31e793c338c43db318fbc4d886a38d8a6fd775afce5eec95c31887f3895ee7c07abdd6bef7de6a6f535ab1f74cf67cd130420e557823645cb34f8cbdd6a0da05e15a7307c93ef8cbf5b301323e5fe149a227291015c21c11c5e107fd7846d784b67a7c7513ba26245647e1e9abdb905ae8d4f91af4554b9d255f314789b4d021525dc232f0f98a10c7e72a422119400e73204f014af106819ec77c60164c014af163778a419f25ea594581d2aac3c01b9456dda7fa0f5802a5d53a83d2aaad445f12d73e5c9e1ca23e1dd329faccb3c4b5035be308861d810b559c89698d07e73c7a6071c7dc234699de238b31979f4b99657bf228fd06ada9a0b5cfa94f265a6ba2b5205a4be1403e4ea5497dda421c3db350b6824e7cbcc11a47f3a967d467d853017e60cc558053f4260c09a642b6a0fe812c863078ea2b2603a87b5747ee49a7d38dae11a0c90921a71e8e08da6284699a20b71801f2d451a0351e51d63cf589446b1d8cb983f6b183a731db95db1b7684c403960252ccabab40b6a0cda3878b722e6094513cf5154c06fc3c17be845ee107fd2fec37ba36735cf950bb40a43e97b89efa24928328a59e50f214e8a9549d2deaf3e985bbce250c49851b355601dea08eaf8eec04e61f386de054ea19f5093a51c222cc63a0521661e10d4afbf91b7a32ec5ee752b8ce8520c8b718dc1c99eb0a4831e62748fa8ac423c861eecd648c9f18f879bd21d31f673324a50991f0b90a5711aa100b25a555972228450bc24029a698621010e8790af0c78390606e61483c5848b2d9fcc781602e6135ac80143f17bd0f9c4b94461d06fa803fe0b4511a756f2a3df501a508133d300976847483d2689c3c4346cfa8c593a79784dbe7c99c5758986470450e941636800d4fc21aea4c915227e84624050d564d7a5459d3990bb454d1ca818b962b587ce020db16244e645b66c8d2218a2d34500de980da8590ba687a83b96756b5f0ca66b3e590522d80e1a76bd0b59838a5c874d59cc4e9465c2b8aa454d5d64f1f4146a5cd23ca18fb299bf8a9c5071a7efebc7ad9f939abe797522d50f25216c9af3f23e2c896942d3ee871d2803c3b740c69b2e40c197106a115039494223a94ca6434699220c224cb134ac4e997852c6b2530154162899c35554dc4e932594b011b198650355165a94b9ceeb296d4031163c600f9e2c4081e71fa4cd66ecc60a489234174a8d2244e31cad634f962d4558273adde4e711e655fbb2819e3549543111f5dc41ab35c59be0d3239902f3d6350abf238bffdab2845e9d98766d6dab0c6fcae0ffb640bea144bf65a76cfea33a6e06f5e0d1bf8b1a300bf0c6bd8c8dfd3c5f4fe6a6b57a78e53984ffb935d97525e16de218d92a54b9fb48d2787c669adedaa5cb44e6f6169f5ac6265f5ac621f3babc3e1ad6e611fcc201ff10a1f65d76338e6d855a870ec2b402969f8ba0a3006a600c3ced6d186e55ed5dab09fdd66afdee5ae5bd359bdc67ad35a6b6dedac356b3a8b32c9eca3ccaeb9c2ba5a9375b526cb5e615df59acea24cbda6af7acd0d4aa34ebd5738e60c4326cb524ea6c9446979f40ffcbb6c39cf96e3bc837df072ce6f00b9e792fae7927e55b27fe71c5098c351f6138ef9b34fd875f706c518875426cb5962ce3bdce1ce47d9e3ce311766d9827e6005629a92ce883aabd7ccdb4f071de1494f7af2030253381098c2f6fe524a4cd37b140b0b0beb07ebe7e7e76762e58945e4eb8733666011f9f119583f33666011f9f999f12382d35a68f506782935e6e989e07a00bc940a93e63dfa59ae5a876eb5d69cd145359c583f6ea3af8f3fe10dc789158eedd8a5aca5f0317b75d981526275ddfd6c504f014a4993e1751976e8321c659a0ad26f98fb3867bd7e8727c0c2fae338e4b82e3ce1c7abfbf88489f0139e60dd7ef5f97c2c57dd271c27d6df7aaf848570c366b3e9f038ce1bfbabcf9e738e73093be2fcded88f347efe0d4d107b2e3cc17a97af8f17cc3f41274a2e0639f54c01204fe1d227c43de338b7e018e39c04792940197bdbb90f7841fc13b40ee417f471ee031f0f02794481790f17a37c6e4481401f10f681392663e158585858583e0d74c5eabfc754513f7b2945b5f4322a01eb5c388a601d3601ebdccb31f6ea2725d397571808d8bdf004ee7bebd8bebce6d45fe027e585c127e5050502f613da9d862f8e0bdd56f0d682221f315b4ff4524accedb5bebe9498a522fcf4b73bffd52d9f6b2b58bae8e86afd7c9a9e69cd67740804be689af50b8e80d433eb52639a9e012fa5a8b25e46cfacd3ee6e2a2bc7ddee17cceffdb93ff7fef4cf8d00ece7fa48f4edd5e9edb6c1a9f02ff7248cfa055fe15841f0fc7ad3eb344cd28b4e7f5d7fd170acef8129707bbabea91b3577eb22cf279d3e369739a937bf397d42cda8ae01f9f41b86329e64eb23d1db8aed3768ff822c5e7651dfbfe0d0537054c153eff5514adb3b9808f4bdfad7e7d3bd35e7bdbaf3e67cc45cfbf4e6c7d5ae01f99d1ca5dd3e230bec0d250c04ea81d3e9e73e3e6120485a734ab36e69e8e333faf8e87302f61ff77c8479d87f3ad8f50fe4b014d5d47bef3996afef719ee7795d37cedb7beecdaf0b611666dfb3f631f8a4e4515ecdaead5907235df7c6157c181c55f0d8bbfbd73d70ab95bada5642d65fef54803fa735224ab35eff7ab7be77b16656d3ae57d804bef79c88d68c9a76ddcaa9bf5e38b2e0fb3ed95d780276ce5ff37bbdbc709c38c45e57da3e230b1e3ff6f9646572208fb07c68bf66c164168bd9e8b6d96c361bfd7d43482ecc45c910c925b7e09955a1f484f9ea728b15c1eff4227b1a32291a1f8dcfdefa36ea5b08c86f975ae6a45d6dd42168c41660240c1b1a31216c541b55527d6b7c3822a9c0d0980120cc1a281a331bd66d369b0d4b8560f17ea61f65208000b010c20000b20b56a888a50802ca3f3eb0cf7b7598bbb6d29eb245bb13ea46dd2d6b3494923641f92bcca4ee4e82ba639cf3287bba822787bc71baf5fb59cfb65a1bc67a36258fdf57675173ac5a6bbfd63c9e9435ece3756e042bfeeb7dc2c5f686e3f5399d0be7f5e9f78439441ee904b10dfad3a716bdba6ef23897be12d51908f39d609741451ce25841949456eb57eb5793d4c945012b7230e48a2b941e30330bcf2c7a557f74178e35e4b15e9733ce2587e3ab4bdacbdb5fe1681d7fdc57ffa8e5acbddfdf5b433a43ad75566b6dad561656ab09625fa9d687a5c2848900fd32c6f96b92478c732c16b31f932da8db2362f8cb0b3012664d2c968397bf5a290d1bf258eb37a35c78c3bc2657fcdd2b93f5d05eaf2c7fd567a730df528cc7a4cffed12579c438ccde313b99f6972f77ebbd39d0f8de5a6b82ef6b2d73c14abfcfc72c6b63e7f5863cd6a7345fa7b2977de198bd1b96f0d75fde3011fc2f3756f9f80b6b067bf6ecb1618544e81ba2c086f3a99bc9d44f29a41497a6b72e27539728dae54a37047e7ae1be70bd565a47ab4e9d3a5d4ff090391153354c069e01e6a813f7ded72bcf5673407217d65f0a8688172a2c201982a78d1416f126118499365d412481c41df186b258d79251c7a6c88830955de7030bf6c105fb0823237297e0faf9f9fa9252385471d5fbaadcad5d281056556a959abdfb892c6cf4c456a6b13144f7ef7dbd9074dd1a78dc1a80dc1a88dc1a90dc1a96dc4b645f1673d6da98b52f7054b66a15dbbdb49db81f276bef8bdb9a46779a32d0b2858bd224bef7bb41cc2fb97b5a61b2d27433ee38cc71615e50aca05c41c982b205852b8a2d8a928581bb1777c30b73d6da97a53170659c202933448e932333a8a1a185166c3b64014283133259baf4bcf16287c814135d3e39729454d97952e68d8f7e72f524eb75efbdf7f5a4c6a27889dd2a89a5a3494c58c88262073743aa0c5902cc9310d22d0b0e4ed010e7a6e312b9f96cf101828b7e52b26b0e9a1684a009f3820d5709f0b1e4c70d32d8a85c9154963e0764b1e1ad7d7d16881a458e26505ea25893438a1261921c20141245cc953a46e6f870dc71f5d6ebc255d36416decaef0297cc29f7e389fb418562ee8b963b45dd5c2728272c4e5c9cc2385539a571c272d2dae18c10300c8104092e51a24de2ed142004309187cc115a6fdc50055da178b8a0b857a0ae6091dd9d7207c88e2917c2c85044bc5b2c10d1049a2d3a808c41224b8fa02c4cb7ca7cefbdaf98e79cdbfe3a0ba92c3a2aec2adfdbd599678ad2a4c5dcbd79b8fe5ef71d7f7d0806f1ba064457cf8dd2e45b8ba198b2093153a68851f3e3ce9734533dc069f232664a0f23cc4005b1302871c970040d9a24d04885e92184822d3c04a1468b942953ba224cf5da48f2e329dd7024285b48af5502bd6ce9369cb3ebeeee6eae7ec9574a29a5a46dd00050d2a477bb3ff5592ba54d6ded9e738663fb77fb77067f4277b7d79efd28a594b2b250e78f5d9367b7ec5e3e1e1e59bdbb7b8a734f1e7f9e0299e2808e5eb0f54c3eed5e06ca18f2e79eaf501cf7d28bf7d3f1f43cf3fc741f9a11bdc1414e51c9aa128a982e4739caad9f2e47c935278fe97309ce919f9348110b7b76f46067c7ad05719c4c1d38e1830d15266e7af8411c67139e1fa7d3d3cf39a7cf9b113fe738c749f5735a5dfd9c33eb671c363fed0413248c12a8199814218e93cb050b67ae14015385e68838b68debc7565a6a22ddb485c4cf5ef2938910354a4b4059f962471cdbc9070a2a34ecc1b2840f32dcf9b1a36e0d801fbfc72eb51ee32d2e8f3d533de660382fe0472e0e149c3459017fe124f9eb167674a7de90a96f9c3019ad31140f400b87efc693eaf1ec62b8fa49c3543597eefa1ef1f491f2f8eeabef76baa465e4f5232572d463c818abadaa224dc49132c9b14db520070a2855cc88236db2f32375fafe9162f9a6372b8e94cb776fd5f9760d885e746d8aed4847783fcaaa14dee0b005278a282822e228ada4a6f8f0660d19294ec688a3bc7ae27f945ba3ac334aae6f1b8f6f9f4d557c7e9c4bbe7d9c4edf2ec7f9b4c18f33aa3e97714e7d4faa59f5ed73cb851f679d6f67735543d417246a38238e934b3e91840b134ad8a97a228e6dabf3632be51f7be9bb892c8963337db738f6926fef9b94ef1f9bcb07c0861ec420c14417132ae2d853df4838c5a0f4b485440f9d1fdbea1b878f053c645942e6082c4d4a22c0525a224798237876883de7e99b427dff48a3beff5c8eb1ff5c8e2c58fc38f49f4b3755fef3fa7976a3e63f277af8cf0928fef3fe39ebf7f3eaf1ecebbf60df8c03f99e63d891d732991b21ff02ffe51dece845e5c8949a267f89a9c9e9f6d4b4365fbef3ce39d8518745ec1676843387f59c5fd811876551db8e6e3dc0db2c1ede625934b3d96c39b66657356d76159b382f9e7a2be55156f5d3653fafbebf09f332f3c4f3a7a482f1f527be922fbf3e411938365481b2c388963138a4c1e3c30d6b6a3023478f0f2017648c6e82c8531792c954e4c9d183142b2626551c122e2955b458b909b385e5f323d324766080f1ac91794f00c08eea0cfaf1c345d06479eab2ac270815f302239228e2a9af903fce306111e3664c901f1660a40cd61e3750ec88214e53d06de108ada75ea9abb0f7f5cad465d4bd033a968e24f1c306a629626da1079e3c3ae881018f48e1c819e2596b53780c765427137164310e5511a594a3e4f2ed729461bed57c7b6dc750be5d7635e6db9dc9b7cf96b0f3ed3098e0e1db8d58f85663f5ed41b0a3a6c293e65579cc22a07a46eaa9e7d1041adc534aa9931e236e4b77dad8e08814852b46302d998941c91a91be798a278aa734043b256fa08b466935a3d61fd8111d639fe5a8c1f7037e7c51cbb90937df2eebe17b4d13df6c9ebe9bd0f2ed3eb0a386214b32f203172f5a63aa6e98a2b1c38a1b1ccaece0030c5a7aa0dc6f48962161a483a70efb210b8b6fff78dcca631679558b12499efa2bc89938dd05c254806fc7b0a30693394995c609c53113ba68be6fa06b21f4d114356172b8ea51c74a46f1e4871e4f6f828099e2c4cd136be562c8a34c362382f1f296e64ef8d4ad3cf3429e95960493235a24bbf3ccf9760fbae623f6fc5acb3450e82219434a2579fcbe58fda2043c45a2054f29be2f4c0f61042429ac331fe3fb6a006b3ce9812ca58e48f352ea88a61f3d257eba062fa58e78f2ae7ebae41c7b0d6559f9eac5f5389659bca67e3a92acbdb8a4069facbda660e41b91c44e5bef35f56c3a75889770e551853d4f5dc7d350e8ba74faf1a5c5f5d35f5a5db4f5aad3452ffa7d37356dba6d93a98fb8e93da7d4ebae34beafdecbab703ad0de2c16d046c9c91e35dd7b4dd11a4e2269d39f50f5f0d3abfcf4f175f5af295a932295d5bf70936cb155821da460f97003112cf818418c1d305c323ca174459c3ef1748fc90bd345e3acd563eada5473e53575d11227efc983f2b04cf76e5df4f3d33d2e5d24a5aca27eba37d545b09fee5175ed13a7d79e4d3c7e4e9f4eadf4d440a284dc864cc5f0d37da888fcf4cfaac5fc749fabda357d66592a3fddc7a7cf2d0eeba77f6e7efae4bae1a7fb846d7e3abe217bf62eabdbc24d5394369dc3ea222e8bdbe2b2b82c2e8bcbe2b6382e6ce3b2f0d26c9a4dd3693ecd284b85c888e8769dee938d8aaa5d5d34da256bb34ad6666d4a4b4cef3f5a9b7512e3cdaf41274248f265b44df40991a0b2147dbc044a9358a2143f1fe515093efe854248300943f209853a4becada6fa40225dc4446bd8a99b64d965236e72aa9fcdf44d4e4f51b889d2e69bec3fdaa89f6ea3eccd4e4db75431a060636b888c6182be45a06f4237700891314c40436245606e094d1b0fac6f5062bd0d88121025003839d32307228aa0719271b8e060e4872e20748a282d11599ade3cba48683221c14dd3711376c24fd3719477e535b8c593435ead7bc0531f815eca2f2e248dd2aba73ec66a488d3425b7537947e34fd68f8c41245b50a79e656d0349a30e00000405fde8f3faf1f5a34f8c1ff9f5637d594317f689ec3fba78ea48334aa06e028542f513cbda7529abdd5083a6b5db50362d455107d6afcb9ea2b4760bf68dd266df4430640d6329c205cd1e2f647810db8d644d0262a4eca012d3f5c31db1674432467ffbec32c9e3ecdb673246fd76fb52cacc969f338a25d710d7196d0a444a29a574ec2f658e1cd6b4a086853b398010a5cf642dc8698f0b576f60a0b2224af76020cc9f445bdf1dd53e6befa8c6d2f93b77d10c85aa8593db29953ce6ef2c63acf87622ea3c38effaf3bc1d86918c51bdfd650cebed00901cf418e942c6981dd5b76f37e2db47a16ff73e10bb07be9c82d5b9e904bb047da869d23d5083a649e7c01d386c36117b07eea051d844ec5ea66d55d4b5ceb1c5c20c956ff7ae7d62fbac26a9da5f38fdcf4b29334cdf1ec2d4ea2221fc5f5b697df755577db3f9f69cdb65edde3eebaeea2229932d660f2cbadc40b64d9c608b9c1b35285b4c1c217892f802856460249a24debe6be8b2c5f4b6217713543cd83e49ecc00e834232300e19a509c91092f172cfbd2ec4a0900c21191d0e5988714829d02217f64db28dc93c3d2de1a74bd04221e9b4d1338a42cfe853cfe4fbf59147d992096412991c95d007b49f4e1e329cf43814925fa91351e740e91ce6309e36ec4fc75f9dec3e238af50c4ef61f65329f113dd93912cf9933a5499f4718031d01b9f54c7ed2cff71f3391a44997de4b2d7286fc0cc7bcf523d15b3181c7083077ec3cf990544874e0b2b3a3871da888524ad9840f524a9ad8d2f3c4264a0f41d62e8095468b920e3d5cc022522d9e27a767d4357ee476a19e35b08320bfc3af4a96bdd4f243d7736ed435aadf1f99bac702f419068f60801fc82a58c3067e15d205751bb27f0a820d334d93a9cb1fe554082374d1d7b317ac7a269fd61f5b864cf11246893265a0642862092171608873844b0c4154901e4a78c0535564861e940429a28d0f385944ea9268ce39bd5b822f7a7695e4e9560af7acf11737516af6b01163a445932f3a66e09a214f1d5183a7eea1144315858e0e30f418424712142932559e90e96265844853bc942a93f5764b962a43f5d45f8c444f892e8fec4f441d067523595b41c6ca0816c6bcd1618f483d0459c3c0871f8e5c41e2e34a0c22b541485a030a82adb8c0e7277f414e4127310702599822502c680538c50f4ce11954e117705e012906b9515f00c27c4517048305cd2e05ebd861419dd779decb7b75dd8ad78aeee5c4c7613e1ee4d37521081229c88ddaf301a5c821c5dc8b813f17ac80147fdceb18f8e329c0cf5580d981e6530a58500528c5d8e7d9a88380603e3ff99322eecf8d87612956585a53613583d680bc3a0a37680de6d5c7ab97406b3fee25841be859b5ba44ae93154e4127d9695eb1443d0f0cf21f30e61fb8c27dc0ec40e01461a00a2a605c97653e5ffd3519502905d234fca09ff657023455a72120d15aad3e5960165f89beb2902d2abd58b6a895f309034a0169855bc7806c511b2693f8ea19980ca88e43dcf98c0bc4ea2854b7511d0750f5a934976a87b14b1812901b750704e2ea5dfb48f415834e56f8d7a0093dab2b1c062a6571453883d2ea0cd9a252ea983abeed2bfc0449144c01293b17ce0072987b2b40a133f9462d6112b86ed454df556df51d0a8960bd6d2884939eba85e333ea44d49baadbaaa957d087684db28d7b78f3a7e4e0657be9ed4177e920d7885c7c72660059231a22808c515d7a01aaac654b01b002b245fb042d2043d2ba4d17ac34df443064174b2fd01110aa9ec99f21a36735742224639454200ece55d0719d0b8548c02a708ec32852e490ee91a4429a5182093632ad5140d2da8f902df1eda3b7f9f67126b6681ce18d9e5d2f9efc40965c9ee87a223dc38e044f256a257569e712c5ce35e5713a3d76393990d95edea0388df3c9fa38a31e63bf40d628d30a198366894d0e2816ec30ba28e62abc2673910df063065d96e4c2386799cc2320b111198d4c8d74e27165f2187b084cc8211e7b97456b358aa461b72d9811e15d64403ceeb2a63cf62ecbeaf1d5e390cb6e3df60eb990f8b1d2a192524961d35b7442b6c03e3607b58d74813d667bf9938aa6a158f48a52512b5a5599a857d305ac022daa086b65a2cef97a3539a85b46ea7075b8baba257acbc24039cb7edc27ebb1c3bc6beaa220c7de2dd19ae5a223b65cb4466f3485b7e57aec1d97ae61d9611e77552c6e96e9d645edb866d16e49d76a5703798a70c4afc1d0108b1f6b168b1fbb1aa6ab9aead6535cf211e5d133ec40a852cfb073d1e8efee6eeb144c6185ef99c2a4b69ee12e5a6b117b908c41b5e4c901bdcd9e745a3a9d6a9131aa1bd9e23639a859d3050e0a2b57cfb0d32572cdc2519dd54f94861d038523ce391cb3ec271c65ee4cb4566d92861de39c65fe9409cbe4a0b3a68b2c3246bb01ed2d8ad66a1249c38e1d67d19ae5d234ec42cca4bc8aac87c751f5c9638f7a6cb11efb178e9ee6b17be128ab7aecaf70cc36cc63efc2acc763be06f733ac59ed46c6a870648bacc941d59a2eb063e7bce4eb23bd3d5ea2b72e1a2717972e1afbeab163a7535d34be6ef8ab2ec2de585dc485dc553f3d762e8bd6844850e12b7c45a8c20a57e14bb4262577b5c571611b569231e64bbc24f192c44b321c5be9f1d263f75480382e701574a8f00b42211256f8057e41a8c205bec2a58843855f106618928a19450863af36ec55097b5dc25e99b827ee898be26edc1447c5597136cec629714b1c13d7c439515daa6b75afb2b6b8640c1d79bc4d8fc76a7bec35ab6e552e6bb34a76e93639d15a92885d0588fd46d17ba3b52a62bf5332c67cecad246b938ad2b0e3a5cc84c776a24bb9869d55b205762e1983730cab59b205beca7aec930ae32c6baac72e877078c2ab09d633db8d2e1aa747670d3586cb16dd3e2ea037901c80d245e7a6b00f7e3ecb16edf549ee6ebac1c525b96892367d830648292b431e67d6d7e9ee06f2b979b4cfac79ebc4d23539d3f40cd3930be6ea121196e59ca9546e975dbef7de6afdda7aefad469a640cd9bda474d24b6f489d4a6046f134ec1fd9a36102932c13b23ea7b76ea09b8cf9861af80c5a23b282854083fa055358e1670a73848943083eedc47593e4ea1b94d6d3c6249365a7ef0e7ad6307ad673ce39c10e8e68c83dd5d44dddd44d30a877adf7ea3077c31a82e48c319e21b9ac16c961c2bcbb4c9633c623f46c3ed1709c717d3fcda7f9e44e79945725b8cb64394f25fa6294571d3497a69fee51af7e74567d466944335aab61db28addb65325b1592c7f964fbf6f934adba883ac6395b9f31494804cb8211c7d370265b4ca7eaf681aa3972e4c891c2abbdddeb4b11e4d287805cfa0b295b50971e1028e5acbbdbab40120d4f39e8c8e0254a0b94101b8485e3f7f56d3c1038bf41f9383e855390c6f741b34abfb072e5e92388e50ce612e6d3c60f58e50ce60d130176c307947206f30913a1fe07f37cce0ebf3a2c6f642efca49e3cefd3ecdacba52cebe6533ee49f7c812634ad9d86a04e3692d8e839a7d69d8e328931e644f0e7dc4b81eee912a16d9f02ddb3a7c5f5b003deec50d07fbddeb046e7a0747107f0431bf8eab5c226506d3650ceae13e0af6b0026827deb163681fa9d7b54ce4aab4f0af4bbd0658bcb85f4b657a75b1c0d97567b47ce895ef44c8c19244c5c4974e92023769221884842a9861ae81c3181ccc97acd99e3c321f161ebd112cf862aeda16f1aa0f000068e1922a4a2b869028b8d9a234c55e248f4fd038b0172a0c9f1c39b2a2e203ef002d410383801451a17a60f2d18bc94baa3e44e0d5368f40c7bce199e306532e4fa8df9dbdbb3d5551652f728e370cf3e6bc30f06be8dd92392b4e953f258bfbdfdf3bc5fd873eb9e67633f59e44fd2e6a8c14f8aa9d38825fda458070d5e4ae941f3f98503f450c5e18bd5ed538e9992244c1041d8b1dae14297150deae14c97265bd00c792376983f0e7f3116b497527a94be4e0e0578297567ebbd97527774f82dc5f723db8310b0f2f8c594440e9cc5a4ec7b2e19be180b172fa5ba5af8a097527698f87188fa70fbbac804b23f617abb7c19e5f43497986e4c9bec2b8c0225506f9f3eca293d45be6819634588942444ea1256010ce810256a071528305d620d43a0b449695d44ea8c143b3ff4181147188ff5260715971d803cd51167931e215aa04491c549bc000826be2c1102c38f3de2e84a3fce5aa061050b93168ce1d1638cd8e128a97a7c1122cf0f2d678820421c65160b3fcaada922926ca599b3670e10e2386d3c7e9c4ab28d921c6a728c29428625c47132edf87136fd802a13064b8d141d2e88e37cd2e14190354e58c8dcf9a1469c510c71d245081613737e10678e9f1e02adc9aa1dded8808411b63954e2f412688d045cb28c6822868927a8c4e937682d290725d40ca16487eb053de2947194c85069810b149a1d4479a76b8917bec0b941cc1471dedea857e8a46e2ec98d2a03a4aec96e6235f6ee965a4086e090068c6f67219319f50e3f1ec89b918ce9a5e463f172fc0a8d28ee9e3620be9bce96ef2b76638a44083a4abe7d48031cb6e30e5920c95c07be207216b26e26f2286f1e8c603404e3ce9a6f4aef687db7ac8a422fa5ee80f9fb52ea0e16dcdd158f92c9d225e7c9f911458fd3ac61d9c224d616e4717ef5922c3121aef011611b080f53e20a1dd4208310913a8ed9435c417a11691845687ad2cbf265a1cb95b8820b3c4958714a554ce20a442c302d612c6b3640e044ddea0f34e20650486cb48663f2e8c1495c81ee10bf66c074e9a3cb5ee697d36d0eb197524f604d9f524ad94e316cce4fb668c760eec852ea09ae6f9731a4ec287dac67d30d950d8564581cd8ad27892f4f123f4f12619e2424e33ae75c8883eb3c49f43c494c12e3e4e91f983d5076258ff97df6248f4e04d63779240a0134d2217b4e6372d034246d3ac6f3496ad170cc52eb41305d4c1fe7130d1b37704c1e44736912994c5d24a5ca44fda43ffb496275fdf4192599d0f3d34360027d1054f7aae44ce66da040a36713c8d528c968fdf40a6460527549f586b5825e6a915247d61e13fb70ebddfde8a34b7749938ef3d37094a978b925861cdce50d8c8cf3be73da5a2f28872897375fb44a496bad94d24a29a5b47ec913574eca22596badf2daa8b55689ddca7034e1b6c9d3a9eca573b023e992564cbb7e7d147398d2a4f74929e594eff5f98c499f81a278b33faf7eafef38d0035f1db45f530e731f75fcd52e9272465dd2efe26aa7e2ee3ed1bd6c9e9757bdef931fecc3b43625edbaecfe3a4d8108dd572963ccf7beabe4640d7b182ba23efe7cb7bc76f2f47c3e29637c30eff5f948d9e2de5026d1b03d30de8ba6a973a54c7ef5c095614bdc64cf88963a42c664d84ba93a3cb6f22b0f11adc9a613c7eb2a7191a8a6495c25ffbc94a273e5850e159d294fe24c27c98fb2db04cbea0ff65e297e3a6cc45facc3748a74218da1ef0e42f5d1e101d42d3979795e7849e915c7e35e60eaaa84ee10273cf55921531c51959ffa619c6188ba38cf394d525022182f5c594c4444e7b81080fe30ce40d2344d623d10ad0a3bc232a22e0e06dfee2f6008b10951a25826e7eadb59d86a1e36e5204c419a1a7684ad5ee090e70fe32cb32fa5e444fde8415fe64099c3c4c91ad1734ebd7a9768a867b3e91d4496bd94aad2d266b22bc95225c44ae65e4a55f9002203e16902ce54fe9888ca9e19aa7cc1adf3641cd554b2cf4b292372789a23df9752462c912fe789d264075e505699c8d35f744004a38be69696ac2fa5b6b27e94d929de387ffa7bf49bd4a7535983a394b2c3f436faab6c21c7eeba7675ef82b58698d2e87bb2526bbbdbd2a111a8144bd74c2339ca94442403000000b315000030140e878482d178a026fa3e14800b7dba4a5a441688c3c120866114c518630c218600400830c420c3d854b1002e16191c79da25a86b585dd58671ea9a60ddc7b77b2d358353cea6cb8d194c125d979a33c7be2f77d819580da3c1462e8207ef881cec82d023fc7173b9c89b26d682c1712a6e8e36f178917c768946d7edc34bf8dbb7e66b2f7b13ef34128f9219e7c7af4662dd55662561eb219e72a8c61561d9128694f88749fe1722cc10ca9074b0e024992ae50cc71392720265dae389c580711a435ed4a1d2eae83d5c421a5ffdd9175da1c0f246dae2d41a1af9a27669653fb01c9a83763945373765a953467c9498e6c58a9517408253b5eccd271be08843ec776f72f788366f6c15a691a48d77e61c5c6212891e8c1c8c05c71336a43c9c08b5fe28cc5f25235cbb9ed90ab2173e0819aa7652b6d3da5dc41eac192b1067fb2419983b5f88bd94997da2ce547395613142a3c2b23cf2bfaad07a662f6c726928400e89e5af6a9aecd91599fd9d41f01e027925e67ba9692a03a1cdb3178582dafd4c2a9e783e132fe4ad56d5afba5035ab0f744a4f60b14f27d210133d36fef4b45c0d1c8a9ec48c468eff2379acc1c031a0045593f54dbda0dfe09eef95297c0dd44c7d9dc756a40603d62a9128a869a5847a9f3bdec18fc970685c55f1514d05d46b11de1c90f5705cb329a6ea2d05b85358e3aec6bb97d2c6a64f2724c3654cb462e820c35707af3a41788e3e77025192d15ac075d9dc89bd8d9f0358e8cbaccb2fe5aedb3c61b8d8f64a21be0d6d63fbbd9699dafa943c895ceb008b495d74b425a4117792d92d91dcdc07fb99ee822050449a6dcc0b128623302037b864acd810ccd81f33496de45e08b679f11fa681f0a65fe78a4641286df7e32c2c0ad2db6145643b4f37b99c52a1241312479565d019adda3682cbc1d6d2e31fc29a2a48015afc03f3cda540a4bcf9c7b32d5d02fc1603917f9d8588d48901590175bc71b7fd7d64a82a432fc9d1fef10b32f5760d280dfca781f851a2c34ceb4bfc3ecc6732513a4d32085c5e0931ba7cb0fa4f6ff63943ae16177450dd7f57dbe3f128a6de6afda6ad5c5b20a7e9dd03da1719ac0c63f8a6b1b877e48d6c07caa24d4983f03c700c0436bd940952db262bc298ec412a893f3e8760740315b4f312ac7f94c07402598f53df3a3d039842d1ab9de3b639ba5084351c6ce2067563ade4d41f1f09af3f181ff68936ded1b3edbfc1b7b4d9821b98a1db26dc650e0e3f36fa3d2e9f8943beea6d5f83cb2d84ec7974c543ff786431b256fbe6c08a6353c8b25641790dda35fbdee117559072bef43c1b6a6a351a9dfa9a8a0c411b9b643c274e9591a096669aa52e1236a459959f20eaa2fd97fe48fc2752c63199de7c9d28a6620be841b02dad5428c531e0e845c11b654b1aa94673f005344848f5f7e686a529251d4d6537244329dee0ec6309a76524570b8221c8ae1a80f7c610bb0fc94bcf79028116d3a57495ff30f1becc7136d6fd950be298b967d33f81d96dbe01a9c3588b678a0a0ca88c209eb6eb5845f3744116918e214155361ea7f6ca819dcbbd0020126ce39e5560dac6324e5bf4e4570e5f6752c947653f7a9ec006f7911a622f3961cf8a6cefb14cdbf028df765ce0d7347cc480322e5d45d3da315c370c39763ca9f4c391a516a8a71eb7aa52c0e1a4b1e53103642f246cbac49ca9233bd8eb5fd29d3c705e7e350d06a6f6bfc384eac8c9151d218c7c1a605a362df13787c3d2e5a7d551d645fb996985c0d8be4b20c7988aff42bc8e86b4eaebe8502ac024d275623fde3c2fdb2035e1dcca726f43ace01e07d8b0585c7a2e814ca4b62c43a5d94b4b62e56aa20db213af71be453909e9e0417ef7040d513cf0ff0778174050a3d43c843b15b23f10f5aa9cd067c0117d086be399d979dea6bd6fa2cbf74505985c2eebb8510d64169451220f74cba86a902f521c2278beb36239bf011b63f416bae8250ad2fe67ba4f3cb2e06e1484640bf54082cb178c26164ff61d2b1f271337da9e64157e66c1925d3c0b37155487616c392b657d5a49975c73560b5700bbab9a6238da85bbdbcf27cbd41113fc8716b99651d5bb00bf604c3bffe59788af6067476c2a9463cedd0acd361801388e2337f2b87a008c9a4de842181059c47d3d0e478ef4a96ac95a38e844571730c5c8bedeab5df56144006162461f9cf7227c9883183026e456d5de395cc8a1e4a48b18e07d5b6dc42ba6b1c61b34785d7ecfd36f70bc6eac6bc1f1de38894a9d05499419ae84b56a0b449f4c9d75f924b7a5a787279192dfb104de7225cecce680f9501d05bef0469f63efba3a8758acadc4ee1a4dc0dafbd3e047dfa5579ac7bed299aa3383f141aa2bb980e78414c2b23271cfec2df27396efd72d4d33e8e857e69c9411fa6748887730a26a4c3f49b0371c8f4ae4c4fd9d3a70e01d43e1f15279ecae5665a9918a84aab2b72bcf778025bbeef412b6f08ddd0a8673df805d016f57e4e7a84745c8d8961b644fad3626b1e7b720231b984ef47689e8e9b00da5809bf266afe4842271a35613b131dc44cdb8d906b545dadb5feda5212de77b3b34ce0e051e2dcb0dedde45cf5039fb58baf4ce8a56cd22d25227335baa83b4a3ab65b131b3f1f2b73f9df4549a1d8e56095a419b9094072627e7fa9b644b3a191f0007e91aef3b10110fac2f068411446dbdb0a6888cd098fdb260af6f1a29066dc3e5e4109e687c110c200a771210b4dc798fd1033bc729163b7ba2c8b673b7a6579e0064f4fa33099067437ca986b21b8834b605e17be7eee86b757c7c81b88ed7704ff10741303f6be21f75e3f8677a7d79165334ba6b28161927a41cdcf3a0c43141faee87042d020f43537fc77b95c820783d713c4749d8f824c8a4a690ad72a8e5ebef26306268929ab10687e4d23e917e42c9121012acbcd1f3ca72ce4d7702a379b3b7e758e1a7fb75050a2448a655e5c6b795867cf39850a50625c82646f6be936552278c99ba2e0dbcf08301fc6e75998c505a3cfa50c40d70c833c3b3bf78450735df32e32b105a0ec7f1022bbb8439ed2a1b235b70b77dc9b48105cfe91d374cf29e91305e02022a237383429bc150bcdb0b711f1741f866bf333091c1d2e58bfdbf79a5a475656fc569c96c4372a1399caa92ae449996475622ae63146c8463155be12ca2c753b46b18d6cc965c45dbc7136de516d50e35126491aeacd3825764b80671af65f55ac311792d3a214746ba565263bbdcea01816bd9c3ca1a259793c472e5c475e16e0b374b1fdf914760ad6611599b6377730be4de5ee91615d7e49c582ff8642d37161b870a16a8631d5981a5b61431d5f2384e057e6e1fb42a3e1d9e6d80d68dc8f21df8a9eaa42bab3aaf5d6030f4b8bfe5c59e3dc11abbaf50c0bd8d7325d093659bca093a13a35a722c9f1504c3aeebde0bf30f67a53728bbc57ff8cabacba9e3b81b87bbc0e7ced16ba295fa0b74b48601a9498f8759f14276475dbde7ca5b5945c91cbe48e916b512dfbedf2acc10ab7a707d1468a81beb1693a55108c7d93268feb1592d54962e0d598a9c49501a3d55242db5d8159c03254d68bf2b867609f282b60118b8997af654a96465a2d8d156dead00cf30e29e61a38ac47d19688bcd1d08ca06a765fb7ff1e1ef78eed2e21fc875421e6f35ae12e2d8186d207f8127902843911585540a250a90055623674efe9d37e32c908f09bb080be9208c0c7cd45fad2b742c9c396cdf47bcd9b05a603a17ef7cc34505db0bfa98a668fedad0ce02dd3bb181c73ca55daa4e8378de63fff566817b955c21614c920c3603877fc8a811f114d44a78f4ff741d7b8c42f5ccd3cb4dbeb9069d88cd140ed2a15ac7aaa83b87db7a01671e508135667d16a902cb1420d9bea6a5673125c241fa85c8aea45017839b7b55098fa18796511cd89cbb95b30f6c74efae2af2d5420255edc88167bebbbddce0a2d58cb50d1433708c2e1421f0d9e22bf3161d0a97598b7510e696eb5257185fc0258f6b7b0a90d7fe2787c74ea4af5c83eba13839f258d8f2679311234037cb8c6fe8c42212289d16dcec738615228162838570570670fd17e41247bcab36b35aa17aed6a6e2faa93b7ea42f2f78dcacd553a13f31db43535aac7d51e822dec27f4958492289b5241338685d33e6237652574b4d551cfe991f0549df5246550a625067364fce202fc5661e6f67115e29534a256fce0471be6f59ec16519cd7eded3d4146599a42cb6f71c22351e07dec84d20906fb8127270b224e993dd1af6340252ffa42aba7525b6a19160d1670e73f5def6ecbe14c906bc050fd48b5e849937504ec8d4978ab381f2defe5f0b5bc6bdade2e8a6a9d24e8028b12d61f89d28b686113f451b462ab3b6d5cbc402a2d360271dfef3ded6a06a795714832bdd2b82f0ae6b415aca75a2cba510c5f50523175ebe821c3f08ee6d3478f46906776e0c84aefd4dc6740b0b3e3b56ccf022ffd7e4ba845276cda9fa3f7a8b7ef3ae0e1ec1c5b14dd1401e3b7ada8da48cea5910a81b4e5bf119359490c5afd118d4f4ae8fcf10aa5ea2661620dafdd804454417ccbce9847a4d7082bd64f226b585234ad45cc4d97b4eca1498e9c3f53293af903893697b1ee4a74f5740b212b201d15dace2988f4798a755db10c5d192e8b5f5fcbe6b2c29761417b89da9d53ec52319fa2acd39022100c827ee6faf61f27243cb1da675bfeabf26aea9bae26af1445649443775ee9d871b2ba3ff8bafb6dd67699d97234741452c060de6ccbc720d0ee0aac80c420e98b2368b5c394e9804c3e40489919d869e2beb68943d4c7df846f4e6b8a769bc9c6e9b564bc2cd7e58a9d10b4723422a926c2554248bd7a415c4437692cf06199df5a2468a6c4f8d0bf94f33939d303fbd27d6b6cbf1fe25fbc79496b5ef13a94bef4149bd00e4fc3c9a7c54013da7c991bd283cd10c7ce917895824aa9d1a1c83fa93b97affb4ed08045e53a53d8332080a74664fb93c68da0c2d921b1f5819f53fccc9116ed7ebcc0b55775fa4059dcf81ace4a84a37df65d83cbf591b0a48608f86897d2592c1b99436fd371850f313415405ca7906c145d44e877af5abfea2593ea368695f4fac20475947445d77cc067c550d7dc2e03b8d1f45bcc8e469e4644f2eb9872c2b6abbe102978642b9bb4ebfaed4aa61f6613590b11540bf15508dc11462ab6d52353cea0747e47c71cd3d00edacdff494134d4562d3e7f7a9d8f09f91143393bb59019590e79e988dae0269220b46a172b6f012388f13f6d755e77920d286327581016513fd5c6d16b0bdfc246f9f8b38f6e5096807e414e661b25b84afb245f84b1ce0b94db3bfbc5614e6d17be369b72e2f27229e6a48b7a405b73b2754f81c1ebb53c25131e9653855170aed075c5e54e1285d0f89e40da04c33c28af2dbfcdcaf44c37ccc5909d8cd1733432fd48b83488f47c6e64f9d33047f25c71a00181f7d551728eac7b1e921852013c078f444f30ab4a53144f3623dfd9ddd1d278306f621c73dbc2b326f837bf239dec6cc738cb1394ec186201e355fa01dbaa38521d955dcd7228221ec72ab56265bafc40f26a10d83c952138e7d808fdb5f745a09ec74db495e146a3fc84b0058d7b40061236e64b405988bf749e0dbc562f6e3e7194a1a5d8d94095f952c080ca01ea139c1be3becb4c71b7fd458cbac18c4cb99d1e04d6bdf8b0dcc4f9bf8fcdcef144cafe913b4e62b8d57d4586246757c6d31630b8ac0752468d8fbfed0831b892ee22bf06d058a14bf53949563fb1bca9eed958d1892203a221a28eeb615ab64e60841764931bf408434797cf29d330ce670aa92af2ef395fe026b8c3023445233b95563caa53982780276de19f839ae12ae55c3516e21ad6bfb53cbe6e433716fa4efc9a12954c521496f141dbf2062915fe2ca8552e5152274d808872deba6146060c38802cd01b4d0582c127ae2251b0ef085bb2010a03b76fd33e90d3674833076b550d0e3ca1622ec5c148bb1fa9528dda86d2d59f6dabfbe7084ac04b37c217daa20b9d8409db3135de76af678466b572aa3982f137d03a84fe706c33c2875285343c3dac1a27bb42b3cf3050e9871460f3599b99d7f4c2c7834b199fb5b9d5380f5cfd3a2591071abc3234f4c5999a2bdad1f2628f2d85f64dc3665b8ee67680c80c1ecd03f90ccb0735803a241f1acf567bb174f533d8a8503f3d23b3f9f02cd4425b21b3484387575c096bb06294e4af645b6034758e2925baad8029a844444e49d6fcad82f75062f99b25f6cb2a1f75bdd596bf43a0d95dae06c12701cd0ba2eff97319fa72f3dad5d1db8b8b70769529b207d3528c6662b778d0dac50b7d80832acb79869c911b25cd29c7294e49e559afafd65dcc7348b6e674b67229ea64416baf415b6f2f32858bf6ac02c967ec1579956623cc0ea6c7c82fd3e4a84fe13fc05d4ba87933fbe73bfe240f545136ec71415c95817f3d62fcffdbece1b3e91d64b8f064951eb7e4f6fb377fd1843f1003c48dd82cc9b4a9591c345edcd019d320a90af0e2f6da40acec7436da10275786a2baa786e3c6a5515ad83791729d0f87f80a7e964ba3912def2c715b41cd3706c64967c5183b62921b7531d0ce2118e89c11e8584a96aaec9827cd1638a2002033374a243b5131daedc7005b56e7065120b7c39223a162e01916b8328b79d89d824465f996db6dc30d7edc369b35ef16f3ec8c3fd69da69b77ce6eb0464849b6601224b0b336434a6980be5fa28453c3f677f6f1eff1bb7f9c0d889ddc62d9a199fe396300de1a274ee8386f6a1550c8616c1705d75351224a46f9096b962c7b9fc24e8268962602b7f4be81fc6e226edb74398da6f611ca9038bce2c5627a3d0a1a8812cc2033691673e4af98fd61f67ca73231409d230a034e2cceb5aee1114e5fe6eb23b12e369c62527090f7f2c0ecb57af7210784ecc4d054a379a8b3133c66d858e8315192f691c3ec8e8e89aaaadee4850ead64c0c2f54fc10214a44b0f99fe2ba34ab82f9a868f12e35b796fe4b2c54f132cb0529427376a865cc02f760027ba9c23e610981ec1881ea3e4588b6aa8fbcdc6e13799e159b0673b2e18fcf21dce5c5d6c78b2aaaa69aa5173c03779f242be80fee1346558c7a5dcdeb04677582c09e6aa609dcc17c8adfc30270f3798180669ed87b96b2f8d389afa5fea87fbade489b92867692e6df596a78bd421d469e695111ac958f6e6c3fed8ac13dbe3701e7c360d18e51be8b51dd7cf4bbbaf243f405be11b471c8fb453f607d58b08984f7be450ecc7c230a6be3603e29185db980fbfc425acc0276882166a2ff84249b8e751edae625f683bc683d412a9ed1a317db38b7621ae72e4dfa8928fec5c299a096da2ee8594d37f3da4692fba627cea66be7e676cc7ce18c6b15fab1d1f22b7d5eae0d2920e6d988af7493aa953d1e1950be7d1b9bffe0a58f39afe8a2544643aa3eb8a3424d046c7cd2cd722c68757442c48bc6df225cb4a73bdd5872e90d7c08f4bd3724cbfee2ab0ab81219046024daefe553e37b7e2647ac3d5fcc7eac60468ca5af90044c3c02ca249e4e9ce3b58e5121ca17eb6cd070364ee3ddbda0d54a1073436a5f7f8d200f900357058b29ea156b08915d321af9d8d07550d675a113bc63b9e10e7fa35708ed0ce6c480bfd4f9f88f2cae3e488c8d323973b3c5be9a587da8a35d339a6bf44ec6a0ef4d03a37afb0e53d393cc3605f99163916f80dd32e84293e0f74aa064161dbb48d04b5ea8c80b70407ea5e71d6cee557ad0cb18289c0cedcddda9e7e43c050a92fab0d8d93decb46206504534477dc9b48201d8f51ac1e02954321296ebbdf21835f4c42f263b43f1cdf5de625b8685820d5a2f3c24cf4a3837547770945ddf07bb154015aa36f13c03bac69d8ad52d8142813b3e85ad80c7a7aa3d144fd6a08d20a884c79828424d7b263b0d6055ee5b2737cfef2e16d56dba7848046292bbc474096b5a386bc7961c1907b5f407a4b9e2071c082b34fbee0b53861be9eaf0bf83e6adb4816367ae0f1ea3b22593f5113810eb2ee845ea182d28bb4ff8c047d55945f6a56ba3dd6a3044fa870f084277866eae7b82262d47d0f3ae1711353ba2cd82837437fe93e0b034c6a07fea06b9fda119ec5c9ad7cc46e3add145312ff514206a02b420f687b54f6ffabde11671a3ceaa2ad745f9540a1abc5d753a84b8a72deffb5fe765fb0c346e8398d29bb7125b09527a04bb08a18c834207f37db05ce08dd06eb8e4f6fc6fd31948233c9191c72deda98b35b3bf3de674bc772d1aa5a566fdcc014a12a22d6146063ebd374f44339c10f0dd9a0aa1658df0e2a3c635335c4104428e393206a6be706ad00fe4b41fa992409e3e072f6d4d7ac6e2b0367a325b537fa56d9672acab94d77ff103060c9c30a888e0b6aa4aedc704b1387f15575b9e15785f20cdc4498630b887bfc28c9627a91ea5b46a6a586b2b0ebef90652f5db340737d9e386e7951971b83e1dd4fcbcfde9bb5fbc86abc8ccc74653008c8e180af8833abb2c9f50a4c9da8fbeb08dc95916742d31a04457c91ec7327ea10ce75ab091bac4b8df5e1cebd01851be1ef17f55bfc3a22704b4d723016be25263b0672c37fb3963f4b36cd8d8c12174daf1e47c67abdd2f4a973d895485bed0a49b4588c9a58e79f2ea839bf130f121272a5be7bd8a35cd7284f97ea66e17b476bb6e397952dd1fed25a769bae7997ee0427a1385464d94febc34214dfbd4f7373b69c2fa5d2b4aeb5501c4a571a60bfd18b2cfe9e0a4097e973bc499be69b0f7ec5331e41ca777cd50721f59ce7e980c4c4630052fced4700e4ad6f14661ff981aea8ca9b3fdcb6e0e7b0a3d5aacc3a74d2d6942818f0c29c2574804c4e091a6d3cbda4668cd2b6fe9e164f3515695616093da48680200c65eaac5c09afe3cb7c67f333ba300537daeb623af1582ea1e961f47552c64b500aaa22c03738c9f19a8a1f3c2ea19e8261705859c3b52cb914bbdf36595465008f116b82c8ce2ac76c50e89a0ee96e67343fd791e8e1192bba4edf78ad0023d40454c48a2d1cfe60bc0b8e564a498a9d72a57367ea993c18a4550d89986e0fde5f3a32c5244d7ea1684f87d819c1879c1e3ea934bab5e756ea4773659f63f7892570f29709c2463357230126e87231886f557d7dc5dba7a025f80129eedf63f2c074ba95f1f109a631fe3c5f650f95a15811586434eb54a4e87e4632474b9c3d2c59c5cfea62fb480797bc8a90c6ece557f9ed31eb179a70509569d89ddd2113bc994b50d667b8d5b92ef84d6c579c98717fe50ee54cebab267e6643037eb8b446479b49328964a10bbda7ac7cde40f1132b50ccbe9ddaa2660afb584efd12961426f729f2386a602884a13750a5c6a3f3ee0416810c26d238f6d04c8f3fca9bf93d234ec71564a6e3d40cd85ab82374753d7765cda0fb3cf15c21670af20c9bdd3c5431c34ebaf92ec70c449429609ea1e2f1772373286f282392d358b9b3e5abb62e670bb87087d729dbc697d9ff54b3b560d46e24a1771ca3dba1d321bc5a137ce877b5e4821431115e51061ce9f54eda0ff5b78a126006223f7425c714de9469e2e2af0e3221473097af2f23cee45f6bf7a0079fca44a4903b3cb111e5d4d7e4e2771db397e827a0e529f118ab65d0d793157832404d86606eaca3abd0a236e8af72a723483442d9d86858fd519156900af331fc4fe5397bdaefe2171f256178593be23420a322374711ca71a365606e8cc0b45a23a1254f9ac7e3c5ed0264d18d1cdba3d28409e2611ab8b4b30ae345a3492c89a77e36cfd2ca5ec6121a8fc8d8f66f146a4d8f4594befc801dad5d709348a5cf55361f5a51cb2664755d51e3b20afa7667f7ccec7190c744b511a18134de313373171823c1e225309057f0415998ec01cd32b7cca47e925cbaa907091e6835735b01f103b62adae7346d5d472ade2ca4c5c4899a5e2aea04e756e23f2a55e3ff1e4b11e694d34496ec60c258bf9fc9c7384644cb808d13c0d92288c09a97240675d64ced2de9690aa2d27a789c7d4f0763073378a86b21aeec669214c5f1491752c6bc1bc62781c20d6c6ea8c3b8ad68d6e4901f170bb02a77dc7edb5f7c423f97ba7fc8987124ae6d331203e94028cac919a6a932a0868490e9a559f85c0549d36303a8e32febebaa7c01d935453fbef709a271b90527947e77d9cd6f25a9690d58bfd244c5b68a006a01e4745c5bfb4fb97ed77b9f50722a5b00690ce803bc01c0c764b10ac82875f39d2a8ec6a5af5fdbda5c52d3457d8b1144736b0b44c3921d3f695c037c5dc908384a66055a97a99c642b4ce79b3c92708a4bb5833b61331691e4599d5c87d8a5f16d957a5f6501ff9b98b3567950cf1208dbd0dda3d999f44293f7292e3b28aad13185544a4403b2d13e60a213b18bf3a5eb9babbf2cdd9167939db9388db27a33e04197a9c1be6d58942c3e74720e0b5080fafea913ea86c4faca7aca8ed8f71ad20f5559489402c336ba8eff8a2d60e4262180219bc869b6e0d274be2407a3808b8c49ec4667360b7cc293aa00542789fc43aee8a26de1728bb1827aacafea8e8009492794e8e16ac0fee541671850af71baf5f25f82165e8b2f04f2ce1616c0f4876f5b95709a86810336cd72438263d6f7f6f2cb13f7a252d10291bb6a2f7a1dd3f812972d81511646f57b4c08923b23a49ec7d7dfbb745635108233c3fc07f0b6a2cfa4b0803c344169efe9c76a0d0e9332fca5245dac4a6d7ad20ccd268a42dfee4a6ff44d025bb2451675fbf5afc413063b08503bf5517ddddb3516260b52769b5f84d8ead7c52d662b1dbf95bd15fbd937e232876728b54ad0b22f8e3b3196bc0d1bf2185aef786902d149b9e3f408d416e092303ede98b2f895e26118792fb059618d50c566b77012a11ddf43143f9be4e5315c7f3f0083957fa0202576f1c7a830c0d05569f3f92dc5e7c761f017877bc4bef1573af2964640e9183458eba5dfae03b4e2a4c2714ee4c3809ede09787dc40c02acc41e870e88171224d615d09770029face40895cb06d0f8fbacb58f61a467a1892f4ecf63694f2911e25ab32aaa318f3d00bc42d2071347099509d56a46e7f34944c88f49c4f12744c20ce78f4a55b79879e46c7ee07c84ad2982209cd3b748648214259709ff38e1cba4d12dd3c144fa76e74174daf06f74a04829499aa31d561595283a46a4bb92163d87cf35387d1c682de76fa0f09c665cdda212e0a4e76013fd4d83108a8ee7e48cf460c421f6068aa477951cabe06a45caab1db07218734467dd6908bf2acee961ab2e85ce1ac7e70df556c1c5f671b874331ee23c4184f94853709a0f9645536e3ae3bb73b49071cef19845c2e53b65ec98a0699cd5f43e56e2973c90879100168a4aedccdd1aa426c787826951d7e2495d7d11a914e2ddb1a2878507f3f580f74d67154a7f0e2db3dc0ba78762d74f035f6875f41d8365839522901614f03fb27a4a074fe73cef197b19697106adc1396286ea2b84b308ab647c5d3a5ebfdcd77171b08350c7950421f2fbbbbb81e6584837630a42ee7bcdadee3dd24361532692227d7798be6ad0f7dbdb57b984ce31c6a1a24447d8547bad7a82c27aadca0e6953aca683b2679e471e03b1985971790acd478da453339e656a01379158374ca1c965087e01359340742cdee310ef099a399698f2fc7c36a1b4e955905084e271fa4f74a05e4e4fae387ce52c447b3d70cd76b035a692ba99e1fc2befc88c5708721da67904607e87f049f6014220d9996516b94b0dd69b1e531d39e9c3c607b9a0fd69d6f933180fa798da3b0ab5f0f120f834377e1da614e179de5fc51d6e2d6780e076030cd5b76e872da643f6aabdf5d50fb89925d24bf9096ab7bee9d465265088a20ca3ceed310b7d6b907014832b74c47e9ed34f6c17a24206529ad015b057da21a27437a294e40e30f2df6abf950840e1b2c225ae6b1d8005e7d74ac26ed01d949b8fb1be500d032fc13d2be6211b98615f2459c3873c258b5412603dd9c53e6a925dd37e239f2289d97226dd7d49d31a7550167ce11a0b9a4f54994673f19add7766fedbe5d7df55ac861b3ee9054005beb98412d6fa73779e410d093b0ab5f69312195de079797b4d3d9487ff75d03ba68db0c0e72398fb89d165af22f657afd4cb987448a12a5e5d991da427b54c4867b207cbcac0720f6cb1f3e1a6076a814025041a8d694fd64f6909c28db66d1c108dc2d3d74b03ea827a1331606f7d0bd9ca01a3639d4d91b43fe7bc82f0085e3aee0edf79d5ac5b9847ddf60e1d8dc88022e5849df696bd3391deb29dd01c597825b8d117029b4051e91d93163adcab4d141dbc8fcc439864fae48116d5c24861e275ce7a888c8c281a573667dcefef4c87dd4225f6c2ec18c261e49a0bb747db1883e6d04d8e34f85ff561e9ab275dab445e59ed7df68ed37d28aebb248a208bc66711fbda57873ba1c1a58c5a0378a4d27a4485d397016b1aa7912fb4a993bbd55db6c347029d7238a697e96369c7f50afa993516df4896ca7f8bfda410fde8efad4d5f74d014055e14c2a73c5e1098210a03745005456df5c93736b0e35a4fae34fb1c52e42aca704c08b8ad504cf86539924aadcba9a45d903a398aa8180e68e0aaa0a0d4cb467813b623887c94b17d6c92a2c9795fc910a1aeb56beebe3f62a17d169741633a0249e85e5b3253be8a616636f3e1b0662d795802d11b83325b9e96d66f696e8e59f8cf020ac959b5fbc28cfded11d56ca441a3aa0b074c6433e77fbe1b204a21adeed122f71737701d29bdb5538052067a13c1fb24405ea197b8523ad9f56401c9e0e7c89e38a8fb0434e4c1cf1979ed8f8edaced33373731f54ab19412d30a04ac3cc11e0712948194de196ad5792b138c3c3438b9ba8e52a1d6247c1bcc2897be21a9689c038c6919f890f8b259c7b40618a00672f556a0b58094f451020273a0158701a9a8c0af5254c403a5be5e20c482d4b30f843a6407ca486c3a56489a962335666d1ec059e0ad9e4b9bda454fb425689fd26e639799a546323a7780179f0658b48d6bc9abdc40a3e316251dfbea60e8ebc05662bb379dce7d6f64faf5b8e0231da9b552a4d22f9192a22b5802dc48465cf178468dbf70c454bdd3b0eaa219db8f5dfe4ea696ba92553dbe69d12e0bb7d275b6ddb57cba1c492b51a32dde88996cbda43973bd3772ecfbc964cde5ec1ddc4f4600b7e76649976f43cbbf6d3f0b584517827e21f472a40a6fa65f11a9172f44f98d9852dfc0c6914204842d5fd4b40db5920ffe22191f22f1ccbf2508272fb7a2206b3e21427a0f8c872abaf074352de7cac008944b400bb4cb1b114bd83c4db10c7bb74c7471fb5c098d4134ca77006dc086f82769c31193a7e365a3770501d283412c8360cd125b3dbf6f92acbde8ef0063d9854fe55b4f9e1dfaf2adf9608c09f005c11ec805a8005f5517340e725b19a210284c18bb3bac614c7a43d85b938be80f96690de91ba1e835b1a073cd353db0404309941fb3f8082e059161294da253742d509066fb6b433d3f5fb0ef81479a655e840a2be09ec8f8e63e2a37e146ee36e19de82ca0d2de443d82e758f0781409b17147092d24a2d117dee43ddd096a4d6b6992c3f0b781f009a4e24e901182a47152ecd965a08108bf1504208c9e007381455bc920cb6f4ff87bde66bce32c63e9b932377ea0b3d885d91247e28456e28c56adc5e99b92d8467d6d35984705627a64c74703d4410dba93158202e2931961549990204102c25764b274cc9984c90b94000f9299859a142879a040da862f5c5f29d73959e2f6d0114e991790f09bc3cfc58cae0dab6353225f9dc48351921c644a0af186c093c88169662d094d49e18cca07a4e762e8adbf0acae24147fce9623c3a1338872b45e5fb37faa4e8adcb2c11fb8a0c3e093488925229d5b891a0314e270520a373345d98b91e393baa69eb9791101169376decb85c62211b888be6dae879a55f68f8ff03938a6fc18bdb4103a6ffefb1150bcbfe5d9d260d45323a2c68ec19b9d24c8f6d42b9b5676c343e9b67edf360c33d6a4ce6e0d90838eb3d981f62b7c76b9231015fff63da03188f02d7a7d17dde978f3ecb2ffdeaf5fb7111fc7266490ce1a9bf73b0df1dc4c5dd9617bd47cc5e8e440c80df6b3d0c4eb65524bb57b0dfd5b7a611c871db0b129a8023e1e9cb0409d490fa3207190755d7c14877d91cbf15fc2e569754e713479c4ac7f847400483d46475b6f2ac42961dd3a8c68ca1d0c1a976a7e7bbcb3c1d23e7a26e43960664b65bdcc6b22020dce617c9ebd96423f06543336c4632c705a4f3219042f221f435a58c12d10c50d2cf20d1adad2e060ac6e7661ae88d0267aee0665234c7ed20338b0232127cd698f2ac0faecfa982ea58ccd36e6276c0281649c9ea3b6034532ff849f474c0e0e163e484cf1169df9793fb15e4423ceca744972087cc654b2da675eb3e7cbe65305229130f5e9a80e3071a1ef329e0f28746fc22e1fe17853f84c68199cb83b80b0c8621249ce43bb67d886e371d307f5c0a6efa6f71319e249b1fc14024818aadb2c93725d97a5dd2def6cbd97db0f156c1b0f2293122603ff01612ccf5363803648f32f582bdc7d0649d7055c4ca512912acf59b682a50b495bd8c92b70aa18689753383dd076ed0689dec9c93fd3e5ed98036596682baa3245057c5930a0a22431895d68ca267b2216b0611601b66db8c442aff101ae8f94116ee5a2bfed1536677a236572dce950b3a34369f1ab7e0edb42eacd2bb9ca2fd7bd76943a4d533631735238103d9c908b99e07d02e6c12d7eda48529a60e90bed0d4468ee43e776d12e605beef7da9521d95f59d6a2b1a17567f13d952dbd589fa7e154d99e52e8ebc97d32f86b42b73abba2de9991e69f413fc79b2d924e69fa422373ef11652826f877bc1063300a202fe298d8d2b0f6f6d8502bb76ef3e4ca360384949c32cf4daabb78eed386a6012845a7cc61cbe437f327332d410d761746721a4e19b99b76d46bdf424696867dbe5b41605a9e731ce361169368cd120a67066d2030446aced4df4c8bf124864b276632a74be6c41a5d911239562804107db447a839a6cc6edf372ba806db99d76c48138546c10ced86cad58d84fc6e2a6fe44aef0dfbc76043b3b42f09177fc2be3493298a833b2ee1ee393b06374652648e819f048a7e6317e287109b39cd300b16fdb58b0e2c3184757c1957a4eb2cc343b9921baa97977969b76e5963dd6a857ba760496ab8988d2cde467ad9c8861e67ac0a7d54818bce3afa8415401a83b028a415260cc9c0ab04da6f4c65134a1df725ed0781824b8b743279145cf31134a130d52fbb9bdfadf92da1530d41dc1796a82d3cb56a78ad18ed0dbffce80b13bcfa409ae644ea8a5b3ca36b8dd547b594385e3e43549ba91ee97df26add4837329f50be470a6a8f77d005399ea7419353dddd42f3b822cbb24ee4161702b8b61823914d3f9504c4d8297e16351a4cb806246ad2cf2f802e16248ad300f12852848021b63ca4a9f23d03a343fe54fc3b5564836cf5aa9d92dd2dd90f4c7c776b6cd147f3994346d28a9140e29fe1c41481e6176d71325804ef4c2bb82ef1b3356a4d1b4a5e4824e71f53adc726447721f7313dd921c47faff7219ba86b315ac23f0e905ac6799ad3a2b6fce2182a6cc7a0efb20ddd502963c7966c11ec3490a3f173a3362d6aa21b5f92c422b6c4c44eb61d4b7a0fc3ee721203829a2ea13bf82d9e148d273088f30257335138f261431a320910b031226331e08ddb9ab5d11134c3c02830b0c3c3a182ffec75380cbe6c853c79368b4e6b8b513495468c9aa1849e317bc85260633b00f07da3bf02fdbd21a4c0c88817c5d889e99f5bd0e8f571e3fac22e7a0a5a6b3dc8d5861d8047b8b02953d0c8d980a89c8409861d7e5dc7b7ea0e50345d07df521401bdbc128786466ea44664aa570c089ca2595b27eb0a3b9665c1635161a220b06a599f30555f04263534a2f980d86a430902aa1db4ad19e5d2925b208202f8967f188b62daa204c6ec656a69bed229262f7131aeb879ad6b2aa6cc2ae0558bc262da4660f9afb7cb0ec71cd9665669e0284cb3bc340d40dcae24e3c832fa40de7c5cc7b22492056e757c092cebc7df2e21d9b89cc8223b398128711dc9b4600ed28e21e6ac04f07d196cdb03543be25964292cd5982ef2a31e25ccb0e5a3f8beb23264251ee9696017bf62a17e7fd302f26a908cf830455f1a12db77df8fbe451bbe339c1f6917c53552e554fa60ef794eafd97616480b9c8824c22e573b0370c71e2a1d9f6fa6c900c49a10c70d78ebc6620338c75f6390ea42e33b541b4e41565ad342b0a84a4283008f1ce17e51b29909208f46e0dfacac20c5dd29b9e014861df3754b9073d8e10751b98c149c2e1c492b0862e07f9c213bba449b2074408cf38e3df0c2800bf31265c058f4788ebbfe178567d52d19590a4b428687d379395292d18f1c0689217895d902f54292c627d99d24edb823eb8bf392ff8fd856dadc93f27a9febd1e8965fb37c7484167093a2467b2fb237d8cb65b684d3200dfad92930568fcbb9c0442838ee10a2484fe643fa506ec5a0df25fb108dc232a63ce977c7d1d1cac1cd0d390bdd283bd4ec1445830b659cc4e218fd82523a8b4481961b1c937eb21ddf571ba01a140ee6309fd44510abda59243273a33e1403a45d9a168f218fd1e2ff45e4aa8708a8dfbdadfd610172fe5696d9982dee9ca065e21a3b7fcae61329ab32ca6368c1edb0a5c2d447a4a640955c51878c00fd851ab5ad0818a460cb38f3506c7bf8e945f48d52869f22d3462313936b7bf95ac3bef97d13472b50133e606cd0487f9114468dcbde21ae899f7719263472d2718453695c7048bd3fdf302f1a9a839ef41a1fe60c68a35418064f5045bd5588a0f1633ed9310b95cc07a443fe081de2c10236897658bb21a8cd090a28068e20091bc11c546be9ba32e0c5b2105320a703092895e34fc9b1d0ba08d224c80178e9c0a0670f158c4bc83077d00fa04ac2c4180b9cc5d1e3ff21d4b3d0ade2f3e5410e3a040a5aa9acc09cc180597547c5c4f8f6ddb97a5c92483d04cf47ca22bb59b8f8a6eed5982f6283cc94bad8e80d9fcc6f49fe28bbde30565783a4c36b00dc6b0f177181045434cb12b08dfdd96968fa1f88529225397252c9671e5a2a8a4151bce89e6d5dd85b46144ea10f6fd3004a408263a5896322202daf52ff0c318883083d05246087afa1c07c6d8462a4bc8d9990c6efe7bded7a4b8d7eaa0a10236444b199bcb0fd2543493583452f8215af683a92332b01bc80c212c90208621a6dab063fb8d9a840f8a6af820378db1be5be012773114920c870c6fc30709a251f83644ce3911193e83e48dd567837e163baadcb54dd29179e7fbbc4535f5890d96c1850cc24fad18ef42af5743f7c4574c9018595f4c7da64468d8f37b3dad46e7faa931bd042911f4fcebd9c5a07289473619f655b74c6e41a496c8e25c432ecac8959543b1674a3aef60e46c7f4f48534a945533a4be8853ef1e109c4577ac636e6dc2d04f29da465da6c532e107d8d95a5821130c7d5808c6c356e41ad29714ca88148cbe74faf4e34984fe231caeb5a601f22f2307cc989285f77838f3954afff3955b3eec6b1ff07ac8b516c82b44b3f423ebbee5732c4b2da76feb1a19f84cfc4089a37e5a4b9c3df76ddf12608b33c54833e65144565a9ede0d2596dcdff3ce68055b8afeb556c80de06afd812effde790e1164d5f7b21eff16ee4ffd3fe04c5ab796e258414594f1ce8d35c559fb14229c29687b9bdadab68c34320719c84432134692bc088f03b9724a4d0837ffb40a736d85c493f0d08a6d1d096f9ca869608afc8e0e14e5d1b527b9d248c4d5e3f688c4c27168823bb1aae975a4bb82371ad9c52ee5794666bdf5042ec07c010aaef6f1d23d28fea816aeca4ed442f40751da4461b4622ee8c01b57c10c498aedb123e948911cee5cfb2a279871abf1c7a32aec94ed1180acfcaab845f710fd20da31ecb2f344848156934a329b97643f89f0dc249bb7bf01142d2ef0e5e3b656d8ef37436793e1c0bc867db18d5c280953a064423544666e8430ebb8ec305d038bd4f70f8175503d3c40c2d0eca064572dcfd0c69813d4eb247ee98e9310b740f2a096e110bd0eb7c97988c542cb2267200647b8357f7b995429bf568a2754633ed89e89b0be79693ba0cf4592a859a591be8d772449b90d9cf8dc1874945bb6ec64d7bfc74ea3930b7bae21221d79b92dc76f93f20170c146fa1af4e80e196f3270cd3fa362b014f87153c1fa55e551bd89fc106bdd24d9ab5052edb0444133d80e665746237cf7ce7d74262a6e1482234848db995403b800a5722fecb71dc853b44a20458d014d024fb08b9eedce97b9425355085b077caabc906e4a90228cdb83dd40753b896e11e1362a172543bcc6b313ab43ec345194edf0b6f78f23728f4b0bf676d81e4e0128f7a26639381f711dcd766cf4638405de656d71ae8c53d062d1b742e3a892671dc84559436d0dc4846b68fb05b6e4480b6b0f8b77a3a610dc277895c07af168b9cc20a10eb49099b2040d5b63bb39f163e0574b945382331eddb36428bd22ee9f481c2c6ada3b436969838c58dcde1a0547fcbf89b9fab554dba5f8e3c4137b5d360cba9b4027afb068021441fc8951c85e6d21502a29fc3eb51e84ac0305c3fa025f9c43fa240a6d9752640c63e6f6e8333772438d3e360ddb3cab69304b6d495b2c09b3035639b5aa96988b74de3c59916c29bb26ddc09f53490ae0f6dc13012e671729672ba151bcd41c3e044b196b20c06e1f5c569302ea6e371165515f9f940ff6cd3bd2e69aa18a2abf1fb2c29e82c6bfdcc2b41ee471e6db3f901e6af0ef3fe1fe4fb38ec29a9f096b572e9b27b7a623240fd7b63cd91a4f12ca73c17b1a21248a7a7815b12d24838995111c309470908541a1f6b016c8c093f6da88ed76bbe597d341b8f6df19388d815668907d17a4b6793df243c3e4b257a3deb511d563f973467da01ac3fd766423d22857611c779537a559a6d46ae9384199d6d9ec0c5a79ea8e3a8268012c9fc77e1172a925d9dde545356813e1e8910784e0fecb6960c304a3cc77203246dbdf3b9959c791d2851624bd55ac646b447b7fbc4ffcc20c0dbaccef335febc470f7c4c504cd72296b3159b385b516d4a4a9f364744534185cd6687c0fb343a6297eb9cce3021c1388e8f1907c8e527a7d512a21d19872fa8882daa24fb0de2a3ab2637f7ccdddc8208e87372119a3e20f734ac04e93df55484ac9e8fba0537a567fab64a9ab107bcc73b816f60e6d1050ebc9a184c40751f14a8f81e664ff9c65795bcd73ab4fd8d2dbf2f3d7589e8e7585b4b6263a3310dcbac6641afbfc6fd17fb111d0ba5d4e29d331d1351b3c35850047333a5a962c3bc7024b034eee3e3f8a0141f0c2dee8cfb29d9dad11f11c9295dae4f70f759291a0c7fe31794aec28467361c5d6298652181cf1fc6dbe24434bbf14b80be519a3e916d48c81fb6b6ea07daf73fc27c61c41a78a377d96bbe0f2edcf36c59ce645b773d0ae41dbc5dd8d3bc0a3454ccd52619ecc5e115d9e911efba3db3ed29d818c29cbd3ebe9e5fa71a5fa7e31057684ed8826defe0972cae0dbaa15154600b843dc7ae952baa47d5369a954497ce5d1508ac78d886989d755b80e508333a338cc9ac14a3e0947376b7bcc70b3cf3aa90a5690e47c1f3b8da5ce66f6b6165a46b39c56a1e42ae166fcef77cd5811f5dfa8ad9ef1439be3cb720e0014f907a563f1450dfddcae8220d50e5d029da66ecb806952901279c7c231a1a710fc1eee39bed407d174760f740b5bd933333a2a26d4bcdac51674c8db4d104d8ce6a95bd587d38611f2ed484a96110a64846f42efb166c70560dca6cc520fbc2fa344c78daf025267ad8cdf9bc4eaa65459456fd9aab190c54d92a0c8532fa59875cb8cd037e0a70b2bd6b98271a09cc26a032c876f51e514af3f56812c7c11deafa8d96eeb0b5d58828baf62d978fe738ff93b2db764bae38d8f40f29b68a73c5460f8d000c830130626914f02982a7624e68252ef4a1a5e55f301eba0ed40dacb998e301baff9aa6215444ae0e079390bf60eed444dcfccfccac66c881b2feec9869a4c09045a1ee8bf168f0b158cc50f071f7a9df037577924185037bac5298424a039f0696c367e2524c3a4535b7caa48e6f68974877e1b62a77888f96317675f51b76c48c4a2c9c94940b21ea0c662c5697cdbe90d5ad726f77a030cf418aa89c251142934ad7ddef49afa3f21f1e583aa5e4311c4df89e38175731fc94ef01e87c30fd700a8e464e77f2e30683d7b0e3fdf7c128fd16375584e5b2963e8abc61bfe8105e8b94ef53aafce1678a503188c8fe416de3aa7d2880d4300dd5569601f4f8050bfc232eb5e126bd31c24964d1ed932b53115e9933720a58f842e95463a22403d4eba2fc6cd30a829808420e37b19b91c706c963cfbc5d3c53430a83673ff3bb69a6a6412fdc68b2b340bd77db581f928b26b6c403764447ac49f88bb6bcf008d6eb369a06f140eb162057383a76b6b48c585bf85bd0a5eea57869bc2cd4a587fc925162539e8f03bbfea0c389c4dd550acb7fda39a766d7a4224110c8f48bc602e187f6e6db39be1cec889e7370c1eb166f0e04a07137cee0a8f0401aa3b0a39f5fab7ede3e847c8e61348b79ea01f4e07bca9a7cf4b97694fb05fcdc44ce3e944bf4fc7371d4881cf69ae3bec6006963dcda2fdb1803c9609c9ab44baca4917ad0ec301817220731da38a8512d94f28962b7a6a1f3195011ea9020cdeccb05c075c95b79516b07ac4323e9057fbb94f562d3d3e8a2c575fbf4189f5c88b4bab47ecc9445345271edaab7cf31093bbd9ca9f2fde84f5f47e300d6b5a10dce57eb86eb17a3547b2b915a566ec55d4658ab9dd7745d46c3415a654ae2e1a161045c6b81e57563d4cdda13a31d067a57d020da7c908c7524aeed363a07b9ebcabda3cc50ce0db18b7056d40a6fd5b14df0fbd465ae3b1ba98de50f81ab9312336589fb31d1f789593c293466a71ae28c848f3d1a451ea5fb83cf06a2c2b6a7bc7a38b7f582070c1c3c7b32cc5e98f17a0cf17f65c3645e9005627020de06e97b9a742781cc49b6dec14338e82598b5b0d79f8a407d39cc7ab6ba8d928aa673bd8f3c7a2f9dafaa87b1c34907ef12832ed1d298f2b62f87ca0969efd3c8043a20bbd64b295a60783d6260439148e6685a4b9e7c45fdbecb5117a2ae9b409e5782cc6f2239b0377b485647c3121b1a267a5b207d6885722812489c9ef7fc4c69803f9254355b183b1af50c57b9559ce9f9741552a059da689e2be743e3861485cfabd014ca5221eb995e7836b0737d87c4f43dfc44063dd6d5cb4e16c6f1d101bc0fe1c333b665110c24d340e548c483778ad265a64eb5adc0937691c1030ef3836371c956f027016d51e157c676da1c8d9f18dc75471862bfe69ef743924ea372307d27f40fa55df236dcb61b0f4bafd7471d5a267e2bde4995a8d83e3c1100fb903f9d492b33f0f7a2c686dc91ddc8f5b6bdc4fc0e353a351a6cda0374ea031c8ee0df7e97f6ec9436879b8eff9b5af8fea550655b5cfe119e470f1fdec99ee87dc4af5c42d0bf6cb03e299dbb560dcf5e8ce7664daec52151f0c29cf000aee88b8527739eee6a29be5369d233e89531f9feb1b0e14e13ca970d9907f4d01aa175ed050cc35083434d619f6f7d25807228eac8f4db66a55ae350876bc48b8a2cdd8cad0d46c5163123b323132e82c7ddddf6cf56571e242d2494ac4b46c86bc2338891ba3c4808bf4265b6410d2c44e2bbcecb9805dde36fbda45c2624ae2b116fd2d2fea63d6d8d60d6fe229b466268e273a863983f6c8538cf190894f1dc40be9e18ace1bed7bebecc09d8ee50f8409a6140f03ac08a9363052d966bb45e6cab8101cd713a37c0b154887a6262cfd567f3034798b12564cfb3fe936b13792985eb651264a1f18f7315da70a3f41981d32ac6bfee215ca1b18470c57140661133e0186a578848b7ab8309f1d89d9ac2354301a19c510237d0854d315538327569a7265640ab72ba7492ec5e3ffc897a9492cb3fbaebf635324e6cffbd8d8dec93d2e1a621e4bd99aa10e699e9951ce5c090a1c47a8560a3aad7a44e7257e950c37fc2220ec52201e97952771d13d07edf157844a91cb56a8324e12a0321adfc128cea1755274284ebac1da9c98ebcc77ec73b5c791d2f342385343298cd8c4bca037698ade5540b363af18ab833271dd54e8033cc5441386ebc6f6a5fb54b96e4dfbad25a1502d0998c11dfa88ab0ca9657013c1f32c55718fc5ff8362d69714f7a532d3d7b0b44a135725e858295c055a1a7afecdc38301ffe9ab50e9025c924391182d3000b3c4386f5b75754b03b36eab17d22fc64cf014327fdf05d9ea1ffaa8b41c24ae83e935948f0d12b8d57ac0cbcf13a1cfe0629039196e9e641f8158903f7b5a2eb6b587d2f4b874db09c22a949b7dda88a78e667b3952161d2143e286efe69e2fa5ef450c58a92da116bca7b8d94e005605f1450506480ac3f7f4dbfa57dd2f5d9c3684fba78921d82765424fe1f339c7addf9c1f5240f5570b421e4b978b2f7bc8ae452747438028d9877880e210897fbbef3820b47f6fe25521f00fbead6b27c1475fd17f4015033f3bcfd22629a9620fbbc78678d498309c4201a803bfe9c4f323a82cb40e7007fca20282a0f1557a5414bc365b8ad8128c1a14feca5d89b0898be49cff6a102c86edac060705284239def46f98edaf391ae5211c298f29bde360fa36fc2e03f9d698c325169f9ed8f86270d6dcc44d7c1fe60cc9f19a99e8d31f2d0ef81af56ce2c50ee11ede5a89f1c78786c07522a6d87aa8f3707a60fc5fdda171f7e89a20979443ac449cde866ad518aa55c4ff1c619ade3a22a6939b08dd51dd228f45e6be56881720390b58b82405d384ff4fe66366cd1a1df8703e0b6b7168e1a32400c431a71d68fe47fbba968cd06e4e383b41b7207895e1d14c900af23452a880905f7ffa518a7e9f383b115ce6f756aaf1c5da93aa517807c5f93b0cb3601a21e10cc23873bcb61fcbe5cc415329ed8f7f25c59c536da075437492a83614d3b7a1acae97671401a11342c685825a7e0fcf521a931fe91d55bbe0af1ddfc8e588be93eb8771b343472a99f665832b1dea154509d95554e2fe6ee443d5e2589583a31f1c92c398295b9cbb7a94c3fb012832faa7b08eaa40a900d1524c243e323af07c82028279cea96814338943c6691c3b09e86aa0f1fb587be24d2a085c2c94fd8839f82b85d0ce4dffe1569e0f7acf18e7267478fe5c59f489a1af364fb7a2d10a647e28a8e6fd1298240d4aed6aa548cd8855a3e9f03dd7ae5760d8ca4c2763ea680435c145acdda8202ebec79f39a27c350aa557b970cb7ceedbb1472340aee53f1f27ce2e5859a24901b09341f7b91034b9a1389c96021fc2a3e30beb3edbff5dc1087b0050344cf43976829389dbf2e4f6663cd5c16f234a6a7547a266f2932919e2d9f6a10e278f204284228388cae631c93ff295aa6c52450185e2d1259473b6444edac497c627d831ba8a9c29aee662950db1031567222102e8dd7e82a47cdc77a23c96d1581e76c17d59d66a3a7a1a067a60829cc35be55d10fa06d5ae10daf44a4d8f0722bc43ef2ffd31a0176bbc370471e6ace9b00512501b3b34c8fb9ba44b289351cc7f07b891054cc8f493d186e097b85b1a7e0538dff95bf68f3abede879925a01c5ddcc58e388fbceac5df40233dfb071ac787ab834da978f284d7275328bcc10a32e41132800b138930f0d4359f83f1c645d195590bfdcec87313182713b2ddc5242f5abd5845ec0ccc422037c901f8a3239f73f2ddcbb7e847480640030d998153434b1fb7c7cc2f788e99104fdbf0e3b1d49daf1640fdfd351cae53404619d30cdeb7587bc55bccd00fc5f661e295aa08b1ba09882368c1edd88fa4138a4bdfac195d734f20d2d388090e9938846823426140cbdc588f75b049ab4982c3b5734810475d874d3a4390bee0a571223b5cecbbf0b1ebe95a5544462d90f1a4c13e7799c7dca2eef2f69ea299a4f47c8f1a53b77dc07e385655d2f16102cd5f2a2411a1a30dd1c298974e48af674a2523b054a41d36069ee36807b0288dd7b231a14687859c73abba28bd50aff3e54cf921807802ecfd40f3cbeb45785eae46dc02e381d3397c26173a07cb4788ac141050d189f793a2d143368a3b9d7299a4a72111d2c4197e28a1473d2f386700d17ab26356c552396b2281dae6379717d26e2de117d169b0f07699d595aee9b303200429f10c15ffc9ddeab9dbbe15d037ee9d06767d10af8a640173ae58599d2a6bf9d53d00e68adaba897a1c886435e722412af1b92e736e75977e60369dd39c6023a2edfd7cc28f8a918a27ad2202d10d7579c2447877a89b7f4ac7d08433f916eaee26f8a30c289fc6162db19fbe7bb94dfe9eeaff6137a24c940175cb451308a855a2d4e1d1b0b0bc7861f8c890062f3695c40eb717bf586b96a8d1378c92a76f52346f006d2ea44e4b40a9651467386dc032b8162db9fe38d685b36b821f97c16df6ca1d98cdc6921727a3077d7c8bd2b619b4bd3e673f491ad15c4e2153aacb4651b9610d930e5dd52db377b9ecd76d232e964ca1118d8f2b763af10eb4ed265ada09b546421de8fd0ef1d8b5195730352608ea5e610b37cf980e984243b53f11222930d02271c770d794c40371464e0bb29aa7d9d6c504c26aec42f0ecc04bc6b270dd1a0c106c57f1c644bf11c94d5972d977002c7391194dacc90b0bda4ab855d396a5d2f23ece741f615ea4cd7e0cc3c04b10158e1f33d2c32cf8938ff4418ed43d0cb971ee95b89a0092dbc1c93417ab208986a1d013ed1c5fef46516f4d2be3db4afd5edb07230b0c82ac345e2cb5a1f55770180975cc278cf11f22396d28d933444476b8caa2a4f1bbce68d6486691380f3190f1e0ea7d7041da4eea571e76900afe537f3946dea6c2996386bbf830f6b6d37a0728824860802ad07f4d5993820df48275e714284b85225091f5132f290030aded2b6c8071ad206b07b10ed41c427c88b64d8341a4e7ad03a0ad107699ee4566b34e28c5a0795d63c44dd24107901b9986f3ffe3c011b84320f8eb44a0f4ba67a28ea2708ccd08e55009ed8934bade6918659074661db5fb386db59dc9553db8fee320f4f68065bb5c99bd200362ff5a66d4fc8500aa641d6067c74db62afd90203c7022df49dc166ff6a8802c4f56bc435d106599e4d0c704e31ad08c9030477c82f60413512634dccc382732ff636410ca12ac4f2fdb2c7347bae8bac7040cc1540021410b3b3fc93f066493def2eae11a130b3c73e1f67e2eaa41148ca209cfc2aa2030885f5d8987dc67520d03e9f04d98b6fa43f0b47d5d25b79c3d69f58936763010c9c4d51d5508aa4b8f1eedeea24dab773ccbba9c73a27c380e158a4bad7d17b012569f24edc30d518b9d88e3213008110ff3f8252c721f1e6b0365d9ebd4e46445f27c2c4fe334214f41aa2a6d4e541e05d5121b1fd8705810d7dff1947c47c34e6c0065b883a483a99a219209a7f6fa1c7f4ad6d1858482530604e381ec31e2fbcc9fe1dbb8c18359b09374ec0486df81650b6786faf94869d4cf4ff88cf79510ffad92988710ef03a996639be1b5174744ef8b4bb81058dd6aea57bcafb65a5b174b72a63462c55144217fdac4a4d9b955faa1243c9cf98144e18f25764a4fcdfc2b7d64e65fcb24ab9627b82c2b4c945927e1918067684b2c0cf12486dd33c44d58fb882deebf9c0e7406ddbb0b0cf3250b78a3e56ca999c6ac2991e7d004f6e8649fd44b8ddfdc40093e32264cefa4097bc01661cfb44527e107b5018a049087cd06bc26467880472766c2c042d8351284e7024e07e99d812655b4a2c2cbc4941eada0de8fd46e1a675b19b0d92b29a59e2316139437c4263926cc87efed007b324e95a5d5a6e71c21f0ce8c7a27201a1c52ec4582d663821055ded918d1323d5aaa121e56f578ddf48d80d9664841a0f9da85cfd093698831d98912f05649188b935aa63d61ebd97c84795df7815818aff1623eb29db200d80343a77aef981fd9ee220ddc0769e808b1971fe7b3e2888388d9b38754edb9c43b3834c67aed0e42176aa5301317ad83a8d04bf5a11ca474ad0e5a9e7d478951e8e2f250056553dbf882c58ec2687304a4e711826b2e9083bd5931118532d63b61f5a3ff07b1d2f10b0552ccaec5353b86ac7dccb804e2ddeb05cc2b046c5799a6ecd1a1efe04a3f5ce639c713d29b64878c6c4c664c34ffa3480b3614032ecca94cf282e60504f6a25421b05d79005665d560edf1a7163e94448698e7c01fb7c4cb4b6209fc6da9d549bf7ef5910b9845ec91a79a83b4d942d018a9772bb01fb7320ed0b6f054ef38649d46f9b154cf384816a0911bc04361fd93a23a7fcf9e2e8686ac8c90c2f945a202cb98513eaabfd4cfe0ca410c0e6d2bfbc09d08b94351938fd191f5669bcddfedc494c34d5a30ec9667364c87f6d2203472973083b6c2f608c5880ae2f4c699e1e03cabdb924ec07dab979a83779b33057dfed0754d59b9a578952a6a414b5da39bed482ddf51137a6bca5b2212d61fb2793ae2928e3784f6a29290e1764d3b4b4b9952c4ad497a4410da23f152efbc7a11a43912bcab67cbca638a3fc2910e8d662a97fda6aac3a65c00071a34a387cbe89b780a429c5c4cdac3eb184791a591e730aadc2793469270c1fbf1385df47f12f922fbbcc79302563befb6f22a11a53e703c2bd4b1c028b1159d7026d0e23175ca8eefef8c8d12f2d91c79591caffbcac8bdb52c9acfcd4c650cf30a20550b54d797b39b06ca90e570fd90b3339ebfd8f937613fbd656fc80edbf50fa0941e3bbe9b6261b88257e8be6e12f78ab2e6d3afbd27e1013227a957b81d4d205ce1dadbaab6d685cfd8635e40621c839d59742838540fe44e04aab3a7bc5820103b4a07821d3da163aaca739be6ea1caa39a4b1b37ca99c5e8fbe3cef083fdfb8ed637d61160c18e971a50a070b40697246251c4aabf0ae3401b6dc9ee5491946eb7250feb96ffba389c9c7ca4ff6de7b4bb9a59449a6520bbd0b1d0c2c1eadfa5aa5dc3029632c43f3510c6e313310e610bee03803d6a1deddc72ff481c6f7eac3f8e51bf3e959ef19e5a95a4fc53da2631e0f9f1a352db62db69c3972623135a35c2834623c67ec1a6c1c5b7643e4e4c17a6ab9af5dcfb4bfd91ae3d8b6e62627a58c9376742aa594524a29a36dd5a4ddb41cd6cd8c354dd3e2269d689f148ee7a88ef81441c25bafa69428977d8b526e685bc6fec81ff3a47432cf283742b9a18d9357885478d51e9df8a6e1240c702b9691458efc48b12a6c1abedb45036fa78c6c3580916848c9550c6e188b7e6e71c3f8e54ba4f9f9c522ee41f3b5e8869c54f4edd12729292929c9a7816c0dec9c38389ea3e2c14d8bb21623e24ad79e5f31a8f1cc0c46af3f4e39abcf3a278b2a353183d100921098908441a65685ab671598d60678d51d6594b141cbad132cc940ca17232d3d8001db2fb798086d71058a2633b8f861c12d5ac325c5144d423100db9d5bfcc61a4c48e183144654ca00dbade51fa96fe7e2a701eed15e8b6e7777533636ce692ab79d5fc5a3db7796befdda8eadada539337df4545062bf3f7afcbcc509d2474f059a5762bb2134bf799ab7e3ad605f7e3c5ac52c31674c76cc1148f62a324ae233f7a06eb9794894b2daccebc73de61136048f8f6c615f1c1a9ab1a800b763110f11e4970c425590b4aadd2798db52b21424880f1f3c787cf3120ad4865b255a691d229a94797ec560e643787e3571f23caebef48b1b89f088d01ccfa4c10d99cb08d3f5573651e9428a2b404af34998970e045482d42b497d74c9300c750a674e399b7eb2e395b29fd838875f00faedd9b9cb3fa4f77ac1f5fc7a41e8f905cfaf178a1ed53a537acb2f94eff54f28573ed73c6cb225d71d59c6ee8edcf6dbe4a4f61be566f61bc651fb5be53096cedca362bf659ca5bf695cb6719afc8de3b6feade3b84e883c715d2784bb137777d318369be3db9cb5d65a67cacb66390b6779f678f427f0e439e78c93552a166b6767ce1326fd98c98c14680be3bfa878e9f1157ba701ac0484ab0fbd67a73591b3fcace2a56f927bcc4f3e9319e56bebeeee38666666e6acbb39728fee6e66a6cccc3aedce977b7477333333339f3a8ee6d451eb610df9f340dce87a19638c316a5a8c59966532289cdfea30bd922e398e31c618352dc62ccbb29e160aea8edc4bd14977eceee8e46552ddd2282871768ea7e57ababb3bcb6ca5cccc6c264c648af3e542fafa31f7a0f18b4b3808f36114f3523af56298c814975a25bfb8615c7ae9282861e106fc2506db08377a11b8a155b1cb2fca6f4981901279268610172003e91b93707f4ee9cc927b2875d1d6d0f2ecf60c2c8cd5b1613b5c6e2be1469fad8aded1968f9f9562e543fbcd59ce34c97286ca87567af69ce5cc9447e180b90b1ba3679b675f9665599665dbb66d2d8802250543dd60d862c0b87cbb6dbf4dc8c8305f69a460866f7795ec72fa764b43f7d65b6fbdf5e6e1e086eb52255951dbe4b6f3dac7c92837daaf7e3dbf2f647db751831cdfced7a68b4d05cd6f84f46b5f0af1cc73aec4bee6fc9c1643902ec5b854f3b0c72ae65d96394f733d99a6716e374dd334cd7ae7a5e0c26bcefc9b671e0f0f2747b5f3a55a25dbe3b461e39c701e3d17a456cdb6d2aa49b1a6de581fb5ea4a6f19f08ffea60ddc634620f29b3f3184e952492a2d3135c916cf2e33ddda7b532977d5cb9fd6915e7dd66ffec895936e4da15e4d9fa1fd268f9c9fb0cbfc740e9234b8f3a74c13956957ff345007f510125292d21253530c8a414391c8c8ca11339980020bd13577767888f81c41c2c17025d1cf331339dd5ed962024e4fb9544916ff8847cf02d0c24872f486183194384aa20b143882c098dc5046d211409cb181992b6c8c3db23cb161882d3f4cb1a20527be58a38833323c31268733310ce0394b1c61c4917406534a87f8e01eac5661d643ead537ac39ea189d3c54f329e621a5f3e90934873ae68d6118466fb51e56bfd54355cc4fa86d2957ddbaad9f4dc2fdfcbc3eb171cea65d23ac5c3571234e0a4b9781ccebe7c28d1110ce809947f0870333ff996093ea3358307202c0d8159960f6cd10030d58bdc17681dafa3127a057b0718e74f9b520d97a294fc92d468ef2648474ee8c34284d90ad1b23b305eaa06a876767c32a101b94d3e756dd7a58f53abdc18d7ad89762d07a60bc7255bd2b577245bf192248a5840852fa3528bd063927624cbae7169beac6886c815d7ed219b4eda57c8dc9c60d551fd9630f6184c1ce7aeb3198e21f8ce21eb251dc434a1d1c02f334873518bb213433e812699d3065edbdfe2955c6c376d359e52ae7ec0932c8882e2f2d7022e6b7c84930e0208223e8e83746e17296388c7ee3142e678963e837cb4dd597aa1d07c66d97445c768e763df3fab48ac974acfbb8297dce5a6b8a8bdde41a6e55b424d02eee9170f9e572f2d914dbf3cbc5c4739633669e1d7b7eb98afe3ebf5c421f37c0b763cb492be3c04a6d9608bf6027023b7107881b46a298d43a61aa4beb84ac4844444484adb8476465b2078dae60ab53f8875c710f2edba1db8ce8a02616e4aae58344b678344d61125a92f2ade4e44faa03a456a9ee3a21349f12ba91cc0ee63b181266e22617d7bc138992b02f462397a949e7d00d77be91ec4849bf6b6dc5381b4a3dd938476563e48614550462a523484c6847a1b9fd8f742b47523b92f610b49bd08e42bb926e7152fb92d8a40848c627dfbea964ebb25849aa5447e4aa55ed3c581197bd49750cfb5a988e79fd5aa05e3deadd14a96ebd7e3745ea12ead57a374530b7be64daef56cca3def4527235d45de1d83619e646df62b79d734e4a7b6c37247aac56f118d2afe21ecc6d958b1ed763876418ad272967d713a98c4e65d3aebbbb5117abd5462f8b9eb66d713b854c9e47abd819d543bb21fd9cb72a6e76767f967b30378df234fbfb0b57f8f8d5279b0a9cebd9bb4830ad92ce9f546a558d72c3965d6497972ebbb44ebbb5f7a652eebff507464691ff26074a9367778447aee68e5ccd5662f9e5ce4827c99574955c49e9d2884aae8c6c996729fb0dfd84f4d3e912a85b1e2405492139d42d02c82259455a9158de70bd747924919a4eee223033d7a475f6ecb35d91ccedb7c4aa5ea67c587235b72f255713f370e7a944b79fdb0df36299a75ebb7e7a71e8a917897e7a6104aa1fd2538f937e7accecf66302eef0c895f49d949452ca1db99212e8a54b20192487a44b222997689a6c9c134ad757df3206b2827dcc19736bb9625fb5e152a51baf1e87f887f5ea510806a2c3eb075e9d3948188df8ea71087e40079e625d951cc37ae0294f35c1f12600f0947bf0dd14f1c07778608decb86967d003dff1dd14d9e101f0007c4b767c2c5737f2336207139041acfa8e6c793f20001e5e10be54cada7b430fc017e64af92373f68c8158e7d3096b1d8ee9e8939f4e7eca3e15945c7e7d759e1842f56d723b3cdb0ca8bec33f684a6870c7c730b8212755a5f7699d9357322187d9ac67c40ed7b1c33bf07e52e08eaf9564f5d4ad1ebb0a3478f3edc855f5d9c6bdf11d31a8babd3abef0a66ebc063ff0706a003bf032d07accf43a3c4925e93be8ffa418b7b31ef65bca8b810597cb05a61c005e0cf54c1c2e30e5385e0cf10c98eacf00c0208ec720e6ba619bf9dadad1bc95f2ea714ab73cf07af4d5db4cebf4a78292d46f7e4373696a686c6c9ca73b85aec7c679bac6b9ebc9e13c8d6135281d8e6118d635aec34bc1055463b15abe3697da5dbeba8dd7535a555b553d8757e3b5945655bf5ed3783dd4aaea27af8daa7f50bdf3e251c4d2aaea3b352ec955f532a9a6cbf4b5c6a0dfbce803f7a8ae554f797148aeaa7be04522b9aa1d7c1149ae6a0ce21ed5ad1779e010aacb195cccf9a94b174ddf2c648b199c20bbea7e03c1922a9099d8494bd25bc97e38bcdc5c662ee7916c692ebd9164cb7647ac11edb372457d4bd96e48447ae9dcf4527204c2ddcc11a4cb9636e4394d2d028065aa6001a50769d2a179cee2069697ee236333f551bce1a5f751eb74770f0e3f1d1f3cb6047dea96faa59ea2afa0269e52cff9f9a232c3cf29bbfc3c459e35b6249e986d8f8961adb558bc9a98a19fb8b7c3b8d937978b7de4d12b9c1c223c37e5a9e797135ea260e2c3d487b70dd6dbdf9800576b7afb4d4c9090e20d971560b63c41050ce188207488c28d2eacb802642acf9ef21cb8f1c5110d5b10017d019e40030d9ea801092e690c815cf44c9af8700516196640c5880db08418826ae0c50bc478e20910896747c26e023b0aec2cb047174720f618c41e879809102c2002074b34f8f2431590896cb9610b971a42481105e478c4b3c723d92ac2c518415c6962e6062740f688245bdc022422212b6228e20c2840f698d43a9105cf1e9b2299d62933956e7b18cd3c7b14d33a22d8f9133c86894c71e967e692474e8c7ae6592fc94effd0af9bb4cac5c60ddb05446bf2d3a3520413975aa79f1deb7a66cf2cb43466161f3dd4c67c6b6234305a98222330d4ac68471a9296a42925c9a16f8d48cc875a9026a435f90e3527df9a14cd95317d674ddf5999a46cca7756f49d55c986be3dfbc980beb320373219dcf8e86146c377d684054bc69a9156e97bc9327d3799692ed24c97f963add8a3f963919820f3a135fa765ba58bacd0d645768ad645b6c8061d59d7677d647f2c501553c97c8735ac4adfce61659a4258bebfd06af9fea650e552ad7c7b1d92ad692457d1e9175aa2ef696424b3a83fc82c82f8ae4232a93a91554a9810138391c1ca5457fd59c2929630256c0943c2b854c1f21d6241dfce213644830f312223acc9b7634ebe43caf4ed1cd2a62f3ea46530d7ec3297c07c3bb5d2ce213d0a29124d6a30a8130d0614dfb44a2fd129bf54f4ed1c5229424d72d504d466cc7c489b7cffc895fc994df2a7cc5c9a6184b80875f90e6738ad84f308a9680a157df4704ef90ea7ebdb399c3f4a1f4ea01924a51889e563bb4c6ae7502a7d289724d3770d1c42f45066f1b1862dbeb938c1125d0e8572ca772889bec1501a492b422d45488848ba88e40f11946e3358c260118385cc529252145305cb77f476c955901d2212ea550bb573189b1eccff180c847208d1435ac6b7c730fc836dd4d2ed914bb492d3ab98538545b4248c4d94be7d846e1d6937a1ad902634ab7da79da7bb533349b6dad5ab38e71b5d7eba08dda2e0740d200941925692f4717edd6405376c57bbb6b8a1ac5adc700211c7534a29a594022166522a37944b1f7d9ab961377df4f946f499831bca9f8f615e3ee0a54e1154fcf4b63db25671c328f4d12b15d1e5d1ade286391f5d52d1f4b3e92ba3bbbb092e5f65e96310e9db1968f44f7459cbb2628c80aafcfcfcf8056aa0f813b6d0cbb0811aa88358d15a1ba7aff03d548138038d18c43fb08af4ac1359155dce17c3732f66e586318dbbc5c9cfb34f3141b66a2c4a11912d77d972ca29fde917aef0d82757f7a31637f66c6eec437fac06d52a6ed5b44fa400a0a37b76ca3fa4538a514ae79c33c6b845195db60ca29973d239e794585e5e1afb686a119fe7cdf32b0a2711755b27a4de38a956c5e9821ba23e2ab15528e48dce52d227a244923b6cd359c696b2878be23a90f726c8d6f34a3a164d5cbc94d2bd0ff988877b483fe2aca6e706a356b18752ba1efb88548fc713e1883e21f988e9c354f5028b1bf2118f0844e49c33cc3ecc9e316f3ebb5ca5aa951bb2e80b9766ae7d679d7557848fc0ec63c9d576138170621fcf6f3309f7413c15e6274961d572415ac5b562cce21eecdc8f7de10aaf52fd19db9ccedf09f30a291be784f188fd516822c53dcedcc8ec953681399ddaabdc4bd53ca7b21408f64341560f21f0ddca9cb9a5795800cddaec5e9b4af515771e615de23667967b80672d494c2f5bd42db511e85e9bc48d1eda782584c0463379c688ba21e7ac28f4ad2569893b52416de2527007c7c465e21f66c8a8c6cbe8c6cb7ee1655bcc977eba5e4ac7bce9a21f4fea33ca0d29100da2412f2705e21e46ad9245ad9293887b48cc8b4810fb96b8004e975c49fff949329469ba2a4041ca144acac4928c2c63a675624d92705c19e737e3942dda2bb76d587a7ed540f4edade7570d569ebb9e117058393500bd7f7b10fe21bf882d96cb2f1c983e04617b0f010e4aed13cbf5d691cee27c78e939a92a2f1d87bb281736d6cecf1e7efa4e90d691de38fcc839e79c627ef251e46263f7ec951b4ecb1e59f2375b5580cb1e77549a58ee18af1baa7c4710c4d8b3f14b2872082e5e4e887eb209c5cd6848e074741c67636363c3794d8eec723442aec713ae4725f46fe6ddeeae17daf8bd9a739e6599127a592a1e3b9a8d8d0d1ff1fce6e1ce6bd743d6250104ce9c89c3adbd57b3094f994d9629a19ff96b9e59ab695ba6f9fd42247f95502534e37c05fa27b073ce79e52a57392e73cf9cf3b80a5d257589128184fef0119706ad619b4fd46cf7e524e823099993808966e33aba13c7e5c891c3c66b74b8cd69b3e9bc14e26f276449509f755977369e6ddb969d9cbde60b51d9cbc9cfcb896bf3b865da75ed0b3de840f342d56b9e79e191cf790de73594e68173346e3d474dcd091bea37cd0b51af695f887acd372fdc7c0510dea635cdb34f7b0ea575ce79f70b69be24a8939f4ea72f4c82faee1301ca371270515ce73e2e8a6b7fab3e2439a15392d01a92b03eb619e58611088a941bc62020168f185d881d71e062e89503d22f60bb61e7befe0d7fcc3d5e4fb43cbf9e243d0a01af275f9e04d5299e5f4f7e3eb4569e5f389479fafc7ad2c413a2ff807dd6f20319f9ac4508266a8468a012638c3f31e9670003684d708965e510375ef12ac40f63d20e2d29f8f61e6ee54411f8479c1e32183ebc7cccc9e2db69d38d4a71293285905300d6c1684e4be6508a61b27ad5b98b35e4f043256d79925ebff8137f62c78e1ddb65524c1aca868897a688cf90fe11b847f449e9bc348dd9ca4a2acec266ea6c9a0cedb432c6e831bbf45adbb8ee74ea368f076b049f2228a8545d673da050dc3c78b07cec04c141a57238724c5cb9cd393b4c467ef9cd6f5ad9556b2b0f140ae3c1665e83967ebb9dadeaf881c7ab6f21f1b16a6dc5a6bd01775129968ac70ed749296dad5689e53a693b730ec8c61693f254d7b8fcd9375da57a22254b9652f250390e0a73ee2375f993ca39c7d8388e07cbc74e1014777176cc3297e50af380c6260704aebb3b4e8ec3a670e7e6e25c92ba288151790eabce59d983cba9e81eafda5797155acd373ff2b7a1bfcad99d8871c6192de7be54aba0534a19bd09482a51b838f3120c1a525c5d06aecbe5a282b90b54a247ef66ba31b121f1e7c4a4006111d33224edec44273b4e80a4c4a028c4b31384087b6f4c2e5bd14947274e82b84d312c3ae11f34df3b3bfc43c76bde19d1dc6ecf5d0f3389626688889f2a7ce841e802331071468c3153aeac006cdf34efc608779a97793797890c4fca88e20a23a42c5e2124519484153050c24b10d8484370b811c7105f80be80ed3edc62e22a82083398a832c59630603bf7dcf5f8f074acd656b9b39325c16271dc45a57076583e78689ed541f6ed18e01f536e177221177ef00d985f68f986ac2f4c71d19476b3583070179562a978ec741c3d47c5839b16e5fddd7336eb230fd5c7abfaa69742a43cb12c51a5e2c1f2b173c4a7089293c7128d93e7a383342b9e717d64ab05ce4f193839e7ed91e63a4f6f3efc83bff37624ed1d6f5c85a9ce63c955b7e39d3c2272d57daa266ee8be63ba713f969be4ca3ad5a656acebb18e65b6da8cceb96933b375720f1fad352a9807cbc7ceb55c8a312a8da03e3d237e1ca42aa6d5072c5935bd9ce8499ce768ef951baa54d6ce34b65407e1118188a7705491e663e692254bfeb162f4ed38aa0c2c89a0f5ece30f5c7ed5e0fa3035c1d74f996fc751717725305d83043294c2c84224a58a20985c896387a12ca0b8224b134f718bd540438728ccf8b0030d4d22d490a4c4501b668c81860998286209a1a12186b802f61846414d4a8051450e6800db637f9c71462c95b25796542a6bb98b4ab1543c763a8ed26a6de5ba13d2793e9c776404224db77f01aa08843904e9ed070801c8ea43d5cfae07f3d90de9df304e7a91a39452c6cfacd536b79b66ede41e9635824ab5a4b57da139765191519501589e7772b2639f624abafdcd8ba0f4fa19dcbc0eea6ab99dabb459662ff7e0b8a78851ca18633f7f2304516c1760024ea00ff864bdd597808f2e97b8d5638c9e72d9ca7c8bae010ca171034667117d741fd1837891e3a38b105d4da844e7197fd21cd4ea11aca911a4641693e4391eb43c4816311f9d47842c603eba4fb396364105499b741688ce92ab1deb799d29b98a114876edb2456f213acb158b7ea4ddcedae96ec75c2599b81dda26d407b3938eb91dbd5ba6b1a9d0aeaf45660b9853cb448ed9c9b0efa6c8f4ac3a8b47b622587dcbbc16680630c79cca5abf52afccf5c608c739839ba6d55a6bad95d65a3967df2457690b98d3efc6415565b1aaef54e7a94ea4baec7c30979d0ff5e662574211b98473e94c6e7c18a41e83374630e99837d95cf3ce87b3952557b556af6e6b6c72443a960d896f04f508d45d65d8386763f689a5646b7e3746b6162676f9877d0cbbcf71df0ddb7b53aeea3e972b0cbbc19d5f0bd3378fdb77e393b956647eb662d55972a5b21553c92b579863d8746e923d9bd898ddb25ff6143b3f567db40af3f676bc4d72566298b3f8c7f698efc856bb4df57763a4b600daef862d86c465c9d68d912cfb6e6e0af3cb9d8ffd78e40adb912b8cd52aacbf163a647197816eb7ed3536691576e3c3922bcc89c815e6d149fc6915b6c5afbdfa8db70ac3306761be83390fe644b008a43e7f738d4b5d3a506c8a064639caad76f6b07b0e51df1f120f70d355499aa75f4833bf90e6c31b2d0bdc43ba4ab64ec02b197f5e785987da2590152472553d1350902bd9df11b9926e742350ecea51492102fd11a955d287f0472dad923502394fcf23373e9108890622908c4b358cedc608d682f56e8c44d07a04298b40777c50ee7aa8730a42e297c02073773e986fb239ca533be60c4eeae398c71eb296975256efa60406ad777e63e4a6482fb9a1ce60e6fdb5d05e3ba76004b98bde791838639c25b4d70a52239b77be39833cbd75decdf41b2311ec3c829d778ea93081f8445a25bd478456c5bf9891ce39e7be1638ef9c41acdbe1bc9be9ac4d8571759e2ea279d24b6050a58123ad9220771968bf61d0ca95949e92eed255b282be5499cca6495067695d5a2f2557944a671a9d524fc996f494d24da2ac9d7b839b797b782b607db26f9336b8def9a46e705bc8dc7a04d23fcfad83350dbf4d2e03738dcb3711eb96686ebf9b2abb22d6b56f89741b825651ebddd4cfe7ca1575955c5167908eb949a81bb76997423c7369f8add2d03f3f5bc7d280557baa3fd5b8d29b646346b44b1c9ccf1143885ee54a07476474648e16e4e86e6eb140668a0d6088428d2ed600a36bdcba71bd91832b2c9801063080f1fa42f4fa62c5e538bc8a6e2d4ee3f052cfd91e442186e572b98eb8d24115621a8909542c7d6cc1cc711c6e72c122064b182a92a840fae83c767c2ce6d20b8fbc7c4dc1f47cc6f30b8b99df68b0288ebc74f62e163754edc816834c5c2e978b59eec05eb8ec72c5dd0d69e7b0a13b9da5f46b3dba2a3a2bfa4e741ee91caaacb35c7912555db264c912fbc3c4e8b1238f398f5c426712d577d21b344748286e64fe711f63c1eda4b7a81750c9810b0c37a44106c8592401440e2f2f397cf9028caff710d0b8ea63a7628c593696ad9b21a860024f32607281311c0104b25b2b7ef8a2245b4b2c1420864017f8d5051954c0ae61802ea09000fbd3b265063f5d60f002498b38c4508a40440071c4aa421303335c88706a00d96f16e51b5b85819d350aeeee86e1466ff9eaeeeef8fd85e14f11b9cd089a29ac88f9769ad8c59ee8b20930b3e3a2b8edfcb2b285a49452ee684f2600e1c3255109e998981b9f5f39343db78a6b95f42c2e87d66ab9482cb5b05b742f51f60a0eed4720edfa373e9c0e45ca18364c8d1bdabfdcaca718a5b829d54eeb44c7f11c1e1ebf666ee672dbdafe72a3e7787e59f9c2c505e3e586975f56b678dac50d1df0d10a16df3dbd6c518c9ae797152b36d850609e5309b3945180919f6d1510b7bd82b9d185c824760bb1714ec864f813d27f9f38fae8231491ddd383c38fac61d9eed33af123cd91135e524d08818413354e54f9e845625f2a3e7a5bf6389be33ccd31d205f77af41d688c8172460c42445534b1e202a59f25ba7c01466771eb041cb4f0e1066198015305187d875b1a18830651194414892106185d3626c48dbf3db9fed1eb1437745ef100acecc18067c79962ae4ce2860ef8d8bdc316725c591e60a8cba57c87c5a170aa17eea8d520e3fa00e3ce1994b6c0e20637d65a8bc69d33f8f072ad0d57b829c0f0a69f36b583c44b6fad4dfdf42e3f3f7b9612a98830a44c92a1c4f232a8572d3ba8e8a574f2528a1a1fca201d602885baf4aaa574961e7619251a0f1bcc52d1930f3b0c0d1836131217a42e4d8d05f3b0b5f49493874dd445397cd8461b187615a20e22ea212bfd63a5816424534605663e8c666ac0b05d3f61827a2583c060d182840a3e8c481d8061e462825cb59465a48c4e22100f6624c8dde448afa4949209263ee4250b861ca67bd51eee643cceb42628e5d2fc968a58c153ea07e87a28996ec5a6293dc5af9145133ea03144c41a5b300c769872461958b4d10232b8227410f3ad0eaa5f94f26107751359e50730b62fc11b4d426b8841841458980b28d01023882d3394e1014bc4865c2ed70b559b32a44161e3d2e98888d7cf2ee0f43be5889f44c0f0d30de0338021f714e5050641419eb2162edcc50bca61bc0f59cc10484f7d52b7673cf5d40f4d4fdd81d8f2d4553b3cf59d209478ea3c41e0e0a913197ac153f7116288a77e4488369e3a92156cf1d44d18c288a7beea7a6853bf752b5b263861c5171b663003284980f6470d41c4e0850a80b090016dbcf2f607a6b7aeea7a6c0d60c8a1429c90c7d71bc0d0c7d7205f598b071f32971f9a7cf559dd3af9ea29157c75ef61065f5de54395afceaae1abf3e8f0f52594c6572f40d75331ac879fc79c005d0fe6676297a229da4f23a6065bb626d860fb3c6a1d269a43336802d97c5118df2e9b5ae701df2e91dae551d196a1d661299ecba09203248e86bcb0e20688250a173f5af490c64f0d60cd1725c1fd51fc9397174e80d0210a1e76004bf0d28516519e5451640436e617537acca7c57c005d0fe673cea22a7e7a4eadb5d65a6bad2e80aea7ca90f574e7e953b7d46f4c41911045403cf50f090989314fe34fe35ed74383440dba0420c104ebab7bd753ed85c053249078ea20743d9488480a0efee4270f40d773aa2f444143075f519b5c2ed70bb44a0913058c2f635e5e4c41c24b03c2e0610c144be400694cb4325952b6bcf5214a0a158f617ea5d0f09803a0ebc152d3edbc428aeba7e3743dd343ee09580486393ea6cd818da77ea14001c58a7f4159234a114ffda6eba193916460c60b4a4c0cd5e00d2033e0808d34b458630730a0c8418dafbea3eba9fe23c677def9075d4f07870aba0c7152a435aa60050af8eaa9aea7524a29750fba1e6a02d311afe77c72de41d7c3c17144124cec5046107050c91287164cac9469a38aa62eb28ca9e109592390cbe58a816660df16e282c68006416990d587ace508293d141187115f88889eba8ae88da7bec3821e9e3a0f0bd078ea3aba1e8ad4b5d68af43509a97a17c313153429630666c400560234b1c60c636658b2c1126075e2abfb1a5f9da708325f8b10f3d5515d4f5d2282c4c3d06f3e37b7e97ab6333b40a16122c4133e80f102cc144cb06048146ad01064c38f4b8858251ec93a77b872b2e1c76583866c9c605bebf08b871cbe7d3a691d1ad9622f4da61823c5c9116d6c01db67906cb57e9021c90d239a583103b6cfa1d6894db44e51eb184918c0f669656251922d3e0ac2f29c739ea3ebe1ec7c66b752d3f5d0cd79072e7ef3dbf56c1683820b95329478838a9f2f3e66bc1086061a7478f2068831f1d80e583ce6345d0fb6e3adf30e42bcf553d763ad16d5e6439caf3e80d5af0e5f3d1546071c7cf5aeeba99efd743bfd4e4f4d1d6ef8e95cd7335da55a628dd7ba1e4d8922ec1266c4860d13218ade503223e88c1131806de40b2d63baf0e10c3784e212958fe85c8206356c668720cad8d246161bb6d031e3a7c950123ee420c9684ad687a825acfc5ce2e7a76b5dcf4cd110e7290b40ea3789a79e1a63c4e5a9675d0ff59a80ea56004ac4f098d7ae07b34d7ad5de2409283ef39939d6f564666ed8414d8ef8aeed4dd4de46ed6d45b6a2eb483652eb706926177c7b8b699deedbbba9bdcbb85a87937e9cb40e050a6a2964a575f8958411df2eb1b4cefd6692c313549688c286112f68029bc78c09628c2621b480c108b05d26b54e54e2dba592042397a4646a2966fec816ebcb5b9fd56df55b63125f5520f401f1a775f825b6719873d8a4d4e3fbf4ada34b6a3a21fd4a58c87219f3ec96dbee53e4886c6d2e7ff358f0945cae8940da95a3da6c2f7d43719867b1dce8e21fda071d65a155d2ebdfbcf82357d2b12ebab887f4f8e46abfa455d25968d5a5403764324bf8478fc75c49ebdc97ce02b683c8088c3446a55eeb0db49a1293a241ea6627c8ce183bd8d8b1c68ecbdca9eba198a7cab0e9d356c7343199c4e98464181bb371381b01ccebc6496ee34e2107b0aebbd8c98e7aa79009115fa7639403aae1e262bfad13a56739dad2512460328e8de6e05be8284c32a55e8839877da8efc62ada6bd886c93085141a860106b7af054d73bb650d50c90348d7e16a8e71b11b822d99ee82066a8eea2640df7aec4ae0ae88e61a8d82696eb9986d4180fd429fcf342ff479ebf2a232dbf5448a518f9a8db2713c658fe770f93df43b63a45e8ae334efa61ddc642784c710c25b8420e0319f18e6b51bc27a5bb18f4e0bc346a3dce9d229943ba3752cda8b02bac3c5dc8742b94442ebd337daf1acb556e766d75329cd6e4840647a750930094a00c2d7ef048b592fdc3c89f6d6b7da4da0fee6b51bc26434c1039711988c267878c1d7adbae63cb292a0bdfdb48ff38ca751fd1db9af39743ab135e0a6bd872a399eb2fb0093261eeab702eb75ce39b121ac578f9d0498b03c40c85aa4207a25f231ffc2aef2d3ab3704131a70b9810c68200d8950bd3b0930f1008b50db89c7be13302701f695000429a4730e5dd24cbaa550c79376be6ddbe6ddf56c9dc7b58a6e6eebcdf685914ab9276c3ea1dc13ac87d36bb87d6194de9218e219904ae72e68a0ec09d03f797725f0007ec0858c2678e042461341a0a4512894bbb9f4f6c86d5cb83976eabed0e7b9ef041bd6eb39548a77f2a2e8ed269d2d3dd228e9042c095f670fcf963e3d7ac38d5d04343a84f5b5ca48e5fc6e1ab4e319fdbaa452de56719dde7146d9915023758ac3a5d8c7a16877fb168770abfae364790a2ff01875ae5591e270a38e5cdab67872a3571ee355f08e9bfa9d5d8f6c76fa8e6d94a3727624509f4e71b8d52790f97c0dfba78d08f8b0c62108d8f2758caf9f9350a334639b7e23e589499eee689d0a61ee91d9cc0ba733f99e9877bf1c39257a94878b39679d629e20406007c8020ef0801f07733cc0c6010c04001c02e6ec02e096cb15d6393b0e001888e6ec20b04e45b9f593c7d83c47474742996f586739cea31cc66df1372a7fd34e96db4ecea753cfc9378eb31ee72e5b48fce47cf2a80f377ae71991c3ad97e21f616c7a65c338daf5e4787e8151c46f93abb9ce791d4d8d2391adf82357985b7b7f8cc8e19bbc3244da2ab68cdbbc79050ca18f39bc085ecf881c6ee3fd386863f3b1ccf1c524b932d26a2724be1139fab72df32216dce394f2f0eaf896e0c058c17327a4b9cda371acfb68bcc845896bbde3366f56e185ebb913c242d7715efcaedb3edac3b53ebb14e2739105dce6c5a2566144dca306372679188984f4db2cd73a0a65bfe892361e83a87ecee3cf11dacfbc7ed411378c2e5713ba7131a95598a3bcd8a55798db78dc0c0823982654369fc1c11cce93c288a8514717c41030af5ee4927159ff16bf981423532a7531cc7b098e4831a91980b98d48adc27cc39c2ad172d3b8cd9b545c7e29353dbfc090f2fc9cc6c5ae67fb2813d7ba8d3f8d05f7c02212f7c09c2281611e7f9c388adb52fc23c53d22977934e8f20b0cd28771cc63ce6f08e12f5ee3386b238659cfea66bdcc3347c56dfb4213bcf6d5ecbb4d5c7b5006e734c7dbc1c7683daec27a7b53e6d445c995b78ef5ee4961ba5c515e89e6f1bb9b80079e398fb41fcee73bd817b25cc54b4929b8eddc128a7f44d7ff804a824a82b216854a92049504d5d26e3649924f82a2417d679323439db2cc2687bda713ea2f4d1214eab7930d8f24417da625b1a72fb4dd1726b9495034a8af41322937b94929ef26a5f44d06d1d236e7715adcddd75a9b04f52b8010e455619067577d108b3abda1846624589bb9e6d1cead671ee699b7d7524acd25739f04983c96655f5813669e7d219257423fded0bf73ce0b913ca70365b3b9a6792192d7dc7aa1bfa571ceb22cdb5cebdc7a9c0e94cdc9e6c03a8fe60b6bbc9df3fc737861cdadf19450fb79a1ffe69ba5f1f09e429e974efd33e7692991f4e62c3be73e9a4f9e3e0e91bcb4dcf785a994b51ee69ba78492501df3eb9d70ef17669eb523b14cdc64e5263789c4f3dd6cdef9c9a5fb77b37d44b8935898f2f67bfa6e30bfe1dc7a76c359d7fc06db36977673e99a6b5e78a3494d4a2e0a9a4f0945c284855c86390929b573639df3fe6e36b72efde475dfcde637986b2e6fb09bcd6a5f9882ff0a3b9e044c32cfbcf026735e7a3ebac93e22fcbcc4ec3558bcbe48f1e2cb0b552ef686136c88716d1a5aca48e26661b871312533ae4d5aba16298b9b556174b128ba898b35a144916c72ed14335dfc40832e52b044172fbce1c699ab3dbfbc8c2153c61a5e6650c6adcf2f2f4a5e92d85e2f477c9872d1d84d3bd92b44b6b5d150e705071bad891fce8beb9429e1dac870568932da18343589a14c061b964492edd2020f2813aefa44379530c2724823263a844d2f713471d011593b4c1cf58a6d7c75719dee1241bd625be61583241b197859ab7165053959eecdf3eb0a0d2fb835cf2f29da0873eff34b0a325a70699e5f5248d7e59e5f52bc008e6bf3fc92228d97142d838b7a7e49a103180324d7b7cf570c5ef87e5d91c10b066686b62f36dbd581b2c9216bfa368d7f2a65ed17fbd4715b6b595b59897c8dd129592fdb763bcbd595dcad036593a3e6d29c3a6ed3b20e4e2b283666d63ed28fd1931f5598af843ed72a7bc3cee4f9c3aa8f5cb1b78f6ecf7b29a5fc543a9efe6d1959d2d3fc8dab65d25d55b0694fdcd834eb69d9fa33538f1400e14fa0ec126b617245273639fa44125baf354ccec0d862cb8cc63b62658bc6ad0f919bfec86d956b2b6dd454d44ab3ad891a0bcfce4eb6351116ad8b342c5bb6d1266a2c5a5b6923adb1d4b06f908447c02d1a6f9a6f09e38097b87163fbd6755d4fe69d3d71430df40d342586d0de457064e16904ecd36cd31a684a6d29750a9d426903f5941eeaa09e42bf1377ea7a363f7134fdd338fc90ce6d5a2dd34eb6e6d8a75ac646331d74f0d3b7f8fdaca732edc4f64fbb6c3ba1b99cd56868686e13531b72890c4ba55a2213860cb744a689894ca79db225324d4c6468ae46c3d1743dd3694e35dc4eb72212924f6f9a731e1ee0391a1969e1c1f2b16220118c8a7f9c8cb4788a55d5e3905ae7b20ac5a503a3e384cf747ce65bec325a4f1349b62e98ce9552499d83f9ee004de6db3d7d1c464de38cb454e940e336232d4756b4645f0d57d3f5645ed30de9b79e8323ca49a2d2d86cd31a482c8a21b4b3d3502f6315e69ad7b10af32d06b54e0dab740875107e17011d1c0aad6ad73c25ad6aef92c420d9aae15854dd23c2fee3c0a98b80f7d4371ad991323dd92f720fccb31c9c96d9aa754d801bb468d1e5719eb568e1c46f3449f2ca1d1984474606b2825d212504f30f7885c32d1ef363958c1fed726353a48de1f8304e28377ef4f9717372b93040e3431bbd7011e6a34f2b3a54098303339050238b1184e1c318176c79614c1a710bd00396a84992f28b1b9da373120c5e4fa9a76647ed9c13063bfc9ca91b2ed878e90d002eaef8f6489f98b3861cd14a0b46f779f291bbb0122f45308c4d64f0718b31c61859d1c1307679713185d6aefef9d824c63863d2189ff9ccfca88fdeda2eb3534c0bc05a9376f8eab5eba9292828a50e78ba85d2d32d7ca0ce61a654925dc821a40cf261909749a0f45bc44b4f7131f3d23d8b2e2f5d75c4cb971659bca08b8f60cca23593f2a389e590058e9fd3adc521eef0f3a7571b454a31af205e483f1d4b01cdf9110b30e4421c2c9840c04fb7582cb980053f9d42b9e14c7d7455eb4c9f36cc1c1e3f7d04612d5cb6802177f9e9d30670f2f490c9f0f890cde80060462752662c72c1740e239616547981d3afab5851fcf41d1e9f2d56fc74242d68e3a7a3e0fae92c68b9c165450a7eaa00daf21a226a1d7e5961e6e7155f7e7ab422c4cfe8c59dd3cec9d91748f9f6d6890f60e2a78bf0d3914c4f828212fe313f8ba40617a66da8d40bf7b549ce2a6433020000000003150030301410088542b1509808c3f40314000e839e506a4a190ad424c9711442c61843880104008008888cd0cc560000106300b479d21305646feb36a226480bd58950b0b93287eb086ea7bc5e5392f202ab88e9a9066bc6dc5c46f8e735cdac8d156924cb73370ed34c50faa4d1a3407226f941a47d0c4fd9b2ef3a633a3f04a52dd00ee7c8af34aa95cd98b6b960d8c18a1ebd06ac77cfba8eed1899a4979d98496749b66b952d0e60de04ce18951821f29effb67f59d70617b3abea6c91be4907ae7966cab403307f735c389912ccb0a45a623f82edeb7863d3ca1ca987ac33aea6bae33b71235dab1be4358a5be977fab7582e68836a1ce0f0d5277e67f165563fa8a8db7f7f63d8ce61bd3e161e2b6f27ba6a992c5b5aeb69f30a815a60c704810a23ad63a10c712a1c4ef99403639d7140a775320e45f53995860ecfb0cc96d1303c02e24ab1c56716f74bf70b1b305fdda771d2fed5009b013026795187111dd1f5ea7274a47ec3aeb06946c39d86cd58ccd8f06c909920e23821cd52c85ef61de4d88b6eb73f54316331004d646da1686984c64f54ce1ecd8a9d2c9e8a13eb86d2f0c60079e70ff30feb050c55f0ea46b6625dcefdb83c060ce57ede3606313b23573190ed3264933119eabea3b99f82b2dac5a8e82ea834a3ff428c8e82e6cd367c0d24625183d7a1b4e503b42d4220ccdd299a702e7d8334cd14dd0298055934e32ac50d7a2abf8a6a005dfd48056e2c04f8135933a2a3e13203a2dd80e867ea4867965108c494d4fe00c891937ba2be8d5dc4b5e69a8cacd8f422ea6d12c894459a04182a810754611d9d51eefaf8fd045181f130f60d43215ccd18cd3bcb5234537c7b643705d127df3d07afaf498edfeea2f2371abeca91c3120e1ef59f2b3591f084721febe2acefc755513ac2871957beead9109badae7663402e7ff498106ef4ae2d2f18044b8017b4c59166a7d4fb69b10fb8ee3583e3449041d29e7eeb7aafd7c8afc0ac01190843fd2e5fa392988d75a94facdf83fe3a04ee14b11ef4e420afb56a724a4d5a8202b1a62673037b3d65c2294826f289f171eefe520935b913b1f84492982f42c521243fcc1629af52bd25d1dbae2d0be73952ddf9acccd5a7b67807b13a30a38dfe020a475ffe49a007ac0b6b1adc7f5549195448eb5465596d7f2acad10f908f98b264830d8f21498dd58b093b504f6882f4c4b77bfd0de53a9ef8a4350dd7d16c7f3138a0eb79235c984fb7ab6bb9cf560707704c3b4cd3d2c9dfe335c42fe84e82d9634ba842598895268b2c89e0a6be08027e83af7a660c10c12bee12388e04830dd347d96fcd49e6b49d8b993c8ccaad81da0e50f8e976b80376cc4c43ac307e5fa145b884ac868bdcfa4485cfd725acf933818b64193b1d50924688dc6eb1ea7f3c04c4aa0aa97bf49de9bd404b330818a0876b2a682e4fa26d70eda4f0d3d5dc20fab9300fd584e54ee043fd5a64a58cfdb9649dc423e6266fd49f693341fe591d41a14bed4edca95d32fca263c3d34a5e4f8a91c73779f8949bbd73c084a4fba25ae9f5a09d520b5166567450352c789c53f297823b81c5d01c75a30b0777d9cadcb25ddcd58ed4ad8cde13c687901ab836aa43a4e2650e28afa7077abf02c00d55a5987b00811d44b6d7aa3c2deae7d5fbf04b24a904ec8a6cd034708caa9400fe37c8a566d504fcb380c66a17a67029610264fc0dcec04e7d55240698922359d447188d1f6d57cb002b7fa5a0999ae256c997eda039fcab11e9883290d43f794cbb55d823fbf4062bcbbb015bd646ea369741d4f5ac9e3aca9533e70b7c580010b811413c27e97a4af79ddf66448d92fff37c621d738e83300bc85c909f999bf2b53577e1f25f5e882f88f7bf543861fe0dfd25a40ad1fc158671d53f7fc36a9f2746815cad33c172930e22e38300c07a36ba1d6882491f8d86dbee57529ad22ff8da437969c895a3e34dfcf47349e4ee624a2bb87c311d214f0a4c62e63a85a68da83d9edf8308a3bad2207398d00115b9aadd6179f9418006bb88b046f488eda0d307767b3c361836014d7e7e11a40c7f6bfe37e856cb73bfe66e5e21829de711eb9ec8d4ab43a85cd000c3206825a8c919ff94b572824246413a2d26ad4a06c02b8333b133ea7ec8141603e5ae39a0c839ccc70fdec0c63591f0cc827569f46faadb5de648917a86b7305054fcdd3862689a6c4472db4b8c15d5e71025ac1fa8d8bd81f9260a63da9e4c505136d5898eb68828cc0c4e726911dddbfb2f87ca73e6198ce0fd28d15064771736e65f5bd752617846b38226ff312d50ef4c63efc2f0ce9c309a1bcd9f250e4f3670ade80f1715b16eb89f49fbb67c1ab8fb0bfecf48d0cfd6763c4a69f151d5d8f510e06e2e4ff1d52bc54ef71b4e61dfda51cdc56ed35c613ec596fb92279319e3b12bc8bb2ab7f787b1bd0716224e54d697a20c4213ab57d8c69ae3bb6693968cdbb874ffa1dae6d5a7124719e184dda75d072e557fd4af14b55411deacd663b669e7ba2f133b22b7d4a140e4cbf77da20b33ffd71a5002578efaa2a95ab6b2d9aa5329335fc4dcdf178a9a466d1ed5515c84f3d7c41ec13b913e47d35cf21b38e781fc75e38ca3101c99de95ef5694e2f6b2b7f5f074a65828708723b26300a3d490fed17d91e855deb76b5f90dcc06d7b45377cd1480d9ddbc772b0b37319072157ca197079b5f795a7a7d330908bf074b6a90f3ccca65c619264a620d092b7a60aff7b249c4800828bbab8ad84090060d898740df46b460393c322bc4d7e22c80eb78989cd6a09a5d0c86b29e19e190f9003af29fd571fc6c183666fbe65ef055c374156b109443aa5834f898cc1bf4c0e1cd41933bc2274a8bb9c82f365c81d7b9d84b1128c880f80abddaf192d77dfba564ca9c144d9923fb72745e20e0803bc4a20a246b094731913320c890930bb4d5a20c48e96e510cc5ab71fb45a006569ec1ba7fd78ab85880e47110d27b771553981d4b12c08ff17858567543bf2a053249aed68454fcac4278892955fb647edb429b2b2b932151ddfda736a5186083ae76ea0d596ae165d161e0e86a2a0161a6f6434a4ec465856578a3ed062e4da813c72adc48756dd44a1553d647b31575e46cc28d8edef41b475085202721fd44d9fe047057261ec2c71dc9f7a7602f3c07c342eb99075113d874669204d099054d04f8c8dfd40a45690693761d87fcdb462ec5047b43a446578be8d47a1f96a784aa82073e6d5080752e1f28d3099f74c0a4deeede0201e095dc7435f32526932387a0ca120da6b7a96f0f25dc8e5853e12ced046eb8402d1d7378309d80866b5f230e3b7276cc5ec9861aee6436db26958085178b29963343dddc61a99d1da183396d3b698f1e370bb421c5034c6389561cc9d8c10b03ac1067326bdcea3e311206128fb3527463a0993936f55a0d772e093a40edba6322d524df9b9952f1003b75ec6cba7983c9b34083968ffa2e9024a5b14b74643caa00d541bf37642427881cd96547b4b7c03fdb186d35b750a08780cc80e7d4fb89e0811f3b9771a4594c28b157920fa561112ea69c61dc71e799d2c230f930c6a241ed8d8058585bb17a4eb9473fde37de629db806744750cc8dd18c40cfd558f91e40f4dddffd5d22c24cac13636f4b0ea33f5d3cd0866b9ad9d4cc2bc2a54a9a20a172ef91bd35775f4755ffff7b979124d743330d6f14140058f61c4053c7b3c29520bd39f854bc58f5d35c682dcd9c63f60bd00f891ca4e027dba917034b749dfd036d4c8c4d61b84fda2981e931bf241ef744468fd009abaf7ad86595969e50df64289e1162e1ea86b4bb8bf5372278094ef9aea16f9c772e59fd891afeafe4b978f491811e5379a71fbe8b2fdf53e6d71fb70f57dd84724c705efff117b44cbecfbfd39fc3456a25e0aa0f9ec908c1f868030137cd2d547db3eac2f0c2b254cdd1a0864ccf1986860b0e42a40f570902ad2077ea5385550aaa7e3501d90be63259f602ec1703e08656f4b944d856ee62bed34dd404f12dfc3f382fca8434025437b6dd730f0747625cf0f57f60041e65f065928661ff7141c3fde1221d88ccc23278f09c1f43b432536e557d27b6fe8ecb292e8d10c471f10c9f547c917415cc0854ca5fd9b44525a4e453c9ec105927c8da9fe027a41c6e340ac0874e0959051096504552b7bb5b2e4aabace7841f2de925e83f8cf8d7a4325d0e071465a31c61a36d6551e43c4bb75439b5d7226ff5f35619060de50fc378f12ba4ef606cecc116db33e6b21e60d1afb70474e6ce6264ff2297485445317adf4c045c19d45f9ee9b327db8401d31882444878b0975e6e8903083347145b073130703d052e0ae66094c88b44156a99331ad8828cb9dd86fa97a17a3a9eb634fd2596ee362ea35f534900be16127d834caf63b4b7625db3726ce8d7fe2e6e1b345c6b87298220af7fdc2089eff5dea9f550fb62785e921ffc94776d9c48c0d4b8311d2329c9c8e54634b545fc5b503f9f219e8dab1acf1f6c806b2ccc77540a89d23d6db2cb5a1b83d11d4c68669bfafc0521eb0fde58281f3847b52465296575d5567035680514afa68058dfb0f8097384f4c025c6abd6aaa1453e1a5d90a2c70f224bd5e102cc77bb8929725ab34f982cb51972ecd1d5fede98033c41081e4e0f676f68a000d7a08598c62db715b8dad12f9c3b68a57a403097eaed5d3936206682dc3074ecbab0261f8154c61edc521b6606e8f954ba786f5f420e916fa50eac7d7f50ea61c6564d3151728ebaac4351c27ca05de48bf19f527d158e8be93e198e29d175c7ddd5253a6e999d4b9badc8145082c0104fac11f71e9f6d6f37077cbf952b4692a3e9f066d7b65e86053d295de13ffb421305b0d976cd9729566198d79ce0c2b63e9d1ca5765ba935840b7ffe4a78ecb8766ab290814c9e2255191f9f589f41a36a3bf278a479d8788919dd9a18c795beedeb474b3aa557f178977db85e9453443e4755e5d126806f3a83305ba4241f7adcfc09c694ee0ce6195e3b8642e21068af18bbe1193cb7575e9eccedba3534f6fbbfc5eaf45f5a677060525fa9d8757cc02b0560eae1832b18c923425c817a6c3d7a99d633f17c887ee1cc758272662980d75acbf8def7813d460bbb4e83bc83781f72ffea18344d4db6ba1382d0a23e76d11d3cf2834055d3da230ae3255ed41e6dd15c2f6359cf97c87858fd0773624bbd350ebd08e0a1fa98d768855d570eec59d6d4c2368d1d119b2b4349490652e9a9fb6650d491326055d8fd695c6354a2b0e4926febae0561cbc9da04781a65f30c7c8481718bff93b3860765e7b60143ad26b562427286dc55a29b6c3831b3050539e0089ac7b470a0d189526e254ae0a7ca8d511cbb2d866009e714566f8bc568dde4c1d4805eff8772818e66e5725b3bf12932fef53ad7d6287f59be60ae6b91e34d94084c75a7c66c7868181f1de4d6c2d028f6131b7bd3722e4bfc26c6eb2eb6193dedb1cb4394adaf8168ffc37fe07a6cad32ab869604194ac159981ab59058a0623eb64dc6f1629bb5e36b7d8adb719879aefd0632bbd46150a4e7dc5da2a6b664d9a0a2e126b582d23e756d2c797bd1793fe1e1d3bf59ec5f2c8b253fadcb9756734cb3bd168611355fdce3984718f2ae8c1a5ed3affcd9c8aa381f73e6908f9f60f07d1883561b8fb76e9ce4122513c08cc81a0a8fc362e3cd811e4ead372fd4248c916e1dc3e8336aba896800c3e8ed1f0fe31fcd0999e2ec41b5344703ea9ea45e3db58731c6103aa161aec306ac8c6d8e0d8cbd922728ee86b1c14b1ad51485dcdb767703a49771371c148a07c2bfa82a30c1651d42379b717731f7c2483e6046ca1b8fd2cba6995eda42ceb1279872667ccc9005a2ec896138dabd5e92931813ed8159e5b36ea7871cf097ab51f9620f769b284076c53d232c6bb15db18d95dd184763e98b8905ec0ccd0df662276152bc97a7f8243148214ded7017b8fe2d2a2006ee6a7360494fa397da44cff6e809b6021478786ed379857cf0c0d2595d15b27c250b6b4f37583a0406c3ffeb32441851b29aef58a94f458423929ce255218846660c546ca64a6c9faae911be1b4533581691c0762d78a109bff2b0f31f219a2899219d03969fdd69e9dc5879fe1d053c9045b01b2641202ab53b1504e7127fab1a7aa9559559ea0165ee8023e21c72160ad7a33e766d79cc4da5ccbb9ff0206487d2980301012efde4a4dda188c5b7611a70c60241f76a8989262a5d4875798166448018493451c629d289126150338373e590a3d4a198e4ac950805d86bdb75643bc4a8594bf5d6563d22ce704a5b9548408c002a6f8a460a79129ad15ecdd58b22d1ddcf27b953a9972d1e5c967c88eb3377a3b196c08854791f4b75bf5f557330db01065126c6a57e5a31cd180c10451a3237dfd318a693ade1a44d94f9c323253ef2f582cdf3f20beff808ddaef8839e612ee6ce22c2a6630ea444fce47a63cad5dab5128ff1781b48f1870deb1f01b88de2597f3cb2e2173e4df0bbeb41d76a65f28fdc2956ada5e3520577cbd153d368b3edc3b61116009f6a26f806fa9cd1b6e8cd150a2a998333e3d307b7ee6494e648102c8e28cdf1cca3626e61d0e51c27055de42136ff03a3cca78f665f787be45772e2c0183217621563e3df352babdc29790845b89c097cab9824182e0df8b8bcd2ae14ea3d32f6a40931e3c1fa31cc0048a393c8962e5ba05825867d6c042425e91908c1a1feac3a1c578884bc9726f146f3948cdb97f536bbaaec141dd14302391e74df31beec85d9ad0829074d7a53b9ded2724bd054086ffb750b5dadb223ee062e2da91c5dafa0691879c3e85eb744b118379ae8183398990fbabbf40a71afe190aee81f4a24cdee9840678e5f22e40bfd239c5f9373c45cfea99e5ca4f7be4824b2a1f4c61186550eaec3b10639967ae2a72fd87f7eaad3c37cb49b9a085355eb546bc3a6c5060b3bec0284158cc0974378aa44956c24585a58933b985a6695bbab8d9764fb1d7a1b21158f36456d48442520213ee45f171741232ce3bea5e16ca635572e1db117f4c4bd43f432401157258173485f632204fd9be5645d202b29131aacd527ebbb948843b7695d10d7e025b7b42824e253e91b18310d71d9f4df920c706c09c54320980272d34f9d7ef44198ebc8a62abe7f0c3e8eafe7f02910b4878c2b574f8fab59772f47d2b82c3f6502babefcf9c3bcdfe2e33a04187bc0cd52b3c84cee7b397884b567d6f6d2a1e08d59149b7bff0e70c14f44b72cd86fb7a7d3ac3a9f7937ee421198be36fb142f307d9b34886947d436c8570e8d42c6d710d09c78bbc09231914f4a2cf33706c718a36b649fa199e53cadd47592b78255c6df8084c6ec06bb5b3740eb276ef10f217c30b8cf46d7753e5f3edf08284e2f03e9fd5acf46962dfdc9ac20d35fa75f0a6755f16eed332b28b09a4a605921964bfbdc036b5cfb3d2fb0aded97786fd82acf92c8da3d5f178da89025aaeec1658e71888cac0de9c0c000b5c870b3c1e8e82bc6da131d2c1981a6b7c71be781d49c8d8addc85b93cc4270aa49fdc82dfb99bc0692990b5400041586facc91f109a91256b6e05dc8c25b6a07547fb2c5b6e02046cbf5a55f0846b1a8c19ec8449311838f3609bc0ab66272fb58a1c9c88533df2f4f03cb69db65cf72f663f73e55d8b2521091a218c4710500742b2aa8d3c0c660fd70587f43f44d4b4a0fc82e195e2083711009230c425028ac11f035262226036b90779335fb75432dd70dc1b023627a74da37c4ead1d6035d86a5243d67c449d4a8089e0af839e68820172ea2fff75fe689856ed004ab92a3220f6c1329d9f6c4ebf6a3aae028a0e68a60b3db31abdfb113c309fc08f0eb4055bee4a1223646964613edf782e40d41e021aa1fe18949c937303e177acfb8caf65c675eadf4ca9a7e03ac4827e4f3dc13182b8ff2edf29ac5607d6b321581c0026943a469ea1928fa0fab0414edb206890e7e2e26a0c2042e429b25ea5f2823b3a050e495538319acda8054ca015be6153c8ea03d90c1eafd6134bc402245d5a8f77958f6f0723d35ec18e04f37b8e13010ca6e6c703fbdaadb554aea3fc1d2b0d7156907000fd5c26052bc8d3b8e27675e7056ae985336cd92187e2b6f2b7546820195d38bdeb875a7ef12048d2f202da4ceca533dce48824918939359201a12bf443edd82bebd73a018f22573406447a487ba700aea969f30081251f16d64715810cbe4e91d1f15477087babb4e1d9f89bb6572795d48752c2e0a60b479474c150d184f6669806e9f2cb806b5b72ab18d008007a43dca7180a1a14a6e9870650b39ddf129f0b103bf0f46020e707c9bc44d2e3d68216da180fc6e417b5d990097bf470fca2110c954f6da4d2ae40b9bc4d1fa47d7116becb9d807a02796e9d8a299e266836752889f2d8fa5aca7a5d64e5c1830028f6d59cc54b5d912bb7dbf8a220a2832ba9e1aa59d8c7e3af7b58602834c0bea1723dfc3db63228bbad8e25269aa30a9779eb6127c33800770ede9dc4ee1325eccf1c420a069a2e97e4485cfab4635d628e8826b2ae3e970a7504c20687ce44a102877623880a16e78de89bceff54a0ec87dd8315c4f3c23805e2d3f3f0f47dc39a881bfd72d6364336d20f41471c135d812a3b09353ed70ed304d9b393e45634859571e6dbdd0248204612a8a709e234424a1e973bd7aea8a9e14579cf640d0f35bca68e8453ca83fa0d69fd245b832a8d3e291620a94a8f0d6a9f663f4bad40e9c0f4c146b9494d3d1deabaf17b6a19f6b78225ee1611bf4a363b8831dab7987f089170596d18bcc6603e8aa0e9c78d74cd17dc214f68607efd9a76e7f88001ff1cc166db34d5d00903dc1d7e7df99a52191631f8ddc2b9385e236d5d9fae8ed171119610830379a4e178217020178d8e4cf05f984f3cb727bd5f71419b798c3bf864256789224e3552cc85db02e4640504cedcaa046836b9d0993655fd870f2449b3f7270295d47e91feb5f4509c732bc761f7889d32983258be6a358f2cd8400df6d126c99fbcf3a7d7716b4663bc8e9ac2134e97d4f4f40b32018f8a0244bc59f123c43b83497feedbc89214aab9c232a14c99879da26ec0dde5ff600215d225500aefa7a1d813dd51f7cc6d0b2b724354efdb33f8b313393c69bf844efb8b0beee600a9935d2e9a4b996af6440ff1fe672cbadcab4f81611f39d5e8b92674e6591b97f48d6909e027e3d50cf1de353901dc752b03ae7382df6cfbd0354ae82492f045eda534c7fd6207ea242079f53aad686428b1d012ddafd87ec32a8fb4fbdb3d17375980ff7be85273481e2e598e74c7f55b90c7f2c50a220ff69f4beedae95b8661afb8d8fc200b968b4708345682490fd6b0d4cfc3629c1e45debf6c864e4c19a79b78a868d9f75331a677a551189a6fc7264ea37cc4b39724c8c5120db1b0619cabb872cc1aae41e8e83171a181e56af421fe0764573bad96c4c0a606327ac6429572f4e091249eab3822623d7f0cbc6a04556165b1c7711d07bc0be37072d43929bd0b70554c17c95582d1fec3ae94f72a0d01a1963905ca67f669f6112c58555891fd33d297f410c6d0037c9d68dfdfa2f9bf7c2f0e4a3ead0bd8a508db0922ce766aa73dad1c7ade8d38ce0d839bca1f7e137fcd05437d9b4f08dc3301774576c7f0c3e109667d31bcea4462e7f85bfce2dc529845ea73023de30e948bf03cf2cea413cb6fb116d07459bc158fc65023b24f9383aa3b22c46781aa5c22ea5ddd0ef5ac3f6d043e0a502c49bc725956d709040852165ff20da38ccfa4439ec45aa360a0a9ae02eb75615ed91b6c7368841e784f6e68e184af019d2a7d02a4396bf6e87bd4aa47f4209d00aad00de3bca2a1194162616f4ebbd34706f64a8b06e572e29f0d9a34fd84dba96731d309f090f25fa9bae6b89f43068cf1302817635c361ccb322d5e6e0adfb9a58b3fb866806a8e5ee6e19b386236b4fd6bbfc3c2c50abcd05d6c4a1c4c27575a325a398757d3be087a469d1dcfe309549d6b2553ba3605b400a5f65dfea660a20319d91678e0272f3da692edecd0e690c8ebd3bc270374fdce985c27b972203a4e78b87503e9e8712e9b9557ec38bbc5af5d3503e730967e31ab406267845eb10e041fbbc938dc18f0c8e3ecb9467237937d8ba6f7269c4e1049779a3cd30e105adb8ef28b00746ef4119515754a2fc39deddbdb3bd98393020388b04fdd96c4f2f714303156dc0b0589314f0da408fe72cc00948ab3743285a4cda74fc2e5ac8581065b27c643d7f3e0c13fc32c6ee448ca29d9141a234e8fdedcdbe686d0001585ded9d65f884cfac1dac629ba99b9a3584e59c7c61019caaec2054093b14b0e2ee757774beafdbeea508b7e8e2f105a7eeda19c922e97c29e018d34df7c5d0a31478519cea07a1fda8d96e0384c826b04b8c35367b4441dce2dbb6d64f043aaabcab56ef5b529041fe3f5714a9e4901259f4a5ab3f2ca85fe0008ddd0e80352f050f4f998f20266fc938671f101c98bef8308b0de627c551bc8852326ebe3533135de646267222e310a0217deb2460af94fffdeead3e7f39df439ad2ecddcfaa0134f13b968fbd10754c5fd99e5ef239ef64a7d7de64b614ec055f069126794c81128296ea19fa49d836b2d013375be141cfabba664495d82ab2274bd3109e9934d4d2a49ce27275ffa72ce2585161c97f0bff5912f06cc0055aa50222abef76f365d2ff14ea99541ccf95bd14825d5a36846c4d060e09bbe2471fd72181445750a226145af6a90c903739346c31185d30da496cd98df115742089b741fdc83f05b590afb1dba9d3484e317c2707f2566b602a094d3f87f11f6ea2e2c1bf241e42a1ce5ba614d63d44e91bb0ed791cc36f86834f2de864f4ca316504dd8b32556ac3c3bcf4dd0939960d2fb1f3a30d61f268d58e1e0f0b4965f09b604e9d3e54091d10172f512f1bca0352f61174a771f0d32a4308840add5ba2184f085cd783b1991800d0c15897cc56362d1d06861d7cac643a292c296c80ad89847d55a2e5413786b3885c69a556b99613f81ceb0d6f8b42b2b8bb5e63cab0678bb496acc57159e37836c0a8a2b08ca04210650fbb308e97687c4d648ca9c457a5f971316a43b54018689c14d8408bcebb099917c60a1b9d34d4991eccee3d33ec9b7f72069bd2393b92e7068f58649f1118727e78136d97c11efa3338947b24f2e8f2af890fb437060c1091610e84762ba7abc7cf590f4ea891225f86e1caaa5c4499a00f9e611fbe97282b9624a545a3e3267efd6df725911d51881ab58d050155752750810507d59f3c4c8cd7ae2c0c9ae4908f49506e5bdfbb3643d642c52ccd66b64e03a2db21861ba9d2805cc6341eb43208f02dd225a4d02fd40e016823d98438ecd51b60d5cc7d343cb270e321650adbbe62d1481164bab79455a0c226df084534c679fea77f9820d2b0051f7743d6642ba29b83d40ccd4a61225829881165cf492e881b049c3bd682ddbe443ab9f4967d848bf0b495d843714f55b00d96886a11edb0921c0170c75e960519d22a2673210cfd622f544c7c03648f598b2210f954d21b73601b4b20b4011b678874e187a086ac9a170c83591909fa09609f694d2aa64f0fb397b863cb4731a7cc9e3a1525b52b23266814aa5eb9ced6b7806644d0f38dc34563a421edc51487200f964ec15c9208c7a9a44459d0e83d0882ae53e77abd2995a9bf9939f81ca8ccc3d6be0b80fe36decdc1b37b533d6009ab32a1c9d1b19a050221e4145871a195ca67be8584f09fe62b504d82a30addce1f87f0d02e709f2a04505690874cc115603b2f536d1738b91f8cba32463afc6aef2799b9a0b68d538d15fec432627bd1f451b4c5d65483124a889a67e603e4c9a4e0c60f78b74b2cc1d39cbbfc5c672491bea3ab3ffb014dd4f42519cf8632882b69f4b138b00d541da1afe2627c8061acde25ceae7d1e066137804f39985da5566c5ca2f0e566cf8f1324b4c8d4ed275fef2d3c6ce35384e84a812fb334f3acf9b02120d56654bd9e3ff4dcc58320468f9067a057416c9c0b91f51b9951feee063f3c48be125c12abec6b08cb21298d7db22a4957a98512866facb448f425b0a19a40db8a5a646ba00e4a6c1c1c16a404fc0716fc80aed20e10cd5e1426d18d2cb23b6f403512007ba8b22a47a91d385d65de15bcfcbbf0279800ec9757d41a03e4e0194440771a2a63e8acda76b4affb089ee570acd7c6e95addb0bf4d5889266997a7bdafa336b80fc564ade55d2a64775cbda9b918693c9ae02a9d1e3ad1d7899d6b4f17808e44784ccee6916398b4aaa4a4043e259b71fccf2eac41e34b903041cef7629035d770026e4c29293b9a70131a2a893f5c03497b56530f4b944445b80fbceadabb3b0ce32bf9621eac3d873a2a64945112262352e02f5fc95f489b9db60053fd1f1a70d84e21cce468ca9706041773eafff08860084a118de995d5e0ad2a45288a5180ae34d9941375c6605821dc7b34084a9768b27b2888a392a0e95367f9cd2113cb791ec4b28642c5f48afbf9758ad585ae61932ea56764810bef8b8cc4bd6459ad4f0c8eeb6afaf851bc451266e2550ec5982004fc4d108f6363975165338e5d18565989319f226967821533b559a7dc4936d7b075301e4c5d80e360b1869aeb700dbcf37ee7476133ed50eeb5883d22dfd9e22ebc60062c84dce82499abb56c4e46f14882600d7d8f8116c3409454366858b1f6630fc8d23b495fedc85f797ee70bdbe8b237761728028da46ac2a9102187de9d4a51bbcf8d1ea60bbf3d8127ab28b1ef7fb5882551449ec5dcbf6eb7c75457ebd6b65fae1c6e06bc7c85406cc33e3bd472186fa77735d5503c04a572bf33f100cb2813073980e170cea54b801b4873b043c849917765218bea30440607adca2ebae00fad3129be32f9af69ae697b94a15650f9e7b3765a623f3d9d7abe1d6ab5d3e44ce83dd83a10678d8b0c9060f0dbb6a1507a7b58f01dbbfee2461fca44f4471e27c12cf95286afaec00345524458dcaa33099e48a107cd93dcfbf5261b881bd399df3e2b6de2500b761c8b24733316812fe6fe7945e2b600225f22ff24c6ef437298ab589883e4950f379950d6b2dc70866a2bf3ae40660b468080a645e2e2a65c605ee19cf9516c9758d00fe478ea50f57149efd0bc24ec54c9c52c232f80dd88d8b69f588a7d7874205ae78085ff56681bf2efcc7972a201f16556eca6ae06f595f94d02fa10d8ada4a9f081385cfb41add4a260b84606873fd39462ed5ed108a82e085924cd3f42876a1328a82aa387d4ed0439db9d0207e5c1365d09211200760391098684216728d221791a35a50792186228df9d4472964cc718a9d02c96c600a5c51da8ff246d3743f891f570f307509bdd2a08d51016b37fc0bf63df60b8e8145cbbacff40c85c72e1a5d8e3b48954b836ec3c65a225bcecef5ca4ed986c45ae0969a09d8ba12a50591d983da83519386188563ec22b8cf4b99e03b750ade78c1e5b42675fd09afa4551cda09427375bf3a462140b0c5a1c525d06942f9d824efc44a459115d9f47ff3cb2bc2390cc19b702bcdb9eb91598e4581701e491d7f94cc00a7f8de7c0925e4f16ad5c924fcd10e497cdb1d8a7af9ae07b0022132d4b5e6eccc1a59a32a844a9555bd1bc76eeea0b349079894b8f4c07a08f4a9715fffff61fc526667464413f4131e9e094e231b97204bbbc82a311506704a0afe753ab56de9bbe7d77639c0045ba0b5a4a48f4619bc39052306bbc3e4e0cc014dcaa26522eaba899ad0b46ef5a852f21dff2188b586702d1aa4684655d9f1919249d8390f63d172808ef92d565842d39877fdd5442f0eb35b0479cced0b3b343c52e2df86589daa6c92ab33d35febd396b7d046ab082473fff93269fa6c070a2ee06c056e7f9d82f1915a14d681e7dc1f025054053cab5c4bf56c05cafe91abf7843ffef43b65f10861b2c29a4da6858f759c6f99fd5b704104bcaf0a870314979e25768e8d0c3bbf8cf97616d68042455c94a03ea18f8d3327931f14df149f6818169fd8fc3b4b23928e3899ff4a935a927fce912b57debafe8a0d64f92d6d4c56279af894e7b32b19c3c62b16a8228b05dae25ac4a4592fa0620913013722e673628fecf0608f3777a74e8f10bfa1e1ebc31bb8c15be6370435779a94e5b86973f0f25dc9b1f687b04c30863c5fa08b3058eeaba3a3dd2ac77a992db010536183a83856f50a3b22f5a83a58cbae24b524353c9bce15eddee8c21018ec8ef688cc82f18e26004ee88a99e07a4f18da802cabc1af13bd945ea09de8e5dc6b920f477efca148c827e3889d2d57acb3f3a50b2fead245b53913b632ac0bfa6fb010b1b1a883cf45da579557d2b001ee344d8705054b070a8204b0e4dc6efbf7fa10961f386ee30150afb8c443aeb36078452664b06007b7c2745c96c97f1ff75851c4556c1431d61c77e096548a93f139f0ea84ba73f0c620da068a5b57ca97d960ca18470a495693ff68b29c6a3e01094a14b36273ecf6afa4930e7cb4545b62db1f6064d748fea058077f998dac8fa11eb0d730a85576ecfaf47a7f158963c6fca963f66c4df292b9906592944d7852d5e6bc8594ecd5a3fb0837c327b2827040f5fa32e46d00a1234b45147ca1fac91596217b1291ba66f5311e415b2b8d7d1459c6aff550340609c8f4f0f5ea907d7ec24373747ed8b342adb281d77e79b900f878c300f81e05f68ffd594ed01d81babd29504ff2052a457cebdc95f0e1c0c960ad150ecff0b456ec21a22bc646721e4a5aaa811f4a40f30a38fff8aed90bf4aec62a841513c7f23fbb7b533520df43c1491ea1ea15d807cec4b2d4aff75a930cf4026dc588bfce8a7a3bdd5ff9cfa16b8759ff79936a86cacf277e6cdd9cea4133381fb4d50faac3a5af1a5489b41d2d6a2c8d2d19dfcb4717fcab1e384a459b8ab0417c54d1d1e4456bf0d39d12fd6f6addfeeb53071adeb899060088a0ae41f85b76e84c8748d06582eedd5401f6a332ac8b6b9d763e80a01dba7ca07c470addd0351554420e1d42450d9f24a774abd0e369ca75e86403166ce1362d73aec8236209434fd0a7332fc9b75df88a2518e8ca0e4315e93d57a7b43b132665f714df9f5316334bb11be9be710d53b2737c5a64bd8080aea37d7ca5d801cb4d4df6823a60a3e719b08943205bdbbb9484c84bf5a05e4a8dcaa848bf828a790370e1fc729bbcae29b6a86b96ab3a1e38e2407a83dbae1b513892d219a69ee3888e7bfebb174835b39de1ab17558e2402a39d552ab1cd46b1f626b93388a1f2e6642c9e995d7e16e3745148a121c7aa9d7675a5cc4a1315dd4f93780e777ee44df7ab8528a7bbdad16564ceec1b1d08c97327c6d4fdc60df6173189dcfca4426c7c72e79babbb6e09cb47f6e51ca305c881c9e7361e8aa46545ca698384de867c85377f4ec6b8797070cb029b65480d5e153b89bda750755f6b0e32e963c0c04d23d3f14d6c4a26ce1df38bb3c382f5cb27d0243a5b4a274f5a612a10e9a0c39171e489b2fee0dbd23e386ac3c2a8525bde525d5d37c0d62e63d776e30bb148aebe8de8047682f2e9e32da139811e9a4ce9d4e910522644c1d32165a7a3de1967983469e2e81a50e0d793b2299063d7c1924df4918ffe6c337036c1a17614644abc02319110154b462da0c8b390486a1d83e8b182b45bc8593cc0269e9e2a04426de4124c501361ae9a8e3068a365cd13d5350505eade833b291b88a3c5461be141161d1547d446af5f01212ec83bc89c737b961f2aa7d4090c4a46ad3623d4a68d0665caddb96a58053c48b5b06a722917b1f120dc902110c2edecd1873bbbf82560c155d72d12275ddfdb97ada1ed5d3c5cf5c09f8682c5979b54892cc00964a1bd34914764ce1885032c83fd2748a51f66335a006940f21f14f74853da4ef616df2bc23bae8a284340c535db282b8695db06ad01f0c57c727bc9e92a9aee7759637f8771b85996a471b424a7abef517d34b33454714b96d2c25429a22305538b6187c4e215cef6ea67210b53c383e4996b48a5e7949dd92a9da513e602500b31c47d9c1b1cd3b2ef8f10bdfe525c670978cbdf6ca1e4cccc65c1b618fd18c9893039bd490e26400218b9e137c66fd1a2ce5b19aed7f20be622b9fd7858f04bdabe399e32480725e45789fca40f498a1233f8fd51d620297270879f9fb4ba4f4b01a647ce764ac768bb3cd4b36a8702fa1b2447eec5c0e92959b829ba69610e0100065c93e240306b605bfa6aca3ee20b446935405b81009c3caf42fde9e5b6a58890e272bd9757418d7a9775a4babb2dd172b5f8548d63c666bbfa837efc3455315ee2f637e3cd0af9cc2c2761fb55086023d4c559e1853f9e218f9d530474c5d924a9090f24c9e574ae8f365ff765a9751896fa859625ad9881c1c9c0bd804b187b0694cda94589e4d43c1c6c733bb84e6e48e37aacf4e3cc9d0e3582e34399e333e0e50417d3032430c269221e3a9dec21edbb91f636ac6d96b268cc8418f3beaa4846e165af5e82921d9bad682bf64b0694c7c781d591e850e7e47e9189136ccb7f2636023ccc072aa75550ca1b195cb9560a8f4ae7507f1dded3228f16f149fa2159e9acb74dff27eea5c54ad5848d2866e695e0b34be2df034c49fdf31af012760395342ed79c1374d4efb8a12ee263bce6b9ccccd4d089cdf03ad009a3e15fee4ddaf96ea9bbf676e859928cf8cf33aab931820f28176f4377663440648ab4ed87d06f5055ea85d02be31a67db79864dcecf97b99048dc21ac055a3267484952f0dcdf90b83e2d92e6e3585073f32dd60471021e04d04d28710f538c37f70bc72c079821de1cbc7c2ef6f2ef5cda777e5ce316d4fbda93a6ba05557a7492c6448c6da484b34e9fcce9cb2c0ebefa71855f0ec307e40256beb91ede38658e4a9761d2e4ede7781e4a62f488525764b77e121b699fb71c4e01cb8be3942922ac327f8d1523300113f84438e81668696a84b96432798d0a384702e71150b2b45a5a5c9042a1d52d3f910ec6d2055e0a599d79b4400f4e5cd6f0cb94c68cd607e0e1451dc3e01eb6748858573e1055d1a849e05a2cf67b52e238e2d075731a0e5a798b7f50c1b0e133f33f638e0df2e14657b084197a097b4eabc3d5e000fbbeb885858de5841f886718e200f155494273ae5af01feb3867d6a317c89e4a944ce6a97b6f2c9fb59656b413fd440fbc1a165a8e30e9f96c1c7219685d54d25d273e7387645de931170aae7b84621a19635f08676cdaa55c13dcc3931df46b6d7318980a430248d60061bc4b92230a4582afa4e7f2c2cfa906bd91ad3c8a6b815eb221408b8871345b70d281fbd3e34703f56cd2ba140772735725ab2a0356450002ce651a18d7a9b34a01c7b6c034e7639179920db695df84160fb43520a80a931dd6a64906b03bdc58a69e323b50ea4444aad5c0109ab509710f98039796abc1805039d62312f39bb6ec0ad28fbde39ab1d8844327fb668a90ba70f364419fc65d8ed05d1f9c982ad057de4c83019e381fcb54b5086b008a6d6866665ebcc920610afee51cc4958550507ee96119f529ba821b894c58170e126001c154c9246c21e4741ba0557edf2e402bb925438c4c8bad3a6236170ded47248032c28b2d5879899f05cf797b26a3e1c7555f52e7272c2479deafacb0bd82c7dbac3005c6b6cf84c0f9212584c323fa766d1451193b37fa39c6132b691100b27a51f6e9d13b246a8807069e13c42aba7d1bec405ad4cded96eb735c88864e43296954965eb77f95f71a597c8bab65eff1aa6b8abf411e89d6b196c267d80bb06c64cd94854a08c1ee538d36d6aae9e632227a45cf7955675c8182b200a0f84d8d6e780d6d8584986adc376f12d0934cb0ad007eaf452e32c165ddbf1225ebada125be7a69669e546001f2f614b76c402aa8f7550cdbc7ac90bbb0cd5c339b4130f744757ccd5a6d0d6e284be5141b33327ee0c97fa47fd5410f4e8b528e7c5c633e9c97d731663b243eea36cdd497ccd82b880f37a3499a0d688d909566bbbc0109d23268f2a190f3fd7f84f65ea76c9a2c208a9b8f0d993cb868fd1fad5d47c59cdc5577610d9f702379ec14beb8b9daac6183e2eabf428c0319c88557c8511326feece9e557cd6f70fda9cf2e24d74617dd92118316f00e4094144e91257564cd30d197d2ea94488bb2a1b99aa10d418d769995970a5da5eb9b27ade6e2dd11bde504c529c35a190ed37f88789340d7a7347f53218502e46ed5750847788506b900e8f5bdbe27b8d06ac2c919f457e800bf06caafcde56bf294c40f27fd863581042a6c9363be869e005160b62b4b9bb802b68435e33e87a3295a82f360137c7303123afe644fe413ab008b2e01b245a8084aff0b184e05c373280bb8b6e759fd8e09f4ebfd8ad3b8828c87bc1f1f438650bf4c0895b64627817ffe93943b1cbd823db3d44649e7109491da4d2a29fdb02f84ea22b9066f4f8b8f91f2420ca651c73ede0fc6f49f7f46ac6cfff73be2b3725e021a3846b9b11c92402ba0224a17148a87d5806546548cfb4c59bf56f77c4bcdb06fcb4ba09a7c3d30cf54c706ab95f636a3e10beca58dcf1262b7447fc89d51615275a058c4a8be8db9ccc27753950534058cea65061ac2b4d34b123a6b2efd3b06daa2cf98bacc619e53e45858215f1b2fa218b9443b870ad9f2253cce667bd314adeb6e758d45c1e376375fde1b845b447f504f36d57de962973b6e5256a512d8aa927e0d22c120629327bb8237195565a3c12ceb69509fa35543e589f34ff20004a1e863dbab4f0e811e877161085a5d1e34885f98491b47c0b610f4808623e8da352d92f8726a864443798d9aace10fac11f636e40c84726ca785a8ffc4e1463f05c24c7ca16c5d61cc6f405b14b33d462516c748dc399ab6945fdbea7a3b48f1d024be801767f374c4704f8520b36a9ca5040aa81abe1f92287b7acf105bcfe2297960b0cd4694f1d71b615d65d19f4a7570463d3cc476c58b55068b95018ed1a8299e2ed9cec832dacdc2927c6ce9da8649e95b48d93bd21ff8a42c22061099f6a43cd20a89eaf9a0397f98a944756dce13ece6cb24e90c6123419a7d88a310165755cd7d4bd882d90f6f989a5f38acbc3eee2851b5163debe28b1bd17e212ebf371b6c7ddad206dfcae93259a992f1f994f3c9fe42a8a3ac14469172871ffdbaac8d6e25c47804bf3176fd73ea2b20908bd517f6c78f087847a3844a09d878d72f64fa425012d6a1efe6d5964bd248a2ba684f886883d3c51eace41409ca6e857f2ddfec1809c688a6833fc6cc9ececc112907488ae50c4bdba2e32c39e012ce49d329521d2927cdda6f97714fbb3ac41a45734f8ca0b6be18b2bda1765ae43b4a64715ee4d52aef2ee8611c2521d8cd8e4036dcdcecb571a4c0e8a5c67c6c64ba5a52b89fbfa23736e5083189c7894c3bbf26a9a342851297dc35e4365f0031a18eee8ef2f9e6b80068b6e59192c62b64ed2508c4f24c20234a58d7b2e719adce80aa8a86bacd2fc2c6805bc99e6922452fcc45ce4c65a82f0d151c0525f7697815dfe2afa2e6eac4f6389b7aa6bab20ee4c44472521b756c711342ea6facd6bcadf64c5ea40453c94d16e6752175055237359284fad3ba44458ea3b4865deb3406a930676f48228a670833a2c42d28bd8f132aafc675384721643acc950e75afcdbe9306f6a66f4e9e9620e947b62309830165a9d9ec3b68c121cc92c6e5d7ee12f818296707491957f2c914f4ff27ded392f7974021a97196e23c13bdf6c635b88d32e68447ede8ccae401c765493041cf4791817ef3ff6ea2a7575c8538a3338135d260877d1915ac3a61f031b0e682dca88dcf9ac73775f8a93c9c9d8e5de8545519a93210331aca202c00cc2d1f8d778479769b0dc549a7bd36a5ad8d4ec3d541c168e235b69d50762a6bfc3384699948aca6e8b0a0c91e2cc95e72750224231ab0e71e622ade3e0184c43e47da7607249718a4ef866d96cab94760b37e926ba535da66d8c2c14529c248b6e360f4c9e6631529c1f29c4cc76b43637d44a3541cc4410b0f6f33329012b84d1922fadf2f03340cc143a0a9a8176867f7d792c0e067ec399a918612e34bb973d2f55033e7186476b2da716e758030925892105bd18091103e56d264e1b87fa21cdd4cb749202c29666b82f2fd77061905fa70325b466f597cd4c6e4a768050b3a82aa9d9a1ca630408b0e0ebe78b0b0c010e88d9cf401800db5b641130f913089f45b2acdc3d4e5c213714870ced78388a03ad985cc3f84990faefa6a69a9b79a650c3a01575cc16c2d9fa0b946232a690e99581a453e5927240f3e164abfd01965f9f48ba3fc3105979754d04a67f936455dd3935c751754c8f60d3a94a12f46adcf619b0711e44d52c714ccd6a0f8262f655ac0400c4e2f555cb56a9db83d8dc09b164fece6daa2308bf446b2cff6c94e50ec9c0180b7e8fdd6147d088e1c768380ba14b7d023793c266005de59d247b52418142bac1f98c49204b5ede8f21a50c77c0d8c1a25164b742ced31b992ea5f172a9940097caf82d954498a4534df2321f46a8c8fd67f6db457039940116f519d8d29684d1e9450c88f6f42bcdca438ad68ea913f2fc38a48568ef45272e143269eb97d40b327543bd90c3fdb1b91f0fd2089b06234aaf1e9dcaf7fa51b391adc0646edce285cdc7e2567518b73a274fe289938df719d9fcd178639930d015dcda5f55a90a957fbb2cb82e69553bd20620d196c64c70b6476526308984a2db7f3e8650d47048734421628e807c9411d20653c941b1b4e49b90b28d8ba93ada699d6c419f8cc0039f57421c428d0631b8e0b4bc3c4d58e4f8a1297a602bab95873b6a17819cb483bded9ad2f5b4c6136457d803fd51ea1560be0e023fa6b64c9cc1f4867dc01effbe14be6e8b65e011cf6bbe9d42556d27ec9a7fcfe8c083f53e92fe2146f54e0342b6673384a31ee8638f3058af90656a88e1bc94b978f4a00723ad734871edde1161155505d45cb2a095f14830defe11f35bc4bc1706025007ef546695028ce2d73db8088a3f9fb4f512ae075734264c3d51b8a8480f9e4c7c44f0460ab7b5815d2d9606109fc6bc7551da40d045c4c6af7bf21662322bbef745cd156a425aaa4dfd4c25299e117309f0116231f581b933b945d18fde03958867eb0b2355e9350e88fc40464f582e294f2869297791886cff0c6c0fead39bfed9cbe8379b3ae348e497d6ee475944635f0657d692b43b9f3fd97ef0f4f9abbf6a74511f2c997ec0984791f6223963164453d9e619406db3245ec7e660bb300385695783d136e1c432b9c344720871381daaa85352ff8e3d52bbc97518c2573029b4d54a99ced64d7714df2ab87df5e33755fdba239e864ee59d103eb81d00bf61f96df23c6f8a8bac6ac8c28d0576481b53d5a795828f54e99723621c9a1d71864c8d15460b3fc898eeea8f5bdfcfffbcd4369800775e524ebafc35f826d1c1cd94452df55d2b3c9af6791cbe410980c70e388777af4232e7c5286aa6d3155d5726da4e66d58e85c07ffe61a6b721e631b2d36f70cbfea7cbd2f430272bfcf0dea4ad2ad96ae2d01e791cd87d4ecf6ec0eb204d49022afba367a8bc9b4c0161ba298da7546f7ab9aa3a8315ffd2b7069c1bdbdcffe36c30f1d04bbf1c1d38195f9a88a9ff187ed8082def8446c37ec7b4a6ceb38147c031e050c7ebde4f73bb584d4d709f46ac4f9c86e536320dd0eb1bfb96868699bec0902ee0e58c4963fd0ff9e8a21f5180e73142c0672867b0cf6792052da0e69db83c30cfe4e56f0f78aff3603d584f65680c80004a04b20de344b5f3d50455888196c96f3558150174bedb17a7da28337560564dd83bcb51d73e525fa29da87fde64e6b775b70f3c1d95e88dd05e32c2636f851d1533d0c6d2c638ee1d667753bb6bbff1d8164ccb6a7f64919326d09e5761da9fd4620e9ab672659fa3d4ae6ebfa7e18e4c27b171271a612728a621691b671eed4883181ed8d0ab7a3e70e6e205829e277e3dd672b6c09b21a2226eb447a529571d53f023bb96efac814bad9b852a8c0f482a9b9c6ac1a218a6979e5c65e6a758983e1673422394053fcbe6ad84bd81e3a14e65b4df8f426e41cfd82f35b364aa243ffa224ddc631d63503c12c223200e3e76b9a85944337dfe593a3a3534ee62f4c55dd70d78d2e81d477292b756aaf3c7f9b8fd1cd57297ec7f8e60d180a821c7089a0ff91e7cd8c089b67878351daf0d069be49bf903ecaca641d20aae69c81f4a821782f939b252629395220342eaad7d2f7f1c4d75db8cf026485c12e6037319997fff62c702df35b569610b7f630085376c58708731348499c07c9e008c9da89d26f29b4aa9e6b2396ba069b2186ace6eea527f2194ec91a163e9cdaf6efc6e1d44d2d730d58cfbfe148bbc979c9a60f596ee935abde4ccafeac02a05a899f07bf96cf89948a1f61eaad80b9a7a52d9ab922080e53e41ae74cea6c8578199e92e55452ac2078019eaf2813d18cf4b085b7f0f5038493256add75f8149e0eeeda1a96901fc26493ad25474baa3f0a9e3c0f15dbee31ab8e130c4e1f24640f20e3b97e62157293117f912ce9493a634a71d9e36c212e809ad666a3dc4a6f997c93aae50a78c6d7278ec511bb8cf314ee13b43ac0c73b2bffb8b87b5b316996065ed230be4adc6488526cdacd9f79a55edd85e0783b72cc7fd45022afa2037dcf8f2a9013d5e20d65b74ee44c31c05c1b523daba8038fa1a0af67b1e52a9b4373f7aca89235ccfc25f838e1b221b2c6c657e27d3786fac26f4297a539e6937b88881295cc0b3f7beae9a04438d1b7184589ee105d622f92710a58670a2a6c3690bb85482ea10b7cc14d641294d755b5c51d9aa42b566d31ef3e0d947afe4ba7d6fe656e1811edd6cf6a7d662b3ecae24f2b6c535f2f96870601d1fee1ec24bba1f80c87de0c850838a17b0dbcc6a5136395b2e31ac405ed21fe7950328fd48718424b0dd74e832fd20a7273c5f70baa7c55c9210ce4ce8dc2fc9f5b7c4ecfba9ef0a27b336c559261efc391eb1a571cb756cd914f3c2d4551b40da13d2c1777f51374f3facc41d78da29998896fbf400a86043e1523c0b261feece91a8e474de9126298de7a3278381a0161fb4f26c77f98aeede27f63b11aa0ea6269ee89621f8462d635b28c317b3e4e068bb4feb0a6fdf067706871aee15422803045ea54513c402023902ef375ec33408be23c89e56db0075a18678fbadaaa8527a1f5a227a2651c2df5ce50a2889c361c8ffd6ae273b8227294ca0bb6051770defba687dd0b12ee1bd98f6a22f464e59c68bbfbb62a9d4eb3da95157096c32b0d4275ce8f39940a0038267ec7dbfe343926d2b5ed1b8f314c623b376c0f84d53547f6ada255d6e69481e582cd71ca85da5c8e19532d7d5fd59df6d6350ed65ab5557056e171419572da4d3d334d7136ba7c3e437245e92030f652507537360eb39c6cbbceab51c923207c313bef0d4b2f74dde3d11f719e0882ab559faf83c392519e817b51ab20c6c1bd4c54f866e63d133e5bb9cfb84ce02eaf42fa0433c04449142d4d6d3c2f19b848a87bac2998981ec3089ae2947e0d00c5b3bd0e368719b1f8575b30fcf1107064ea5d827e4267f4a8a7078e0fd907d12def9cc850df4020aa6ecc1bc35fde5e99971aa02fbd384d9fdc3948a4563175ad839aee194f42e9c30c49a96f38f1b68216cae913e9d4830b06f5d2c2158031a50e0769337a0e876b772401fe85ac3421dd0f96494dc97c4342791cefdf280091732b40fa42eca1fbe60e45f5eaa00db4d1d55d4e1091aeab6f324b2b91a9522be91c5c355981001bbc5a5bd5e301d7bc49b3c8b407b0025c494a717e6e633dfac3b410828a5a2d843f0d50ea16698c61260e081c7a34df4319f184b90c11a330e2c843bb6eee9ca76ac5593795989e47a67e5dd858c0b93a2cc7014d1d17c7e394d13675194d299574bcdc72ea499fc147b083df6049451a82657575c299ecb073f41643bd73681b11836e888a24e428297b360c85b69999bc90801ba053d3c1f34e5908d22887d3c350496af3a18b8d975dc4a66ea72d0a1c07caf89200b27805286e07001369c0b9d8b4f708ab2ecd725b803b31ef7c749839802222c1b7b7499f4360033219454f087fa9a526bf037361412b358a6bd9e07fe29bcc29478b1d66be9bf5dcaf76e9899bae27724c90b8a16d6b88e3a625ba8b73f4f610c774f9b21a9e5a6640130739f49f21c894a10fd75fd0322a20c669331c322f4d582c93de7bf75cfa7dbf8a72d2f5436c322090521477f0f646898c47a3b801d4b7eff413a5b4c2f224bb478a0cf3aa3947ea21798174a136f291fa0bc5b7003fee60d7e12e11c1abd37283d10de6dc47103deeba9d2a89018fa9d5b694323adb2b7378ff59022f05b51f729f216ae55fb35782a4562bb99e99a2c4a36a543af23c8a36952933432379b19b9268665b79b8403193115740b1e2318b74450856e740bc08ee7c8f656dfd44696aed3aedaf716b2cf5d77c2e197a622e11815b2d03cc2996e094b796b81363e97a780960654c9d5266b21437e62e7ba8175a18003a9d10d511c65bcbae53c7b40e539706494c2f4930060353f78967c27261129d302b507a70e2c56285e88538271b70527e84a807cf9a9562f1e267f23d54d1938cc12d14c10375ec67a34b809d3f638bb1e156a1bbcc0a9c1f05673d3274b37b52d9a2ab13492365adb9109c27fd4b8bca8d2238cae0dc8c6f4baf8fa0fbcc701ddd4eb03c961063314b26410649b2db820a526563b38be6c5822c50b31126bce4a1ebe005c1e71110f62a09ea877d63115588bb715af61dcba5599f13df81986a1cec0abef5008986b9a86f97610f6875721b4f2b6a5b7b9e0d614ad60db2f4ec2aae4c312c0f8225163279b61f84f7a8cd40415f71916eae3abb8a1ff0ed64b2f866f3125f1c0ed738988c6dd2875addc1e1bb99b79c1bf6590dc6f367a438c84b7bf8f7e4cfae617c892d36369c6f924091879ef5ee387a28ba7f86b322c2293361edb85448e57042b8429b90349e1b4c532086c46663e1be1c3db1f2d1e2bb47ad65c7cfc6ee2928a052cf1d1acce38ba3a294c708d0fd4c79f2c4d4aedf5f2e0449417112431a2840338a533c21d1f2862b3d02857ceb9f24a9d861225bf2a8c4d55b8e392b980ddc19b8c38bc78e52b87e0f85cd6aded3e969f75cd1631b4c8f4729fab9744d48b4d4602dacddd316452d7b8a3cbd97861c8a64f2f3df09583984d6cba3d8b661c1fb86c606d98d82373bab9747c521b2d3c35d5e617211328486b214682664ad196f7793a1d1f0371905b3b907fa9c7202df1c88b9693939289930373d0ffa610cb036e8338a92fc6deb14e4f6d559e9a5d9f30e23a3e42e345263a85096521cef7219c989e31b2480e7b9941b28d4562a99a2dfb39af6bfcd1daa8831f11878d2d9e0b570b74120714c73f670d1854caa4b33ad355b55bd7ea996dcd110347a10e6105e7609046a94dd3a51635c266cb53454d2ca5ea5bf52581deeb38a4d6bf9c40635d2052bba9ba4af1a4bd178f7e4c11ed46c8246863cb84f17c0662ad9578bdf6f0d8ce7e37fb118a27b9ac96e9762584e60ec5dae132b36e7568a1f458d6de9341a715b6a8f0a14825c42b615b678714a0c5e1e61292d3945e6be3097dbd6d0513b458b522fb66d075f02d4a67a83230359333703e209ceea3c780f02ce411a7085fd1eb4dddb4c3b364330d425b2d7cdbb4a3f414171293c3e3ad7fdbb7f3bc273fa873eced09eb216d5edcd24ca716fd75035e88832bcc77c5d1cd21981684c90c417c5fe707a249202184403cd6a9ac275329d687bd0e6798b8782c0c340a8440c30a82e6987cefd689778ebd955f6cfc1f12b10748b5394f8c185a24286afc023250ebc0405299652ae4ed9c0cb4ef34b60b01ee304c42f8c9c910c461d47ae512431aeede86d5a5b769e371833e348f58f539397803a60f7b35837fc923e8163c2d55af9d0989d3a06b92a54240cf97d445075491b775a327a7417ca4b233844792cb985c48c6232a9b7cbbbc6f79d89a78605fc850dc88c84bc1b356708a3ce940b7b67bd133c10e31edbe0afb33911ddcc43d7f4f932f2662741a7eb9fb40775150cc402737607fd695656443595cba6ae2d51840571cd553685d033dc49a63bb19a690f6b22698d4a98e4ba716ed35f3acad58b889f8969412d004d487894b776313cd0caca1826ba1afa24f50d0dc7c7f1a84ad0a2cc5fc7b961c9dd5645fc11c13b3c819937417987fbacdc5bb5f0bda544e348fc981f39b289f7a4cb814dacce76791b55d547c4891477d128b8171d9865daba0bde6b52a3901987a85bebe97e06f7b14a564db638411dacc4490f68037829443b6c499b34a358d99ca150481d118d06cc3bda9eca909449c86468df0009e92f9ee4e49c0200797940f01d96ef032d6e49ede00d116f7976728381992fbefc5ea915b0d6b0ba509c390f69390b742e14b2b9b35aa2a4af027938b924bf99ac17ac7752651d7528f62a05d264fc4490a902675b18a2190c46b48e300f88ad98c10015e6c03ac4f3a6f1b66c1c55ea021cec8c3a46ac5e129d857deb62f2783cae6e6e282eafffbd6e79793070ff9ad8332dd3157a8332b96b3e1f6db4f66c1d82fd4f7b1cc694f683b222f3a0ea5c036f7c0c239222798df00c1e871d21087ff698119240eb6021582fe947cb73c99e60579ac2dc036e2cc21754803eef50bd1ae1ef10da70b2afbbf5ed4209990ea68c214c44bc4c2132e2a585cd85f7279716488177fc5ce09422fa0590713f88234f44b1afa505e17a6997bb5acafd5d148fe93dc30627462a7b3a044192b240f59a1e4e8437ffe0fc2fca62934ce8754acff9352532667e8d43090be840e9b59a10098b7417e379c796a14df471aa57fe8914f37bde975f60fc221930ebce4a6965c532dd7fb47a4f81a671f39aa9cfa94b63f7e3676bb5f2b0e58df13c41f576c8fc7cecf4ef3af8e8f5f84ef27ff3257dbd8198051995955735242dc4b6818cd42a3b243d8f82c0a4cd8b16dc82c91c9a3707aa1490e133d0b41c6017f86af686962f04903cc2abdaf589776996f94e8a16cda28720f4b2dda50a41899e15596b9584f85f5d05c5ad010b16a4b4fc4429e7e9b98d2be3b9d33b571a56df05b91509a01d22f31baa9f8cead38d93c8eca8414bf1553df074eb59565c0e1408b17572294e1240fc286134a7ddfedfbb1e521bb22d8a8efec137d3bfb060b4e9681a32920fb1454acb98d97b07a8e936c73c131251e805e2c693e383fc6365afa437f5675e5d7e6d592480c9dc40fd8c48df3042dadc91c4db6b74b28215eb104f4feee577515cbb64aad2597b89d853bbffc1c547d50e5ce7dc9d54abc78f74a27d5073715fefb085cf241343edb25de690cc3d40764b9e4dfc7dfea89a64746f01338eb813ba037ddc9e9ed4df7301bd3085f391ef897e6ef256592bd3853f883dbfd4f274b5b3e1c678508a96444fb890899944434a9ccb409ac681a6573f020710a39cfee3ef809befaf6ce542766faf2ca0664b452319bca00393d650aa5c94ca3ba1daa37983ba222a619a299083633c811aa5ef919dc743848f2bc065e4f7630ac17600828476eee010e5391ccd0537a0e22cb9c09630c0cb5804c597843dcd8c3c6bec69d6618c4d882d28d031274f5803cea4cd8b6968c9da1b3852875b462c35a11a30957352413a3f9f845895bcf34b7035a2d97d47d8e64a6a3caf36097809605352de65658941a59be29739acaea130b65f653c58a94c23e6e78188f532cc3218720a34ac5683389759fc402629eb0f4513f48caf6cc6e0161af0ae39649af65504edec70d05a80b1407e22ca812b0ad53a556154710cab80d56f06ee518d7b584356089ea8598a5de919999ebc41f37d85e59f7f51f61da21165d6eb5913bcf69ee4265ea39727aa1187b02ee85a1e2340d393105f0bf4a8a8939650fa04aa786ea99d0c29ab65902bc8d76e454091c1b00692507c340af76ac09a3fa18e15e9dc2f09df95eacc66f51408ede7c51707dccade0e2e05081abfa7f03fabd7b50d0d3c06d196be72a3dc4cd0d4298dc28558658f9a814ac937697a38e7ea06e8f295192b109864b3b20749002f83adbd039432129ff0ca6e68660d2233840f26e54628eead398704db95beb8f7352318a72e4d552ef5c091f44476255501ba820651550ce54aeecba0a03065c105be408f128fe68b82640195aea9c840feecafc573e18e64c95a927df91cd99ea705414952054a1f038b8155948f3bedb0d7ba59762c289a63326bd01912c43f2269e7b74d05c5e795a42948e120ccd12c8403488f9b5fb953c0466bf0f043faf49ee8f411eb821fb0dcd92e308e8b2556f19c0084ed0a638aa80699a300b52950f53d54192d3ae32d831211fba3bbd8b61569429a678b83685ce69b498d85add6232e6baf778134520090a03d7f90de8265e31493e80c2e53711a1f68a8b6354b393da613f2c0e2ee5e7c0ef0630c699408ffe14b95ee222ecb8d036a3dd8d96a5e2609eb0030a5907025107fe50a56a1db4670ea4750ffccadb28f6eff7cc5c3121ba61f97b10d270fde0503bdd6dfcb83b1e1ed9032aa12e1989da03cf56f680ac47caaa105368a8241dbe1992c455c137a8f0b44aba150894b2fa9d32b97e855b0319cb5e49c07b750b04bd1dd355089b80bc032d63926e72dba6a590cb5df165eb64eda20a6818dcc655a024c681e8fd1b6f207cd71ebbe5504e1201d076e14e346b55214b05b0d9870759e22ac6cb8a87d869bb46a36cd913fb851937411954ba0be859a61f228c08e29254c0004d10f9f4f2af8d8c94546c6fa0e136b40afdf34dabd058b4a30592418d661536b08d0db3fe45ba5b82df30ee95bdbf901e0d1b5bc4aa6032226f12c262125a60bcfdf4bce2acad71fb996b1216577dd1a7028e049707bb085ff9fedb147f356287290c7eac2b563e8c8d46a98d20d646e691af01b5d8aa6f6c2314e9dab2eab14fd18bcf536a114a332ee59f1e345c6825f5eae2d71f4f97beea6b76ad06962db7ec339591202be8f97bed327857f3ad21ee25c77c22d9577e1150844a89249a131b687c2a389a308dae42991469a882cb0f0cc472cb969e5207d09585770ceca86c41ebd00318a928a1b27ecf70c3b2a00868d96463035bb431b7b306e37226a5fa485abbdab43056205d7da3a10ced95f12c2c63eb4e5c94051012c5a8539ea7c1e10553fb2ecaf1fa70d4e5f0c36918eddc1317dfc6a50173df226e1ceff93f85396bb434134b6d8efea336166957faf62948fb71185077ce5834dc1e80040cff2f6eaf723520ae0e959fbcd4a9426b845f10f309408739b76d8af3364c656fa021de301d4d2f9f7ef7247670f6fdd052c3578ba20d03cee9232a8625125df831cf73c0d8917c7c1bb88a4bb106b2f8c69f33d97edf593aa9bd987aa82c74f1e1a0c29acde05b6512d179d1ed00969ec9cbe1485118d2f385e8366fd154233f2c41826906e6e1da734e104c61c881519081c7866559d403400d8dddd455c6ba01672fc052ec39060d3da76ca31e799c5f73b8663befd58566021fae1b686d859e6ad92c5faff0e0720642555f9fc05b2a88013325e99ebd8ac54517c9e510a62fb64427cac1a0400b2fb5a50a33bf3e6852e539757102fc05189bd997969abe48653867a21a203852c8b93cef826f85f64e93fe3da936dc8100156524df49d0c1730f3685e8cdc1e898b812f30c57dac4f473f6ffb83dafe9dfa70b4175037f889f624618aea102c42a7d3325726a5328813ca55cf7cdaacd3b02f182b8fee70b05021334226013038f35ab01a21e0d2ee709b55f4d087b641f68c6acb0e469c23584a8045269d728e8b6e5412ae1c409d8a036c12a6548d6c69744d1d9931a95dd5e188e02541ed7b9d3636528529ea3a1974bc3fa786b9853ce7a0f3fdc0a4ad956308723710a9acc389b6452264593594a02165aa0ef7835465cf2a61502017c93dc3b330b2ee15363f80281852eb1f428173c6d8616213e396d385470dfc0198d956c2712a73335b4bc88eb50eeb848ad15c430197aeec6ba2101a47633b615d245bc1970dbd5942e22cf9b60376d4d67b2d5ccc417e3950fae363a2d3a1813ccb84ab20183ae45830194c52f8a6c54406f4c0a47a455d30b9f72d40bdefc7437dab4198c253e15181342c0326b28572c675da1e73e6929da21288e767c2e44be2e4f5c5c8f80fdad9a0e354fb4e96962d88b9a859138e690fd3ec6d49ee8263391a064017c927a7db8ab8c9b8e6abeaa14c52ef270f0cbc777da6c38722f0a88aa151b5e22cbe70783289f91b1a428e544f054b6d23a2d69dd0b216d884432ffbeb49170df7b1869e7c1bb5effdd4d871093efb02cf048877402b6ca9ac8f51d7ca2efe4f6cd823b42b1b7073967f620fae9ee035410e3c37dfe472bfad0d1445db43595b76ec43346618bd1453dfa3d2063d0f647bbf9f869d79bf74956c5c9d96d00e571b20be9213599cb85dc2ab453f4a0f5ae416775630105026424bfc88806098126abfd518cf0ab1901b0c06925497b7fc7ce6753f28f5d5545a535b1b724286b13531b23347bb069f5feaad2fb4309a66e2a3a07f3f194d00fd98be183e563b75f0e0a0265054446941946a49f4fabb656d666aef8d8006e4d94920d8a24dc4f79aa14b73ce78ce79cafa123b9a30edbad94fd980a08a515720e4c716abc359a441d5627898b76139e1348e1e4991c4a5e1cd9526d1ca1399c4d637f325668712d5c33b1e81f1fa1a54872ff4fc4147b1a8e845437baba36815c1ea496edad776402f5219a295858307294ecc478b3dcb64bb8794318b991e89b90d9042779da3a1e0bb836a0a6d42bad71e534a3c2928426dd7d6f5ad718bb4431b938b7663e2e8984e7b5bc340030c7006a38b0fcdea219a67e25497e32dd8ef30310e55c843f1703df76d69b4f0d3c1cd7789191a7369ae1fedd88e7d034009af172433d05dbce1cb9c55a000ad1188379f43bad33b15b674115e45feb5b790d8644cb65777fe80b292aa0f64a97d244bbe61c1b0de72050a54329cf4e05e60364248408b774841834cf739dbc04d5031a8047168bdd43a4370edd8171c969e403cd024a1478e550525391fb2028802b180b7e765587c8a7b0287177ba8b2ad80dcbcec8e0774d1637940e38715dfd2abb6d71d326ac7b1d95341b2cbec17d807f12527a9ffda456ae1b93e47be1290baeef2b3840259a104c690fec1d064ee4027b0cd95e2d5bd9429f966c3d8b26279154f14eb1036c87b776a289c8396cc1029eb3a5ebe9363492525c70ba8992fb3c1d57c6477ffa03dbf9ec84c69b0c0f363d6363e610d4d39fc6c2100d85b110bcb61c8c2952640360b4b92d9e960fe536342b3c0b958502197e779bd6edc0a07f50fb6547d36a932fca4efd8244326368077d65d8b0a64e8cfa36bf5126970a4cf0c8c924e98572617bdb25932de74cc43a359e3158f4939b6ed21bf2e78dab4113d4fecf5d2383841a2cb35c59d30f37c58dfd9a1e7af5761e7aa7f2dfb235fc11b5f8865af9ba034571f33c1b9d6b3e2d2d99447751c112b8bcdefaf314d71327d3558c30802049f767ca5d0c5cb1027949e5f13cd7edbaa4e558fcef9afbe3aa43efacdaaa6b295b4eb3d973ecff25b080334ffec52aa8d97a2530b5f7fddd6c08de4be36d9ccaf86c5f4643a19003faedabfd7843cd7daf34d1f402d3da8304700e5fb062ac0ff4741dee9e0eec990c307bb44eeb172a84cca725156e88b30ae91b506c58e0d0afae1982eb4d5122afe272e78423a83d47a28b652df91ad875a90bb2bee1771ed3f23bf462ef3fc4146895cc883255bba586d266d2d8584be9f8e6ca54f4996f4df1c822897be02c8989594fd611415d22ab94af9ad18f5ce9f11b3c3bf1f52ddd8270be9143faae00f2d0deb909d838d339df20cad108a0790acdb26f5c70682ba841a0c7185cbf002fd5da4530e8c9a746fc0ac47e0127a64e9059fdb47a5c5aa9d55283a3cd8fdcf38b7c89b113d01be70cd13e7f113ce9d1dae25bd174aa98ff561e19a0e258537bbcf5ed48301d61baef10333abda8e3bc8f8691b45c91f12bb310304e4c892e4d8369c0c142b9fc874b47131f26b5997cf952bde86f5e2868ba0400e056d1cdd6e692fc533b6148d1915ca9de008ab97ec9a068ace97dfd081a0942d6f50bc639e54db8c1bb79f736322cfbe6c44902b74a36930545403fd74a883b7ac7d695858c09f015568f11c3d2248c44f91ea59be1ec6d4e1b009efba1c4498de0990801756e70638fc9942318680e0ca8fd3b66bdd8f0bd9c2fe3ab3ed6c4d34bad0be40137370bf02d0f85901ed687ae106da2afb619dd8f75930cfb1b9138ba4e4bbc5eb7cc73da6892e8d481c406f0dce25889296a1154af3c86ad656f5ad534b9d20dc727642e85667877b55ae7687eafcc72a929dd09d662f040a47cf3b95ea0782e17c51e08897a4799d46fc3c7047ab3df47750754153969e8e266095b0bb1c159655a95d40d6bd68ff955dec31012d76583c6d4e5d4126901ac11045af976945830923a4a074a33f2acb4c9a6f5b6c4921558af31e232c31d436bdabe82cd3f0a4ec0ddbcbe9beb697013d554701f33c031087167c43156775b8e4da66d3db73d70955300aad8b00fb1e088326de5b7bd3721724b29534a29280911091e09aabac3be5c17e7fc48f341a263f062dea76a1673f215424e7240cf06668ee23e3978b53a3630038b2354d9c202325aacc4195e9c784119461411841b4024146389979458480644f182b8aa903b604c8431484c431fbb070548653e4739fbe9743a9d86ecdb98fb79ff981da2a83073bbe423a9ee8f351d2a5d5dba94d2fde27d1e90ca94ddacc57eefbdecbd2d6ab852a8e17fdeb7bfad9b1a73f006731d6ee1c7ccfc38c893c10f98c4fc7bdd5aa2a238f4bbf7ada529bad2670ec257e70fa2ab1389b08497319e81605e8d40a7cd9e147d07f49dfa69c9c9af5e91b698f298d230156969e8db4fdae387ca0ffd55f92e3ebca18a172eaf19e6ca75f101f0b322ef33c736a21f42f39963ac83c79a8ac75e0e1e83498fc5ec068fd27870f0618d611863d8621816310cc3b00b85990e88c9638eb424c5a3364cce7877729ed1ee724dbd3b799c811a8f93b73b00021298e13a4d07a656a618fd4308a163de417f501dfa0b72f2f620b03b69303c0d022794b29fba0e011010f79daaaa02611bb550d5002619204396ba8ce0336ae46b9ce72e870143e0e1d99f9caab446134aaa991e6ab0060db20833141404060a8008a2c265872e2d0642d345c6c5cc4982b87e3084115c65082d668062f0040927b428a3e84808403f30f102841228b0ec0004dfa52fcffee454b1ab7c65e3156909084b45c801d358c454242e8a1e890b222e8652412de98aed906c35914f2f231f83fcf03f8e84d779afb9cb9461a189ec6b9932adcb757ff89bb8d0ba78a59e04074c7b07cad32c30046508cf07f969a096f4a7bd7031d72d74b90949d701ca109e574540dc1d40ff5a6feb6ce81e097fc5b0abacd308567be114fd6d445e78ab2bb82fc0675e665638d35c11feeb11b99c880ab0ff1d79e1fdfadb5ee0a05f8ec8e53ff2577140e8cbbe508af05fded0396d7e3b609743c72e6f88ba7c986586f2a79a2995a8ede672c9c1154cf54bdf0d561b4e9579b954f10a3a0eafb44d7140879d3f74d58d3270c9544fa918e5d7a6d29e13a7521cea282ddfa9f0d0f57472d475a55057dca463ae272eca2b42254c71544ac714aa74f5e56581a6f393afa603f3d306975c7c49ef9ded81b2a2473078b8f81884e8daace940a96ea84ea793a6e3e4a793bebeec3169b6d581aa107d66db2a74157d87a2ea35d754539a277f9ae4209230457c4ac7f86cc631ac47b7bc9a19e5ecf1e4d8d5af485a8e3e6a5712449ff9d5af4949f4f057c6add25eb94e27eff6cac94f27ce4707fcdad66d0f5e8f7c72a80f639bfed58d6532d324709d4e1c0d7b459b681082424df96ec990198d0a30dd98f58ee699b6a74d7f6df0a4c862e82f2a36c511579d838979e79283464ccc59932e939a20f90bf59ad4e4863fb9bc300c730cc3300cc374602e37b8e4240405a56d4243de9a711dbca59db6939cd9b485bd6c6b92b9a6f98cc665dcaa59d1593b714b3457bcf21d989cc1e6f039f9ce85d3693f3296058b8e299f30943fb951ca13e6acf1c0a45c7e4be44cc597b5f634d5744877b882ce4e38bc624d47eb8881e697b6e14099d23bc736cd4fdbe5518aa7618e61dbc9df0db010f3999f1c636d022d2cc250963e263fe356bc8a7eda70bc4f9b74d4b6d2d2f4faa72b5b8d87e39ca04c95bb4a7543625bd1772a4829e58bd811734e8650357995aa32f725ebe87b2f83ef71433b4e50ed0127fcf5af07d536ebbcd5bfcbb78cf94eb978eeebb5067d351dd7e2f00ac75da57aef82ee4d6677e36f703839bc62b92d099fcc2ef58cc3ef317cd76bd8a9a5cb057d5d572f0bd1d551abf34eba365e5d3700af0478f599ddd16bdb25b35da53ddd9eb626984bcc55db4669963e1c60305e9a0e94a603d374f46ad66f667de37505b5627d6d3360196bebd86eebe468761be4647db71978b551240e3067ae00500b5ba5796f66371a9ac51c105e4121a6be74b99c9174c69162d4894b498ee786bd4155c84157bc83768b8416227e78a83479787543c7f3ecdb5aa27cb7523cab58667077af2d1f7d852e5fb8d773e818dccbf7df15172e0655db1b36480693a68b97b05b5c3b5310f68bda034cd882553754704baa049e736b581fab216b5adbc1fde54f7bf4d7a594ac6209616f3293184ae371820f9fb4079ce010a6f057b70f250f55034218a3632d25d78d202707453540da32f4bac509ed15698b930cfa30314c8b318b61da35b1abbbae4dd3361b7e6125687e617e6d26a41cd3fcaa717f1b1b1b9b1a1b134c30c135bfb60ec85f29c75cab71ad4673cc35bf5cdb3a20af39b675401eabf14e7313b81bcd6d1ce3b41a27c16b2e0c7b50d4d8406163b3753f30c3fcaac1ae19ed72f513b6eee27ee067da8c0d28f8911b0e4ae650ba8cc6311a282e1a9a6bb31180000210000000e0c68d9b1b145038e10495ca04136cd828a184548a04126c6c6a6ae6a4a19999d1b42cc33014ea742aa104aea6c6bbab47e534f04b701368b82ebe8dcfb86a53c531c375f12f4f6d7fb99a50c2a68a23c575ef6d5c55a7c66d6cfcf20bc8773f30c80f7c1b5c917d12fcaaa9f1d66c780dd779cde529aef3bfba1a4e27f780cc777f46dbf41d080a355bbc276c78b6d928e10495d770a9d46759365397d7788d5f279c70829094d7a46cae948dd7b88d5f5f63c209a95409ef89d47ba2041b365426a4de133636b80ee86d78cd66534209291b1450d8945935a9140a426c04b1912ac1860d1bdbf4d66cf8e4bad4dbb051e329ae4ba55242504d485b9656082d9a5e91b478f29d0b18cd3e6f517a45da72f4067845d282caaf52609d159801d2d97924e370beba21c34ce85d77e3c6c302d387da50db7e165fb220f33d8f39f6b6b527dd86d732f6c775d869d3bc3ba09741962bb2edfb3eaae735ae43053d74242d90609cadc65c07f42cbda5afa68a636f9e4b3f71485a2cf9e79ab1a6396ac35cdb5ee87914c67da0a7933ba43ff7e9d574a01ce33a7eacd31ceb50fe23b3ad938e6d97abf60411d2f328ee033d8f72144704e53ff25571b49f5cb6772b177ad1fd9382ded027afba69b2432824fb1b2ad6e11484300710c29da92d3eb6f600131e72dd083e72cf1b461bad6f0bc94f66121295d0aab7f1f4a91a0f1d7b4f53b323ce4c3782879c5f11591f773f77acfbe97baa0998e946f0bc5d549b5180c1751ce79c15208cb088f832b8452033d0d0308857dd1fb70d5a2166350632c7b82350a4671a05b435e3be741b502decda4e2fb9ce87b6b0d52450f3cfa176bd60f3cf00589451467f7ae299c709f10a955d3b03b2fdbd5596effbf01afb74771930e4ad93ab1196ca8093abce40c3eeeec69b18170ba316cad8c95aeb3dd661e09d19c3fa0f19c668fa7520347084cacd40c3eeeeee6a2bdb0d8241d01d5a24ea0b442fb8ed2fa0af501d3c6b9527a24ec32537081414e4ab9c2b939ca4fbe908fdfc704367159955d3d643d53b3fcc62ff4126aa56aaf7021acd1e0badd0b3bf5943b3d87586768cec0fa98adef989f3696eb92dba4fefa878a50414e4d33bdabaa2ea9d1fde5c8a9bbc5205acc74d6e44f086d6565555c90355a1abaaaa425555857a3a22e88a2ea1943edaaddaadddddaaaa8a011105a638dd2e0b34af72a5642b41632407f1d036be7d87b4e77d6f12df5bc4f7aae0d787b815da6d837628531f5ef17cfbd31592aac39c0386e9a86cc6b59705fee15bfa6a3a88488f8ed95c3736dc0e7e9b9a3d5aeaacd5be4538f89e3a3448644c8932c5a6e6badc877d4c8e86ebe60ca7715ce7ab5feec475abef5429470f5e754fc829c92620bc228c115eab2984a7595ae62337437cb8520ae2f90d6a143b8a33f223c5ec548cced4c980fcb00e8f11d541f9ee0cac03395436e397c6659b90998da759288e065eb1f7e02e8e5b0efeeb9c345a8ce703fba87d7acc39678f1ced3e397aecfaf4c87256e0e996bacb50e21f17a723aeebbadac83c713e381878d5e30891e3227cbd234f93c0f3f702fcf7972fb7b30e0eeb4414ea0625d8bae2a82084509799795d99873e740821ec26b1e366c1317adce17e5d3af43fbe1ef3e3ebbd6bb517e03eed191d11ca7e2de4e974da54e7e3fe81b65a7253653df9ae0703b37a470f5ec5227039bd139e5f5783d11c9763e4b89ca352d6735796b278afa9ace7fa3c6e529fae74f5ba1fae9a1fb92146b28fef2337e4c8c3b70553397ccb6ff72dbf0b3691db0d293965ad6f8029ce748875732ffb88a1fd473b90f619da85b4d7f0d3ddcbdddd3ca74ae5be5a754e8e0fefd1ac4e323bbf02b994e3b4cfdee966028361ca174689f3300a1d84cea303399672a694157d5a81fc3a0f84cee3e33f66763c3c57f88de95658e115a90c2654898c7cac136560963bc47cc0d0351b9b6763dc3e0af3ec34d4f0e4d97f9ee862228159d2cba35816092e9e1d1e315f91c004fd116697031fd7e4f2d95cc6412f465230f8048faaaae6ac5c9fe8eed656a59794a598f931f39583939a99aed0420e4f96ba314611475af3e0134f68115ce0258d1da400892108b13551850f48c06c31451a2b84226264de272f80315830328872658c22f6b94fc41823c91534d448c153c3076c0b267d5468c831be90085003aa810228a50a069f1e181a62a8311130060e6588f1c5698b7792f38f52eae504d35cee628ceff52a5fc1a99965df65057845128308317a78020d662632880046d312137b5404a6e28bbd50dd0d1198994f582089b1c3cce19959a65250314f317060a42f64be5b3d30b0cc2e2b50f12a3539788339e76a31b157a42e44ff78f5aea44bd02b52d39227c02b52d393efc13acb8457ab380b638af96dd0751b62c33f7f43f69fc375e51f66b746eba46fac91d11a298e751fdeb7d401dd69818186b2f4d767d09e7defb1ad1fd468dac18c6f81514659fa9d8af19a88f8f7cf33ed511991e389f9e73247df609d9fb7ba51d4a58abc670ff2dca78623b37529e1d7ed638df6a88b96df45b2f257084ab748b4f86b1382d2593c6f3fef21bca1ba826697939363858c75c0f822bf391f2366d7c2afb790e36a6a45c9c8c0de86bded05ec6dd8db5ec0de86bded0584dd673c2ec256737296d9871237d459d7c781f19cfded1ee13db80a5fab2a9f66fe31c3207c30dbd753d8dd1e3ac2c971f73566fbc5a9aaaa5ac1ce52e2a870b4e7fdf3550abc71ddaa8567e408cf0a2b64cc7a3e31e6325ebd15cc4e3ece8a59cfe512d39bd5fde476dada5127d4e9ad78f57672dcb4f585702bf0f0ce93cc7c44034c972e954aafa4a07a1e1e9e6765b6773ccf17a757f499596f8ac92c250fa64f0bbc7acea35778fea95431f480c1077b4b4160ea53ccf8cf53fe1c877558677bebf75d3db8ffecace9d8521b0655f505e13591d712b3e3f937c5ecb2f899e2781ea1985df6ea06d09e22f3d99fb39405f6e72bed81fe3c851cde91d17bf3c9c1bdcc331d0faf5e0b5b8e1ecc7a0e37f858cc76e6619d1c30dc70de91dc6396fa63874c4c7febd96a3af6c62b921731f87d766666d6301eeb3ca4d9a996025ce9a14c5a1ec98b2b332c0bd0d93db02cc41374f5b72c48578fbb9339e6ddcc7636d63b00702b293bf9267cb77a13769ce03ba0261fe84204649ebf2b620366e6dd5d4ec04c07e4e464e5174b0f7ea700f343f40a18581ee5fc3c9ac9436d8786e9b243bfa0f2eb5c202184237c6103e5f244b3502ba2501ef440b3d8420846f86d0d02403510c202b858400a66ba17729084f2c00a15ac5885f975ae0b0128b12a03051458514384005ea055826ef89f2bf517d781208b9439335d0d52d40ca123845f1ed8975f8fda0e09842b5ea8994e044a3c2e22ec8842fc6a3ca0113b7a8a03a2925f07c81ffcd63fa4bca49497bc2e29afeb92525e72ad98e9de010dc5afb3e6009aa35f97da0b3dbf8e9de0b6aac2c9e5d6aac2c957bd03957572bee142097f62edaf2050065eeda33820d2cb841c11ff935ffeaaf138c00fd1326bfc76dc9f5c3a767abc659e4891f828171ec5ade2b8fc65d001402fe8d16f6b2ff04b0e880cbcfac12b9e418cd909e11eace32387575b0a2b30279e6901b6ab36453c5f91bc186a4c8d07066a44a0c91263bc2412d313d52b1213954fc9243ec5ab45622a7a5d15d4c53c35ae9031f288ab97ae9bfe16ead77505514f7d90cb23508c58f44eb9ce86e79a6011e5ba75475e3b220de1093776e423d769ea31a05610b5509e7ad59e142e6f9694337bbbbb45d74ec8aa8190dd0a65fecbd9defcf7fa79ea5d3142f8ccf822e8a333ffb6d1fc82e85b46efb6dbb66dee8697b9cead52cdb9dcccfc63d41e227af445f8872c99672245e443ff89cf1f37fe1e7ebe901ba265ca3ce3c01d4c1d489eac0afadd7e3f8d31c608e1855df1f278c50821112e26f60a185c68f4d590ef41850a55dff30861e40197a3c0de2fc71acc2efb55f67d5631e7cccbbb459061a85ee7bb92cb54bf505552b68af90b966926c4eca6770fb7ecb1859bfcdefa7593dfdabcca53ec0af985485385a47e1f845048ea95016333ece870f9bd77cd8710420cc21cbc8adc7b2fee3bc2022e65458559ba861566e9773c4865b87c271fa98c131d3e0cb10eaa464712238c9958797d1d489cb08e5af9f2e4f5db7dbab71dfb3a7c10e2950e1f8458e7a67dbf393e4222032686116b7041785dd745c41284ef4108e1d3d7c42b7dfae5bb1ff8c583906989bf78909bc0d8852be5a3bc72dd4fc318211398724d685ca9489593d9a956f8e73ebd9365abc77537febd48e5a3ebdb899a8e48e5a147a7f107a73fdd7230ebc51eac93b94f0ecce1c9318dbbe9a1af390f7d8dbb99f1209a5f3ec35d2e1de8e3d665ddce6cddfbe81a966d408f6d42b247497949b33d66610cb160ff79efbdf79eabde1182fea1fea150f04979bdf8e07b6f677a1598e274d0e89f630fcc62bdab3deaa3389e63dda330b24786528bce7513afded16a8a47513931fa57d4ac57f41dd42c2ea6fe7a3759090c5fa13b3ccd7a7e94c59521fc53ee727214ca15c3a2cb2b4657d7b80fcc0b93e130d559a977de52b39e3371137f6130ac83f2e72c86c744df23d68962e5b94c21051c9c6ea37060fe418e978a30a1f7c662989b361ed3ace7a88dc1f0eaf969e32fccb4c45dcf31189d9785c8b1d232a13d90632c14c7f3c74b50e6b2d2b2c037fcfba13866b39ec72666bb2e0b3641af3e9b64eec36f4aefb052679c4ff9e74fe967bc7b57fe266adb4d8c71cb7cbf49c61db161e6b5d27306f3967e288ee7aae799bf30282ce3364ab39e87793b0522f1ef229aecacc4ab072167612d526614d6d19b8c955ee9396b79ce4bcfb9094a4e3dc9a4aa6613ae31b9058e8757eb9dc554ef56602e829966c426725e6f6436c65ce9ea54f96a0b754c5bda827ba47d9d683f1e7b346a96fa4f95afe0c6d32cdeb4b59bb694a7f0913a5f5187634c7f755775ff2872aad49d95961b08987260aeeec014a7bbb05d67309e4f5aaad034a72ccca05fa2f99e32df51b3d8a59c53a5824b580766e1d503b32cb0431e7407565138a43d8f83478aa308ba0365a02cf69c7f4d2cd60b430209d0e83575ebe2bc9853a6f44e5968d4ac87c5dc29900bc885f6a87e5050efa8360add6977555050178386aa10e9a08bae70f2ecb189b90e9d680f0c94051633b78bb947cf0e8dae98dd4e99a23dda438a83b983dc55aae864c628cf45e40fb9ca6c73fd6476ed8407eadb4871b491ee539596f661f21273e195432ff386375b6262cc7379590b3b8361676d594bb398dfd1d1d3f2fc8e6edaf7890f9418d3da273c80819356dc6e9af3a13ea0a2c503440bebad676e62e8d6e5fb4d2eee880db1530dd16276dae4c5ec74494bef28162ac0086a31f683163b8f5916f89566a74d4014077b511cac12e23bec3bec3b550cdd8abedb901dd8b7eb68122f6ea7348bdd8bf67cb7539a96853d5a15d8d92f206617cb3c7b6a893625ba826a9ec0f4574031a69023c47cc5815a474c25cc510bd55262386128cf3ce3805a1105bcb4ce5f58475f4e1a4cd469f32a66a78abdf1407a82ccabc643f5ccc4abe67809a231fd797c7af8e827e60ac17c5407fa935c2724f597b78095313b9ee7e17c32262e8f575c35efe891e44b8c339c9c6134af0b42082fcc48caebbaae6e9af1c50c268757ae244aaf56ca80f2aae9809c518e115391cc78f2dd0e0d098919b3a3ad339afe0d9db184a488b52c8aa9ae1cfcb7cdc79ec643dbc1bafa88f2ec57e381ca8aa672ddd55d7ea5b665c2ab1e621de6d609af56723798b1c9bc7c30d9e393c95c0b3598585c626ad7dc400859b1207a826487c68ca05f5f2a3268adaf15d65124348cf0eb7b65b158f9f5d5022f1e4242030cd1182abfc4c49e4785674cdfdd290b6394a9494a9abe877298447ee66f0f8a635da66145a77784a0c0df4d83cad098313baf3506ccaf2f13d6d9b5a168fe0ed16076cbed97c3ad065ea90d450fb1e8d712290e0cbbe236f14a957761a05ae2378ad5eeee122d125e010dfda2106730b589683a3a99fc3731b43f7f7dc4553267a5f2e159bd9b18b64703b5786e76681533985eab98a1f4ec3716781707a459ad1b0bf40920f7a3592d759da9a962069667ee87bf86f8ea8f6b35776381534bfabbfc41ae87b41f973750ebc47590367d0d469a15b45751b3b4d534346bd79ba88bdaa89d7414e60b07f6ad22863ec20ec4d3dc8dbab6dab5a553a5f2554eb3568c7eddfebabbbbbbbbbbbbbb5b1e59574ec6c01d51871c50eb39f6de902dc3dddddddddddddddd2da7ca8d5280690b1661baaaae15e525457f05313bf973648516c9b6e4949053655e6666666666e69172aa7c05492960f23ffcec399d1379eb7f9be4e75e61b3d40d32620ed3d755175897eb735d85c599dde554ed00531c76ff65397547b5b0c1981e80f08312455180924012a3458a184dcac0c1b7882d93c1ec52377ee0bf95f6f02ff117cc4decc3189f54cde28db57387eed3ae6a54fc81713b6276da8387dd2d71d0a2469076aaaa6fdfbb349ee249d5a154bf9e3e9452218c2eb7e7d7061b2af9c1f4aa60f1a51392f9b091df1899628c4d30c218e18f2e6064628afcc35196e2550c6697eab2f752a96cfe605a1fd6eb3a752914ca7db84bfd721dcadfe5aade610ea652170b6697752ebca76bcc1db04e64c1ec5ef6e21193bd475f377cdd31baee53c2dea6aa1ae3c0c4845446962160dd567c8a575784af39436185a6220d61c977d93b698ff2e007aa6184a6eeeeee6e1962529e0347840d681c11041920c8d001870d93c587237c49238d2d5e5421573aab8f0e6406d659b5a2a1845495ee68ebbd552fd0db4e0265e018638c31c618a3037230a2228d15b4a00c325a1b88419517a0618496222eadc8f4d1cac70883c4e8610483a4179411e2075d50e9e18928987cb10416672c11a480fce2a5394a05135a4bf1e2a52e74c08b255198be28c3840468055d960883c5920e4d4eb60b2830ca2cc97cf9afdcabe252b915638ea0c419517c09a306100e375029430652948c386387a0c4755d314028c59c1ac30fd8fa01ba0cbc239d06de51fe813da04b15021efa2a073a0febf8b00ef41cdc6b010fc5da1bc330ae25d7c98beb268429de9937fc493fede1ff95dcd990edeb29ff3835e2116176ef65bf6e20eb409fc3ec24aeeb5e2a8e75047c6f629efc0fff102c63dc7849785a79c5852de18e1e026e14d834d9d7a888995d30c9c0dd9e131d61bc21c6e81162dd375c8133952dc44cf0faaf3d02fa1d0cd3d783ae7e3ded775d9777af566017bf0e75ec6d99d4f178d5ab8f57da33d17dd8a16ecf444e9f8b70f91c436dd96b9477ef51cd350a750a8a635d915eab7ce46eda81beb9ae7b7b7bb57be671373174ebe4fb4d6495eb07c53c866e61dc111b5a9863d70f735b6644afcee5bb4c834e38e90e8f6916fbf39b07c420aedfed51a3fc4da1c5775ca45180335f2d8639c486a06f8eb25714073b17f54eeb40595d545454b49445c76390bedba3a3a7c31e35eb0aaf160bb3d8b938f9cd62b403fe1e0d053d6cc9ad09e6d9b64bcdda2aca62d741505f31a4e58767c7b86d3053715c91351e7af4b03bf243f6e8b9b51a8ff743768d878eea7e906d78107244e43b0221944fcaab3bcaa908dacae99d76e9cad363cefb48f9b12d2865aeef172f382d73ce0c30269bc382c86473fc864ae2c0e0d38355be4a0aa2073f5f938290e2bb1c35aae0a420be4812c2054941007134037618fde2e46cb10e1fda504c23bd73727839f409e80e4b59d04f781fda73824ac1cc213c643df44eb378e839ba23792207957b685c35340b9e361a80340bfa89fbd12ce8402d201fcd821796e98a83c8a638d637d92cd469c36e62c026c6298a53c9d92c5695aed132843345c2dbde3a75f8546210c285efbdc7b9005423548e3080cf1b4265b15fced7ec33a0c61823848f45185ff3c2196d7292d28a2b5b9292484125099531267c4d4a02c597c9af49499cb8543a6796d3f12461179292c02029c9d067af4948c8bc1214d80bc2061d65ecd357ef753cdaa9d2c6e03bd5a29d769a04fb7427cfeef3e4939438f11c245b3057af4941a4f136af494180f11d8e1106bd20e2091153d8ca6bd210639e791d689708e6ea9d776f9d10c95bb741446386c06c50d39825a5232d5796943c67c593d3f17c438f2e3c6612942953460b7f60f5cd0559e72956698d76ca4ed9283b65a3ac9475b2466bb44ce40cd0a36c48f04e45c2a6cd9ad122d74121e6cd03b4eff66fa2037de47e55a7c6f9348b0bd317314bc50a962c4c9e48795c98be888154ac60c9c2e48914c985e98b9813152b58b230792225c31c9b3333bb5df9b7053979f61dff89eba0b79492f3dea9712985acfe8580e6a3d76cde3b5c98be88592a56b064e12f4b983c91d264be087d41f245c9e3c2f4450ca462054b9618c612264fa45c64c2100a0349184a2417a62f624e54ac60c982f2b284c9132918192f425e9078519275e1d285a9cb972e62b4cca795b4d064333333ed331fb90ed2300965c0f09116252d4a5ab42865e12b7cc4476c05cc3655e91f2b0f14ff701de6b388b9df2d0425934f3af4cc31f8a4ef93ae9fc94ccacda4bfc032fbf9cc9f76d2951682cffc6933d29fe488cc484765fe8af0cfcc705271c8d3cb11d06852e33a239fbd203f6b7fd416a4fd3d4fedd0c89de9a70d8759d2313ebabc69467fdeed329281b1ce7b88613929e0f80bf29c3fcb122c4d0fc7e4601643e83eb63bc18e1fbce2ad391978f5727777975b23bfbebbcc33dd09fe713c3e76f8e0d5ae472a783708c2ece419eb641caf9ec65be01d1e9acfd336dbdcb45934dbcca6cdd2b656a50dba548cf28ee87088b99f79f732e7a1d646498e3776425429eb268a879e25c741637e157a0b7c3974082184101e81619d77714254e9710b66dd0863c9057b123694323434a4830e3af4d0430f489020a1d1276143d891b7b9ecb0c30e3c44f878881036ecc8438c909f60f0bd6667f8de763005b3083fd884cc5f1e23731912f1b47517274ff28ad12fae63324599f6a0bccb32ef321aef32cc6d9c667b9f6df2515bf6368e72cc668b8eb241d9d4d4d4cc39b56dc66936f9d9963d6a9bafa94ee6ec3328c730c7b42d3a86f5895bbf76acc36b834252dffe382a813db8edd1b9617408bbf93584dcce0d1f723773ccdd03ec3d9f8650da20a907a29753caae5d7292875a09cac100537af4ab25d6c913732ff07327fdc4c95dd7f68e2513ac01394d442f0b2184f02d61526633c6089b71a08ac8be4ed8673f272d04f234026944f2803d14b8c06838c88b5bc6c47c987cd90ce673fd18dfebf8de7b32b663efc177043e6882183509bc87106edcc1de412e083b76b46139beb7ba7a0eff71e4a8f05d2fc068de75f973ecdade0c263b3bc68c2396e0691e3311095585e73faa7f2e8db426810775f5fc2481f7523ec9c16702b8479efdedd041341145e00f6c2545e004cc00a2882459084d416600442c31264c109c8c49028c0c9ac6162d787085135c7860869671a2c8092114f1200a17325465509f5936a0aa1ab8118421149103297c5832c6c98c1978616a22093292c69001e88828863842891884499201096058c1410f5c04799981180418230544528c41920415404f888e80628a951438c1e58b06948ca4187cd1c3971e78589a61e98b279c20cad2258c3034a0ba011732c028ac818415445de800060fad1b4330d18352103c00518617193628537441d484161cdcb05d8abc60290b1914e080430facb006a8d0dd1c24a5c05701ec9005efbb0b51172274a5df5dbfbe4decb17577155252cab36738dbd3f72159ad5d47a6dccc78c5ef090f42cf7ea3b96cbb9183d9654966a75a2325b33c7b96b34c94f3ab1573d102ef6cd2d006f1d2b3ccc199b089d9e5e4ace0384b66ec3329e079b71ae2202bb3631e3a3d0ff50b621d21eec6c7f3ed4f7ff1a05f92a06ec7ec98260309ef20d46058a8caece45f55cc05c32b299b7521a1da9c83e79a82eb40e6d971f4e8c6c773f537836f3e78c5ae0b66881c177054579efdc66664c82d87c5d2ff75b7bb0a3a10b1a6a3b3959d738ef3deb614274a41419620f0d00fd160675947935060f4eccce472c5e95e94674fa13b875b61eb9e0d5de186a3ce4cd809d28c4eccee0dbda1ded93494c57e03110f45cfac02a31f93343b99bd28118b922544444818296162a36c231253e5ab647dbbf8dd4f7fbb90ec9b4b3d21cc8e8998a8777688b928cb6176efdf66b4051382f272babbfb12622ec7b302afd8230bae2db393ee9b24148505b3731daf39b5647639392b1cb940e32e84103ef9638415c0de59303183b88b56eab6094ab1b32d4dca01c9b37796e78ad3c1a3cec22cf62ba96930dff5c3ec78ccb37311af9895f08a994871f07bfeb6a959dc4acdf2617652e9d983e0d197143b27e1a0e5d9a702d8b37f00f61dce73cf9f4141413eb480be3bc78925ea322543377c412204e529125e11b102d8a30eb3cb7a87be7ca7629d1e7ad5e907b3bddb21fd5def23302128b06bef6d7d688778b53263761bd48d0449d20d529e7d855883eb6476a9d8c3153b10e3d9533a3cfbe90161761bb44d7486d084d2decd3fbcda5555fd3172641e5926a5e75d0821ecc7751b64e4c80fafd8999e99b689775c660ba6070ee220fea12929a8685b11caec5688cce330d939e8fdc695c09eb7d650c22c5d3299a89e04a630a8842df7643deb14d10c000000a314000020100c8744429160302854c67d14800c8ba0406e4e988ad3288b510c21638c21841820000002003233a45515386bdbd7e022303e8890492f8dd7465338dd39777c286a90474699043cd69a5b2da4addd02a635e971a33c292862fd4a2689d5f743290a89316def58e00fee32058058fe7b598e7119c68c175cc461d2e5591e308694b29ce59e4fb8d1f18bae33a1232d95bfae3c7433ac552d2a0e9ecc12b3c0dd03b00be3a0ce8293c8f1a19cd7a448953aeb0bf9786a2662dd30d4a287c875b26959a0d6b6a58ba3c5a9c6617021d9aa1a8c2361028de9cafb4b8126d184fb5d6606e85a7fca16ebb68dc57aeec05c7846ce7c70d9d0febc2acacc2749d1e1471cea42768ff5b5def5f65b093f4e0bf4aff6b91bd9f713ba9882157f726444682c1ca9d097bf8817042ea34dda67d2758cb15b502d5d0457d3d783cc31e48e8bd1b02274743159e2430592d40c6159beb1286de1379030c0ea3921a7d69ffce4914b0b09689c055b300aec3e214675b44d4bfd8c12152ff15090637b042750d16b6015d68c0f6447a7b38cac9e6f0966049d1af179596b94bcfc30dfdfdcf7953d82211ea693682e29297a37c3a22b68f7a647abc89515015dbc4a32dfcad66ede57767ba1001a9142a0c5c404a65630f57bb08bed56f77d4a08f13265fa3f5c8e8622877e0c110cf48ef91802cfc1b09bfc381ec1ebf9726ea7115643635ff7a8ec00c107e54cd5e906d2072836c502b791cfc72b670bc22fd28e2acbe993049c82f137aedda7f355f9ee748823e636df28c41ddbadf8d512cbd038c13bedace8fd132388a0ee9a04e055166d08f3f611dda1a11e0d3630ab00d12f7a78526e21a9cdef52e9ebb25d321230a57b26c44482f9012156e3d101faaf9415d4990b3f535e85a0d2ddc1b09f3c73024bbd69bc1a298fee7807fea9b8591c56d5628d98cf1114fdb644021a25838dbd66283a86e563931da0b97a47c2c8f99f5e4d198da3fcd90e1e34b21c7eff45ef92cccc946aa5913cffe1948e07e76c72f29a746bdbbb1f8759a86a312242f6d6825410e7082242064124331a1dc32d1061a1c2d436b4885a1b640f016eb04e0008378b445938a26f1c82520d9f46fd269277550e42fb27b627d5babeef2e9f724999c08cd23ea5d62b1497d2c3117759d6b55ed7dd1ea1a53189d929c6d28592b3478712e4527bc349b8005b138f6036e52338f6b42433b7ef8b479f8084414f8b3e32ae394c58fb9a680b986414e50d2e47342a55fd22162d003d892c258b854af31fe626815b622c2aff4b61f744b8bbda024430f663080ebf627ef36c9ae4f2274ae81e00c1c972b6b2bf8110691937a015cec2db140a981c16ab050145f07ff530e41ec162c53c1bc5c21a9427d14a9ccedc24aeee9c37a7efa0fc44d1dc181c96e4151c89407691e09608e8982f174711db1215eef07d532a8b0e589927220d2a0ae07fa604608b4c89d10490109bb0c2c8d6a9c77dd1a0a2faced0dc466d1862f7bb292a72a2f5fb05c5d07aca85cf5cf1c9ac42a1cc93dc17784879636bbcbb1a6a4dbc5f796d503ec6e532a511fc4f6b30be20e654701e8a0f875969f06877a1591222760ecc187c622f6987847617ec52cf66e2723a26191e84cacb2f640ee2e8d9d44789da0036c724bf3670fe743a66888288c8e3c3eaab66cb5e0904ac3b7de8a2d232ebea2a6221ccd5b18a30d3d2eabd3662e6adef3bfafb844cae7cb35e53bb626affc5e03e69e9adfc698447ef8603a79189e3eda4956465c6ffa176ac8c026ccffb4f467e530d70ca86cfb8caa091c2dfae5a655a55f9a971b43596c0a4cad004342543953d5cdac8792afb16a599440cdbf2a805e4c9922c4f062e9c360d36f5066f9d725eecfc5354f5949cea96087079da12a8339008e72b0871268345ea4715280f16936f5554d5a2425916f85075c1788c30b2df8eb41a72b649d92d13dc5c020c45781eef8dfdc928525791ab1bf84c050e5f064abb9ed9d9e5cc0c71b8eb21d4dcfbddb31c5fd76caaf5c4efb4370839d5400f87c7b40129fa65ae4d7a895fc6e265672d06615fbe2d3aa833e95718e98c09d57be742b78984817e902eb791931dd6d2fe1adb8c225d4a524196f9de776c125b286966e58db429ffc2e841f70725ebef85ac6e4f16b28c3bbcd2a1751fbc443902a8db2d98d3ba1d2bb76ecc3cb1813ed57a33d0ae2666c4e05ff28b28516f54714e439c4eb0de0c6fd155c6b3821273baed633c7a2a728ab94e579a590492a37464241a04719565d87c85f6b81433a72b507f42fb95a85fc717e607afae301249a9afdeee7bfcbd4acc0579c66e60dd3cccb1ebe80e77c3630d5b2400eb18569da7bdd8c32a21dc0cf0230021a8f81b7da3f075aa498ab448581386fcf9f13761ed9c620eafa790304aca23888a05ac7dceefb3984aa5e8a459663fa1fe3e5f5fb34116350e656cca7ee5172d0a27f1bfa530de3ee690125e63f3202db2093a97104ad6a689306c217a28a3c85757f68f8c516c562dc2d2c291e706121c8ca3f16dc1b288b7def84e5e7e99ebe68589a922070f0a02772ad9f4f6fd58649e0602e859231bc653605c5a9b3584156a349be3a8499cef5b5d82c390ce859fab5e86f2dfe31e9f88568fcfbee5d0d375162aa9afea48e329ba5eaa6e5731d9cef6d68ad86b5186a15c5e5f6329652f1056d7932ef82ad668c82738d964378e6e1d95ccdc25610eef1d7714799e91712974f6d00d06d79d4966f8253bf71b8d3378335707f6d793f42f86a975bc19622af62e7d06d961c08f4a85cc30a6f56fcd6ca44a9281e36809a2e20235a7bc486035dfa1c464d08ee7183266f29fc5dfdf758c9f8b240b2934a2b3aab782bd16ffc6570b5755ce9a64d8f4064f4927fa3696ae6be51d988f70d725a38ef696cde40147e18aad6b015fac82f80de3687ba13b87460a13107b2d4bb7d7ed8ca3cbab52b22fd7a46574cb408b2be04ded44eaf53cc4468c9923a495b284291af4639f1c4aa156ed29e083cfca36eecae130a1b310000e57261d4ec6c7a24da2018a2e75d379473cfe941e2fcaa450d0584493b46c581d19a0416af979ffdea31a587252e777c1ea05c70493505568b27cdf96c3e5fc11c0cdb3cac002d65529335cf2cc376b6a2ce3bab418ecb392c1e67e1c2694210db2a20936986efc1a9455c2c514fa668eb44b2499d1b898e074f223c92e199b07e918eb60050ad9d18896451fbe2fb9e66ed302de0863b13911430d443a2018b0f779678a2d3f7e474f5d2fbb8a9361bbb72da648c2aa2f8f8ef84d13ac2dee718549cd1d66f8e340f099a8f115adf07100ab8b791aa50c28103b7e8864aa0293aa6d435ff0873ed7a8abfef81c4dac1a903b8c380e90d0c70d5d22ca2eef9bce21027b73b8c0dc707dd532cc9886018d7dd1b89d819df90b2ed99b53e61541fba1659adaba5d11abe4203610d7fa3d2515399849866c4198ac5c30755f7cb730b7d890d58e1c2aa1c6e00b59955d4ab23acf6256ab67e168318ca419dac6aec51cfbc0b609b02cec6c8d6ee49b4636a173257890ea8d559ac5001a23c09e76eb7bed42f7007a9cf4072c2343cf9463c7023069ddacd0110c59ffcf1c4498a4dc4ac96c2c9961f274fca34f77e45f1c2dfff3ecfe0c2f7562a0ab9231071fd07e5b31bc0393c47fe27622737502a9a2180b64abdd49f2aeb3d0ae75c791b72367a62aa90864a74aa2496ed6c2fd995197a774b8b701b9600f71a99ef00c02174fdf3690f01ff7a13b5f9a47e743de20e2cbb65334734bba215803cdf8e6d301bb6d08c4992e32976882fedaad383ee978778ff0689c2b3a8434479c8256e16e38ad7438770060e75f587dcf787ca21fbbe0a0fc1c00b8cb1303843c3102b01a516c77fcc3f247000440b61f7ca4441640ae6b57dfd48361f19a72039f5914cf13ddbc60dd46fdfa855e91da4b791a2ce8e5873dff361e5c3086c96166d4ee4577f32200efbf55b3db2f7a6502b62eda2ce33770855fece094f03a36009fb088b1e4eedbb438a1652ef5c5a3b486840c4bffdd1ebac362fe628db181a5bf767f4a11210da0fb4f6cdf835f399f14804e41febac07e5008444d2f28e0c4aecf7e6bbc41741b4259b8766f42e8feb186b1f39b8f278aabce3604fe4be18bacf63279709fec83aadad45d4008260ba194e987b7b18daa983e8180c06e4626f6a36422563a8d14f30ea89fc3865b30ca69906a1682c3bb62354471ee2d0db8d51a76d62eec87331cd83cdaacf24a33fe1202d4db6c48e92ef6be01cce34ab3ca217641f935b34e476a82a036f5b74bf43e47ccef9e895a8b7fb45a695ae5da6908d3c4cff292910c189b7d044bc6f3e7de0ab851b7c0fc836b785e699bf5c2fa1c2d6247477ceef1deab8ebff9d01240cc3b2cd7df499d7bc277d7f3fd302518cb996ca1c2704f9ec2a98b5768fe68ae7f45af268ad07a5d4d31495e421eb5d3248e52f5c9e8a8e58a57c973de46fe311f2bdf4b89f60f8f1e14d176873e4b216b0e8fdebee35d1af4dbeb3c55d39adf4c9dd1433bc4680e4d5d626819b6c2133b93d102065d389c71b756be21f260c2fd9c9d6375c8ca1cc36a1924421bebddf2d46d4cbd5c686e4c28587d72ea666b7083f3dd350f51c20c937652635926c4fd5eda10008e061cafdf850e2fa2d3dc6f16644eb28d62df312b083ed30be0da1f819d499861516ddf38de11459160015035d33d465c0865d4109088addfdc3038da414fdd1802c34005e4e671d2ed23b90a42c949b93389ed8ecf16a48fc42d30371329599febec15374d76f298cf600d5ba3acc9a52aef5599fa2906b5e4fc5e624ca4a951ef4b33e683756575d05d143a4f6d888182b222efc0dcfc76cb31a588bab4b4239b049028b27057c9878b8bc16361268479036a91081503312eda4b95614b1066e8ae42c91eb4c79139de33999f0e00cfedfab36e384326416bead6c6a37ec00dc1680342b792ef47f993e8251d2bf727e5c351dbed3fb9ed587476bb1675da2ab9c0743c690f1f602613b2699ded61b8645712db4f7b02a09f6fd7b8f1452f2468de03a46773469e7d2c6e3d0320ae8381e084fc76236d926d8f0d80e632d1f7c0d54eb9380c05521ce188c5a93c85061412ee74c81bb785a7f987b09757405b031313bc64a06eac8424c46ec3d1d0e11c6bb90d42eb3c5459b909ea36011b78b2b008822fb0999d375f0a87b682282ddfb96e2db53f2010b9b5a245d7f43f4be1cff60e0d9848d6a9b5ff6555ae55517454a911d6e1cc0bebc9ebea267c8723310b1fca9a7ef0e31a1597c661a2d25c2f7ea3c4ab32aeb57c0e39c60c1c2483a73a7e09a878887d8adc925002a35518c68db33ea8cfea1d715d40748b8ca41209e8191684c338f7a5403b88d5502076d691307f82910a666a5055936c81c2f74d92f1b4e60f3951fe5a2f2c043281c6202ec8352f238d5162274ff38e63e12a818cd5fd3a909cabc2c6978f966eb885ae435166c84261f44fbecb83eedb2b3ec02a19dc766bc9a726cb77a859b36d11ecc2162ca184f4eadfe6d18570451ef601f6ccd852f833657f458700d683dbb4594167127c75f7eda948bea78e346750b17f64f2e378ff6114da845f181ec8af084ab3fbdea4879d5bc90f40dd0b4f416ac071cbf0c98b8465dfe07958d5627e46c7c7145124b7e74da47447403dca68e9190838599a3046027ee5b50af22e9ce6427b7905a49b640f87021fd5adcb42babafd44f6282de6385fc6bb0333e592da11056bfbc44e58e192d40b132f4ced019f216181cb0ac897e35f55483a5af4d2e751882a57012447b217c6bd1cba043cb78ec29372706bde851bc5e0bdc940d7fd7014ac22adad8be15da27c9c7a5cc7da1c710512060aa9fec66ce63a2ad6d2b6895bb1ef1ac075539930feaa6f748aa7cee7513f32b434dae332b6b6868e64f1410b2630586e65e909e141089f0e9e79730e85f6581126c20de961379efbedcefc1cd7290eeb16c979262b56b8632215d7413010d0e700900677fa4d8889d60fe2c6bb227e1e9a0ea4eb31c29ff4d2861202434108295f075f0849fe0474548df6680b215469b63a4c58ec4d0327dc4f08e17bc97a4554949a8913decc8bfafdabcc990ee9325586c3e19b419c388dba9e97c811c384a794566005807398717259bc17c86616d2291c1f56f45099ebb46266acd72c9733dc3e195a3986d9631b89f2844bcd30f184182f98d5b77baa1c64843ff308b57642f28656e535b1869529684ef7027944bcd0183307130b1ca0b3568ada3fe46182fb702451893889fc7a46dcef212375d6b20c1e91bb4e14cef7c6c7d331b4cf2674fe452a7457d7d19c2305c25cc706e2d2c3558d42fac7f4a97238944c447591fb0324223fcb0a0d40ea4ca56eb27370e32507a7ba8cd2dec4faa067e4279e9215a0469ef05f1b0ece2d4af4fbc249e8d9fd64f08d18a25f94dc91d70233bcb5ab8932b35fe1060e9d7180df8cdfd84c40430b3f69875a25aa26269fd0b61296c4e825221814411035579e9cd78f3725e31a35ffb600eac38d7f2a2b4f1e05794e2860981a5c00a8d8922e92244598dd99144c2e373ce0273bdf1e24a0ec6a1ae4dd1271e24d87bbffcd3aad29bc0c7c252ee1e20a73a50c86fec87d8f280664f518a62e31980962a383ccc8541d631ad0024ade40eec455630d3fafd9712adc03acc15d6938df72a9f956278cdd8f30f25ebc748f16c83c53201fa1bc8c0d55ba2e6b35a930c34cdab8adcdfc9bc037d96b441da0d738f144b219fe9e2ce7e7bc4e057431d0d1f39196f14c7b0980042e4241323e3e64f108a3f27bb2428263a03f7603a56917213a85c58056f5ba5cf7273b3f6920a395617573014e7c053a61471594914b971943fb67fe8a47f81bd43096e6d4c1a49f7d6fd625165afaba67bb1b0abd02ceda86c3499f0db5d83a9c4e79cd1dd7794691e6b10ccbbe2bcfc326adc9d23205a0e936b77497111f119cc602c21a12656779f196a6c00ff4fe4965f97925ebe76f72a7fa332e28ac6b4bfd09c8247a5e6584a6ffdf3ef0b05659b61aae6dad8b87c35d409b1468c03fc9adc2b8890628d6e19ea0296af24b7a5992dd4b1766de847e2b0c87156f5dc44301889ecd7e530acbf5d9140d7f778c675a421f54771db2b21037b04de9ec8312fa1c743ae2a417802c55834d0080dcd70a3ecd45ddcb77dc8e90b027117315599d00984293b32b58d9b84e438f313f96710dff1e70da3e8020899d7e347d3fa2b5967b5051c69a678674dd2c2f0d0d58a54c5d4c9f690a8b7504ba0d44a7ca4ae8a411bc49561308ab71775c2ff00e17355d28f8284699a75ed4429614cb53e20c11bb8a9d5e2d8c7032fbb4de0ab923becb44a487db99e4bd1dbb89d52669be9057748c680033daeee4c3c113130a8588b509ffa5cd77aa3d9779432f1e9e34c1503208faa118f4665aea8b25521be89922989f41b13f8b50621617382b6f1983e3d0943d315ae0be13c567b06a00461cd20b6f6100275b71d2ab0f0b37bd936dd2145875b4e62b31aa582eea2eacf22e4b1aa7ac7a1746690626ec5b97970a53c253e0970a08ed7fd1eb7b6694423442c8c2b3f64965a99d3264ce90a64cbd4a7a55e326cda21b167c7276cb090242eee7c7da6ed01dee9c86493f4649a68c0fec64bfdebd28bb810b203115c13b08951574d5876a0174d9b6a77260c5d767849fad2b1df459612fc0fcb13a2fb203c3efa565cc856415d7c0b2baa6ace4bc23c82b733a379e52444e5e749712645790454603b4e94e32cdc711321138bd1e20a358b7efff266ac7c19ef4914225cea8b5f98519c9487fb38095dc55d071c94ed41db20c6892c790ee1d5cd552f31f144a11526c293b6bccc5ceb90d160da86e96b2388cf442c8daf577c6085fdb08d819d61a74c44dfc17af633d6baa627756d8f7c94ec6d4e39099e95fcdf68302ef2e65e14a2437d375ab4c6279677fd6ca7dd2d1ddd1d9599659131cc0a9ca68d49909bba1e3898c4934a9d620c4a519b5769d1937b58a5eddd66f745de2da1d72d5b41ed44aee62fe64394aef5cca370cae8d5a4dac437937f51109d3521190f78e47116e85f3cc0ccb5436416140a7d7d18c0c24363e4b5ee449fecefdc34279ad87afc8442768fbb6c8e9e47eddfa2387653b44f04489c11165d3ad67bfd22f881ef39ff0566316e27deb09415426034c38d1466814734784a3ac73f9bbfb46bd10acfd0b5ae598198f55702f7d1586c910283bafe369216302abc38242fd4abf36ec352f8642315059404f19976008571b4940725e65c09b74aaf7c9c6300bb5aff74a85b47b2d7f81bf67dad69aa28b72a1316c833ddd446d06d233945b60be453b2d5aa7880040e88a503ba1cc563c1b1e07a6fe8e6098e7e92c0fcd4d87f8a4e3e9ca7ade28d4416582efaa9dfc4e11d1e91363ebf854c11b8d21a4fda5ed4a06636773ff294524e55d1101e550438595284783f4e457a04644a136d5182026f836221120372eca289f3a70e6b3d21c10564e6c4171606c7c73f151d562f12223e03f940f6955e1d182fae7afcd28485d8e16ebd029b6106639517a9f5433674ba532bd4bc210ae74336762934c573b1168eb55b4ea9007a8bb4c4c7b0df0fa422a7dc4a70d9c6604cef5bc4d120c05e160f88f61aa12e38f86e655f877f4375e51d74f4ae264c9cd98821115bde7aa8162ef531915c2589e9751dc7dffb3d55bdfaebf2ff7ff4c1f17d586939cced7bf6c6c57cf1c61d1aeb5b880e8c3c5997a858296758db42c3d7662647e75ff2b00c349cb52a45036db50286577a65200a98817f3ef30c5480b3478059e8d9d653d9048cb4a3efab22e543e6dd5def362305f4af855712ab90e60d775d712320bd09711bdc1c0e91a704ba7f8b489e9396741696e8e077b4bc1057e5be8fe27eec5c75b62d07e2ba547864f8c73737d8f9e2fe37c0566b0bd6dd6ad94e5cbc28d66125a236f5b8c3ce6f80704f5db297700a45284114223f89e8d0b4556047b4b563f3ea6971d552e67f0542f3bf4432a820688acd136cc74fdde006c7f9587192834f616cff3728d8e65a1c9e4fe3d6d907b62a37ecb31337f9cd6008da5a40232fadb5d9ed2ce986e5f85c7580933a64c7253417fff7d124396295950d063e9d648c0fc7a9aad455100cd5f0db658800c9a1e1105c897fddb151c8efd290da98cb1c7f740b173d670d608118fe46981e97e80588b75e5608cf279e8f2b8081c6c400112ffc5b436412ebec6a64e6149406bbc81161e3fb92fce0c66d003fa9e55d84147a42da6a04fdf438a10228740769f48463e5b4ba1dbd14c5b0e719ccb0b1fd5cbf8adc71f72905e357c4913240b67e3465576ab5ecb644517157bc358166bc1bca7ff4d4f65cffc3086ff6be36d858485fa1e174954e503a964a750cdeda906c7d06f9de9ce75d9a03c6bef454d9f70fead4643150c5798c5103c1ca95be9ff51d1556e90f6cba5f9c203436d8f11cb92bd900dc759c6f445f52fc02dad4c45b1da7a6d98ead76e8079034a0df96f38ef708778c8ed9cc5e631e7e0eb3886b9cafeb4aa8226d33ad881c4adfcd222fad851043c041166deea5d489b297f1237f771e48862c8527be04d220369e67df0605f469cc9c264b3073b2b9f9d7ca63a587f2ca98ed942e3565813a07ec6ef27ec43cbab662f0f2784e154ecaa01ee2bdd75f5667522ed5ed45de555780508530f116b27c055e12a41f4206ee09fa96785171095f5242b1f7f3f96296963ea21dd94b4f222d3de588011772ba0d7f1de3de0e34ed2d3557c84786982290cf9725f6bb72bc9ef6bd134d968a7d32ea08cc5131f0579c43d4db6ac18c46eede6a438ce83ddf5ce7f39ef175f22c00624f2fe3f6a1c6b37d7c7ea4ae244ca3207aecc4eae9fab534785c7096bd062a422b5a466a835d1d6eec4d6968302d02807abda1f7c2e5ac20946e94fb33ad43c99d61040b56632bb1e97d36363c3f21dd852a876e182db97d13593879e08cc71efe3a86345ff84643e0b7faa056077adb67a7e1543282e0f16c5aa581780924b20d5ddcef0810aaa6080525124112b8415ad9ded6a49913e4c02285363f807ac865c82203d34d897ce29d272cd046169f0866a50040f463a56ba816f59d1b3758591e6c4d25a64224ea62bba3fa68de2da5b8011f297fed0329c457178ed074813f5ffc3a0850431a444939524c7a09e15aad9bfdadb6631288cbe5dded0960244a4d252963cbb221a473584a6d65c709da123821988d278d9dcceb3f6413930043e3c93f419e2c708977c6990046ca3e3592c4390d4c58ff6aa43fddeb74cc52d71f171c6da0b9a3857958281b4a75076146ed676241582ff367e408de3ab4a45ee69e7bd2fe1c9bf5060f0e7e198cc5bd6cce21ea65fbc7f0d5d03a8ca132c477bd490bc3614a6007697f1d73103b013756cf7f2265c4c4c750b266077a3ce03609049dd05068101169036359407e11ab2dc6ab7d01fe3ced5d901eaae8279e200ead9b4d5038c94f304610961f1fb8648cc66429d4dbfa20a8d2f01d067469e8a5376c1fb59cc3597227c87d2fbb47f068906d812ce5f116d0178105e07fb2f34b5a38700bb19bf741525443b2cec7850711aebf21e8ad7622f8618b1e83c84bc1890bb6408fcf043b44d1c8ed7081339bbfdd558d06b35fb21932003c69e83469ab24cdc4976d4a7ce25adc1648a7b93995063d43c5d082cfff90fad850510dccecfc7d79daae3249a6d694aee499418545675a6f73dd90f0a6fc81ce5ef4cbb89a12b2cc19ef471352780154b27a4893da59f053eb6d4414f331535449cdb6f72751d66828c9adfed1c0cb39cae5aef8aa702de2e83ed4187153d33d755cf518dc6f9d7f4b93f4a6bf0f7919770a131598b2a60515f021411e48ef2414cfc248759a95672a7d19e460a3920121d5575d240344c0c0dcf17d3259892bdb9d45053a23dc040010a2836fc55fd063949df35ae64053ff6b597af4247b46311f2170d1b44757cb0c13f7cac7284ae11ad6d1a6fb54d639525aaba3effa79422e00ba92266d08d95caa7c17b5eea4a21b55d795f8e227a80919e0eec9d1c09e51752929577cca9dfe85a7f156d6f264a571d9747e9e4ca6cdb0cba73c3fb9fa4d9542a499fe89e179512deb2ba1e062426a312bb4f288fc8a1581254ed0a69a094d1e7fee11d45a9f5144ecbc4c6aca1270e31b51298726248ed76d203bd40d6da5aa07b92ac83c23fd281a384bf780bf9bd894a76179db8952507c1e72eca07cce3b57a11411114b739dcc8c23fd4a32451890b9175684764b12313d95fd2f8d08a8c16b3729020ba84fac87ea4989e4226d8c378e18f789d4c50889e54a68351d54583a965e1029e2b84a7f41da97d7ab036f7393ec86309842c58de504de6e461b48a18569115327fe1e4ca1ca2f1528d8978e5084c213ffafc0b34002825c56b45ad74b684ed4f5918015aa29516e8b2f94add3652ab56380a777ba9bb7649663395538152f24d6ae349b89260bb9bc6e65bf38fcd270ba3a868d5554390b334920367a7a022a0ac9e49669e71660a4605ff74ed2e0ce6a31e2754ca2cd36030c8dc90333413021cd145508440e97108f0c266d32b1e67e56aca8db5e3abb1f28549ce04b1a54197a13be329f72aa978d184a6b4ac55ce44afa702d2138b4ea642cdce951656c0c12a3b027ac197bad6f3981684e0807fcce98d21dddb73cb53b76b72db17a3696a04221756ec7df675adf4eaab4753b93c09f19c5f045b6153a8b4f75c35551528605012b3f0e4903360102cd39a6487d70d46a5cb502697bff4b6544b16b321c572e7871aba395549883cebdc39b285360b4e9088fe89fcd434c823b8f806b79fb8c79fb6185b1f06b15101fc6c9acff875b52ace784fcc41cc68706478410afde420e673c5d5dae30d3324ce62e36321852f61bb0ddfabd3a716f36a0274eaa50d2d4e341b73aee2ff0ed59ede17e11f535043d037b3a269707d8b9e425e44e81da0099fa58f6bc616b50eec47fdfc375c5aed5c981a5ff23d036613381199c6c3612f2153ba64b42c5ede7ca70e4d66d36d3de91d420d6ecc51d7905349ede560249284839c795494cc98b445a7b7f79bd069a49cbaa65a7b79f98ed10779b810d6e4ca1d462f010065d7198dff22e64f2f892675521a7f07d97f0e8d552e59b76e3fbc7d852462ed73e8dfcebae7494316532a6be8b67cb72f45e7579c6311bcd7cb049406946fc394cb8009ff9d2a44df1185956551b9beba5e672678b26f7d026fc6cb113bfed602df6b733160e1197744687a16fff564538e15fc9dae205e1dd686f7ed49fbf3ab50e01e135c9450c160470ba3adaef74a73aa6022f437611734a0f2c1201bd6404d8b61218ad2e72e2977081dd61132a7c38b527abdf145f64592d24b9f0c3f979ca4295596a8b8ad8290b8f3f08d738e2bd6e7ec79fba64e56607dbb72c30986af7026e86ed2e87cc7edd81550dc29812bdc9e521c1cbd0656523b1ab155132d7c0204da278f4d4bf029b89f2c8cdb0da9755ec475aa5ccead3eaeff3e2b758a857a0abaee84b76a5f383105527405c57169f125bb3f5f73cab59140c42bad766b379715c42cb712f6b98f313dce6dcea4dbfa11abbf204dd2811b79ef95440af3187cf7434b5e0056720436f30f4464996eb097317a851433df63c898f97b31a4147e173b8c4ca864748fdca38ee297fd327627aed8b7fb251b0cfe52d39349cd8f3e6e75cd41fbaa7b2621ceaaa947410cbd2dc8842e8977901309db0fca79f71089f9315dea8c6fb9a43a5500b0a88beb59cc9800390d04266c4068a295eef85e0b8ff58f1ba42f05d0fc123f4d6c463d08e044244ce3f561e536106ccbf758d94bc2fa4018f1d9afa1fc5f0330231e96657bdc8b27aad44088190faa4194085d4a383db79e956130f215cd244a42e70d667271e19a336853176be2adfc3e39081e5977ee6f08e6d1d988be8f2077f657e36ecd2d4941f8054146c2a9bd6bc3948bbc590f1a3b0315bf455467b10f5d9ef22ea65115835135d98ac718fd2c83a6c3ecad6ad4721c3c91ea17313b6e444ae1fb7e897219395936237b318bb498cbfe75be539a453adc517d2f23ed0d66e450c41ca32f3312d46c236dc62c535dea64eb7f84bcae909c5d88d7a9e6bb454aed9a537e7757d09e71d2bb0a95b7beda3f4c2e131b0441cdf7d41632abd67d54afc26e69da03262eb8e3f861aa5b5f7f62a24ca7cfe8743455fe998202efc1d0f898fe66ff10242282e9a2ae846c494e0a3d99a5db6d988283d6c6c6315e11e6e85d13f6ac2d9fc6baaf22b6c01348fc2e52d163d3cc2c14e1bff20b321f5d94553c4a19817f544ad9a6146feac29af2c466223619a898fa4fd4ae3988fc612dff13e5a1c8086a9d7139b844ee094b428ef9f01831b8183ad9a9f440f3d345eadfdce474e14f537ec0c68ce1d6b1a067158bf966aa2f15f4f6465a957b23d6d70a7a06c86c7518962eacd19d4f82a99947d925e6837bc5ec22260b7accd4259ab1eb8bf488f3a9f7c11a8d39e934e61084a705c25620f9fb38f8d82967fe818cb0bde97cf63321c4070d88a2d66e32cbe0b82b3aa84ebc273e36b4fadbf826a99c0d730eac001efd4dfccff21f8096d325780a3e5d9d7bb58edd86a9adb904150f4aa3c7550872ab27a5d54d5ef6473e80ccaf026495b77c21e1f31c5e125247bfd63c3d8e49c4c706883ffeb69a1837ed08e8c8282bf412f64fa9bd16178010f06e4c2ab898835f96461094aa6fa9bbe71655db140f9326ebb7f5138df5c04989892965dd3a680f57013702dc1c7c4f155703fcb385189584187e94d27cfb4d1d362363387a72678f0d552afd7f476f0a1ef6d877a8056c5013f1a058307a39bfe0ccee4d3a5b965f2e54185275a4d87996680545de9e26ab8fb2fa4136d0a29bb3b8503b0783bf4283a46063bc5eeb000d8b2d1e064b2ac0551f49acf953b902de97fb77ad41861a198c86b702385b51c41d389d215df390b8e06f90846a8385f944960397ed92b8ae7a71dd3ec9628223adc192ca773e77a0e0604920322b7d5590dcc5cc3d9c82fdcaa4c9153a0e78164230544c3e04b84676c03908d2830aac886631ba9fd2cc82144d2bccfa29f969938b39b57c4abd6c368a97eaa50894338ccb266fb39e8d4e69a835a737b0c48cc95d9ac066113dc3b8b12757799ead896d7e79c435ea42e74ff9008195ffb8ee777b4cd5fdb0af37274df841010d8e2d70c8a485ed3ed5c3dbe328f7e1e935a51879c08a4962ff2e9423be38267aa94ceebe9c7a0bff1ff6c10456fded4d805d7f55a1a4f15f751511115bfc0546506c65936bb334f88ba37a0692fc49e80256872857365ffb4051b710da83d555823ab42bbf5209c74d6bdbcdfade98abafd2daa9fb3a704351c690396095cd4bca3238129c5d57bbdc236d20c5cb60067e2f1313261bd7981e82bca34a153afe483b07934d56c2ad966881ffe53a4a25a06c0c552289184072ae3d76d5629c75295d3b79d3940fd995da744b746438c4c8d9272a94bad23de136d4f88bac0e445c37485e4691d09eb0aded29c0798a0f099a03bdc1bde2739869e26774e923f8533e232b5cda52aa072b1777a5870543a450833cc74fdee0c12d1f0604c267db6d1f81901a68beb6cb53ce812be5659f5f60dfbe3e0d0db3e8a79a498ed51bd7e6e230a5de3fd71346d4eefabc6805e88511d246e539478fd9a1dcf9f1d01fc0066c3ac1173383bc0661299d643cd309250b565fab29c70b16797d5fd07acc4648d6593711abca7b4942d2cba23c806b655cab6f5971e499a317ceb2dec0969afc9b2208e275e0d751bea9b03dbbd2cd0b1a486b6ea5d0ce79ade13340cf8c08f715f0eabb0219c8c00c7c0400157d2a0e586d9537b01e42fc81d622419da1730377c8dd3aed7a1c55989a97108d444bd1eaf1d55d6d7e9dcf7e84153385574b34bdb14f0ef2956b188f1ce519db8106460a5701ac4ae5cdd869798daf60658dbee306a6ed9e1e6cf0623b73c8fcc44fe93a5406823d8e4c6e8388d4ca507d308b7c4051c67a0b66ec9c018d978782c8c8bb03bea8c37bfad71b43eee6f46e2ff199a6a9f59d7f6cc67538da4ce54efd9f842f581028a32aca0d5a92069876aa547987fc969205ebcb2fd6465e398bafd6f97001ea0e932339f9685bd8b6ea06b9d2b4070a8bd1eed00fa37e878a90b1b011df73646e6ac804c1472212349e5fab4baa27067db10108f399f14d7bfc1a5b78fbf21ca7326e8cb8262f96fd66247cd1dc8d2187fddff347a9343b48ecb816daa1efc1082bd72cf0b612a86bf3390e7002e99fdb5ca90ea35478643dff09428899b36a709b44bfaf44254035e5e8088159ccb203342c1a5072b3e44b7619e46902d6ada5e35dc1a9c164167cb4510398f0d21de0e42d6c0dedc42e31165fa6dfffaaab04c19aeaad16ca267aed6c31bd69a9bf0e3b9fedef832cf045fcdb0e574297defa156a6d93fb170f1c42a0fcb12ac157b62770a457b5ab7c876371192c41e06a6115a9fe01364f4a32123e4f4c300bc3a99aaf90251995b8ea3f1e98df9b989f2ae708f404964991ead62596795d0cde8f793e84d1d1867018ae537dfe23f7c7440af91a04d482ba78b0ce35d4c7802d4a5c55b7ea71289340d37074be72b7cc6b6c38bc3cd82c5230593162237345ac1688943e9e74b7e58ce374bdcd87c9df901ead87030e1cd7ce24d5f42e6a8fb8d8c2b8fabdd767110c92ff4e6c73bb7062264fcdd114666c45b3a94f3ff5541384c82a1a5a183f062bc8cd4b03b1d4393ee3c184d5c71c79663db9ac1f96eb852ab4ca02b3450395d5a3142b21e3dc1a105901c29d4159a2e02e28e926956d09af58fe48b40e47950edb1cd4d622157216702de537a4e85767bdd188789d592ffc9e5b8df2799af981c51b7de02b5f7c44195edb52aa723523daa137b43b36a297c5045bad0a7339a7b6201d2fbee0d8d36af303017659114c516393c872386158d94c9aa95092cfcb52540a9fee7862a3edda271eb101f58db5f8680c44e763409680ece9d745ee631deef0cc87b772aadd4219036cd7cb76539215d3d102feced002e1ad52fa8eeb19668450f4bc778f66344258e983d6a774c8513faadae61ced474618f69c2469035766ffafc61814ea80c7abab622d943fa9e0df6f5f413540665d37b463241730fb211084eda7c58e41de45e1658fa017a509b73dc780d242ac523375b39a74e16e37036e85008b85330028994637066b3a176d86391d972320eb841b796d8e7473e43178b5c78b6c8668b306e6f54d25f77a692c3525b16db8e053d8c72b1368896e8e6eb125a9e47fd17ffe60fd2772b83a6eb1f99f055ef14e190c7f5797cc5500fb686187495ad7d5233ae5d9beb38d3d27373ec6ce2b3bb231ce590931b352e8e2f10155a1d236fc0c04fb83d5905319dcb31c85056d02313785325b7957f08e7299a47aca286862e7d8dc5de9c4846dc79e7c001c377850198d57b7e60e44401d0671d385b642458ff9f4964a47fbabf6e4603650005e6bec9cdb0908123a760288d0102dc26c8effa0c7bc8c4caeb1595aa50f0be71771afb2678cf3de40e4b05e1345764551136b004bcd60a6b4992945ed0737d9444f9e11966f800a459b8a643b49dcc78679858ef7fd38ceebd5ae97e402c79cd707f7c1ea49e0c9a7c25c0150a0b0558fab25801249aeffc56e6fc451da6e5979763398493cea8c5b9b409503612e061ff37a9482012fe76a3a99ba81bf0084463ff264aafaa16d320a4c3c786d198f20e26b77eaa92cbdcdbbd162693d993ba276376fb8bc11818ce188adb6bdebc6ef4467040d386b8904a95db358cdd4894da7f182a661e2e71098ea4089e4cfb93364ce2bbe0b32ce9c8f5e056d51e0d9aba0e6f1f451e6d92bde8955599357e87462bd9b745b1f90aefcf8b2b03c2e59baabfa02b1567e5837a330ab64b517feae80e5ddc66301b19386b51983546276e4496fccf7431cdf56bebd70740cb12b0d689e581af71af56689c031707f4a25f45a8098b7952b81a8a15c445e5d34d29a91b1016b70134dc885817aff7182feebb308a8bc4f6dc73027ca794380236cbc565f3ac007591607a106153a3d091d9929b667c2bf2426f8efe8d0d1057c061f1fba85b7214b4596509885931e14fe6ad4794b3e3b8756401eb68c0c24d62479bd48e287c6ad2ec1e7b15c142d30cc7dc9137b74db7de0741c0916fb987acae665382c640facc4e8555025c428fe9005c6d4140e341e2f8c03ce1bce0b0c3010be1806a6848724a64d2c725880610a438a506f4e402777498e659bf82d258ebb398b4014829a69f4fcf00ea91bd986400708680dfda84d300b463b202c544bca365ae65c4ee5e0a3663a7c8336dd9d938826963b435837cc07b70253ba9849623ca12295b9c48c4846b1752fde896fa106e250091a60d96e3224a6f117c6570517f8d9cff57eb787b2d80d02bb2b02fc5fb89c045630a14e2adba4c19603208a9cc5fbd55bc2a3bd4e0d220ae7d0957dc2d3cb9f81007f4f6c05fc1642c6318fbb2c6ec32f63d254077c90c787a166122e858005bb023a0c0c49738d466b60c7f750378518d54ac31868f5c53f608e079546ee7847ab15769ead850475ee3de71f6e11110578d7f2086f443842d905f08da2ed9aea466966b81e620d9e59b0e935656b4797e177c9f3112c9733acb71ce63b493281565aa24c4770bc35d469be053edebe5082dbcb251ecb23a4a5aa667fd0edabe8e5ac1bd1a9d6ef2173c60cda5bb21ef0c4cac31c210531e9ba65da39e27177657a26c16ee133a2778b8146935524f65fd1b8e3f81032c27ee5b34fc18f218a96af5c955373063f0b851e52f346d82c5ef4356968f507da8d2c0e7a7b18ce7bbb9f592543266f4866f0bff0dea5009d7122b57c75ce380bba0aa533193eae66113dc82722fe6027e950c800e87ec29ccda4f8fa619cab9f5beebfcb2259214d31a937c7f8a4551f3499729725ba02664bc36f77a09d8b4cba41c12d3d78b83ca155a373f5a3e311eaef4f80c1aa4b538c3fd75f2de9529cd2fb87c64c78cf2f336ada7bc8b0a2fe20df71d9afe59ccef3e34ecda5be51f34409680b3e3568bc471278abf60abb06678591d50261166c3575bbf80d5a430d8b3bf57c44603bb1615ec1ff08c9fd44ee404851e203e91fe246eb103a081558fcba690184a7a49282bea1ce7eead2cc1c08c6f1a85ff7a78b30c190b854ff931b0dff1d197f413fc034a8dd55973b13a806580402afee5977cbd45f50ccd47f7b940ebc1d139af6b60b80a308c98baa57c43dcce809a48cf294ab520887659d7464f774a2a2633d3a9b34742c2dc3773469d228f71f3637eaccb80df32744ecafd50915f89e29cc01f98cb3eaac1238c7469281fd16b7017091dc3e749f29878d3ae47940bcd64067401826f37d341d472e89899a6678eca978e66878f6b7fa7e231aa1229b7c0201900e8c6d5bdcc6dc5f2e3ca2a7b3cc34f05cee679ffccacff6637e63f6f58fb0b28d6619cb0ae0d7f4e61a83cca0176913c956f381ecd59cd11be4607170218e28b9cccee7b0d6be24803a8e0fe5b92b3449dd924b701c20c1d741397170e1e97a5857eea5adba1c7a272c5f36644f67cf85d405361afc866fb2939d1c988d780a0b11ebac962be37536d8fb38962954cc8cbbd989f86b12a9766b29e2fbe1673c06df94de47ac60db744e954ed3d0469bd3c6eff84b76b93ee09472f66ec571845e3a86079d10ab240c4d9e3180dd166c03eb930b7fde73508dcce1eadf1a3df8e673808419edb145fad67f50fadd1522576a52edd6ce2b34850a38fde1822ee4526dff5d5f0ca007ea15d078ceb46c94f3e365eda167300fdd00f1f5a8f9e08b67c960df6d754a82174d584740dd9a12d7fe36322d2838fcfdd16a9fb305adc0ab10046b969b137fc69d20d89f4c3b93c3030b92f16e3f98a7024438b014841daf5bff752c9f6134f853ee349f1c84635e41d6aa51aee9ae852be62383bf3169d595a0edcf6cb5d7ab2e8a48a1da81c4b9a60b22b019988348fda0923b0a050d40e5aba17ae1b814025569ad39cd0d6036c6b623195704d0b9f1ae1a624bb97e2431a0e54e4d9478c2524499bf5ce6236f97558bed6202981870d7d14c59b22d82c3809d6e4548691d89b4199500648966c45838fad9b975f59fc896aabaf667f274522079801929519b30900f1858c1b3d1df4206c2c8f9674c94d4cddaf87374abb0b3bc3d979e3c0413d26aa86eabef6e9f360ad490116b451bdc7a8087cacceaaac0725f720bc687cd1ce5bb634d6160a900cde1f417d975c120a8631944c9b218bafe7b992c15dd422c344a6caab95996b0ec09530f97348001239b8db4879f12732786aa7640d8735e6e720f84061c80cbb0350e864f7127e9d5670512f93c684e3063299aa2ce7e495bc9968a94abdb1ce1feb74015788b0d546bdce3cfe367e881f10571325755cd023075f6c8ac08bb0a46cbe1f4b682590c8bac8bbf8e2bd091a5234b62d758dafa06aac2246d47f5cdcd9cc11ef20dc1b57b95c0352f82befc9305f3e37d74a47fe27ceec26746eec5dcf0353fc4da81cbc3532e39e7304fc36405bd52122d7d6890e3f591a093f9421870ae5ef1e1472a7b80365fad45e08544f76d62651aaa67f342923b982a101c1fea76f33ce037e24797a3b50876ed048799986917996b12d298624269e6c450dcba5b0d3103c61c704ad8ca9a7318257e3075ba636c57875d04e31539ec1ab00798a887fed9cc2fd0035291ac9bfdd855f189f77739b1fa8c300380e80a4298b64bacb6d6241def941311aacd4e6d018d804c6f9faadcb21a1607922d49afbe83b6bfe12a54bea624ea105381d6479e2b38ac0fe9dbe2a7ac319a2ad3aec1d81a9cf6b611f849fd0ef6e8ffcac40281f86fc88e8bd5f17081ae645b654fb469c40dfde53364f3f882dfa8bd587afe9b8d704cf75b6850003047795cac34d7d7acc3c5ac4de0fd1259a8193af817ee7ceb792a3f03336ead94953026b9313333bc5fb82626d1dd2f009417c484fa4d065ecc4b1b5f8974ba7a788ee37c932fa1da8d664c4517a74642e87651d6c05e88375147dcf3638afefb44d4b241fd840727b89f3e05014d6b8de2c8b20730f1e5be74dee805d979fecb87f4a9f1e2171246ba9c3a34d54a26c63d06cd02df19d2e6dd28e1eebecd939c69183c8e5bbc92038316f650732f7953252c57548ac7b8afe65ef8200c4b306ae51ea111651afc656f54765851861436152851dbd3485413e6cf2c7c81ccb59d1087febf254f2f336fa397675e358869e605c09b1bc49f43d8c48153e1cdc24deafda954bb0bcddfc67d870e9e38784e2e77e137e924bcc73b370d0229a7f08ca3b7c95e999be41c3b733e593c1b9d2b256cd6653580bf521737d496118084c5cb1252d6cc42a057dfa2a05507654b015d1ba623af2e578ec6434c295526c19538060de1827dcda1b9de99a6e6d54ae852a45d5de63d866124f61cdaea7c28ac30e891fffbb952997d090136d7288a576e6bbd50fa283ffde42befb2b247af84dbfc8dc95a812b7c25fae0a5d2d73ad74cefc9e757c9606ca82e5aa56fcf2d6060f04be161845ea753977a60f0155df90675f09c55a675d4f3903cfd0cbdb1bbbb5c9702852ac9991644ecfba683bc20d61129dea880e4dc79b87a9c6ab86e54ed419590a3d1a67256d5679313c74145653928970a538a4564fb4614d1e857e5a8d38392e9abb673ace0604b348fb7a0d164674bdebfc6ac988fa81ace46088e6ff817e4f8a66c6c996ae0e272e8cb09cf565f283f64ee394ab50d7d177069e3b17a3f44d476b2ffbea9ee12f5add92cff66eb3bdc9e323a5bc66644c0ac4b973affe466d93bde3058bf960b60a83cad433d8957a402a25c34c52509e38742824e2e63ca2ee4a87cfe12da9bd9e129dd432fba8d8c9b474fa4ed2efdb9b1abd22a2710408ee3f90e7de55f65abd5a85afae5e3b2a9256b6da14515c7be912977df8453d5d967effde60ce3d38fad24552971be11ce9149704b68b489b27d3f518d802e3f2a1b3842e42c062d0d19dc253be441399154b3dd5d94241b5ccab7083e58c1b26c30415bfa39d02de2c2dc86c3ed17d96c707d18e41fdd89a5d5c0f6cfe77d4a392c200995e24912af2e9f80a4bde952f8d9491b0ca986d2a13a9e0dbe255b7f2402de19e3fc351ebc531af60d3e377faa8736cebbf3ea4a26defa86935c46908fb95dd855c11a9f2f3f1a9c73db30198345e8816166ea307a0a50fdac6d1c66e125445fef544e9ce191f357465db83008c78f6ccfd7944ee62cf655f67adb0005519ca50c6a05c0f97071227047bed7caeb64607c95de4c8963c32c2319dee978867ab59ee5fc2c029c45e330cdbe23679072527b00ffa93ed339666dffcd2b28f8554262df45f55414952e1ff7c702da6c118363bb2ebe7e4529db6b97c2c5ea048cbbe491f3faceb0450b70dc310387a4b565ab8e82f471035574728dbe1e6bd197ef6f4e1b13c1f7c9b44be82acebcbca6bf979e8134f75c35360769d05ef9cb6e2860f31da8008c895e09203c5f66e5f71b1458d7a2884ee5a288bf6739a257bfa6b083bafa45e99f0b2a635f80032c47f5e8d788aa7cdb7d26a74eb0616a6c58d93d9b79b4a518280ded2982ec96e70d91e726f3293a936f8a4863e58adb897592f81da9e9cf8e00b8c1f6067be49c313ba8e53ad3c826f13bb2ff204b53d6d8e80d68bc6c6f515c351c12eb7c0ca0a1e6072d24d8ec2b8114decac83ef8a0cdea134164ac23807cd0f19ad91057b711a86f83b11050dd6e83b10d5eba13dd1f5c12f64b86296b8b1743176e916b1e2b2d8ce6eacb03f29a69dc0d47e1f9ca4c5ddac2507d87e8d9c031b847d08efbb1c12285dc3105cc80f6f7e6fd62dcf225a752350793a71ebc23eeed365c4798d4b3444cc6055c23180c06bcc138655b671d91417a37143fe91b0b0cd2c594cf165ab63efca1de48aea60d0ab0308af4e4c51d0f2544cf0f3ffbee55ea9678859a1b39b45afaa2fb6a8147d444f2f4005324a453314c44c69106cf22ae815dd8029a867601990e27ac7c1d5e13c99ac5a690bd3341b674765f22dc7da8b545de196e5417a6ad441c7fe66be518adc5be1ca0d1d1fcd75b227db00c5a26120d3506fc7ffd7af7cfe60bcaa760bbd890fb9a2740312fa5042cb94f40844b9dc2edb567bd881c804d51f7b051c411e69b48222ee7573ab023e6477536621e8aa8f4a324b9c753c3eec8c49a82e9436519ad948df3aadd54b81c2d9c7a378f21d18fb194cac621d033b0548f29b5eea50557c1a55c8f30fd10648cc966217617c51e3ef2eec141c8ab426782510e8673906e1ad1c1cf50a85e8c0e1bc45311c8d0008f70e06be895d974727abc84714b31c394d162181967b89438684d1fbde6becdfddddeac8d08ab05299c1fe64fc8f364a146d71693cb044188c445095ed4ac3ddd14d788b17e30edff6255b97b74ca2a67234e484490b4785814cd01cadf4354e279556a0678fd0fad08cf45a11de0f53fa48a6bb565fd774a889931c16209a885cb44c488fc8dbdf986523bfd359f1758fd7c1f20f8e73116ea870feee773de2334219211948d409cb7da220ff8b2bb943605762a23563eb740ac3af0323b44082a7fd260d781a276d767c04b6285480b6bfdc50af89fb8083d96d35750576105e45f8713502e5991cc6d2109525e1c3705659d79d1e20f468df16921fe7d9a791958567c2ccdbf8d06e9400d6e7a626fe5fcca3c953b2b2e242f2d6df3042a8f38ebafb63282ba268806035641b2006f8491536e735925ac1edd9fff4e06ac20a406bfda508f6193b7b7c73b285e98ecc3e749191800d986a2edeaf7740866a3a4c925edb4a50ff0ec4712cc4e8b69e903d1aa82dd64552336b9500d97932250e38cea1cf62b2c6a5b0fc165ff874495213139ed687c9d61d1a5456dbf00aad7500da0641b48696b257381dd6bc4127c14a952b1bcd4ecf1b40151b7305c17248152b4b7821e769dd7a4adfa5d45109b81b8fbfd6dce8fd0757017fb4bb19072bd4c9c56c75c04831c8c1d4f63178edf07d1c68055bffb5e1424499dcdcc462bd6fadca12ee59a6f4465c2c73601215822111900860c15fa86392c60c1d552214376a7103f541b3623ccf51163e5b54a582357758a8d76ddda414bbc9d5ca0295d3125f21dc68c8540739295c653c4b72e520163d873b5e17a5af440794b8ae65ab8a9f4dc28dd545eca3f80ba1255dcbb7b69fa1f8b12d0bfe50ecff015c7bdade175a2379a17d901e58d249368573cf93ed59e655a069fcac516511b51da0151b65c3136bbf7bc415497f708436606652d7839d8c5704b5fcc9a0cd8c192f034babbfae8f040baf5f5d38cc7601c4108657cbd2639e284b27c68af1e2a520676403d0c95cf8643387206dc0fb6232f277ad49404211b4bce6d162929b29b8c78ec5e484c4dcf1bd4b12649b0e82656b179a2e2ab5533e86c3f7affc98028b9f50cece74dc459c2df4636426be4ba14b12cf43c5c9340be281a468cec734093f16cfcc0aa7fa11c63b0a687dede0a5560a2ec3ddd1c1282c2c4b090eb8fad66d7f97c400ea812c9f5596df70236bb37e5de9a8fd08cfd6a19504df40482105f0fa03d12e788fef6261a58c6f2f00d292b35c8c7b4c6158a0957ee152c81532b79799c633b34f4a4970904ae1d238907596367d9e456fc2b4b754da48395e1ca5e052352212724433e55c717fab41210940b1f52b8b1bd251cbfd1b5fab1130f6900f98e09787e7bb4dce965981d5ee667d63da8126105db1031a594e27eeef2d763961fe2a11d49fc6677cf5a8fb5877daf9127cd7a66a2dce341780c96ce651578a4ca9fadb0b042c312861772e0ffb8dc2532a6172966b606ba4f0c2ff7c58e283dc89ec106eb76f979fa7b1bfb8f617e5b8415f19360447534f787d5dc28dbb87262e86085ac1dd9a0eca086897fd7bb1d5be390c364c2545f1fc2d6ff91f664c51020177360324872c66725dbbe617d3e0f525957fbd8de886d88f193012dd98788c44fd8cebfdcfe455952e3b6791fb06ea26913eecf2abf622900f1d7df3167bfd9fd32c1400ccdfff32e274863100b9770d91f9468a5070b9e6b97f3175aa85b73c360d1bd3eb645cd97fc0a7a2dbb53a9bd7170a75073a49fb79118ca73dc3d16bdffd6f8bade6e298192e67441ed8624946702d9f0a9a93336a4304ea4c16cc7e4f6973b02a5b6c6d490e14a52035e9dfb925fcc0111ff2e05e9d45e06fd141209731745868c38f084904eace6d717284d82489624075081ddb9c9472cc98c672586b946e772b3ae08ca7320506f915a6b2ec7fd4aee78525d85639e76be8be055eee668b65814b898e2552b2a6c268fd29bc223d83ac1336f73e2132dfd20bac044fd6a72cfdfb671a027b9edde8d5620d6c78016344241118f8e5cd7840219eea97764ec4ac92aad01bfd445133ec766b63a731486c4cdfd08471b17828f385a49af3160778da3b12bb58282c1b73b47ba71c671b7181833ce3bd15924e58d15e0cc7c954a3b7e38f423b817cefa5e3c6b4627a3a689467c1712965186dcd4c0f841f01f04a502a75513ebbc5e1c00ed3c13dfdaa3571bae56bdfba18a4413b5d8768d07c64b986be1c73fc2900ecede06345b80480735e23e7d1c4b48afff7424aa071bb728d76362aab8d1db36f88847718e4e0788290d5aafb90c6e22bcace03d5e794cb229e61764700bc36176e9234ba10425581c8859a8283e07330b58964130e16ae3fc006af2f189bad1f02998cf87e5820c4cac6704335909be5b5f68783957c715c8cf52ed7dbb1165fc71c994f2846ef2f0ed281f89ddf43ece9bf8384458940ef42ddc30478766d32d4500b5cba7657a9ca2818015cb6e9565b92fb95cf94a39abeab30b46cb625a08f8c16261d141a68bb6ee20733561f17affef6d2e2d14338ad7a68a3d4da06f8e689bac851a8be09e1076bd711a44210e14f9a84790705819e9168d6b2ca7dc7d8e946f5e2f2d500160b92c32bda45ec36f1d34065dc23425578bc96397140f79ac813a6f2cac83ccd155900193f8c5169c8f4aa34f498bc0599590616686124bf422129d7e22ed52501505017d2741860dd33c6b8779a5fd779fc0edf0240be9481d3cf1487329ba808169d30583cdabe6b5fe175f9a81789221c1ad756b61bab063b29db01512aa08afe9a66d599dea55a60aa6e82e5863db19f32c524bd2a323ca57213412d91bc7a2d12585c32a8540c9914cb547e258461162c2882137ef5dc3688aeefca12c960fca6f051fe09413fd290748be2663681c813fc1031c6cd003b4346a61107828c099aead9298988c9405de8f65b1e8a0475ca712797065c0ba4398e0c5a2a58a4925f55da39dadb498b0b23d77b479aba53ad379bb4dc40126a53d74cba2b3fe0dead7e4a07da7e1f8f42aa02a1a6cca1d66a50558e619491e14ae60ff943218ad4416549e1ca05167eec8cc893191eec11cb778fa6bc25052143ce31ab12c69991f9194d562d64c71b05316d632244f7ce17175e3bdfa4bf53c395e7738eea5decdacef31b480ac49edcd5b220942d95e3593043e2ed811cb0520eaccb0612ed80d8d5f558fd2444f6e34ce0eed617adbd90f34fbaef45a88912a474b3615187af9a31b48deb623436b7becf3ea40b1321a7245d4982e04f0dcdce166d285bf922a68f0e88781abfa2683cd569d331828e1efcaac498d552def5f08e88fd637557f8d2973367005dc81c498facc35b913fd63d8042704224a11c7fe7847015540c1f52e271d3251b3c4817e3249a18079b69088d7f9160196ef2b1f51d008cb58e7a44021712216d249b92157d978ebfc2fce024a4b0c72032bb96a8a6f8ce64d1c17f84a261370bea253263ec9df5b97e46416ad12d60c55d4aa6c3c5d2249c4d01cf515993303b60372b25095ad48981bb280106adde12224e7e070837698c3068a9791899320b12543b9b0a439b361b9ee5d8dba695c49976421b80b75909afa92c65bdb6662e84775912653af51ac22e3258935c31a6951c04001944f8bdfcd08408f4fa0bcec7897ac1727a7a88323178441d822aba1b3d79013a5d8f01e0001121320228afacca286a1d8d05c178efe215aa1697f9202063793258bdbebc2209fda4f08f0138b4c19e67916fd36c4831517f30c7a8bc5a960504c3afc9c353276cc8d021a00680d2aebbd94475efe7bdefa4f828ab0c832f378967b232d7c2609b7623d625f4fe6e8283eb042b44b9b015a33790c45d35670e18a54330b3e939e4eec0a920614b7d609ac162de937662ff08a980d6bb2438f94f1cafe1aae14f7302a9bc2b28ea1848cdf04e81c0a0f4a66a902f0c4822d200aa4dd622346a0f56b55e503193599843cd8fbae2c93f90dc8a6a247713d2221a8d86cdb61685f5484e15c82e7c8bd34492040f129b7d505469031a44da7b1d9afda2b7c041f8ee57af129da08c02082b386bf94f02ec0b801eeeb938a0e7a748205634587a913444b31fd6f28fcbf0d4de2195cbcb1b2f9759bc2b58858ce6560b226e3246a1323aa99362259e886d5834e1900a360dec6b380d43eb5b9c30a5fdf5d2753cf712001e4e17669ba86ea165b1e58c1de584eb35f4552d77cd16d34c1ccdd62bd00db1f76ce426dbd5949adebaac777995e56fa996f14815a1cb068312e3e656839ac8c54217156cfab0e4288dab66e16cbe43321c10e3f49435cba39745b160bc34eb08f5e7353a8a352f2964e7ff31a45a55486fb37a5eb7afb9fe0dd526e3b619612b5911d9f655274b8d30545246160c79a6c502283e4ad2be6db63401e51022c52015b128d79f80937c8f2684d54801e44efbde4bd564d91ed9485d796f46bbee29fa60e226c717411e6240586dcc51a99119b632e74948a5b2a60c8de875cce6b8de5ced9f19a12284edad2a86514374da7fd6d7470d01f3e6717f727c7dcb1af8faa8f794cc4ba10ab6eac7fec2957acdf72fc082658ad5b0008fbeb724ede7796d602759585479fe84c1327e39be23be2a0c2a8395a88c2dfa1294a4469b2013da4ee7959e95955520b0bfd1e47c30a938c0b0b7931d50d7142b0486c13b68591ee824dd61b46594c42cb8640ea2e2adbc3a02b7e2c12260d7c8f1a10a40209d8262fc32e57ebb6109c08609739f732454170fe9daf52b5c2305e4f33b0faff9986e2d559fb831e13a6ba5a365be630c101e0444bafb8b8398c5312c86f26ce3b21ba72e814893f62be5b84343cee40e650913a869ba7583fbc4106155424767908e8cb788ad4b9fbe68c506ccca07e3c6600881155364b629b36f5faa3138a72fc672ae8247fe338b7f25443cf8cb98a88901588892b54a44e574d44060b220945738a12e03c44194d65560e6e4c54d71601b50a2d5f3d44e5cb982acea8a2702c04b467ee2f39f120d226cad11925d3d808555662dfe7c105d219a5d820eb896ec4da9033ca6e3aa3f6606335c44e132b7711928a8c646e45ae3214944e1cc82713a1d9a09ba531bafa3f8907d4bc56c137f780ec5f8adee807115a556ec6160a9e52ac36a6c5b59c403f7db41b277943d63260b28ec184a2f523beddc80263e225eba89802681b09a93904621f39efd6827f24026cb327362458e126dc78f2ea7b3e07b58beb9e5d64522d63009b1df72953e045657593e0429fcad29dad76b9c9139a668a5a74f30e2cdbd89913bac76936600c09128b01c4d2054c54e13932b7d7f00752ef62902ac3334ad36884b443effd1e07bff83ac72d4620dc28ff3fa08c6297c54d528b9222d9904acecff2225f56ac1d567dccda611d3e0f421f382ea4ade400fd15e5b2ac000b3339b36c39caf12d19e4736fc80d3a9259987812f6e0f999fd650aca09635b606cf4c6538679a31f28bf5afccc05c61e27a7df75246876781fd75295fee6652c078862e39714ddf23a22f898f63639ba56f8381f58335e300a2c8e64550cdc097608e736b42ad8740b0d4dbca4f931159c6b84a005d12491da628707159a45033a62755cb1da8830112c0076eefcb120aab07b0277c369edf027c06832fd855cf7bbc93894ab4336bcf543b30d9ace4ce4ca7a6b7a25ce98a8d427570e6c1da35223b77eaeb7eb4029fccefac6e71d41a00eefbc8ea53375ef097d549c0c8ce9fe4782a92667aaad41dc301b39363c5802824edf7a64e57728e555fd633e9edf5a20f1e19a0a997a76d4fc32b09c44a9dbc1eadb725ca6a61cef6db5043f19c3f2b33a800d5b964895cca8e8373847c460631b39ee719c5287e422e467fde3e120d7e0e5c0e68bb73f9a282558754e91f18398aaabd141456020626e4fc03b5b0a5cba7966951863c6c2f543874b256ef3be435525935d72dec4564babd93ea267e7a302f923818134b34b8962bebca1935bac15b296e366d5e30ae2a979c9c16791e61780c3571529fe4bf4643604b6c7e4cbad04484f0141a3d3c052881eac67c6b95a3290024d89b27cc39b1319ed1d1d36a69409997d56e460257417cfce87b4bd7b12fb11dce2a79f31e615c9a37cc3aaa48f867e5815ec93a345e6d0a7a4ee42e77f8ba6b1f78c1cf539dcfe41ed6a113eba460a782ec9cff07982f80cc795501cbce1061b59c167bd95d1ea8f523663f3b6005f205faf38d7651fcedac398ffa9f94a8837eba1092c1b06c552af3671921ec600c83b8360505c068913124b5ab5856fb3bec685cb7e45baef951ada24ca657ff945892b7ce6357e441aba810ae76413309fc1d5b340c3cf310da05b7e963e89c32b4669a1162e6b33e586e6b1a85d14ac6dbb5f60626bebed6bec98ad59966ca700fa2e9a2ea5b5aa1d9c12d634db99fb3a486cf396a5c2a65fe5135d3bc11a3690164346581d89146af13a120bbea4c390f44fd65bc4b2ffd5d474da46d093c41630ca80997ade9e1b4b4a567f603246d86d19e280437420fec5b3ad67c210443aef7df168c82cd0709e08ba2d157a5a0bb549ebede55b138dd6aeadaa6686bd7c986066051d7444a595369a8c077389c9d181121f673a361ef243c6bcb090ddc62b63399388db05551ad3046ac90b7ef69d6dfec2b38a682ceefbc6253741d1ba2fa3bb5f97b9c3a1b9d7c2c6ff1104ffe0c2c72b73221a3dc1346ff90e604b7bca13d7ca7b6b7bd5e7bda30e87ea23a7241f6eaeff7f3707488cda70ed3b05de7206619bc301ecfb64df655fcea1bb5f17fd52c93ce89ec17dbb4b8187f1cbd420e935ffc25bda57d48f697b2da6152223566955ed9527eafa3176da807361060e278aa661990b1fa5c7dccd6d652135ef206604ffa3ae346faabe7d29b8ecedc947198aa81dda3e3503b25fcce3a5c9d8198829765f6e583a10f6a8773c935b35db8a65be9d135f7ec9356d1c44f548d5bd2a1ddab9acd836a0ceba0c98b80a49b904287f35e12e50a7afa364118343b9da614e7f1b46095b2b97c0e54cb483f3c6910d48181bc2173b6715a2ac2a900cad2ea7b09e1d80485de4c496ec5f057c1c324253840ae6949b252b947fc8654bd68f49e415271c2605711380da7984ca6f5b8ecbd095e91f56ac5d354aa0d81b569b37b41cd96f6d085cfb63295c03a905093db1428d6cd28293b4d21655e8d97c8cb146a70ddb14b17857ab1d1f480bb13c6d0ea3fd352bf2536ab6379ba6a8cfb07148f0cc06fbdb66d30aea016d4821465710588a8efb648f54f19424b458e22e9adacac77ecd8b12ce5add521c563721094a170b4523a86871260321da3c65ed43b59e817a326c35b286c13e8988845f53ee71a84058849dcdf90218d3ed80e8454cc6d2fef60ba7b9fe6023ae8c28a82601bd0f7927961f6e49d3a3bcd87b9641d9b6bf80adf7ee254ce7b114d57ac20d34d67bd02fe0ef730cd24e6ec12b128299f88b65658165ea82831176d0418150d1d22746b4c7daf0d42505a98c9aca23aedac4ab0d42e54aa75e77a537df65f7a2bba3edc3587b47df52d4b47cc71202f83dbb982154aef7ed3199a1938cb06a22b07e267a1c92b1347e06444762cf53348107558b1c936171f875e2e32522513d4a9256fc8b67369f94a6d3844500cf5feac4860750e428d537e3d2d1c51b370816ddb2ce0c4864a30f0210ff29745d1ef01842e45b7295e8648e9d9d75ecdf2a88bb5c5820ac1b7b6571b8754408e55a55e0a07469e1d8e189de034b2f7174d704e9cf5f6f8f436fb03dea91143c8c621a83984bd199251814861b90628b7ea510b828031818a7e9e3c7ee9a93353c705cf92ddb1823d749ab016db1e17fe05fe22c2d28ed892eb61a8b3680bf0f8ce110f60f4e63b68d2f78c5a9dccac90f32924a775e62e28b26535dca6dde958273bba0d610bb7ba0909c922d38d7691ae9f2fffdcee54f7829c6d4153f4c191c1f0332201b27f63ca8f31aa7f6bede044aa14c3fd4406e53fe1ac48d15d981e779ae3ab4e5ba39eb05014bc49c37b2bc4b65a01ede5622a587e2c6787fbbe86960d110d7fde548a29117c02289d9bebe43edb5edf672e0a1f4f480a2e9258d748034f416c1e86f3e26d02d41d0cc10078b09625f03110b1a251ac7814571f361b74272bfe8eb9fad1fb25296a59306772f53e1d18ed3a63111897d15c3457078a906a01785742c35aeb3a520bcd5a83fa92b5e2f6706f3aa210eed138f74efeab01e5cb458b81c912b80f6dc88bbb782a0840fb631b9528742818dc49caa2d0bceb3e56e4cf6067b4446d5664798934e91f4e5a34fadf77e629599fcd48e202bd167409f19e35e24f0c5f0edcbb2bf210391ec3aa3bbd765dc939c09bdec50a97e1843d44b6257d81cc6cd4cc552373b821be11b9e091380c5fa41fe5360419843431a26e603b02daadbe3684943a7fdb70a9b0cbc38f403a06b692316cd51c8cef37fefb3917255ea0ee5721405432a099d0fb9e93eae489327225389640ab263845bea2ae85c2c1f2ebc0ae150b7a80c709afbd0a44747fb914a72bf06662f36639edba581a476c481852f710459a6ccc5feacf77cc16ab3c0d3790b6f45f7813f1a34319412e46985f2f424597700a1c2899302d01a9e0ecb1bf2623d8c2de9f38af030f9250e173d80ca5ce83cd158d658d10ee7cbe33808bf12b0718764a024302925f2e8f91a630f9352514140bae355118bc4815f3b7c1281ef210aecee053d6a8b6b9c1d36243cb2354104227cfab6f2e8e2e01571ec87e73e0795483cbca6bb57294e13dba5c2dc8701a61f5d9c5f32e6eb29f8aabceb1667e4f93db1334750f00762148424d90d5b0e91e859fdce1826abcd2db2e1597e26216b228a537c680d06b47a4590caa479f20e3592b6bf010aa851b3208eae09a0a9199cea0dd4664157a315e83a670ec6dcfe0335fa41da2c859c671669b3bad5faada86aed3a5139225267399a7bc54c270e51ea0153cd9c7764af930749f10f27b31107763952af12444fce6e71c0b6979b085060080fc43571e4a1cecaab0a3a7e3455592b08434192ecc8228d1f1195eeaf2043a507d079b5fa70c52964b882d82fee5898cdb33a361f074b6349e38eaf9ae1d6cf1142188f2de58076cd80c73b7d58d6f8479749d382dc8826cd327006d02147e370de0b77fa142e81d870c8feeb7246efd771d6dd81515dcd7f74afb4605c4287cb3d4f4214e2fe76939c35f7788f30b6342107be02798fe0286ab49c537fd1a5e8d171a4f945d722a37296fa8bdc228cc869fa17ba8a3c1ac7945fe82c32520ea97fc955c46839a7fea2dba4e5ec536a58e77107e31fee701bcb51d3ca2ecebfc9b6255c3e6444c4cf96747e7489f0b8d0161713bf919bf837c6ad28f1d7bb8f5a67149c8110e58efdc103b197daf275847a2a785bd08eafc5b4daf40343898366d69caa0c09c66eabd44019df2d70a86627e9924b65764c27d57845a97a8fcafe90c7c47dc0a7f774f31d55f59e77190f1746a184905a6a5658bdc701207c3e76343ceb37891a00e8d5cfe171d82e8885f0b79e78661b27299a59f8fe310ea7a4745da7f478ff16657143911dfea2de9324793ec38da7cabd274a743eec51d9e9ef156bc7d3443071794fe5633c45a88ff2de7325cffdcadb77b452678e278fa44704a6a3b1bc5fa4f878146ac000b483be6702cdc07709ac1c769a7e40f23cb61f9dff372a15dabf7d6dfc0a68fdcffeb54ae80f002963d4c7bc2014dc2ebeeb505c745b220eef651fb36508ef21863821672f52217122179392c21adfaaaf6b7804795888a52c0d7662c4502b66086846098652def19882b62f8c7789e4595121f189739ba602c83e9395d0afbcaac9ae6344abdb81bdfbc2ab8fce4fed6b211b0c0b5b20748e014b47c41ddb0cb8761c18f3e70e1081672ffbec2eabc5870b0e082b947d764a2405d6746e5c5f597f9333fad96717c608526f123f1cca0262dcee70d680abe85f95a2b46bccfcdf5cc05e1a18b5bf220f51ec6412d6833949972f3ae256b768f3c62e490118c9045333263c242a54c6fa424adb7be100e2315af087dfe2fab18f513d852c5c80e18afaaab3b3020d59a303eedd0a5c0288190563efb4a422b8fc4192e09d1888541b441ee388430724e8463073f6e05416dba9571f3500c9d64ab3bf66d7f51f83a11a0ab7de6627c69ce49db22cacac750919b85557d6ad4582a23249e5f3643015ed987bf4774bca8fe6d3e10aa7d013745818cc80f82670d63379fc5bf331d5c4f526f70ab2fb1d4d5384e36b574b7393ff5330bfd062b372a216d15af4e15fdb61aa36b67d19601a762038e73009e6c2feaef1055d3646aeaac2a127ae1ed1ccfb4fceec83713fe8d509621d37b2e832d8bf07c6cb19528f72fdece0c6372e88bfbe4afc023b69a140f798807c4e09cc0c1458d99e3c9500c7b5637bb95ed66746d13b4a13b78b65edc1a5da7beec6e3acc98bf863183f5d988ccad98f67032b59be00130e6a8f250233e672344d2ded64dd681e711ea54b85e93b2703c96461c14ad1005c9dbb18b1eb4aba3e721b196b6e5068f5e915b0f4d4844138c6d587f3daae68312dd973db062cd840d5df25c936689bee51906cb93d0dce5048f7c294e2342d401a555c0f766fd25fcfc0ae9c0d06f3a05cf277ebd274159b6a07a2031eb3b93a5868b79ae6ed2204a66031b75561ee7911fcd54b1b5ca33bb4026a6004039d07e6b8960400f011ba655a797c7420e665f16b18068b5d87a8d96547365878b167505e4ea6c2f60307f77e70641b9fad8691eca3d84a5030d85325b8b69c530b6f645a9d2d1606fbd11d82b42d46ac8988fc34c8e98327790725f6cc157ac551a043ce78208261d2b4d65a8ef7b4181a433690bbeeb0a9e414e024453f85406d8337eb1508d176804a45e4f4b17a56cafa9d067b2ecf7832e7a2890e0ad384b3450962b18e1353a91c837f4ff90328c61bf3b278ef290fc67aca8a810d5d1c792811bae2854903573ecb9ead49c831cc362441049a5e6ba95720d23a4a078d66554806ef59e26a20e33fa78239fb961c1bcf5106fbd513392a27e6319974bd8f08673ec0443bc05088c820064957a0ea2a108ae92a7b52d1d4341e8ae5f2101e2cc462b34412b2f7de5b4a29654a5206ef0a410a5b0a524cf1924a19e50456b007fbdc281b96bf5bad60091695e301a1ce0dbd3b18af9582ae41868ff08fc87ae2cc1362a0408251375060b9e818dba11e0a1ca080f25d7d16a3069ba9974cb50143ca9311f6942f8e3892860043065f6ad0012b5aa9810e31a8810a7290062b32d1c788e4c4103e4656a4619ae0e23b1c6642052427ca2039f1e57de9f2dd13d329f8b81d0f1f4db4e2e3dc1e1f2674233531037a86ed7cf86013909a28e2e93fa42688f86ed56f40a80535a3a786082d76e8f9e109a8bd37a6044b0800ecd1fe5c8b66ec3c51e5882c8060a28b33ac159e636c8175151221c8c61696c94b1e045f03aacaab2e397ce66a777794eeeef6876d8ec9ecaa861e725ded34f89b3317e1c669fe3676cc376ee859c33c9325e69247321f573cb964fd4385a43a64094156e698c3072463c19bba623b545dedf460dc7b39d973c13e2420aafcea1fd20f29f8ec79c03e2420b2fc43faa1cbebfc43fae1cb738f27023fd0000df04a7862ccc008fc208500cf9f8d89315ed7550d7995ebea57975ca75d9c068545fa8186cf58a3dceca19f17a6c1f934eaf51b19134714455184293868fc600bebed80d539f0b4449928ac28b31db0a40f71905b5132ec659e29e0624409b189ea397cd58fe99f9bdee804ec41f18d88da6de73c6666d8c5162946909028f30f090ec2cc1d91e88284c417e642062e6dbcc7850c5806135c9828838465078e84c4130f91d8f290ddf9f956e8167aea05d97b527ae7bc1970619ff315b6e61fd2113db8ff905a0083fa8e20e3530f21e4242222a21872c01b585f3ca0bde8a4feb63d4477f7ca28a05f37a4d24663be3db6d728be3d95e58a6f771fbe7d058330be7d0706dfee1383207c7b0a51bedd48956f4f22c5432a22e9db9750f9f617ae88628416538278242d678ef092250b9439d4fc63218a72c072062906a31f581d241ac2d2c316371c21850561706175300a84e33b3845084a7c89d5c129be00f33de6fb850b7fd41853041bb670f1441a5643207c03f1ddbe812496d5ddc2161bd62082123eb01186d58fb505f562a1e7b0a2478f1e77ca640fa78b667eb6a51c64a5fa87ca08146aa43efec25d3a677ae56655c33ed6e32e49d3f9cb741633a3195e02568110da964d842061165653987e45cf7c889555ce4775a40af5d4bb6364d5397d84fa7585b02317f562dbb9a7d3cea5308e72fe742ece5ef7512e35c4a27405167a52e416f3ae13b04822db813203b0104262b14de6d4ec76768cc2d87081c50958e060b3033d018b19e80ef4842b885077a02af8a490f2955115dfed24f11549fd832bbcd8ae1003001d20f0c08c36b6c040891b58ec061a2f443c89018d317050567b2913767a4ee0fe2119b5e0a97c87d346c69e317cced079b2fade8561d77bfcde711e7e16b52a26e52b44d1220aebb9edf149c1c8c459edf4304f06c9ac10df75b93f1ecfb2cce516242bb2b9e6fe7836bf4cf7c2f92d08d4b61fcdb7feb85d9e71f0336e870bd2c4045e55efe155f55755b829c82058ec76b215f95fd205290fbc679472b6ac32c68eb11f6468c60c1a1c62ea86dd97fbbf7ec61d99f9548afc318836c4289a90a845b851e07dece05f57f5d3c57895688fa37a4f07ba4a08fd1ffe78e19066b69c7a3af04529a5bcb566cb9ac32c1761c5a367c0c206cef55eb529a3d4111c1026b13d3193e5c50dce378f6f7f3ff81e82d54454f926a28def1750f18d85876faff179eba1865c4601aa0e57244308655c30368cd606431081e4021f5c0852baaee297ec3dafcfedf3d4f3e793f594f147a2404267789bcc9f08b7983d9650368cecc40de20c1367ced49854f79f159f9990b89cb940d6ef4d202cf48efbe8cf549f59ae2083ccf299b97eee2033333333430db2fb700ef996237c5172d7de576c8e99991932333333df54852fde0a5110a2207c37055110055110055115f2336354b20724be077178f5babbbb6baabb3b6a61e1db8272a14d50262817da04658272a14d5026bebcf7e5eb63d7e37c6149b13492c01e54ab5add8248af5c254d2189176e2f1c4c825d5248f2c4c879554abf6767d5396f05eff7783678d8e5e570f17e848073f88df1e2d93b0463562de52a6e3fb71946ecb3aad1262c139672b934db3fb44c4bf1ea99e9f20ceb45b72558d8fef21836e5f428a416f6791cfdde7bef598df9458e02d51a5fe8037d3db38e12eb34aec4f070604228e29c576528dac119964c9198ec552bc5772979542f1c221652d196cc6afce31d1565b9e43fa4221bc2541bcd0427d651b6665376a791844883c5222e9cf3a6f001428bb72035f5c4523445b0f41f92106f7ca7656173fc431202cc03c17ef94ed350111082528c6d3efe4312c206990368698810024208a2610cdd907bf6d7022e86c83229d6775e0e7bcf97a32e417abc1ecf6e64852423c8eaabcdd227a573c246ba7420324ab1804c113a5cd031242e532071f17244c506882f58c09c5982868885814449d51fd2952a56bc14d1c5173fd80229e90b761b861756b4f07164258bcb8261e50af8b4b082c51192952abe5bc536e01556b89e708519e90a1b4857aef8fa0fe90a15ed907b3694530924259a434a220e9a84994735978324cc7894945262d9d196946994529a6944605c34edbaae4bdb92c021092b9bd6485b84f0a852c603d3298cd54aa552c99ebacc2fa78b8a1aad91b624f1281bad660b525353b30d81ffdc06a5f543da6205698b11260d8dec3deee6f7861a3a9149d0cc777bb7741f2653df5b45d853beb7f0aa8de05567793a479a25893aa7e3c726236f9381672094493f9044789144e460091f6880a2418a09a2879e628248be8048be604e08a44993e661908cc17465ca43375d99b284bb5bb162454c10c5e16a50580a04058202814352fbf01043984396f4cfc1e0745df4d5b39efef15818c6fe4a808fd40395cfa2d6d33f5416a83ec4f2e73e29185921c903023d4a0a12d96766043f9eea881616308f6ef2c752194139ea0a4196f5215645790e47790ecf502647b9c951350e59356ef20c6e44aa2339fce439fc74554820ebe49075f21c5a6cf507dfe7cc574781796abe7a0a347c75159847f5d58d8cf9da53be7af59e52bdab44f95a5d09ff6056b5c207455f3d04ccc34152c0415647e9c1576f1c9847005f4d9e831b62e5b88ca673aaaba4c3476241eb83d8c43551e7541733c4cae03684be7dc3da78e7466c2091897bc1c66daa9bee083aa79a92744e8dd79f4e74eee944b735a9d3551d31b9757b854cf7f9744e75fb3af5d031f7a95ead1593aad97dbcca9274ad0c80ebd60bd494b1310f0e2c617091420d334f887ce083106bcc90c31a3198410ed88da11a72a0e10d2e55ec5085053de001e68a35d2a0f2858d2bb88d36de083460e0450a1b7af0c11b475c20430fa62053e6881a98797001eac6ff21f120c363ff90a8a0f90e4707d99cf276ec19739a33107b4c4db1508b9db55ab31229da51a8a0fe6ec8cc32f6bb95ccf4569eaa91a977757a4629adb5522965aa73e69cdd1da31d638a796b7c7f7140ca15f07eacd0393d7d095da17f40345e0e7408bfacf15007f0f6abd5deaeba503faac01275b11dfcd2031a2258421fc11e6dc5d369ef302abe93454fbe5962ffe6ed2ed08a0704dede2283376629ea1f718997b305f6686fc9c43792b5e9242aba3879f8ee2eb08408c6ebd1dede5b3c20518ca7d3de5f3c9d1663bb566bb37c3b19d0dbc7835f600939af07f496de33489900bfc4d592fee129345405b646397bf87e3acc6a9f1715feaaf41a3915bc46e6cd2819708a5d41e89c05859251a66e5a0754bd372886de0d5bf26861617d3a70e537d46f523b4f07facd152f1df563d80e156b804e6db037505ec6d455fdb4e4efee55e7402ae97509bf39d5f4f6a1cfa4949076aa1f7e1502350596ffb5aa6c4e6088d09f0779fe3a219590e7d1819ec7f83eccefad1ef45e227b105ed7e5d3218410c20b5e375e8dadc8b2cc6ad9834e53f887c2bfe98fa3f276cc02ce03f173e622b732cc6987f38d9aae39bd9d3f1582ed78f0d8d97c528f3edd044a7de39e3f1dea26ce720ea5f4c2c7416898b7d769810bf3d4cf572d0c3dc40cb364eed7095b679797380debf9f627fb49c4ae9965ae790a6b0f8a9cc59bab572cadd5da7a1f4334eab322a883baa7c63071702a8f5e451ffa88735df18a31c618239c1ccae2ac78cc297de8e58edcd9611e99edc81de61902a57c46b8a1772939857a667a37686c75769ce9113a140ba9402a900aa4428579824c0885776eb47ac93cf40b5efdf5aa88c49f1e7fde15af5eae98673a672be65931cf90c90d79bf81e93eccad30e79297d16350b4686c57bf68b61cd50f4d3f3468ba7b5eb34fec0f4300028717a2b9dc84bcd0ed7ca7c4c7c7232b6c60dbb0c622e646b2b771d10c16cd74438f61905b618525cc63e4c806ba77e69969add6a652b44bd1548a7647253d2fb3d4141b79c5fc8385bee5522263d8d1637cc8b503f5ad430d610e59fbc7ce7e447d4c79bcdd8c5e32954c5b69731ffed2a6719a45a56e5ec68e1c6b09721c381d8ef6d3a27ea6dea9c7cb5d9dbe95b6d20dead7367f69d26cda45659c3f1d3a84d48d104a218e1f51a3d8ce1d277503a7a4d2499a3469babc0c923f7768a8324cf769d71e9016a06724fc2479da09e977e408afa411d84920e92caf0f0abc823ebcfa79406e7e9c37ebccbd277accb9e8db5544d8a7d778b764c70e54f2f974a833c76ee3bc1569b7cedce6373e1dbea7d35b9166975b11ccb31a0da7661332f4a61f76aab27ef2f75de3365cc7a988605ee398d75c957515919397fce4252f7906b51b9f0edd28ca7b0a40f98933b9e5840cbde9e27025ce7240da4d615eb91e5e65b71b7aec9a70537a40201398a65b55b6740bf0e926a4371586aa6067a74fe9e57dd1d9a47ad02c92e4a900984080c7f4f9f77874ae3d1de8702b3d9de705e6261f2b1e9eba61cbdae381d5b1dbfd38dc8a54c79c624ecf74d1cccb7981a8476f4cfa6be7544ff58e84e95d9c3d3b9863985fd18d1bddf0e7c3b38a2cfa68923665e69cd3a7c733cc037d07f3f6fabefa3353f4b21a0e7a4fc9641de32018688583556012afa4f487e5c0dc80259cbc7778a7c3690ea73c9ee2504a294539a514db81aa8e79a7034529a59452ccab77392eaa2b1747b05a3d32b046335986f97cb18c241a1a020c68befdc532593c532b566b3cc33c350eab77f10c74d8f506317c5f3c2fd0c70ef364177e81c35af99593df5ccfd7f9cdbda39f5c67829f59b350f558a6c6217cd75c2bf55886c633df05713fd0bcb622d985cdde26af25afb78b66be9d07ce4d8dd55fbd134ed31503e6cb17495e6a67424fe748ef7c7c9dde984fc74a37887f367329c232b0c7ac0edd72a69ed4773dccf5744f4f6a6ad9e46c1c665efb47b535b7b3d8ed525c579fd5b80d3333f3c6b7b3f10b74f9e6d855e35dfce91a57af0bc3a2998f9fd19dabafcbe305ddfab0a9b4d570a6d2567371f2ada9b461527ec764525cae27580c7fe1a42ed3b1eb7627b0e1a04737600fe817d799e02fb7a6d25633db8adf9029d3547eba6d1c7ebaa9a1fcf4d2107efa76e6a7d798e0a31bb0c71c41ff8055ba95f5ce5332fe74123425a6773b0fb11a54c63111af3086c239d38df8e9a7dbad88702b3fa9fcf492641c7efa762516dde8ba9daf3df628d5e5cb55e2e3b1cbc7675e2f76812ea75eeb75ebede2cfebf217dd8866ae1addb081393314bdf6d1897ef5af45e5cb533769d80ff5e9d2e3f438247abd40b30807d3f0ab2961a36bdceb1c392717ea40f54aeaf3568e9b0a2a2d2a55becad7d60e51bec503996fc0bf160f5b6689524ae190ea5abc1c6e81694032cc7339f5de82d02acf7186b2e1763a677ac6f5f06aa67835dd6b8c31be18a95fd02f1a63918c524a23a544aac78da35c6a52280652ae73f299532ebb5d1ca239f518219aa1333054875ba098ec96f16926b4ba0f5f9783d4218499438765984773e89977b0cc43186f107f855ee1e5e80f6ca7fdd42c8a79665635a75c67b983417fe6bbe854bb2e28a6c2329749fb30dd8a649b47cfbc3bf955e3d7ed9ebdb7abb941dc9dee95451bbfbc0b8a1be4e6528782eacdc5f761eaedd31a77e1165e994c5bb55e4db56e9b577b3b083522986f5773936797d6e261ca675f2199af9f55cdc4512fd12e88fdc2bcfa9539f5ecd24c5cf5124c0396e0b53ae4c23c2468516024685104a9eec318a7d5aba1b22f9a76bb13609c7cf95ec47431f2e504266ef3124c03f630c1633e93b66bc64b92cea14ec604300de7af545382832d5e5147713e9d435de3e2db70afa94f98062ca1de0e05efd704aa67f7e2ba8a610eb7c020900c76d5231d4d64ed90d580ed9521acb1ded884df0501fcf4f60ebe0b02f89640d61c90746d7a877530bc4a02fdd3fba7efbc0492ce60b67cbd5d74e95a14567a77bb27e688efa2774d01e93db05d3b36bdb7145ebc4df8a343cc1b07dfc121f0e577f1edcfdb0d6d299c5efa5421b95898c3673558983712ba467c3550819c390831ff6d481e00a50afa6f4312d330220debdf86a4871833b8fe6d481a4c1b3b60ff3624042842228bec0c521936d0fe6d480090c30ba808b1f110507cb04515a57f1b121d61927842c6f46f4302d540820d2c3ea449c3c2bc39fb6f437242230c96223c11d2221d731f6eeef493ebba0991f8d3a5ab84c86702d3a88c3c812c8c490532c7bc497699bc64cab8ad84952ece68739f2e0119655b86b989cb7cdb7c724c824c2642808c4cfe5e890b6f945debd57d5abedf3cc35826c72e11d6447a052c4724baf04698676f43724b44186bbbd80aa54b84b1ac679708931c11057c67b4b992212b6f846dbe79c695dc722647624d9e5da2378655721f9eddf51b4581000b051d64783aef3b2e01051d885e0f88714298cf30c43a39d152cab2cc88e63e5c847a0349ec124916c6196143ffb621404698bf5782823722922c4c4792b753f2cd854a177b2fc9fa636dde59d3e96a91ee9d0b36afe46d81c5064f1da89dba9096d739f60a2db944fe90a820fa0c690a343f6f1091fe76176a5e492433836f5939264634279a97b620469ecc30c4a241cb8c5b1108fc9cd04ce7b09b3838a573b873322f253d7be90ac1a44ccc119624a608164df10e1609cd30c4d222ddb5246cdf16ded1337969be7b437820176c5e890098182309212d473637b9e90af176cdf86395c47cc744db85c22ccc1f2bbbaf7380fa020d19fa761750afe4022e98e1db1fd21a5f3609b497c0cb7725e0e2fb094703b3b2ab6acf1c4a955c931ffe760b3c56c6c494e6dba11b45f1c1c23ce3b04bc5f33a5419f52583dec130743d74785978636e0743abf11d3f3ae4da2347a487183348d3093db3e04a869230f37d5970ee8420bc46348bdd09229012a187ad294f7cd01bb324f635127a0e8329298b0c8858f43285af934230c64c90a43c3043dd78538091828d7fdb1019a628537760fa8724851852e4208b4c0a2f2dc4163e93f1e93c87dd49220e24afbdf50179f1e93094285aafb1ef548ee199a1f8123393a625c0ca081465bdab4efa24d24450d0c98f0e2449d02e91024f1d8707bd360c51ad3bad1becf0d7bfd60db43411b23a80561759fef4afd5450fffb621150d3a9d527a83123fbdddbc4a709efa4dea8d2ef893522d9e525acf401d3da5ee8f7aad67bca359656cc6a93edbbf56d2126ffad74a22429e014605638a242a3688f2efd4aa819937bff2aabd846f1fefc7fb6121f0ed19c717b36ee6a9bdc56b16b6f3f13e4c50e1018144df90630f50837de3d3810c9ff6b2a8b63eae1ca5e428a5acd563adb2ba740833c83c902133330c82fcd5b9c9d095ca45e5c242af15d25abdbbea75e3c725a07c10ca18bb2594af6e516b2da1328147b08aa7cec305d9c3c9e4cdbb425aa0cffb3aa76385517a0f0969810e03c6920c253bfca979962de3e412df1b5ea5b4c83cd11d75c3636311e0c5e1d52a084e848f4b9d93f78a85edde918f659e19637f5fe7155b148e75e6691f3c82f8f015dc7c9e0ef7f08a1dc7ab16d684e83e2caae38deae776ab2e1616d1f9792918ecdd8aa288f987ac535876e880e8dd1e39d8108cecf943f134b1afb585e8db6109d09fd62f3a37793001fd74a037793001fc74a007d56fc2650adc32e5e94ccdc629d2dbbba1efe44fae89cfbb30ff27d724c9bba07d3b8c0f0e791a8dd78eb9e281ed98a99b98caa645596d8b5e8a3b3e78c53ba87f95df3bcf8fd0ccbb50f3d2dfedda630dc3c6efeea207614944df2e8f883ec621ef07b4c836e48129226fbcdb4fa321ea5e17a2ef27889e49a321fabe40b61ed8831dc95e29c82cf34ccfde53ee89496a2161464bdda43e9aa845cd128494fe6497b66d58493355dbe3a4d509a646abcc33ab183ab41c5b107aab15368746dde4383a34d38a475c31062f0861a510c219a13c52ea3a90d54842573df2aa86612750bc5d04aadb4fb436568dbaac343b693e2c5074ea9d8f19ebadbce20ae6eb7d4f27bb472f7fa4669fc7a734e35e8c5e4df01d7517fa8d4ea0b911ed3e19223a2a9a12058a0c3110b19e4079608e60c10d57a4f1c61360589a4311f2000fe0888308454853851896e64230a4a9e20c1ec0110711d2b066b82b88d272c10aa2b45cc0d27c86219676dfcbc9a84f8eeba8d7237b39e6d865f2c203c55ac49fba0f23b1e58179db901b5dde2e8d91655e618cf70259641e20e92f46248a9e5d2231e5d99b9b3ba1398122ecd3250704d961f51686be5eb8d5dbcd14eacf4bdda7af6f2026ce847a0b434f857eba0f0f4d00fa24d29d02fc76224db4dc0834ce0334227abfaa3d7eff6be3557d3130c49afe5a3558e35fab06639efac0ae9ebc3468e6a5425e1fae31b0b09f937f4270a89bb3a851b47b53f9f6d50e6c04114f072c6068748dfa7bd5e5d55f46027bb36b11f3edd1db598b996fc788be7d7a3b4b2c5eb0f8f04fca8979bd1d567dce5ae7acb3ce8741ace86b5c73861a97e605d2bc26d6b46b9aa6695ee33e9c3d2d6e3ff51aed701a69dc8ca2386bc785016369a17e056125d853af4d8b5c981f31e531cfbca963dc7529f7833d360401d7dbb8845da0ccb12ea3b03b98f9dc7e32c73c3b6d3fedd36bb8396be664ed629b05dc09208e08430d2ab02862bd97436f87393bb6fdd407c2bcfdda86601be618c64587dcdb90e8708bce9dddee7ae99b67282ebe60ccc9a5d32fbee4da0bce7cc927968d03cae1dbacf1c975d1338f5b11ea9a5f9b90e8d52ba72272f2e8278f57a5c3515ef28cb7a8c323d074a0936fb5cee8efafb71529f9bc2a1d57c8d05b57fda0fce4283ff969c8d05bdf38e9912b79763be926dfd13bb81c5c6ac575435f737bb88be270b81d5e5da0d2769d5724c02081a1a18fb793db10ea926af272a17702c335f4bc614d9840e0352af4d54d9a93af97bf0c86afd8bd86bede4e6af4fae015e4b68e62af7fad228afe421d7cca8188a47fad21aa7cf778d01a22cb67a6e7fc63ebceb30e647678a7f20698a733210523ad21889e3d042b8cc004145e133f3695f2b77ade57b68ae0529db09bc6ab777dc88a887253c6668c121738ff5a3130e211878f2c5a3058e2841f9050864d97284a4668453a6481f2864d18ad8b11a020418896119416963224d42f2cf4d40e1d395036352394e414358c2a468d2d2c54a294123eeaa5cca84718a78411a749d094e82804f540d0519fbd0744e7abfb70163d767d3b18a2c64ea6cf306f0d106055af909b11b6ae302123bd443e6fd71d35cacd792b0a4eea03db550440f761aa83f78424e0a13f7f3ca2f4c975432ffbca16861cbaf46e97724aee7d4f2963ec66869b10d85748029e086f5c0723f4068a2e04327b15d9f3223042bcf119e790ca81af40797edc8b3ec4cb17deeb85a2a543e1d02a2ad34f9ee8d57835af58f92ec5d622bbc976e0d6bab245fbb9e14a96df4050c59397264d9a0c3ae41e2ca9c15b186dca226a52c8e8c46c2eb41a514b2db8341d3021a2c0561043789414218820ff88bcb10d6422af4ad501edec75c551bc20e07966e21a2cdcc108cb34b45a30e56b4de93d1d213804991a91a19a0c79d19f1402e385134e87504a19f98d27c01cf1f17a66fab1d05f2b0830ff8424e0e79432c66ee6788524e089cc4d48029e2f13a1ef7ab6845d844c051b5f7c2d20acd07fad20be680581f428d80a82cba378c544ad2088f8e627dfdd0a82cae3704e0bf12ea871ee8a082f720c6334fe71c339d429bda1f56a94a27845d3d82ef5347593848660044b825ea0443c6859f9e25f0b882dbf807f2d208e3ef20f947c6f346fe41ce9f2c61c6c472223cc73640558027ce94942c03c90875d3a8c0284111f9dc304617d78f556d267eaba6e576bbc9db5a9d4bc47f2762b66c89021a77e681ce1c32220d88659ba14b511349a914eb720f3aa88b44f1fd23eeff4f1b17b4eb138f42f88b97e0f877f54e1950a8eb8700ed35a83ed60111f75619ee83c1d17f804f34c2e13e2005fe81c3e595ec1a7c31e75b05dc3882fd620a2995826c201b79079ad1e8640a60cdc42868c1a37291ef45aad5e1cb9f792bb6fa7640bea7784e39199c0e7f72e18c384617a91eb1739cad8cd31cb20c7662d882791faee8567ef6caada60eb7f85444e9434ac4e198298d5192cd4b4db05c5d5d35cbb38676c87533b47d36e97b2d235cde116ef2d8836f9043e218ab3daa35b3ea13d7aea26abd3e9a642d26e720bb49beed097ae0a09bbc92dc06ef2a1d7b8cebe962d79cc37cec4bdced13c636c7a1614ffdaf2d3c298710442f6703a1b67f8e7468e7c68106c7d22b85c731f8cd58c1d87e37b7e5dae7906294ff88010e0e9b447ef4d939059dbf9b18a2b5e3510a6300e2043b0ddea1be7e9b457ed76ecd44b5ce51cf6cd7dfa0a8a9fd1abb3a01851175fccf5d959c4152b9d7d151f10f874a0f38f239006eb83420a2a2409c10894304fa724f57e6405e6e9ae167f72b1e260bb77c4734395a282121c79856055f041c1486c29031fc83cf5968fabb700bf7ad65f9eba8a4874dfe1b4cb531f9ed0e1dd45b7698fdcc559efa2d72d880e8f5c0e6f4e3339e6f1b263db10ea28af1cca6b38200c73eb254ea5c3df97fc3af9c5a97478c9dfa776786a8763bee3aa74b88a48c94f9b0e8f1c6a04afae831332f425cfc17599574771361c508d53af351c50f5d3b5bcaa3d25a0eca6ae09bc92f5def02a722d90f003c57ce4ded3a9f1bec7a3fadc8a50efe83e2d447b3ab2f474a437e78357d2a5c328d21f8e44f12c834990f6c9c4039811f938c87510c62a48181202be57ebbac2d6d8b47070f4d0377f5b91ebe630699ae635395c3b6d9a8d3f376d9b437f36db96656cdab82ef34d336d3b4532df5c85ba4554d92df29ecea5993cf3cc847135b73b6d2d1c6c69e1200b36746dbe4307ca2faef3bf4a2dbccd4fde596cebac5747655b4d069439f41c1cf4ab5e8edd6ec96335288b5d548d3fbf6cfcba3ceb29954a289f156a7314ca33579534238f393fdeaeab509777491ef352e976aaedfe5cce362a2235eee46bdc4d8e71a70b9f67455c88ccdab5c57c66aea32557ab44833a24eb5a3367efce72976faa222737d552e68fd3b86ec96baad2fd395dd37d4fa76aa6776daf5bf21ad7f5d5aa89eb96bcc9b3f77eec7839d2df8f6ecd6b97e4db977cf5ccbab6dd6ec9b756b993679cc977bc1ff2e5b4cb2539dc8773dcae3aaadea048eda3b8ea355755331b2e88bf2f7f03cda0f874baac7f5961bbae5e56d8be5d10fcdb75dda999573fb9a9bb5e15e69a57cf7cabbef39b67aebaee8f3f9ddeecbb7cf3da98b7a65d5556abe6ed15f3cb5f0d8a964d0f7dbae58c07b8092992f98575f63bd5f4c92e1566c48b5c5e337fbfe4a9c530e84bf8aab2fb73dd771f757855f3fec40b5ff5e9cf0c197e5faeeadd1fcdb7cbe3c6bda7835d5575d535affba3aad255b555f5fe2459d21ee7f5793acfe535f274de916a3af5ccaf2ea5a2f707735655d5745575eaed5755ef8f6ade9ff774da55d3773ad2dba9e6fd71f913efbb762883d5cc85c585c585c585c54e26e5bac2c635cec64f7404ea278e044fe5f0d3c9ea50e5b83ff69e9c9e4ea713d72df993f326a488759453afd1e135394e39ae4ac7fdb1d4514bbec6e9ed963cf593fbf489db810a8a7f72558d6b4eef09e5d651235c575c57a05040238c80b2b149ed088ad715355cb744a55af25d507c94d77856c30105c547456bad0d8abe044b02c3b0a8a427a9e769c63cf887f5d59b9c52b71c0fcea9f7f1aa9aaedfcab5d6d8b7b2c6dd253baaf5763ebed66a6d2ae5d7e58565795d927d8064be25d7c93b6b602f8f3eb9c5403b5d900f69c43c46a718c5b0cb24c943a759c5710ca310c26ee753bcba280b3e1e483abd9eb01aafa2c7962263e19179a0e99e79fd0c6a357a7d6b7cccae9247a67273660fcd5732dfc128d7179b719a12765e578bf33e161e998f57c943f37d2bb3131714a9542c80b5f1fa99a95a3f797bca6b5b1bb78e61369a635cfdb711f9f1dadb84d85c253dbfb9e6189759cf4e5cd7f327ef7cfcc957cc63e327f7fe91638777a93f79ed1f23f8c95fffd0e127e781f9c947e05ee7a4b8d73bb8d7281f8fb90e2e07e79d83b90db7e295f513a7e4253de6f6865798bd295e616ee278f00af312b7c3b1d0f35a7651bcc23807f3197d3c76a94313c7277548d7b3b3fa76fb9b5bceb9d24df58fedd6cea13eaf3be94e64c886a59e0694f77f2d34c69c4ea7d3c99ff519bdd36c972a5da8d641935b1b454a157b9252e514454a15d8a548f627ae837f3ad99a9ee25754d238f306f8d74ac30b1a5ffc08ff5a62a4f8ac356944ccd2447011fc78a19528b084f714563939f458ba91a23c7635ae79677d8b6ee21effb07193a32e8fccdde5d16db8c7268dd3de9e384d096bbd3b7985f6029d6e07dfe456f34ea3251ca0145882e90295dc7ae9024d976fe105e92d55f958ba500aec11a38c34baf4254a521348fa65b5b736ed761362aa907bd6724636d19ab8c7ab68c3556ba14dac55a4549152454a152955a444cba72a2360d837e6df61d8e3c18f3d9dbe52603b1edfce63c7478f0929cb0e8f8ec884c0df61db73643a72d8e76fa26c6ade7befbdf7b8e832953a59d5bcf5ed77f5c2c1a69159fb6266b250b4707b2a8bf08df89660803027dbec8b3ea42f1e2ce4c7498eaf917c5bd4e0a81d799545eebddbc669d781edb4ac35f8d8a1bfa31abaa8e06502f986afd1f48e4659179910f8d829bbec8b991822feb5ce18f309f8d73ae3cc370bac45a56e9887cb43ae09fc6b74f9510d5d3e839a51b550b454c766d2e3895eedd67e71aa76f8927190515bcaa685a2055e1a9c55b901ec3c629af817b33392f871a682182e12a7d6e8a3d654aa8f5cb63e32285d6e1368a77436a5153e2e6d4386e6aba720395409f3c4c3bfa8d8ce3e84337808c36c79c884e395038453761bd98b1042080d60a13fc84456029b3dd52ac7445020bfbd72dc24a87e50eaef75f1f613e1b310b6fdf40468b66d937590417f7ec6d1bf5698a3ef4cffc224fddb7e26bcd03e0864cf46678e5f0bd1044fffea2581c07e78e34644c8106f42a2b3f304d8dbe746a4037fb9ccf4d1d9e91624f20dd414bb18bd259d52d22965bcb6f95a8185344479e970e96026d3ba9e7f9569d6d12b54224c0ca615dabc3746b5b61059bc6a78648461412b0c1051de1b8afad70af3447691c57e4450dc80451262bc11052b26f1d153644433c210000e1cec6089379a10830c2158b106af59c147b565469616182eb0230a29a820b92b3fb460082a7ee0031747acdef27db49381325318218311645c9185d5570db1fb88ddb2a7d88c193ca7bcfe6b99f1c477383b6e5c3440f99e151c6024be5b7d0ac2231eee402c021043186fb8008b1727aa18bac1063031c881941a640083b5b4c01051e1a839580307d3e10fb9946f0a117d735d19533c24faedc74ae6e11ffec3592a3c205dc61175540a8a964e2be2dff6539f7cbcad5619443cd12a838be3c48be891f1c5185dbeb4c620d31a03cd992a2d32c6b4cac8a1550614385a6140c1d202e34c2b8c2bad30a888d1fad70ac388ef6e5e8631c5dfb8741ce92be93c3c324f94db0dafa4bf60a5bc64b09db53b4dbcf72630f4aaee8901af504ae950144e905183278e580194385c20860e19e59046d1186068b0022c171b454873e5cb974ae6226a8151c667ff5a6024a501a3e8eb3f325aff5a6444f9ee756991f1ce45cf2c0483f1c473dd86d4fa784c576125b7e93eb0afe50598ef5e1777017ed73f9dda1e8ee5edf1c2cb47e7871b11f8f1eeb061a7b777abe7f7def3312107d67f4e8eded1bbbbfb49d67e415e75511fc1a2f6eaf4763db7db59790abb9d850d7bba9e9dd50a9ae99c4ea5ee108b81bc6f20e890c889becab7901678bbcad369e7299d939414bde9b393400489a00b4122964f10fda962874441f4e7050ac297c94bf3ec2ed0e7db0dd57000fb588f256f13b13a080f3d0ae13905e641018c1edeaacb0342795000c387b77adf3d2efe08fb82f0efd98012042f69788043872eacf69efed1eed33f5e1443cdc82cb76c7de9d212e38b34a816b4beac41e34591b13645ffb5bce8c18b28378c8172cc9831eccfbb15e64e38275a8e602677c29b43cca31fc13cb2637edd239af71582aef9e625bed6760e753759e0b1a0f00e3fb9909623d6775817d2724487b343e8991f819e650efdba47526eba42264f5d235748cb9193c32bb4d339d44fbee39eae1014e22be49d435dc77d9d1339acc46d57488baa02d1313f122f17ba47dab52b04a7740e855748cb11eaecd811ccf90a41a23b4548cb11e87c8584b41c6187576873be42257f9d53bd66c7c61f2b873f1644f963e5e084b41839b90de72473cc6b38275a8e641716750e75cc9d68459caebd1d2c7aea1a177b9d0869b1c06349ec3a91fe581ddcf2d44d5c3bc63d960685fd03f6b5ba40f3d9e3c725239591e91678ace948204bb24c43cdf408332a189c1e253d65b0d04306945dc928021d76bf377768b1ab18aa69b4d5c51301a512a8244d55b5458e32453323000040004314000028140c0744e28050342416e6e50314000b94a0446a489988c32cc751903208196308210680000800ccd0482b003e6198211cc71749f0ef63aacb2da0a52367bd48667896351781ab0237eea66ce75f2237adfe1844347e9c71c8481993d92f76a471eadc39f11f4f9409c3a8a64c8c6b65e7509b3511596dbffe2ede8c40b4883bbcd3440085908fc3d1a067c3260e039346df1ade95aaf0256bef702024eecf2ada2d6088647f7ba5b351a3eacc095d07ef27b1f0c872214190022c15e94dc711cc18afed05cbd444dfb9976be15dd0104d1f13f3e55a20b81a71543c552e168996b0aaae7b908c90e430181da5930bd716190bfd4710a1761001eab7b63e24f1397161e6a21c3b1c66304c0453122a4eb59dd45b054a99712ba430b7bcd72f12f342581a5cd1f658a8da127de9a396ffa16655400e4d405de91356d692df908deaf03eb3d46f0f97700f537c1e7ebb49fc2ebcdbb50f1060097354e873cedac64ad5ddb324c5b791539d8f7b1682dc5e50375a7c67119452149e15d2e6af0383c618ce5c245f2636907d7061b98d4449aeb66a92b7bbe0a88560202dae977a6d74b187917b47c5372f35b299d581efbec967c1314b07f23cd7c2c4c67e530c5188f79423fc5d26466d44ec42df11a40ea8929e526a06da7d81f65ea692cb2460aab8c596ef215ae8484af8c92e506c9d58131bf7f5f491e341f3271844fd8346b834bcfeee39143d15875fb5a0a765ea5bf9affa743822d69628867a9193535ab8f9e2e0a08aba57fa0ccca94f0be49816a294e7669e05843e1d2d3975cabda72ca70fb14d43eb37f4a410a1b4af2dfbd249f15718dc310883ff2c5833a518f841da1bec9ca33537c7238c60ab2a9513069542179b79255f6690fed842241b08e598a3d583030b91fa54173d25bab0c6590806472d7889cc0d5b55c5b0ee06333c2a8af6d4823ee16ae100cc89790a880ef703906ac112373e66a552806aa1839a034d6b218ead6de6720d0bfe892fb3f6e7af765a0b2ad7b49b850e639093e72c44ffd530101b5344ae0517b96470972a2e5c0b947dc9808a80856c082cd8e7eb0a03168abb58eab04fd01320281615a89b458568e5afea21ab6b40a7fd88c1c8c5b900887f58ee1a0aab0c759f8acaa02797cc38e2cd9d969ad4fc1e84b13517d6d096aa13ae39e269278e0c238b907bdfb2b4a24152ada34fd1ddbccd79854ea32979e0cf91454de7b05d731e698bb97b0883c10e4bb003a5d54beae365e414ec808d4eb6efbbaf954a602e0a364a4b684c1fe2ba393130ffe8b51a5c3da245d2475a5f5cc3786158e164702edb6991766681f7ff97e942362552f512c4c4777c48946ab3e51c27352613d3fa407148d467faf5d51c639a45eb617fa26184b055a999ec95f5a80444fa0427fd298b8e86063d8f7290c3b64dc52e4fe105f888947423f02d73cdfeb0e853f66b9103beb067af7eb737c5afeb90ae4499b64b80b2c7cef5847ed27281ad1c0d4f3d0fa141a407ffa07f66d42b562019e04fdf27629e4d47f5687cbb61bc2856af50f0c2d530f3706596084a3835f51a48d36fb8f4652325ddf37250e91f63dc199bcaae96a45f331b0e437f77df7cbe2290d4664f1be4e74802580e4347aba8d350df210c493f7be3991fa72d41b387f1af65d3150b1ffa3362a1e5302e1d7ea1ace4c340fdf78b5f0ee93060350e1996e9a17b25408ce1874fb565def3301c65c5492882b5d48e6977de87e32330040e5b2cf33b273105154d86e3b97b57762f1cf8e73b524c6985d34df7a22d303bc5de3ed1c04353416d76c16c680fc54bab26594493ae005a58b426764b51e51f1c31ef034b9232242a92d0ab6283aa4fa5858938fce22b6f92597ea9b81a88439905bdbbebe26c3b8007453d83807656d857fbc84f774d911883b0b6c9aecdc710cd464da2615c0f642234505e9848218c643fbfff6aea68bfc379d85b2b5854294c07619ba95d2563db06dcb29b9ed8d9844130775e670741b03efe7857bbefc7b5204cab35775e417e1c40f492861b409b67f9fc94ddcb2023810ec10cde1f3acb8080be011897dcbc4ce109d5dfdfcb05dc8dc66406653c4c8658803d3493046883e39d9c702479da8a4281a4005c3ff912001bf6a23da60b00705be1bacb76fdafb5c5d83f525b509d0a280d21f79420a91b8bd6f03a497322063d011e9d1a45db4096bbc36e3364d7a606fa9542caf7c099f636f72274ae783818611883927a980d52c6188710d1d2e1d7916b12ed3ae9b7c3c3917f0306711729c59cfdc9a8080b51b8cadf50b4562e44b541f0f16c5e5669000921f0ab994942b3014311f263a6d099d865b83077c377e40f59de96b96c357dbaab49c75aadecb5555add677ce7847b89859d23e52adeb4f596518279b1cfe5c8e41a0fc5acc23ed9448c72e5605358778361ca595b7dfe93090d786e8311444913fa660e737b958d99e0d67d95ec923b7a766097b7ff1caa68160b6f1ac09aaaca53712e2b76b9dd36ff2e654a42ce25f9ff5ebfa0816d44611f55beaf977fc57f549c1f1027733511e2864189ee192806a1c9411be803a1f3111c20aff73c50491aa3cc6f41f107a9b9622fc1a6df7d75d8fd437f51e20e2e803ef049627b79406fb70560532803a28ff97f177fb7c1335f8998bf8603652f31fc10cadd7cce0a0894eb98e4cdd45ab29ca8d1e45a5a0670e4796878b5943562709f526be05066d8cfba4e04346e5da989b74d47e7adab024a4014b6c98b68e3d8002319913dca7b56b81aa4f786b2bb6a30e44f94426efd96b7a7d9e5c67a6dcd30157d57273e014c6874efa5fd9b182567ec506d1eea7bd91e8f38748e37a3e44548e5132a318fc4de0a019bf484f969cdc4ba2da5517456daecbfc20733fe9beb094e9bb9c77f006d32bb3f01b84aaedf709c748664821bc9275a88b02eea30300a59160de09a035e961e468e5b6493f57bb61e11ec06031124833a81a8f89409fad71a1b399a52db117ecaee68cba5a4575efee445108b5815f2f4370339b6c0279709b8aedc790c75d2ebc2b5ce483e2c7e30463f39a58c32ecd0cf5f256539c935435230d54f26e64b027ee494deb4a355366e055c798bc9911198d77ec10d241a61a2033cd30884d94687308fde5bc077617e6be8dbe8ea171d3e2825aa23fe3f138798d3aa1a5c374aa9ee330cc9007f684d76e3be467faa9ee256a19778449c490e4f04f9a8bfe408f384d38057f375bb3d2e937ec951088c358fb960f6100efdeee78d25a8de8a0c0d7ec911a57fc2013d83d09aba8bb322bb0a5c45875a0a82b1daa0bb5ea84ef99acfb39baf93ae407fc43c8544095c5536c6faf810edcc9491a368fe696df6b655a888b9a2fceacce03d3b5e29f38cd1a501725c1f1ebb254782fc26d15894cbd15716e107e27e8c7ed7ddb0938124b0f9851fb6f6117e17b8528dd6f61bc0616242702ddc728e235fe446340082c475fa5ece8bbc45df4e4bcce3d0bdff290c29b1eb7ab88032705292f69587240c036c725cf4f53758d84ad1404caf5ebe1d7c761bb15a4886c0b3cca7dc11de39f16cce0d547f0baf30d79e50cc8e8de793c1bda97b5443e0dc00021d8c393b9ee409adffa4554258ef8d960d47670fd8b13d3bc18ebc8c0fbf4cc7aa9266463c6706f9403b93e24f222fd7c8d20cf31e28cf2db1ec4064d744f298711899fe0f8fc379738316cb03708533ccfe687756c1a923b14324fd41308ca6d762aa65f418722d02ce9d7cd399a8a99b7705fb0039d973b0c9f9b9d00950dacd3fee7a2a21eaa04a3272641b959cb4a83dfd2d1d98e7f38bdf0d3b268e0b35500555b972f61be89d399bd6d97b27bbb412af63d52c386bfaf873b6905a1cf7f1c2fc74edc14fd9d374702c032798914891a69ee47a8617ec5ff26044735872ee2069a38ab50ab66bf2754ecf3e6af18f8c0235716e963ada1eea046f9653a2b90e3d5f7b238ac91137ef54665964dc587b922fc4fd0f51dad910837249b338bfe21f1184871d58eaad87a9636668382f44eec07b5fcb52ceae219d2d2e22be07e9fed704c3229f548922d45e4e27933b2e9af7e39e0e8399f952bbfea3e06b39f91c1e2324409d8f0f4ffa0c5af8ac72afe90a71cb5e94630d57d5e60241f0f26c499ae432aa654241804cb6bb00194d74615c27dc26063b295b06937e2c35688b127a59f789c2ea878e33519d9a28b4b92b0f42d3b70763ebab2369f19f4b5a72cccf02ccaf8c21fa28b441619b0c343603361bd96958294886e834fad4df1f0e5c7ad4396b4c2edb221a6bfd80e1e42ff94b573ad83ff34f22545fd68971271a7fc3ccca10c2d51d4493763005fc6a88517e59b9751094aa771e885e21b2b8774e0bc54514eafe34ed21c4292151681dedf5d37151a477f38b6a5681af67c3258c9dbcf9d2670565906bb85544c466d1491df1fd40631563cc42441efeafab047c27230444abab38c63a8ac5cfeda9de6a9efb0ef3b55a093ff1b603daee9d2f0be5d621260151ce3dbb1580095f0540bed93f2e228233a1601bfae968bbb23392df8771c106d897417e184000cfb4b3338bba8f82f07dc4afb02d8e0d97e30243c637ac1c65a44d651eb121a13c188b088632bde05696250bac9ed49076cc148c6ed453ddae3935e90ad3fc205cc0a88cf74fcda8a8a2c926b81ee9e8c1e438c1df872835110b2c5e2714906502b1a6839be068d143c35a1eba0a49b157161e5c24232c1c8e395acb6d2fa4650c23031910b20da8afe43920764c64a93de531bf787a4f4eb8010170cc0576d1bffb02d7eaf9ba34eb95d54cdfd5746a0f84c6587412002e6e2d8492ac57150c13ee07cdc234cc59c3cd8aa1c0168e348a9a52c9a9e708069007c5a5a8e579716612670c2cf68b699c6758964c8a75f8f2a47c27173c1dc4665654af2072b37d2cd341462382b5bb225ae7e0db6d93c8ff4a6dd426a0f7ac9bf5bd4cd7d24eb6aa654b4c8545e16a69d1ff3ff01ea437807f640221a791f73df4f8b1a13ad3b20818dc301c47c939eab13ec85822ff0670900db945ea8385c4597311f3bd6067bd17ac29cd78a1c4f86f610468001c780703125714dc13c7d9a529cc03c875f8292deed1fb1c417574c431ed1cacde80d28aa69950f633c05a381c652e7b17fac1b935e04029f9bad0ca8e059d30712e34784185e0463d7ad6ad607d42892939588c1b0d81d0b95c39f6ab04670fe3175299d18c6692570a79695d719456b5d80583ca4755f1906a1b0f09784db320c59c8faacdfd1463b21393c5c0b579673f2ea6a389f9072443867253ddbe16579aeaa60a2f95dc9c36866db09335d4b473df5b0dcd6e77e8983efca2b81a0b73cc0bbd8e7a476a7b80c5c5c88bf7fdf3220d499ee76279996879abf018e1af76d34b2e4fa365e02e635758b78e93ae272466d49903c3747c0b35f5d6c1d53f79605ed9b2bd2758ce91725bdd599f22257261ca7a9a43f17f5d2c993c927cfc1487fcf08e4f8d57d1ca5cd4f4bd658a0454817058a069c85f3f7610bf0da382e202baeba5a8746b9856149efa5045ee0f8b02df86fe68c06c6a95638a4987d80f90473155aa5874e07554c927cd0c224821af7385bfdb3ba358814c80d9a12829ef7c1ca5441986965b74888f58a6b8c7c10f0d77c0753e1904ac761880ef4baf9b59b3e06390ae3bad2d721c7be3704e930c838b4474ba48cc3e6ca760a5f469bb413b7ba57080725ea601982716137a10cf28e61c7a64e2b9db4815b041541ae8a0ed3880ace590eb9c7475e4b35fd75cea89aea23596e2980c6171f7a037fd76415d3e1ae01a3c66c238f1e4a2b07349d15995abe49bbc034dd7f979cffcb0ab60435ac0b6484a164f0dbb165ca11a2d7c180f83961be0eaba4b2670d91479558f5fb12dbce77e11a25f8844ccea88889020d71da68ffe0a5f427b7449d68b3cbe434ac82f642195b4fef02f800a511fc8cf88f8d0d64a6b960111034352227e4b358aeba4ce25c2795e4abae0846a0fff8fddfc52c50edb2a137e8089bd045e62f1e120362c0909d7e48815832213aac2fd13750a35878e8f3e195ab1dc8c13c91a2d2457dda3f2aa6b39ae9e5c1283f819a548b0d827eef4c71da959bb447392e948eec02f31fecb2f7ab761b23c6a93c3d847717752b62262c40524d2c83ddba3106e34e26efcb80359c9c5ded6961d01b01727a3b69151ab649c924bfa1a68154b6ee4e18aea747d98d0694fe053e09b614c7a6ec22d0536b0164eeed785271d98ab6523386e9d2af5d0abd72db9f426b18f6fa745113be4b0d9035e3eae7f60a7d56f37c1d7e8a8852b219d30bea3c33fb637206a78ee79b74591573924afab890239581d736802a34bd2515be1ef03ab4a119a1acbf8644c08a75b0cb96da031378a684cf188a9a8564244733b311bc1d11c3a6454580e327cf3a143562fe6ba45fb89c3c38beb949b0d8395114c96fb690f409b179146d1209b2cfa299b602ecc9639dcf45cb2ea2e23a2a304cf03f5a41f568c9f7e96d984599959a8b2a287aea9e18336a38ca3675b70316e7afb29a174b12ca969ca23a28814e0553056601f2041d013e63d405d475df52f0cc2c0708d04ad7b29ca5068f978cb54d83679a977d4ec33d50a7d5e171e80497ff25456d81533f329fadc44b99d2474027812dfb5a2af0398e1b0cea6b9891240e77e2f172d9a597ecc4d048860885e810d0c21b7dea34d1455dd00b93f421d2c13fc039242613402b296124996ebf55f02ae6a41c0420832e35cc72822d244006c2f12b5ed3e06a60017c2db09520c65a10045a71b11dba83f57680613c20896e878fe9df9bcc43ec3ab843010b73882f12a9f3c1c511cb449b1a528c6aad07acd1f656a502cf67639120aa0ce40e7d8d24c12a49cc753ea8b110dcf2f3e5ff20241685bf4b334d33a467899e6088d0b8578117b765b7dab73b9c8d6c944d1dba0d781a736874f18e4ec61b836cfdc3707680489effcb0c0e9b36ed03c6c2b9236ddcc9fc53a38a1225c0a816e671489b440100398a4b252a535292d40a7928f51eb8e509940f5b5093a588f8474ad49c930b9e56322069943b0156d27cb5efc0e1cbc2b5fb601f39214cd80b4012d7fa244ac9dd172f0e709b3185a94e6c1ec733ccb5df541a2fa3ecbe1e3a75e9f68894a4483167b89aa64271ecfd1a4677cc83f86c460ba5d0d3073da13b4041fd46602a2dbd1a76e9e7dd033941b0fcd20f3c8a8d033b8b7e0d08f77b6c67f7b713d05da88062a3ddc55295b3e79d0073e01b6ebe7bd593e22d30c6e6d7111a0c7de2b99df0d2ff8ab91ad550b45bd3350836136b5821f992e2c89f88181063f30f431ef57607a79eb22b7e29755a07da33d738d45e683fd48a9d656d0eb61aa21842f8a0b96e0b5ba73ca8a9efb13db64b96dc0f627af9ca1e7092fcd28b7ab856a8c0a3a715d741c03e23bd10f221592ebad0b3ca6e82b67a5c0447f4a16be0992de122a2952e407577261ec857494c499c2476e9ae069ce91986437e749941889975d3f6eddaa89dd2e162721cc704f39a64042642acd6415c7e39ee0aa8b0f87fe45f8d4d05e3cfeb0289529766b4b1974fbd6ce4f6fde01989b5824d15d1dcd9e1066b660d0d3af03eb2eaf84550b3126b3c100f8ae3ec2e9604ce52508e3663983d5c38e01fd54b75842337b2514753e88df1403b5b1a7a23365082543a690f923be736512a1573da2c46eb879b59050742a97ccb26592a19f793f2531fc2e3a5392b1e935219be72d760ea47e22184cedacad9ddb01d5ac111c86241faac15cbd12044a92fb5a260b381e28aa3dacb9b72c172f5167995694e082e645906f18fc8abae0d87ca80671126343d66aaa313db818dc0f8b29dfe221d52375a3b22c409a8416dcaa584aaf32b940304c320bb9178cd1e63fc56c97f7a554cfaa21efd58e381830c95ade87e3940a5ca3051480cd27e2d5789e99d1be550f52f9d419a9f49f2d862e34a97f24bc93f5369c51a95502de56ec4428511bbd8623564b25a55be1c38fa576fe2ea59523c567c94b945b234fcccb1ea64e6f7930ff9e5bb7925380f5b82e8c154446a54db21dce0da9f5824d4d2a351413c2e6392b88f5f2d3acb2d92ce0aa4cf5d62ee05fe15af23c17a453bfbf8e22a0bce848a03ced5226a8e1099df54c209fd0626f94c64838643ef3922c42cb590a7ea3d2a182977f08e0b092db1be1ade9a168bf0bc8541bcd2c9ba9e5725a9747f091a0b96ca6edbe11ee14801c096ed036e57cb49f8b15b408d19e95dbf04f5e5bd48b1a69c1379115fc55ab88e8be3d57725bc036b833b4dccf12f723b5995b0adebc05dc4ec11b01c4d69afd39b686b1e1a221728776606ef26962dadb6b83195b225a1a30811cc133e06dedfbf4359c8ffa8b32a8d9d1c8d258113288db1815fac65877e450efc87da1e7485be12228a4d8836be6650f6c07eb13269e15afcd3757205d626686ca4775cf3771bd835613e2f983d9abf4c6c7520933c0740fcf42471ed0b7a417ab0b2b4c22b8083bd14b96173a959c9386da76ef46ef2df743049967c6e385403daba07856db7b051a32e411d50fb5aeefd8b6ccdb4303ccbc081dc057994d3af3464a402217cdfb1c976c58f64bd70dd7f5c3e2c8ea3e422ad72120e196b31b01654000a7eabfb0e5c57d5be6dc3e51e9e59fe8c3683d95c3ded3f515876338bc12f47b86bcfc3650cbc0c61998df2e51fc5a97de7b90652ada81c7fc5c8c8225472f7f3ff1be8b28512657f0c082747a9957e8e5f4409eafe74de815f5096521b5f6df551bf13d2e05930925db62ee5d35f04382b230e1e593a7360244defd33e1bdf9400d90c1dca3053a13f3f18bbf16dc8b8cda7de25666ba595c2e70822ca2e4d1e6837c6ffd893098961697bb2c9d70309b2e453f2a78f77f6549024834e39c191b96a04bd9f97c84fab70c8a0622d23fdb441c0581ec2a125b945c82c2abf7db5873460033a73ef803f11f28a0baeab80a9659f627c345799f0abfa87967c79faa84c7fbc60b128438128a0a293757fd1d9049c17bd853260e584be2ccc860079d7325084eab095b1b0106713d8dc204df74db40bc255636f72fbffd1263cc2301024de9f9b81d7f8b3004a54e6caf24fc90c6f8e105ae23d17248ee3475affc17b8e02c4169a4eff180ac7fca0ccbb29a73efae5942e59d9933b12da56530c66a562ad5a669bb7657d494229ca0a6c16689599fbeb06f6ce6cd8501f29a392c16668346ab7b66cc0666cfdda3d43087322fdbb1211916f292d3f3edf7b2d05db95ec70502060128d78acab44417601d5fba8008c224524535bdf6cb2233215737673c3e6d76bca0a799cdcf82454cedf1ad52dd390b6867565ee7d6b3f8acc46abf10d33fd446f52a0706f7d1fdbbdbb650c4cd6a8d48076d98a51825ed74788ba10bdeda2b703f23dbbfad6ac017ada6741088b23dfa12ea4f1e730748572017b37569e76bdd3386ab2a228c94a2c3601f1b667bbd9e90aa51333e5a7882c076013878f58532d061c195d7279babf4459cb0a68e09c9717c5484ea63cbc9b06dd4d2597f2f5ca3450787593bffaa6051f534374bbf709cebebcb3a55daa3aea5a72184d4d4ddeaa4a319e39320092a33fa927171dc99f194db63230c244dfe11749744fc2032f337c3ecc89e5a83d4b0c240215332cf82b273534f0bdd667e1cd5b8aa6cd474cd50309ca30693e1419d851b751038dadf931a85bb23b2e29b8f08041b6cd0268bebc6539cea9cfc75643d703ca24efbd8c46c8d10d5061e7cd453aa6f3ca46d3f0f4bfe7def5623505e88edab4e7476a4509cee2c2e7438ac0b7cbc28c1e91ee54f8e7590eb93483164e238b18d891b3cf4fd9ab5b1a99d4fe774203a800cb564359a6b30bc0becb63b05bd9e648d8bddd9d13106c1957239d2a687d839876d7f777b7263cfdcffd753a2ab7bc96732fac3b8c3c498ce7ef7d516c0a78d14e4c9d3452a93e1f433d7443c6a65b34c27a7992f64f7df486a8ad80b73679fcde8482c4323e014574bea6f4ad3ec6d9551c6ff56dc0445eb8b3686b6600fb9f499dee36c11eeaadf27942a44a11e78c4e91a9034b0bd47e3229204f7287512f4842f0579de191063593e93fc9632d9f7642ca6fd3aa25760dc3ba0bf47c6eb20801b5aab46ba3d81aad0c5039658b95673baa9348d1da2665f970aa00d049483899bfec9527a160113e66b83951eb10f8b133742c975006927baf0c99ca88198df05dc0ff41d057b3e7ff01960aa919d808ce1f5bd91d77e89162c5afaed87770c8ee95b4403ef5b9565197a3762b5a27c501d427972c2949aa73758b6c41b93fa80789e0f8686c65eefa2ff5df6b9abfe77397cafbefb5012068535e7f86d68378494279ba8181eb52a77e26d60ab3856b745f117a048b2ec24c225cd95c98eb754cf1a8e91cf273c1ae87bc6e7f04d20979033143d24ab957506870bf66e689afc1528634ed86ff86720bc1f00732492be4a3cf3acb46096e329d8090fee2f2a3dc656a00a4b82ddb8ab5f3d82a67002e244616411db34b4c53c93a43e19ac36bb246e6efb38609896312ee3b5b2844df968d36f8611a5ecb7b8560e6e105531de274843d2a8d5c368b60a32fc06039740f671d528936da10dd14b0a764d3b62245aef8df82b5ed19f55bd05be02dd3b5e026bac1d33bfb966fe1ce4076be155af8ec6e161b33c8f618be2e2ce60f1bc582bb166dfa7bb6cc3342a48b59a3f582cfe67477afe5a6df829617a24295e183f8935e71d5f1133032204e2a94900e2f55f1230741654afa33d18eeb19d9cd46df07325eb5bbc39a978ea321aafeac938704a950c4c49b2b88ea70525c735dfbdd07c76487c56a3ac211889090ca647a6f09da410ce10e617b2c896818031bc874b707258e9cb0775e51bcf55f31d168ac8028d7bc4299061dd36ae71db27e2afd31ed1e42363174d0a91034eb9741393b0dfcf4d57d2f93121ba0c4f4968583e10a3127af48f39554883506b8550058c1daa9420c15225f5be68c551abf5303b02af921b5ec7ad4af306dbecd5745233b852c04b28fd7c82ad5c48611ec28fd8cecdd13a17c2a51638a806e8dfcff7ece9008ff7bcfca4ca922829786e7a750ff641d157322f4aadf7cfd50a21201b82cbb214223f5f780d494612d9595df944844ccebca218934e94bc18c7f23715b1e44457da2ce6ad8b5cead45f64d456317b43072751330ccd0425224a50d0455829c105d1359eb054b366f49063b1f842e2bd56b7616e536e82ffd3183a3111bc49a1927d902e36cae4f129603d0f5aafe41187a5f80e231a17ab16f1b4bd46c910e527ac0c829da3c92b4241052b9d20c378ada0830c77943d7a2a023f2d0dfa3ffe41a3099e2f90379ee2dbb66cd4deefd7b2f4be7b09852c29014c0b54c20bd4b0ffd90b79bdeb8d3ebbeae199824b29c108d8d48a246a0a8da2a415887d52111ecc2177752549fcfd84096076c4e119323eebc8f69b1c228e83a7b588cd84b322c9f0a28ee2dc8790b2c9280c807cf59ff0941e0d948b02b94391fd7971304acc3ae0f3cc3a3cf8df104841fe9d1c8b59354d43ef41915cc22990d9af490c09e6da7acafff1c4918be6447bd664f9447e2c259cb1afaecd456cf36e69dfd65b88e613c8ef1eaa182249ee80aa2a9f1e72c33ad2038c4dc18b73ad3b06624587ee45feb95287bafa0680be83d334fe866429fdb130dae5d5c1c389093af6c17cf5f81254c647c766e12b6712e4b0b96718fea240b9b8638493ff0ccc19345d30c613f39a61841fa1671e953fac561ee4a28ecd055abfadae51bb9f33a40896560e33673446b7d700ae6247757323393e3e1f0217e3f07c0f18246c77358ab4010b009c560f528f8133ac2a8be97615b77625e79b8ae621f4ec3e85bc7120efb313115dae5c4df308f01400c87e70ef30a9fcf0e0b028aab4fcd8e6edb4ed509d59e7bc24ebe4463c8e069e041d21f51e72b72343bc41b859c7742365c137ee819ea9fe821ed81c2b0558a7121aebe5ce7007d3cf654d79ba743d89ed9433eda61b81933c178d9eaf1d0327287bd73068768cd878c8ee39e1bb30fad83ec4253aed6acc53ac3f61bc819ba1f1936fa2e2663cf4ab6715eca41a9d622652cc9be754bc6604a1697ed1a695946486d5d91c6369b15e80669a7747860a80160b8d6ebd3ce0ca9cf08382599d82e618276a01e2513adae94551016b3382949f3ed4509df7d1fbf1e780cbf47a02da881792532bbbc72e25c138c6b1a04811de93e1aa054423bac198e9494df0555b6c6e2b88141a87cad3454c2bb7f20216796a7db97535d64009794a6d9be24fcc92454c8b5bf836cbba3d216f40e0d942ccabb72068cf9c82590fbf4a15978726d767e1e57a018bf5e18c09f129b8a1a1feea4f0bf9f9be4e1169de1945255039f4a35e2dc645211954f81571fc54422092b16ff146dac0a5a12092b0ce15aba0502b905f51f1fff5cd2cd76663c43152089ec0bd694e354921e5d057b76c944bad4c28a1f296a80ace0008aeee8ede80876093f0f9a45bb908067df1e9fabbf71912e5c344ff246d7151e79874f97034110d8f9c07d1d98a80009c8af7e764e86b7c417baa7d8f4b664698900fa5e6a8812e23d0d934e6273462c7ab44668ec1cf46f08438fba44c52e7c667ced905bd040765d4b0b7aead72a27dcd0501b74721d653c1106a5077cf6ea0f32830a1068a4088cd0a17f987b18c2d9c188b971f18c4ed68726598899907467c1caeb858d822eea60051a99ad905375c1ef2680ec8c5ce0aaea219ee5afa5fc5447ea30a299c4662dd9417788bb1f0460ca0294fac9d7c4edaffe6e62213fb529269700355a2682e65a9eb526c306f61c61927236508fbb23f0ad346eff0d5a711be3444fbcae325b6008c425b58c36ce392bbe00d142889d2e8d652c350ba01583760bc70890a55edc52a2ebf8c60e1bfb05387dd77042f1114594b628a9bc29cc829cd527970ef65871917094a1df8c46c870a7cb1c4561c98e91c5a5a68c18fb6873b38a45896d792189498e0ef9c5148255b3c545951f33736206043e6d92727f555a8ae651a26cebb5f4402562521555f3aeb7469be47142d010342bf252404244dba87d46a8c7f984524e7b34c153f40402d559c93736dbce1ee5e7cb58ff67fb7a7de86d790d234c544300b1bd076fd1662a6afa580cf9c83a6472f7a27a36d5e64f2cfc83ce778c88309998c835f7ca8757e7e57c0036c1240753c44c0734a7868413d9de2dbd4aeb0721f8ebc14fa291ea2549265014aadeeb491a321cbf05d8c3c31804149396b52d77d621e24c89a8b1c629d827ba1aaf4bd9696f6fe595edf15ffae016c19f986d6d55022fd1c96c1bccd31a0e48b96f3a51b93dcef737128088713092ac15a05d78d77de34dc9501edfe3a53e7801a039717c42f8cb5b9d40173252a633c31c34240e7fb6ea8c7865d73811a1e03fd3b1d67def1ab73f9212afacddae40076db20301fe1d049ed021c097648622183645b806265052cad83ce319365c1b84e6f6754fee4c90af3b0db3c175c70a05b1b1b6a68541801e1418d671a5de8ece387a1df895b2aed7d1a26df352d9473ceab3e281f80a8f228257c0e47b28c68951b31e9406eb44368f7c4198fa94c6920603aa6c12908e1074a3bedcaf6c492f641cc00604c86f0c37749281d5c063a8fa55dca889316b6d242ffc8a0bdc6f677e719d2133fecd78031ebef3b262d08caffd3c862bd902da0d04f88a608c492a8a54a5ea30cced680600a881f0921972ab78d3a5280ee123ca93ac380653dca50b48462a8cb36b224c4736d64ab751f6a8eb270a45ee639a91c5992b08b25bd320cd00a467b5e181de5388a988f720a1acf503ebc28f7543fb109fcf9a298b015880f8f76534838a5fdb0a72405975135d1076bf76f74d4803cc2ec906c591db67e26c2474ab7ca3839185f1e6574cec37463269c86800cb0011e213a2316f897371dd1c42fe98ecd7fc7f02c8cbd0144e7ac3ac387f504177e107ad1a1518499235ec17fa11c342710b3b1dc7f0e98b90cb146928b71a5ddd463c071d3d846f7ff92a50c294182dae3ce6016ffa4c4c3c9c313ec5efeab07f226d4709a21c8b46c030d3f46d7eb5dcab4b92c90b8a39180be3522ce19ff4335463b77e5a8a2448f2a46dce4449834f8094f36a4a2d169e70d87a4a6b2d695e882ff9272985e0603da02ed8276b68240a658d842c9effa5c66e5c351e3aee31edb1a6f8cb7fc3fc90af3c5367f127dd1cd154843203eb07e3aeaffd5a38d328fa9572bb79cdde3abde985a5ad65833f866c7e84d7a41d8e3e411f8c9478829f967e1b20da9ccf2ad905a57451555058709aa6496238ec6a0ca949f35f2a00a1eb3fc70680cad6335ae5065ce75e52484bbc5ac2d6e17a88bb8e8f027ea9323a5a2c507d7a857abe0f74054c47b686a2aac7915cad4ccb8a2a6b8e271b81a0a38547b032e9e0f6153b157d347bddee3c7d18b7c725878f4f54aecd11eccf02fb64ee3149f129ee713ce6413d7540ffbac231fa7afd111ad5337830578437dacafc7d13b6b2e0c584398ad14214b2063a5d87af1ad13f371b33e6495ef7bc02463a301c37340ac8683b344eae72ba3a7becee0df7ede8aa96dcbf2d3290f225885dedd85835446f826bedcf2b6460867d5c3bc22e11771cac23dc06b323e9082e7f643af854d6f4370bab2eaf23086e3e37a62fea3806e87375e0ab3aecd47f3067d461149f332d6440826562d83061f93999707966e5024b5e6b11c0c9ccb6a81ebf14a15f8bad8b9f495c944467b438663ac08f1090888429f1ce64dcc07b6fbcbf8af70e318e0837b8277247fe2bb006cbc2f7b237b70c2322ad430a1a9b3c50760c55a3bb156dd7fee2f495a622ef4358367f53ba9f0a3edf56883fbf684cc4049d28fc08a5db03a267c606f1f21493a078806be711420920200282a86cb899e4ce12414f07d4a23a6a25f80544171c3b7dbe325d3222e8f8ccb0ab8b8e4d8af04d0fe167bc049158ea53a194ce2a6e64219616feedccd95d71d4fb82669bce47e12ff8ba0aa8864af592a684aa57faab423e0ca91c4cd684e3a381b8d9b8622093ce4bb27ba9fc8d6464562a8382ded7c7caa720c4c30838cd65b7639871d1eb8d4d9977126d7a924b34b4b2096db638c30178b929c78e0ba349586d50d004d0b86c7d25f0d0768dab15a3a614adfe4704ec3a762413931eb347ba65fbd3c4c4377460c5ff5c21ec7795164f502ee858794e4d93111aa733fde9b37da4226bd500391a76a1b4a9ce7b8180beb7033aa635ed3bed5c7327dde492e46f25c59330ff9fa47dcad7af68b71df6556cbe38ac5396ad7bd651fc647ad7534a31c7ce89e044b1a8f6ea073fdb508e4f3d78355e66e1eb7a49daba7ef4b69ea911c3b0417565488a29a470ca03c20a44d41ac82d84513dba5add2666714ace0804d2a1cacf087186bc0380631105ff21090defd16195b9768cbf6862aa0ebaecb4823e05e0b8be277ac23b2ea1f02b814ba32adb4ba09b12a7cbc5c2f57857c62a8b528265635420757582ffb129954076f65b96a3c07f84f833eb8c7688f216b5b248c88e9f1f23c93f1a9d797463a76dd5a19a0c54358d0dd5d42d55045cfef49b9e7541f0f99cd19693f699146a1f50c385aa5c68e3807dc498879f625d0580bbd089574fc41abf713b878f8fc5b4b5a07f10e1602958b7471e5881263121e20a620dee21188151bf34baea87c138fa1d262c281e006e7d12dd7c93e2f0cffc5533af3016acd01fb792decaea29c854b7d13e0673ce0f842bbe640d0b83648db92b53ffeabe16a963e2fccbbdf25bc42364b718cd0c6efd22fa117116655b31ed6d56490b086d0352ef9c000fb3a0fc21c88a15c06ea00bcd3b99310307f585430ac76168a23f8a1db581e7e2a00d67b616cc1680ce9f94c4f94472fd8d0f21c8138a1b5e9ef43db2274f1f80c7d4af5d0b50f7a45953ea318b7663b1c375519472f279be9e45ec0d20bef1a319527350333d18f2e11bf360650cb9fce02ad1ea92c245c69136e7e83feec3d275eb413efc06d81e5d1eff0cba1c6740232766c6bc55a2aeaf507426d5767b1403831e9c7ee6c8e0381a47a9db06f5102f17a8e847483649020459e1c9d468cb06966910d656201ff3bb9276b84ff29da05068afffb546441b46794f8d86634ae33e21306c92328e099954cffac705c3ce37d8aa758a5db359da4d63c31bd0db0c5f0fc3f048f7684b71c7ff0dc73b5c14e1cc57a449b87dc0c510667f1716150dfb3576e1c749326ab354ff02b41993bee0bd8761fbe903dcb0b1a711f9ca86a4cbe42cab2f28aee47c3d0cb112a15cd8d666a494bdc3cf6651d6ef5c4be2e81e9c14c704a42334639674405e91a0db8d4a980b0a68ab6c3cee03ac0f94f925997dfe61d81fbcda0056ccd10eb7c4b9a64bd5f2d7af6f9222e4721992dc2337a3e2fec8da99d39753c0a3a3223cf3e425dea32391c3a9d47737184d452e19e7809b11cebf889ffd0b5c5f9e25f2eb309f7f35ad1da9bfca2cce314485269e095361f8e9e00106b2dac0a5441068a562253b8029d34970a0cd5d8ea88cc383ecaa060d57d889ed36b9358a2c43be91d98e703dbfed4e74f8d80c19b60cdcf2ea536c335f7a4cfa3a20120d0c09391b4a15f83a2811c6cd485ac962b4600a7297b9757276065d2760ed1ec9c8ae9e1e4998ce93bf5103d73291c51de5220cd8be6aa04abf6d99a3a10733abc7daa9fa015d752faf328d26b55ea80b60d4f85a5cd25d53f7509954bb6fa1d97fcdd9646811973254e31c47ebcadc4a18f16ef1839583210830ab3079737e86fd4eaa9e899a3c71f2674c9e6fa9c2622c96a3c17c41e250e0d160f04032eae3b02be5674aec881fa2484aa2d030c5c6dc1304314bab78ef8fc83d0432e9951873b561b6c4488724ee318e7ec4643d07e069bee6fb3d5f23d0483eb8a952899aa6ba788cb6ed906d19f71fa5162473e7bcfce5d3e77522eb81e1945e81ac5b9299b87530a4722a87901b9438fbdb4778e0456f96a1bc7f8a44ab07fe17a186489161736cb7506d165c269494328e8e1aca7fd115c521bd2ce8c5933f6d176792e077125334bb7cfedeacf1e6eaef1f52158cc64d9c0e7f6e9da351217c65ee7c1e1d973051fb2fe5910ec5cb7a6ab6d2001c11bddc5b8314d129d088355fa5223aaac87e68b095e9205ec7399bd465cb0c255247ad0a0ca3f265c66decfc9b75a287f794d522a6203e3b1d3d6afb32fd9a17cdf45d3251211f43ef028a97b23f92e1e2e1cc4dec84b5d488d729c964799a4a0ba17a86d64af2a8c297e2b4987e4db652632672c26ba3d0125a94991210431aa40b349c7e0f075fed053650c9fea0e2c74b2498cf289c2d51194bb4e47904988e41c8a291ea8710dc8d86759a1c9996af2b63cd3b85b4836932eaa4abd4a9a337b5811b0a759516ca7d708120987370e547c8a6cc09fe600e6a6650a5985c619b6c5fc0741f2eca9b82cee7114da9f32bd3e7fc2f8167742814710e52f79b1fa74df1928136c9628396bb5859ede42764a7091a55dcf31025391f0afa20c7276db794a0149c82df79710532f03f441dcacd8cafdb6531db2a1f45e375e779d5a1c4713f363b631c70c6c9e883bffa3e18c4f936169f7578417a205a04f6356cef7987e49e942e67f9bd1820e6bab4a8e83b5d8578a061af2e38b2ffa0520cf26da1e06c0cf053918a0b91c8fb15749fbe57893ae664dec11f80f94f28e02f6c9b983564a07ab959f0638ad9533033a53979d2afdfaa427c2793d10e33f7074d47f44f210ba19231b5c86f07e363181b6a792d60104f9afee2b2f3444143d94495b10e6382fb1c6636244cdb6f44ae35db7ef58486eefa9218208b159c6c95ca31742c511c435b12c836a4591bcbd9ef434d7d058a9f1b38e74efcdf8f5d0778e6acbdd206d953c66dad10697701d3f5b5dff8a151c90f33121f0b630b1a86aa927f2b54edf90fbe2592cf9339723d0b8b66834e53c69f675054c30855b87657b9283bb5ddcdce15216f492a6e6e20156559c4e4fc12ff0b61119759647ee18fa227c969e407a14847a5380341141998e62d21136f113f0fda85e15a8232ba13a484c5cfb149d1f4212771394458516e440ae992f4be1ad193317c6c157327b7873ca133ccee9cd2b4d9440e88684c176481c1dec3dc9a3edae93e4fe7484e985f3ec89287c0faa37918f79011d5a893977ff0484e61ca9fb64edbcce07bed87d548353b849fd2a4534a80fb1e3ee41dadbf1e33261bd50861bc0933451112ec653178626cad4f4b18f43bd255962e35f00b108f633930954d1915461711dc50ccfe5d1d320042ae16ade4fb924862cb39f7bf63c2b16f37d73e8d7c699ae5b0ac42cc8e59b662c5048d4db7c635bf327ed7dd3969114d17af81b6a90508fa246df5723941ef4c84dcb821a7993a0a8e12756166d4ce52723e9592dc438b337a3e26d0b2a48acf46f7027700e8f81d464f84bf696d9de733589c8639171f47c6569fe1eee15768bccd44ff3dd373f6182cc5e2c938adffadaf02c4f59d078cbd71682394c02cb38a055519b2989c852810341fce7adca776850f3a5eb74d700173e40e9ae90c476cee1f494141765ecfd13598608c6b2641f885ac4c0c35884ea210a4cfa62360a6b67d1e792253e8db223121008786ad98b4a39a19edaad94cf586144f669e1942cb8ab0676051b9fe034b8d8fdb335c4384cfc5a12e148ba247164a5e7a0c90961a8615d1918064d51806b8589c686b4f1b801835e382ac23fec34c4ff560716c299a0ea88ee43718f6e91197c48cad7e5268ada3f64d1b0d9a5bf20368ed52e25f9d88680a3490222c3fe8e8cba48a813405aa6be169495552dd160e435a15b3f93f86fbd3c4542546c0bd7d8db2f980df60ec86c696091c0943e31c8b96502428d6145394e3f1692cf766e05c3461f17d2e7c2b2b17d441b0f5af15044a74019cdae9a98560ffb7babf1f5d2809b8f3baca86b917e901f6b45424df96775da5888badb91ac2514fe51485e1442eaa7e1df4b830bde4135d1e4ff0450436981731b50669fbcfb0c5399c826cc298110808396759ac6ae6fc2c5b6b67539998ade9b0062fead5f8c28bc6c9910fe26280417619fab0bcf13712868c7e57bc7336f447a84a4a073c7e917790887a52d76f60602b3dcdb20b22eee4b784357809ad73d61848b9f05d20150a7a9d18f40e9ed200f80d0c4c2fc73e6dac74f233955f981b356ad030410a284bfd9a586638353f8a4762e4615e40ad8e9b74c8b5bbf32ab1159127a2ee227589c897747e30bea4f3e83f6203d02e3e8b181e82293f7e78d5b9d9e7f317a1cc25f925bba36931aea82563dd5c7148d9f0ebb1efee147b800a3aeed42baeee4064f555ff77f0c294da13d0fe42212ce1a5d4f0af2c86302b814a0e7270717716b7671b24cd95ec3951369267a8e6303bea8230959106af6b0bf05d659273261f8b978edc50c05183a5afec7f43b697c2936c16a9d0fc88e5cfc1baf455f68615a9caac4c9ceb05c5c7117b449ed0ceeb6acb77fddcd7226fc163144cc94fc2ab89a518e4ad087c1a0a15fdd6a1d3252508f95e2cc8061691d8865c7af744239e713dc446a15da842b084548d29013481ed41d8cfe22d58c083c11089c39f30727e8e282b3818b2c1888834743fcc69214846039fead93f9306f6f2044abb882f87f5af8eac8c0942f5c28260d1e445f566d8aecbd42db4b1bf775b696ae64571f5723b973c73df3b6a9d9f69485d0ee03f1ae06051d4618179151af5dc25eb96b78e89ed2db3298e8b065b2ef79bb7d1f5edcb8c9e389c79deac594f033c01e1e8594acda4f59f842d77578c47edb010c54ca5a9559f0976b547a5614d2cbbbc35b8f4590d2bc13d05f7d5c30503222c5684423656cffe96effa52e899624a1243111f3113998bd57069eca51d7f44ef90c98f2804e2022750c830f2f2cc6849a870e3a67d1607703c56a6ea0354c12ad4e8aa2b900404fb7f284bdc8c7e3f65f303f75fbecd60a896cdb54d218984e131418e946048b577b8dc32e68503e755c50db88231c2caa421c3673f7818fcf6dda66a8b378ce8731a7ae064f5d8a33a6306569e6f0b008c77c9ee4173dadfd732637119b78193295341818dbb700d98a1f6ff7a0184cecb2b1953abbf7b19db28805aed471e0a9281b8b08850a6f13de03e938a1a809e16ddc49a6e9a18ba4f68ed83cd317a1e79a6579383830a4678e9a5edaecac32cf5a99a88f14411628afe240187dd656055d0e3d70d29ce95e4a66ee997e22640c6df9fa57d741273049c6af87298fa44885167528b4e0fe94eb2ead33d9c8615637c4f39142ca3681eaa80de9f19349feabf16d10a1d442014b03677ebf4f743a2edb212a81ee4aac9623e74272235283a855d111c22e5a618dac847f9efd4bc81ef764dbaa763f6a21ffa5436b617989c1c28fd0c8fcce679382360f440094e24497e98fa456ed54523d4f9897b5d04c22049f640764897f4850e2f5f8dabdd3cf7f41b39382b7fd798fa96daa4d1d4bc05df5c5e783241849da45b30126e41ba37dbb129d556958ffa86dbf7419140b4aa423f5948280bc2d8089b2844b24d4baa26b99eedd18d7e8b5221188b9cb7405fe8694f6329d930fd73c359338830dc814fe501f236e564799e9eac32960e7a0b15b882f55a9e4e5be44e670cb01ed23393da09ad0bce5f4be74d61e087e0a524fd32f89d4a85a4cf555826dd5ac5a02c20cf9001ae3f740fcb8e08ba59bb173b45bef40554345688fe038c373722aac1cc2d6abe457a14116118654375346bfd22964a0f610d855cb6eaa413394175e3fb53eb965583a1bc49e71a817b174127c5ba0be62eb7a2ea8cdf8fcb1b388b3fb4982fb3958177c63358bec88042d365990fded193fd34059c268f68f9056579ad1c437cc2c9889344ae3e9edc80505109acc59905234fbedcfc987d222a62d9613ae6d862c568718f7fc6400fabc4f886dcd121da142e24ac74ce1d11c938a69e89a85464bf3bb12c8cc84bff874506dd4cb6fea853a18fc65b53cb230a0127864a525473c5d0588c6d910c48c7c5fbdca92d02fbf043da5f2deaff8daffc098ebe5814d8e04a794abcb35d8b30b5c03c63630a5f1baa21a26b35e14c12254c25413bcf303d84afc3c8996336c3077ef2eef269c7e75c22f36176f0c307a6c24816e1a88e6783f2014f11055af738f028d904b60466e3e75433ab5f7e1413536c5bf9bd73305fb998ca8cfa661f78c76dbbea254ee21dc70394cf76cce36b38307b3eba6ca3184334d36d771c0ed26da877bd4fbab17f3c843c3c8282ec4b65653e69495ddd509a964aefd6b853b340a6ab8d2ce2fb4ae8348f6a82864d97dd4a45a848e546309726c8bee7188005d2606a089a13be31174864a92642971d354a9f2eef69363c3117dc61d2fa87f1f6f35f21924cbdbd39ad368a414419544ffa634e920523d1f53763e72ce69b69d7233950ae10e98175d678d95d9b2ed2d5ef8bb3af8d7303ee547e8ec56e4d02ecab1357851db40cd4f45e247814f5b556dd028a375a96aaf69f927f3fbd4ee181e35ad45033c81531a1bb0129b3ba7fc6094f606e2947a8fb6e760fd3eb907f2693e4fc1d4bb78673af1e3fe7cc34c87ce95b0b0cd06241c65b8e5cc9a9009f04428f3ae29291a0e4a4dcc594c36767c2dead46088ce850231c7458f17e79e730edceb46d7088488b2a16dac06c79af39106be9581279473cb3247f7c0e4006f7991b2a1bd9e20122b523cd7959473b93fe84f992cd54b012229f0d87e261cf1b860ac4bbb6286d434292fcc33f186b5bba2112861e81e1aad0beff20b80b93c971088e3723b56c99adc2e0b081cdb58c97a633cd97cb01ee9ff09a71e259d067dca7d094b35edd3225256d87a34dc32816dcdc274fe926fb5df7503824adfc6842bddf65846b917075f937c9be26038788f59ea10bb258f646530df4a1d7d0b3f8531c6e34fc7be6e0081197b80d91b144bd82100e7a3c5036799f5511acb0e1698cc3195027893d408e20152ab14790fc8a86ad1dcd882996da01a4e823abfba9928c96c86be7c9c976276a92672a6bcc4d6a4781199565ccd45c12f1c0601d30d046c4488f85fd04b1eda024815227b27c2795bfd9bd122444a7e6e6edfc35a16ee7f68e5f09d4da07351d4d9473233f2706b5460e25faaa8982ec4c4958ffcea4d6422073685507600091cef6576e8bb363d9609393ba7413b2bc30ef9d8eefb5d38b8c5b41ed7f76252e8de1a53d2065d6a253a5931cdf0acb81e1d629365f0ccfe32cfcab3b0abc73dfc84dc9c87ce4d6e474206557df1ca700e936a5fb41eb30a97e7d90c10468452ba4bdd0635381b4ce10677a87bb04851e0bc62d656857c5fef29e0bec53169ad2af153a17cb85cc0409dd64694f4fee395dca9cf83670da80bb5256c76a70f792faa54a614b77cc33a5137a96dcae458289e97b4903a0a584cdc6f75188653e5679d4606b90fc0c26700b9a72d4257357d6154f54eae4d6a513bc29711c43182e65ae1e4787667a66668187aaed3aafc20990e5f4b0a0d194a6cc670a308c44cad1df587e738ebdb2201b89cbd6f3d73db58545c76afdf9c92e349112aa6f3f07cb7f2ee4d99d4b40b25226327e3b6ac7856497ef2ecb93ec5b105cbb4855ada03b71629488f4d1e0373ea701cbe1423f4b594b423407345fbfc72a9e7be9e3ebc9a6f0676d713116ed087af167a8ec7c75baa39926b2b629960538187abf4d5d428b66afe96802587e9cb828351a6cdc5accacf2fb405cba3a1f1bf7627c338e446130d20f70d51bf4348ebb8c241e05f0a2bf02644b58aa75b2f4e18d1fa42689259361c00a756e474db96656de37a1a27131a64a2d3243b2e7401d8bcb6f9d929531deb357ddcb82da368be1558a89f09ea16cc020d80525865f78c5118a73c89b5775738d943f4f65b610c1d997e79a2e416d5009464c94e9bece5fa69b6a908b8959943bb6add1c68b8f10ea0a5b6ad04b0db8059fef42bb80239b44a41ded60b6fb481c062acc10f9365cb64afb81b21b7b570be6f44f4bd6af62953cbe04158e7f54d4771d3f387fe875643843aa3965b9ed6692c52def11f8ba3f03d8b11a9e59dcb92aeb436b2fa43d689b60883aa9c8dd32e6501893ffc361ea39190be59200a3e2cfc22538847afdc843316c448d749b92e76cabc1ca14a6972d5d0d3a15172aa3e38fe9cbc206ffc563da393a450533c136786050d7b231df4aa86538e14b06e41a832799273a7849aff92be14ca81f223a70cab15f475d3bd11286e1bd23ae71740430df489c7286e1832e089965cd5419c2261b220a0cdfaf553710a72be162b9b62384542d55816db2f48b93f7187ec6f0b2dcc4ba2d87ec3bb3a7116ba5686de5b59bdf08bf4ed8a4c92b708713896bd4432f3b7e38d3b1ff7c288b7dc4d56581fd0bec25a5f0f003a7c4c7145f516590c58bf83a64c2badc5dfc436c4ba3192870c4ce67033983d7977be311b2f59e0fc95c6bb31f5612bde868633164ae2eef71c09d071419ec6c36fe2069baaf0629bcca61e8a21e078307bc05e7cba69ef55c1e5e6fa44e8f1aafe0b6ac6e0f884b21b9f21b8516f64ca23b9a2b7579f35f0af889795c31b7e97a9a53412dff0af1305bc96a7919742a9ba6e9a3ae2ad07f075b3185d481a4fb214a33776b791ae4384b6bbeb1b85051371cf72d1a731e75401dca0d5759e054ebefa7c4fc65714f3b8822b85542b02c3cf36db553dcea8326803c5e325e397986016f0b6097b90acc21621acf9ca4d4c461ef762250ba04e1bf00ae79ea29601adb96f858580cbd05918775a2b9501443ecf976d1a59133aded8caa4087dc99c23fde5b60f2687b0264ca35bb903e777f549ea738396b8d34393ad5ca6e19c893c9e29a94fbcb703ef67a8d51b6f0354da655b7e9cb20be88ecd9afe6899cbfdeb9d46acef672b204894cca961c8d8133e7664e17d636176b7c02598e087a4608ab4321638b2141f1befcc98cc359893fdba65fa9703139027db6e3306ed37d39df27f1ec89c116b03cf238e4f6f0e08762fd89100dba8366df4b8363311306cf9011697131ae480a9947cc133d09da2e14cb3d0d8c18265d51912ff79048bcb318b0a3404b7a60ed0f70c3d5dd132e7ad7529c7069b81c60134c484411c476dc68d65fc7b22f9a65ac8149ab6e203712fc64ab5e7fb66d554d3581de61fc045ab9c96f8abbd6a62a8ef5fd50a3782650be070a1ed123da48130b11b79e8f3823b121045afba208a6ba39e7eb8e70bd703eec2f7d3b9582f2e30f2c4e42109071e0a8045cdba647519f7429d5b911782867b075eab59143d668030fc016351fb58739c8c8f584fff62781808f2b85e077a29d3af8baecb487ff6d6dfba5ea7a57e0e044833c8975cc447b067066c7ec280e8c1bb2923e41111415e3c640a90510684d604fd61a5259b3abbc11f7a107d7459b690cb145fa0015c7849410769f0bdd8f63856d584ee558e2703db1622ed4473c2176df06a5385360fa8ba4f5f8f14d179f2d1b607e2fe998c7e1030c13bb7dde0e15ed5d8acac1825f0886cfb4040c8c15a6181542b5ee1555d04c0053c3b54847cfa890741a097896a3e1473c770427474742be3c06f5790ef2662e4c67d9b8eee3da0d0ff2fddaee21b7bbdbd1572f54c5f41f8778081f11e5c245f973f69ddbd5db77eda60cc7706c62cf6652cca27823f6ff28677da88381b3240ab3396ff277e3d0ac29868c1cb5cdfa6377666ffdcad3cbeab0d8e5e02dca0d48572f0570052de73452ddba69448d103088e5f478337b4f442a091f2c048364f0f5796175baaa51f11357f33b6c4ed9b834ad918a518592e368d806426f4d0580ce250be92675acebc95906a81539bc844d6f6e4f8d0893a4cf0c6333a85e789820fe8999974ae53fb61d53ea5093f79889a837b3d0d981bfe517279fc675bc88161d3474976dafe4029d8f6325005a18f3b4390158152219016e51aa545923f5259935424910385312be18f12c96f886b5da77000438312bbb6ddf3712863ce12f3d0d8a83689e0b250a5b659900a61c70971fdee6849809aa85254de3e048371906b1a433a4e7aac209db43825a4ce6aca935efbaa132d2f63af4e6e1879e952da19fd469a6f2015aa7134f52fd3796581ea2ca50b0cba8f002a37ca1f44dbaf1884367433d3a8f15267d76cc67eb024a747ea13ae17c7fe48c3f9d1e277cc24029627c837c4a25349b469304daa67d5db102623ba5709c584f01b18746c0d8a636b9afa4c0629242a45d5b263549a6451bd3be7d8f60e61087f2e391b681b220a0b99e4f343e25550992a052b78ed9d4d1d1fb763e89736a686d0f4f08e3cde722f10156fc97812376dac253c85c617e594a41d18e85903f9ca0929e03ccc621ee0aa7237ce099c9c2eed4efe63e03e14499edc66db7dd17693f8b8a518d0b9b4a0603fb9b3088717f2b0e6cddb17f21ce39a68407cd3ef3273319990f0d28f336e7842f1d09d624fe40eaf26c807a1b03f724500d46cbf2e26ab7e790fc5abc3003647b5cc39052aeb6e0ea9a0336d878468144bf409246d0520e8dcab7f4c49851d103f28cd7fded94b47a0d1405920b0f621ba6635699abb83f96c423da9698b11b11a8e22d60c3c1c5083c821a6ebcab42aad63dab961184a14bb907885180c4aae055aae2f321cfc179b7b161bb993d89066f2683ae9c3f8bfd65d9bd4f1dfd6a19c2e6e01410561683159b87c3cbf4bb93bfac99328353b562641fff8415054e02451d60ae7cff04f86b5ecdb52af1d649498d2b82693bbd6429e66100dddfee790d07b93e88d6878e57454687b909fa079eb089820ebec2f94e06b7bc818cb98c4e29f36d0060f8b05ac583cfb0482f4fbd5315a674ec96fa164f32fa84305fafd8bf8caa6e0a18da7e9c387154700b94b2bf16288ae4c1199acdb6e14da2b4ff6804440a235d957beff6fd45143ae1079fb2a84ac91f6198c0d8d294bf145b88762984a81ade2b346f3c01d060e15ac39e5ccbd50694a4f12eec56230d1cf72512d98086051760c421ca572a8cc81029145d94d260183ff66075a6bcfe198e2d248f5156af95c47ec14810e5362b03a728ccd430c836f20aa6690ab2b9ec6d5252e6ab414e3431675463f49e928b78f0860d5b85796cc6853dd77cf4fda302d96907b04857e1843eca7d46a90dbb1fd05f773acd46c1452a129c588b3f1265ee4eddd9254bcec19c278fffb28a2092cf8869e4029e930ad47bb6c09333f007bac377456562d8c7a8b4d521f7aac37e0489f08e34f3330b1de3846d97121d613539649163c11e81bf146814c45c050b14193984f54694c8d0e9ebcfc1f8e9e04306fdd4aaf591ed79544e11c054529b22f51c526ca5430cf37a7670c1b42f45e302b9efad70a23a1501156b51d4cc322f2bab0a1a36d8410362cc9f4d4797cce69d8501fe3504a56cf3196b40edc9de2c7f82b2de69f326e9dd7518c381fe5adbf57607c3b47f0e66d66f208b4015edd4360531e140470b74aae00fc948dce5eff6dc72979a8a1bcd290d37920dee1211a0a1e63af58f79f7e881da8a0344c41292d051d134867c5676489a1f16513bc8255f6b8a538061a38256693180d319c19810b9156e1741b53a6406a288af899384f22b1714c80699962c0315e75064511a9c133aad954c3108ac4a7bd3e5a6907ac3937d0291bfd3c689cc50f3f138d27dae5b2004b2c892f06696b293c306a2eaf534430a24fc4b1252e0cbe4d52738b780a6390d7ce59877f7cd6b3ef484ae78a0020f94c90f37e91ac3fcdfb7f932ae6b12ece3fd994295040f93035d9c053d8fe5cd99aa97c411233311fa93e57180ed839cbea1933957db9540505a6f1bc50adb44275fcd0b406c837e7c6c12f35abb8639342d7adbf6654dcf7bd66804fac7ffb2f1f2cf6b9f4daa82d0c2d64348a974d6679170cd338ec761e2407abce01c2229880fa6e39f0d6ebef8d98b2bd879b3fd26b2a9de8f931c1219d9d516a1b9772e4c6e7d1430990e3c3c3a65111e52aee5a49160f3bd52d79ffb3582d107190c957577e454cb252a1055d2a088ab446ca0636e0c31ab541337429df3918acd558e3009832967ac5617e8d4fab35ba0e88371c3fb67f3afd107c193ff1bb5481edeef57a4babbe691e1441f31e8fd85b08c31e538130b17b590bc2aaed3039730e726eddecd6519f9111efad6314f245920ad33d2e3714b0424cb24da3553142d3e0a4f19fa02e51a6f9b3b514ded773af37472ae8c070834a21b8cf0dd1bddca04578580949e843e512ad8b5a0d74ad3afa663abee0609ef168600e46674704973ead788fd41f7d9a23180dfdb4e5d612af4c3b992032446fbd1c0a47c0248982359e42cdda38340fa755c19e0d7a62d57b18ecd9509d6c5bf51ce89b5d69197f0dc39cb8b9eb3ee6328ba19d596525f92964c1e1f9adeb0b5f6b3482001c7c88ced8b407f84930ec649ae8f1f622b367294cbbfdde2caf327a981a0c80b7a7554e5dbcb38c735d55e101dcef2e4e067c84358a333437fc6aa2159ec056ace22fa0d25b9649ad567db1ff33c49815d0ac30e4f90093546eb3c68b30cca2a4824f3cdcc99863217e29f25b082dc694c6745aefaee021c1cfe9e7458d586bf90612f0826229028d80cdc321e0bbf0259cb14c1b1994473ec0c65c064e5107806257492a64a9c3c74eb56b1cc76f439a079cce6392b6d80dba6197438851234121e48b20aa5230cb61e3fb7e6f3f75c0a440497a7c61ab0958cc35131935ff1a9817c3728a6f0652bca438e83d47046f88d82b1990ec2b00b77775cfac6ed27fed040948196b8d1fbe14f35cc816508929b07a9386885e670b2328203896a4e833bb9b7290cbb01c51e8ee4fecd466c534081d39c37c4461696e19f7e9be627e60f7fb30c7679387ce845f107593c18b3e08a390f5440292e19df193ff9d768ba26d8f33bb0ac8e84a1b56f7f01037d8cf4a2ba25dd4d94fb9b8163305b611969322c56b39a079607b493ed06a3391a6eb2a28d6d87454217d39cc04fa067f6de63e8a4d2c28881bf216c9503c9221afe6bcaa2e42552e18e95310e4191aa2f417c84d804da9ec54a987f585ad7e01183e8bca24c01a021db7208b8827a0c399bb73a6fe0f1f47b78925ee4905efdfe2514b02306a75335049e5087a2839ee8e167eed71cdb8aae22728e628719677e891ad4d5fb0a9dac0616c88a76194540251a22fef54f0af5a118dd28233f9f2307e663b6cd75395d34e35f1f2f0ac461fd72a44ad7303e2386b5a793938f564a734648849a0942723f873ea979bffb9a8accfc15b5fddb1ee2b20756640bcabc31c91f1580a6f1b9b3a24dacbe3f43bbf0a71343d7801bc105153d1f22bc277f87d591d394ba98de6ea5dcea9f6b809d5e90c1478256b7d108081d9858bc431a5805cff2013e15a820925d585747587e955fb3bbca7940022ea8f77323b5b8b4bb19f08c9febcc4e4dc54620da11d8f7fcfd25e4a938089855eaa9a7ba9dd808fa808824377e7eaab420968009e44a0bb5b993b093043d19bd68dc016f57429a7379850e293938cca5e007cd161e10e4543bf40d5478ce50e62b50bc9b905e7743e39f560bf7a85ae82efc2557d4bf78cc140dc3d20ba48fd5f05de006b907bb6f125aa92881b591684a6e2e62014cba497fe1ad95e68925bd073a88bcb6a7d88e8c9435bd39ea541ec63e1b4d092fb610cb8ca6461eb6038d06d5d07f22fdc2607c99c8d58580c3d13a82a6d8591762010c8b9092f2bc57d0672de75beee6c4fde28b421426dc5f2a8b72216f516d8c3a0b32e1a822067b5a94d733a5cc54e0075bc5ab95f39160a109f53e529f5ace605255ab0d7c468ff6b7b350e61775d757dfe9050d73ef508b27af7c390ee2f6ab7a98dfdf6ef756791b08235d8e535b986a7f13284bd5f241314e1a3ced7f3e91949acbb8387a4463a86133cdcc173d25812415d6884e27f02cc0b99f6a310ad9d2f899f280a48aeabd9d5b5eeba2a1bf11a4aedab497c511c6d2028dfc5e7ab31312abb6edd41787e3493d117e7eba0bc403356d74069cc9d48db649c598a2a0c4b14570b5ec7a457307f8b0f15352209dad9fabe75e3350745ca868f82d5ed0ecfd7ff9bd9e7df9a2c2ce9ac18c7179178efb84fcce5acf02d9e65a8568654aaa61904f420b078401975628a48048507bb4c872d799a9a9e4e13d8a513aff7f1ccf8daacc5d84e57ad57a22c947e41240fd0b87f6ed5c282cd973e895e29e5641fdb645c4214bb821db20645a076ef65bf0e5a04d1bfe39c21cbd667ea3abf60f44c32299df98557b52ad27bcaa2782e91143b9278ff6096d85ec0e135dfaaa7d795693e55dd5648c937b77085a869b64685264c5835f6006d5dc2846eb546bba071658fdab43012bf5466322877ca68d84858bf04796ee10ac1037dab9a62da441c4a1c96ad120a42356230f9d75c58fef8853189d71c96ae5d46290de8d1c8b4d32782332616881bd8e41b5f7c19383c3ec12d7a609a7a2ab0f71b264b513467f4155f63f1c0d00bca37643e6fb69fdb6a1912abc021a07a59486746cf5341423b1a7be2fdc5f2177ce640124852f6add88193502a058c3f69b86aa1dcfdbb16a5c497c521dd25c5c492f50c5d1c0222e3927ba577961fbace8c91d650baaa95de1788d2dc106efae452b7e6e7ad58fde86e72ab81860167ac786dfb763863c60530285956adb3046c42ba88abbb34a367c11f46394c811f890c07d90ae3ea89dade1c84046bafe6dcd5092676daf5a033923f03601d0f8075d70d8156544693e50dfe04c7c223fdd18d6025b38c6a64be7007b3a1ee1783603e7ceee60f7679fbff4c9f47b9b2e428e7e50f4d0b1d3636e0ff8b3b848d53e3f6ce7482960b7364efd863d92bdc81e77b0034d7e6da01a45df9f3fa8787632f80b1c7e2086664f43cfc29321136f5f4bbd9f674ff85bf03281eac4a1e9f34d8c98f0d381424c161df2b63a911d966c66b51417c25ee2eb5483fba769b65604b1d5dfbe1a8a8c5f68f6bf1efd506e3145d22826ad2ed85a7c30e8dfc2f72f1a9e32c5f16238805fc9caccf3402e649f0f80d41ff56831b2e9012503271b120ad70978c96ff3aed7b07e0e1a8c4982b2d904af856732552be3d8b23c5b8d18d294abdddfbbb616a1cf0cf5d67e03ff1ab1421abb5251f62b1908d4c03cd808910f95d35d1d4d2d67117584f558c69bfb15b2c101164eb3086e3a9dc80042837ce0b20100c1184f0efc72b30a47225961d5bbd98bf0119a68ec1c927bf97c7aca8bb9fc82f2791a12ddda09e88539ff14e56810ed247c7612703ffa1abfcb5efd200fb6c9fffabe80b2d181c551088bc4101765716c1f4c3f764542a837357a581f2faa157e5cf271ce8c05ad82b26b7aa4e9753aa99fe0ef749ac9459f389824337073791320114a049e9c47be855b05d804aca66ba40af4d8cc53844b2186d6732a1a2cb4f2cc2af2ef41abcd3684be5e892815b09f607fbd69fa5caf236959cae8040e92d34d50897354599521a1b97ad4f878b8f2c11d2bf8a70a363848bbb46b8af38c22d203ec25dc5fa3cda81185354c277712eefad867d32629abec318845965a53ed51e0a891a76b525bb41dbc517a8b12f693f1f753a948cce09c3f031e0ca98441d6e9237adb49f920b4c7af736927664a2917bb53e64acbe0323c94bbc4841956f17142fdafde85294a617a4f43189ca37744b977d8099946fa961df772c241c65d76e1f1d98bc28fca810becb19268e6f98aa093de29751622ed488dd0e5d9eb2e3c7992288f198f3bd35eb1c375a232f6e1c9dfb107c44f384e6ba978b69627b096cf7edb43709d3f3d730822f86133db83e9bb10ab602a15ac089dbb3b461b16f3c5b91843890d18d893974e7312299c12490386ba27b4d2a02e53509240ed724f582243b675878a073eda224a63f429f346ab172868188dc108fc3dfcbc40f7ed5275737ea9436fa349cc5ce58f807eaa738831960ed20daf33faae5fbc8b63d8f1fa07d42988ff2d3e1066751d0f0fc8cf6ecc7294036c62dfb36fb7fc6f1c012f60e62e3f4df6d19b51d7c6fce2b1edd0953da5d1faaf4fb357818e829556cb7785f902ac640819c6b584e0dd32582db87816c4daf858cbd44300aa318f6b6f99c623f845c0d9b80f034d6b206efcf70a69a7e9b407c9279e0a1da86813e1fa530a605290899d66b1018d56b264d3c0c63367bdb8e30b4e5996aee67f858757fd9be0afcbfe6acf735066df3da5c231fea75900ca350c85440872b4a46a155f21f1523c7813d556e65c84541aaae60bfd33efb5863ed8e75bf5f1c0aef44b6c95da2f939b3a62b058ba5bccd74ed4b15159f5518b2da793333d6e3de2195d459c5d376c39cc24212277c5bcf166d56bfc9f50e03d92f6563085ca906f2745fe49f66e2ec3ef9a67eb6b41fd4c77a15066b57f88acfd63876c691d69bc2ea4c96722ed394852abf7753ca6c010a19259c74fa0b688230c210c1671b77715f3e09990851ac1b014d30a88376461752b39514e78d497599818c2af39af324bbbf32f26153c26134bf906576b7311f82054560bb24aeed7a159fe542d8412b0f4da1f3ad4de02f1463ced26b81fe33354c56dd6b33c66b8e5fd52d80ccc8e5940165b1f65caf5299538c4ad7eec699f4e44e80af42ea66fcaa8c69e13adb3aacfd2fd96ef20e7178b1a3e4662eea170cb87a34ebbbd54dff7c9264b67c87c5ab27743ba53b1022206d5c35750dc046cf3c250b09fcbb6936821ad7e1465e0ba443c100768a2400ba677724b2906ee2b11a7ee06a13384a216cbc9b5783d286b6549f0afad4e7f8f0b315443cb345c2bb0134a4a04dd275cba0c52eb6295c3f07710be59e7ec2b4ac37725bc32159c7639183ff39ec182085617147918809f6727fd5b6811929bc870db8c9491afa9cc0c6826a2458c7aed9ace74a19f2c07b5d78998b179be02c0953f9e50dcda1aa1fcfb74cdb85a5f44a0f31c33076788c36c86dbeca5966282998a61f732699da4c463ba0b56bde307ac2565700ca9624444316d448594e4a0b4a080de0437c5753eeed607cc855074c21885ce62751a8da5cd0066c9d29e023e07b888a6647b7219242779729d398a6142962dd274b89ca7610e47d4efbee32b9a985248cd9f723c912c422d25d38498743fd5d7deed7ded4693d7ab7f7b61a1c169b614d975400340932e806110e55daafbd514fd77e7a7916c6dce8e6ea768544804174edfd1c44c7b5bb37085f8ae5748e87b93aea521d7d9952008fb7d1d5444f6902be0ab938b12480a0ee5f7ede11b22a794e5d543b8c5bafae6ca418bedb00af8235797f387aed144b04c4124e992943708771d080de2a76d8018250939a0a60051da2a9ec317e83b220cd9afc14ae40a86a166acd04d21f74a3de6a3574c386cd03e0933a9e68594847190041d075db4ce052bfc03adff4178bd759d96e3977d43b3096e805dd77606ff4b95d52e679d27a16ee00adae62e8170ac494ee30606d2c10c0f2dec5cf432bb6c3478235186b15887627e1c35f50a3aab58273a978f157e464d41166a01ff83181a01b3930449b0005edcc90d46c8500e5f0c306debf6d1fea5981b13d048ea297048e7b7082b83657386686a6d3de52e07d70b7c240b212e7a39022680614d807e1ae57bbc343aaa6ef4408105cdb423cc97ff745a763ca3c99f5518bc3462f602deb001f3ac514d7f8e20872d21e7e090c23b07cfae2ece19b0f9a8c5e915f4a7709647033ce2c3e0b1e11bb66dedfcd21818f795b8de4949dba5ce79923c84c5c01e1d4e99ae0f0965c586619d230d23747039028b775d2668db972ac95f8ae0a24053e94d521f5ea166f1e8ed77a9c490c0f5d008a5cd9b3bb84eb5acbf151c7eeb212fd385f65b097166628d04c1c60e49ae0a74693df2e63e182cde6a93b4f2059d807608e5f999d4a74e73d31f8ded10196fc1c1f7c83a085adccd0de03f9e2299bfe8ab8b620ecbc5d694f3659679c0ce5377d761c7e726d83cc240b6fe97f0020b1c11b4408da965e1cfb4656f5675e907ea456dfb023f03c5cab2f7582a5a0d09330404e70f3e48484b9e1cb749b9b955af41e24f01c06ce01c789d5eef99b1c1623000e3375dd9c9f5ece3ecb56c82b4fa11dbeeeb4a07f8db2eba3f1f38ad421035a3495bd6dad6b652847d94a85b6ae8df6fa488c136a2b47f850d12c35c44efb2a7d12350fcd7e06d7bce8b3ae353309cf70d31101f4a876adcd4a3c08013091926f85c388bb0094b042457900f118312eb23410609c10e0c845802d48cb1fe2bc1e812b65078317286919e02a576bc14bb853668db09480bee99bc89c4cc81f7f2b47a7e89f0f638d978debfb88d04f3cf619ba08dc4b0ff2e187cc36620198b9256d9742b0208843b604666391b0f3fa319ce6d522f42555475dfdf786578bd88c92cdd03fbccbdfe3f35420034f42b4d90fed9ce202f131af7410e12a8fda60af2860686a1b037a51c3e3849b07b797cd42c44a2cbee983a281e824fd7f2125a4e4c7d3d3cf5bf2f8a4b95c20209a71a64025906d169a3600f4c8df80bccaca4bd96e8a8c62b14c685dc51f4f007e8a674ef67805604e8ec0beb36d43b482b4ab4898407690bb5fc11f0774b72d11548361b769183b29b90b035aa75e1ade321eac87378f12d0ef035c5a026a83429248101085de741ff76805f00040135c905350a22bfbff3fdf67e53f3f50eb4b2ea3b091efc8c10cb9a669fab98b6c9b818f086cb09fb0b3446fd73216a3d6604244f6de7bef2da59429bc081d099f08c337564d94e82d124f3be78dc470a13215a659c59cbbc1f2fb355ae2f4360ac2e45692d0169a62eb9c56364d2a9974cbcbab80403128bf2dc72888d4dad335dd9c73bb4b31878a39e7dc8e51cce19873ce5fbc2c6777276ee397b393132b81b112d8d4e57dabd465d9bd21cbd0bd808f874aab9885abdeef56566db7b2b2ea7a5815e7be81cab49f524a0d021bc1405508947233bcea77a887b977e54f79156740767261de1c3f4ff37149bbb7dcf34f09536fca39e79cf90fcb6b027e3dfc8fe2efa297d16ba7bc52e94d8a0769cc5881e146401246921a0f7ee83f2c749d011febfe6954766f9ee61f1cabcd5f453b9381b28906f9385a77b2950e7d7651ada344db44b1a087a260d01f513f9f2683e814744d9bcc97674e479498012ae57b9037346ce0ec49a3c54f11a8a94342bc84e901442e88dcd7192183f073ec30b11405140d42e1a21286d0af94df58062289a15328cf983c297dda9cf274b1e3e5080f0ef85cfab505b629f3b6a3501244727c164982fa530904205b3a983427502302eea21aa075d1ecc62a2f8a07ea4f91525400e8a328b4ca07b9881334f3791178e4650c06452d452d401545ff2e4ef4087d9203ed71c3e70941c9750c45aff28c3085032881e0faf62892d2610a183649fec09192255f1a126d42245a051521040ed0f5055327276591dede1f3d892ab94fe84e97224c0a197ac4d7c1924991f4a065c044d3445f28344c149abe1a495bb8d065896633bf882a51344fa1f077bea099929cb78326fa4c720089ce89fe1a3d089a95746876fb3e7a08edb804279a1f092345af2645f3222f2eb4c9525c9e436d60de180293c7ceadfde1e7824bd10d96f8c021060a7d487b510ea25ed0428cfe925476b222da00fdb82f994d18f4f5e47c64a8a411a28cf4efa1e456649125477a28e159b406be91019411142c521ae561f113bde0010a439fee4a56f421e4e80b4284e5501408dd008431fc4cf4e55c100dc142bb248a22896280e245f31e23f4f934880e008d1394c7901d9dfcc7033851bc426f26f488ee1b18a029021d8267cf10337712ddbd210cc232c90d0c5eee13127d137d6a14cd3872922868d7cfbd9e235cd0dfcb547edf7ebbb2756f566d67cc134f5321502ae65d8a4bed4781eab20498c4e743044867ea20d2212cf200ea86163b53889cc900d012278ea220a0ab5c22443a57ca5a1c41bfefe9408a56d882aa31d296fb7c803e203c71fae2b16caae6bdb371f57a6b4c1045392467e73770ee1f97a0cb6398780b077bb5e9a12acc7bbfb749db7e98baaba4bdedcadd2443b75123d9597431ada28b6eb1091d8c6dd4d08ce8a8c7288f4cca3c46a83cc6c35899c708c7303151a5eaaf73a6a6be06d7ad0aa90e48e1aeaaaa5099f5e6f1af8b6d1936e2f4d7395350c68e53a1f2c6ebb676825ed004eb046bac76cefbba6e1937a0b1ba83ef9b1e633eb0328f39f29ea66544592fe7dd80b3ebf6b23df7758536c2d025b2dab57218c7f036c25c0fb34e9fc1181f77c19be5b2dadb745ddbb58b69755d5be2dbc5dfcdb4514caf89101b5eadbffb5ea153fc3a0c5dfcb930233211d7f430ffda271a387f69892754b71fc54ad8c5baed3074b1ed2ecc5a293d4ca1876560e5c789a9b9498ea237e4ae0a3392fdd32d0787e0e20cf1cb8d60286e75de53db568a65599665d9766d3534231931e6d77f4c19eec3741fb662e0f5d7d75fd77df8eb8fb5aa6d5015dbac53573bdcdbe01aa43aa04d59e1ca0aa94cb46ca73a00aab3c2b5433db1ac50090765d8885735f88fe5d4572761f693f5e861ee4cfd67a787b9bb59d5ad661ac1b693d25eaf5d953d8f66dbac97f3b85098f1a0ec9bfc0556724348943f43766eb631c77141b277a78bcb6e8ec32392786f3d5ee50cace46e7bf1eefc4def71372dd47a5c882eeabc3604b835b3fb5ea28b4a3c3ddc5dc87ed3458d441735223ddc3df3d8f37beefedbbdc5032b5fcf6d4f55d7755db5d65a6b61951eae420dd56d880cf9d19387d7065666bc7f6a5266bcb50b1e7007a5c2eccdf162b675b390f7eeb66a7f55b7ddad9c34d56c2a84dfb07b0b0bf8387fe65cdfbd55cf6ab85fe9224f4b5321f08a28a5e6cc25c5da5397b3fd2daeaadad7becad8f1ee69c7781566b761091a2c18586915eb2b0f6acfdcd5fa0dbae757d5fe9a585b3b5015a641b76b0d79d7bcb3ed0a02dcf6b5ea63b815025b37b0128eb5e64a96555355edcf735f5f9f5ebcb78c35de3d4d378be8f1f0f21e6f90dc08757286dcac949a2eb6d0bf673ddb78a17fcf82b29c36e69713e7a7d03f4e1797c438c6dba5faf76ce8c32a188f6ddf69e8e284feddc536a67844398b2e02fbf7cc65f974710ca71ed5bf9fa8236e63a6abd2567109379805e961ee172c0433ddde90f7bf04bea7faf71c2557d1c5d5155675a9a092aabf6e50497ca5de5e1594f154c134620c0b739c1ee65798e12804f3980947a90e1f8f461b3a45f63141a8845f2825a4a1876a0ccc514e3dcae98b1e3a093397a0ae42d761b6f7dc897ebe4ea83c0a951f0797d04309415d450f7516bd4177d8aaad8353ec6dacb2ba722504d5182aa8c6ef5470f97a710cb6b7addee3c56e87b1ddce421b5d27b73f3f6caa28a1bb5d842e4ee86e2fb18d16badb536ce385eef6067411aabbbabb4a18d895400a5dd92b74e590aa2b897155571e63b743052f042d047393bd410bd9427411aa1fab84ca23914aa8240e2b0895c34e41a8ec40a050098c122a6129a19295ea4a388e928aeabfa384caa83e15cc721e4bf709c1bc440f759710cc48a482bf1e151cc650c11ceb376d64a137e86ea6879aa9a94705d9184a0f757f62fb5350c9c241e5e33905956f480924c64a2d8415e6257a58054916f246a59f08bd1f84db38ddc6ad5935a1a317d4348973bfa0a6c9076d9a360d5c1ba78dd3c6690bb6705a382d9cc75373bc6d1d38f7b60e5c001d5809ffbe5832302f808b89588db1f6d0d2617f30b0aa5b49d18173ea23dd696f7f61fcd7056edb56eb586b3d4cf9dad7d78717f30978cc6fb0597f71230737460f79efc4384d5341294ea475298fdba3c1450f79163de4ffff99cb979753420f391dacac8a3990773b447ef292dc44e8a55dd3b269e3b469da353d3bde8f8342e3df2990296ff7d27f617e6362a49d8fe037763ee0fdf76deafe84632d6c6add35e77ca3793fe71b31b43086db3f56395f59beba7cb76bde5de9b2c2189b73cef7d64a13b9ebce27d83d7daedd461a7c1936e25428c3860c609c85dad5c1186a4f53b11d6315da88b932a8d4b9a3793fe7bc956cdf69dbdfc456f2e67302ddd59ef2a00c601c4328c346dc761d94018c55e17397c831bbe35628c346bc0a63f4acaa42193b8ef1fde3d76acafcfa3ffc0bfed8fb06f5deefab5ffdaf2aa44aa0ed6e0c2aaeb086ee545a618ddd43e0d0790caa7bc6b17f6c0db6f10edd3d77adbb664ac1761e6cabc0ed99e537dce08e1063bbb7c136b73cb6fb8e1063bcefdf8b63f7dc7fc1b65f77eb636e5f836dd0ddb3b00dc7ee6ddfd1c75c2174f756d8e6d6c7defe4c0b6ce8c6b1fb8a14bab741b7ec96c7d8ee06db7684186bbb5b1e73fbab836fe74c5409f0fef615bb6761056e5f55fcd82baca057d0760d077fb36acf63bf2db08cef8b55610c2a3574a75283c32974cf4c5409f0aefb8afd636f664aa1b59ae3fd81d1c26ea30d1b16e8bebb05b9f3ee761b6d6e7d2c5da1f6b45b20b4b1a3b742b73e6681da59e12ab440cd3d15eefedd02352fb90e7e1638ecfd89817567b751f7d7cd8db7b971e18e311ddc9177f036372d3242e4be830bb568190cfcb878b092fa88a697f8e6bbb32ea4d8c9101c9bce6160377701a53448e4e36e5548143ea31e74d8b91e79f6fe5d5925c43fd7834c8f2f6adeef41139da8f6feff2fcab3ca2d44b991248a95bb499449b17257d163ca9d65bbad3117ae5a8f168427566a4451b152dbe1e5edc5bb6b3a55ada2e2c7c90719b48982684ca99bd8c54a5d254eacd45cf4173ab1528f59c7941a4e2ede587679f890c1216737274d11e1a18995596f4f43759bf62188f3315e62658e8b77967323a76e6fbd0c65122bb35bbc95d90797fdb6f6ca776324ae53be9ef773fc415914cfb9edcd5da023deddea4a78ccd03cc7e32e6e8a7f8ec7a0385703ad4801457448a092be74b133a66fbcf9900344c8ca8f4350c6b4a23937bb391e94549eae39ff3811fe418195bf38f79f14708e8720ad3f53d8447237a82c5192244e0a902845e686b031034987063cf034a25f12b8775213beb63c0dbcd43d2233b61e8ad74474f19aa8cee96c043d447566de289233b6b26afc733ce6f07879fa8b77908df9f3977a29ce5f8af7a7113fdc08d5550dfee2f7b79a66bd3f6dda9d5df3affdd3201cbffb55331389391e6462cd44a280fcc3efef37a5ec33154048d0d3a550f14611577d9eae81141e8e4fb782458a067451aa8ae8058c7f8ec79378c73fc78349ac04c6828cbc7578fc70f1f06873db587ad53c6a15257213097aa37972cc7125cdbd38e0de265e0c5da973d22242e266b023c80b66c78e57cca52e793d16d12174650f123a774a1b37ca99b70d98f7822c3ea0e848a247c71037900e371748df6b44521a46ee0586f2f4690185f04279f316e7ee11e3fee8a0ed23a5d0122f45e4da3078dddaa2af103d48772e062310fac3a60e519c570335ee9d0fdc362e6f172a21704026033a397cb86272e478ed546a0739ba842848a011f0b81c80e0480e4d19b7afcb9bc8ca3ba5499323717000a9844307df5e194873146930c84d8f9b47c78dc4e6d561a64df4e5111657ca13178b062fa1a890974a94470b89cf6514298edd9f42ef103e47eab8716e5e1f68de35615c365a9e4479db94fc2162e90277c81c14ea1e99d44a6ad40a12e18e9f3276a4c0797ba4f93106ba658429853678f5bcb961fa7ae0e8c3f132a1e42ec1eb73c8092037cf9d778e9c406b0c9169f73c70ab5401c3a41dc1884b84ef87ab86afadcdb3b4c1a3172ed18b45d0983c7473dc2f7321c071f1e2bab9f25a71d23242e2eeb814e44d7269477be9d29abc408bf008bd4af6b88de8ceb4e173c6f502e67d02b75982c02d14574ec94ba4c8cbc15e0f97ca5e8ed691a5d60fa457cb22974b21974f9fb7889d0ce2b493d6bc7465de2d5e166169f1a0b887945829f2bab1d4c3cd6229472b82a5770e92eb64d106855e11fab83cecb47d71ded6bc7eca1cf2d2ea6179df407107299954e4c553a9870b572987abc4526b07a9fdb3a8834283fab81fd879f7c441b2a64899378b17571116770e0a25256da4222d214a3d5e1028e53064a9bd83d467915ba7d01ba60f0f3bae993866d6bc5fcac8f1e20ac1f27a00e58a123b45de38bd1e7ef472b8462cb95b20bd4b16bd1814baeb53c88e5d1c286beacae4f0f29ec1e2a6815249c9db4191966f520f2d937244b1e452820467517ba8d01eccf6010166ed5892e3269973d19c791189a9c205909517fa2416f446d25bac64bb9c241facd0aaeb2e080b8aeeff2ad59e73cef907ebc92c9bf70fce6c865916867f3fae2ad338a79bbfc17a98fb050fffb8f0a78752b0aaaa733ceae24fd3746bdd97f62b022b7f3f0ca4f6c419895d6fb4ca9a5b75201e891bb28e64a5b55c242c14d8addf0fe0748aab07f3272e93481ac44aabf651a420c4a32e3efb04a68a5f2e2f2f4f51ac043a7af3fe30e5d1314d885f2e8f8c223a202b2622cfcbdab2eb3a85893502af793d5e152806ccd3a1a6404a3f5e05040219fd36a441bf2aa0cb42baf3833417af2d10d88790cac44ae26b97a6ebbaaeac2b07e6f1cb411263a5896943e2e0fd417a735f483d5a770ccc14bfdc23be970cecc62ff728efdd01a77781601516db756f2ae2e3c460bde689c3302b04bad1476660f8d197560a665df6519578851f4189d75eb5aeeb706ba6323f4471bf1cc90a7eb4245655a22af748c887b1f00f8a8f33fa4f59e2d40f98aaaa3accaaaac84eac0a30a6aa42e5aa762f554d215555555508a77c6b20f12755e508d213586de12a965d5d0fe0347e39478dda468762570447825e49626efc728ef0b88995433abd497c1191454aee388fd4f2491def18451def78d7811485c02ae213f5de81502486558426e69ca71c08c72fe76883154fba1d65c0eaad76ae724742524717ac299e5eac24d225a2938ab3d44fbd5184de903bbb55390c3bedb94b1df5307b1003e2287ee1c06bfc72788a62a554d51591c50b21cea313fb948aef7ef400480c0f4d148ce7e52705efdf784e62e5b08a568155786f4c3fa058bfeb93f0de496addbb42516daaeff2fc58a0b02f82d5f8e5eeea008dc2bbb8a7bb2d4f7754d8bb27e9dd12f52e83f56e08976be42850ac24fe04bd71fcbde049b012e650f1cb3502a1919a58198a96086708d0a8479cbd3de40632b204d132e50d98bc3d1276126031dc5220490ebbbdab1f7418b408b9b1e7c1d0ded3990586dcc531f0fcfc5892d437c383bd33707e10a8b3e407cb1adf549b246ce0fcfff3c9b19466840a74f6870a2302fdffd57f4ea5d8e6d30947e971a275f5e1282b709413388a02386aed5df43366dfd087bd27cdd09c4bb4ee44eb4fb4dea14613d944c228eb48b4feac41064721101522aa031c85e5c2457fb1442b434b736ee81f3cf461375b26fb070f7d89f622491641565616047b76ff3d0c868203437981a1a07c0f737bd8f32c99d6bbebe209e3055ab3f7e75932cd451246d913a9f621f8e1c3f387a1cc602811ffdd89f66423ebdd89d697c9b49e84f184a1faff339bc901f41a643d698636019a59673efb734d2df97c22b7044f3e9ccdac6793e94c4b43aa39b5cc924d240ca7d6b3c9746a25cbd0d29c271e7e3af634e493f9ecc85e23ed59966c369965fdc95c7667926956b6643beb4ba613ad895c53639675b3a419da04cce61a5633e964839facfeff7b98beb14ca6d140aa690888674b34144814046029335a1631ebcc7b399f4de49a99d740d440d641f40888109cb191c1c14ecc0dc31acf35b5640b275ad6191b59100feae257b5f5f9f30ff9d726d92c7dcaeb3be574426eca2c1737fe7ee31756cdb229df39ff94ce7afd39011e22ffda217d27357fce394dbdf4ab3fe7bc75899cd7ac73deea0074d679d5130490b39ad7d799296b6b551dba3d73adb990cc73d66e8ea473fb69e67a277356ea9c35ab80a6d259ab5ce7453a6755e704f254ce5bb36bd2bd36e509394b6077de20ebacea9cf56e9135775b2ffdcb20d89c5aed0f79d59a6f6d57ebbcc1a99829e05b2f899d423f7f2d25f33de4a9cefbd30c32a1fcfa6118fefc99679d1b655673c859a75aef9cbbb25666f34f6bad5500640d5a739d893beba5c066c84c5015f4919c6a0a99e79d5fa7d0ddcdfc359afadd45feb13fb826bf181bbdb39af99a99f246a2351bb6f37167ad79d7bf7698d39c5722dfc240ccda55591d96b5eeb3d5dc6abe27c842cd96f3c6caedab33bb662da62fe80bdac2fefdd929ab5a67260e6fae2968adb39af9596eadf29bea9ce62663ce39672a6d627d5b9dc9d8dfaa730299cd79ebcc73896c4183e92afdea55a779679df5ab579e77ba7336e69d87b9cdbf9c73877c41bb7bcd2ccf3ae7b09cd5095a2a739d539ec1f49bb7be90f7d69a6b9ec1b4ce1558ae73ce61d98276d79d39cb73cec69e811c580f9b8034efdc660ecc6d1bf6424075210bc0b3d6aa5e931996407c4be4acb3ce3963fdfa6bffc08d8ce740a3ef0e384144e740d0901d0348421d283048d0af08f279154eea245520e9bc009cc06d2080201381049c28f15220bdc44e38b900a904b28a08e604a805866cc2621cc464650cbab938285f2abae8e3a0d8f93ecb85a50b582eaae82b415398579dc88180265777185cf41f863e05f54da2227817e990ef3cc7ff7e16c3ff4ff1ff153cfc3e9366cc32b4251b536e12fee70372320703ff7902abff2ce3f76697c6d0cc0c5963c330a9c674b670a2656d1892b1395b98256394256194653d97c89c2ba519808a15260a3021a245012654b468200e40ff00a26f182e936959676c6433d2d626f87f6207d19d6c4bb467fbffb6875937c40ea23f9748b52c3367336bc97c816c9a69d578917c229b4fa75659d28ceb9976a6a5c6b64c554c6ae1e76e4ede92911fa89f369314801b3e4a52ba9b92a38033aeac6f459387313b0f589050b4d2c2e68c4b862e32967732d0e344c780e55a0c4029d84049d0e2a1670f93e6193b3c20409265236b14893064d853ba6e508003810b1f39ee87b54327929d004f435a4e128e9776200ddaac0c406420023b51084a797ca81c61b43c323243a3c490ffbf11965a0c818e2c775101763c62a6f99ff1f5f6ef22359fb7b0fe2fb4417f3389fda3e8ff2bddffbbd11d92c0f934d2a07f2446a0ef3426f67947937f0df0ff46f4ff66ffeffe7f0ec0dad79065cee459d2ac8c0c09763416bfbcbab8b688ad910cffed0ff5f9ff49b6e633e94c439e399b59664c35a286c1b63a88de6cb29571e861cda4d38904033b8219c18a605f605e605d605c605b604430b0e3f1683c168f5f47af63d791ebb875241ec18c47a3d158347e19bd8c5d462ee3969168042b1e8bc662b1f855f42a7615b98a5b456211ecebf865fc2a7e7d7d797d757d717d6d7d11bfc0bc8e5e46afa2d797979757971797d79617d10bacebd865ec2a767d757975757571756d7511bbc0b88e5c46ae22d717971757171717d71617910b6cebb865dc2a6e7d6d796d756d716d6d6d11b7c08847a29158247e11bd885d442ee216914844fbffb58739dc3f0da2b399a5c6b6d47aaa9d259bccb2f6bf818779024f8696d6649221ffffc2ff5bf8ffaaffa7faff0aff6fe29fbf71fdf31d49b634e404dd45b339c2455f22fb92d95d6c18ae219b33966c6161cf34366752002eba59322d0d59f6ff148053ff3fe15feaffa3fe1fea1ffeff76aff046fe3ff0e16da38739cd966c4cb27ec6ec4f3666673e5b3cd1d2d69cffeff4ff4dfffbfec1437736b3b8b28c595b58cee4b3c6938d590379e2fffb7fcef2ef7f8efbff071ed6d07f67336b2beb2b8b8875fc7292699d6d11895f5b4832322e2e33e3d659118b8996e54c3e91cdb22c1a49b3255a8de6d389f622d9d462be6822cb9afef58dff577b58eb7736b39e6a674fe6b29ba199753564b2f974f6174bb41a69cda4d992ad27613cfb320963466f329bcd645f22bb5972d9647b269bcf65522d99b6a686d69f68c8e6b3bf58a23d9f48b526f3ac23ffbffdffccfefffadf64369b23fe3ffd7f0aff2fe3e1d7fb4f4ed06206b2f9f4f0fbf9ff19ccb4b366720266aff1442b43ae21cb9e7c8ef2ffcc87ffc43b9b595a359ac826195a9a5659d3a9458696468696a6c5b67c8145836d899686b59cc15cc658b26179155b148f34b088595bc7ac2d2de7120d09a32c8dc97c6aadb13d9d6c4d2d32ada41a1386d6ff333dfc58ff2fe1e107fe9b25d3d09067dd997cd620ebfd8cd9974cb427b2ef7ffeff3f1f01efe1610d81be9b2dd998671dabbb88a0d8d5afb820709184f1ec4bb49e444beb4f279b5a0f7b2ed15ad0403343365b349fce166acce61993d3a6da67a0fc07949f5039f4bc468ac253a069fa5b33f08972275b7cea17058b8a01949f6827b855c01cd0d601fec0bef03ed51f4b823daaeeee0074d33850760c548a45b4356e0e1ebd81a0291cad8007fa7b0acf405b60935e3ba45ae99b9b8497c2111cdc07d429e814dc584f5a2cf0a90f474a007b5c3d6ca7ed818d02dd01d8d2525d350b74bf6a057ef56eedcc7ffcca259112b03aa056505d55f993fa49b5c076c2eac0be8443adb0b9e048dd40075072b5de62000b3cece7a43ef1bcb13600788adf94aa570656aa15452aa129abef4ef96fefadf7bad9ddba557caf0aac504e29dca7555df35eb917d7e299a5b0a9a22d86140bb4294bf449e554ac081c3c100e618bfe7d7c87f6e8a943f7c60ddb0b1543848c180bf1c1c85cde35d2d2003bb12b040f2080a26f4e5d08188210911c11fb2481f2d0698346cc162a5a59198cb03d83389b911ce1f9b9533707e6860512b078a0010450144002c385a90970656e6ce9c0820a5a58a8622e3134050224430ddac73749120b08a6263ce569c3260d1a31613c0802e482161238c00002284cd099c3060433484af4e143a7cd1c9a3353a2f4d091c3115e9e3b68cec075698326cd4c8c7862c213c150a0377365c87cb132e447d2ac85042c2060c0c4880e611b9e98e8cc79b38192216d4933090c304162448717c1109d3970d89421f3c5032b4480b4456080890f1dc28cfcfb44300408ce1b367365c8786085c810203fda08b588804508adac3d4b270e706afa5325c4478f0618203ef9d1a3060d2d6ddfe6d397524bba128b855fd1563495cca5b7383167bd589b80dd2760d055996aadb02964209fca13da2828a80d73a75f13cc54e147e1ad729fda955557adaa69baf3ab6dee0071a06bbbb6bc892daeedb6f05b1145216487aacb1ef9cf29f39fda82cfd84cfb89ebc99104aa36e9b5e5574c168e1d40dd057e66fcaa29aabda8520578563da8817e3821e22987e62e3fb1611274041c1ce8a2390d7bc22016d5bcc2c65acb4110290177a0aa8a21459b04a7311dbb80280f288596819fd44f6a002424acb14e5712d4c3b32dc00511786d37531a835fe023caf226d54276ea8a1e7ad272c0d3c6ea1d69d26f2af6b482f103921070c111950e5d126e069505e7b082e1f8c0490138ae04990013db98ca4e6020077dd9ce94e460e272ca0b54ed0e2b8562d45dc154976dda4613056c0b2e0949507735c1a4822d41358284db96f8a930f3f001748a5f155d352c8a4975df114209a6405db6c405b21ed074c369561350ddb483ca01c4d8cbd66a604ba8ee4a8149446bc551b4535255192a4ce0c01270800032445d366bed62ea329a48b1fef85a210ddbc5f6c73574b1b55d5dae951ec08f6239a5dac17402b165cb36d8880e40d69dd01aa30040f17ab1436ec5add42b500e4d5c444a407aa1b5e2554e5bdb020e689656de671b8bef9402a10445ce30975b3aa08be3b2e54a140c6e5440c319e32c59e64202160f34b080022a529c30a044d8b16b986100013a6733d777677728048801841528ac4d409043654a022342845990f07b553938325aaa508902c549930d14186ad0ca529264858abebd3cb207ee1aa169c17c221204ed0c440777ad324488b1dda3c74a9530b0e294d4ebb26b159598302c926608a030c0048911615e5b1ba09e9a983807402ee00125e8cbcc960eaedc606001631128c5ebd0415a00c48762bbaa1eec20d3e58991223d2860c2010741104001a283865fb6b42b693d8ed71b6944fc901e940aca7c741e8da7bdf3abd375341d0da73dd85b740caecc5619036b21ad62a2a0a7b4842cf5149542e9a70cf326fda6ae6e5956af6baa79de3913f0ffee5780836e3e8d0c89e2041cdc4232d3ce5ad44033d352635b12fb07101df94c4b9a259f4e75c4f05301fcfff3e18ec03b9b59cb66f2f944ae69359fce082070375cb9c36105bd02f7caa5a0f7b07ed529e8bdf7feff1b347cd761c40ea23793309e4ca257f7d09d4fb41768cc65763e8c81c3ffbf40237bbef56737ac3f91dd2c19a30c6d895c4b2e99285cf42513edb986405696053616b8bcd932f94476a7052166cb246c4182131dc6f3c53299d6cf983dd9649e3d9bc8a7b3275f2c914dd8c2f0d3c8904f36350b4cdfc3cc9264bd861932d94c4306a0c96c3647cc60369bcc313906fceb3b14ffba904ed345dd0528ffc97eb26811cb4cd9ddb261abd83d78e85bc3eea177023ac072c50ab183e812fe733c4c01c93b9b596c4eb4e68b13dc699111344b328166ec11b1237140a10f912f85a8ac78d87ceabaa63658e2634cecb5e380bc58a2258188be20575b0a9aa021b19de50f96d5ee011571800403a0424747d55ecb32ec7bc83ae46d90da0a1c82955872b2e4b7c16f775002471121d190ad0d99ef4e87e10e9ec240dbd5de567b60017217466c49853cbda8cc04274e50892202b6d3749694d8d813858a080f8674982a7beaa86051c88b113f5a09a12660fc1cc1400cabd35124131e80444150452039fa4c4e9fa3c40e0b1a52e4f409b73d48538f84312138bd25c60f1a152b129d99f3454f90c42649130a12262cb2e43d294ad478f501f33140943c08100926663468d2a2d092dc26030e5f58543ad2c4cb5bcee2e64bc59c1b23117cf09189ec806007110894cca969cb33beac30e4a4c61fe00c1b99c5a39606055f2a88a1e399c79ea841d120c9dd0c03d2b2063eb9915985b51f8acc32139100a05d4da13ad4c0ff23b9082c501a936121c98ad793a30d0ba40296649f7f335c00258f3edc68a922e29f302a7bb255276749838777638280860c53498423bc5eed4e08c72858124161fcab086201d71c0a14b158fb3fc61d9943c19b558297ff0bd1106034f4dedab6ffad85c6a2b92c64bf3e4488eaa4c07d739688edf579a92366aa0142149257797d1af88093d33253b8c9b1ebb3004e04d68cc853854586faca2ef100f328c7c369f2d367e28a959506684e2276eafab20cb180e53810d04195d327a54108426ce828b891458e8f12085c065020b9b515068e2f10062c9e1e1a270931bef0c97d2062ad48902a4ae864e1b3a267a5051db767056f51f8824c096486c91811c60459c2f70c446986d5da060bccbcf13d6004850e1f43c86450c0075f8837707d2ebcd21055b4f10dc083ac459a66c3801e36f85c3060b454b9d2071df3bc740789905e11406b1c6548bb74070a96b306985af0916476894c9f2c6956159049696371a94991184ce69419e08d91159774ccfd11a1a1821d10c89cb814a3cd4d5da010d884e820e2528a2ec71796387c7501e2e1d2d79d978b648a431611bc2e5135d941078423688ee45d5dfa3c4f1d7106c011d6c66a6f04214614318f25902050b517470dfc560c80a5058c527b1ee0f000552382307318f8ed19e9408e8921623454a8f5f13d0a02910ba864aa99505a164346194a040000000002f316003028100a88048224cb812053f61e14000868c834503626114d0581280a82200642100661000060000680100660280830a6d20b1e40e5463e7904fd5aa929c8d05be7c07b02bff9833264ab8c1cd7afcc95bda7434395c3c0fbf27ef18012a03bcf4efa285f0d604cf11f982b8deacd2797c8a76a9fff81929a17b267d3c1d4da7b60dca9f9d72b3710234a2bfb11b471985dda5bde1c9dd68da73297f21284e05febe56570fef59dcba3708fb0fdf967b325f33b711a586bd9b46adde6ad074fd30c3187d42f2d166edff823e6ab1b177b8b1c768add890736cfdd4de4a6fe8c587a163faa9e44f27b829a62ade8532f104b81e9695b871e4bcfcdb77ea6940f06aca8b5281783e2c76695ee600141f3dd0ee323e18019beaadf52907e2446fc557526061f1e603517fe2c1ebb87debf91d7456150a5ab312d0d0d17d16fd81fd8c5713a3f390ef60900b036a47b8b27305a7f77012fee99a601df3d261ba7bfb1d72cf30e85789ace4df4d370fb73bcb54bdda0582c5d973f635a5bf6055a9125bd99f55277d368e67b0d6e83bb877e20fb68c15b430d5a2fb56259a7d627101000a7326b175df7ff63585bc6151a91e975f315e78a65eea2164fa37bbfb1d72be9167d91f45cf88fd8d14dd765bff1f1ca0ddc174b915222de0f4ebed414ecfb133aa05940deaa4c435b9169464c61983df519f06e34c16e1f00751a11ea17b0e5f3747bf4f57bf43ce347f7822c06d217d7fd1ba78cefcff1dc341744cbe885d376d527ef5fb739b9b1b2c35eadf478f88cf6e48997ed0a39bc63d99fa18147914dd9f4f45cde32c1de8e9fffe036d344d7d8946ff18962afe7dfd274f82b51eba352335bcaaa9b73e48b0d1cf93b690c48985f73bfac56f2efe6a4fa721ccdb31106684e6ef1510b7d0c358bf14abc41f48f4ba8ea07ffb02ad2afd5187e4221ff1bdafa755d6cf36128f0af7f98c04b5fead6ffc87cfa4fce4b557c0427d9996c4bcfb853cfb53f5337e315a9cf3189e253e9ccc434da3961eb288ebfb6596a861c7f598ab252f5bafacb528e785fe206b19ef48c2ec3c6424bc396d5e4b0d6c44de0c863fdcacddd9e88c802f2b29922d5f79fb877bf47bd0efe853cf03acc5968cabdeebfd0bbfe8b7a28d0ff41c1fb59605a4f14fed8af804ba15e375e51bd16886d2c1a3d3b39770d12130de7903fdaa53cb87bc4f0c4ab9aebfd3fff9b59673620e539cac60f55f97df849bf6ea3e961e620c59bf761841a7f2f7608b940543d0eae2d0e2e1d3b7896e3b67bacf22658ea01ad336bb8183548112b08b2b08952fb7f604834cfddc3cd9ffdf804f96f3145f613c94dd4e769dadcb2fce29003d00ff4a2e5630326b3f3daf56fe0c907006debd5c26d74b5be45629645f56fb9bcdb8be92147939ececb9ba7555239ae54d2718c72e8412ddee1d5882a8e0387a98772d43d7b5621778c5f2fd56364c555ca3d1bc17dff3e6d0d3b2c25f99a1f135e9166f75d24f5e2aaba58a36b5f47b197687e7bcd53a0dc47eda862d0df517ed3eaaad1daea3af942539e054fae318580ba839047e0a9fc3b6736f001d48bf78c69c217439fca48d7ad3cff0fdb76a023ffadb98f331a789bb404eca2a2597e91e4c1564d666d151d3cd45cb1f05542260f2a6c2e8de5952c1cd326547f7820d4760616a9a14e86cd75f5d042d6e19a40ac996257982b997b119ccdedca99bc4b08b35c31be75868355d837668703e6c6162dc15d38ce4dcdc28fa67df33aeb61a751fc9eb4dc10ab6c2fb28138dada0dbe760006bf68a5b8fb4215eb719db1f08b02d0cf86df1ad71a081a5d36b78400570bee3ab77ab09fed3f5c8733d05906db7dcd491e21d322a26772e220205f57c9be48de399469db95b0a614770f8b27839772b781eb7fa0b52e107d9c6c170ea762f6c131bb0bdaa407d527e0ae11165a31db23be78493b69f81361d7f6358099c8f34df6f41dcd8e37ffaa68a5542c04b6966a0584c2faafacb4be5d23cba3dcce35793ebdbfde383dea08fa7f1005a80f4fb66f89aaad57c1e2055983e17d0052f1a74d42331c0278ed5deffae83ffc7081dde3de650330ea44dcd7bb3e1a891589fc5841c030abc5262bed31aa097e3c71908a17d8fc36e854fdfb2dc6880d02f8f8e20bda08c33bf0fc16725025e98a06b868be42505182b3736ec5eba8048e62914b8af39d1fbd3b33da2a8aafc613a6a4ed75fd5aa9b0691b7cde30f0cc6769f23773825e538e9644a8d7fdc33bc39733ea59db21dc42a447f6e8e8155ead21d11af7bf8fd75579c2dec914818e725a8990c18e8d53eae8dd6298cd11772cfb57f22e8c570f36c38e8cea84ed1fc89dfa173f4c90e75ac4fd27a55702d9ec8fae57c654a5a61b78401d10dae10dcae313b3944d7eb0c389b81632d23591c223b3a5139e295f9a404f6530d8cb4f8582c1e338ab7f1b938baf8e8ed51ea8da8b64e791195ff154219f2b91f33f636c63b90c41541faa3c00c710af82bdb1be78153a4111183d8bfcdd7e982736499fbba52f883b6a39aa392812a1b71c21b4577a87a1625c15effe790ea3d659be1e4bb51a0b037564fcb56317828b693502dd807c0ec204694c6c5c43a9fd326d0d43283fd9032d255e60474bbdc50cee79cb64a5bdfba359e29310d57e6751d5f0ea93edf9677f346589e608e9d119b0745d3b0743a4d999c40dab630a1aeb046d0fb45bd2c44ea3e51c4d761000b77d85f4366a9711e3b85748f33267a5faf550958fe3562a55d717296081f20e79275a99cfbb8652c8661330314177b0662b791d48a277686a0e0c9c0b8966f83f489c08658e5aaf3838d8ffbed4ca5916020d8e4dad905ef3070aa07e06b1666316d693b8322c4af3502a3cc8c1f89ae9802fe52e0ef96c184cfc6310d30ac980e378f497c524941c84fcd0ffbf6625f439e812a541767cae3399305b883b6790b70b2b89308a1192eb071cbace6984c60b8f140c4b7a452cc99ff596b8a74bd498b57a8ddee460f515181bddfb37094764440f0d419a6481f16024fd6fe6ebbb8295e4473e6f467f4c01ee083e8ea49e817ae2e974a524fbec74014325bd28041624c84b980241de11c17c8658ed7da66fd5254101c2beabbccfef05e6c39955bdc25f75b8a64c0da3f87257987f2b44430df19e1cdf158e5ba09628aa44de0990a77e2d571a705e5153e16a7c7988cfbf40b884e0f574d4f95fd43003408cbc0ad35166a1654ddc110b430d430a7d60e2c7d3f4a676be101b4f1e7104343e5fb0b3c30c6176fd1d8204eedfc94678c06ae54c9702664d5086dc38870ce7f1d71f5c323a464411e001b43d85ec22f4ae980928eb5f368ca7a0d4766db81a463cd2e2577666129f7d10c4f1391d21f4a6f5e74146a046723f17299122f910788e6070cbe80d56d60e7e2cb446cfc101b2ef321d631616c159e6b0aa945dda677d5c7d28cff86b39c3948f5cac3db0111be7512ea6f43a46f7ebad44c7283fe9c226229cc6cac8fafce1abb10feca8cc9be3454b0585cc9f3f3d8fdad83b98c3317358db36f038056d660c60c848a06fbbc0162fb97e796723ffa6ec4cc50a01eed0de6170325513ddf8094c5a89f5c8f41604eab37924361f1061117ba95287ac1b8b47f0f83e680d6eb490c1577a52949f969ea97079a65b69b1d01ce6c356e90754f2163e272cdc11326b0aa54b04738d9f9f67cef6da196ddf6eb02c3fa175cf6ab942a076682c1da4e91d47b49627bcd4cf0075f0ce019ff0a85771011e16c0c6ac8f8a460f2757a1349714a0b77b9383fc884027eaa9201fdef8b403b867830cfa252517f86265bb90ea838d077bcb12f0f1be36411d1542f08fb4b443af35c9c5ea25d00dd49df0e49b296d42a6a7e8671c7533065f49fa23f83ccb7139d2eb009a50680f3307984cfa9910d5d06a6f10e86720fec894a2b62c5cbaf0a22b199e1b57389f57513896c78a75955ebf886413753308fd176db0521eef100d396ac7e40aca1a492df60229c6744b792ce8c13f93e912e178e45328c78f5ce789614b68ec4aa6497b410fc4df31e50294e510813d6a6d00fc3a808c97fb254c811e3e007b08ce9a6502d567552ff01902f6d08410df18be80586183946780cb1dcc21aad9081da4f1824774eb135d544e88779150137490c7238c51cd8fc41cd556b0e344bbad067a5d531714b4d91ec15db142b86f810c79d52abc8b0a5be8419c1fba029fb66b83fa9cf8c70c3227e15f1ee669f871802cd079f41b079c73400402ab8fb80eaab0463c0185ceb43b41991b61fb0b42db5fa355b5f5d7166c1cc1a78f2f2f4b4134f73007b6adf657048b470f510f8298ef0fc31c62787b128e9c4b24b88a866a2e000d8f1084959107d1b8accc33ee016c45f0367800365aff07fa6758816c5eb2be2233577bc1167e27dfe7cf8970ba576dd94fa17c1a5c48e825350bed1e18cc4881c10ce0982f901c7af88fa7bc422c9e726570eb931a7b749238d51c9a8d7e905dd0d5b2623ec17e66472ab1829356abedc74c15f44476a792e0b83c3186992b907e4d2ab6dcca9b7648fe2f64c31293f820e455f85deeb84562a18ec32ab3a0a536233959f78e0f564abe07113e49c9ee23e21936993fb434b84adc7d4d67dcad40f34f241d0eb1a4fd97abf0f84e4892d56417e20a49c1f733e46dd3332bebfe3875eba7b385d75f4fec7aea4854faeefda09df9d0f64be3d131fdf77782601cc6d4cbf1e89df211baa73157cd091d793a81bbbf5a658cb578bc84c9073016add5dae1c713de09145b7fe0214f929ca11abbb24dce50af18dcfae5591b643185d1b17b523b26d73a76ccb7ac13d53199e80823579d8e264196f7a84426b686da26e8b5d0bf8c090750f8082c55edc9519b0dc7f4c466919b4ad973cb62ee172484a3733cc44dc01ca60382052c8ec87631ce2f455ddf80825cd18f6157f8ce0d945c57559e10ad4c70dc718b5a07483b92319f2bc764f0b961b098db88ba7477565a1e5e54f33c02f91984ee4c0452f238e7d222324bbe542a295b689e0e9d27a09d53d840d362d97c2c02514bb5ba7471023ce7135dcc6d332c8c9a9a1c31b55db0254e1f4839458096c3a15e8080318c87e32881a9b2b729b6f8463c9e022d9298c6d61b8fd310de019dec9886d07742c039c7652f1aee2eb87df813f6f8d17089d46193e68e85966b381280e06104414bc9d408c5c57047ae877801e0743372e76fd9ffb766b22067fff981c4cbc3e9a1c0d57accca511585ce90916167deba91da9c2377ed690fce05e30664b25768db5801b8f5a8b137bfc66af87cc44a20bd59f927b0f634730267230b8e9cc8f0fb1b189e0d73e24f52ea233246732bf105492d2e2f5b5a222bb12725d123170061db7b6e36295336b49ff8ba57e621fc648e1f118724270c3bf871ed83f37a0e6cc22d0dcf769100746745a101b5ea79852fe0baeb2a5a30c849403f732d7457329bf2a136f2bc739b7a11bfb32530f582e1dcba272f7af230b51864adb7e5fe1b217fee815f54f4be605e933ce08011e2a9918ab4222dc2c555be5d54f06f1a27a383c54957a6f4631c29d52753d78ef86da17a4f42f5a5077fee85f501e1d7405f818b3bd740bbee1385fad824b2bb02a7c46047ae826b331ee13e05f8300e61f5dcb69df1cf74d808401c2a3e0d730917e07420e615ad42fc3d6387f08736f967abfba90c7a5186f98795b15c1558012fd7034708f54f0084b3f498406b52c687242e856c90f585c955f49dc09c3c21d9555f15940afb985620a29b2e449f56bfd6a80afccff28110fa3dcf1cea372c388d1a03863318398efd9d39821c3d7211dd67eb093986dd71509ae420088d03667420dc85a6c3d62a21f907b17baf86cc5130cfc3d7ba0c94251a4ce601cab58543fbac8da80090ff546f83c8061db5a8222f4c54d6eb2ac5e49e1f7fe24a07df23b1b47fe24d30cc8b3ed08ece303c2034cf4e5c51e10ea86e5454106bd977060699a0442efbdb282d84c945578296a9481ff5aa9d521f0ae3b28ef2a31d272ea44f7216621c941c95572010ece7914b9dea9d8f4d3592947c2614e18545fe3e90b7c40a1509b562619cc8b00e47b87c16a4d408239d9483678cb79d48b88509d3c224126ed2ad5921a6db66d82d4d65b9c97506abd8db8b328fd39b039b6c3c616ad49c6fe427f11e02475e7a82181da3123a666c8dbf77516661b687d867d8c7411e0330fd11055b4fa278f95e60ea6417ef9fb964c85c3634a224f4531a0a455a59eaacd3fc23f9887feaae8ddf4adbe9088c905aabf170c5339ef1636bbcf6e1c68693fecf1356d743432e8da0135685aeab8185b4910d48413c603ed581f6117b53da9a1dad168b48b65d6b0a44d27d9959f16a357c9a300b04cd6c0165aeb884c352f2fb27c706423dd57fa75ec3a637c9dacf206afe1a5da71a124bfd1aa7b378b105ccb792faa85ba744fd53c43cde9f0010c4a559fd152b2ec0e816029c86d0020bda715212f9031feb9c3e4a201155af8e4dc27860130089786a0ccd909474f8171639d2232e10d1c3f00a815d3e1b4a096b29d8eed74b86494e75a6ff85606709cf95ecb08ec1c2f619f0db576c8f3e3b25efb7410a6907e273fa62bf6d8aabbd7deae3b2fffee18fb6940d0d3fa93e04d684e3210eac286d35520eef47997732e1be70b5591a613e903e4a9797477bd04566deb1c35aaba62fa983759e7ac5b54c984c5e5d288245b0353aaf60ab634576c98f77edaae382370b64bf079b5cb9e2da6f88239f4edc60ca26405c29d9b594c7d249bfab7cc3b53fa183f1920238718302b0a3477e6c12d9153f6b6e6c317a010603a3d5d1991040ac1832b2d1908e0ad74032b38860d76db59fb8218634171b190ba35c8eaa5b10b519520b93121a9879e21a820772abbf20bb3803f8a3fe36c4e24dc5b81883c189606702e6fb372890e1a2a4ab115c970b441c68b9975cf9e0f50c12d3865f21254c1a0a2cd7ebefa955232c1112cf829ec88f803cc955d0dced5a9066e7bb872295eb0918fcf37c7a9ce7ddc04591b57726dbea0ae8a3032acc095798166c300036d3137708f2e839ea73d7da8a6d8dff768b6db82c2215a49d7e01699ba0b63bf8852715293ee8d67130b64b636d8d802f2a09b4df27dacdb4074c0ba15f72f130cca65e23158f7a37d356f6b59ebde652190ad334f7544843e2b17c89839383f3aca3477fb9e5f6cfb497df4056a42b7f40d3b443c6dfd2e98da940cf3bdb3ce2c4a34938b1301f741bfbd29adcbf740386e8250bc72dbfc2ccc1176ba6b27b929a70d1f0691107e44fbb436497deb6e36a46e35d434e63e866d3c57979916165e99d515c299de0471673c5b135cd89117a57dc34707b4e310875903a5461eeb7e9ff3bdb00029b017c62c84cb3cab469b2eb8c35b263adae9add798df1c7e0eefaca41c04003669c5c71447d80ae78269ba13405f3126181131538e6024097cace3a1480b8f2e9c9926b5b82a594655d7ecfaf4cd3c2c7b2f2bffce09b226c9a77ff849ed257edc3a6f0c2c167c8454cd5afe2d906515ff2cf10784b0faa8260a9e7cd01b964842a189786620c15a58bd5f9c1fe77e02859a90ad44a773bff8a333d80ba1cffcc1fd07f058e127955ed2fb04b4e76f11ba7e7a1fc2146889105601aa7ffff37fb5ffcb87ff77ffcdf802f796f08584bef5641b7d471d68050a2558d4c05582905974b97abce6ff94d8c763520732c148a5d5a22a896a91dae996cb114502ed7e3c3671d3094e267c80d32b6aadb68284bcdea37e38fe02ef559155c25379841532947e1fedcfe102d4b9296f9f57fc52fc91fc1a334f6556094266716674abe91ecb5705324544ae1169ac8da8c1f0aff42b104b40af8e9ffec2fe85fe06ff02db9b721784a13af8261a9e86630962ad626fe175ea5a9544151ba364a3feb7ffe497f72bff01fe43788c980617b49a04406196262325c20e9d85b2598960028c9da4e7f92962512ac82a9a460c3ff51a60845b20a1c4b952a609d0a8c4b466d03368989ddffa6bffd3f9a48b6b47f8fe05d32d95b7f8373a96ca6d0283d4e15c44adda80879dad0bdc2b224205b08b04472e6e6e652f124d538915cd355e95ff5dffe97bf21ff0666e95e9df831ff44fd179ea5f255f96dfcd3f42328958ad6f8979a29c1a935e23f215592ac2131f5b9446f375fff066c693a0ca2ade452d8fe709910f8c6be350e3de8767f59da5069f52f6c94ba6ad7effeeffedc9ff707fe6fd0977a6a8b1f9d3f02bfc4aaedff16f8961cabfbd79869620e950140495ee5bca906e9a555a6c2a5cddae5aeb72df878f8017e49ab0c0159b2585bfd0deed298da84ae521faac05cca5bfed7992e2ed4afe0d7fa95ff44fd080ea5db3afd71d3f465463f02bc84b6ce3fe61fd57ffc8f68329082291c4b2956f05b499b02844fa26c03e2c596180377c9519de92fc04a935a088c12ce8afd75fceb7e74ffb99ffd3fff8f301948b1152c94bc5205a592abd5a63b33feb969607b91f8e67c6709d025f595f67f034f895bdbf617bca58fedf7371096c6c310402506548150f27a33184a156b937e049752a50af2af81bb44145550965cacf6bffec6bff447fcc7fd079a12c4580f7f0cd4a53336ff8bbfd8bf8049231163070ca57a45c8d44c880a88cbd2123211d1002f4963cc81bd52fa86c02f81d4067f88e692b135ee87dadfc0ac242a1e981c50a706fdd43f27eb8aaf401ae5d284b5799381c69ad5a44f79a5a6c43dd83f7b5dcad9b1317acf8064f27cdacc7a033557ce7e7fd007d63a4a7bccbc205a7181c7ad3ffa3e27c1db5b212e0fcdffb2a4f8dcb3d0516ef1782f410a98cab37866cdd0e66414c2286025669a6c4627a9308ac9053c8b0bdb44b4eb145be66506fb30174d0bd099c11f741342921a0233843499d9b8f729273c86afecbc1c111e864d1c9658ae0ae492172a210cf15a80814629ad39a832e092758af3bb1c4ab1f33b7ff54d0e0893c4d804bdf9a5fab5246c01f863fe4f3828818b437fc1a4646cc3bffe974da38a8d7e04b5d2cc0ac96490c461aa8112898cba42ef846b3ba67011d9eb9d7ccd41f1e9940e4e2c3c05a34dea701e556fd06c8b99899f14f18a9e3fa89a6b7de77afbd31c55b03c24fb4bc2d9aab9baa5e8704699591a1d91890bad709c9373d6c5f546a0fa860f540a67c4fef9e1ed147a8cbb427b75e8a09e0ad98ec5fd1506bf5680b3381c400ae38e73d41414d1cef5d1f70ee1510f908b71cf54d9486fb25dcb27cb8e5d52fbd5574a29d6aec890a7b3339d913a34f320bc3d2c3800dafecf19858cf1ea249143af596a7e8604f619a234b3b05e606210cf9064b928cfd259c1649d0d347bb406761802f4ec6d9fcf2048f566429dcfe0d286f613e84c7448f3536895e64f0353413d663b0cfede59067f350c8556e3f4c7941f181a6b598cd424e86e9e2bcda12389934188b28663f1dc09b7e14144d13fe10e0425c9fcd58070ddb0121caa5e124f0dfa89c9642bcbe95781e96ec27fd84df06d803912ac8f108759281f040483cb7e1c6e9a0c4c2c7238e5a592de74606bad4d0866b304a0c495fc44a1126572b7dd4f9c7c1f8eba836bc64c43b58cf9d0b1069e518c9f6afb02016521669eb697f00e1baba2ed0e8ca4ecc6ea20ce420bf52f3a015053c35c1a93234e16363bc4281f19e1e643e428f3073e24e956f1a037b4bc925d6560f68b9e62974eb4c82c2eb6129e2f1950eac5db4bdbe495c90a7127941b902702a8d3233c62fd05fa949ea8a212d766d00f6c8c5d0a80b2a7634e3cbe7c2a5699b369b6bca47cb981c1ea109bc74c373517f9cc96501676749727a9c803cc2b205df12fd4eb9c4571b6044da46f8f41c6a87af54ff09e92d40dd58bdf05451510899191ffb08bdcabe69c037098cb8029330bf01fba289107ec399d16bff93df91a845c07bdee4afea1f4a4c6824d45e4dac4ee6d8f9c861a6b58c285a65df6a6a60ab831fb038c159261e1aed74cacdd8d11ba0aa525fefec23e5c183b4d5da5d58616d780a57a07a4eb7c3d68b77382f20534441dfba1a053a48e8188ef0f014bb93267d99a6db85f037ac20b00e606556d3ddc91cb46940202be7ee95aa1074d5d82eefae772b3487a53ee66fea994cbdca159708448f785733e21e556c9af3873f12b7ef0cb5c395e6687f0c39b9c7c9018540253632c9316aa5195d8f6ea1404859cfa4c3a54de77c3ae43c50589f8e1a75b8d0b0a2a76166ef5b00e193b6206c678ecc96f4d50bc934cd6e3c9c5a1dd6608b02b70c5b7a74d3560b898964a61c07dec87afc901acc5d716821f5c1c4bdb7daf045eeb53fea647966f9e34d03677294c89cb66e43da655d9ec201c91de31244ab0b6f80ad5f0a628ab5c5892528d1dadc2e93eb6a05c60f092174806a99f79ea9e6a7d25f909da0a5e09f3d056866fade13210712d0a3791862476f1e31069c82e00334ab2c4ae8aaecaef805e1ac09c047d55ace993acff78802942343f1f4a371af17adb1fa8111736b140429635a209e36725f6545154f14adece348b6d89f324fa18c9ff6194bc5fd883adb90ed16eddc51e2d6f9d9e2d03b1ede59de1645740630222d60bf07697444251f033fcda4bed65e9eb12a86c55b53ba05e8972f9cd0a4748ec41c9b830b6032ce9d80618e064683f40214f8eb53b99c4e0085823205a3d54885d317e6084e4fe0bdf01e2ecc8119fb92658d415410dcc4d86df79db6c7952382c0483a3b7a0a8e3383cd2dcb67d49ced2ed2669958c8dd392560a843de143ee3858599a2ea489ab502f1cb9662a8a8f8242d687745c9a79ee08d634aa188ee6ba5db4c7ba0a54cbff2a7dd3aa98d9d5c4162c6e042b7185108de657f5b78687b24bd5e7f6bdbc04d3cd1b929520b0554602b0c4f30de2f3c6f9a3c1f0ced814ad2a0f0b1a4e59afcd8af306121b876e95107310a3923521539100295424b45bca4497fc03ddeda861f4237e06c054ae5df8e7bbfebf09b298e0333bbc3a21b58d017051d85b94c5d1ed2317b7db447c24c0756ddb07e52956b9566e7968ee5456e5d0d678d08f855c4d1d9de77cfc2ddf582f852b1d533fed4694cc17eca1995859c0cae1d9ebaf429263fa87b33a4111538227daab0eb709fd632f11c5ef5a918a6ca130f5fe5b591dcc0d5e6ea9847f447cabcfd51181d0ff176835c65a22f93508d0a1f77d8b932c0df3fe84b5d0a1dce5f00aea9f1dfa0af58c3a0d10018fd130becf90ce90ba6ef6b8dc9a239001d25aeb8f988b9cff8df943fac33e8b2dafad85846eb5e0b5c9f4593e1f92e91de80b300c3847c24939a72e84b78b9e0b893fc601436503b54764f26588fb4b4016fcb92e4028db45045c049b54080cba3d8f4126f224eeeddff971eaadd34f7c6f492b4084ad657044193a244d53f0e3a377ea9bb3333e6afb6c8f1031a57d4c080ceeb2d1d6e2fa892b0120a2ebdd1a4a445c065dee56c1254192b7fc2a90fcd21e87441e5618f1d4fbba2768ccbd3ed6bb26ad0cd8287be3061d106d795665e6e31a1978a3e09c8a5e6e5f97e5248339c249d6aedfef5e8eb7ce966cb854afef3aeb52d5db7f61292e49dcb6da7abebb136a4adc7d1d2a073a0a60caaca1b2c46d77819a4a218cc383327e9a941be74b1549f2e4325566becd97baa79f6373a5e97fc92f9ce803be585498543a20ad91261d575ce07f610fb8fc6a1d6b1f420707185293c1c1fbcab3d986915c17dba2c5c2c1fa40a6c300430c081103744880dae1ac16db9b2b0831b4a834d22ae1278cca28b18773a984ebd44707294c26142934f79e848fcf14b7e87a86edc62aaa8ab3dcd9f2776c3d70cd7f2efee38abc58836bb199a24f94b627190c174a3d33e6c8e64ff00d5f453ee740a16dd6958f1eaf10ccc60bc51a72c54657b27d3aa5ab1e4fcc4404034520ad16264885c7426d07245479eae6734f3fdb58a9d526f87f0b68b746c82a83c5126363a374b3402cdb262edf82df5142383e191d2e5bd552dc4916557de42453e98019984452a1a9a403316bfc6c668b5ddb1d491406bd5251cd7749ac4d73f3446cd6c7c52060d506ed47dc3f8cbd601915ae71149d8151813f4c5881e31863d1c1221ad6c61d834864e67d8204376de9f58d05e18aa0a83ae003cb1e98aa2e269147701c1e83474d82f44f8086980f3e1bc14a2c7a303d9883969b63a1cb816bb4031275ede16ca664d324c33334ff3bc81ccb9c52f4862ec18209754235abd65fc4876ef2b7660c630457f14146da6b380ff1ac3a3856c2f1ff12d8cc175229a7e5d3ea65b70e7de1beb444542181096c020c1239428e249b0413a02189817249a5312f44b8ee69fdcb20c051e069e88ccf7973ab96abf66bebb9b1c434027d624a06bbf203d0b3777a574dfa0b73273095b8f6f9986118703efe4b573d5a80ff48cf46b1427b9bd1f23e4aa4cf9bab38d16a8111800d24ac7edac924b8f4b0c31c88b3648888060839f9858632ac75ee611523d1bf646a0c9240e8c8712b3883550bdc7ab2753f369d8469c117e711538244c3310068dc10f9a6fae166520ed9409e2d01e41fd6736541cb9fa89fb09cef7a20b56f21bf0c4abb740107b215d474f73303b7be652bb02677c587018d450e3f4aa40d40cb0c4a82467257a9c09791d0d302ff7809ea2492ef6f31e8257686510778340ae208e0b16daa12632507fdb07b3dada891aff44d43299ee5d4d03d9201781b90cf060310c833ccc702d1052cdf903e11ab0ecdf851321224d949c8f140578e37f8d51e39dd92b939d03892243a1bb8591506787b94ec682855967000cad0d952dde9d8021970c28a12db8ebe683edef9da10f9decb36ddd8f62a0a3b026fb45da4916759cfaa414980154be6a84772f41374deedf948222f979447d7a3c2bcab6827fc081c184f781f8c6b9a9b93d34044f6c83950823aaf55ab78212d13163f5a2ed7400dcfda7db7699a0f1e728682c9ac200768b4d6a4774eaeb97fe535bcea3d5490756c4ce6c4c00e9283c876a7b320f5400e6c00a95f324bc35ec06db65faf4f13c5fd42d0e37a281aa7e7e041e4ae13d3d97fda10ed17e26c7549e944191a8aca1cc714d922264b9e6f3ed83ed74f008a5f0c962cc9d13d0ac40bdec4f15ace0c0bca71ed2b84728ba4c7c620548436267e8921b0b086d76fc56a68f4da9896c4047e6a62f6d0310db81f2c51a16f1bb4b1c0de1450ff12a667db3f912886d2352665f0485fbc2c78c24d403e033ab1a77ed42eace7a1143bdeaaee8304757ee865669922df69a344bcda3e10a5c2f0f83f13909ff82f9dd546b5acbc027d8118cdb96dc52f4d1918aec806e914c163f3e1b6c2b5e0d75afddd0183a0322dca3da50bc3fabf8319663255e57b3d3a86fcfc1ac6c03f4b4aba8f8300219aabb86cee2820170f327293ad01886e150506740e92a207388edffbb7a0712ec7018946ecd6b2b83458e1e65929a0886c37204b5c04703b804e98eea31bc32bd904472d54a6c5bf18210c52477be2a210ba657c2be744bd14caf6813b7707a03fa1a2e3ba27abce9b4503820c64301b9c87415a6709190017681d06f8bf4c906e864b27aeee416a59b43789e84f1cc49f7cc474e201d61da29a0d38132de04732a2d7c7bcdcfc8975ca2826cf18a5e8cabe2bfe5b1af31e7dd5b2bb216f67eccde786518a66b8e6a482326c40dee2b207b147fb74713a72600e7bbc3b86ad07ced301c8ce2e94f2a8e6f3b893581fc89c6dccf33eb2eb9ff642dec8ed5698df8ceded69f0584a75fa3677ee5652024e320bcdc4db24350b21030ad6dc74da9dfd28d660a83480ccbe68d6c020b2d238c65a89cf52742e0f0a08e2543d02c039b4ecc4d487b125425be220e27e958bcc8a2874d5c0d7dff41ad1f14c4afc624571d20266214cfd052e9588bb1e411038b7da250ac55f4e5aed0af1a082be7de357b99dd2ce85ae7a776d93d84c521206919529934cc052777b83ee7f4f7b657777ef3db2e180f357f181e8c0402d05f21caf24f31e71be98fbdc9f1b8cbfe6178e5b9e8fff62f985dd1706ba73c8f9ccc2213c873c5edcecc6b01b037961ecc2300ba03b873e1e9c63d78d45f8e720f007771e2f2c84dbb7cce7f2f993fd8fc303297afeb2eec7c0b55027bf7010f6e1675d1e07c3bc708431fc2607e5f7bf5f867b3d8c833091502707671e73209087410fc7c010068cd6f5a1eccac03618ee852fdcb97ffffbbf8f63391b94c31706064378f66561be6c1117ade37edb7f6132390cf641359f16f7798cc57d1edef541b545371679807df0b7ed641ef7db76f397611f94151de0f3f1319f8ff72fd807e5302cd479de8e03491cb41c0459fb3d8ed7361feb5a5a223e5a13f082c6284d55e3d026ad45209fe59f3b2312830884ce1d3275eed097ce1ddad25a7b10002dcc90ac7386469d2b044a6b7d8ed02ab4266084560bf9d1b9425e74aed09bce15da3a4788059d23e448e708cdd1394258748e504fe708fdd0394230744e03503aa741071a8e7f9138b1177665d7cd25f301c46ac50680b4fe9a600330add57c3e3e16f4ff05b206b6db9df928534b5b83ecd61c61693ed6d4763b30b698f7c6de60f8725f38c3efd85a3094b9dbdd97cd95e1579ee186ba50e69fe5be50e66f61bd3976d9f0e5e11b7acef6e2e01c6cbbde609ffc7f1bc781213c876f99388ee41b4ff36570dfbf65bc6bd0214c8dd66d199418fcc1a08b0ec13038128261b015829910820dcaa3750836a88a0ec106a1691d820d221182090a41eb10ec4d08b613e413948660827408768118adf505bc102c67c10a16fc09c18ce89c05432c08b5d621582013b40ec13e0864279099d6baf8b76d909d83ecfff1980343f8057b61570e025f37f45cac82371580015482d6fabf652309a4c7ff3866b87fa6637dbf99ecf385c57d1e61656ff099fc7d40375e83d7e637088f55c5fdc9a2b5e66115f0cf5a88e667d41f135aff826f58a3c62ff8fa81b3aae127d5646b9f17d8b13e7f661856b332fb44d17dc8b4f605bbef2c03005d767fa628b023bb3f19149ca1e084fc83b2ec8633078633e2a00fb9cf17d424299302b2cc674eb6c647448e4f95d67a8f05fc7b285aebdc9eadd95ef775c3eeb2c166ab8fe1fe65ac5931f1a0a12da6718881262606e8d0c0135d14128f14f07187090739a8708042256a0d6b038b017accf861458960519532ad8500e61a914874e066c66134d1e95db1258d15395a0b04d94de0954212002f0cf979c1a88760a38570096924ee21e8ad908c12085ce5beeab8e89a80521d23ed560223300252408b1318e090f4a060d18c00283005ae1ac8608b0f2b84b7cf0c4f9bcc12f5d1a91e52720430aa082835193c164da0b0207407146f938b2b25348dba44a2930339dc080228e1c20938af265c809c74d2c20391a900c4a001a4f0700584b536436404d9a17c50c82466064d84ab2a6dd4f058c8729403c31c274bbea91d23407a307cb08183a94e24d614d924568746033cb80604f948aba2db1397250949054d3eb54901079f371e89de381e1128a8711845c2c6ae9365511120d906b5b12f4027ce28ad558ae00330696a2091a9d46197c6039bd7577a00c31f53094ceac2ae714324538888050b1a503c4824e3cf056d133e7c18d0da7062a8f2f2060d200c6b2856ac60135998fa657c88168a38d9a822c48137674220715cc992c944154e8666f74818470f181d4a521093030e01129c01836528819363497bc1c59335a60c11d0652c22b230d4f1a2637eff0f08fbbedbf7679e34adf5240dfba0ec84cdaf8da62a411820219199952156bca6344a130106405a21f8090f4a65114ac0fc20eeb75539a12299c4c1bdb90567395e0284df5f9b12b7c75684c810214180aca9a5fd403beb61c663878e1c3856b231b13019ba2faf5331607471bd20c0c5560b162b4e852a52a0386142ab048911224e9da23a22c1227806c6c55dfe6eeeecfedc1808060606b6e563f84d96395ad80c9ff5668ef60bca61a929ab69ad43f05c2c35bfccc53c17bb334be233276bebb0fc8171f37c243ef21e698fb0478e1c617124c3005a430b0da2d67aa77375dec8e4d689bafdf5c2b292ddf7f1979368ad95e81c9d4a757668ff9784336438fe4cf8f785f2ecb261ebf66439d6cd7deb4e1df9d5bf87fb17ec83329d9e96cb0f3c60c4a883458a38d05a274a0091d61a83d687f40f8e7168ad3768c090d63e1fffa9c1f05afcdb362856838a0244541d502d9213468e752e0639635aff706ba0afba56ecd065bacbff1ec338d680f8ef5fb7cb3fadcca7a989f5f0a90989670efc69decf7f9661b3590e92f9ff06fb77855347ebf9fd6e1180a0b5d6fd82ef0f79114cd15a97adf97c7c2c8236ad232b0b7f6f4df7c232877b3de6f177837571af8f075fd70c8ef7d0b9b3fc63b8f5eb8affc26d9c87adefcb305908f65fd717fee07986c542d70de3e0fcd9e2f84f0ec2716a305918c34af82fe42110066b93dd387cdfe2c29987b01cc23efe6eff0dd611eafcff71b07ff97579e1cbbb171c7f26218c389f8fff18465b16aef091b61609cfc274ac8569eb5ad89a96235cc5c23535203d42ddfb8170b8c667790ec2610bbfdcebcbe1fbd5e2deb05027cfee1b7479bc202f2ee6f1fcc2ddbb32db0bfb388f17ca5f6e5bf87b1eff1fdc43d9150b753c1e2cfb78102612f278bcd04918f29993855ea1178d9fdb5303f21e9f8dd708c33034200cc3ef73813fb8c32f8fc70b435d0bf3646c531db70c9f2f08ecf53fc7cd6ecc81327e70d7b1c1deecb2c990012603e7b9c70bff570b7541d88db7e1ebf61f03bf6fe1173e93d53852d3456bad7bf12204f3eece4b6e7f1caa5992e68534711a56eb100c9e355587064669ad759f7d7bf38a2eae36d849d8c50506a6d3855e06846108f7deb8e6f8cbaf0b0656a575c68406c8b4d6bd6eb89321a381e08d83ec4edef97c7c37bfdfed8c9032219cf171a64c6b6d464cce4c93288d50c8e18882b70c5cd05a6378c3260234107e0aa15a6baa02c218f101460b9a3f5a6b2a2e9d5474c500d088a3b5ae325b0bc0c4e50517515a6babac2f8b3c9159e00f23ad750606c68ca2fa00ccd40dad75d5a550083479810c09a8d61a0033bc00caf40e29a1f4f56546879e83401e10064ed0ff8567ef7ae1d831800003bd187ed9e6377cfb6fe815feb84c254db6fe08756e9bccd7e697bf60b00fca4dcaac91e1e332e419f641b599fb80bfbf7681055aeb403d74328f2787330f43ffba6d08cf21129eacc633e2baf17e0c8fe9d4c299f778baefe15ff8dd5efe43ddda9b5d6018dadafb7d335cd00586fde092df5bdbe9782d1cfe1cba1ffcc125f16fe33fb73c9d777d3c48a8fbbe30eee5aefc737f31dcc61f28f31e0c9479bc597e5dcec643f9bff1770be1f08df9f7c130307c61d7c3bd196e8e7bb3fbf6e7b70c2d2c9475b1ecc6bc2d43c203038b3fcf881bffe012790e79bcdeef3a5312ed6dcc15facf16ff5ff87b72d8eb3313f707cf72b0ff98c72e07865d619c0f0672c96e0cfcc1bd8bab854399c70bfdeff5a01cb66e0c875e3cef865eaffb35fbdc201bfb087565bdf9f7e6b62cd4f1bccb0bbdfbfd1bf7721ef49ae5e0eff5a1853a2f9987311cb6af3c07813c9fef7bff65ce7ead3dc2d27084bc2cd4b9401ef2c47863b20e9ec3b898bbf1997b1d8e5027bbf2ffc17d0ec22e304c880f9d0be4619bcce7b6854339eef3d0b940ae16eac842dd07c6c508df78acf3ffcb619ccfc7e1306ce158d75d1f1b04ae6661637fe6fd857b5a18f2d2760ef2421e7e7776e13e77dd42ff651808f7c3b8dff6bfec44e7ae98d1b92b5e74eeca139dbb22ebdc959fce5de13a770588ce5d29d3b92b3574eeca97d63a805c860e1ac4871158595412d0392a51748e4aac73545a9da32244e7a898e91c1553e7a870e91c15113a47c54ae7a678d2b92995ae387400a1250593ce49f940e7a46ca0735202e99c9407744eca023a27458bce4971d3392944744e4a013a2745d43afe71dc0c3ef3bfd7f94f9bdd9f6bf6d9b82cff5f0cc7f1f7053ddc436bfd466b8dc18dd69a0a02ad35551bad35151632adb50f18f4585e6021a1b59bbbf24278c5030cb4d632fcc657eee4aeb0d19ac70bbdefbbadecfefcff3ef8ccfb601dfebf40decf048e71cc5f96c3808c8dbdc1be2f16c7f95e1f2e77e32f10d9bf411c56805656d890a10a0a5a8e756caf1bcf729cef0d721f5076c91e70604d862a3a3450d943c5926c83461cfbfbfb834bbe1cf2d1070cce2187e35f84cfbe4f46e67db08eb897f780e135fec9d4d85e97fbf703e1d6b72ccd4cec8ad61a86ce4d79604a161d82b1b08f0dcf7ca8ed08c92933b41cebe20ff4fdde2efe3b369dff4b425d5b0cbf85f0fcc2b292109ec3f8cb5a6b35693490ff1e98d51c45d467e2ca330f2ef9e167e5d07fad75036834ec836a695438a20c817d506bbd0019adb506fd99b8f2ae85e118d8fe78eeb1b90a8cd1bb188ee30fcf3b607097b63310adb518306afdbbeddaf87f0303dbf9df7f10fffd1b84c5daf817a2b526a1b5e66aa14768ddeadc133ebf6de7e31d0ea3bd3c39b52e755bb7bf7c7c07c79fc9ee855fb8f9e784a7f39e87fe87be3027a9930e2fff8a7f9346b92688b4d6211cff35a1a0c999d0461882ad50b496d16484d640d6c0c0e41776e5f7cf701fac27731d6060dd8dfffbd980725b877d6271b3ebe3730cf7805b6bebbf37a6b5aeaaa252d35a43915df9bf3f47a89f68cd3231d3baf6c761c87f41368cf37d37577e7ffbc9c6da64bea6f6d3789cf9efe1b1a05a1c042f9030f8ac4de66d325ff321f770675fb087ff387c3e3e06c7bfc80b9f8d91bd7087d7cae035d9ff7fd63f50edfff859ff40b5b70c0ed03aa673703f9dcc7b6e211f5bf3f9f8189f3959972c7f9f8f39db8fe3cff5f9ccc9421ec6f077e399c7935daf637bddaef1b7719f58d7af37bb31cce6e35c616f4dc7d3c183756e87659987b2ace3f1d87eccc6c6c3df5b434b4d35359d1bbe610bff36fe8373db3908b33c7c83df36d90d435dcc7dfdfb306e8e3f108e81210b1ca929cb2c52534d2df47fe62f9b2b7f1f44f7f5babc9743084ba693f9cc7d4fe63afc7f83dffb60ae5fd823d4c1f19f2ef44199b321984c40d89bddb71f9fe5f0bff0ffc1720b7fb18533fcc2c162a1ee3371e5afd70d3f5bcc7d21e74c5c390c02a3b5af1b7ed97d0b5f980de3eff6dff0c770fbe3df9bdf6028bb210f5b37e4fd1facc60b756465dde5610cbf6e186c7b32d711eae459867de1677b331b9b1bcfe16767f80de117eebff0fcc2fdfdbd39e4f1fc9783a1978d351a318ca3adc33e312e5ef88171b3fce33fffde6f7bf8ba3fd97d79afff5fc8f6badf8de750fe6c3c86e7d0d7bfe61e9beb0b651fcadd9d65d7e70ba301cffdbb85bc2b8c63bffc63e08fb9c290b3bd2e10c87b843a1e4f2dd4f92fcbbfc331702483e107c6cd3cde1312eac230e640af50e715ffdefcd9e0399c83c0d0e7e35dafcb15ea66f80d5b37ece20abfece338421defc7f30bf7106edf70e6ff2d18af85baaed90de1597e01e43f2e39d4cdb2eb0b7936d668c83c99fb78bc189ed5c2005ab789ff4bc2193d99f7be1c3ca3327d2a7c58be5c5ba9b64f5aeb0074aead84b64a6d87da0c15d24038ec72c11582c908bb5c84a1978b100c08875e2e42ae3004f392432446be877bdb98360342b02eae998740389edfbf8be7d7056b43734a0429914017ba72e8f5baedf7614fd7c3f0ed9f856dc0a4f9b403fb5252448731dcc26f68e58c25bf6b93f9bc83fdcee773db76bbefe1be9bbf3c7f598e756c6f93d5a71d7e61404163a883a7aace0ebf6ad4f86cfe5bd139360d71f1fc7e1940fe6b831876f3fbdd601f9465200dd807d5641ba1971a8d18c6e163b9cfc7c7c0c036ec5eb8efe4ef77eff7deeded5c20df016530b0d6f7e51ea6d3807b6f2e077afddf86e1cf73a03bf35a38f4e205e7ce7961d8ffedcec7dd39febfddedfce7ffb7bbf7fbfe6f6dd0f81f47d9ff6dd0d75f17e8ceff07f700035b7b835fde894be2573818ffe21df8f0fcd6391ec92bb133b413b32b20b783a1d3f1e62fefe2eff32fef857ff7c2bcb08dcf606040bc4bc69383bc7f962b0cfefc1b873bfcea927d9c377fb5b5d7078f2be4756d2e1fbcf06b2c6cd14227c341de83fb6187fb317fe3e1170b75f2fcd9c2d9dded42d90dc3dd7fe133243c0fbbf147fb057feeebf60003e3198963c397f7e630fe9f05fef82c7f3ebf7865def36ac31f9685baf803c3df5fb80d767bddf0b3bbffe5dd0f8e5b784e5229091f2df3b71c3a97a4974444b249d715c3ae1bef7d56767f39241868fd06911880840b18377bffba41b698872fdcbf0ccfb31cbbed1151476419f68573100e5fb6d7f5225be7202bc3bd235974a9ce1dd1a1ebf2f07c8484d68dd2e58cf0d15ad725ffdf863a36dde70afd37b280ceff37de9b8df0b4d619e10a7965bcf0f7d68a3c0afd8fe159fef1ec72853f3806ca41b94814add9ef734578fe1711350fe1f97543ffe7d7fd1179a4b5eb7fdc432f1e2f8c63c3b7352260b4d6f0ecbf1bfce30abd9ad6fa86ce11d1a1f373e7dffffebab2877f4434681f7fe3b197dd78967f1cc6cdee90425a760bc386a8d16243805ae7dfdf63737b210ccff20f32842be8e11086e7708886e3cf44081fad753c1bde07eba0d1fa985feec63c88f7c13d2159b4d6fa2d9cdfff8be34019428668ade3e160f27fdc0ae1fafa31302ee66e77dbff7eb12027f06438de8317fa2ffbffe3ef19d9fcfedf0bbb36fe8fdbdddb7f67f97b30b0b55c100f40fa0081cb0191b1f6a907fd8fdf38c8f2bcbe8f75f9ebb6f1dfffc9f28fbde7e1ee8d83ec2ee421ccf6ba6daeef0512ca6ef8c64116187ce3a0d81aa2b5596bade3bf1e07612f99c3ad6b29d438508b5303a296aa9dd075bd71b0d7c3d6e7b2ae2cc3c037d8e77b5d37de0b67f89dbf2ffc42b84271fb7cfcb7e17773f91bdc7be3855fba1e21d8970e48daa6b43f5ab7e6c347daef31dc86716cc881a4bda599691d6f86e19817ca6e0b8731f705d97efc42e77ec0f9b1f6830a2d4e0e8d4a0e4d0d6d4c6bfd43e77ca4e0c38c8fb1b313c274ee4cce0fc6335708fcbf2dfcf3cb631e64eb75b7f7167af1ef0b671ecec0df7b731717efa197cc7bb27f83adf705e19e1c86bcf0ffd7fdc57ffe9e7f1f0cb3615808f6a59bdfef02ddfec178b3fc3d2ffcd2e9747dfea197ec25c73feee5712c07fe18f8df5f1884e3bcdcb690c36b61fcd9d0ab8bf783f1cc0b6537e47d37d7c777c0ffdb785ca11cc3a157e8e57f5b877d61dccb67ceff4f27efbe8fe5bb109e43398cddf9fde1efcd6737ce32f4f0d463019d877bf3ffb5f0fde69e4e37f7603ccb21d8fcf2b73008c785ffe7ce2e54b58d2331a2a6b55e75ae87969927333866484c9d33e3d2ba18e6f13eebc5439987df873eeeceef7f837d9f0d65577e117f37f7f71ff3fe8f71f0645e6fe6dfef76f16f79f0cb86ffc76de8dde012d717ff96c70a3cf4e8748e0716adf51ab6d0f178e17773431ecafeff3794e3f89b8fcf301c87712c1bc6f95e388ebf856cefcce59087af1bfefef2a02cbbbfe7c3d2e41796f98fe3efb6eefc7e5fd6d661b3f73381e35666e33e1c3c9ee156998dfbdaffe376cd9779777e83f08fc3edebca3d99f776f157a3b5ccdfc0783be0b4e66f613b7468dd93ddd76d77846cafff32efedd05a973dd25aeb1ff7b0323e40fee3b03230fafd4020ef85af8f325e9ccf176c65f9f71efcbef00dd35ab7d0b932516badc3742ceadc07fcf1f770973ddbcbe6febedcd917fc8561391d607cfc679f9bd3217e1d39f82c97e391d6bdb0cbf6ba71d0872e742ec71badb5fff3ecfed81c5572dcf86ff367c35e9ff9af853f8e4d9a2d0e0243b6d7fd6c0c0c7f7f7ffcdb1f8770fc997cbdb21bfeb8009dc3a146ebf8cc7df8675786bf5ef8fddeed6e502d8763d621e1b5c97c8d6724f4df15d3391c24d6495aeb8284311cf27c3ededd5537771ecf703f84e710878d1ff4f120719f4779064732d826f3b5b53699cfdfc3dd46dce711f7db72eb9ad65a17ceeeefaf5aabd6f178615cfcdd7e18c7867e4cd7167fbdf06fe33db4d63e748ecc4b8eecc60b5a6bdd8ff3fd99c7c1de7908bf85706e2bc7fd36362807c3109ec338df8fc32f248401036c5df3710603860ece6d7f0ce43e1f27a1736366726342c6a8726284b4d6693a271604a27362a1d6f9ff06fb7cdce70bd305fdef75398ce19017e70302b9ebc338fe0bf690f73d3c367fb5d7072f945fc021dbebfaf7033f99cecbbcc7f6f25e7f8371507ebf170f7d99ce77c5c5fc7559aef0b3f19ffb63205a2e6cd40f8e5b9fcfe511b6e8f76737fc3f580ecb920b7b91bbd1496b1d44e76e8cb961e3465a40a51986d342f9c76e70c98fd774bc1d2ffc329050f7e560e8bf7fffef07f71fffffe372f8bafcf7e3f0fff81bf60ff4017f1ceec7701b7acdbfe57218f7f2dfc6e799f7641e82e5382b3b4b0b13a28bffcc7dfebb3e367c790fd7421d8f17c273f8f2f0337163d886ce15b080d63a20ffbd507e31bffff7c2b1ebf6fe30cec7febe2c87b15f88fcd938306ce1b00060ae8013391b8d56f40f94f98ffbeb7ecdf01bf2d0ffd60ddf60ecf3b96fa11c9c796f0eff0c9fe978dfc39d2787712f0fd95e17f6e11c84e7afe68361b627731d60606b3d99f7becc7bc0757ebfdbb7b10684673e73323e73fffb0bbf722cc7ff17945fb8cf6f101e6b7f9a3cbfdfed6edb06651eafbfbff01918d89a8dad354a5df397c3389f1c845db71fff170e5b97cbfbe0f0f7d66c8081ad791f9cab8180d6baf8cb41fe0bc3df5b8b7335d0b4d6f93f730f0c86efff6c28f3de5aae06570dadf3c050e66fbfb796a361c1efdc070cdb60780e6739a824ec02039bbfcfc7d1b890c87c07fba06c240ca381800e7f6f8ebf7fbf1adc7b13b246a3f5010cb6c1b0d9db7f6df87c7c0c0ccc069bdbbef05828f3708d060d3858cce7e33d374305ad350f9d9bf14617d7bafd03e5109ec3f8cbc110f641b537cfff2cbfae97cfc77b0b876dfdf77233ccb46e86e1b4dc8c122b740e6c140c18baffc2feeb0d869f0d67f87dd760c0d0b9c1bf1f8771bef9fd2fffc51f0d8c841c5817ad8bfb6d6fffe56117efedbf3caed09785cd5f9edf1fc7c1aeb526750e0c057ba1b556d339f503ad75bb9decf6e630867f6f4dc7c3f7bbb96c21ffc1711bbe2e9b1bc321cfff97cd55e3f97cbcf350fe71bf2d847d500e7f6f0ee53ff3eeceefefcdc1b0f7c71c78167ff6177ce720700efa0003ebc95c07d92c7f36d7eb88bfe7bf678346ff41641b699046ff41908c2412710c67a4412370dfbfbeac87a57cb8cea5642e90effeccdddc18b8db8dba52277eb1c13ef4d38f8333ff6dc8736be385bf270743ff7d2c7f7ff859fff2d0e7c61f08f743d90dc3afb8dfa6b5aea1f50c3030b3b60efbc46cf80f04baf12c83fd64fe4683ca470eddf27f493823fc6c08cfe12ccfbe206fbf0fbf8f75e5f7abc9b14e9edd9feb03b311cf72e8d5dd99cff20b1a6ff0d8fff177ee1cf883c7c0c0faf7701fc9a01cc7d1fe6f77721c07bed9883f9a2ccbdcd777f107c2f15f5b877d6cece3333cefe0f8cf060d38fe13f2775fe6ac8d910cd280e33ff85dfb9952e0f62dfb9ec76c402069b3cccdca98b83efeba38d6381f1018f665de43fbfd598e83dbb76c7ebfdb1a7fb4ff83d5fe0b9fadbdc16365239dff6ef1977fdaff318e2ebb3f3030f9fd6df00c062607673eabfdfe721f17fb3f777e83714fe6bd37982b57e4ca0142301e2f9c79f8673ecba1ff333018c7f0189c18c371bcc6c5f0ccfdcb7bf878fc813e7cfc17c367b2cc7d6364bd3e73a0ec7a398ea3917774f099fc8990595a6b1f070303dbe9c88d0f6839d6f9b80c193d060283b28cffe3712b830dca327263015aa7d3bd98bfcf6be63f660b67f82cd4c9a18f735fb0fb780f7bb3fb16b2bdee1bec6b631e7e21605c7e793c837540f71badb59b9eb1436839d6f93fcbffddc57f76773f386e77fd036519fdbb89a324d05af3744e9cb5d6febf6cae2cf7668e26c7ba53b7b76efc82dbd7fdfa3ede651995f8db7f01a0e3648397570d1b35c22e38ef72cded37034b8b7dcced370bc330dc604008e7dddd67f37fd7d6793c8766273298d0193a845083461883ede95adf970188e155a886ce7945d15a7f0fbf6108f63ddcc3ef6379aff31fbfc1d0fff8cfef0fc17cfc8dff8c43eb00d268ada1e85c8c4f5a8e7540fe632343ebaa118462d0d0a1426b7d06a34a0c0da18dd0bbbfb6ee0697c810b5ae22d2f5498e757fe66cae1bd7004c9adf20dcc31abbb9fdbe9df7c101c898651fd6a8d163b90a0f91b5b2b130b4b0b1904608e7ddafb58ea2735c80b4875f19ffc7332b43fe3e1fdc6d84eff765a8e2dafa05dfe80301145a51a9c390492203401598421d4432c4901421aae4459707c659892a253c60d2f625040435a22ca980852c3642b874c40a05e990ab624a17391543cd985be3d25343d64846b380d6818845262f5a21a50112817de2f302016da44aa8a31d21349170e4882df2a58015155951bce4ccc8f1a92447ce199d2d222cc20407d1272d86b42e60633267871d11f6190d3203b4dc3c64b1597101100845781479a094d5183a183cba52d1006b8a4c070d1d544a9d790b6455c9c4df002d0536c0d70d0f64f0022d9081cceaa4c16b03318e84b07d20a23556c2c0c255160f846878c3929316cfa1f3a5041a044e784801cacd16a739687b9aec78f2859d22628904454c4091650b04a4c4190bc47accab15bcd469b1c303362abe2c9031870b8ca8137d9c600280cccaa26d295189ac01f20412e102194e4ad0a0902e9852630e9c25483e164bc9931f3ba40ca02a4d6d65297227050a25a72eeda47c8961ae50404d2418794a8dc88268020938e8c0028ca6387846f033a81496078d467de14063936c8296237914387d0a1515147902c76513e6bc11b3d6620b1889123f6b93d2f4e5d39613c6dca67ce002881c55722b1032412600842d679228ca194af1c883b3351944a72540e024b0c1254d6f48cc093e1afb32c6e2822b20631af6a8e8030290a84a6707530f5bd855d56f672646850244da3f9580a0c0c1cc99121d0b30c152620d9126e2794b01aeb3c4939a3817d28440c76615046960a44b17232e7ae8d84c392f535457af813a0e38d00485a3213e5294a8146488d88d529818a5f17a818b054fc884c00387c30cdbaef2068a10114e3462e5be24d056c7ca05e709a31c0202393222a605256dc5c486830a74fc00b1644c21069aacf10dca69539b9fc18d9805a1bc68d9910ba5b64321ac82c648458f81241cd66830c122c5294cda833c54fe0c43c43273232b0fa632557404484c4e83d65410cb4a7485a40a93451a8b130cfc287aeba28ab3c144210f44e12939bcf023c50394245384371160635e5f8e34ea5cbe1a19c9c2e00ea9ab4226a0029cc0f960c3e5cad2db222fbc13b216dd21175490004d1c1f8b02e519412542d0072ee0170485da81823c40db25870acb74ab42844c151210ba1cd9c067451036142c8480718142c3a28083141c0b4c211c469cc9d1617971c7440a69742c4824946860b509c2254dda0a228c48c0e5eccb133311050842d6437b4cf81466cfba038a18a769c4244a6d02ec3e5910dc2959738a880b2a408cc08402189e171a09264f9a4e1920c32c4517074820e9b48401198d787438348ac71c12c0297197fe14192190086c800e7c092004c401a60e4d813a5aa7309d593065cb8f920a1d40446812f2048132ef253674ccd2a91219e0c0518075c8cd9c14d0d2c29cd1b3400800807cf124355251811139282642d49c1c06b2ad1e4de2982d50d605c3cc1a06540935bf0c9638560802240573a3e01f5242441192ead19a43e86409830112e81256e65a395f48e80c2201854d671c4550438bd2aa5149c7984bbe34996eb490c21b6e662b84a91e1944400b92e947a2315e4ed0b244257708c888870cc7276c09592c44879e538b921627acb42216f4f480a1717193254816141d7ec22419902804e382ccc6841fd6d5a8660c0765321cf5b861a8cb478b2d4113554a1624bc31e34287030f6f9ea419f324c2eac8a609c21a34b83ce24081294c8a405d9dd9a186412632dd011034c41cead4e182135f6314ccd8c085510356befa5012818922115bce889131c3010f98502185f090600bc0d2e0646cc80b536234522032849a63e29f88c40260e40b0d953c17f0e1c0824e181a23b24ca04db69e5489a2e269d8c4e58d88f5a6839488629b199528d3ef4aa39000145cdc842a51c8c76e85260e585a12a48ca3116c4cc020849a02a0b0b0c1093d2fe00c0081b509900ba704a276a74184a8340d0a8590224cc607b72f73800b7400c565cf037302244a176d46c5a008a8b4a148232f2a6082208e70eaf4c56541a74c6f9d2b40e7003152b87005a723ac94e3c0251e3ec6b4d04146a250240dd494305a4c8046a3003853d4a0203cb09446e9f2e323830e2f9cf26306cf4e0505ee0a5a2c03b3d700dd1f452a85a9127c05186d2a7180cb980af6b4c0c3b440881e79641289a71268bc1dd2806b4a012267a32b94a03b5c4e30440aee409309243e9428f50105349b28590a419019950e7254300bb1814cc08813a06cb26306d86bf4499003b935a1f880d86ad52c6842e404380bcc4ca075e60f113e6035d212253028cb8b26d5226b8798430331a524398aa0270207b28529571a0848c3287748048e15e11d365f5c3063e2460d4454ceae00d5a04a5402861261c264213255c37ce4412c658643b8284450ec0a78c8c70061e30032756868ddc821e1c084a6381ec0a5d8a0890b4c5e2c20caf4821311692884c023b1e6854e280085a96145810dae24a920020f0e4da5b25c22f366a371403891408a2d7c96c832c27e81642929c8c9222204122fa9158eb84804eab340e5e5d30fab6c8e0b31839a74e2f0a20a061c7050610b0a313a6cb0a4d19189d0660d180938d2de46f4b8e851cd5c5861fad1a3909e0e2485c1ea23001242401467f6cc36c06278281343c142907d848715338482525d223811b31a310ac9a63947ce26812054ca0f095f2a02f135e204214e385cfae0c166e34a180429059d2e7452e072d494f8b109cd97107c5f4870712010d7590b3c39e63e232028fb14836053c2a7e0d1892f3e245c8e950054f0a2a2ed83005d4408f1a834c60da1a1039f4b2558c4bf3e745401a2bc6119531d20842284092f15e84011024be4e533094d905eca89e07068c8053e191bb47c8a9121066f82127f28c5b9c08cbb34298228648de224fa14824c8920250c429c7678d228560b0e2f7270235c0d02e2f3036f211a25c9070d155a46a826000008930c9eacc9b1421812bc312b8b815118c858740129199084cd2971414e84ac044e342676734a0046b001a2536abd80c28f4f2e243965c095970b24194ec22c322e24bd90016534940e812ba5b04194ab758f252b811608f5d3600e013dbe68684db009b4088453465894d518a191a527b223112610b9b92a93a527009f27cea6df157755a791091e425c21494365d01f0a38611173c28c0b88320af4b00b306244e8cba4367d4438c026f88118044ccc09067df2883d85b04e48113569cc4d9910046000e2a2a4817aa205b7cb1895c39b2e26dec678181b091aa1ebd36812211a571a35d9c1592268ed61712914e7529a9ee6aa5409202f384073020a39330eb005d2f812c48402d2c18921034600eaeaa010931228b0c04132c901321fb058a5fc78505dc8b18391a73b4f4ec4b9e949c16240c29751f1d50f279b0c11e202840288d8c5d27230744c88db524102a0507c1528826d8067b4ee303972259a90c78546242e2541a1829dac2285cadc1409224a8608204ab87449900a643ad48099a0630dd345021521ac7931f0f985e924382269e0c46482124e7a8042c313c2463e4913c2034f85c284f0368a5cea81c52794294c70c65cfcc27268db125a8d3709883a956285a21f5ba5568912949478e18609814c2970e6c926f584102360c912c250a22de48825e290092e6ce5f2f87c935e1b1ab85690b4c29f0a71d2ea9323c41827e2001ed6c268c0a3252997c519b94d2a65c1862593c2d47cd151e7c695090f193cf165d6ac7087aa47013f22da4492271a3600fbe262916286ce214b5c3a0bd356b3a650dc871107225cc09b427d55e5059e3c6a8c147af3800855885c89a24f646863c21aa9c10091d6f80ca11ed05a44db9e4f63471a5862401e34001040d3fa0a050d882872c2e38017c0dcc030dfd0fa84048d582051088e842f3c65d4f40905874125353c3d1574e5c05308490ba856894ca20eada947d4f42e50838e3c10280e05a1f8142c2b9cd981a265e1028c3c1c780043c49a3b29a6b059c0a418c1674c886bc25b2d8a14850416294571a1a5095cd992188f09f5981203cb974d8bcc707ad4c40aee51a61b9a040424b0c061e80c6f8e15ad41f0d1a3078057049e0a3068ade20014b268b0b39566488dd6256c1051d5742941d2075174885da9854c8e563481a375ee8526192ab0a48859b42e0169c9255355a834ddd021e6acb067b42a29d03ac7058617571518315a6bc18dc541429327d43aebab8ad0083b5888a2739f1465e8014218ad4d685d6a64090534adb3eaa080d3d3e586be1a728987400dad4d5cf0633b2ba4b588528895476ab4be1a1487568aa24fb48522a0d45ac41f0c5280d11a4b3c83e98646a125868dd62374b86dd21a4bcd2ed428127dad4738aaa23508ac455a9350a235882c2a6e84d05a6badb5d65a6bad754e6badb5d65a6badb5d65871447419e49313488021a47894551658330248083256c8e1c8d3a13a6803546d2ad800450cb519a08824e2f4c40c0056a67cd035c19a110200b747a1045f4212e425654e3c88300429c3075eb8288d259c40eb6126841f279af8d0a1e50e1e11a71ce89e5779f0af12dd3920c8870f9e761aa448f1670d062a4484a1f814278c072588dad30682b60dcc17263af8be466f592e05db7cc965f82368c9154bc967d8a0c78b212c714a3098a4b064f92153238003d8140c2841080656c6de369980e1a44319d04f1d2d12e6e881400c104bb916bcbc989329d803c8811902594ee8a193a5ee3b6578586a125151d2c3a9050925b4b03c41718acf88322d26c4012f4712a59c183a8c0279e0e100355d6e1aa4304180b6101444c2021362b435901fbc41e08683062536fde8e24181068076dc3034060c1a077c727ba440d1da89f3ace7a41493510a19a20694de58578b314b55689a3c0ab4224a09334a626a2af84244a2421682074f255052a16604d6a64f39b4aeb64480c082f3801010187868eb40012fe08e090e38d4090e047b48e8c1ca90810b7bba20f1db46a631683e85a52059de98b481674035bca8017bc009881e6e593be4b8f96f58c011b7b505010724420f184023a4830240908f46fcbe164d49d1a5410ad99c0cbc3cd21ca0d01147c6060b521bb40d4c301397434761d483c706994680f1f040293782842c60c19a0c951a009406c58c7556e34a82139e7c32a463010d7e19b07a5c8099627cf8000ee224d1ae0986ad1155747aa8d0e381212e5e286eec3102c0d78941442ab139a0c3cf09a2b6c060da1ac05db540c2eb86060304e73e6e91be1470828308b80650345160187550420804480f2478382122830c5c98c100ae74227aa03032d3c195971966d030770b8f29125730096b7a16a80da6007035e857a95403598742d0f2c7c45b83c595206519911a0098b1e1819c18575b99cc0442559ae3488316520220e36126eb552168940a4320f5d8238797652591a265c80d9e3da28c0f6b5c90893353640216b90a342c4a7b82c2c560cf13395424ee8010e2042e18d8503c808189298910aa2422ecd0e23a2183289806083596448f09174c3066528e881833c02f5c14ec30b1f190c2420127044c4a90990429683ab3c654282a489bac125c468d9428d5594365032711985e6745547862a100328ecc68b904080588296ffc13885044345590e98253c7c2e8b5b7a03949a46087d351b3844a1f3c15eca97102191515328e30d1d271c0a5087874fe00bd310f8070520611da6f089d1242f09de2e248b09040a20bf059e8447a402d8b8d14e2f26c4a31dff051034e24047af4949cd521c18205080d6ff6952d851858c4c5967cc15941466cc0a8c6a62f261754894b6000b80d22c54101e84a223685b4041319518b1a954220089602f30d241d8b26194f5ab0742509934623685ca1cd7fdc4a2e24a1c0cc0b164a7041c121eb01043a55210276f6a840a990c6131601275c91448e7b3060a9a8d0742c94083b6f362170ead4d7c3444a98950c6b299c38e2018b09a09c2a8005a4150864cac14977d5c72a94041f4e610912cae3820c1352402282ab8a0a291238e5aaa96c541736e956302101043232a5a7c6de68d850888925b03b573edc4c428184345bca00c800c82c91af93e5000220b48580c52709870e9f1a0d2892890e6e3b34f020021d5823226129a44ff891d364c8d31fb2b2441cce368999a4c5a865adf8a3a40dc8911b672cd8f409718302362d2531ac648081078dc7e1d12b83a6e982dc1423648b4876b06a70f8b062c7080ca4106c409d32a183232210f56054c21e42e6871287e840d904009e1350788e075c5050959653d1e30328ab2fa0149d41a4019904d6cc215e846a2790c99ec6a89c1a55034e4b0725c44dbd4d63c094f0813fc582592339ab0a272ca8b0e8136aabec49012a54ea202408083a2602a1f2403ae778d234ca17c0040a902823880599c5872a4494ac61018b000fcc48610199e703a7043e9cc18e990bd1003b40a4219a9614cea8f892ceb2948192e58c44062e2f071e7b51401a0b18812829615304208113475c4080fa40001c3db023b216b03050e40582094c708b000ec69d9f89cb89116e56319a772346ad91892410ef8b04146a55ce2e39e920ae7748901e19a97a046b6dbc73c6019b4e23402172a70695169144945000123653784000899288a20b09262c3ae1c01793030b11c08009f2c2d6a7139b305c6552a51010ea905691130919115857562276844600e2a951e9d3a0155e90a4c0983113a2288084a8d20044bc5648810656133031574c3ee00a3b6810f2a7c488cfe58007d06441d232727dd8f08ba302890d4f4b06c0c0848f4e4f24c04a244096a6d20b9c017e9457572ac890c1c3021773ec4481044347da055941e0165c4861474689136b3ecc91d89668c9e1408a824c47c02875436a6957543d7271b034092183d403871a40f201881d6a168568e41a293163d400a6ac842a2381a20c835607ab3b94b6b070f5e4456c26c996993597638a8f181340dac0d323376bb41a8dd0210411d6120b0f80a901c74b075a7897326725603f66f2f4c8d3236bb4d289021402b1517108ce94357c05af089417ed9bb63a5b4050da81c00321e40921fd02a7a66bacc704241ca1383d80b00402079e208548312bb65474b844058105222d4082e7c5e4465cd70f44cf0323b05359d27ca06102518f0705974888615d31144889061e706011684a92374852a491e16a226385c392a813ccb2903663a9d0405c0f345cdad62ae1718106920a5a46d8b932620d064f386090a084020068c0361467dca0d182a3cb519e34233869f040972b585236090a1e8a44c02212de14fe10e0e883112c581540d85864c7ca891d75dac4030a9de0e4429d471eaa8400414762647de10e1816d6a41e9a0400218026535a443800f29481083262d6f00e0941c44ba941e16c8e12b71335e20cf131f5158889130162b0189201882b087c294034100219395e5cf409f5668097885c002e16b89200203277ea74490002115126c468f064ea4d2aa754035a2ba8d862277845c3ca985d570b5f8a298b1e2530019db22c2e10b430810abe1c04b4b0e281cf0344246979024381b79363080a72dab43611302d0782962c82272f32630e055221ca8d96ccdac0738d22d803c8001b753ef1d0a058a065460a488735177222793062029c4f6327073401c28b3c64ba68d0414a3e6483040e427461b1c1923580e00d46d04515783823a8449d184e3c6cf0da00510a0060704298b114720318a0e3d2c088290b468c9909618092b7103948a42410958229208a10522031b06695c8cac1a9d08342051db688b041d38d8aa828b2a6c00b07dae67cf9026eb844c501148805e6498f34686116d7a4cdc04114376f249e84c93a13254705194950b24c093b584bd1c0c9001b3d645e3861b453c22602002200c1c252d8e6ce13383a0e18c0a64d040e6c19d18981378a508820229259112e3e4274f0a1c82445ad0a13903360282dd1b180f4010b969d9c072328022225121708fe804028023d238e6469883406c3d20f1d181f07550c0b14a4168f9c07a118c0c4a4c4e221005230b00af8f472aa121745918ff7410f0317fa885064c296362ec88c6095234e80292c804570828aa639676f2948642584f020018f21b52b4640443f0048e266832f8dbebc68483e1091a3c3a98f63821f80484464d9a5609989478b0ab0b140cfe41525d08d1348c298b9629bf2028b0a1bb0a4456f59aefa18b026eb02f64e4f93070e8c3018a3444497961613db0f924161075e0805fb6060060f8f913b95a555668529a4684420a6cf086827fc64d988c46f2c71600f170f489550e681169cb4bc802105c64b87366fa1515e0fe075295746cb4c0b430869fa35ccd888a281c6871081b8d8284fa446b07140958770030f1025505013d803830f112fa218026f3a4c729433a9bc90c6040f3a4a842e330268d8e02684d82517d84af00010959587ead08e01d04aa835007683129f0066492baa6c9c00f3808a37560a7530020201d2ae4a104be4409e44200ca9a199428750061ef0d8862cb8f24393f0f3a60a0945e2f6e840618a86e806d38d149cc24070629370a1e5c2c9211a1d880006449a19371d3450678428e44d93c12a8616891762086890a148082ffc76e0204425d40829368813c5024acc8c2c671ec579158860892087ca521e165e6863b201f0a04482c40805845419614b3f1c4ce9a32545231150a030c0044129805dc049500b3746db654c1bac9f4cca91a760a420c80a3fe188495846685834aa470d4d50d8e2c0e9da84e283124e1c02e0e41dc077610a88c9c3bad8d1e2ca1409612f0c3922298ba9139f0009390b22e2c9192c03de19abadc6035e26cc59d1e9448ab1115a3bae4664186080f4c52325ed5598123c01df1d747a21ae31129ac4a264897a4049072d9388bcd06754a3b4024468227840952f72d6ec18b0a9824d8d4a10b2e9aa0b2e8674288fa71e4bde7e5cf9d1085496dce80b181b6cba2a2502c185a64c6673b4162122e7b31d798850ed8039254a8f7282a0a8e1b2e3c9ce1e351c584113a393a6102aa8c8324e8271049396aa1718dc328da02543939202c4cc2ba4e824662703316acae4907c62c3f6c7108904d404a06340934bbc1041df21aa382e24e1f3029196d611147025c2102a2548440b67bb03856a54d86aa442545ca9f10c9f41a72ad06d3224c31307102dc8b151c01a1598406934e98713402b1022414a480f455b8044542012d366d2d712522ad0392bc67e1d60b64014285a83e3e00dc41444e5065b2f3250e3e88315620e49d940a243097b61cede23c00086ba4899e23d5234d96119f0e8c9d6a11f33663827a4d48018c04fdb016c678d4e6165c075e8ec0f86111dc0c001bc8045970a1cb9c5a658b401802283f95107506d323c1db0f601501c0034c032e306a04184a552a148ac6969b485843323c4c6746c70c20ca038892bc7eceb0c1514581f68bde08020391cb08061c44eb572002b06066026652222878a88202f66a8b0c12162023d7ab2769f4650d9214731bfe5d109df5914d963c20941270a30c5a8d41c2f5715000a0527810a0890fae1e6d498085de244e87e71234a76dcde20b83a15a2910c3226fa6850d485cc1931595f14781289839f26576bab943d225c10c20171157cd09103882e2b8220965c348ad5ec3cfa4a408b088c381320e43050c7ccc326341e52519550088ec899c0a3d29c2f5a7eb05c243060c298086464bd48f2e8910a6d6dfae03921c58d1f104cb4969c5f3e8838be74ed48607315c12322b92b824ab84fbc4ac449f2b4f2d8f0220df1264e3368d21e158fd24a688406d19d0c25187dc99107842d4d1cb03d60b616302947ae45992e1d0080e646d01ad48993839359082f289f00c05105841237461951a0c4254a25d03426645880800d3b04ced800354946a8b0824593061b32ba880a56f9a095258806049ef9d32760121fad08622dc031655348a849f37a021c43c00a35453110f53143428a42ed9e063af4812378238885402588490251e3c62888d00a563610202e120aca9021121dc01420c781724383cb23b40c3cd19891e2431e1f6843de2b0e7438f0a2dc433bb00c2dba130625dbc04d8f1ba7b4d8a8f030a209d9241632c82af52344c0c6083b206084c24890acd9cd4893363d3d5ecaa041bb8245242b51cf10a92f4d7c495c5895b6260205233704bdf016c7d5448e7a55994a381167cca9e0678c100ab284f510b352e3c015a7533b160052238807a1b816958991b5227e20143694749193250519839130204431714a77c90b00321cc591f12183f86d0ba52b284ece1e0daa91698352ae24b62d1320caa274848d971506e039f983415ad8cf433121843c34dec9f141132354db4121400d5c898892e4141d38323b238e3786c28d4ad691d02d10034072601b08e1a376e9832d2d3c5c62e0289cd6ca9a9c00414f0401bc7275481dc9c04e98798ea71059a8b664f02784245178449dd87305c92d0387ea84b7185a58a1d4ac40c2a5463e30d021a6f43e0895e301a94a190f3000a02245e9d081142b5a219228c214286d03a1f747980360844cbc126e5428c920e080b8324cbd100114d98d52f1c156a3163e898ece241154420051140b202e91c970a4518a2b17f8517db4a9808116484cfa4368050e1070c5300270e08b2e8c8f8aac18a44079f82281973c5abac4a4181100e237a3c91941094565441044110aa1c510123ab6182153e38d4171c2214881075eba1445e4a490d54bd77647ced4b8728852b146c919d183b728fd94b1a30229af16aa8c98c0118a90021f15a72828445170aa0b140f74b9d4d344a8ea875b4ecc20395eac2b8f3c5c0026040ea514c141181013da8ce0f282b5241488384a5427a47410878d831329dc21e3211e3224c8059d0d0e116117608da063ca0de00d3d5311d6b6442594108186810aacca8000604528ab910617f4dd8995ea57c5041c1c647c2499c12df9835ec5092fc508ec68e3a482960f877264b1119155028a2f269a0c98ecb4a955404212071366ba57c10a838e3427ae70cd497395e82a2c858a1123589ad3977800c947a52dcc42e04330299291217fce742822f4c0ba492b54a0dc18b414749db8242b0a0e10c2e620915182248d0c1235145c96d446056920eb4329b215dcd428dd5c92b536b1e05bb5d45e506077d0414a0793be8ce040194090dcec641225166e3a680123ee840cba8a02211040032448a71f19b48522d1cb11a58d9f12136080230702024e0d52483285084f118cdc95204e713439b244438801576f214831208408b24d901112453af4230202081eac8154c284055ee43010f6e3890e3b3c78e8d8e243056b4702211674d06652a41092a4d092430208347460b747540280f3c6501f468be4782061458bc39a17070c8d497ba10b4b1547572920e079e992c0cc4f0b6efc9025b41d1a8178f1c290481fe0504dde80a097502a9461042817e05c023c5290e4c1861b5e84f409008527263b3ee09302853084102dba73c21b2d587a3abc18a80002889f3f95aae0524b9011ac8f2d6e321ec5802187841507aa3871508091f003e187033394901456890489188345c6c1961710de0814048905f1ca9ca510d1886a0eaa8402ad17723ec4a302ad697382cb1412565636de1d32207c4c80c2160f578eb60f351ebc33af29df152320139489302be500578a74d0960a021081a3530b49262ad5e090820b0d56f8fdb2487ad4c60446573e025ebc09393304031fd4c2c696c72a8b908c3b40bea8bca19c84e97441d81a0c265217d0c081bbb4438210444170278c00eb95151ab12d5cbcd0a9b38156219d0beba12cb22a097ce9e22246feac6102d667840dad316df68c62e2e1530a710c3d32d44333400e0d96302e989505211327c90b2723b05c213028e1ad8f0a23726a2860de4142a48f0425586801c21b372319331706a1c863a76b97531b7d2d3d280d8041412405309e4a480aa18387a94e82d25c29b7ecc066979ab41245929882004f0eb60bbe42e052356b60536187850ad07825c2eec4a9cd1974b5210a080e183853a0f1c190874e1f9895e104011812826e6040e710083f691018da59f0d1ca14292c0a15c9c923382fd00cd863e7c903612084082af3c68b1b2543c2f448e3c007011190f8c273034b821f649e26a8e4468aa54f6a29d430372209260560f8053a608dc8e9619190678307333e9c447a4269caa4381e178c38b3a64318b116487ea420d3c5386ae00e0a2a867c4cc0484ed9a6ad4183c900579060c5483a603416478da65da615910eb985111e42e1c0f181025a56a0941c1550040ca9138c2420f348cb9f18ae1547893e6c13c5b2aad380a620596656a80041a5ae27178c89a862e6ca9a1866a83801c12c408ab02481132e04f5cadca408fa1df25470a3d100a3aec89491f2c5e9aa0494179f58d864a5909fac52504688f3637622803aa164e3068c93892694203902d4674f233a3d29877e08f0c0958ec326021a899120d317d50f155810049015e7c592d845a594864f589bd6918f2c5a8e5260e04f1d1d42b04090e6c182035a28c969204a8d9e130e38f31052a12c1d72b208314a4f16127a9faa70529f4c5c79c7e2689d963a9d18f36ac304cec7a227c0070ae4d81e8c4045e082261f97b13152326c891082c90839e864952853868170920bfa34471dbbefe131aa395aeb9ece4d5af3554142d8a475088c42b81382f1625e38cb1ce8e6f918246c07f96921e874dc414970645d767bfc8f43e72071d2394822e81c24453a074990ce419aa3739014d0394858740e529cce41fae91c2456e72005d13948623a0749d43948a1d69ac3002342e4ac3068f8e520858abf8ceece309cd6c2708cd6eb33ffc96e0fef73d37a32d7f13d7c2607e1fff2cf83ac27731d3feef308232b9bf9fcdd784d6b7d6a86e1b41776fd5f7ddc5477e71fa6b52e85a1ed05193e637bddd7e5bf9f36e6820fcfc5b4d69ad2d85e576bdd82cc674ea6b52695c95115ed5d8ef63f0e9d2c035dd707fcf1ffc6e379e02fc886dc0b560b7572c803bab3dc7b9bd115239c11c2086384ffb73baeb0460874e7ddfc7d33ba80eeccd57dbcef6a84e1fc7d3264845eb31c8c793c5ea803c6b1a15717d09d43f8e50abf0225a936b08e238ba228996e919ba5474f34ab4aee932ccf91ec632f59d63cb36ed2fff46459b634fd57d3d2ccea7dc95b94ede3e7bfb72603ebd9a6e7274bd58b6629f6922cb37e6e922657495e9e6cb949b82db7d6726c95e974313cf3f8cf6efce732787ecb74baf8cfee0e9e5f57a7ebdf8d14f759911dd515aa0556d26ccf4e927fe422dbf69424b3a2bd6fb2554bb635d9b4e4620fddeff7ede077a76eb3efe26637e6c0749f15d9e1a052606dd5fdf9297eb1e5fd34fba61a439e676a6e72ef739fe216b789a25b15b9e763dfeab849f44c45332a312b79929d1cd95fa667e7248a26b08aa2f766bad9b32d477593650fdd3d3908dcb5f982acbab596a32cf6d1f26f36b615646b6c8bc7d6d896ffef9b0f9d2efe6d31ffb53fed7bf84ca7d3e97429ba4f736f2a16a8c2c4b31c8c773b2d2a0456d62c4d5444bb577f0fdda9da0f8e71e8743a5d3ccb678f0acc7aa2a2ca55ef49df59cef2b187ee72e7a0fab2a65cfdac598ede6cd3961cd51ebac5f1177cbdac694ba6a44ff7b953966c4b4f8ebfe07bc0da7bd9cb2ff6d24c47966cd31eba77b23bee2e68aa92688a8eaa68a226ea3bda7ad3abe889aae93f4df58c8acb2aee94dc645aa2632ab6a2bc837db9cd78964faa2deb57c76f725164cdb2e4eadf2d8f4acbaaaa7d9b3c3549d6ab2c6fc51ebadffe4bc6bfd763fed5e2596d6f349ee52c1b1d4bd444cb3435c5524d51b24cc9b6f7563dcb72b3e589a25458d6f454cd2f8eec3f55d2dce4eea17b2475505d5955f193ed17fb3fc5d48bdf7ce1df0fee3b1fffb9ea68525959558e76be51311d515544e3e2f9fde62cbb66aa4a55651dd3cd9ee6e72c2b7eb434bf0f185c13a9a8aca6ea7dc93d5a6e53ed232bf6d06dce3d18cf6a7ba7f3afa59ab296ede61e155b9e9abb2449d4a592b29a6adaf929f27293661ff7f96720f7619ea3e97472fcd3f3acc88e8d2acacac7d2447f674db51c53332d832c94b5f43cede5ee9d9764b945b43c5df6c99aa27f9fbd97e488a2a64fc9cd9d6cf43c4f323df798aaa4ba5135454b72e469ca96e3d9dbb33c83bbf9d7a2654dd6fe53536d47f6dc25db9e9f1c49e0cf2559035671b3aadac74dfaf4147f2af6d0bdf3057fe266b2feb4dc9bb33df56737cffe7be81e53b1841b4936572c3d7fc1978c5b47f273d5a3ad499afda725db43f70f8e5b559ee3eff6c23d8d6799845bd9cd77da9eaac837aba6bcc3ed5bd6dd97a3e97470fbba3bf4acc8ae7d5b4f3eb22c6ffb4ebfaab6ad3abaad9da7a939963e354572dcff9f637025cb71ec7b1ccdb125c5b2935b6b39b6e07c19dbcbd3743a9d4e06c21b3d2bb2f3f37a9a5e4cd94ff674e4deab7fbc21af9ff333ed294b9a69a976cf9e64f1ea51534d5bb2fc6749fabf13c9b0256bcb79dbcd746c499ea2deff9dcff77b095c4f136db798f6b2f3ce8a674a9e67457647e0b535779a72b573f6a769e75ba7f3f97e17cfb3223b22ef3a9e623ba2e2e665ba37ffe3cebfe568fed634fdac28a669e9bf68fad1eca1dbbf4138dec595447c2bbacbbed56f72ce966459feb3ac6d25dbd37b944ccdf34cbd3802e19dba83b21bb399664a56b1f7cdfe3eeef69725e7ec4e7557de4f7f926c3ab6a3c88a9ef7d07dee7896c9dedac9f1b79ca7a968969bdda7ba67b0ad65fa59b434bbfad39ff24d9266bb8aa7c8a6ea66fbe8d5dd8e690fdd3bf9af5c25f7c85bdffff8cdb3e43d749b5ede447b8a726f8ee4e85ff7ed0dc26fbac1fa3a9265fb4b1155392b9ebc3dd975f75135f91749738be5ef650fdd71eccecdf53b72dc9bed75db54beeedef9c937bb3d3ba69c2d7be8f6c1aedbcec7f0ee8577e3a896266f65b7e977f93b47d57efa13eda17b47ee73dcad9f8fe8b9d393a37c9769eb77f09cd248b28a651759d57b56453bf7a908cfa68a641d4bb3fc623ba65b4cd9f434fbf73b78dea17bc691f577b19f5f3dcd5615cf34557df26e6ffffedfef0179cc66ee71a36846563f8ae2e9c516557b2fcd8ff6d03d770ef7c722eb886e7e8a2c274b9ea2aa2f7be89ee53fc7704fde99bb8cc8caa2a9297675fb92fd7c77df43b7b8df60e0ce17fca9678afe82afd89095f74d7a923577cb8a9e2dd9b24cc86a9aa65872df79797ef5fcec9823c88a8eaa6896688bf2322d555eae6de148db1a730059395a9aaa699aacfa7dfb4f4fea585b51b29b6c79b662dfdbb39e6fb5f514dbddcd54255bef3d67d57896c5356d25d1decdb22c7de7e6473b0cb33a7eace9475bcf9ea2fab98972cf8ee68ab69ee926791fcbf3a72247cfdd43f78edc9d387cacdef49d93e328a26299eeadee31ec6ce56d27f7a89a9e654996abbe876e798e3970e7ffac16d06315db7624c796e5fd2cd3ed3990d499ad9b6f5364c7913dfbd8f78883c72ab6beb39e7fd524c5dfa2640fdd3e1eb3fdf975779e03c71dff599d7f2d99ee5877cbd553544b34fdbc9facd943f71b0165abf87dead9b19f6ddb4d546de530f3acc86e888e3565dbeec9f3b7ec6749bf7d0fdd33dcdfb105d9ef7767cc7ba38cc6bcd74bb51cabf8c79faa65297ad26c7bf7e9b8c91d8e3535f729fe7f8add647df7bf3c83bb2fc71c58ee725d3b4fcd91976cdb49957f76eca17b8e6196b720f3ed5755ef51ae8e2de7ec2e1b1b53b13cbf67d1b2ffcfa6e73e136337da9262efe5f9bd5a9261ed38b6e74f4b4ffe161dd5cee3466f3b2a96a698fe1445c5b68035f566cbaaaaefadd9db917b1babb9c9544cd19d8aa9696e8eaa698d75fcbc24cf36dde5464771a71b8cc69a6ed597663a72f41c45f1e41e069bb1a2e5a98ee91f4bbf49d43449ef61b0951c4fafa21d35ff56d9946f7154d5f56c4bd5a7bb3c4fd5644ff4f7d0ed03fedcdd1cfcede07997a2e9ba4753f5e2e79b25cb14f5ec0c743dcf5fb22d798ee2389e6237c771c6b9a2e7389628db55b364cb72ab6f30ba4f7355773fbf79b224d95356e5fcfd6e7f07ffe018b847b0b23ccf5dfaf1fb93dd636f7be806c2b1df65a4f93d69a662dbc5b245c533b8c47d833bd93dcfc6f52cd514fdadc95954345b91f7d03d077f7b4db9c8f2563547767b73ab680f9ec92d6e31ed236f55f197e8986ed6d777e3de2163ddfd2c45b6ddea38962a7bb63d74a762e65991dda85b4b72fcbd14bd79ee361d51afd3f9743af53c2bb263bfc89d92244aaa648aaa7b8fa76aee5e965d2453ef51b2e45cfd4c5c39d86e8963d007fcb9a3f90bbee4fc6bdfbc56ae9a68598e7b979e93accaf6d00dcfafbbdbfb4c4d998db17ed224d5f13cdbd1dce426cd1eba65f9a73f86c7621e841dcb7d9e15d9a130e0badcb8567f9eea897e913ccfd4fc6ad94377fcdfd7dd8dfb9c7f2d79be58c7b6454f12ddbdfc686f5333dd280163da76f46479175bb22c4d93640bb29f8c6c73718e6269aa238a9ae3689aa3b8cff26fad24a976b23c4befd38faa9df7d0fd5f78f706c76ce9588b53f46d9b8e9c6c4d53257fda43f71b1cb3ed360f166b67f9b953d6b72cd943f748ae583de9fd275bf6e4e3e937da7be8def997efbe5bfcf7886eade5d80adb1adb5adb5a33dbea3fc81b4f538984e5a992ea4ed32d8adb5453751c47ddcfcde7d3ad25efbd9b28d9fefd53762c7be8dea11b35cf8aec7ea8f8c1f0cee7e3dd4e80142bff6a574fb6f52a29b6e8e7bd2eee1d8a95445193544f7e7ece4fd4ab3d74c7b3bcb596634ba79b7fad4ef763b8cb7c4b1c83bbd43c2bb24372623d511565f71ed3b1fca7d8b23d746fade5d852d3e974baad35b3adddebee8070ecc7329e816626d66e922aaab27ff49cddea667be89e7fed4efdb31b0b31e75f4bfe18eee559919da835962031228588ac10284060c1b87a91933f788031408a0e2538c81b04d010c0dec1fd131950009002c3698e5661155509dde1cf86352950fd64fea6439142ff1f7f316c60538883cec04b9430fd03cdc7590f331e2bd998d88d026cd4a031034c4dd1d32cc9117da4b5a68241358a83cea04b9630fd67377ef3fcc7ece8b603db01e5d5cc7ac0d5daa42b040bbd4230ae35ed3f88ec02c36417c87b7390fb803f976c03505e7b83c734e80c0060903f1b8f3f8f57d3344dd334cbb22ccbb22ccb9224499224499224c7711cc7711cc771efbdf7de7b6f711447711447711447711447711447555555555555554dd3344dd3344d53144551144551143dcff33ccff33c4fd3344dd3344dd32ccbb22ccbb22c4b922449922449921cc7711cc7711cc7bdf7de7b6f51144551144551dcaaaaaaaaaaaaaa9aa6699aa6699aa6288aa2288aa2287a9ee7799ee7799ea6699aa6699aa6599665599665599624499224499224398ee3388ee3388e7befbdf7de5bdc6a8a9e66498ebbc7af4c13b902c340fbf857fb315a9ceff5f13ddce3bbf11a977d5fd55699eb587dbcc366656a71b31b04087cf62bfb337fcb62cfc55ed8f55c6c2c4d6eebb04fac37c7ae580bc3319ae762dfc767b51f07e7200e9f8f8fc5cdeeee3447f86d6ddeb1bd542d95a7ea5a53b15a53712ade77e335246b9132b51dd94ae663ec6cdda5f9484b5b77ab1910321f3d7643c27a70d9f71fcb6060ea36cdd1ff99b371201c03cddc3edb0bfb6cb0f135b4f5fd6df05a1ab4f1fb73191becf365ff75d9de75ecaa2c355b0a72ac334d5d466b3dea2b728b1cebcaed16bb5fe50e128e8bae461257e399ab5de54a5cebe2a2d25ac7f9c21fef28d39a4a07558e3732aac8b12e8eddc9320776de7ecd2f7fdd9f1b77d9f53f99bf85b00eada970c83e3ef3b60d966d845e34f8cc3d500ec203c87bfc1faf89e9d6abaf425aeb745a537951c1e8a2e2baf27acb1898b4be8ac1a6a95e501140e5826aab85f6651f18b716f77980818de4150c09ae60d8e9d2e9745ca1d61a88d6555aaf6968a9a9a676d5856607947f700907faf071d545438e75b3cba6e3dec9f107fa7e2f1d77f08a6b0220fec3b938766060fec3b96d18c32ddf0165acab1776b41ceb601785d654274c687dc6cfdad7fd6a5fb78a8ed6faeb2b0216cd33fc429163800a1a7266128a5b214c1bb400d305450cecc73b05521f2803c0307109c317304f1cad917062511ce9091b383e76dc3062e9c96f120f383a01ab27e8251a5974f0cc13ab13a5d432a2ec38e1404ca1235d5dcc9c2cf096c1ce8a1a1b9cf4306d16689199e144069a9c160ca8514d480d10848fbc02a126186c88a3c120186913301ab4b4295a6ba10911376238486061a1c996150e1a60926167c0a7360e775c48cd0ce84346894a8c03701860c52a5395961a8c0c4053d4c9042323c900ad4ceb0a51449230c164058309af1c5098dc41cf262d7c9f89015cb6f0d23930131c02cc88f225a40b932b352fb45be400e34228096d7863d2230e02306966842954232e1ec04cc61b353b8e8625105066724a5c0026c4101d61810a8e511313b823091b1c9a04b2e08123b681638b00ac6b4d053e70e3098556e404917a335576a3d4d4c091b74260650699f0c4ce5b026c8833804602de76566b5f2e5001be712972e322e34c11371520c560d3c549965ba00b282961c2fdb86961c3e4a9d0990cb735b51443d4d8e8e2168a3d996366aa51909355294b21360015cca3c8d4d99b060b825120f81cc2fcd8823b1cf880125a1d0ec12c1f93a0c88168cc2374b8330a3ad5e73839a470ea608106e620230e80cc4c48cc61c1259358281462e680c20905844070456e34848438716918e43595266041685e24fb180084215e93229f96c44546dc12c9556707c84d761ce2443b0ce8d4c28e1393790d6911b38296980d14c09a31163e88bf4cc566d280525b22ca942011250e0861c9a0b11481892312967899a04f290488b42d191246c60e0b1164498b372e2ed093ae8028c8b099524c09400aba08c81a04670d5825ec447626cb18100d5862d09f28858e40812f9d5120d14f0422d88e9375c916560d9809ab414f062a62e0d504188cb6336e70ce92184f7f9c78bd9230ac70d202a7f4b639a3898c0b52a0bc4b76a4517a81adcc3b034e0af22bfef266587147d016411d7e1d007f67d644f8094342a65f1b411c43623e3afdc61541c0ccc82d7ca5aa5a8019c507f511d2c017064c1f0652421df890e44132c84b8729be17839e9c1c6a986d2a541d4a027b186d15b4650102658f6d7edad4de1658812b88d8a6645327aad4ca011b94e041a1fc421fd0a0040aa65007910cb2923225215c3a62858274702bad71e9a9216be4c209290d90080c943b6b22e1c8115bc4bdc1a7921c396775dc0d17b03199b3e34e0f04362b2e0002a1486f8d8a065853643a7a6d3db39306af0dc438ea5165f140888637106c883ca400e566ab139b024b242862020a2d6c7c052f755aecf880cdab8f134c00905d695970810c272568d256104bc9931f3ba4da03949cbab493f2a5159205d1041270d0a165e141a3515f38d4f89e545450e4091cff7c4afcac4d6ad3a792a34a6e054226fcb3471e9cadc9213e8939c147635fc63c098044553a3b9cbe8e0244da3f9582f8b835449a8807ce93f99c9729aaab97a643aa146488d80d53fd013c7038ccb08d1df82581b63a562ee86050d2564c6c147500c63728a74d6dd845ac1916294e61d21fb03f0fa632557404ece62e14f240149eb203d7006cccebcb91461c814226a0029cc0f1232b7002047de0027e61102f05d3ad0a1132553c403c2c677274585edce1a5b509c2254dda0a3c142008590fed3961a76912a5360176a07678466042010ccf8bdd932e0e9040d229dee9004e89bbf4c7c82e09251d404468120225490419e0c051808528c90c00902f9ea446496e241140cd2f83258e85e4832842523d5a41246a5a395f48e8608044498d4a3ac65cfa21298520d187808c78c8714736a0a4c5092bcdc891315074f80993d4e4081fd58ce1a04c3c12a3871116ac8e6c9a20ac61e482333bd430c844c64897af310a666ce86224881116454c88c40260e4ab81227bb24ca04db69e14993216e95164041b133008a1a600229688d021024764ec02221ecc218f863830041ea2b60dc1d0238f4c224141c8a22e42ca5412e2a3081183b41024831d620e0dc4980a8240102358415c203255c37ce4010828e0211f03440140fc00b9928642083c126c80fc90a482083c38360159cb14028997d40a47d624289be342cc20276b4ed672f4b8e851cd5cac61f511000921600ab5492c04d94778ba9a1b1f6a7207351b74bad04981cf51d3b095e6018ab434696e5a99a67f1862f2434ca11fbcdf0f1846a8260000880168a1d02c40dbb2430382b6a28c8f4e3e2610e1438a0f331f6796cee474387bab7126e6cf06e8e1a8079b1e6f8f34540fabd8c5d27204cc14a108b6019e3161b680593793c183140f0c40f00013018f22613cb638d8f169479f1d5676fc30e12183279e811d6598e4b23b47ca9a94e12833d311429c0e08b88e58938e1a6d74049083518e0672f448c841e23085a3108e0446e0d8e1e8e2b4aeb05ab06aa95ad7cc35e402c38bab0a01324e647ac8a290f1201b1b612cce98db58d85807b146626cc47e62a8585558a2443f8c8ca32a611d6b5198ae4a941ba394dc1894e5c6971b3788dcd82ae0933ea283711b7c6736d87edf59ae3fe94a7a91b640dbd16ac0e8281aa8791a4ddfd0a20e754e6bfd417bd003e80e9a83dea005d01a74003a83064063d056ba4a53695dd5ab12c086d6555654a7a85aa09a43d54653a9b91a21cab1cef31f577da8e25055e50295a82b114db42ff88af022d6b4d6bc2b11a51621e24a84060df6817173d6a5abac488cb21069adbb42302f2faeabac08b2d4bcbfa00fee61f85f37d87f2cf3df0fee2e8f67b8df0b391b1cc741f9bfb0afab7ddd2f1931c2180ecff85938c36c5ce19fddd76d43f9cf70704918f7dbe27e5b178e2d8ac1235fa2288ac1235ca10fe6b17082c48b07c60bfb57c2c2e11b7360f87d6eef2dc4e163353345ebae976b17f35edfc9aeaef57d0f19b4b078575794a8b4a84a684d45426baa115422b4d6e5191475a1d70beb0cfa2ad784a7a193d61a89befa70eafb728fdfc71feeff82ef07f2dfdb7f67f70d5e7d80d3e1d5872373e731eff5ab0f3478e1fcba70a8b5e685f167fbf3eb5e7df870f521038f17c7e398b3bd5c6baa9cd6541fb4a6f2a0d603cc958739d65a7bd09ad55703a420c7badecc8132e266392dfcb17d39eccd1c4805001898d65418ae3a8cdaa3437410d3ba459c63cf0a00065d71e872b561d495000b5c0960a51349e4d97066c2589334b811f6cb7b804a0ec4a0197190333df8156585213dd07a915434900115408400c8a28303350b0cc0138985123c3a38b70fc32f000e6ea4025d068c0a41c34d92033e596df10910e308dc0a192de4442b986c1039f3fef980851d9e5697422534d15853eac89793164ec0d0a30533c28d107c4a9df93240a65821e703690348d1b9044a3d420333f54dc08da2323b62a0d5bac2aa800701321a62ac6001a3b52e306a64a53eba8ecc701e0441c2e6018e007e7c8ed4a3134800c38be0ea525abc620d3b81892e2322524d541ea864e084662ac22024ab4f1db216d2d86c284afdc8490a38e55cb12e16150a33612c803726d4a553493e99584443ca0d37ae84531a05143e3874484bc40d91aded43c8d3678048173834d818708548052b9d0aa501c56984116aac953a3374c2001534e4cce4893856542ef8d15d9a4514c2b4410b305c24fca9627b614c201430b0c07ebc5320f5f161c8cc950ee7d48e2c286098b884e10b18286f46390240844f36c08835124e2c8a219deac39383e10ea7338eb0e0f8d871c3c8086578a64f56176471128762120f383a81aa2f561c4aa43933c0182f232ed1c8a28366da9cd13082591347701e8138514a2d23aace1e3b01683940060b051029c4143ad2d5c58c48890744f9b63a915041e22d839d153504a834025a069f5064a954024498360bb4c8ccd0ea1109556187079998a84093d38201350a86882e155288a0c2118c120304e123afa041962b3f5c989e40a1b41662431c0d06c1487d915e08f72cd09a8de534686953b446ea531d51cb2bae13f02ce1460c07092c2cf4c054621093237132010a61858306986448f2c09e1c8ac68840a1d306b9360e775c48794c402a430170e002a100821619252a310e58417901fe49079ccac422cb2a5395961a1d78e170408a1d8e4e753acb29ea64829189f448801a7740882ba3858356a675852822490808ca98820257a8375859563098f0caf1c40a8c2ebd406aa2287873859e4d5af83e0aa44658e60329ae6682cb165e3ae7adc053a192abc4972a1522049811e54b08974329a883d472b4316376a5e685768b1cb89111ee7ef0556952e3444968c31b13b32d311479801222802f9d08306966842954634690026c20ca0100a802ac01cc64bc5123be4076ea033b74e0173861090494999492c09a05d8988de0238022234c88213ac2029598a639670e688a7d3ab09a98c01d49d87a1408894f50c015440d8a04b2e08123b6998d043ad1c20591b6c811118075ada9b0074cd9b753c84c881206619d5068454e10a91b607b2c50d324e7a72a45d98d52530346ca88eac2c6e6a509013424c0ca0c32e1491d3a3b07ac98d0c284f9090836c4194023012e4af8682008951660bc0aabb52f17a80067189140814f1d308ab2868422372e32ce103124820bce02379218d0020129069b2e4e42a811e10a217da54c47968a0b282961c2fb3050ea81250c008337589460c3e4a9d099ce92a7e2258b000cc8b3106a2986a8b1c165139a6be32dedfcb22427f6648e99a9466a3296ef159641015eb4ac4a590ab1c1272b56dabc734e0ddf4e0845a6cede3458a0a4831f2e8424f9a5202007c1e710e6d7fa89e4e607d69d4f973a6939f00125b43a1b3480d1e6ac8a0f4d1fc8c9f231098a1c6846077ef6c456b28a4941ae3adc19059dea1e6464b082a22f6677b04ce490c2a983051a705282461f4c128438a392c58803203313123e8438a68a17b736e75570c924160a81a03256e4ea7c94841302265038a1801008ac34c0a84bcfd6011ece1411434888139786018a072c18a0a8c18945d555a50958109a17fd36aa6bc7d4da26aa130c00c210af4561b326545053a935085c1196c44546dc129d691285c0153fc6670debec00b9c96e439b2b3b370d4c70260137143b0ce8d4c286c30658a6c3defae20368c46b488b9815b24851618e0345a808d1c01456a000d68cb1e081992e217a2c55c949b351988acda401958680a4405a5c34954c4d30c2942011250e90e4c6d2a9352b7868fd2420c65204268e2c99a0a74c8f3c34b250604a31419f520810690b014450d6095e9e149841228c8c1d160248042294220811e282ec05106f5c5ca0275daddd1984094b0e8a458654c8b09952cc262c533cd080a2928c3c6e25ba08c81a04472d8d9910323c314b81050c42849dc8ce6411cb24a2ac814340413bab9c1690454e544529e0c030c107f4ccac4a0cfa13a5d091276408c0808d59962ca78310671448f41371488e0a2b3d02c011f4c94dcec9ba640b8b8616095c246b80f42cb8a2c56ad093818a980f542419aa6211566ec8320106a3ed8c5bac888400ca4d65d79a9c25319efe3889f1a5839e3448ae8059716602c30a272d704a3c726431f5c286286659d6194d645c900205f6fd1630c446c35873b5238dd20b6c655c7c1232e7354102e961024e0af22bf6e280960b4b6519a4f04482881577046d11c4410f9d2a7a02588489cba6ab3c5ecc191cc018704183244da41f34fa9c5813e1270c099902580b8d4104464a0b83444410c790988f4e2a06356f8d22518d71b15604013323b310638527012c1d54646b28aa5a8019c507555355fc980092193557469425dcd0805406217c49e0260326963231c202d387819450074d4019a14049213d568228f22019e4a5c3143ec5cb880803a030c3d388414f4e0e354c2d0eb4904082830b435c40541d4a027b18063c7a7de0807fbc02a4502242292819e0ec2cb0f3c4118929656f480081b2c7363f5012113985c584ea832b20de1658812b888c324b4220f25088ca8d910a17175c81e09319571e4f20764032030a8d4427aad4ca0102f48131e4031ca2c905038040a1fc0a3adddc6373ff5b1feb3136b6b58536923a1d109dce14b7864818f0ac9f4cff264bef4d3f96aa6fd5d2080609d69eeeae7a9393db73d4f3f6ceca8eaad95bb3ab2269a29e7f3b2b175b5345555644b7475591acb39a24ba45b64c3bdf18e8ac68ab9aecff2ad9fd9cd5b37fdc247baaa448a26337e5aced1f7def6639eeced93425e3aca94f3939b2e63751d47f726380b38a9efb3fb2e8c9cd92fd698f60fd7efb13e52d47792759b2bf59c7de55f1e4bbdde52ff9c9ba59cfb28b65aaaabdfc26df2287601545934d49d26f6faa9d6cd5366b4b6ed177ffdbf497e9e9d507561535c7affa32254d7fb2aceac0aafeb214cbb2fcece8476eaa6c56df7615f5beecede937dbd335abff662b96e448a6a957779aaa59d3b4aba9faf92ef95677798eb21e0c69d6b273efbf799aead8c78da60dacfde4dd54c5536c4dd697628a663d51f6937f9f6dcb8aa569a26756b5657dd9c9961545f2a3dfccaafacd7ef224d53465d5b29f0cac63e94d9f96242fcf322baaa29f6dd3d6ab5f4c51b35c60354d5e8e6967cd52dc2ce949322b499a252a9a62ffe3564d5681959726574fd29b3b2d3dc98e634e9f961d3d4fced134010c62d0ffd5f47791dda379b6fedc2a190c0998fb2ccb8daae8586e74244f31dd23e7bbdda778ee911549df43771acf400c61565eeecff2d69f6aa98a258ac02a92e67876542dc716fdad39825949d314c5913c4fb1257979ee2f6b6a96ad88fe727bdfc9f2dc3e4e6e1f18bcac5f44cdb29fe3c99a665a96690fdd9b07860356de7bca9a7d9364c98e5c357be816f73862e8b29efcf3942cf9388a6a1c0c5cd67fb6a4c9372beed67b534c770418b6ac1c3577caa6a44fc7b6554f5410062d2b3ba2a5e7646992e8e87befe2d8074396b5b724c9b69e244971b7be732e18b0aca82fcdf63c4d13fd6dda92a5badb59305c59d9f42c376bfab28ba4f79fdd82c1cada8eec2fbf699adb4ccdcd4b9d6e87a1ca6aa25bf43c153ddb76b2939fcada9e622b72516c4d51355374eca11b9ddd9febdbf566e0f77018a6ac232bb23b554f93f5643fd1543c8241ca4a9efc73fe3b577b3af2b66388b26ed41ccbf214c57144f766d5532bdfe5264d12fd7ca7a4799a5afdc9fe9665fb49aa65efe32fb58e9d54d1b46df9de7eb7a47f61fd9d9fa769fa9da6233996dc8595144fb1aba838aaede66da9b6b09628bbc9f4fb749729675352eb78aa66db7e5efefe51d54c47ad66fbcb315559b19f9b1d7d296ae57ff3f4ab261751f4aba268c5c2bad5f37fdec96df6141dd1b487ee50abd87f5afefe559645d97f9ee6c880d50aab58ee5464d9fff9d9c55e923fe62cb9bd58a9b072f1f42c6b6e3555b98876aea6d3e974e7560559a5b0a6e466d3ee53f6abe6d98a1bd49a9e5d353bebb9f9cf8d967e6c4b44db1adb127d6c8d6d89675b635b628fadb12dd16c6b6c4be4b18566b625ee3e569fd6b19b24a9ee9faae3f8b958b659a1b0b6bb97bd93ac28b65e157bd94381bc3ec6fd06772f4c6e57253dada7efdb54b71f459f929cab27ac6949aabe54cfb697a2d8b2a709682fd5f2fc9d569e8edbfca57a9a1fedac58f6d0dd9bddb732eef3f0f10e9ba15bd561c569eb925895b0b2e54f37abfe7f9aacfa3b7b5664375b6d5a51313d3d79b229ffeda98add4a134f4db59fbded28ebdbb4ec94ac32a9aa98aaa86aaaedd87bcb7be896e1338a15a69555c52f9e7d44cb76a3a719cfc04b9ee5bbf47d73b245c5d3f7d0bd83bd48c25a72d19bff9ba267d59d8aa3a596f354ede8e9d9ef53b3eca17b07fbbdc57134c06a84d554595615fbe9493e9625db7be876d3153dd5713c2bb2abca62556945777bfa3f7a94fda7efe7d943779cef85c9bdb566b6b5a354a6657ab2275a8e7e8f5ded8fac44e06a49eeb1fbcdcf74cba3c1ad1f0765d8d7b75834b8b54bc73876378edfc7f2f605a2d339b29ab4b6e948b66c99966869ee4d8ae558ee1e5621a4e51e51933449f12c45521d774996ed57d52feed49fa3d89ea3222b492bdb72df8a249b8e5b635b6b66261dab48eb177b3f59cf8a228aa25efd5690569eb69eb3bea7bc5551f3a71c583d5a3d29b2bb6dc97e8ea2e72c3f0b59395ab9e94fd5b362ca92bb6cf9b9f76e9b1a58355adbfe49b36c4fb4ecbfffd28f1b9015082bcbd9dd7651ed67aad3e9743addb8777b8fb2b81b597db0f6f1f776b3e627c9df6e51d4b135b69563dd1adb221b4333db3ac0ca83b57754153d3fcff1a7fe1ccd9ecc756c8d6dad996de9743add6e9fdd45ad18ad28f9d59644b7d9c77293e269feac3a58d59ff252f4dd8b5c144f75fe6ce89e7f0e9dce6a116ba56835799b9a1dede58976d5b7eaaad37dafd37d1f7f2b0eceae9222cad98f8a238ab23eefee5e183d8bbfe75f47d9eb031dad12ad243a9ee5b9f9fe65bb4db5a76745764bac10ada4d89e696fcfd297ac6f7f3e1fdfb1eab8b596632b4cac93d5a1b56c7d697a93ffddbf798a630fdd2f2ceeadb51c5b664912b2da60e56dff9b1c3f2ba2234a9a640fddaab80dad28fa5335e5bf64c7cef67fa2b12ab47adf53f28fedf8fbe6ea1e7ba8ca8015a1758fe8f6db73f44c4df134450dd616fde73fcf2ffe8d8ae569a219ac66299ead49967e9fa24fd1eff3f1b1148c15066b5bfe7d8e6d6755135551ae0e5ad9913c77caa6bc343b17fb2e8d95a095eda6798ea78a8ea2f855de7be88ecf0bd64da6a3398a67ab6edecfbf47726765c18aaa253f5bce7a15f527e959797eb9390eb10ab4aa9f971c3d4596dce2fe63db43cf6deed38755052bbb49b435d1dfbd48f6d69b3d74a76c5680d2b11ccbb44cd53daa63298ae2399a6cf7bf44c99d6eb5547b0fdd62acfeacbd244554654d933dbf68a2bb38d89f4cacfcace537557f7e52e4223fd13df6d02d9770567d56b62479e77d8fddb7aac851f3881505ebd8926929aaa427cfb43d47b1876ef81d47372b3eeb58a62dfb53534cd951dda6e9f718b4dab39e663fd1cf77f9bd47b9df3d74cb13ac6c2b9a6ddfe436515564fdeea17bf7f23efaacf4ac24aba6e72ffbb97dcbee3ef6d02d9a4aacf2ac67cb9a27cbaaa6c94b13ed1fcffa5b953dfba89aa87ab2db9b12ac1c4db738a2ad3a8e9d4dc57d67253dda5954444f3565d15f8a3d74efe2e299cf9c6c6ccb97e9b6d6726cf99d2fc72a3b5676d6dfd1f31c4f922c77ab8ee7efa1fb85d3d7c7b8c7b6c4750bcd6c6bb4aab3921d1d773b6e2e9a5b6b39743ab90d867be446c08aceca8ee4f7e629b2bbab6257c51eba7768a95acd59cfb634539ffa737b922cfdd943f7eec7c0719f7b87959c95454d5ffadd8a6567d3dfd3386bdf2647d14df6ef555f6ed30aceca8a6d2fbf58b2a5f94b6e8e61ac2258bbf959152545526c3fd93fd94337dbbb3b379b5fc57dc6eacd4af651dce2f9d154257f6aba59c9ae8afe6447b4a75bfd650bc1cacf92ffb6ab68bad57ff6df663ddb944d5bd18fe4f7fda70faca4a9f24db6ada9fe534ccfeec0fad9d12c3b9a7eb36fb52c399b758f244a966727d553ece356d7acde64d37244db2ea6bf77f454b3b2ea3f5bde4d53454b56fd669ab5fda37aa2e5de3c4549ce36b09a62cabf39b61ddd3d4dcf12cd6ab69eb7a4c8cd9da2e347c9336babf6ddd5fec93f9a59bd17f946377bb6ec989ae41eb362602d5594abe56fd3eec956657f997534c59444d1516d45d31c4bbec0facbd68f69cac93355c71325b3aae7998eec48f2912545b154605579a9aae399fa323d4773ab63d6f644798a7eb5ed6cdbc56d8a59cf726451d54c4dae7ab45413583b5a9aea296e93edbbff745b8539d57414c952dce23e49b52c55d5dc27e97929a6ddb442603db999b6e23f496f8e6a473d98356d55f3e4a5d9a6dc8fa8687e594551f4e43fcb543dbb7992630fdd7e47ee1c565ed63365cbf64445732c3d7b76f380b56d4791a368898ea73fc7d677594974a32247376fc7f254cfce65ddbf73344d4f161549b6fd7ccbca9a5d4549f654457224bda96a594d544c7949a6dbaba968965956969b27d9556e92a61596753cf738b2e9d89aa3597295ecdf0d87d5959545515265cbdd72346579db5a5959c9113d49b41d4571244d936dadaaac693fcb342559758fe3e8c7d68aca4a9edb9fe4c939df5d1cc7d66aca8aaaaafa4b4ff63f76be776b2565257fba59914dc73e8efcfb6f1565ddaaff652fd594732fb2ec3fb5a2e53fd5d2443f57b739f26f6afda249965d3c49b46cd38ffe52eb6e5394dd277a7e762ccbf3bfb09e6a6baabf93acf95d58452ea6a9dab63e657fcaf76f611d47f68b672f7dc9d97db69ed4caeef297e4fe7e735144593f6a4dd594e5e9587216edffab5ed49a72b4dc2dcaaabc455913f52cac9d64dbcf9624b94d91f3d3875a4fefc5cdb22cef2df945d3afb08a24ff9bece4e94d72efd2abb096a3688a263aa63b4d3d1f7d0a6b6b8e65d97b17cf91e4eae841ade4d9fb1ffdf9b7ffb4929b64db71abed2fdbb4fc28aceaf6e7688aace8b7dab29ed6ee5b72a727efe716f9f627acbde49e7756e4fc8fdbb326acaac98a7f5447734c4d92e59d56758be4398ebb253bc9a226a79565f9374bdfaa693a92e7d84b58513235f789929df7d4ff74d38a724ffe53f5a48ab6ac886a5a3bca77bbb7498a697a7293cdb4faef7d697296b35d2d4b16d39a96223bfa7db22c2ba69c5f5ac994a72adb7dd9fa93145512569625cf8d76d2f45bec246a69dde6dfdbf3f16cd391fde308eb6659b4b77cdc63caff28f24a2bc9b67ba79b4455f6ff9f525a55ff5112dd5b3d4792775484b53c51f3ff511ccfb6355973d22afe6deef1a3235a8adb976a08ebf7bd2ccb2f9e9f3cc5534d25ad2849b6a928a66cfbcf2eaa68a49545c75fb6eaf669cb479485b4fe93a7a6da729125dbdfaa8fd67eb69d45fde9515454d9d4d1ea47d2ff163dcd12154bb36cb48a2aab9edb97235b929e144f10d64ea6e679b67dfb9434cffec18aa26d7a969f35d196eda907ab4fcfdec59ea623db7a9265b4aa5b1dcdbfcb53fca2efbc83d5143de7edf764599eaca82e5acd3f9e9f2d55cfeeadb2a8a968ed68bbbb5892e76996694a72b0b6bcf5e5e6ff9f23ca96bb4cb472d29bbf8f9c24b7da961dd1aaa2df2cd9b654d5f4f7943db4f2d1ff8eb61c45473155cf0d567473bebda8aaa4888edc34b4aa6da9fa7134cf56fd5d25c9422b17fd39fe969f2ae75ffc845675b7234fcb123d3fbbbb066b6b6e93a3a4e7e4d89edb67b0faf17b951ddbed51f3f426066be9bbaafe6e8e26b95b4f8e83d66d7abf59727bb597db6405ad26f763c9c9ce4f9645cbf48275b3e2489a626b8e64273d6ac17a8afeefcdb98ab22537cf406bebcb7324d9b324396baa66056b4f5172b7dddc9df42a0b683d5bf3e4eae7aac98a7c977f56939fa8f9f9497e544545d2cfca51f3a3a54f51b124ff38f659559493685a927fe4256ff7a6603d5bb46d5154543d2f3bd9f2594996454995fca65a9adfec7b5611e5a8ba4b932dc97d8e7c82f53c7fcbf6b33c3f897e3dab4749729bbe54b76f4d36cf4aa6692bb269db374a96688a6735bf4aa626bac7f6fc1b3d255839df5c3dd3d634bfe8db3b2b596e56e5e5d99ae6eea4696715c52eaaad78967e34d193acb37235f5678ba263bbd32f6e91ceeacd164559b41cdbd3343d2fd9605f4a9e15d991557350b16ddbf4645b92b7aad8a6bed6ec5572ccf2ab6417bf674fcfb2c13e9257c5194bd21453921cd17d8a279a8e232a7af1f3df4b516579fa7f0fdd1e85cdd8d86033207ca6d3b1c1be2a38eb78a2e449961d6549b2157f1bc16ab224cb7e4efaf224d5d2ec556fd6966ff67bb114b7bacbd3a36e56b25551d524d1b6f49c145bb30a827393e856d17d8a292a8efb24535525c77644fff6e9d8fe2f92556d56dec9b6e527db53921dbdd9cd2f550face7efbeaba4cab6e4df9c25d533550eaca9e8b9dfa81f5b3135d12da661aad8ac9c64c7f2ec22697e9e8ea6a8a66acd7a6e92fb12f5a8599ee3f7a7899e15d9f5aad4ac6a177fdbaa5c1dd9d33cb9aad3a53b2f5569d6d11c4db5ef5d8a5beda548f6d02d8f635a5503eb68aa9f444b16f5e348b664efa13b1dc7aad0ac2adb3ddbbbc8fbd8fe911d7bea3ec7336be95374b3264a96242bb29e34b3fab6445b16fd67dbb6e63f4506d6fe39a98eedefa958728fb665d6f4937f8f5de5e93ebda8f21e8a03dd64550bacade8cb71dc6a59927f645514dd5245666d772bb264dbee8d9266c95b34ae4a81b5353767b9dfdbf4ad697a33dded71cc6a8a9c14f9888ae9b93749a262d6afb69e97bb1ccbf114d99474a02a81751477f949ee4bf51cbdca8ea73aa62accda4f93fbde929be5dbe4e569a50a81f5b3dcec9e6c53b1b3676fd7641ff0e79a54aac0acbba77da7ea49aa6d59b6a8ffafcbe71f9b233916a9fab272932dd1adaa1e355bce72b63c4fb1cacbfa79bad5126dfdd93947fbd94337dcef8dea4e5775c0ba4bb5fd6aab96a6c8db3d963a5d97dd9f4e27eeddeeb2fb2bcf39555d56b5dc251f4d9477ce7a7217c3bbf9b3953b45735471f9a36fb978b622f79b2dbb8fe138fe06546dd9673aa22a3996a2989ae2988e625ca56515d9111d39d9a2bd9be327cd2cabd945ae7aceaa6c9b96e65615a8c2b29a276992dd93e5488e7f2c7f0fddc0b8598ee3683a9d4e97ee765a7565445375a7e8b84d154dd3722c4b334dbf58b2bf1dc7afaa245b325065651dfbd8fa928b9c1ccdb44dcb35b3ad37784ca73bcf8aec76555556d4a32c99fabe4f533cf7d9aba8ac62c9f24d6e738be5264b54ac9ab27ab2f423dafefe772b8eecc7b135d696cd7d812a292b99723165ff173757cdbf3bcdc2c47c98e53867b873935551d6eecbb11cd5d424c7921c59d4c73c98c3c7753a9d2e0ad5a9b5ede3e9d5d6e427fb5bd44c7be88e63774bbe99a667fc67b7a432b58a9f8fa867f92fd96ea26c2ab635b615b6b566b6f5babc37a6d3e9743217b550955a53555545bfcddf9e665755f585d5ecdc54c5ad8ae868a6e427a95c585194a7be143baab2a3ef24d9c2499ee726c73d8ae27992a3989225d98e2a99b6a378aaa4498a24a9553cff57dbb1733f6ed3b37dd46a8ae4df28fbbbdaf2cf7256444595a47a92a829aa656aa2e82e4b12dd2d6ab6a8ca53763cf939f6509d4ea74bcf78069250a85858f71ecd8ff6f4f38d8ee6cead2d3d2551855ad36ef62e7a94abe8e979d9f6d0edd6b66bf9f7edca1d84c71ceca1c31ccfaa44542bac9f655bf47f32ddbd87ee1dec5315d67164fd2ecff49365df23bb7be83e5baa14d632ddde54f9e6e736c5d2c7ff2c9b7b86fbf30b8fb1bdae3a7e0fbfe5a702b5a2ad9992a6df2a67c754ece827cef9687a3255d56fa2b0f2ce76be59b69323674595eca13bf5b4a2ac2fd3d63cb73755efd97ec2ea5bf26fd6b7229ab2ede84913d65165d3adb2267a768f969dedb492dd24cff3243bef2df9d994d3caaa68f9772f479635b9d845201c93e9744038f6aa2a85aa8495255b143dd1adb65bdcdbf74debd959cffba992be6cd3df514debc8fa3efaf37bb41cc9d1936b6664a655fd25cab2e7f84d74a3dbec98d65114c7f68be3ee7d64c56fbe09505d5a4d6fee4db2dbab5d3dd54ec2ba4f91fd5ff4e8eea96a8eded25a9ea369b223b97fe9dbf68fb0fa163d53d3644bb29fe74ffb9ad9964e07e43f54fc425569e5e7ee623b8aff9fe9e7bda5b4b268ff27599a7c1cdb54654558cf9144d5d477d2ef1265cddd43b73a6915c9ce6ed17bee55b6fd240f611579d94db58f67dbc7d11cc71eba7b7de67197773ebedb2495a4b51dd5967ff4ff74eca1bb728e6179dc54915691f3b4f4a72992bef772f49056f4b71df568ca963f35477f3e5abd9a8ae97992fc77b5b3afcb7fbb72dba072b4aaa5587ad21c7dba559697a7badb62a81aad247a8eaa69a29c65bd49aabc87eef32c800a847514d5cffb99724fb63e2dbd4e37770efc75a1fa606577398ee647fff85b53344dd383d524bb289ebe8b7eb39c2453d364b47272444db3edbc3c51b2a3a7699a1dac6caaeed66c5b2e8a6c3fd16e9ae6a2f56ccbb13cbf17cd7e8e1cdde21b2a45ebc97bf9599445db9235b937cd720e1507ab39aa62cadbdefa123dff1ecb32d19aaa2d599a2aaa8ea6a9f28f9665896835bb789e24bacfb68fe9c972f3d05aa22c2b8e6a3ab6699992bf353758bdf8c7932c53defff7a32a9aa6a17514d94e92ac888aa82f517397855695b77c14ff589afd8b26df654968f55d55cdde72d42cfdf855558375e4a479fa8f9aa7df3dfdbf2c335851d69ba2789ee9e6a77a6e5e9618acbd6c7949a266dac791b7a9690e5ad54d96a928a6fbffcf498ef6d0dd9761b8d747312a41e22f7f698eadfa5b53645bf4822da2e8998e7b9ba54896a838a6a427476ea62cfa4d3e9a68dff18e7cb9ebff6fef19767381a6112a0bd6b41d45d6ec65e79e3cd9f3075a49cfd15d9e2acbcfcfd95304c6ada9bbf40c5505ebefdb3ccd6eaa66daaae56906d1e94c71ef360a68155bb54c517554b917d5162dbdefbb38743af96443f56755bfea51d314d5d22cdb3445fbc0b8359d2e6ed6e9c4bddb71f3289aa1f2b3fedd6e96444dd32ccbb41cff8643d567e57e1cd3af923d4dcb722cd914022a0a5692ed22da8a22fac5b1ff72e4b39aa53f45f68b7def6d9ee9ebf6769f892b8b6ba8f6acfda76d5a7a76a79bb39dede214aa09d6933d473e72f4ff132dc98df6d04d8a0750e9595b3445cb51f5e466c57e8aedb983a46354795672b325ca5b96454532dda9a8d3a56745766e547856b64dd5321dbfda5b11f5adf7706ffe3d5c60586a874a82b5f56dda92ead8459feefd4560dc5a581eaa3beb49a666da9227eabf1fc5967b33b8b5b6c59ac12df33c2bb2f35476d6cf5552355bf344d93225c9141e3be950d559c9b67fb11ddbf2ec69a97e332e9edfb5a48392dbdc657a8e2839a6aaa8a6272fd1ed5b1655fdc8921f7d61974ca73bb7dbdebb7d6e37f202aa39abca3dcad19645d3f26f74a768695b62dad6d896f8630bcd6c6bd5e9743a15f5017fee49d500959c9555fd3f457393a7bacdadfe386b6996e968b263cb929be42a9cf5e42389aa9e731645c72f8a3d74cfad1b7b3382b57fdf493eb62adac914e5bc87ee1f1cfbafdb5a33dbdae58e80eacd5a6e3625c9ee4bb3f466f9bf9b758f6a8b9e2a8b8e9bb3238a42b0eeb3fbdfc5d4b7bb8b632aaa56a8daac248992e9e6e617fb886ef23fb09a7c3c4bb145cdaf96ea59f683631cfd03d5743a719fbb7f37520e9503eb1f496ea6243aaafb34c9330d4da78b61a06ac6331009159bb5f46c4b727fb29fed7ea7ed9ab5a7db973c4d47d5a75d24bf9a755447d64c53f2643bab8e684fb38a7d3ccf5145cb334dcb9adca844ee6986438128c961140641c4503215490040013312003030241e8f074452c1a438673014000365a6708e4017c9439128876114c44010c420640001c00040083186ab5a0d05361e53843f9c10aee8bf507ca0caf01f49a5117dd4f12df92c5be91f602c8c582d998327c61fb9b79c3b9eb8fcc97426d0eace2b6c4b0c6e8f31d7bfbe6c3b080003f3c26eccf22662378b7d1dec57071fe1c879f4dc7bf38931bddc46ce2baa43acca2397114c47ffee4e950879eac623aa58349b6eb24c2951f99284bcef1a318b01a8ad417d2bb5f9347e16625e8c40452c1685321d83196456ee94180e58674d5aabd45bb7a2956867ad4c6dad2aabd7aca764c5d78a5899098f6eaccbcf7c3473a7edeb77d08e96c1729207632fc5c56bf2465e677d7a2bb8b0467eab7a62efba8ddc835e636b3e0d62d9a00c8d3a8c1ad488d922987cfa0943a96176158fa84f93cd27f8e671178a9ae3ff5036fb88df04460057985a851ed36cd34195982afc04f1306e51311e5a9542bd5661392b4787342bcf4a199da67daac0a8ac894c2d5a26d0df2d9572636bcaf0c6ac01de201595fba8160a1933795c2a10c518aa2d5ad2badad132aa4c6ec262548c8c64b0b302edddf77ced782babfa2e08d9888316e248e2ec9a6ee73ca2f53f2ea9c182a1e53e467a11fe209e851b8e97cd38c9608d91589ba16035f76e43675605c91468e2c29427fcf1700da2c32225d148ae96b19ebb747447ec2725309a2cad99da4e0c95b1a811b60cc555f189c135db6077ca6ba9a108821587af2838ea30065fc88c34b9896bfc4fc5b3c39483a8c26cbbfb461b967ec9010e494046d9e0b21151f578a992d05ddf026165182b8c0db0fdac9a5716f76505416b949e698532ee0fe56b57ba8d36151cd04a563d269a73eccde91d0831f86f2ac87b4b57d48518c2f021bd96ee814cbfc4ae8673525cf1d48302373d7aa79543a548c2b2de03b08f2d1bcc8b9a383659803612f590e09849972edebf867b1c143493246d615530fac1595de0a6d05b6fbb746dee7fced73e9c127102163a13ae9df3af9dabb32cb691b5a37773a68fe9a17b7001057d33752c7871d489d1d2c4477f9885c64cf78ee121b83c313d32b69115d8395c881bb42ff90952187e5a1095f95da0b2a11e2291d10ff84bf953604c3a303f6aa1e93300efe653ab3459372d9314c099139ae5b15d28a2b85767d3ab3cc47a92a502ce5e85156f4287ec1e3fe47fc339e31a06aa30b493016361c837b20ca5f3187637276cca8979941c713dd9c98a4e818a60184055c4df3bd4ab3c05abf8d2f5ee081c110d0395ab3c03793a97ac2f1d9bd344db48dda469cd7fb1eecb360e96585b42b658bd41f9fb2285a6c4bee2ebcfd915366d2bab6067802375715ced3abc9c8a1a1a54a4d714e07b063e3d3c0f6dd055820b434300b3a5c5f542cd937b91bb14a6894303f3e103fe51f34f2c9357173c84d471d0a78973aa183783a303a2a639249bd21099f70934d4ff7bdddf310825ab86c362971f32cc39644657888c142376c213dd0c88e3de4b6988ca4627062bb7b3a85a055435e59c011da66c8ce9e96826dffc7c2cdfc7864eadfb33e60de0f613b461415bf25653744642f59de1e747fd35cdbcf4b7ad040d2c9d6ccc2f5ef9a66098c5fc13b9ee04d812d8a7be58c72f9019431635e4f407683f2bf46c31ea5d22f172400055cf28b24543ce7dd14faec29a00fb4973497d5a2568a5de69490e8ef7fbe58b9378d44c29a85ecfefaf9234b4fb87f834ddf60a8b24dccad038e773b6f1231e1ac519d7146312d3112548ca7407d88c2326584c263a30876ccb444b031ee54ee721c346f2463dc217aa5c85fa92ea1bc76a4c97fbc110adc7f10db6be04003595e90e8d363c223fb47cfae3cf972a57171fb1c3a717d0802a1b5a99635e3aa48ad3566ae62c1b8e7de00362ff7d9cc3497ae5d8a7bde383fb6b7894c02ae8c878fbbbaa302b92a540512b165d4a1eb84aced63a9998293aee77ae7ac0b581901085351d9ce4e22d7d76bca8ed6990aadad1e1452da0852a246ee4ac2092d2f009203d07685b457e0f902419f84f03c17702d1d206751844e60e16f328002f04f0c5f1df2140430b19e7f1513ac3ad9be2268e84437c1b01d8df5b361bc5d59b7511e2eed772454728e59cc10169f02d882383e5593fbe6b30770c648a4244adc064761b6f4b88bdccb6ebd2996151191d74b2f30a0419643c3f00390113031698a67f8fe1186266ce87d1ca2980b8ad02cd82514b72af2356db35ab853ce916e0aacd254b954565ab2f97bff4707f4add083466b16b7aa92d070cdd5a95a3da058a86371d9cd945248010aa00dbc5a353b960c669aaa21081b153e0cd40570dd1fbd410c7fe3a0b33a4a01d91cba86cd100fa9273a51302f5bce5b602a78a234bc879c019a32338cc1dd1d7a683a110a4b8f1d80f877b7a5120124b5c1bcb6839314785700479c56043d3e9c427c2f638b9e4b5ddb2fe11c738575ec255fd0e79893062df3bdf3441ed339aae44d2fcabf561fdc647e83f7edcb8526d420f24419f2d66daa6aa01884f6affd91b4fdd83b02c5035dd95095a9b82f4075191b86e267de4f0461b88d2a37be567c53903b7e362928d90b1d6d8f02eb06619e4308f693dea4285dc98174e9004b234b24faf89cb408f0cc53ae55a2294c700c1b1bc63220bf7a6d3a99ccc0b370bcd742616d52e5a82786fb11741303e919c1a8d48f088020f9b836a873537c3969655076a36f2886dd1cd624b34c4a5a9ac2a8ab291f1d2d6bdc665d2890d382ded57eeaff726b3c658bc18662f1bac9a537f6313d19befc86f22909c9ff73958ae6989636167a17b94f8cb38fe4d782264ec5429f46304f5e41bcb41121a79ca165d6182a79e2471d97af22591f7e0222a4e1d6d0ee2ee59eca2c41f264e8e62f99578c1efc46c7bf1d470af457eaefaeda2931f9a9ea80db199f8508c0e75c31c92f41fb54c8514271175639b200336cb14650e0329161b86157654ea18429c7f8d289871eaf89fa18c0f70363675c4fca4dcf0e0694df42d09c1a637444104520f842584a3e975d09b1003463595ce3c4139fac1744d445ba6286934d890201488b3a77f7ea26315ae7bb907d460ba3a73b7f28d27ad56e1be974340dd4d7133372a78f544f72a1cf6b2078c3695c87c55b9ee0739d4e8be851d8c454359599157dce1fcf71aedad158365356c9d1507c5ddcf7fd768dc5a3558ec864ab0e2aeb87df0628dae5bb807cbc1507756d88a4b9eff5aa3fb168660ac1bea66c55171580fafaf2eb1ff7b10d94648b2e54aa1a6dce9540fd4b0cc86f32890968352204bcf7ec9340302d0f3332c7a540b6c3b40d2baa1a32c32fc4998a4aa5bb5b61261045bd4b6d458a3d192e019f1415527eedb876d09943708a7d4500dcf0655167f2d89d5a860cecd74012378caf1295f4108fc8ee90c5e238400a8ec041eca78ad587d677c85a9a78b624703fdb38de6accc1a5f2280f29168d841ca79bc4c1e6bfc8429eb4f4e34b08a71fcfda1071c83857952c8e108623c997e2c1466d3d37866166cae002aa6e6a4820b75d5b58ddb90467824f0e3186ad63966dc7b8ab77bf42807a7347068eea1c9a5a000174bc8f6e70fd370ad7f2b138d46f36449d19568783ca308f89305e21105e9f8225164c20422a89b0f05e14407a112fff8aa1cb00667f9f668614a91002288ffa6470a3def110216be3968655f7bd59bd2e62ced49b657f56c9964f2a6931e53c4445e228352229766ac9b2d48318c43404551651844eff83143b7890a8c63c53e2c29f3d82c7407619c1817d80140539e4396136734983429a1b2af7c89d2eae70a6aca260dd26790ba4030f6f38382c3361c58063ea0c050e393c8997587d4903d00919822b96400b4197e72639c8415ec18c3efc5d8c546e8ce5bda5bddc7d2897cc1791376c1eff23ed8ceeb01194844b70ba76e8c1238a96575f7136191c14ef4263b2c46a0793db2dee93527b7f1823d44d187510a5cb3d368acbf51231e265efc753788b8ad77893768ab5e751312a423f1e752922704a27f0777c13d4298d31d632cb933a399007fcfbc6569cf2c79eb640c8d9f9448fb5a6de382d58949727b20bc5e14acc71816f49063762ba12e6631f1d37f00351f0910db6e71d5233fe33670b52276c0d2cb56828017b7b0eba072db75177a138c6605afa378845280f46bd2ad28527ba9a481a9461a1c0440a7a1049c3202a8e84ffa0b5e5018d3537a10d3a3ad2db2050b25f91322ce5a5d712c6275c13aed7ea0780b62fd2e1ebfba9cad0a314c409deab2723d3185ed256720ad4cc7b3d6b9b251750061151362b310bcd56b0fa9894b9871f0ce6bb21b5abc8fa037dca83c1ad1deec20068d394557caa8b904fee8124c0448bb63aebdb2e34b001e61458c8227e501902989024d83dab078b2bfb2e88f9c78086f14f4b4ab33a8d6e9261906c9ed811eaaa41988fe94b51373313a06376e93a8abfa1ee4365bf6110611c68db867c7ceb90f30ce5341d2f92f9e81c6e5350cd45505119d230234f4077373b73fa0d99c12c03208b036b4676c66ea5f07195fb7bb2b02f684e088b404c0961b7ccb00ed3b9675cc13e9c24a57028d36fe576e668f72e2a59f12afabd8cbbe9e3c4b2d6ba7fcb4f1433f3dd2bf6f29fa7a693cda540dc2baafdf759c6c0c6ab7806991fa4f476efc6e7299d48432c5201cd6244090767f6c01a456eaf5d17d3c2a93b27b632e6bbce55419cbb8023e72ea9cdd2a7ac75b4eff0ee5c33c66031a3f20fee7c55571cc95c05b397b35028e091969998c9bbb3e33c570ef66039b13f2b8d0c77cffbf4e0ae8ad2532d29d95cff21b2be801d75af7523a1eb8f4410bf5f540e826f5c97969082f25b04d3131441b2ff0d280b06b8999ea3bee40943df725b4b2fa7ab326cbb6c467d2625bc0bacbd80c306c5a5f13843ea2c616aa45070de0a5c22d064b15f5cf1efaa46f6a4669d0a0a74314411f81085e2b43da132b423419fa2ee860f40aeac9e30295522df9a6c61ab8d25d58b4a63934e765a4bf974302d2b7387234f6c327af37603a336b980e7a6a87adfcaf7b71726f0c49e94394d21d220a2d77919437a1ec845a0e407f421b40e93b9832a84d6d4f0dfcac4db1bc2b320efb8635a3246212efe67dc9a12a62d9bef0f77a53bbbfb5ffbdb981f8cd295460ac84b89cfe1f321417700aa64e40518bd9a5a98f55b5ac83be17d2d676c89b84034262dfab2e8ed6626265acc5101ba6ede9d779744ea4f8b61f5ec9173b9000a702c029ef3738b8bf44a6262d47fb42a46a67e44c215ef044e80f1fb0f3e942dbb49a03ff64d2f74dfcfd5619c7070c8ba90d327482b394820b0e6f03e46a62b344f122254420809febb64adb6006a9d6247c98e3d096b7e3f0a19b79d1b200e4bd80f8b2995f22136999325b6469243244615bfc39cd18790137227c31d90e8fc06043a6a3ae4dbb9201407d5262ec9c864a540facf57cbc480daf17abbf0cf04fb2ab2d8e6fd31137d7eb223f5adc6a0b7d84cacaf2e0bc64e5e8019436f8f78c42a56d30d68f12bbd45162c5f90e48cded5c3d33c73003980621c9ae1326af022c7a6e8332d2cd93211a76978f5724d6cc5e573e87b61c19389b192409998ade5c11ab24e58a0d9bd061f33873717d68f91e5ac4a192bd760e3de4a8ebba59a26e51ff83eca43f6a72f4b8e6801239571030087c434ec917484c9eeae843359da8a033d5f4aa8aeed5e86725fdb3454fd7065230de65480dcbeb42f7014350561446e8f606189e3e1922913defed7fa4fde50a29b0c610a699ed3105f1970e5f092f0721cc638f5e6e2af75dc41c2dd501510178f8ee1a90e7b7e9f8e9bd35b17dd48be7c5eb162c24ea191223c5d0e697665f589c9ffbfde7fed1eefccc844c7be6d268e03e6497918d1cdd6cce1b2b113778e274088f5be5fa2f290fc8f5c3180833ca8aba364b8362289af1daf5176799123989517c513c6cf0891d8a111a0c52b86401210ef8b81b9337de1ae7ea87914c16c13c40bce9e17836beb21f8d74bce2e18acd0cc8abb9e91c9c214e57cb64a8b354b82244365c3428da9584823edfab43f5cf1f53d2530804bd2a2800d841a086aeb5682f2f1a2ce505fb0f12de66ad724b6f1fc7b4f28829716a1f22881ed6a44d4e829218128053f163acfda1d8fb6d3e1a6d1906bac4ba96ae709e937d17929dee24c3a03e94cb42716a0451b77d7ff1111ca50d711f639cd1148545e988cd67a595e0d304e5a8a29d502e763dcd1ac4d546e7eafbe927bcde2dfa6cf2bbdbd1db927561a9ac2ecaa628259c596c1465c0c3c3e4031fdf00108698eceff5ebacf6056a1425573438c03ef6dad24518a342b1cd8edd45c386c267922be47ca06877efc17fdc11790aa51ca5b34404fc608f52ce6f377f98c0764babd9f2582ea7b18c84352d1226f33c15877685a0f21bed1f60dc733817855e6dbc49b4a196048d4c73b9a4c295d7a62706e8d243df46448b045ba0e32709b83e5999420e97a6be52be47a819c52a972d057e6e00c2b8d1c9fb8fb32f590dde697b1cd44ca334e2f6341606ae9803a945bd02cde6c147c3ada9ad0da72517e7b664303931c009b6342e47e5cfb4d9134e3e9e15f96ea5d053826943c55b008aa20abe8d4660280c2ce66bc0a3548f0f1df65aa5f37e1de79f2817664ddc08f650916887a2e0bda033e2ce6b804e0dc993c7bd2138122a52aa284bb950420a6843e04c01f927308c896c7d44869597c44d590db9e5004e1f435f26567c53d26f44673e9497ca285d460f270d745cd7a5f948ccd35c17544539c127d52c742c700c4c486222cbf966729c3c20b4c4324a723964e304c549b42987e07b5f360555d8b220ec749bf2297912d737fdb5c405d34eace74e27588acc6958acd737188f7e0688da3dd0e0ac4e83c24f9cee5f5e67d06245d5d06d6581bb6cda985496c19e5a58c90a5779d23d5cfb15b83e4dd3574e0c85416063f40ff2e24ed3e3cedca316aed1a2aaf00564d0e6dd7a4fb92bc88cb2ca10fd08ee15c75bd56b1e1c2bdcdbe7142a083fa101f67e34f8746d04f55f6302324b2bf2fbfd4c412e503db925d431c8153fc8f866003230ee41337e0b1a0d8c4aeb46070ee699fff7642beb02663685946ba8d7733c81c48650e1b82bf36845d0cb449be3eb4ac28c7e2cce811d29ce3e4f7f85914684f8aeff8e3619fd0092e4c7678487632c1d7293a3819ba284c850f5567229ac24213b93844b0a1c10306d16de1238a04be1fae5dd4f11ba60a6e7c6f483b988651d83eaaae716425f1f0008d48421dbd5417c886b30e513baccbfe186f533a2aa0e6f4e95c6908976590606ec46a6795d0d2d95ef135389a850b52138cb98136f672471d332ea07d88cb402cb6363c88af4c8c56d1d4910a379f692acba651e0f7173c6509327de9afe1a301b910156a2f02640dbe4ad206e8788e28cc2a6394b8227933e0a7e779fbd252be41861b79d56d5b5ac203a6e4c75fe13680b390c1ad2d1ae099a74b4bb6fa5a35d695046603ada0d0d1d6d9dd4ab819a8e76773a1ded5483d2ef4f479b52f01f4ad4d146278c72951a1d144f813ff6a1ed0d863fa73adafd0daba31dc9504abb3ada5de64a59aca3e51d32c6c40094e419efc262eba8eefac57554b79f761dd509a81ad51caeb5ea375e2e1960479b43a14f1476b4e5a38a295608838f1ded1acfd1d1ae0a293bdaedcbec68b700e475b46db97b087f14b4f9d3febff082f178835dd9eb808eef49a87480e7dd0cd33effd0ce3fe1eb7f2f165602529fada025bf1716fd970ec773c82f9cf20d80b57b5e79d7c3de1be5dcc25f5f93c157a0977d80072d72e72caa43636f64f0710012856b25a7360ff47f23d4566e98614a75bbe15257547690860363675e6103a5b92b903f3e8041e4723addaae29e59990c3f3dc362233f9536b53101ff980ea088b8fa09548f11660d5fa17cfbd8177942fe61c9bde60fccff35b28a3720ff0f18755fc770f5a1d3ef02ec951d8c6b3981f535c33c5b3d8ff8608fb0f825f0eb0b523d4f907dac72a9fb83ff6745bec215fc9f1386eed7b02e7f68f65f0075bd27d1eb01c9b705d79a7f70ff57c8aa5f80fe3f61d2711ddbed934ecf6b109776f23d1e217c59e3a8fd03ef6f9d4cd53d88df739a5d6d9710b44484db47db2c6aa321db08d8e2bc96de1a3cd5d0a1f6eb8407d33aefc05d1f216a7f02e4f11f36659ee3fbbb24a7e13f8e57f3cc7bfc4239e78ca7ef1bf09efef9b49d8fe0f79f4d390ff8ffddc86cf213ffc52ce6fe3f509d39e1d7f3169c673ffe6dce21fff1655fce139cffd34dc3491246f140f67caa3bc3682462e22ff63fb411abf800d8d74b514719f3d6b333ad47e77b5c3f0d4a511afc1cab756906027f46d797773867c841dec5172b980fc0293f78a8d0fa95c13aae2d11845ef6a1f9dd041769b939a3958911946341edbf1be638c6030a880e668b41674da9f441b67b8acd5958c267351de03da716446547c36210fb24ab1c2fb29378ee377be43ed86efa1cdc21d88bb6d32e8f9785d3095bf8eaae9a2f42febb1302bcdb2e005ff26fccfb2391b7bd07ca9e51b94e80e7016d1174d0c40ebb1aaa37f1a1d92a5fcd3d0babb0c9667dbbc9d28b300e27fc9f5010cd0787bd6506d834a84275a2f7e85f2c0f077b1f77e8f70ca48a007a84499a78f75d65c0ee8c5de8234bfbad7ee6df6ab9300d210e3f5540ee841f2362a8dedc24740b6cde18e84ed5f95d78edbaf54f3be571e23f97a9d4227838d5cfe0eacbfd938337921b1d851791f582f9c303135064926ab7115ccd2670117aafb92657dab0a42e267d5ead7f7dcf2c86a4e4643357b804d4306d0a82d390f3aa7164c7c8cb03ceb0c176098abc2bce4201b1d3523b3d4dadb270dd1e4da1a64081ef94d08d824f64a5b4a13715ec2059d6d4f15132229cbbd6fe4ece02413c093d2ae9b6c708f25c3544b48193830793fdfc8eb33b2d1f7d07d03cd91acbd253c1b571491251d4dc23b02359910747c3ac42bac2872c88db81faa3ce5132b20dafab73488a4a55c41c1c0bd9583c498e013c5483d6c89b2e6894500f6b28002244f889f6b5328dacdddaf90116c79c7e2b28e6b9ae55b08e7790e61e6e4c92d28eb720f21c79979f8c811fb97c771114dceabd23dbbe7fe07d0a0a4f985b70d9f706bb379223afbd61bbefd77f6b45ca65dd6d4c95bb26b30a077cf535e6b73ef3ec471fddc3032cb93bd2a1e01679047a73c4ab9e39a8f1d975e9437cb6f140dbe31d2d3a914ff4b319fd820c38537d2ca01d3f6fc0450684d283823c2bb6883297911d9d50ce3856b3695b0db2744755b2837a231c670b2a3ebad94315cba46aee89e6723e81d370026e45e2266c2bd5823ed3b8ec602ee62bdf3a0e29cfd948b6c339a4cf381033189ac5dc123c003936fa40f49052e370a15f1310adffc484d56b8ac2fbb2a2515459747a82ba68fd353263f017e971780a04045584d02d44da03a9455a7f3549be215d327a4d9c9cde0a050c95c20a99525ca91407a912122b4ba895cf72058f5e812d58da2896ae92a557b34ca06839285bb0d02d30854bb972e9a4d22547bcec54bd1c600183471a86349431cd49997ed0325d6a664439f3ad67101134d08aa64cd21459d344889a7150354f750d5661c34ad9b49136a5b44db5b81958ddbc903780fa0698c06953381d9638891a679ec8f9ac72d09439589d5350e8b4c10f171fc48e6ab5c3267740d43b6482a730c55348f284d23c2b44cf47d58365b20781f02941f974903eddda6747fc1caa7ed0963f34f44f0301544f01b592400b34d0b10802860a82c8a0be3aa85d2114a0846648a1335a081e31045743d5caa132d1432514d18624baac89a089222e55d45216f5d6456dc268a7323a2a8d506a23007154591d552a8ffaf5d1d08d866320632816058f22d07daacabc0d55f3413f1473fddc96988b3c2789ce673ffa1d36216698b0d5f4fbb5157a1d061d9bcee327393314f73ec827e710c80cfe1966d8d381dae5b308c8d5a3a6ebe98319d1f057e1c1f88212073e7691b31b00af0a5031785c90dd81d56faf3346dc822871c7cb8a8f4a83eccdb5996f41dea84624ee6ae3787dff63bcda18e610b9b603c3597dfb1fabd9f2b384f20e9a7ad7d5fff834af7bfc8af4ea6d41777ad7f4d2cef4ab759e870a1497534d182a7123bf8e3a36e0bf3bc8fcc9dd43eff34214619e7aa558219903bc96d52d5729d24dc21dc6a066053dc768fa67fa467fa33afc16c142e95b07ccffa590cd84498a98e128974e9b4339e1c8ad0815f3f6d2282be9646f123863190ebb68303cd251c8a718bdf0dd6ac19587b93d6560de13d4c9e60586f03afe182dbe2d00965d9ae8e9e5b5758aabb22afa83ef386e2963ff13410c7b9225740cc5705c9f878c231ad374d7724e71c7fa34cff01dc2bcd19114549101dcdd8c7cfe8cf5638c19e62525b197f12762b702788cbc2e815905b2688080178449153bbc536b1a807a60d86150d4ba0461a7f337abde5203303a78381866186e3ccec8a0a3a323386c080361b0fdfd1fd24216fcfd17fca4a7871f01d0b615c65f3d0b2dc751d630f9cc7edcd3578ef3f117c11c1ed94a4846256dbd430582b3c587ec70b071a16c8e9aaf4464a490f0ed4cfe3170342357bf10c0e83f4ba94222453f2e91e4cafc04c5ba486840d3c0370629380f85a37cd35bd414c2b5d9e1662869ae7bd752d818d4e0790757e03a6758ab4d8f6d8f08381b389bea035925ffac7909b49606c8cc8e3734fddcd8ce8efa30c3c33b36e2583e5f1bd0b09161d8b4b624aa0743a2b92582886ba80366430394460f6718ea1a16c36bec8702e21f324f6f12985b890b05c57d81bbf33721bf19dc0f40c6509d15812db5f9f00443efc470259b1b4e07c81caa6b7560c1e690be949276d27b800cfee1bba8b544bd349afb713fa7f925c14f62a477b0797485a3b15d05608aae24b069d6d3cef44409a8022c4de630697744cf0f2d6251ea10d71b5c4386708b81b28c167615c5a04e989e06aa76e30d2bee6070e7bceffa2469e8673b1579b64ebf26700620b8fa199c2e4bb8c710481e64d8af019422aa6fd632922a44764c34b4bea9262e106b747e5864d06f97802e26176aa232fa11861820201e80b7145e249d20e4647ffc5772f9571a6716186aeb6af175e576d3eec68ba0532dddea9d01d5e4a6e0df624efa1e2c550de4c9d117e5885a569c985d74e47a9c47bf49985a2e504ec408e6437e73f1c379653d6124251ad8c675ea4a2a0122b292c89f101fe0428665fb2d644985b65d0d9da5710bdb17b9636b192455c5f31766d73f2b660c2558727e0e8ac4df160d437709b4ebffe670ff9154651cdbf8f027fa916f720b15ee70af4f048258b3d0000744404ac919def86da3e9ff10615c10383b960037488fdec3d31c70b33cd57a174ae3058fdb591ddd3b77d77d31a1a317149a3a532e988835d1c82feaaebb70135bc534c6a4cc98d029cf65ded5a416f1fc54d06328615204df8702c725534927cc45f97904e187adab9d191a22d5f9082a7df99d77bff435fcb3741b4c11837b1139a78a4884797f171c6def3caa6ce0bde13c76f3c3fcbbab869383565a3a8e5cac8071bd769561c812109dbf301d2c49c3dad06dfd575c7485d82f04f4ed675df049dd43d7b7c40b6851989e96b89ab1bbf193cbe536dd490b275933b0c1df0d3894096ab0dcab671976899103f3c10430b0312f7b12201a71b95dd113fde0d9b42ff93ac88a9f3fe1e468963ac7b57106902c0cdfb6865180eab430896c04c23396bd0dd7568342cdf1c075d232cf6f8a3b2d272815dea999e458064fd5bcdfdeb431cb733871f6950fb94ee8927def3471789c8599138f52141d314cc5011f637eed76fc36958d64094bbce42d63246f2d1b198082536d9f4870e008666167b6859692f24d2333ca61ccf8b9b5ec6bba54308b9362d673b6983621ae6fb0b6e36f9508eb8800dbaca93caf4ec044ce6b05bbfb980f1245e3df66d979925f1510acad238bd64cae88c401087894075a0f9ad541fb8e3a9974769f785120ce681d40957d03d37d7e1ffa52ba4514915f3c7801496803da7dea268463dafd5af986b9b63046aaaa21d0e8f28686ccab2c3094fab813b24d944562a38fba49722cd1748eea5212038e1405d9b4fa3f7af059079b6712f10573b4773012db5feb34c55924d9fe4504105ae0b40a039e260fe7014734058fb10e8af8e36b01e916fce9687ea93b39bd7738d02e0965f36f59e488fac31ac2e70cf5a71be9c471374adf830dd69edfe805444305bc12751aabc66bb5a63bdfc54ec81742c1ab5193e1890467c3793eaccb98694bd68500e2cd3a0958d6df54135d18f967b4451c3c976bfabecca57ac2c7a6413a387913777960c455ffe0874fdaf15681f13cc3f712a1118685a32dcee5bfc8ee63a04147d02df80b58739b57bce7afab4fa7ce5079e3266c8a960826785d3c4495a05c7c8d26193c85648a458ca0b4a6c8228f4e16b90697ad475524f5fe3a89be3f56bc5c33ee9fa5eaace52843173e81ac5de625a4ef331fe6b36952266a172505c67de697e9ae734b5f4cdca15e42b8db23a586d12c51b544419d3587a59327631e32ad491c327863090e7776d2e7cc2c5fbbdb3821452af833292739e14d642311b27e285772e99e78f2686382fcf20426b855bb8214035d0a187d11ef83f10728540e54999b9b735d01e3eae0a4b8b2ea7808ee05d8e16e8b76d61c19eeb41a9e67a64df508fc33e24fc6b0de9fc419d116b9fd41925ea5be15aaad30001cce701d78abff05906b81ae4757704ea5ae12ef325b0390573b62f0910755be074c2f438e1fb1176d32b5833c96f25c0372ef27ab28ee410d022b423d04e946c4270feff850e4d9c711b44e7e7f46a49dc2bb1fdd655aa56ca0ed56189352ac2901879e4ec7b384343714d43b6519e2f8e776c1ee4746fda8ffa3216b2cb9f5de70246f45c3aee32f6ebfd0dea473d88bb4c1d70ff52e5628bf76d1e0d9aeadeda462dfd00d96a4f1e8cefe701361ff908189cde14cdef7da7a9ec798a25d5c8d07fb366e71fdda7334eb7dfe8edddc1bd95309c41694dc7d6517aff3b7dd41ecb5fcbe0ebfcd9153142f0621c8dc4feef8386588dcb5e7470d81771d8e6a03c8a4006017692b5e3c5b06650325c933aab45b0836825d61abe89010e64b843e223796df599f5ecf50c2abb5f566cce081ec22b38b41b0dfcaa758b818be45d69d47ddb5e23a05f0989f4c23a020fe6b49d56c81dce13462e74e52d211dc23b9b5f64bcc1d4c5f743b581e1fb03fe0cb1907cb4dfa3f390d92e0b3453011c53d70a61bc989a73d4cab38dfdc612f3343dc04ce44fe811cf28787db2eecf5d19cbfb62853b9f0201d1dd07f32c9af0aeca7faa916b3001c05e5af2dee5f14f3167f4a0132ebe233d18f111334aef0faa5ac755b36a81ff9108aef84da05c27da2b91169d89187e171948817c309f170ff38e3ed8f59d76491217a3126e4408243574cebb113068907bfb0c84155f911965bb2978a0162f9941a0fbe7c067ce0ff5e896285d3f827d026267388762616777865df1eee0ca4401befc2a47a07e8b387a2db68c2ce987ea3443c8b39cd4e3b46308b67e9e8d927947009ab692380d5defc0b4863646bc4f234f2b96add45d0663bb3b09099be9d18f4916b783e9007e83b883ca3b43f00af2f4107fcc1e97b9bbeb196c22b73b15bd6e4ce7d11983eddd9424b3a928083c0a125e2dc9001f49b30a1c50c0ac6f92b5bb18a9bff39a49c63b7a52380545a5db1ea2079c28151282a4f8cac27b76ee2fbee16b8a9ea1939668743c466504219e839817e4edaaea4938fde9494388dac996111f17e0f56b47a28c98cfa861423d27597c488fcfc3608eb27f9dbba7e9705f0093ea0c96a28085dee742cab2841006554fda115591fb3dd7751f55f4aff4f09d6d14b153f7731926e59ca451a691cafb253b3745b598ee8ba2386cf5cac35a4aa0a3102d60e9c503c48141562f0cfafce9afbf8c605c67b45c8646f1cea985b47e28a4103e2cb40ae7e5316e4035662cfd049e4db8aee076d045bc3cbaee863d37f8095a0c8faa436e3eaa8b635e96fd26f5ab01eb3b96c2093ad2112c3ce97b6fa19a5a8fa375d16b0661440c42aed5df3dc927450ec6ebd4bd5fe8ea0bada96646cb964ddf0a38815b789942325bf07416a64dc56bc88877d0791dc9cde02076194fa2f59cf1057899a4aa26feefa5b90dd47362e8c303529546866ff8253f280d903eea37a460f4af954ca36ebc1feb592e8fbed1915a39fe70123fa44709eaf9e497c97525173718a0a95528c2f775c5a12c6c76e01a157f6b8b327919d0546b20b649b53340e07ee126fcc12466b82ae0d0c0c65535929d14dfd5ff8ccc2b2aea012d58fbf50a6b9d96817025c24db0246d4e303add08236b1a5b4ed21fb9f6d59fc6819c62ddb87f656f991b09a964d583612a9083d79afb50a1eba84dde5e9451cb91d3937eae71b07138a920666348375faec46a4bb038c08c481b2c01ae6bcdbf6b01120ba6edff876b9db471b79549a8376d2f1424fb0b86df8ca7bf80798b95149d9b353c4d11d99a5005469fc4dcefa4e0f27c95616f4af59ec29ca12859da1d6aa4e24f27f9a207e9966a5c5a9c60a0f87d184c8c433414562472256dfa8867d19b2778cad20d4452274961493bdcd32a8ca6682dd027254fc84bdb259402910e46e1eaccbc537d62424a20691804d0c4a7d892c7f5501045ac82772291a0e43875c7a9a07dffc0a2737476733b7d2ed946d4f69372dccb208de506e198a8684742cee0084cde1b8c04c0ebb3016ded9210d5e600d27286d45a08e04167ba822266c2f2146add01d86896015b736e9b38e77cf37f02ebcbeb9187980b953d6101cc37b8a3066ab117b0891d93b9738d972ed120901fce6b87fa7a5ea221f96fd7209c8958ea42c7316842467500382df7d663f9cae2bfce4f48d728f909f6b3a75a2313d0631abfd0c5ad36cabe6bf2646bbc8626046c4cb66bafbb2247207fc2e39e9903c35394120fae136f9c2f1e7306f49d4f7300559c4f7b3d50a172209a13231a78b2c54ac09f30188dffe7120832542bd8afff6f9a028e6f18927125b201dd144e7e70fac6953d0b32aa57d7623d5b315b35ade567f6d0e86dfc366d0a98319581c364f6d37a28d04d77ff39b700c92de32e87e8a014986f66ebf36e112b4a552a26be400ef0bc4942b9e9b629753fb8a9e45d1f11e6902a2bb103ae63762446c3caa02add8f3197d40b7867516863e122fe83ac22c9cd4a456335341e10ca141d09fbae085a6b3a74aeae6a1d22d159e38b48370d0299503d7805f666138078945bb20493a1beb80b778a3cf529d66aca5d98e48b34cda3a6541499aa42b737c4340dc46784cda2b01baece72485c260bf6e1b2dc1590912daeccb1a9e8cd35b738dfc79606bea1d4cfcb9f2380a9ade4c954ec307eee91b9492d68dfeaac45a38b59c8e620ab7a88c620181f534b14711bb96734ba88f89f8eb775fc0ae4d0e8615e7efd076e86b8362a981bbb9b870cced818c5d6835bcbcd274d8cdaa70c9631efdc98c4a9eadbe995b09359dae68645ab6b37ff9311ce49cfbd0c756981e8538375c66e3b3c1b388722ae4ad83f97faef4fc52fd27fdcb219be875667a244635f9ea8ea9e2070c21accd558b2a0b00e1fe2e98c1416a612af5500357536f4124aed864131b56e16d7ccd384d26f5485091bffb693aaf78eacfe9cac7411b6eec64a4c0ff18d21102719709047f5c41037c7fccb7dbd528029f832a0d5bf5cdb6135277e21c1ef225f6d484e102b2608faec7af94ada74ab7bd3e3011c9b18cfdaed2ce55ff9c4db5d224a54f6e7079e78b077d8d9b07d9e5c095a9d347ad795fb667a37200f8d8d2a0fc2263cb97019d6fc19d6152fa4b68f3b3a645080ad7bdd9970f75c47571617e8c6d19a9d1383dc0880a663e2a8ddcc73c9d9da1440df3eaad34ca9b099ba180ecd6b6ef59080ad072e1a97cad3804c11eeca2868b2602612651fed1ac81752363ec2e0098732efce178110159124ff885aba694d81ec688124bdb71d3facc4b6997190c75e9c7bf09e3cf2cd576f3042ab0f60b3f2bdf18a2b4fb336fd0aabb3eeb8c8a88ae6ca1de8ed7bbfb5748f95ff64959b073faf27e51d737ad88bdb1b1f47fb1eb4d9ef1028c65bb07d4f6782115a1fd23a93d9eb4993cf4ddd955fb6a7378cc95081a6d9eea503ca48b022a23a5ccd5bee245ba031835376ed1dd5f54bb46828c18a50e15138240d5018f51e3e72b950bf614451a03f10eb5e95f06214db2541bcd3f0fe8695d6bca618fe7cf90e076395f5c84dd578a60356c80d4ae4d1660af45a41a9b3a12e256048ea8b2021987002c51149d12dcfaaeae761c203356c50b92bff3dd509daf8b450617f8990c63f79c3de3689d0876989a3750f94d86314055fa6fd31c98229e79d47cca2bc521dc642d738172fc820aa7d252957e4e54e48f86c539b415e6d1d140af99b56e7366829c4bff56903b742ddda107ff8f3d2251de4452a0a75f0dc3792a1ae3bea92d6a14802d944b92e120912d21b3d0cfaba12eda0eb60add2f1a92a3318abd9e1baea334943f436d60b511e4ce0d4383f6baceb3312f2902406a429d5389b197fecd3e7f36bfbe4069ac993163fa4d3e095c0fe7456de6a47a21ab4a528eafe982e48861536cefbf5537ae66bb73d991a904921a9a132163678e5cfbdd3b22d81fe7a2ad2e59e95722b371008fd386aa5946f823cbda125da6b80bf61795503b3e4a1fbea0a55fd4201ef42e0f6a38a3c1e779695f844c7d38cff78ec933a27ec17a13623fad8693c5e3d92ee0b23b35366e1cccbd5ce6bb25f13a39924333aefdc15118dcb6be833b9ed315d8496c946ec621de82fb13d354d5690b239feb072b47d573085c3b660f186dbc6e1decf6c21e9f2be46664d0a4e142457b39335f13c250c1771a000af92147b0b11bc7d07881a0881662994dd8a4495006968abb624df6321eb3cb854d022d9acfa27961b4498a5d89152f244a600a5d60d1071763d4c12b9aa452bba23ee589633a703a912c92ee03b29cafe6f504f8bb2b90bd138286006b0b0e262d87be82db5f5efffba9c2d24545935f429586ee048cf7ca2ae0730a6e13ce56d4ee5f722709c76aa75a00fb472313b0050f287c8b28c0cbbad0306beed8471e7a8e23e62f7195213e90bd18b5c127571c189c55456513606b3237149124a4cf91719a0859fd5a1d6751580e03d1899ede85c027f4f0761ff9c8f97119e5613c1548f005d3406e80118eadcf5154541290f3e9892db6c56df0d58a673cb7003a3fc5f65d1d5a562afc7ae612fc5b0b8e37225206ba564a498541f7b3c0f974255e3754a7de423fded7220517b88db0621597b3216b05d74afae4116d1ce00c4e0f42996191feab770259d5bdc81c29884cf96e7f4aa8d3fc51effe796a26010acd0f2ece258aedc1293a7e5bffd7098a220f9c7c2252f6145a7fbbd0b829f4eb54774e322d88f44dc23fceb3f111a231d7e3e68e497fe7525fd7415e93ac79d3a7be89a3550d0955272a577c37196cbf5bb93f34b866d0a122608e325be9c0fad12610a75e88f6197a7016e59604211222b64f84efa0419169c5a51ff0bb7688f379845b009f32613f9e170028d6e14e32f596f23a6274186d0c06084a82e68035ef7a18682e893b027e79172bfdfe4384857226e3df3caa83e24897879a5033085b69ee410ee238b260e827dedd52777a76910b8d0ffa300729ab74a6bb185cfa446fd65fef82001dc688f803ac02d6de04077c504e14423d6010ef13270a8662d83828e383ff50819c025c0f4ff41ad3ea0a502b0132787a1d9e1448b5784e215bed4f794c8086b4cc59fed6c57108c85f4f82ec38c1ee40cd27c4838f9465d7c7238a121acb7c60cf0c36429efba650eb51eb114de4f1cd1bd3be223cf2a02eb9d339e5b342f00d65ddbdda0937e969ca097f3408ce2778c0b7c507522e791d79274cf8f5371c107814dc87284e67c684067833c8279e56f0ade412f60eddd8cbd59c752d7eb48beefae5a145791fb1f03766b62f089118e39faf76b964b43c3fc02dca6b27b1e0feb3673752ff06e0a7c884f9fd7b5c9f46028be1624ebbfedc53f3d22f08ab426b8de16fcf18d43286e79b3787a6b05bc9cfd4e0ea15682777f95c4430157b9570caac6456a3e3036c8034508032860e372fe592bf4e3538a30f05f9f9cf2baddce0e724007b0ff56682a0643eb3accbdaab8595d7c80867d142a155b46ddb15e8f90b43c7bf70c00d87e19114f823e7ce2311340f7836d559515098012f17e70884e1d0027df7783345291bfffca50b89e205f7fb3186c6fbf2bc6909d8c87f39678ce69e0708ea79f3cd889639740769ab22e01e14f77fe8854bcacd17c18ed1c81af6fa847a4706608f0c91f79beabed33ebaa1c8c1e7a38e2f0c8c7ff54def00e9468022515749f69d5d413259b7e3d61ee8c6f8ea65e9cfeb4fb3bd9c8639cc7cfc1ba9eb6af43a4a1033d276491c80502680a7d2fe2468611d6cce664c06893a50f926b20e21d2ed7f996aa5c15ed7c4594d499cc7e52c9cb6d2c8e08eb9cd15fedc1b8e7bec8c7e75c7a910488f8decbc0ab66e429da40d723dfc432b7bede2b2849da64ccc2ad4a2f9a2c15cb971b9924d41de3be2de463ee54122fb7d863047d5388b4c1678582b64ec9a754fd9c94f003aae95b1ee40df9c187515b8fddc2ee79f7ccac1f8cffd9ac452dc988d3549173f38fe583f9058c2c27e9dc763f6e315d441cb2b490fe30c8f7e99a8b57a47e81b44ea10fc85384993d1a0ee688582e924e0823fd7b6c4c4f755e92681f7d899cb698725a98d3e5bfeb24315cc8d54a64be230ef9064d44ba7d708b492d852c6be6d625696606a6716b080c81a20a198ad31c81a3cf1a4e0fc85f235e51b51b6d005072b56ef98eb15c9f648a3ea743f49568231b4773beb1cbbbf411e6cbeedcec347dd785d07db9aa817c982eec722eb2c1869f9576591a64782f9461c76cec636b63ada0549bcf8eee2396b7c89783e5c94430a265cb36dab025c2fd2b976c58ac5a660da34615db4df9090f21098d7ad251ed901d166980c950de4b61f42f5d2131fdd658704adc4233ca1439c6da48cf7e169adf009bb17b0ee72010456ab3f5670406ad88682bcf2f2ae30d3397522c380fe15a7979e238761d98715b5cb31c3ce254be2256fda2b27a99dcf75dc2e5d20c221b810a6ebd1201b509b153f3bd9ec928a4c4638ca67527b7288eb3a14a231890ba1b62f33ee17947e622cec2061ff6060bcfd60a232b3c66d662b81537db32fe408f078fbbbec7a1fc0d1d1a93e9dc381e380442389220014007c78f2dd7d257598ac810b9027c2b0d85061f086262c41fa712b7009ae1bc9967b0539138e237b31dfabf5fd2092883d45c5f7565c7160b13a533ca90edc61bbcf5d9810c59ccc8e93d62160eafa1a754e46d21dbf269f311e311e29eb56bc4087bada2f897658a30e3cbfc3617a0462a85eee0a00c4cbf3586a5465bc7f9ae2ee86fa060ebe6354515ea8420cd036aa2c10efcc9cd24a4396b27f861afaeee03271a1fdee2f1053eafc441fc09454a480cb01b5704f4e81da7080f209cfc85751a30203e33fa85a8f86d4500fb99ee51e5be6919a0d3b7c74b5e7551b8bd3d1d2e8938604e6a826f2acae255acf2a2c82cd0a7ba1e1a90ab1e40770b2c6aad4d8d5bdaf604292fa648add4f1a17a572d7a7abd5cb0f3419d6deb79cb0e7e3584fe7d50c40629bf2c486dafc75f2ad14be40920bea3d4c545882311a74f818b817736234e61041353944b1199177f7d3974269ba3a7bc12cb1b1f02f13133399154d1e2f4bd721cf27615e3b6ee7baf58fa6d8c2d42f4846e5aa41997b8086b865d4e188481e78211d27e488e0dc3f1942116ce7023c144e0ea59231759032960bc58e36df29c8b96190f226b644ce1b91b8ee9efe082991363ece1950d19158888654777800ff8926a09b23bc2ab50d58c23f22de5219567682fc6e49852fd563fe4b89f8c1eabea79ecba36aa32669014f76b4f57bd12a0c6c5da62bc68cfbbee2a8186fb24e7aa94ef6f61e782ede6f5f3dbd7c4dcf7a29d73de5ddf9ab4bdd23e72eeb8ec1863404f912944831dab19c1c76fb6e7c7e09f9efa2b432641f5333d10e4c766ef7266e1cc793a13b380e5684e389031949e98bbb9a47baed582c2b1530c5093e54c4e956565fd1b532bdbba4b3f5627b8ae19dd51a350d5f823d9600c97e87ddb20d89cf858e2219b0411691260499d632d753a0a7594f2719fceb73940ab0417cd92a241a9be3e9741fe25d2533be3321fe80c5283fde322dec46996784f692dcad9e420b66ed5f0aed9618704fe7d45eeef9f16ec30c5c345cce1bb3db74f2ba176697e4ff91713ed0d0ce7083ae1e6072fd1b9d562eafb6f32c8a1c8fdc11c5cf5856415274d9d8c5962547c59fb1011080324739a63915fc7fde00c91fd966451c31e984854de507865fd62134cd5ba22f62fddce95c88177d0d6e7ec5c1aa5dc9835d2ee8c375458a4e8ea73eaf1ec808f6768f86774db527826cba9bfaf5d50ba1ecf82facc06ebbfbf805451e423db3dc70d40aa2cd0f533bb9279a354dd16d0e8bdd0d17608e91a18d12da9da8ad054276b0793aeac6efbf75a63189678ffe7daa2e20f227a796ffd8f0b2c96701dfa5b479c106f5545d3a25c7c5996bcbb3e0f8a8266ca4304ed382d90ba6219424644869bdf825f6c61449bee05510179882da60a3e3d8003ebc809a36c31aa010e7288d85e8f17266072a91c867a46573b33e4818f17c7b70c850de6fb1bf630744836eb5238be89b2d68b01b29e54f04aa897b26585dc1ba96b21e1fd7798cf0114ce8a5ba75d86833160e659ff902bec0644224af1c5eac946eeaca7c860622e8d26973dfaa1e7d38b1c31737708373412485bd49dcd7a70924dd5deb3b9e07862618b5e01802fc1a1d4dbc5ec4a9d4789cbd94e21660cc1ce91cbdc3b9df1205c4e86f3542bd45de58f43e7c29073f0c64065aee3c6f600e4df6c0ea19c3751be07aa3ba6ae09fd3b502e01aad2229542cea8889ae185ab55021047b3db06d23645890f2f86decf6778ebe75c00749652b758d56d5119b9a590edb0efabd91e724eff8672dfefd2da391f8449f60a00bc7f7d0f86637ac8309cef7e92ef48bc616a793dbdeec256638edfcda78cf4022c01b1308d29683fb730b4bc123ea0c1795edae7caadfefea9adaf557017dec2ef0b9d21aa2be868f1c0b9b6564f1d783b09a50a5d69b17271f0620e5f0b86da19290ac65cf3ada99096e338c0df008323990b40124a91f97df45386f942567897172d1464f4d35fb46575d1eea64b5b7674d77fc7ea9667b2a47b71451888f6d649fd052781a091139e71a7bb67992551afe56535e9c90b8522e2031295e4f06329731af0a453ffd8ed36162dffc4f007500f176a46abea4f0f775cbcf3c23adc7b172a822a97adc359de64ca83b72969e91dd955f34ae11157511a6333cf07e8e42ef5144da9b9dea7849b21182bf2b091146f3a757accaf2f8222b31347484e6e93e12b23f95b0f7b2c0be55e43462b80cc88a74d0c761dcd539c08c2bc10ba7d6929628f1a992e73bc9cda25efd63d1f545482679f4a19417698a2c07aa8e9f975118424e5b0926301937412e4a8e9c7fb42fd86d8e6b662b213819297706b384107036ba9dfd5552c2474f0cb955330c35700b4ef26a4c50308949f1ea559d61174edf21f0b0718adb5c8fa4980308cb7b980af1f6c49b26272ddfca8e7408fde209d8c6e89293f05473973d861e0dc7cb379645e252fc9bfc75f3c4374c9e209760f207585d4b8adde19bc8d3ab04a605a3d57a272cf1ca00fd4b3c3bef89c2a5b386906f60e57f4b5338c4fa1941ee635093d2082059b3076ed61c4095ed1201eb6d7b6ec2d1c8c800c7183139cc4d6acc94f4f81c143a2ce67b4c8ddee12bedc18711ad6d2c1daafc971424bf1d661d9aaa2a581dd15ee807c25000291e0336f1301216e45d9ba104f5d67940455ab0f9a155158d21b080d4e00dc065154d0cb1aaebccfba66295ee38dda5df719a2c57e93b8918e4e06ae81cd15844adc2bcea50c56e1aac9735d47c52c8471557ac121c339213f1e46886d9fc70fb89637d68167fc5c291f55e3d95e8f524840a9a42d092867162b4e43a8a8c7eb3a34d4563c60bbee32ad3d8f949271cfd566cd05ce67e4a603d27713572d31b3b569fcc7da62c43d87a442a1458b5a3351c2940a7b0132936a2ec98635ad525a7c21994944cf6ebcbcdb11c8b22ba7a9779b9e8da0aaaf710dc6e833f5392ee03454ab6a793552d72a29c2f337ce268104f477e3f7ce2d00554f50062e710d8a17825734ab8a36826a9189b286df9ecdcbb2859ae94556ccbc46b326188ae7a06d90a0c43391f05bfa46acb0b048e18a38b9b8fe8ac82a64ef20d6261311f5e371ba9dc3d3af7c123e7723829ad777c46cdff17710ff97a73bcc0c5aef2d712771efb8f6fce1aa14f012231d2ce3c1d776871acb64151a8e13e4e3c7177565177b93589be8ccf52c923b05df9e14a54bed6e649d23ad816b1eb7628aaef4ad14f9b9d3ef33b65d4d74116f9bffd8b2eb84163bf520922e129b1d65a6a9174a5fe908b7210473bc33df71be0673f0f6735b7420851617e86d52de9fdcd456fa77bf0832b6a700f6d1e8680bea783cd1ce5b9b6c6a996cdfd7bca918ff09b18dc2d8b2613a082a5643e1fbd6163e5b3b9ab40a791505e9a48adb8867056ef467ed812b3fe9ef67692ee91f3fccd7273a62a6d87c8b96ed706383520c146b9e5f9881174c00c2d38ff88d2bef392f355c94471ec50dfe28c434de859327a9ea4c83461930eda775534a2da0aa6c8f362fdc1fa5b2f787a094b439f7308aa0b3d66339cad12b8d5850b4d67effe3f864ad81b2f7a4662520764f167eed725bf69307154505a9b2c7cff9e3ed94522ad51f2582f0cda523355448bd8fb0f47f30dd0df6fe4034e77690ce83b275f7ef72cd9863c829ac4a68e91078d42d7cbf45e91379f315a9de42e899d76408a023d22913c93655acf698a6a57bf7e842548eb0e7d19fa75eb064d2908ca6ab8bde14b2a64bd748585a0852e52d6e5caff02d557a5b8f11296f52067f6671191c293649b25e74483394cb8dd7b560e1ecb50bc926a462b57b5a9b69f970cb7227f7b480b2657ebd9f922bfccea68218f09744ffced9dc5d6e02797b5c3a6d8b6f304550eeb37cdd00baf23d6ed1067cc3fb13967c27eba383a87d55ac6af9e56f3ef5e313e5f3403e257cd94223882d7e645f17739909a40283e51a0dd51c1ea93fca96bdb84081abec4d7bbbd72f03614b5a71781ed876029ab07a6d74974498776ab9ef8e325f7f91433ebefa6bae7605ba1f8dbc7c14f248797245d7baaa40ca8bbdf8e25d4921e814abb2e19304c80cfdb3d35ccf69e863a0a46f4c64578600c1bea2349e20923de9165cf2d372d8eab6676bba3d2454ba3a3e2b782fb8c1e5bd6cca5c7e231e68c13d379c9b18d3b6987c9522bceb35dac42c81788e4387b1bff77444809c275f4db900aeb297d4a8b16732ea4f5629e44f7cdbcea50e77dfe5fe1282778196c4b62a0cb11ace66de7f1eb1308189d91a7fba54ac33240e27ea0d87b70354f9bdecb9d39face85c11faeebfe306c3d6d86b79c6e1ebe3e3f42e1b04981a9664979164fcdd022909dcf696acf35b31c4519198f4e7917c15986b6d927da77d49145a2dd288e827f88d30fec824d422e4e9488d3d4c02661b19ac192fc1583508a232ee9923be68d2aa2ed081f21c6dc1f781b39bfe10abe650bfe53cf1563f43d770db0b4b3079a40d251b2b60b1561f9144a1ee82f63dc22976312db6806ae78b23b9f5e45031f2a0535520ed61001f6d72e3f56a4609f6b0600e37988858ca60baf5d04de8c92b046808ace57f629167d7e92dda82c1119c34a8b0f646248efa42addc86f2a2fc3950dc57d1ffaae4c5d528902158c9b877a4440f4aeee4d1910848847de10401d2b8303c20340cde53a6f516e98e5b742fe1d704b2fcc382100cc3fc9c5036cccc621d5428677c7670de632596d84a69399d0f23f46029b5bce7a4b6b756cd7d1a2487e1fea5152ff257018c7ebf54d9ee47bb71353fe88f54a29cc0c02259a0c6c7f9772b8db16af897ac4cdc4e7b611d0d63c880e1157887160700c2b04ea818664d9c9a359d8618d1066b26cee358057be26635419fb037ae62bb3bbae7efba0e9b62e8c63c2c0643e65b59c4219767eacb4bf33dae0e7bdc279430c62d4f0566d77b393b52ca1db7914d8d3b37263ae8fef221f5da662b17d89d06ffbc882e50d6cb4d9a0f35cf614c63e2a87b33739729dc514ae967783d37f5c29e2ff814308d094fd378bafdf900708b8d6f9701b6bb85f55517af1fb68fb9203b0cfd1473a6206f3b0b2a5cb2a2ef0a3ef616f66b772847f35124e474aeea78b720511fc97309cf97a05f9fdd1fc8086e57d747ed1f023f7b18c9c6138b701add369628746a109e42e765ccc1b9207c4e664ea5f9c39dbc5fedee8e12f10b0ef800e31cbc38f3bfaee211c1f1f34a1e54b37684102c5a6022ebc045f0c3330b026c301000000000000000070f1add9b77183989da494eca42925408394524a29259960310034d77e471b10349e10e9c40aa70c6b0c1f0c8d3541b69ad0208349dfa9add3ee34e2511a63308a5df709717297652f051a62308ba9ba133a8fb24f2a1a61309f4ee9d7e45c0f553118ccd529e9d264e28f591e4bb62e697cc134fb245526c493c9f1545e308531b326ca93f283d3a3c7491d34ba607af7e495334105d9f1a1c105d3e9b86e7237df82c9c9f1644b28a5828945430b26f5a871a91ef6ee940573ca397d9c681e972e8f05f3376934f46287e91c5dc1e47359b9c7c37cf3b582792dcf478a3dd94bd72a98346133bc77b54f788e0a0697db278fa92ff9b9a660ca964c3e6154a5640bcb460b405034a4609e91b3f29e4451309f944f175c2f4f9a0e0553df8a296b0b4dd61a9f607e3dedd959779bbc9e130ca3f4c47bed523cb626982a6556f27495e3932f1aa0c10493acb49de76769da231a4b3086e75b9813e20927751a4a30a9e9aeaf858a574f9246128c79e99c384facb4a29a20c138e364924a61a74fd2ff08065d9a3423d64345d3311a46307b999ccae6647fb118e677f2793aa1164f9c1231cc647f722693d28b762695255a00198649e7937aaeadcbd467b2c23079268f7a3f1de749f36098e4b2099583ce911ded92ad0282fd020830ae9c46b442a8dce6fe8b4f07df50353d7672f185a972d58608d9d01f7d2f0c4e1095467430d7277c78612685a5285f1ef3efe65d98e4c6eb899e4a79e75517e6dd9799f1732798281766959793f2e44ae72fe2c238b7a2de3341bc2ebd5b989d9c33b93b6fa93e1db3854e50a1945e7eeb662d00a985b92b657c1627b4306893b217e3893d6a3f0e6e16a507882c4062b1134713442fc7f5e84ab67ef03ab841c6292b45c6d1713d78fc38ed031058185b54d7d68dbd87920ece0ff4c131818d316cfce007193acc0e14d818c346da8183043fe8f165a8c0c61836be8c1ce70536c6b0f18327818d316cf4f862328e8e3b2b80bcc270c1d533a97abe556d3380b8c2e04df09c74b474f2d9a515a64e132a3f8827c9c78e05105618ffe2494fd2b99c4cfecf2a36d318b32f4d2d6b11d527ff93d49d4a418d6c630c1e931da7071055189c6049bbf3da1694c006482accf2a4fca430d304d327ba716508105498535f8474e2f8896c924e6126b9e774b2b549eb51640a930a6a52bbce4f3d132f85419fecee1a5a7edc440a93501ed749b7f67ec64b001985e14fe54f2a9e83f44f021185b15367824ecfea70a29350982fd5e3c34d3c5708d57c3c0828cc6482cb67dfc7bf3cdd27cc44f179628db2f849c74848d210403c61b04d2779aab860aad4096395b6fb89c88c561227ccee49692f916a429ad0260c6b9d82d60c2727711e4d18bf456cff5975d2e45c268c9d5d3f2c4d6891fbc1845974ce8ea2e63b3c9914328e0988007209d36e7b9235624bd49cd8e900b184396c7ae794dc94021b8054c2a493ee4cce04d3fa7f11258c7eed57d2643c09f3656cff7b75d2419b92307d34cb297e5f90bf311249116a497c5a1cd38771fa6041eb9e600637120824cc048fdf7e176384ae8f30a587133aea879f6fe808e3577db69edf9df8ca8d2c328e096c03208d2894eb8855d414195102b2085398269efa48b37bf74114618a6d7289d5487dd23e49844194d40ecb793394183b008208736bc899d5a628d936c821cc6eb6fb045df23df73408104318dfc996e542866c4b9e3a8014c23c6be27ae5b3cc7c9010dbd7aba59453de92d6cd7db8db384b15cbf4255bbd3ddec725c8208c7219263fa6a229a509578ff7711700118429592e77d27d8cb3f50361f212f39d17ac54680908a33e99fcf269d27d3fb505903f982b3cb756d60bd274740c1bc607103f183c799347074dfaa074d2460b4a604307884709120d207d3086cee9a04e7d5477e68331d763e535db4a4b0eb20763284d0af2bd09ebc19c449eccf07c4263a44c00c98349dc6d67f6f37be3c68339d63529c4e2d92713dfc1942be5beda7527857e763067cfc1ccc99ff66a4465d4c14ccc0c55a53fe598b3d1c17c9e4d9899d3b5ce379b003207d3ed87735289ef4e42a86477e560d0fd334b3a9f6772284bb67477f02c7802481cccf76492e851d58fff0d1fa7c42afdfbb8b2d1021070808c63825c103824d39c9c84e9d9e5ba07206f281037d4016903f2ca4c6962c52ef14948387df80966706307081bcc332a9cdca39dfcb9e335186e9bbc953bf22ec906a206b4f6c5f7a4476557b29d03240d206830085519f1f9c4381d4f903398ad2e45e6cc7cb72a1118b3108098c1e8840b2a67b5139b9ca22a903298b7c9d1ba4922ce629f8090c138f2a9aa83d23f221609c8180cc2532679e627bb64ba92ad1dbc0f3198d308b13ca33cb64754b2b5e3d78084c1f41594b4d204a5d79d976cede0918307ba010693cebdd4d8aeb4bf720c902f342b7263b992975b69eae99c820a3ae5d393f1831f3774f04fc6e200f182e943eb7f774a397b0148178c4f6e97ffa45268513a38d8c12307ab00840b66e29b677230b34c4eb3b760ae2aa9223e28e5a3c4662e00d182416772fa3bf529a527df593056d2fb149f42bc2d8a3a41138060c19c536fe877abf7ee5bb27505a3e55bca3649c5f8692400b182d975cf49f3e4f9d3ba4ab67cf05702902a1409154cb133b9b44cd59feec68e837c4cc12017d7928b26bae8abca46002205b35ad21dbe9f459354ba648b6b0565e8b0f18115d8800248140c5af4663599f8ef51ab92adfa64060205a38a25a9a1968293eb04f2047367b5519aa479b576910188138cbbb2b7dabfe77b3190269889e99deffde365153513ccb9a5647e9aba151986016409c651eb27c99b85fbfd1b0c204a30aa76aceacfe9149b648224c194e4d65d49eb79bd27fb06102418fff4276522dbc692264730d7c5d0316647e87c2aea06102398624eacd59d5dfc275a0cb38e1384a97b79c95889610a79a29fb8ebe96b2fc330d5ede512316a9af0248561b02e4d4b7d6d1e1707c36cf9cf5cb49d4e4194c03055551ecb2777edeeacfe8531448fca648fbd78f12fd92aa37f80c65801090f7abc0f03c30c5f9809a327a4953c4dd092cf2231a317668234119e5b4ef85c7e7263070a5c80021b637c8084a40c318317a64e5ac73271f5892df2714aaa1e8920593063170627599fa6952a1dd3a4646b478f32bc5f304317eb09d39694c6a70bddcd61462eccd9f57977d5093a97c3770b33703199ecf983145139f792ad1fe8c9f0b143042424242476258037ccb885c94b35a97744a52ef1ff383fca3081eee7701c38d851c6845d30c316a6b2266852d507155fb47c98510b5a98728e0beff4514fcec4c38c5918af65f45fbcf49d54b2309ac9788f1f550a6261f6d1bbea23fe2d952702113c0f70fc3838f8139090f82021f901525898e293f579fc3df3925f6190b91bff5bf1f163eb0a8395f5e67b274fe0b7ad68ecdb5d2e8779685bdda76be78f16ff1c74a85498c10a33314c7e90e939eb21afc27ce1e420374f9e9592b161862a8c153ae69e94b29256a930553d31746f6b6e57c8460b4070e3060909090909c98d6ac50c5418aeda82acaf0fd1e2e41426b591317b499beee4f5196698c2e84ef03cafe404273bd91ec38c52985dc7ebc27acb697fb003073858404232c1d1e35f5086bea0078fc98d1ce81309490144318314e67c82dcbb888f61395ab275e6c3078684440c3346614ed993691b7db195491285f97b2ed738397d101763166684c2ecfba1e6f24ae9c9def95ef0ed748fdb0b333e615627dc292775be7ca76ae120830364e810018e1b64f8b8f68441fafee79a4ef5a559270aa184e7fcc96238612fd9ea81e346d572c21c6b37efdc3fb8fea9644b6d13463595c48a134e9354122ad9f281836db4000424243e74e0e3fcd0818fd302eb13cce006116668c2742a96cd93946e52524ac38c4c9857a459f44ab7956529590f086106260c4a7e7ab18f159f4f26b4987109a488586a51aff2799223c719232d13332c61b82b155d51b9640b7b7056208c1995286306254c7bafe86e4afebbd481a3c407090f1eede051f0d10e14ecf880fa9831093edb74a86e62079f37478e83f8471926d8f181641f64f050c10c491845ddc9a153e95f4b4191b05390a7e5e4b92a3d06332061eef0eb393ee58da5f01a663cc2a0c39a8aa254ab9778673822cd92ed7aefca1536c566467f6c92c5f5bbdc6046238c22cc2c8cb0fa9f4b419bc108c325a19e2e7aeb724abd0748483e95198b306592f0f417545a30f9600109498ff741424242728219dce8314311e6ec5af523f5fad4134b84b952bb982a7dd6600622ac4f65b56651fd3b842947bb9b7e0b0f3559c9161947c78d1f387ce0e041f7e0f103870f1c2f589b610883b036213a4d6aa798e5ce2884c1d7e2499644e9bd77e0409d4108838a5ff6de70bbf9b88c41a4bdc49426978f5410e651eaf19f4c26d5980eddc0c18eabfc643923103d9801881fccf8438e197e30977636416e5b699f6e461fcce460f719fa9fa0bd590766f021cbe4b4132a6e49873471ccd88322f684ddbcf8292f93197a48ab93d4ad4634b1732501d979fc91f979f154468eef41c6b2881a4c414b3e9cbc2959172fd9bad183dfa1d50191349874892af5e99eeca4f496fc3829c0921f870cfcc10f431134989e245ec3342d276da792ad1e7fc52c720683bd8e77eab2d3ddd11044cc60d452ed57ede37b4154065389cc9ac907af4e960819b89272d5272c591d3d787c40470f1e93de31982ec74c91a7ba4e4a411131b456692e9b25b9d86dd1e4f2a7790775f249ba1b8884c198f541fe2fbdd89303834997f24c1016ade509639321f205d36892ce9a62623cfbf68251d4e7638eca4d50da2e98da2e133da54aa2d2850ba6f37c59b2655e3794b4cad882a9d31343c93515dd467c3910d182a9c9a49cf4a58f28ff30070f1e9e3944b260fe14f47ddead2609ed460f1e3776f4783e8108164caace6e9c14db73e9125307225730f6490fcd26ca6ef60112921205112b98ae89574d9e51bad2edc97b800722553007fd79e475975c7974e0e8f183abc70f1f2410a182a95ccb9ea476369a1cc231c1e10307978f1c387e948101912998ecb7a47e366d4ddc908a48c124223fac9ea072493776f0c0f138e8c1636257d6e8797049240aa673b29a302d35d77743c1a05410623bba966c74e3073d7e3014449e60105d7f55224c5f6dee04f35f3cab2cfa548c9136c194827d1edd442786bb26c20483f58d3bb1e3473a493986c8124cdb1f679c686fdbda2bc1946d2a3ef1f6f249b94e8249db7fbc52a66fd2c98920a19456595bb4b562d76cf97867bc3f696409d38a1cc19cc48a6b05d3d2d1f42246308d909f7a4d675bfb5e0c3349df747b5b3e9b9413c378ca4497388b114fb1611845996e3b99a8a1e1496118ee444bc4b32bba5c42826126c5be27a8b8f15141280418a6ebbcdc571e47e964fdc2f869bfb227dd31efd417c6921bf5cddcfc2484bd309daa2708f11e3ef6897961dab514cca2c8932fa74276614efe95752cc5105dec4ed2eb14952705427261def1b7ec9969613b5cb2d5757cf8c0f163c7d1c13ff8f1e37b90a165fca0c79d6006373610820b63b8e7e9f3bb54f9df905b70b1bed36e3bede56d8b37e6a47ab5854b6b610aa1ed65d343fb6aa585d67276179e1e2bda53d57aa768e56bc82c4c22d3b36979d2e7266f9a16021292bd513e32441606b9a0c9eaad7d253cae8d8541554f6c7d3d58aff53db00c326061de7873f560eacea458b2b55606193b44e0a34719639090a04ffd0a6545478d5f3a93a58f105754b1ec53dbeee45a6de3ca095ab55ebd53ae1516c20ae39ffb2879528884846f94adc2e0966fc55abc9c5c5955186e9de8aea7679af1242415e69195e4f678d272390a861054984a6efb789a9c90a2e715424e6126b555c51ab3dc5f9e348541ec63ec63cb74cc14520a33514468b3d8ee52151b238414988d6ab668e5aa8eed4cddcfea16d493924a71c8280cf7a4b8a52e3b8f685bb29584105118e589df1a9e3429c447570921a130a84c0c1d3ce85d7652261d8510509849f1835b3015b65fc61e8684e4f4f8904f540af1c4579ed4e2e77afeb48474c2a49eab3653b493478913c6b827aafd49ddcadd6fc2a4b5a1cc83f6423461caf99d2b564a39ed551fd8818263448464c2a0c3c39a10cf1f634f0c440826cc49ddc9e7535e415c5dea12e60f71523b51448592d5e8106209834e276852dadb154d562b616ebda07395d0e4fc9ad5208412e6caee217413e4843653c9d64e216412c851bf5df34e522a56b2d583d323d5102209e3c977f0d893a5ba5bc956614248244c761d1e3e4af7894dd8c618f6881048189e4c7282588bfc1e613891259ab4f53bc2ecf21fd37487d907f10e23a411a6739195940ec25e8430c2d85bbade92baf527935f84593f29599f52543971fbff809a220c967f4d7cec574fa726c268d5613c67a96df920c21cf22dc9afbb1cc2fc9ecdcde74a2c44133584e172104ae333697c3da34148214c39c5d3e424bbecac574218efae8429199572c93c6410e64fb9c572b6ca0eb328224410a670a32ea51e7dd25ab34098b2dd563ece0795e40710468f26c4eadf8fdcbc2d86903f184e8df6b1707a3f18de49caa277e92f25bd3e7021840f5908d9036321440fa61c476a933249cd7930a9585e9749eae59d38976c7921040f7f3839faa69e7c884b36ef606a62d9cffe958dc76807f3ea65cb9f9e9cd904ab0a21753058de6e3595948a6b69081d4c4ebed46499cbe4042173307726e7aae09509aa7a2ac3478920440e66923d497ef47af80e6e1d42e2100207834a2a3541c7940b0e216f30868ae6042dea74684fdfa80244881b4c67418bd0d74eb214d236189407215d2f09fd2793668341289d27d49eec93cb3598ce42e628a5b34a8f6a7ee428039f10a206f3cd5693df2f8ad2416930e7a9af0c57bd98734a5a820841035bd1b5aede2a77c5aa7b26937bfea46b7a8219dcf8117206636832c9928518b91ceb159090a01e1c6206e37e95dec88535153fa40c069dee449c4a41e8f7a4103298f4ea9c5879daf967cd40c818f89c7226093b4f27373931e8a44cb40b6ba74eae671012067390e2fea97a5561dc103098da62e71c3ba4e5930d18215f30134b3d59de2cc5c9db7bc120b249417a6c92ba14a72e989d64329c942fecc732594042c2cf830ae1822953d3a367a78c11fd168ca6e348efcb54bdf6b4602ed32d2ae54543b2600a3a54b4acbc5a9f3f3a405f32462542b060b0acd19dfa6359ce5f4d845cc1646f63b17ee5eaa45608a982e1fcfe6c54bcb24f7688102a9846f5938ab7d1e420b639844cc124642b852d71e1ea49a721440a86279eeea0e27dd2c447f11012057307f53442134dfcc3bf2a9b8440c1245b4d45c83427956ac288902798fab28715996a424d8a978810271873bbbcb53c9490e926ab3f8434c1d4d10942e7fcba9cf7434208138c5a3ac890cf387175b131c6183638807d085982372a8b9097523221f6018f0e9090a4f7418812702db12cb1309a726ea96405293a4b2dc75b1f58810ddb4448120ca6df4bb489d8934a1324988976a59e4f0e224b4f2147305dcc284dce97b53ba71023187c4c5b7c828c69dbb11806ed6b225e848c18a6d104974f6acacb3a350c639b92a5a2631346fb424318c6d324b724bec2bb973c18a6aa4e4f34d5b0936603c3a4214ce6f9458dd1f51706f57e266fb52f8cf296e213eb777d3ded8541a80d2fb5781ed493e485a9479a7a7c9457b9e02ecc66a2ee3df7a67a902e8cd72de79ec358a959381726f3e4f9dd3d783cd56d4f30831b3b68e0c2b8276efd4eb08fab148d5b184e56d4cb59d5c9227feee091630c1292dfc123075a5b1847765ba6d8ec681dd1a885413f395e58ce492fc642831666cb2d9a5495639efec7e3a0c76981d3988599609a3c6b52ddbb453872f8485b1fa0210b2fc9cbe93341ce637e3462c1899ccdcca54a4bde96a4010b83b87688cc274a061aaf303d99d47add39676be9b8c2f8c41dd924717ab709762bcce4718f27df89ce2469b2c23ca746a9707f25b3c530d0588539ffe2c8b4a05785e9bdb3bcfaeb933e8b68a4c29c2b588a75917591312acc418cbe779fd2dbef4f61eaaef4ccf190b35f328571bfa45956ab9674520ab3c810573abc79b238290cb2e67bce6647dd671426d99da5cd459e26499128ccd5a14ed2153f74527b280cf3963d8fc5a9742a28cc95a69c742262f72efc0953eccfc90952c4fd42ea0993d615d3a2745ff85276c2b8dd8427673533f9f03861d2f9d9b68997740a966dc2a477fb4a6587f5f5451346f7f94af11562742e65c2244c48bf6e6278de91d7083430613af9546ff29a65d0b884252a716301342831091a928804046840e2110fa0e1881b11a0d10846dca0008d452822110ca081881b0da0718805d03044036814e200340891001a8340000d41d4a01188ea09c2f3c2e69678c2340061cef126cee8a8fdc1709a2cd292fecc7272ca0fe6fc356b3376a6917174dc0b68f4c1a09ddeb6be546e27135f3e98462b9fd619d33d279392ad626fa0b10793d4f6f0c4511ab2a387a2910773b252b225f27a2c8f98061a7848e3333d39f1cadc42d0b883d93d85ce3629f7c59d255b3f3839520ef6a19da06107a39886de77f83ef9f992ad54038d3a989468dd09edde23322fd9d235d0a08341a87dd27d55aeceb92ed9ba44038d39a493688eb01466591e3c4a6ed818253f70c0c0478e1c1cb031860d1b63d818c3868d316cd86841096c182c9534e4607e93a9a7da33898359c384abafc7e160269937b1c42fa4bd7ddeb0d68cc8b658dac68a5bed7be714c693e54ce740c30de626a875588aff639f6c83e9d356ce53f5d9c3e768b0c1e844db53ffb7b74ef0d660329db57982b65141466a30eda755cc782f11761acc972fcb92ba8706537c9213ffac63a8858d8cdb2bd0388341ebe6e86951972316fc781f26061a663093728a53323c645955051a6530ad5912356c30f58e88d24dbae4d95983312f9b4e41ad0633319fd47649cf9eb4d360521d4efc83c8a5cf6830c81b79619aa053c7f60c66733d799faac369926630a97c26978a8965307f36b13a5c93a36c886430cf795fd6cefeef87633013379ea0ef89180cb6fbbef949cf851f0653936259de86275513184c269d60f3e4d199f8415f307a10236d4bc80ba6b8d6905e3968c289ba600efbaf3ebb9c3331c405e3a8f3d1232f7b50415b307a48d96e8234ed848f164c4a6aa513eb2a15ea2c98c99968f6a52a46648d05d35c6fc5318fa6595fc118a34498e50f321eb682e1cb9cf0c4b0dc1d73158c3aafe56a3115cca67da4090b6dc1894ec134be4dcee9f94e45550ac6b7115561deadbc8c82e172e5a8fb974c7a775030eae52667856c8f91dd130c16544cdfafce0926cba5c46686267faa5c134c2a4e294f376f72376182d147de935a34d933b927c012cc3bba545c8ff9711301946096b9a02ba29a286a2240128c6bf1f3a1542c27c809800483722fe52674ccf79900473068ae58d27572ea94096004e3c907bda5ccd4655c0c73d0bbeacbe498215b6298740c9317a43669f71c86e1443dd68f10a7ea3461184f39995827cb60986eefb4e8933239f5070cd35d677210264296a57e618aa52d478f71ad4a992fcc04153d6cdf7e8eb9582f8c224c98324b73e293092f0cb716aff267b20ba3cf6c9bccb0f015d285595d7d8493827261be2c169aa0aeb24d8e0b432b7e169ffb166672f4592b9b6d61ae1cfe5a39cb5a98c9413edbc5da63678b16c690fb77e2a4b33007a195823539ba8f280be3c5bf6c1beac40559c5c2a04b597e15a1c9d74e60617c11ab6dc2084dfc15667527a83539cdbac55d610e959ffbeb694cdc0ac39fce113a0815646b5698c74ccaf599133bceab30cf38d94a98d00ca9c294d28b3419b9105953613c15ea579ba0499e4685a93b9758d19e73268ba7308fb23c2ae9fa96ec4c610aba3c569cda26eb560aa3766b5dfc6ca83c29ccf6734fcccf0d1dab511847e97ad8cbbb6f52ca88284c41757b34d59ff259ca48288c16b2730a427cac68662628cce6de39a8b327d9a77c667ec24cccd2b538625bdf2d9888114f98f37fb8263a5994e93cb23e8c74c26499e439bd33c177ffc57a015e61f1e0f630c209e397e729e1f974b01aad726413a626eae9544243a8d864c263b243048418d18461bdc4af6967b2e878a222463261b44c0c1bf144d13022463061f2b0f57c5aea4b182cb8d545ffacced78e58c29c6a4be99adf327d6ba4120639d22f6baddfa59c8be07694c138420953f65a3f3209b3a98d07a5e74b8f76333022094d075961f33339ef91c84c43ce4be52d9c5acbe5743a46a8caf1cd532390309d4a6d2145a794e6a547187e7427d90bf788234cf1929e68a57c72aee848238c622657edc9fe3a278d30c228d6644b159b9473feecc8228ce9c1e694b7d8fd058d28c2a43c4c29fdd604cb151d4984d14ec6cffcee49c1671e4184a95493d35875955c267f08d3c7139b143fed549769c410e6f350b6a5561b7a21cc39bda8a0779d20ca9d10c27826bbd7afc9599496066126cc255d1a5af2ab6e41182e857137277fda883a1208736782980df9d1d37d228311409c296fe9dd4c2ea5ec1427c52a51faa2936487f80f8e09d1393f2969c40f861ff55ae1c2f5c62a288cf4c14cf8d0e749a45ccff57c307faed8d31d915e251cd983699efcc19c54e99dbb2bd9d283a9e3cc87f1916a9f5ec9165e1eccd9b6ab542727255b3fb8819582113c9847debfb43e93946656b2a543ef60106ee9f2d493ea31c1b6834986565fc8d7533deb60cc9db54c124ac8caa12b4507535f68d2653b9d428f58b2d573309332e1c967df27db49a564eb0c478f1f2807638d762d296fb560240e86ef0ed6ba1d4f66ec3ee0600cdbcb4dde9e078f1ef88191371854ca9cce139f7ce1623018718359c4af597ace78ac26dc063341a89cf36ac283fc2036989b9c72ca534d1cadb0acc1a03e888e3db99bf2e44ab670e8d0c103b10b46d4608a6e2fb29fe245dbb51a4983c92efe833db9c3823dcee74009821134183e353b589c4b9a24e5108c9c4108236650148c9461840c236360d6b6626ab89dd5775b0a553a767ef266b89846c4709fbc15b15cf115c14818cc417e59762cd10a4a5eb2c523180183f9d2629a967ea2fc9af60553b60edad3743ec4a5255ba54a7c9c12138c78c1a4c9b6dbf9c29ed5872cc8910307094848ba70e300235c30295b391de4789f0acb1626c5cb9ed32d590e8c68412df574d1708f8f1bb9ac7be2ab96f94816cc5af245debd9ba8961ec182c944c9eabe353946c847ae60de0a15fdf24d255b3e383a9a042356305d29f11fe34f960d6dc9fab8f1c3078f921baf86831d387080031e3996078e1b64f8c813cce08619a98241877082080b2afdfe3d18a182f18356097dd9a4654b19998249eae776d593edc9b33826132c117ce0032437ac0b2352305ab26d6295767b8bad1346a290089d573ec90f1a144cea828a9f9d44479c37f204c3c878522755a22ecd1c718229057d554f2e193a8ece4813d40eabb3ca1ddf61a76f6485911d6919618229f6857593ad9cf553234b30bbe5bedced152efe52c688128c23fa6df14f990af3a88f9124189ea0b5cb091e6aedbb1124987348fbb6e0a9938ad9c811cca56e5d6ff51e4c87478c606e1597d3769fdaec122986d93fafeb534f7be98810c35cd16adfabde4b8e900f3e042424c9075f8244866150960956e724d3237213867954fc85caa79bf89548304c154334c9c2bff3e80a11448061dc79d7badc9d9ab7f68b12f185298f3ff16ee4b346e588f4c2acd64e76825cbd8e7bbc305cfd5f9349aa626da422bbf081882ecc9626dae6a154aaaa447291db8959b6c865d75ced2cc2d33a447061d2398f7eeeaa9cac22b7308f10e2895ea6f5ee49f1c187a0c7f78047096c616eedd1a5a216d43cb15a189edc72af5d56729468610eeba432671e1f72b4b330a51d2768d1848fdbbb6f94882c4c4a54136409f924d10fc7c2182af5d8ec8e1a6fc29c3e7cb0054460614a999c899a99fd7165dd1bd503915798744d4ddc9ad05dd1bbc2b0eef23ada752bcc5967ed82f82ac20a5365725221cf53bab4a2c82a520b96292a96b32c65dd9fe8e7669d4e08e5231155183d558abd8c4f62f353b2c5031ce93cd06cd5980a839bbe5db1fb59ed302a4c3d2a45c6ac6897d44e61d6acf40d9dd7fca445c414061db67c3f257bdddd4b61ae74cbb29eddcf4f2385c15b2dbc8ffabd744d4661b4fdd2b14b7fa6a78f28cc9d72d2395a3cd3d5c9501c76a529727229a7c51295eb93a6d4ae9f1428cc9d391af2d42a8793aa2f887cc278e2b14eca41fc53d09290f08d3a4f985f437df22d39aaa3df097375ac5f102785f7707102b335ef72ab7039f3e73ac6a4c8cbcc9b30a9ebd9fb92253e054dc8d081838484070e114d5c260e1345227209e39a05f9fcd70465991c4b189b78fa2e869c5135b512a630d22a961a35426a8512a61296fed209bafaf103870ec39330694b6ae3b33e69de3bfe442461ca615b7459f49dbd924824cc04fdd1fe891aca9f4c46200209e3c9b5931e4daf28b98b3c82add39ab1b65699addaea4f995571334d529d8a38c26c1e3f6baaffa4d14f6efc60c7798148234c622bd49334711e4e2fc208636982dcb0209fd5275b8439de9d1cbef2d54d452ba20883ca3e273ff1e48292221f7c49f5104984b153144d4ebefb41c5ae64ab5806441061ca97fe9236e1bdb75f9f5f0109493adf83840487c821ccff64a2e9d34d2a0fdae1f1e306193874e0a30da1c5baf3fa9051abb6b251214a9c74d727c754b235e17163070f1c2b788423070bda062285309cb8b4d19976a32384295c26aae9e8af27b5bf83878f11bcc8204cb1ef4d8912322b4118948ee8f58cab11627b1d1c1da552241086cd5aee70b520ef76d173d0f93aefd5ecbf0284a9e24941554e1764fb3203913f18ec9ea42ea5d845fc60d47631f92453271e63681f4c840f26b207935f3ab9c9e904c140440f2b10c98339e7fad2fad149497e13113c98473c298e13744a496dbb83593cf54b8afed167a21eefa3c7490109c927113b982cafe67f08a533e9553688d4c1bc5fa53dc9454b5f4e7af0f8800e78f028811a44e8601cd1179f933461f22d14fc0e14e4096670a30522733069a2e9ee79ea723085d2fb9ce4756a92f2c70e1c3c52e081921f386020120783a52065e4c935417317818341073b3d2a9c5744de60dc8a22264567df27fb6e30c869ffedeeecaaff44da6070353516f4dee90f8d0d29fb20162b46a8eefdc78f43061044d6608a0313c052812e15402b06813a0995f67f0940a09014939403d00f1f65f40009c00fbc023502e0a3c78f60c0070e324e8d1f0020000130400b00e0c38793cc10c0f97112094800ce8f9378f4200901c0001430d2e36fe8009d1f3e6edc30000002808010a3890a2e6b16d5c9a479802395813f76e0c0408d4084d40004193afe60fa68ed972f9a05970c1dc80fe634c249792d75cea4acf5c1a4ec89a6674e1ef0d0a1e375acd6e08369439a9def8cd249aae375648d3d1c8e1f3cc091cab87163a4861e8cb35a7ff7e2a5f2492a59b62ac34ac7f7b8c1031ce946ea52418d3cfc800c8487911a773027b572795234b5718e3274dc056ad861a4461d7ebc0f1daf83460d3a98c69f4c7832713c07777b94f8c83107934a2da2c4cb93f41c8e1f394a7c9c1b373a7fecc0713e76e0f8b135e470387ee42843c78d1b2235e26018ad8ceffdbc4f52b21a709838b289dbef961a6f30778cdffd190f423c29df1b55841a6e30895813f2bd435a2aada350a30d46ad13f2e4a0fcce643b35d860ea3f7de288275ab6fb7a0d69ba7b5251a347ae8672d5659d55dacad89235a57e44e86f870635d26094cfe4347b9a24d487d20bd0604cff1816f7f2ff934f673085373337714eee93570d339842ac89a6f239c982eb653068828bee1dcd3af7680d3298abab72b217b313bed51883f1744e77a95454a5e4d50b6a88018fa246e549a3b1f7a81186529cdb55f40a76d1bac3cdc9d504bd4fe29ff0a406180c7afa53708232f9e95f2ed4f882b12c3f5eec9a93aeb43276f0a78c1d98e205e3760a35db31d652b31a5d30ba7dae20f497935c672e98843639889986121f69c996aec00835b660eaebeab85eb916d6cb2264cbb65c230b6632298f562b594145786a60c11cf652eece3a9d72d27dd4b88241278b93a6c3c4c3044ca861055326bdc57ce2565e12f601a146154c29a9b94c0e55499c675430759011ed3ab6b36941428d2998e34fd9a5a56e6ff1310835a460b47df2ce8d9347c95321428d28982b973c39dab3146a40c114f52c9d99d5e84bd71c6a3cc154397da9d1ebc4e850c309c670729375e64e5fd651efa146134c993457a73c9f30c1f4f9ad9af0969390d4a1c6124ca5efc9724d98519d82420d2518b4849993b4a5f00a261212ab1a49305fd6b69445ba3b70b80e1ec84a65500309e5b79f080da1c6118ca62642563a530d23a871d6ea31dee159a925f4b357109fc94ece4f7214a100c530f68cf020d28393fed2c4306727cce55bdf6ed86841096c8c41421284020cc3d8e19c7c9fc9e97bb4957ef8b841868f3c53006198e236f9cd4935aa43ce050886b9637a0acf7d0b000ce337d13d7bccbc00bf3028276596872d27a5130be00b7350651523eef39d30f5c2143f7dffe73d93c9a6f1c21ce32e4bbfa8e650805d9853ce1746978689eebc2e0c1bbacf5c9852f49f115ff117d652005c1874ea2443e54aa19a74dec2a0cad4750c15ab6486b630857672ac54717255c5c628402d8c26477bca7a8a7e926861263fd9d3ceb79c93cd340b730a6df966be76d4230ba35a9a76b2c6dfcf680588056f17e3ad6dc32b6c6ba5ea27a7578e25536a016061509924c2cdc91df7fe2b4c59663d67c7a7adef0a637c2a79293e9e8ea25618a47dce27f8796e86586192e5bd4d3e7d9e2e5f85995c41e9c993dd8f8f2a4c99b47527e7c396dba9307b5d56ceda57ee352a4c332a8626e65fa5bfa7406c9b7c2ae86a0a535898111dc454aa6829cce13ec72feb2c97901406f1eb7815c7bea4381985492855a3743d69adc94d4461784b2a9b9d6e120a734a7ab3db64b2c8cb4d4061d2f3eb049d1fc47b36f984719466b686d22c5d4d3c6110a2d35c2686c5cb4fbe13a63ca1c474554ba5fe3961182d117d6dda844198d69ecbf9d27790264c1bfab9ec7274f578264c413e418b9eae1c9f63c2b4667275e204fd417b0993c5d2de9e3217ebb58439550a5d9e64894ebaaf84312cc8ab38c1f3c9ee2961b20eb21f463ab1fff293307be98c52afcb2937918451e382c9f14ad1528a84d9ec094e8e16d6dc4d9030a578961c0b5234b1f408835a909b5ddbae8b3bc2e0a755ef924e234c1eeef2c80e23cb3d8c30933d87fd6815f54bbd08d368c9502adda408834e499ba86fb99f3925c22c23d6e266bb677f13220c4e72d14b9d3c84999897639c304d0c2b0d617ef2a58abe3072ffa542182c883db9c5c9dab14b843089103d55fb64b2782a0dc2a05475896af2677b4b128429abf43d69a2abf69340185493549a5ec87a9e00616ef12727bd2713d7467f30fdaf8fa54b7a2a457e307b93e4b2a9e75fd1fb607213d254e90e1f0c9ab4a36a72c3743f7b30ff293562af5ef4e5e8c13ca28496b11444479c0793d0b6266e8407f39e50a7562a554cbe8339c5d48ddc68b5bd76305fa5c86d49cb048fd6c1d8493c44ef988598743039f1efe594e5f3f01c4caa57611a1bdf15948371c684de12ffe184e26010eb356b7f1f840a0e06d9ee6b5f3a256db93718d4925e7f92d2f784dd601097733c1db43698edae9d9c4405b1c1a06add572ba8e659680d062db7922e4ed4607e52aed0de7a6d9a7c1acc379a307b26341875cbfcfa5a7b3ee46730953c157488bcee9cbb198c22ae1d9cf04d8ccdbd0ca6f0f05a51e33c93632783298b26c94c53edf7b18fc1b8bd9b9d9f5c9633591783e9842693b39aea61303ab94f4b7b26abe9d0c1607c758b6dd67ee236ff82495acc8be7eed795b917cca934419e26676cd6e55d30ba09511baa2ce5cf840b26717232b52ae515ff16cc2499af67b15254f0b5600aab5921e26be14e5930b65ab2b32f2768324158308c99ed5d1cf17e4157307fe9ca5dba154c3aa9e44e7ced2696a70ac66a152543849349a3a682e1e6c9d157bddf727a0a061517da39a8ab8d560a867bd3cf21b2b3f48d82419d1eddf952f98ea060366d2746e8e8134cf9ed69bfff4d987a9c602655b4a4f15d134c4167d8f513b4a713134c5d77eb95e5464d5b82e19b94c5e47abc5229259873ac676772932ec5249894ed25753a99133d24983249e52d0b2aeaae728e601ef3544f2e62339c14c008a6d22707fd9e2f8639f4ccdcdac891ef13c3ec99ecfb95acf3b7340cd356ac1d6fedd44d9030cc7655aa5b7430a542c13059a8509e491e3c38716098c9229621d3f244efbf308baaa43229fb3439677d6150523b7fbc1766f27607ddd17f63535e18543431c7c962fac5db85d1840cdb914e982f952e4ceaede5ce4939d99f0b53ddef5b9ca57161aa7732b9852929cfc96abe538a932d4c32942693c9ebc42d33d5c2bc4ebc247fbf82b2112db0ffae66614a293869b7e262998e2cccd7a4d036a74939b41d0b73967ad063173f5f121626dd4127bd1ce45798892e9adc1ee40a536f49ff0bc26ee65698ca934719d3fe996c312bccbe4d9e1df9c4f3ca641586cdd11e2d8e9600aa30d5c8de92e61f7e3a4b805498c64b45b75a2ef4bd044085e9747e137634e162de4b805364a265a96253183febc8fb2c4a59d8a53049bb7fabebfc1b2e294cdd39da58f2ac548fc26069a46abcebcd95a2308b1abda749ef7f2686c29ceec95d9f8969b20585499678c9b4fefcec13a69cd63f9f269e8fe53c6194f99c49dadb76c2f8e4b1168f1a270ce3224fa5890fa3acdd84c957ce4f9914d5a43561f610594e9296b3c39f0973b0ee74827d34bd13264c428fdcaccceda0a34b184bbce7d6ac2a95895bc2203627dc09563acd953037b1091a5bf952b69430e5eef49e5f6d9d4dc2ec253c2e7d0eb5eb48c2f89ddace833a12e65ef7552d592161d01d6adaa2d44567f511468bb26fe5c4babca93ac21c324293edaf520e3a6d84e964ff49e1bfbcc9396584b13a950a1dd43cdca78b30e91e6d7ba13a4f90a922cc2a4a4d9e6c3a29516922ccf1d3fe4be9cbaa4a1161d4f268ba3247e8b8e821bce42bc283aca8218ca67cdde747b55b9342987ca496878737fd3e214cf597ef4a8ddd8d3f085338fd653eeacd3b4810b59b081dbbe4098441ae53d0a5a53ac293803087987acb0915d772fec1e0273feb9977e9b7e907b3da134e7df8272d66f6c19c3f7a2594e55c9a60f2c14cecbc14af54ecbc61eec1f86b4df4f839e6f7a51e4c9a619d82d8cb0b5fe6c17cb2156c5645c67989073349f6e28b977730ce6d094f2ac413ae4b3b189ba084f86a29a5b4967530c50f39b91273f2694907f37a132e5798d06ff939986ed63f68fbeeb8931ccc6e4ad493135d3e131407635c972608bd155c84e060162bf11ca296d5446f30ed5e6a954a5f7a416e308ca753f2b4c5f34c4e1bccda6d3dda276ee2138cbca8744fa5425124108602a160200c0605d16f3300a3130820203c228cc6a20171ae91f30014000449382c4c362a22321a16160b0682812818088582a140180c060402a150181c12cbadac531b88692f60b7412702b5d3b3bf651b6948df1285a274497839b667a41517e85a268f2eef1fed614a13cec94c4608e29de38646d06b7a99e63bb41ab68d2dc0bda9d386838b05b68e9eaadbec4e94a67678042f1a6bbe1fab19daf0705c4a5b66e542c49e6da351e0f0f9c44796acba0cedca67a54200778689b86f9834e93d1bc285c133e99b729db4c73775b8213c9de859931e75d42e157097682e869b0818d9f9911fc52dfe22fc3b8a47183d30b0b8f8768e5c1f39d143c8c39bcae0032108f3c524d0eedbd0dd08547b9dd68de8cd82452237b02e1a4d0a70f03ae0636a3b5a7504cea3cc7a2feea0b87f366b862ad83997a94e24a3d32423a989a44220195f49dcba198d98695dce1c1d282a0f820ff283a24875e859af9ce5f2530b4d485420eeb1442d18c46aadc06d9b492568f221f9c8379960eedbb3369c00f7696b756650d4e9011773b103a9a5d48791dff0d0544f9b4b223c0e906cb245fa71cf8b63407c186838c609d2a6a14cb0b7228b1349dde4d8841ba2f1999aedb09a2ec05c382845ab63a8357a17ab3bc8feb52103986ecd34ed3e2d9d52c2cf0f374d10f187c1efa859f7d440d178c690779ebe5382f11601b8dd04529b227b43d640a90975aa1e62b7a20302019d5b25318bf7238d228b6e8030694917c0a4261f246358edd1de06e68660138aa1fe10cbb2d56f9fbca7d4d0a865e74a35956c54d8a715ea44db7b557a7a88fba059561cd3bbd3e97614d645492170f5b657e5fdafeb908989e063e64e52212d82fe8edeb6f815134a1fafc388fe6f5bc9bc52a24204ea99c9a892bbf4fce725230ab0e5e6f9cfbfb68d7b187fd328b18924fdf80ab9f28f2e1fbbfddc094b2fe2f04a40f2cadb1c2b1d23c5cec30ec0c1b115ec0d18d1139478384411359ebcf96429be95d26a3ded7e56e679f30ee1340442dd609c14d83454102861607a1645708e5fe73a2a980da26391373e940614070496d6d874fc1f08fc36e8fd8d5e4f443e045c0a1c6a7767cf058d11fcadf2ad09910f806ce2a95fe5087e6292b8c765cc05ee73b93ef1c51f30ef62aa1c75e46df55f68a5bcdaa9f1f2b1a5f5a8a8bf96fbbad88bc3eefa27fe6a9dff8ef3f79743f3fb9eb9d615b05958607eef30d6ab3b9419f821ef1030dd5b9d20d79224fb7dd4fb7f03cefda3a8f0f38260991a8b7e06e89a91a9217c4fefc8e93b7c4ed225bed027bc66160a27a6505edb81b1c1a4caa9d5ba36a94c92420aa5ae544b99aeca13e0c338df71ba8ccff521bf63538520c85df5bacecede91bf0578d87dd2ebe2b5fd68ff612f618f3b2014620704518d3a68407051c64aa3a42f4129a717e47a3d29c7b6ec03e0a7ff2347f228bd49611071a9f62d4de3f7fde47f112c7d06b01c516622b585507963d3ef71051639359853a39f4291a51722993fce68f4444890bb6ecf944cc5541949131b471075e09ef3d137cd488d94b88a5e2527776ceed3a9e38ddecdeaca101dffe3e056bc9217d4e20446dce0e88a184cad1d97d068070d797a7f154c3d22e0b7a50a4b69d9ddffe099b920c7edd6b94217f8e23a331b01b25fc03abac2c7dbd60b541ec19f611af5c1ad866bdd0b01f9eed125be48ef63559505e445d95c0f838b7f42788aa4cb216e5e7d989c4412fe2030d2ac626e8ac56c4f9acfdaf08dbd4235f38801df8617d27acd28e7d480e0bf549ca774b9492e9514c4950813a889a1a2beb4e710dde2d3dbe842d5983cf39e296a8b85c844962cb0b80421bd533a91d3ea144f8da993ba9268c58202a69939b0501ed09bcbc52d1d26c2ea911ba1d119a9452ca440e594fdc933cdd2642e99b8a813d9280237fe747014cfe405bd4eceeab148660680d16fdfb975a52ff8c5790ceb02ecb71162279e4b1fbf1c34b90587e4d06e7dbe64a8f5aea53d28c776634e4f07f95c5fa8ebfb04dd5ab391da26ba4b7124ef9289255a571f7d3c29c620ce95edda50321912459a248dc4f93cbd2acb746a55a48d2a3a8ff7653507425f9b6e9175b6fa54efa1d745c011e892ee6e9902d85e740cd62922f35635d222f0cbeb9984504a97ad5a93477bb3d6a04075fbde78d63e035cff9cbc65682353af07e59c5a90cc9f2992c301f95ddcbb8a9c154f994ad77ad5a3d3be659e041a3e2452c2039f36247a986fa70f129bf8aa8f6f7f5074a6bb4f81357db5546966967806996e635d01a76b7b9e44c0236fc59fda817a8992d220025884073515b01fc7446fcf39bc1b16d9a83bcbc6ddfd93326dfe161f87216719252f92e1e39b5d5a4de5c5a9e633b5b169dd5331e9618e6f4b860af1cf5f858d477b22a2fc3e1ee29dbf28b683c198eba57b622f86b8b81236afc6c01076dc94790e976b8d738d5c357972a5c16cdfe2b872c1bfb6ca1ca1cc3c6396049b82f103826b375542151ee1653d446a4e1814e951792e8c201f53ada3efe3d4e0ed8bae72859a1cca887c9a0a1b9f964e6b8d238ea38ed0e1d516d44483c962d03ca8f51b9370f3ae1c96366944daecca4a60e18d2742d06f8393b6f1a0f5bc429a7c06559380cc255b8e6155d5c4575ad488034f482505c4824c00b0727ff784cca767de700fce9beb21fc0d8ce55e9cd54b7fdc89d9418e411dc38ed82d9978847361be06dfa54e687ab5e0750eccb605f86d295dc98006e4a8a4d381ebd53e33b0e9c0321d0112bb27640582df48ce8b7bdc8ed49dfef20d8f8671b0343b00fb5db2ffb33d225ab98fdde6737d6167501759932d5386fff1e45537a8312c26bbd7ce2d4b62eaf994aa20b22b60cbd5099a1a34c38476d6bdfdd716e91144b864e6ea11627e00188f729cef13221ec79da10eae186bf855df01ef98a4cd579dd05891c3d1da70947e516f3bb3e58e324df17a63bc394f34851c504979598dbb9c00135cfa21d6cda989aacb3f03d418bdfe68212c0e27001f00f2fa4be8939d660c196f04594b9b77e34ee91f913f548c23ce308b427e2f9ec09373623dae22ba3b751b0e13e83d616b220972d77b03bd48732db081a574517cdda2131da1cdcf1d20be542417bf97a5279991dac421fb0791a3559c03dc3eec98ce4123eb6027340870de5e6838f6534d19f506075ac6f4d5ef532a28dbec4184478364d654d378e3b11e971adf9352e1495c3eb474a4f8810abe84e68a7789311f1013f5b9e232df1d083a8ab7fb3078a0971ebebe4e1fb83004a5882313e5b0d13c8782020ba851579ca80e04a7a171e88a033d5dc3e403c986392845486052047b08fbb36b860752d05587e1858fe70592b8f0983ef243322e8bffcd5ac2b34d1365158b966f477195dcb4ea4cc3f17e77bd76a8c03c796931e298c5b344e1ce0ab69eb414e049fd9b33acc028ff92e69d2e847c8503dbed96fbe104bfefc03975bb5edda2b91b57d96ce50344606104f9586bbdf4f0a4b77080da42e52c00e3f9add22cebdb52dadb06773cba51a0fcc2e72ec9b082e14bdec64a63939e93bc096ac606e218d675b69a767a9c8dd659fa736f000eb7e2d7deb6b75fb7616ad1af51f3be9472e17ac9509c7caffe2db262e45bd2806296da52ca5a6ac73cda821a3c4da4b5678737c38736ba7c863c28940b222e6dfdddc8331b465110ee9e10244dbea2d85c5a803a80057a8d1880e8575380aa0fb39331e30e7d430545308fa7390e83b25d171149b9725d2fd32d36be7acb8b9e04362734820eafc0a286ac0254f41af34048f9939b6dde97d82f93b5689769fb8c626482960dc9df5f93ffcce5033282c3422914ca1187e3f770687cef4619a54f12db44da5d729fa4e2ece8e08e274e4643bb35e9a8df0fea820a38eccbaee801f3198eae8cc27bb7cdc97f6178e88fda76a45064eecb8b490d46c9c5d527bddf74ea3240e166042606bc5007aeebf252e3f7d75a36f30f56887decfe10d594b3c4a8740a1f2039e9ca9e39f2c7a7fb8b015ff304dc105e4bdea6a2db7fbcb94d92cdf9446310914f00bb813911741823042d10643d457ff2b337781e6f8eed1029b7a8697b7c099196927aa00dada49ab74fba7013fd1cc3a76ee5365c9347c7a9fa7c22f71ec43ace22cbf38e9766148864b3f271c3ed702466928692696bd0ec3f8180140e899563b1f1a0721d0d56230c2a92370d369a9d98a3c872fb4b3c6fbe358125fe753dcacdaa40be357f92ce278dc29c4397bfdf3bb04e2a223e25f0f135b0af948f12add35631d7418cbf99ddbf3dfb59a107f9a9c7a14a71b7fa43dcee32d777027853b97caafa9245293ca4356b6c049b61f76d991f3de29ce63c687b7f60188542d1d30e9e0656ea6beaa88dbd253232b5c2340a578cdc727c9ff2e78857036c19da0049941aca95ac24638f891e320c041e106a42dbe56e4c083079423f8a1ee52178062d7175d7a68ae036967219c1918bba3ae76e1b29d314208af05555b808a46406ae9127307e749b177874fd25bb20ac1a0bf7ab66b326d015dbbb3a221607f679ef4bf94dac16de1bbc33c306a6ec4ec817dd595276fa2f45511b88143a5df063d6fe0e0574bae545f02a3ae17336c1c4e072add3082223ad3a37b6cd0da1553eb1ccaff0d18ec8f27619e100984f4efec4d397874e2878d5117e5b07a00571f7b8de02072e691de11955a162c48a686cc3568b4ea03b0b900ed6cd8f1ad45de9dda8ee04b4e5a0b5aa5aff31d81c750a2cdc8cc12dd06c3b722b3188781daf07a663cbc38800051f6d15bdf408df7b909b5afb8e51026191f8a118aa6104621d9a10c0abfc0dbd44109dfeb842c8f8433aa1afb5757aa9bf3560ba57699022e26b2a8e24f51998146f2b0bdbec5fe85fd74901602eb6935540578a09d490afe2d8a6846ecda80616ef1451ac3c8f8699476f55936b7362b25918c471cc16364d1925cdd52e812172820728e262d4d3fa674ea1801dda6d3ac7991443693d08be66ef0a064ab7bdc039323be4b94971e86f5b1840b7eb85c1b1f344c8faec8675096deb89ce31796782695211e3ebd0c1ec1f3bba319d4d1c345420f62c3d5dc23d9283ef17159c9a903f40543b915bde9dcbce0a95609080895c866e3ab30b4b96b67217fcde48b727cb205515e504d29b1d6b027bca65601e1e13e2148667a23b3bcca6d68d5f0bf7536877899a231b2d09d5e4ad9d6ae2a80dcca4cda1d4ecaadb6c0f4714bbcf8e5a108f5170ab8caad0594a6845446899d0c5c2df02e8f47c52e63f6ad835497c1cb217d7e1517c406b096ab9971b9a7380db854a80f94f0b39f2bf02a0e7b243c6fc133e053d171c2f5f0409a9941d4595db4c630a947a0b333753e55c045f0b41f825c7908eab22dc2a9171388001e3202362d315084fb25e9194158180741be0443e5c8a83d0c9496ddcb10b3c49bbd4a5ff0433a2a417a795a1bef4aa487f4cc4c9529335ad75b334756fb0b9d2fa12eaf8973bd9151f7436749d855466250420f0942fd1b0a4d271c42e4a27b4df01e3e9a2eb2e5b7b8153361d94861ffa63ed16504dc0e5358cd38652b59b13e0cca1ccddb2dcd58d07947696db6186c47c63f3aa4eb141dce7699f34906dbf0d6f04ecf75a830d3462943514370f1550e1d75140156cd8e272169321ad41afacc08b127942598587621df4a740c9975c8069aafd2da068ee8a3e80a7f0f164d9ef4b82273489fe9ad393713e4c5551bf770e8aa6e464720b83b63c8ae2a1c0a16d04e6859224d11b8e1731f2b0a8dba3528ea002315074004348f18d751346b7ad3d8b6ce4c777e31271efb46c57f4100c4d4e28b0bd4ecbeb84a80e2eee0e308c74d9684a8ad07e0d629cc9cd6da510a18239c27297104a586c16942957307f4b40c067583a4559f0d5731d0fd948346e39dc2a05b7a30eda77b03ea9619f0125094f295ca4b680efa01da16f01fac656ce83a027364846f0aca1ba32cca2a0ea03695a5d7213ebee518624527a1310e48cb30dd027733072ae79fbf88d5645130ebf4f8e8d30c6df35fcab95a2fcd5be26a9e3ffb29898680a8fc4adaa810e68adb65d48005a1d0c9d27d2b69ddc1e4cd704360042ef8b27046594b3250ca90a5074164b15f937714a9803823eae6148605ec98d95efc57d0e62dc87138809798c6c03bff37e44ac567f2ae30e27487be6d242d035623224edcb5f7d8ebbd4ec407dc92dd38d208c14bbf89fb252ad940c5edf08590dd2b3ab84c90870f11e4c314565facaac2dfb03abc4e5cb1bf20fc5ff3fc32841bbcba1bfe0b0ef3767d96f59013b9adba3c5e79af66498024316d6d6a5c58d7033e91d306abdf2bfeececf65f3b3c3112010dde4eab461473033187872c322da5fff9956d517bac1320b0f5d1ef1cdb996c31b71dcfa5082eacc8c6817d67657a827ad92a693fe7ec7c0a35dbb3c8ed9329211fe0753a037c1432cf6470a13ba44046f8609453b4425a2eb307b9a812601392f6adc6eaad7c1efccc0669406334b644c4958a987ec38a6acd178869e86746c8da24fb2fa0923ba46f2e7d37d8a7cee6503ae287832557a67e3ab3fe82e994f4c6f6a6cdbe15614a23271559fca73d5f9d908f2bab798f72ca1437fa2322d51e57e0c13d4ccb62ad9ba605f21c7b353ffeae87401129eb3a7fc60c2c015f7820480228b30f445af2bd321bf6886b7b8697803fd41fc433e0d7aa0df1801a4f936302a7c87fe3f311f4d4644038c2e02957b548eed4943c0c8c9e9fcf1260a0a174b14a9e2b1c37b83838c81b6f86401d1b12542ac2f662cc9f424d017933195c9aa836b8e9291abc4ddf998bb3b99403d9da8be6f08d846e16d6ef1e5c73154f627806f9040e9853eeff83ec602ae55bcc36627f8e2b17a6548c66d8dc4651aa5611bbbac0eb613b29ba18473106b787a76c154dcfbf9740f72566484d3a4782579520483af3dc0e2ec7df31c27c57c18d00a912393d31ca2b2bf28b9463ff780c4295920740eeff3dd258a104f886683f26770a2360fd855728d00cc0245780a78404c9944ceca5767484144af80b23893cd429d6468ce5d6ccd087464f83c862737e5a746e9ca6887ce779acbb1209f997da020d0de105c7c9852267c3ed1f576191ae3f20da0214cb06253833015567a22e0815c1370c1dc3832b4f1e77f1491c4b74bbabf85d051a8fcb39d1500cdcf6e6bc45ed3ee770971c66d8a854b00794f26550c9411e54c3840a063747504bff3cfc66b0c175c3809a2124f043c13c82b882adced5ecd7b56353a26e1c2540560cc4e1e01ccf9e0c8934e5e00a6ec13d6c9cb08c16705f4250724659587d106f289c6fa3ecc90e20310800b6323b9589d7e1d2b3f230c9e6ca02d019928b3c21e13f38541b87f2e608230a0e4c161c24048d0368e387c4d71fdc4409a2dca82494049a6f7c3d757f4494109dc99fcf94c6dd2ab2ccff61533f31136da70853ad0e1b9715e57fad703f31fe930e1c5cd0cbca0baf4ad53e4ef1ba00db088b7d1d1e39c469253adeb29ba459227418b068819eb96904a240e90f7b3a54a2b0a398109cb676b6370ab86bc4197400407a02a2e5a26452e5aeef08296481afaa0a2fccf306e5a9d88267352726ec7d38a438ef75b50234719b29f83277d1fd31dc778cd381a481a6bd198c3b2c3a5378b094d0bcb96a121680b55ca83cc89a1236ab8777220071be7f85b3b0ec83ea1e5334d1017fcc818b1f6411c85552d53fd3b915611bd7359b14466980b72f80e769cf6f9e9ada0bf5a949a8a3fb441c1aec3637e80dcb5834657cf1b5c5e6ca263e31121429e94f1d2566045bff99f87f5d64c4641737057d8061fc65109615be0e9913b80923ae766324c5c73d743f8788ae852105d0a9168ca47b1d6a28b7d9fdc87ecf2c84a98bffc6c75be7057151cdaf46f887ec85d30ba302fc5dc1deac9ebdb34d493303530422fa3af3750350f326f9ba76fde21ab798393796533fef51c3dcc2c7ffab00d941e1fd13f54a8806925a86e2b303abb94094defbd96adcffe01b6f5d9cf15396454b6216ea5b3832bf99703f9dd3ca0127964d772a7b83efbcb727df6e53e873780de8930f15c9f5d3900dfae38918345a121180794ae3a142e26b3ebb3a781858f551f1d76c6ffdefcc8e4ec797df6a85c7f5b84939af957eda68190da8a4a0be756e25950babd27b8b8cde606496f99c3b58cc1d820abc7c03574e6c981c6e7c798a0e755c8674004f113a401599e7d40b803c9a236d484643a262511ef46172ad7621a7b5c731a2cd9662a3ea7840d29a0dd3310424faa60199e15fc4c2199e6e9d0bf42bf35e640234ad2574934b1a39b75e09440d4a04788ae6e6b939fe17997060e904765ccde109d35152a54b1278cd0c174618edebbfc689a3b259a9e746d768ddf44f7ab9ec7a40b3af72ca5c5acef3508f7acfd19bd5aa5772a83b02ea45f22c7e52fc6e896ddcfcacc509a7bd1cf03c405cc1310071cd1fa8e0f58a7001cf3aabf0aa44017787f7ec1deab6396dce01392c96d82f47730c31d1b1a5e6f30e81890374ea814ad05d4cf331164d489826673570b205827c4588fee606480af3180d9b9a62e77008031d7f655cf502f4a17fbf81b41ad29d1adc38c95b970f4d44150f87b7b457acccacfc7879e23002fdea69e8b50449ace8f4cd17fe074c31062498396e862df39d14675c30d76f606472899665aaa20f0834f8f81c6886496fdb2aba6b240693921242b4c09243a02400aab791b9c4f7ecf8500f5ed2ce0db05ea5626d256a9e4b520edbf6519b21165cbc71fb4d364f5051c1f81f9b5b11ed298c6f17e4fb77bbadcd3dd2dddeee8e68d76eb387f7bb92b37d1d7b17f160c17072b9ebd1c141701c1d2f4b370673170a820f9aee32d73836de0610c25beaecf5e7ecb599a2d95a59ca5a2f650a8878b91b90fec89f2db4866069b846c5703e31a4c2c051b89a5b1d6832515f4a60a5a2780f5a641a488febb27e64faafd0ce686c779e8100132858a5420814598934a5cee22319b3d882a4ae879c7f0ab4436e072257b7d0b8bd1e3dd7323b5ef3211004d438824194d42227f9166641424140cf961086929c9ab72baba077b376d867835d88016c7fef11e0b026a6f6e0467bf237758043041095bad4cb98c3e09e1342b8601766994bb78d6ddf3f6164a5f6e89069827234e35abb7cfd8bae5210285fcd7e0479c8497968768a10313f3e80f08e765bc9d5e9d8a4be6e9ed5b0302dd676054b16bf6c8c7a14585b2d26ecd4f6a538118a3640da763829db730789c1d84eaff934d7987a3495c1d5e76460ba277226d0e3f6a529f45702d652378fa4de18e0e1a108f917be35f82409745d64d07766a115e801804e4a473220ad167c7eaae7286682b5df619c8848600e1b118fc8b9985dc9f5b983357398918b02330104d50f4168b1844c7a977f181857faf41def0f6ce046813ba1d438147959f72b1caa09fa1a5cf2a3c8b2ae38a845013f8ecff559629f1f58d78497cc13f7e4a4528cba4630731941a8c753ed663c113b2062cfe06c4e255fc20e6f2c6aafa3a87d6dd9c0c921f7023de467308366d322c1bc61336152c0830c22d54434ca76ac0571a89813dce737b69200b27078fa6080c7b5c29b379b9bea59bdad6ac79921012138b9ed38fa86c28a3acc1fb6dfbd3ab811e0357e6c67ed3576f8e948baaf83346a28ba29635f950941746f01dcb2a8d6e56cfa43f504aee8ecc545063160d4df8391406c50320cce01144fe4488ee33c86a31265a8705828fa18be1d5b82529336d90cfe408564f97a8816c70994884b52f5c4213931a6b6e754b543fc2d75054c7b8ad06b6912618e16eb61cfb2cbff56f731111c1dfc23a1be3c0d0b68cd28150e250a16713605ac13f5b10900c83ae1b497c3fc5ef555170026ae46a7d11688a246d6104bb87c0e965c542c421a0564c4df5245cfa4d01f9e8577e0a766a7962a26d3cc964252123dbcfc39846db13108a53fe65ed90fd882588169d79aae6ed9321adc9b9e2755e42096a237f86b2f150b5155a61d4d344e95b9e1b20f63ef2ad253db97943f1b81ca94cd6734417ec78cf9891714b867930f1c75ca229fbcb0b6d1bf2716d234999fb53d3748802e33ef4f166eb21c1181cf9b97e65081256bfe75b2146e41cfdeeb2d911f2a12018c14be73ed7dbfb571d7da6c15abae250da485c0b7e972d4700e3e016a63f0303127081fc465dedc61df735484b363aa7db74afc126858a441cd69d8a8d40b754525ed2c7d73c48254d7f1e08886d180f450d00acad96145274cec0b12c79bf7973f7710696d508b0a571063fba17b040bb5cb338264865bd12d899762e8135a7aa58b25483dc0bfb2baa9b1b83826131d352a8816bd49c00fe16db7d00c47c90ab4ca827c909b1c446286807bd2aef918344e770b433b06e71fd677dde02f6bf332765b64e649aae9294595165e60f4a0d7b297259f9094359a0e7454d9d93f4d141f685ed01374b7c79ee51df549b8204d843f4c40e4247b22da922aba2294318164eca67268b5660ec6ba00bfcbc79ef13b25179da7b4ac5bf3d60ecef9052f6148db2bf043d5e75ac3322759264fef4f182da176bd14b027ee908398f218ee0f2d2f18d0c464ad2e1935f048d4035818ab111b16c52ebfd648814932e271cac8a0102bedb1a12d5715b122bd6c12e94b78768debaa5c3342099535bf8556c265b89942cd19532b0e311822bd68acf33f0ee2af84dc5712411ae9efc8df36af4f2583ce404556769f1b2d894b36e13921c47619d4661fd91b6f18af8706318d1b048753e36ba127c71fb056a14d639a142661b77d3d270d5f1b1146b0576d6ba3ac2549b1c568a11f1a2d5b70436575660b5a81ce41e4a9c7b76458be1068eee86e76ff652d2e964434f004a001df769fd68c7669953b32d7502f18187c6fa6dc9fb9f5c668c2bf0dc913a6fd9dccb1fcc3a7c0976af4ac937a89f66a3cfba8c7cc39c633c2cba5ad5b7ce0efe7459f7d253411471c9e9c5e9e2ec981011badafb892451f4fad043a654d24047645a41c36cda479bd8f86a95ca8376ccad332a8772fa66e0ea60a543da649f241354708359e88adf9fc91159c8402bf32307317e6c35bcf05f74bfacbfb761e86ada983c36add1c0d31499992843787755dc55923565fc44cef91543f6a5fdc3c1db3c58e40a049e6f0514daeae60e9c98b9cf8ea732ca4db03dfb7c3b06238bac2a876613bbc4c0f7423e3166fd768cae92c10de2744a72560eb65e0ce68e130713be98d57cbd95b8f4e013825882e4c450c5659cb10bcfe382c6282a8c3bd7841903d5a3915643e0115a013b8acbe6c6dc5d4372d9d31f2f120634bddda39f6afdb716a90359ae78ec7a022ec31a5f04e2ed0573893202978ff39aa3f42b18cc79af1b98b90b1411a439454027740ba4039cb42ab4a729e0034f02a1e06a040714da1c037013b31183d93f8b3c4e59a7d2a245c82be4a9b7acc5eae798a7095cfb7140e4c590f14da3460719c35c0b4473ea659f452a17aa367812c8a7b068eaa0a4d80601b7eec2d1a3022e5a6c4de39c5b349d7cf0a19159eb03cc4150b41628c106809b4ceceeb9a8b115ce31e1e12fc5aa78907777e302a7c6408ffd8bd384ea29d2f39e00b68538a9ed3bd1b23b8f1fe073727a71881f13461125fb1969a2146fc3aefd0972ea87f8739536ccb1bdc06b94c9ea03f05e5fb5071c51ae8f6326362a2e19c602ba12811e9f220dfa4af617a073feb0c9507f6f50b420a73e04ecb4c59fae1ddaf8826d1bd6888a7cd59875e9ed5fd32eab98fd957f19fd0b4c0789afc055ffbcd3427358e5c6e3fbf22f03845359ab595df6cbb120ad8cf5d2810018630372e9b23663f043839e0bb99f4db4f14c9ea19568770d060d0ce16181374b163713a948929ffcef126dd34a5463c74ddb04868ace3eac2c331802b930aede61ec40345b4da63138eab74c19409eed18ffb702c9a064141c0e080751666a93cae337e3db34bdaf866f1ef8701a59e96250f2822d18e14e8a7e55c71c6aa3cc15e34a76c09e6ed920748694437320191213b70ee5ca14bb0478238faa7b9a23cbdd8dd856652ca03fb010b1c89223e7fa60da461364be6840eb6d44b0b82c9720d7d6fe8914566ac4c0d56ef4b2247e9a02629685e3e0011b67ce843ad319f878a9092c070e9dca2e665ff8578c3fdc96657ec7890cdd7cc36be3fefc1aec83fb1cffb18fd9600692707e1f0a087ab00b4eee3d12a87173006cf080db669b9c8d77f9220c045d88774ee45a6441515afc1213c6a6ec071fc544f781458f405309ed48776a06ec19fbb54369054ce8b449fe588be56f93d3d4d9b87bc8842fd88c8727fdb945f81887d7ebe891647721c6a20ebf0c6b309484bae5c6ea57bc90a0016291c71788132b5529937386def22bbe3ba6b886c1c8c33040079e01f9519f16b9376fbcdacb7e1b307bf60bacc6fa74bf5d7957c8c6e556470b351e823e00e3b2e4fe7ac584b45f24fa61ea7ca0aeb9979f4ccaa05e7a327aaa99e4b1ccceb29b595320bdcbb97f357b4f0e45b4a4c592d9da3d04e67160bf8a74dcdd973ffbb14f006e6903da37a0ceb89afe85d22bc0432d64c66cf861391dfb41e51ecaf875a86395b5012b26fddd3a371891617137610398c3894a75d7582898e65ef5094230d04b35b6a843f0912f7979", + "patch": { + "balances": { + "balances": [ + [ + "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY", + 1000 + ], + [ + "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty", + 1000 + ], + [ + "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y", + 1000 + ], + [ + "5DAAnrj7VHTznn2AWBemMuyBwZWs6FNFjdyVXUeYum3PTXFy", + 1000 + ], + [ + "5HGjWAeFDfFCWPsjFQdVV2Msvz2XtMktvgocEZcCj68kUMaw", + 1000 + ], + [ + "5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL", + 1000 + ], + [ + "5GNJqTPyNqANBkUVMN1LPPrxXnFouWXoe2wNSmmEoLctxiZY", + 1000 + ], + [ + "5HpG9w8EBLe5XCrbczpwq5TSXvedjrBGCwqxK1iQ7qUsSWFc", + 1000 + ], + [ + "5Ck5SLSHYac6WFt5UZRSsdJjwmpSZq85fd5TRNAdZQVzEAPT", + 1000 + ], + [ + "5HKPmK9GYtE1PSLsS1qiYU9xQ9Si1NcEhdeCq9sw5bqu4ns8", + 1000 + ], + [ + "5FCfAonRZgTFrTd9HREEyeJjDpT397KMzizE6T3DvebLFE7n", + 1000 + ], + [ + "5CRmqmsiNFExV6VbdmPJViVxrWmkaXXvBrSX8oqBT8R9vmWk", + 1000 + ], + [ + "5Fxune7f71ZbpP2FoY3mhYcmM596Erhv1gRue4nsPwkxMR4n", + 1000 + ], + [ + "5CUjxa4wVKMj3FqKdqAUf7zcEMr4MYAjXeWmUf44B41neLmJ", + 1000 + ] + ] + }, + "sudo": { + "key": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY" + } + } + } + }, + "id": "custom", + "name": "Custom", + "para_id": 1000, + "properties": { + "tokenDecimals": 12, + "tokenSymbol": "UNIT" + }, + "protocolId": null, + "relay_chain": "dev", + "telemetryEndpoints": null +} \ No newline at end of file diff --git a/templates/minimal/runtime/src/lib.rs b/templates/minimal/runtime/src/lib.rs index 972c7500f3993f5a362e422e300262025146ce1c..5d549bf1a912d7be414b206d9cdf73ad75c3161c 100644 --- a/templates/minimal/runtime/src/lib.rs +++ b/templates/minimal/runtime/src/lib.rs @@ -138,7 +138,8 @@ mod runtime { RuntimeHoldReason, RuntimeSlashReason, RuntimeLockId, - RuntimeTask + RuntimeTask, + RuntimeViewFunction )] pub struct Runtime; diff --git a/templates/minimal/zombienet-omni-node.toml b/templates/minimal/zombienet-omni-node.toml index acd5b121c67449150d41859709992d85fc198c8a..55539fd2086203508aadb4103454c42049708c54 100644 --- a/templates/minimal/zombienet-omni-node.toml +++ b/templates/minimal/zombienet-omni-node.toml @@ -1,8 +1,8 @@ [relaychain] default_command = "polkadot-omni-node" chain = "dev" -chain_spec_path = "<path/to/chain_spec.json>" -default_args = ["--dev"] +chain_spec_path = "./dev_chain_spec.json" +default_args = ["--dev-block-time 3000"] [[relaychain.nodes]] name = "alice" diff --git a/templates/parachain/README.docify.md b/templates/parachain/README.docify.md index 47385e0bbf197b6a5e08310ce94e9f97b33d9124..0d6071ddd95116d77f4633ac6ea73d663e60c204 100644 --- a/templates/parachain/README.docify.md +++ b/templates/parachain/README.docify.md @@ -144,10 +144,17 @@ export PATH="$PATH:<path/to/binaries>" #### Update `zombienet-omni-node.toml` with a valid chain spec path +To simplify the process of using the parachain-template with zombienet and Omni Node, we've added a pre-configured +development chain spec (dev_chain_spec.json) to the parachain template. The zombienet-omni-node.toml file of this +template points to it, but you can update it to an updated chain spec generated on your machine. To generate a +chain spec refer to [staging-chain-spec-builder](https://crates.io/crates/staging-chain-spec-builder) + +Then make the changes in the network specification like so: + ```toml # ... [[parachains]] -id = {{PARACHAIN_ID}} +id = "<PARACHAIN_ID>" chain_spec_path = "<TO BE UPDATED WITH A VALID PATH>" # ... ``` diff --git a/templates/parachain/README.md b/templates/parachain/README.md index 15e9f7fe61cf08f523cb9b4edc72a5128aeaab91..818fbcb693d1f157805c7f3c25c27361410d0a0c 100644 --- a/templates/parachain/README.md +++ b/templates/parachain/README.md @@ -146,10 +146,17 @@ export PATH="$PATH:<path/to/binaries>" #### Update `zombienet-omni-node.toml` with a valid chain spec path +To simplify the process of using the parachain-template with zombienet and Omni Node, we've added a pre-configured +development chain spec (dev_chain_spec.json) to the parachain template. The zombienet-omni-node.toml file of this +template points to it, but you can update it to an updated chain spec generated on your machine. To generate a +chain spec refer to [staging-chain-spec-builder](https://crates.io/crates/staging-chain-spec-builder) + +Then make the changes in the network specification like so: + ```toml # ... [[parachains]] -id = {{PARACHAIN_ID}} +id = "<PARACHAIN_ID>" chain_spec_path = "<TO BE UPDATED WITH A VALID PATH>" # ... ``` diff --git a/templates/parachain/dev_chain_spec.json b/templates/parachain/dev_chain_spec.json new file mode 100644 index 0000000000000000000000000000000000000000..e114204ebdc517431e0c7faffc11af73d020f29b --- /dev/null +++ b/templates/parachain/dev_chain_spec.json @@ -0,0 +1,108 @@ +{ + "bootNodes": [], + "chainType": "Live", + "codeSubstitutes": {}, + "genesis": { + "runtimeGenesis": { + "code": "0x52bc537646db8e0528b52ffd00589cb4052ec5c75e185310686894746ada41c31b10bbc208bc099f203dba4ea0f0df2c84da4097c22a2461c16f39afa1334274bbb07b0ddc6a3e2a1b6703863823c00bf144a3bc028dbdc423f48ff8e8be25ad114208d964efbdf79601581ba6172b175f42243fe4444be4873cc889dc1c8b008527508889897966623a1113d3b9c7dc2c6f500f371b1da109396801c771cf4ce48998c89bcedd3ce40e40c8cd19908113634082c9647a66c283bce9e620b707d8f50770b3f544149e0801ce52de890d96cf4c844ec484870b5d3e5fc7cf31177ae6cec3b3bc5900d707d8f5b19b2514564ca10ace4cf089783813a10b04ecfaf806f11c7421e0c4c23c9c891319ccc39dd8601eee0fb0eb9b6e1de6da51c7398eef9ce73fafe13f0ee43a7c87000420003ae8a0430e39e40004c89d9830101c70c0e1c78f1f0000c09d9830009e7d9e7752a9d4330dcf3a76ecd8f1dce399a7a7a7e7d986e78e078f3ba9c13c9e6f78fef1f1f179563dfba081863ba9c1343c03a954aa1b6eb8c1061beec4846de8d1e34e4cb8c7f3cfb3cecececeb38fe7940e1d775283753cd7f0bc8387e74e6a30cf33006aa8e14e4cb886671ecfd7d1b9931aacf3dcd375775283bbe71a7cf8f0f1f3f3d3757762c2dd73ea19c75afbbce339e7de3ba9c1f7b9e719478e1c77528373f4e8712735b8070d34d0e0e3e3c383078f9e9e3b31e19e1d3b76a452291d9d3b31619de79ce7938d8dcd338e6719140af5fce7999b9b9be79de71b3838775283719e753cdb9c9c9c679ee78b03c79dd4601ccf1d0f0f8f0e1d3a7676eec48477fe3b31e13fdb67ed743a3ddf671b19993ba9c132cf399e513333775283679e7572e4b81313cef18cf33c35ed4e6ab0f67c73e3c69dd4e01bcf39eebdd6da1b37eec4846f3cdb3c67366cd878463dd7c0c0dc490d8679be79a6a1f44e6a30fdefa4061f070e1c39393938383837377762c2372814cac6c646d3eec484b5e79ae7188ee39e699e4da552e9793e6fb5de490daecfa7672bcbeea40667cf32cf366a6a6a78cc3cc3d0d0dc490da6b1e1c6cccc8c8c8ccce97427267c9af34e4c783edbe8ae9898980af3c3692693897b2e9db66da3d16e66d204c3f44c9c6c98de8909d3e74c07ebebba64bdb1ac3ba9c1d661d7cff407ecfa4c9a443ccfc44909cf3ba9c1f34a295f4483e5d501764dc4831050256f1602761d2f8a087c3c7cbc43f19d84dff383626f41e083e0d190b7c31859ebe44ec2f0fdde7b37480ea0f6a0f9c0fd70028226889b562d59d28406c737a9387e4951c544710d241c5f4483e385c077e02ace3f22d093274f9cc0e125139a7782072e28a1f9274ef4972424a1283d42f35172109a77e207121292909429340fbf0317df4b709df4441af8078eef8d080e583eda21f903efc0fdc0f06f28fe07eeadc80f1c2f110f58881db8873be9890fe057399a7718be23500be51f0c3fad10f0864e8a50929175c7f5dffbc29d1425099f6aa6b4de97b39e3ea35683dd7cb51cece6dffc7cc5537e3e93367efe06aa92c8bf4ff95e64285e09242424240cef952bc8152917baae1116cb3abca822f0b7e8e177ad8b12f2b03c8a486d02cb3f2c71c5588886e21be7239ce5e38320b58d8dbcc32be71dba8450055943d57ba69650d550d558bea10a7e3e835b90f8ec6570cec7675393364bdc9f768b37835ab4306ad1bef706e5adb08b4182e0d6436378041f1c41d63a70effdac555c6f36b2d6c9c7ef12aae0fb0d55f1fdac7f701cecdeb7210f571cb87c7a3857fc4e03edc327a87abf812af807e183a001bae2f88ae34515918f9737dfa287e18360d63fb8c68d7b1b7284e1d57977e8f2bd2ea264c11c0492428d05ee6b50f5709f06aa1af75ba7efd071e7387a0f08142962bc29b8780eaaf2717cfc23d0132cf1f2f15d047a82254b1c2f6f940b617938fe0481a0504c7a72058ed7a02ae2f8780955eff1ad138dc8ba6182c0620cd835965b909bcc892db89f995e7c7eef5d093b08efdba27d18dac6cfc20dc2ee417b04dfab9235ce2a54e587e5fbdd40deb304e2fabd0d91b7664f937ff2f93df9273ff4fa3d3e9316e224dc843e9c356923deb8e0261ac459c3f019d4a49578d34a0d64c943c2443ce026546b204b9e17dc2406bfc347bb24e2ac49a4de88705a6f441e127ef14130b2c6f0ef395ec2ae9f455b61d7f0f1fdde8cc00fc55b61d73f7aaf87ac5f07b84e7222097752135d703661f86602eea426d2c099a9753287e11baa1a76b962f85c71bf2150c3147c3f7b5b11dc7b272149a95095add3c3dbf484c1599fcfd456d8c1572b61070f847bf861eb8de1b3a711b12e7d109cb66117ffb6f9ec4dfb30dce6b3f81a9634a8a2879750550f5fa1aa31bc651b67fd83a3afcfaa7df86df5368409020b3260d798de26082db2b44fe30c6ad436aef6e1ec6df470eba1317db58d336a8b9e0f4798fe6d444124ece2897098beb7201aecdebcf908cf4aabcd12e7f8a288adf716643e0866596f43ac9b25b67ebdda7c5c4f6dce39530b209195c0f50dbbfaa07859a21596af36dfe0f8ec69966d4c6de3de8c482ca7258a58beb720f24ad8bd07c1681b76efad03ef10873bc7517d520459bf29b84e6a428cac1f0ab84e6a420b6e9c390c4f0355b9c3f0f05d048a87bf81404f089e83aa4e42ea02c39fa00a62f8de82d08206edd3380846fb044bd6307c940b61795883aa3e7cebc03bf4833b87d13b7af05191f583d1604703bbf7893b0909099f60f7de3559d60d13041663c0aeb1845dbfb7200dbb7e10ec9bac7bb8f77e5f3d39785b388118588f969e2c7a6ad043831e2c7a74d063839e2b7a56d013831e2a7aacf45ce951414f0b7aaae8c1d293821e17f4b0a007053d5610d123a5a7043d1de8f140cf941e0ef43cd1b3811e2a3d51f440d1f3819e11f488e055e909410f0876a4b1438c1d67f420ed10c38e2e3bb4b0e3cb8e31ecc0c20e2f3bbcb0038d1d4dd8e1841d50d841851d51d821851d63ec98c28e27ece0b2830b3bb2b0630b3bc0b043093bccd8f1851d49d8b1841d61ecd8b2e38b1d48d801c60e29763c913a426a4b6a09a924a4c24881914242ca8b94155264a4a6903a232585d416525c525d487121f545aa09292da49e906242ca8c5416525548512115859413525d5265a49490c242ea0a2921a47ed0e120e583540f5249dd968e0a1e1bf094d1d980e70a9d950e09a9187460745c78b4e8929062412785ee07dd10ba2c3a1f743ae876d0dd2085a553417745c7029e11742b48b9a0834137829413a927a928a90e745f521a483d918292ba82070b3c62e0e9c223021e3278b2e0c141aa05a915f0d020554507821415a92ba92c78d0e00183c7073c4448f18007093c49a90da4a6a4a4a490524da438d0add19d81e70c3c27e0b9d261c16385070a9e1cf0ec80e7063c5bf0f080870b9e15f0e880078bce0c1d1a5d14ba31745ce866d081a1db4257a5334157864e0c3c61e8acd0a5d1c5a0c3c253059e0ff070e9bca4b6e001437782ee053c54e8d44869d191a02b010f19ba297454e8c8c033a50b03cf18523b48e9a02b42a7a5eb428a8b0e053c56e852d04dd179a1fb820e2874804007151d53747c4087077420e9d8800e293b58d82163e70a3b65ec7cb173841d2f76b4ec106167083b5b76a8d859c1ce951d18ec5cb1f3829d2c76b0b04cd831c28e0d768ab093841d1cec58d949daf9c10e10ae963b842bc66dc265c25dc2ade2b2e0aee052716b706970b35c25dc2d178c9b84fbc5cde216e112e162716d7067706570b1dc2b6e0c2e0cee0bae15f7ca75c115c20dc2ede202e1fee0fae026dd1e5c1e5c2eee16578b2bc545c12dc1ad724970a3b823b850dc2877caf58055e322d9352e157b86db015b86fbc4e5c0d58035830583c58255820dc382616b609360b1b037b059ec16bb858d81b581c581a5c25eb12eb02ab0565e096c0a2c0b5e0e8eb026b022b0536c073e8553e1607ccb7b701c1c8b5ff11bdc06af010e97c780db720ffc03394ac8112387063938886ae01c01e70bd3153722c071851c31e478c9be684d6848d91a365a6e6690d3054d0325277046c03103f7054704ae089c169c2f385e70d0c8a902e70adfc0a1d83871a2527960e30c9c0970a88073c69f388160e6cbcc194e526c98e15270acc07500a78c47c191c275051b65b0f105b5458e14385dc811414e14385cc809c10da4921172a0c0d23821d97820b342f645b6844c0959153227645ac8b29075c9c8c8cac8b0905d216b4206852c099914b230b23132246451c8a89089914d216302c6042c0c6c0998123230b227645b3233322e3728c06a703305e7050e183824e0ac9133c67be249315531d9c034852905a62b262c4c2c30b5c024058e0c70b094ba70d3e5060ba82e505aa0bc80e201c7011410505e5041c841e35c60373085e114861b3430a9a0660c1315364db041814d086c626063850d143632b099810d169b2c3657d8d4c08606a711d850297961f3848d94d3066ca2d85ce14ec09500670a3622b019010e16503ba819438d1830226045c0b46046c0865013849a2e6c52607302b805faa0e60b4c193567c01fe028a1a60ad6093723c0b0c8c66092c10e1264143aaa4813d4a440a2c064c54e0f5022a8c1e2615193a5660697154c55c8294c35306181d1029c829d8199818101230326064c0b5818302ed040b9a106cd139c2adc3843ce0f6e3c71434ace12728e9043841c26e460c9b922c7073931c819c28d2c9cb2385571438bcd941b42c0f102678bdc82b3841b30b861051b03f6056c0b5816302f181a9817b02edcd0c08d26726c90d3839c24e4d42007083945c8d141ce0d72b0c809234706395a72789003464e16394dc87941ce173948c80942ce0c72b6c83142ce0e72b4c881410e17395de424e5e420274b8e10729c90b325c78b9e2966d0b88162e608335ecc68a1238a9e2a3357542e6c3470230c758b52112e2afcc98d2fdc00c30c141916cc68404605334dc85c9169814c15325d645c70830c32556c1537d0b8e1059b854c961b629009c3e620864122a5a43879c1e9728a8283e2f481d39313074e509caa9c767032c10907a7294e5b9c52c041e19ed820034705470ba8244e8a8d354e529c9eb0a972cac1890527149c4e80f38453132728262ba619f078e0d40528052e0938637024b831861309b82e1c0a4a4ae094c045e19ee03ec099c179801b0137850b011705ce0a1c324a6694968003051b0e9c9c908982abc24951e2820d354e534e22b08152ba42e909361bc0d942890a9c166e5c4053e584064c14709260ea622ac34446ce15b232d04891a5012346a6064d14272f6466b8b1c2b304930b6e546012410e19304eb861c10d1530c904050d096e566022812543290aa5324c4d94b694b050aa42e90825304a652835e1461a37cac039513ac30604a81f94ac80e2a2f445a98bcd935218a52c9c3c50820227829218252994b898904a53e0a29859a3e4c5a603a52fa5317020e03650fac285859c2794d02879a1b48553149c2894c060f3011c334a4c388500d503cc8b921820074a6b4012947450ca025e812e802d80554016c015402aa015a8029802880238053c0134012c01ac02a580514028e008a0086098702f9e1660c880e1022a8a9a344c25903e7811646a702da52a4c62a89902278c9a27d44001c708273058314a51708a509a52e2c08e284e1a9059e470e154822d09395030c1c04483a783c865870b9983d317b019602cc87c6092627a0253a384046c0a1817cc0c18181812b02d5812b032d8c0c0e605d817d811b033ec98e142e3024325434da39484921630282e2f253270b2707541f9e0aac24546698c53076ca4b8ccc03880457179e12ae33a03eb003645460aee0857172470c30cb605350b3757aa166ea4902181e6816b08560c38605c25b8aa6853ea186a146a0f6a928d094c596e6400d30408460d186ac2003305182cdc5cb113841b2c364030c5e09ee09ae02606305430a1404708767260f3039b225833ec19a628ea152a19d50ab50a5b19766a9091c176a94bb869c14d15353ca8e122670d9309785c50c3851c3360ac90f3a5460b3548308de14ac14186f885520f5059c06401e60aa61bc048413ac103021c24a05090aa02334689075b10609e5083c691204f703101a60b3c66c8d142490630667450e0e0826905305c525a70542165059503a9839d2e6ab050d303eb01d30b6a13b40fa48c005385541172bae49c51b385ee8b1a2992073959e86a50e2e25a4204034c82e904305bb048180e503880e9c2a3842e0a4c073b3740a580670affe2c68a9c2d745e7c0d1e2bba235c61d80003060a355fc82923070b376eb02384d410de44ce1960cee009a393c286127892601ac10d2b6acab87941b7011c54e029030f0b78d2e8b2e048e306163c5b5228b881814d83a706300a581629227455e8c8c07260d345aa8b4e089b103a19f05051f38404822482fca20706b208d208f2077207ff22b10821632061205f205d20ab4829e40724955886680669458240aee064904f2494e8257e896b4434a2186217e2182217a4067490006a01768158804f804e80654028e88802c78054805c2013a0126e860b011a012e0186f1215c8d9701f6e047803c805b9c08b003d00a88c5a3006500b1bc351e17600ea006e007a0072017cf8c97854be16778633c28bc29bc28401014113d0e2079523c0fbc29493ca4d70493219638a00141306001030022010838c00f0a3040018a1080480f43840820871a7cfcece841834feadd00d3227bb8df298c0b46244c8698c01124864062812347b2178b5082e4c811ccc7e72604cd04c905865072047543a58b903041b204892345482a5073038246523444111326463041a204c9109b9b0f1071e4080a28219224c911022822024992244708a0e7c6033f375392241982882449861040072c50540125489270a09120a1c091238a8e1459a00246207192ba79a299243162882224451c418284023c3752fa080a2831e2c8124b902441b4c4103ffc66038d84082547283932c4112390c04888507284018a942471041144609c9b28451c4104922270dc4069264b20193ac284c912488a2839c208264c9024c0de3c69274620819720195a7204038cd81b27fa08922490247100208a4052810a0c0144cf8d069ac91011482c40c44d13cda448099225482ca0c488df202931820228d49726c208264a8c5852a40492234b24410289218e2c415244122392101a22e288244237a835da0912239a087182c488052020853a4333b141a9d1431cb94199a12f706488a2218a18a2084901605065c08011498630a2c8082546c8a0c890041148944012834aa3971c21000d358656720412491c29228911494ce08892218838620412b84809920b540049028a40524412498850628412050cb12409cc8312433341624491114b8eb040511243d84085a1951c6144d1104b9228e248d11149981c3102093cc49224b08ce9033d44c4114926700449d110451891648826a57e48924c608822254950e0481111489618518412238e1ca9c97195c0da2286165ee03eca3a090909bfa35843b12db02d1e12cf92dc7befe1e070ef3d4e460687e338ee8a93c628e7b4daa2742be5443867b609a38c55ce5aa22894f401d62ae935e7253bc6d930cabee6359bbe17e39c94ce6c66b3d639698e19e3c4b039e78c315e57d3a672ca1d51f66c487bce481bf675d5da978c3d3bc66b5e59d634d22925a53de38bdd13a3578c598cd7451bc29e3d63a4714e08bbbb69379c35462a67acb3d6963593dd52d2d9fd6677bf9e5d678c595625bdaed85d6ba518462b86454a2336a1a471cecccc6815b625a385513aad1a69a431d28a4953ad5726e345e915a99475c648a79cb51ba395c658a4ca6eaee98b6fd249e37c5a849376946f3e08b3293313e7abb39b62592df59c354a3963acd112e0d69633764f5abb67cfee186bcbd874bef8289550d2d9dddd1a6d9b8e594ccf386562ec9e337657d9b3e71523bdbace39bbaf3967c79e39cf14a3a4b144698c945248a98c924619639c13764b2963ec5209a3d89c1b46bb648a447068ec81079554768c0d1ba6db9a3bf1c6536b301d69ecd8dd1da39415abb56252caf7a49cf43434343426d39c3de79c3dbbad1863974a0de78c39a21c026dd8a0dd0d23edd8d69cb1299d16a554522aa98c3036ed1969cc2165a53da594154e78d5965885f5f974539fd93042181bc6ae9d452ae3b4e96aea8c0aa157d3be68103969b7a413ab55d29e2d3b769d93365665d339b318af189bc70068c4b098180ca3514a0cebae526699cc32292386c5586995b5ca4aa9acb162f492751e93326231464a05705d58c422166322966159c44c52c2c6228df38210ce572114a23737373793bef9669c11c649e59c53ce599bca96598c31c648e9ac73d207e19bf1451495b49bd2a651a2b61863948fca5a258d7176a5904689a915e39c51d23853d3c6d8b2696c2b46d8b223ed53c738e98d91c69918638cb17bcecedad431c6d8b25b42d83576ad97cc6c648d92be4863a5d214218db14e5aaf8e32beae3433662f464a4ae793f549f824ad5276d74a6b954da58c36bef7ba9fbc268d70ce07e79b33a3339b336273ce78757784b369c719bb044b31ce39e7a4dd539229f5c8d20e5aa2a9d841ddb3bb69a4544a3a63376c4a639c7176d3d9b3237c31c649299434522925c564acb146d952b6ec8eb0d63963942db15a2995b3769cd1ea860d67c7287bce196b775f52d2186337cdb2ac562863a4b1ca482916df75c18861586c2cd248298d30b4bb2bedd81dbbbb676dd92d65b78c35f66c3a69ec27319ac5ae32bbaac44cd5b22c4a6b8489934a4cd22823adf49ab5d696affbc558bb5bca18678cdd1d63a4b2d68ac5c7184d94ca3925a5f04d49e794323e08a9a434c6186bc4260ff3cd49a10e2a63ec76e84c19a45de5ac35a334523a679d01e0e179f0c198f9ea9cdd7352ab9b52aa439573ce39dfcc01080e3ade7c313fe69b744ea0a99a16a4524a2aa5c42485524a3a27f66e28d1186795b12d4ae97c3de78b7176ecc9418f0ee28d864b2c39e202482e406d50e128718493a21cd50d35fc460d3e2aa0c4080b3019c202d7da07922648921c5162880be090a9c011498e5440891115a8c011496ae005721a0992251438b2e488a221883822499221960c51c484a766c766888821269024c9113b6cb0c19183a3e6c68d5544c4104c940cb1a4e848911117b8c0115dcd45d9508204092486b8b1f19312488a5062c41125460c6101222840812370b48f0b1851a4248925f707058a92c039b50f24163852a4c48825481c2182891117b80140114896202962c911475437d470a4062443432499c01124462c29da018024498c18faa981098f8faea1e88823ba9ff6310492255d0d92a123454a2051c2a3a6084905787ab40f26454c8c5002c90e1aba06258ca000922548fcd85832049224441491c4080b1071a42849124350004911a91a728a8658824409920a2cd9d9ba86229030618264091217388288234b9034398208244b8e0cc1a40822901cf131a4baa106248840c2044867090a18b10449932338f8b8e1861a8a4072e4882224965842c491222590e468a2044984691f47941c61049325489a20c180114c8e50e0882396207104490586587244119323454a200140132548626a5301ec95758419191d1dd5363aaa46471313e2e81dad8ee226c4d13b7a47cfc848c6a31a85387a46efe8c8c8c8480a71f48c8ca051b4ac23ba3aaaab2329c4d1333a32323a3aa2991046cfe80971f48c8c8c8c8c2e218c9e911126c4d13b825188367a42b4911114e2e819bd16a28d8c8c8c8ee65115a28d8c8e8ea41046af8f2c21fa880a71f48ea610dd110ad14747474752883e3a82421cbda327c4d13b3a3a8a42f4d113a200120cafbbdf05980cd101f5d8737d6ff97ae9d9d3e6e6c333562a3d0866721bf25e9fcdfa7eaff541306e45b0d7a152fbc49bda272261d93e71029c446a029b9e25ce12976eb24b88da0b12122e8ac1dc8b34cc5d8b4b8a28d696682fa2987b6f458e60d3212e9db34438b0e99a25e2e1692693e976f328d94c6ad066ecdab3de8640ed422e36fd6d441e15474d60d385d036de6cd6fe9ed9fed07be3daf8f584b12e073b7a6960077ff1bc27691f2e3deb89cc029cc49d14c5122cc04ddc49516ce9f6c9b16ddbb669cfbe6ddbb6bd75363164599665d8af675996656f9dac0bd7755d57bdf5ebbaaeebad7375c9881eee5bcfda8a01bf0d77920cc6804ff6ddb4cfd63ed62bec2c48f4f0b34bded5dac7fa90c6900a473fffa870f2f15962cbfad64082c05bb7ae351068bd752c2a64f0d036ce3279b386e5b3d84a7206ac2e2b254d06864c2081610cd75c87926018bb4ab06c42f83921b40e2d7c3de433f92aec2484cf8214e9240c6f0ec2f0d935df49b893a098827bfa004b69551c9368785eceabb50bb2f9c94155252233a84d2be5db32074fe16960d79d498dfe7a507cf64403bb879b3c4c27f62048ef103d7d94371761999181b3470c716f44b0875144fa0b2a38fbc4b20bce2e7c3de6b4f2c18ea57e3d66943689861f1dfac1189d3673ef27d861d6fa65ebdf4654f14dfbf4ebed2b6fbd1aec24ec38394646643ec6f9193fa36d5cad07c17a7aeb700b126f3ec2d5d270d9b44d1eaeb6c98b9ff0ed235f0b102fa37db4fea8556b7dbdd9fa23d2308c90c20823fc8312762d9f416b3d7bdb1078eb19d4de66fdddb22122048e8fb79b4715325fe9b56cb63e142312d08810b83e08e68763bddd3ce23721f3f1d607c577ab9fe1162433f5e9c97b44dfd442d60f468b4270c83213117aba1dd37e1dc3ecc9d2c08eda260f377958d360bf86b2f4eedba7b53b44ff1a735075dd7a63a687b3de82f484e16087fd076b7f5b90171483e0b3f9e121fa77b861da3d359087fb997dd8b26f9f3e07553fb87f590e76155baf08fdcb4cdae71fee2d4805eab54b734fefbaf9085fd7ecb37f0f8a9acdd885dd2c31f6eccf46981fd69e0970d403dccd43bb19b3441a661bbfcb12451cdf50b8c8e14824b195519be7dfab45bd4bf4b0757bb00fb6ec0decfaf347d6a351de5b27ff3cf91b913fb65ee185ddf51354618fa7c1b2ece6ecd7336a35a8ca9ed98733ed6f6bd85dcf6c63cd16454c9f3dd82f961eec3a1a1e371c7e375bf13dcb36be6ce5c116cd20ef9e6007e9df6d1bb79e309d0eece2ad1f763128b695363f4cf4be7cf9f205539b8b22eef7d56007dfdbbc1cece0b5d3753aa86a1c2f6de31ba83a8ee7d140228effc19de3087bf389ac08aecfbd1cba0b200fe2989999b141dde0d4ccccbc1a708f482221f5174188a06c2e330b3a864546d5fae5f0ba8c81fbf001b5501f7b39c84bebcea15f0f29d340fa0c40da4b610d0402c170bfdf1838c39b8d307cd6700c03ce47589a01cb9be16d027105963cfcce71305a4cb54164c24da4297792175a7013ede5d0386688ad2dc8bbc2bd5bf0d6468422bd676dbdf75e8def49f81eed4aefa76570b25390751f86e00b7ef815e021e178f343c2bd19814d1e966df311ee37d1c3b1db368eb6dba7ffa864930a969f9602dcd03c0fcef3b9aff06cdac648aef48fba8cbf775f7a9f44f111a2976243e85dfe4d81aa1396b7e959029793e0f91f9c4f38f7150ed0424fe8df9b023bf90870f94db902965ff5b9980ac3143950410eb270414212a27fcfa86da16791640c3ec0020dac800ba127517c84dea5d8107af6491428645dca0e42efd44ad94168850588f7d50f3125ffb6d0bb0a8a2979ebaeb00041ffeeea31254fef4fc754ae387752d27bee2d2d860d10e1ca169e00032a80712cdf8304ae858ea2f0828b14a4c00762d4000c422dd4cf3f401c0949e84d812a1e2cdf3af20e3d2a10ca136447624a66046ae01bdc49239002ce4cf0dd4096fce0f83c6f3eca4c703e4722189e9728124d232c7b33d264e0699d3e1be11cffacab84dea124fd05153c2f3dfd8a5e3aa0bfa02254afd4674afa0b2a7028499381e9e533c5935e254d0696cf5249009e246179af3061d4a3093fe8d1841fbc9b95c0f1d5f67b73c0b4572a51fcf2055f41c2f1400ba0b0820499306a3284aef77369c7ca0cb42049249a0c7c05a947137e804403f024a922f51754300d341942d7456a3284fa59c3f3dd3974f7c89d24022970d1c3579066a4400327b2808424d49709a37a91faf36679331238febd372060a8200517acf1040949a80b6003c34f486390c5b74eee2d183e8bf6e14ea2520696d6cd47d8caa216a978f9f9015599eba02ad6c3eb00819e502785e00986b7610b520497397ca882ff812a88e17f40a0c30741a00bc1f7005515c3fbd04022563d4c450d0c7fd281aa87aff71430d1fb82b310386e427a0c1c9f454da621b5690696cfa646b72059c0f299a5512c60f94cd286a578530389b7dbe75d268b6b77fc6c90ee0743af06bb796960f7a890f11ede823b87113ca250f220eb6702ae93a8848127ee2410a0813b664b775ff894c8847466a4db741b5bc960ec0770bd11e0084b796fbf3780ec3d7b56c8c3f5d9878fdecba1c59bd3a28a4cf9f9a69c6fcea10e4c3a27a594d249e9e97c9f76e8dd9e2774712426c5acfb70f3e1080ff52532c2fd0cfffac63bc4bda46c463a6dae9fa776a89e3e5a549138541fdf386ad4c63f9b413a9fcd67bd68e2f74c5acf54cebf77b80579fd6eae87b7c9c4d6836036b567ad196d8eaf77681edea254ce17c1903554c93f69f3441579a7a77768febd7106ed12221c4c5f3431fcc948d434a822b2701388e9611db22eebcdefd6e139a8da82c013861b914ecaf3d66d32317d36a1a5ef6d883c7c10a4f6bd9be3e71d92703e4805045b702781e009ce262cdf833b090450c899511b1b76af61972586a736be42553ec2f0569b39df16247eda876dfe3ead95f341b042154ac8c3f3f356fc4e6de3a19e277091c808430984d681d3b0c49949ce172fe7fb5a43150a5e21f0f191fecd0fc5cb53fa0a55906a380806412d593f80cb4c20e0227d387ab7c24e5e3e33f9406484e5e5dffbbd09640db3c62d330daa5045e2972f387ea808e20a34c170fc6b02e3e08eaf89ac6b4f185c3cbc7cbc7c266594f6e1dee2836094b6f1d17b48b20a55f16de33fe005a681aadce1a8e1f8a3038e9f198ed701aae4e36fb82d70fc09aa2096cf15677859a16a08bebe21100753f12d6fae58c234ece425ecdeb386df3387e3fbbdf7a40f50017a427ded6df0bd098197b74208e1103c50456380eb24113cc10fe9f019d0d3da52807b4810779208a0c00fbfbe790b22dfb689c47d698970f908c777034111c1b07cee2660f9253f585e2213eee7fe82733c7c50b40db5b60f07dcfbc3bd119d88c3f1dec0ee3da42d4fb03c05ea2e909084fa48b82f3393842afabe13b89f7503293dcb8eb4976cb78f767316840862faec6688b3bf6b361b61ede152666284b3cb63ef0672bdd43ea59bb3c76fbf6cb7cf76b3f6f8a09811595fbe7c5903cb6b361f0979996d8cd921799b3c4c9fe921a68f5b1179f8c6d99fcd0fbfc74d087de999451191a76ffcb621dabb7d9e6689de175c5fb2a822925abf6e7ef83a66f3c3d8336af3c3f4dbe56644fe41d003506079faac33a8f536647b76b3c459844d2a2ebd74df464462fa2cebad74f3112e5db34d2ad69ed9fc70f66e20dacdda9300c1dd3ed9b307c5ccc6f8de4a9728e2b705a1df6ca68fefad883ced024903383bf6fedb86bc2f58bbdd3e39fb7c76bb795c8fd83b52fbcc5b36c33ff8a3eb4d35b25e020d2c635ce22161da0132307d7c6682efc778186f86f277085ea2f705472bed10bcfcb3f1110b7c847f9f1b117878898e9030aa883c3cbcf908cb370e825947a0151620acd7c3bfa40854efea210959f72535ee07718d1f7e60b44fbf630adefcb4e0fe4b8aa97e7e48b8e7a51d926f4b038937cbbfe7adc84322224f6f8e971745047e1e7edea1f88784e163bc6f4bfbf483a0113c92306a21eb25b2ce00d7491cf0828f901e12c6de1168e6f03502c91c9e8b40a7c3d344201b877f048a397c1781600eff1381b8c3ff8840a6c367bd0db96ede7ebdf46873fc64a1e09cb350ba43e1fec4138272df739385627328a89b3e63a1a00e65e63b97b150e2a1c81cc76d58283c0ec5c67bee2ae73d87b1353a77c5837acd5dddecf8ca5ec7a13cf16cbe6353739baf52b7d9f9cae63d0ef3180ba507c75dddfb9cbbda71570078cd8ff7fc3d5fed78cf5ddd9ae3dc15ce7b0e25de557ce7f378573aefd1d1f92ae73a777573739daf7aeee3ddada9398ebbd2b92b1aaee317c7ef573ac7715735aad7f055cd6bb82b1f9ebbe2f9dfe33c77e5f3d7f0d55fc35df5d8b9f73dbedab9c1faf88f8efbc4cfcdcd69d0a1e32b1cd771573738dc107d624cc59a1d3b3d3a3638f7e2b03a28a09a9b9e9c1b14ce8e47950ae5e3403b8076542a95aa47a5c2c1c606c7b53b3a37efd1c1d9c9b9c9c1b9289bd46ddc517383c2c1b1430584a346c7265ebb93ca51a97650f771a0d873a0ab542a150e3a3df7f11ff6070e20a0af520702da6193f2711c6c70a8f9f1e3ab9cff50fdb8c94101f500451c70f80ae738e080a346a5ba8fffb8d9f11f3a2a950ae82b1c2055cf6d7048e170205fe51cc88f1b7e7c85e33f5e0d3f7480806e7c5cf5739fc357f7393c201cbeb2390e770584facf57f6406aa88186af704e838fffe8711acee367e740fee3ab9eff7837a8eeca061b7ec35da96ef82ae737dc950d37bc86bbb2a186ffc0e183c75d01e03c3c3b70eee34034d0a043070f1ea78186af52a78186af6c0ef41cbe8acfe1fdf81cc857a8037900f80f90e7f095fdcf573aff61c35dd1705734dcc78786bbf2711f9faf72eee3f355cf69780d3c78fce7aebaee3d7abc86f3f8398faf74cee3aebafbc4fb0ac7bbfff8aae63f9e0ae8ae6eb8e1aabbfaa1faea57ddd50daafbb8ab1bfef373a0afee7d7cb5f31cee0a071c0e80bbf2b92b9ff3d070573c78dce7ae68380fcf7dbeb237884e59f7b92b1e3ee7f11500fefb43a7ac03a9e13ef1d3e3ae78dc158ff7b8f5f1158edb43a7acfba8e13e1ed429ebffeae6bf2b1c72fee3ae7e1b70bcbbab9cdf55771c361cc757f138ee2ae7a7e1ae70dcdaaf6878ea0ad129cb3ad05da952bfe1ae7cdc958fdb0080bbaac1478422ef0a0b10f1392eefe32b1f77b5e372309779cda5e994f59f1e34dc950f771e353c5ef3158fbbeab9e77efaceedbed2b94a74ea5e24523befee4ae73cf73aee6a47e7e6b82b2cf4f7ae706ec77ce63696e93872706ef315ce5ddddc9f4e595f996ee3a8fba353d6639ed9d816a2f621e11adb4296cdd7fb712bf29e1f12be0e37214748f87a6f42aed707411b7be33596e696d54e6df6a0180483208d65028bf516ba6199c042645d260fd33339c2f32d54b2b97ebb28eb0f094b249c69b6270c2ebb76ecd9d332fb90706f05e82f38bb43d96dce2e8ac87bfd7bbd44a822eff5f5e623fcde1865fd0809af90701fb33d4be01e126e5c7fd9c633b6630a5ec6d698823f592ea6e06d589a98828fb18f297818dbc5143c677f620ade647fc4147cebd43bf49070e730f239b2e0cf10b2472028a64379e2fdefff442028d6a1cc9cbeff230241818752f3d2fb5d0482120fe589779af73b0241a9b9ab98479b43c1f1ecfd1a81a0fc40b9f19af76922109499bb9ab9c9f41a989bec67be9ab92b189dd77c3573eda643897755ebb9bbe26ec5afe25dd5fbc4fbaa3ee730dfdee7221014ecaeb043f8ace6aeeead1ce739b45ef3157ccd5dcd79eeaeb0735fd53c3b14799bbb3a9d1e7357f1d75d5db7d957f6d95dc5f85576d46d70dcb5bb9af3d85dc5bbc239762e9efb4a3b7757d3c657f3a9ef7cc57de7ae4ea7cbdc95cc2deb397775cab98c25f39dafacefdc55ce1573beba74ee139d8dbbb2711999a36cc8c8dce7c0b0e7e06058865d56a66606267216bcb09958339969b25383b506c604abb5b8c861964c36b5999a996a4d3013bbae9871960c8cc6cd5c5a0d8c052bc44c76cac42953132bcf0e2e83269bbd076607e3e1b15193c52b95fa0a3e95ba6666ee3baebed376ecf80afb8e1dd6b24cbf4f69d853b3ebbeb2ef78ba6a92e17ebfa306e63bdef3d5cc7b52a9afb2a77652eff9ea9a3c3c99fd7d3765de411e1e9e1d5f59df71573c3c30f13d3b3b385f69c7b97e9fca394e8e999ea7beaa79aaeb747ce7aebae7d879ea2bec39bee2aece6dd88035bfe7c1c1798e9c9ca38e93e3385fc11ca79ee73cbe329dc7fbb979cf57a6f73c9de7e8398faf669ee3abfa547773737f93facd57f637efabec37df41a19e23e7ae70ee0ae7398eca39ea2beda8f7d5fccebbafb8774f07cf57d679ee4a07cfef5de9784ecebbafe2ef57d779dcd58e1dd7b92bd45da16ec3c66feecac6e6a8bbbab90d1b477d2573d45dd9a06ef39576833af5aef39e1c5acc71eecae6ae6c8e734dfbfd0afbbdab981cbf5f6517894ebdc7bce72bec2ad1a9f79ebbda719f78a9ec3b7785613fddd5e9d9ceb3afae1b44765758f69bbbc2ae5dd7beb2f7874ebddf7c25737be8d47b77573c32d77157f7aeee77ec75ee2ac77fefaab5f0840c5e7c410118442045c82661035020a10c5d300194240841b10faab9d5ded5ef676e77ea1dc7ed98eae7e0d4fce6ae5034b7b9ab232d6c60c616315c00832fb410aa393a81069e10821f38810c62a840a8e62b984b53735734b7335dae53ef376e8da9fecc57f15aa053ef337725739f784250607eba2bd36ddc277e84a0c4c7dc154ce9a6bb3a6ac195335c69411a686cc10b42b1a1e0c5062c08c109d2f8011984a0c49bbee2ee8f4ebd9beeaa747f58f7a753efdba58157884ebd6b7795dd273a2128f4d85de990832db830033494e0250642d77de2425070f8400c37e8c113a294c10c2128f0d657f5769d7ab7ee8ade9f98eaafe67da7dee5e562aadf374a3d1f2e6459d61bbc4336c7bf67415095b5e7937cff07a8cadacd2b1b04c10b5f98999991f9ccf38debf0e3c79dd4e01fb7e199876bef0f00aa5027ed4b4e43de0702aaf2cccd191843194318838c8c8ccd659e67bec30e7762c23bd860c39dd4601b0e800bbddf03549d4ea7d39de4e0d383bc1f045465999b31b0021f38c10c1b1b1b9b9b9b9be71c9e7b0000007752830170fcbe0f50954f37e7dc8c73338e9b4f02781f025095836e738d52ba0414337c298312654cf144cacccc8ccc677070dcac840ba8f002858c8c8c0c8ed3cd5610a21042176c9e651e80e799dfd8d8d83ce3f0ece3c3c79dd4601fcf409e69a8a1863ba9c1353cdfb0f9cd56153c80c205ea031d4c010c730c304081041c1c374b3154218c22003dcb3c87e799a38080eec484819e7f3cf3f8f9b9931afcf37c236af152021bc416fc800c37803ba0820b5e3c2f44410c29373ccb1c87e799ab9e6fbc238c4003523c276090e4e5c84a16664061020b32a654d1e359e600789eb90dcf37a618614b09b4a0010b58b012810ca4f08281a42c7861049f6799fb789e390dcf37a2f892042a7246a0c509507094f840074420039465032ba2d0a2e759e6ddf3cc793cdfb0a156bca08c306e726e9e25e0628211e4e0dc2cb3400328a88183ba197a39e30759a49e65aee379e63b9e6fa06c6e865c8c1105149b9b9b1f15558081859b9c9b552f10421272706e66024b0a5630841ccf32d779be8183ba7995032412800165737306ca70852f43b8712226376c6e6ece00d21424689939119399dff8e926e7660cf8600853b670e3c68d99df783edd3ecb3ce779e6f7f9460ccecd4bf8800c2b00636666668643dd6ce5a08c103c017522262893cdcdf30a3f50c2183627626273d44fd7cdcd5209603c010314ea4e6c30ea9989cc8998c8dce6a8e7d3679e657ef36cf31bcfa82ce666d8852ac4e8828dcd9dd8609b6726a71331395de63695bb195aa90110bc909191395dc6d24c37f71a51b410c2e9743a611afd12edbad9e80c64004194e7eba767d36d9eb9cb3cc7d4d06b279a5f42af69da9de460edd9cd46556c41093eb84ec4e4d26eb6314f4fc47dc93ca594bedebc9ad2852aa0613299ae9b6ea637c3cc39e7bc75f31252f0e2812bd775d55f37cf9b33ec6625a294c10a6bd45aeb73cc699eb1d3e7cad5dc6c4541861da031001b374f2b68600620d41331a925989b211542e8000feac665373f283c8083266aadf5d97af61c731bcfd86b9e2b11cef4259c909b99484ac112aa582762623de63d98ce9de8fa12d3398ebb931ccc7d003763400c2f70b104ec444cb05b8fb999bb59c875d389e4975c37994ca6976e5e22046b40a9c2b2eec4065bcf4c624ec424e6d8ad9b4d370fe0790991fc75a2215f227ffdbaee24075fdf6e9e48e882055ec0b03bb1c1d83313ee444cb8c71c7b36bdf4cc7d7b8e797dc66ebe6ec69e9938c16c607927395806f3154311c9472ac0f0f40518de25c7f447985e987576694c608137c27e6145b0aa5df3c980eb242fb2c0514802b05f9789ebd815d042d7c5023fed86800df02084dd2ea6e4b3cdc80ff51be041e8faf5fc2053086e45302cf119dc88c0600dda79ba1181c1f1d9a541cb1dbdda44efcbb4dd3e4f8ba5ac003c6f56d21e7c102c0004707e008eff91b0d220eb87a531088db0c513b015c10bdec19d54042d45c82293da85fdba3f8f86fa20580587fdc2ee84c32e8a084442c2f1464848f87a5b1119dc44e224d7513d34be6e11ce649cda2504227484bd95604c596682818131c53ce34c0f823130a5125732954a968b8729a45d326c83557b17c10aa601771211bc7021c296a8555b352bb8ebb562ec99d434fb30c442a856b327d8617f2fe0aed74fedd633b7f9d09b0fd90d7a34600f829ad50176d82dfbe347041a004c61c7ba0b8cfdc0d88f01c00ea3c1d87377a149a842652f4216dc4945b001ee24227881ca2e11011af7f070c40f57abd69abdf487b752c974b311ce6a6820d9b1d344a098637f047a42d8bb08c41dfbcfcb41db388bda622c6a8b89e1ec13ca6c5cd33218ee41d046cc456926138c29e34c1917ef70238035f185dda1de42b76435839917983e2260817d702711e10946236a1a077126356a2f2b6157fface0acd3c7ffbc1ef53c6057dfc1aebe3eeb22900d30555fb30db876b8b2a0b30176b509375f9f6dc044a0da450421e0f862291f61149188b1478c1d5a14ce2c0a1ea5fda1b47b450a0f42db3b890841c09d44842ef085dd6c84afdb40aed7d708c4bd9e8b404fa89e2602955eff9703f6fa0cb3193b2abb132fb01323e09245657f425088b3a8ec1ea0728ff284b83f7b5a89c9c357608ed9ece4081893b8b7203f981e044b0f8230d68927c45d1476894c5ff0152936086d77c2b486509427b4fd49355d27aced10f78680fe92069213fd250d2424a46b02475e4af0cec5fbdb0ac0152062eb751e4d38c5c8f0cbe1e197037c2ee177337d06ed50fcc35cf002e17c276939037792962d60f87a73120d5ba79695b8832a7afa31b464a1c50a2d55a4162d1bf10d54d11faa28fd692302b1a414d35b0598d88262d0f2045f2e5b300edc4943c882876045086b609d8ee6e611bfad08bcfc0d54e5f83b54352d50e0296dde0a100fafdc0a0023e6a02ade21fac633494b1418d3dc1c62b8c9735035f4aabd1c3622f0f1e1f89703c4b1003fb8dbe74528d4c0b30bb8797006be183e33113d2c8bc4c39b93a0c0efb02daac8ec027e8f76083e3339c2efd212f5972f5f70c34e8ab44d64b0849d9d5dc0cf3691c10dbb782d8637c36722eff142dee3cd0f2e91181e5e5491778b32dc2fca700fa6e022b8a4e2f7775144649619e03e0c6eec82c7051938fee480f7e04ee2220bdca62dbae0f88b26e1f9eb700b319e763510faec6f33127ffd6d3d24c1e157c461ebfde09f8b5e0f6e46ae5f17845a707cdc881abb8c0de9dff6faed70cbfc3f2b9c757e6a9a162bacb97d76db505c48417ddb220d1c1f37ad374dbb963db376d36c49cb329c9c1331e1e4985e966ddb9e6d0f82a852dd50af47a12e1b38300c1c140a8542591c8ee27ce638574015cee7b3130e544c038523db6c6812aaae219b5fffc1d9e636bf1e7fc5fc08439c5b38db6fa0ae802ad4e7ad2d4896693718769ccc2e2192e53c339dc876ed594ef6cc74f336050af51b4bf4308a5ec313067589da4ef3edb093f869afc6e6876dde9b9114de6e636b6a686ed8590576f33336a2013b189b5738c6e61567f3aa64f3eacd2a50f5621a78fe45346018f86d17fdeb815ad81573fbb6bd3720fe87c29d84650c5c54e1c28a2db2d8c28a2daa649ad69ba6dd6afff5eb77754dc353db9e6ddabb02aa1acf6fdb83a0a65df5a5d7974a9fcf4aa5d255ca2eedca82981e04b9cb2e21725dbb340dbbf6ebfaa561d9b3794e8127872f93257a5aa9b4fd7dbbef0ad8cdfff67a1054e2bfb77f48bfb5da9fd5de758b855e7b6f6e41e82d7a3885dfa55b6c05b8f075b313b803d2b3bad13f9b95c0efb74c18d9ff4842bf4fa25ce8b72d444f9fe7145a76f38bc7e614bd15a0c3708ca75b4055fdcc730ab80576336b78be2c78be28dce19697653e2cf0e4fec6f3ef8aeff04fb90161ffc70d887f75ff6b7f3ba668120a766864bd441a98152c6dac2e38dec6668851df50ffc13ff807f7867a1084364be0e87f708698fbdb8cd83c43ac41eecf6a371f4121d41ee16751df6cb639fc761c3870e0889b900ee3786f40e07816351c381e044da61c9b93939373b805c9d9b62ccb7620068e8fef6efe329c920dee242c4938b3d16ab80fe17e849fe56c7ef95dfb16cfd0e89c726da4c964da8264df7086d2def67eb319601a60bedbc37ca9aa81ddfcc66f7ee3e6e6e606bb390ececdcd83e06f6e6eeacd4515c1f1ec38b22c2b955e1536b7729e3de7c22e6e9e5187cf3621f1a8876f5ee31938733392ba719cdf384e8638d446569a544a3838190e0e8e2d5d388f9b9114c6b9a822342f9de6a567377689c4372fc95346b1c84aa5d286692dbd7451456abebde6dbb3cd66bfb1153f2b5095c9e05862c86bf6e12d7b38c3b1440f67d7b287e96f6c637a3194b57950b4b18d6bac1506ece4692ccd023bf91b98cd2b9b57d7a452a4c3d9451599f9f6995bd3809dfc769f159988b3250696af6958629cec8bc2416c8501558f6261c3be28dcc3340b546d7952e90255303097bd7e7581aacb014110da7b2dd42cd412e43aec02aade25365dd34d37bd37075cfbac298bd74ab990bd51bbb6abc0a6c72d88e9cf3686b18d4d1776013bf96725abd5fed5fbeced2576a0650755b448d242ca1652b4d8b2032967601d8ca1832d7470850e4080b318eb596799d61b77f30a737fd65a2917ba577bf6aeec8d30a1863770dcb34cb3f28f7b99a6d53a4f2deabdf1114615e14e3f848b67d077f30abf1fe1b705790f8af55d5411ecdbb16f774e819dc42e9fe52288b14d4887b1f716247bf44ffb7ba797defc6e11c4db7355237b10cc20de5efab3b9e68ae935bb848876ee4462ae714b8870873911d3b96b37d3c7dc869d76ed6689616e267a583b7773c38edeb43dab11edd018d1c318463723298c5d5491ebf5d78d5db029a0aa5ede2657359e15d8c967366f051cd15bc10a56c0bd3b64bdb1b41e04a370399e01b5c83fcb5e6805b1b072042a90848c64171f98e007424c2cb13a12d2f9067e84a2fc0861799f53a02a9e01550f4f811be7e805432d581e7a912376c901b5c01d72e45705967f565cd8c53dac02ee70ffaae0c6b962797945ca85ec1b4b14b587f8ed60691e0defd3da348f776f6f735c8bc9231cf8e30153dfe645b1813b29075be07e63b8937200056ea41c20755244e3366f031cc49d848333707338c608a37568a1a5599675c30c2a0841091b7710a2fab418638cdd952aa4c3f382f6a20f82517b7f1236bce1cd799f95a9adb03cb4d54ab9d0756955ca85e60ef5aeea8dac37bc014a35a0ed57db42124b1388832e7011248a785ea29851ed59799b91149e16aef83d1e4d883d79fd5ac0491c6081e961fd410b420889851489a73c7d10f10656443cdf41158afe07cfd6d2c3fcfc0f3a78f6e0f920ba1d785e08ecf31688404fb060774ea18945173c6f03544d3cdf7b4f876e42ba0b1adb27f6a3ef47c40386ed135f44713fac035544ef0b7e9f4bfa4514d3bfadc811221c443ce0d73e6f1342b72196f636024008730670fd6ac50413985e46f166234c6fa6ef78f87ce443b543a744e0cd4ce0981f8e3f54591401e023845b9158e4d15be4d14095f5f99bccb29d64032e98da496f7e67c0748de661712788dffbd23cfab8371f8e7a802152f3804de07718bd5c1fc8fa51c1c937f714b6dec30f324962eb9fafb53387e9738b81ad0b0155f907b66efd070db6ac0755eb3d44a02758eab55e04048a42d68380aa4eb2c1146c1d02501583a015c60303430b31cd16f83a9688de17dce7a02adefa09aae42dabbdc4276a9005eae0781da8ca1547f8c6f13e0da41f73ed7ac3e0b2c4f0e5a0037bb27e2ae03a89066760d8493548c2b86a3ac0471a9a9b0a81a41016ca1e145cbf77f4e00ed98b828350700fc38d88081e6c545530e346003e03989f400f60be370a0800036109202e483d80797be044c71ec4db3135024eebd8d3277af80676ef2b68f48e5e7c1dc002cb635564bd847c9627983e9b011a587ecb020596cf4cdfde3fd1dc5ca7832a7a79795dda2f4d7bd534a215d68cc82c6ba1deb2215411ebf39665fdbabd1520b3b092f5faecc2def8c2ae90faeb97f66a1fa64f08f66b685a18766d46e4b13b349fe5991c61faba19617284b50fd1cb5b37d36bf73a3ec2d36ec7ec11aac8f5edd7b76747583bb5264b6dce1e2f3bb45d5e37d9274f9e3c313d4ab78f0731fd138ad2ed23474cef130a8a2d94459c8fb41e2670dbe3b7b811c94e6fde9e5d5476ebf37023b25d54768bd4d3d78c5aec56b5866a0162b52a11f9eb66fa4c3bea7ae3ecd4a2ae2b643e7b76b126241bc270a6d9edf6b944efcb7523f2d9cdd829a60f3f9c99fa557b39c02670bff463c30f1da0aab1d13bc26096465604f7de9d99de14aef1c3fd077fc8a0171c0fb9e0187014671a1c0f83b385e33197f612a4b9f41618701206675373c13509cb476b04976b9677052771ae48583ebe66a94151ca27b797069df3721621ab0d24de18af6c20f1fdc6f0de9557fbf45f6c2033be581fe9237db41e5f697c8cf4319e42347a527a94fcc310a32418e8a77df4cada3e8d65271121237a0d045a2f5ec013da7765fbf4fbf3b281d0f7670379d806d8cd7301ffc06ebeb77c83e763d6de941fa8ca1a9e40d8e77568206f9ffa791e5035ff03aaaecf54bd0e04aa305533ca062d785e83402798aa9f473590f77076d99b883b49066660ab677dfcab59c0b5be1e65a1ac77920cc8c09d24032ce0d3756f60572d3bdb87da87e314594f18ee4230fc60ec6b257c4632eb99b505d1aadd4edf36d7bf679b1522a4be1f04b7a1fac69d24032e78b60f15025fdf163eb315feba9ed9ebbd0de9873b837df3c37ded19d4368be167597c014aef9b2b56e289069a40c2444bb6ed6e4b4c1f62d25bac808203d8741b76dbcdfdecf58906907050ccda362ed9ac0454026befbe1cca8464efec41306a9785dbcd0f6f4230dced93b7678d33a95d16beb721d7a185b53b745d17d6d8aa561e6d4f66219f69f0fc99f33f383c2f9ed78140506826c9200b3cf13c0755f0f327a88a9ff31a54e9cc3bd4491988524e19a50cb088dd842014e086a47c386e45e42462511908cf2ff9c1f31299a4b48de116245ebe5903213c2b585e8fb7270cee59c1f2bd442f813d9b5a696af0b51ec36a87b16adf318b3ec3ecbcd8335be726643bf668eb359b3d28d6ec59c9e65704317cafbfaebf7bbdb720d89fad370ba1b1f1b3dbafebf17a16adf586aa2b5cec70bc793e7b6f407030f3596fdacd2bac61916bb803cc5d1999def006ecab8637c4738f979b910ebffeb3d9350bcfd91632592cda9fddaead98bd3621147b66eb8322562f68ad5c04df662445047e5e6905f7b3823b87513cd22085e2085b45f27d3391f91e6d5ea99634a98f2f92a7cfd24887b351b459099cfbd512e1c0f5bd19997f37c7472c4fc0f9084b16dce1f96c6a562e82789e476e41e26d52efd06dd8e5be65e7e3568407c76705aae68b20862772fc8870e0b7c2749e1e6e4578708e970f8a34c3c74f9b5738f7a58d5b910ec7fbacc0aedf64622c9691d5d74c621be1bbf941916885eb7befa6892f9965bd777311c4444f0d4c2fad37e1701289d404cef044961a4d7cc14d2a86bf6ceebf9b39fc0ead9621517da28126f09226145f6f62612647f8928799c8f282e76111248a985e14919784e3e1f54e1f6d1388e533085ff380d45e5d2fb4f9419b2febd908e1cdd7fbba56b8de21f8be7585f421967728c63bd487976885f31fcdc24f115ca6c1d9bb625dbeb5dede33f81a966e6007af033beb364cbd7338d3649a2bb228829334181e5a87d6132c3b185e83405108bea1c010c33f0d77d215574c087ba07385941f1f54efef815f0efc7e82402f0664fcf85002420cb28881151878f1822d807479cf8a2af07befadf380d2a8e24a1738e227df5b302c40920bb860f898b15f8f9b0ff3f27133021f2f6d66d3b304ee0763f60767a61ffcb621cf07667de0dea286fdc7da8cc4e78787b0c72704071cff3621d863665fdd1650cf44bd4c64559b5b114c7bdb02eae9b3b73920ca13aa6722ca13a2f44cd05b5b10f54cd420ea2df9620ab22c387e45371758c1f1711e3b85f9bb30a7d6897afa698d30a1f96e20d6e935c28468dc8cc4fe41caf5f9842e8b8588079c8f30a704873d8a752cd99130a17979d31bbb800ace32ab04c3d9354b042b5d6e42de63de0d24ff60ed9b1d4a925dfbf6b809b14ab26f8fb1f908c35c1491f8a177d3e393e0acf6de7c7857de7493e070964848ef258bcab61688812deea42abcb4400bd6c19dd4822a5a00c5d4328b2a6ddbb6595a665159c9a2b26d6edb8360666d45b64e6a0119b808e2786b2b8221a085e875a2ded5911076a3587f4273b357a458dacd1e84e75dd179eb17bd46739e7e65544faf940bd1d7393f6fd198cda33269c4d515a7c4bca8ec73febd8bcae691150cb720f16fce6a44619542d63af907aaa0e9464108710bd86e748231db63626abed1f716c4f618abbd1ceafb41ac9810da01020a71520382891bd7ce04f71bef0d881bd7eeaa746ebeb720b8df7810dcc28224dc596b7303a2e630d7ecf69265a2e6a5cfcd0136df4e2d103587b9abd24fd7b3a95de7ab92cdb7bbaab956b22d446399d06e731dcb84cd6b7eb24cacb4d7fcb2f908e7b7e23a8905597036ad120ccf5f960886e7d47e7a96bdcd01a59f6eb24c946e3a8c5d950e73ceae4ae7de9b036a6ef32078b22bd375aed9239c1d7b6669d336e66c6f0e58c17cfbca749af70644cd6dee8afb066399b03913f74cd8af8c98c0f1989fbee20e73935dfd2b9bfbd5bd3d8d6562b5d2be7d257398bba2f96ae636de423a9689d56a3bb7ba79cea1d0dc80281de6730b827bcd5d1d09997ec3ae9e90e94e0b44691ee632c11de699a5c56d01da6d2e13db4bb7367a81a83913da4d8fb1abeda56bc4c48deb7c7bd65b10da75c2e6da4dd7081382f9668d3021ae1bc8bcf9075f9152ba768d3021ed743312ff0e634de7ecf6a0b8d92774ebbd2d80bb2beddb8d523a167a8792cc5fa7877903c96efec1d7b19bdfe1e126e43dfeb24ae6e983223659276c0e73574f68e732b1427d85f3d5cd73aef3fa6e5db34ed85ce737ec8ae6379e510f58c1fd0515ea012b9866fd52c075121555702701bf13709906cbcb670e4b791a8c91a50b1658f1b2022ed80777d20ab254510503e14e6201972ab86015eea42aac588195153c4103e3e04ea2220c4c4517545881334d9b1665dd2217a67f18c35617dc64585d306d32b22d004f926415b020617a0b539c95b46951f39645cd4b248e6106144898fec215f746a447137e80a46d4402f02489c8bd22a5749dbb7a42ab1c77337d75afd1764f5fd92be542a66b84e3da7f8d704491c28310942321d34d3f7100bfe758291782398ebdb146db4f475d23ee278ebb46db957221eeda6decea48a88688073c94fbf5c89d248514fc3edff809d15829175ad5d557522e6454ba7698dfb0ab996b542afdf495cc358af9e94ab9d0761b57ca8560ae51cc9572a1d2b5eb84e9cb972f5f84b6db31953b490a24fc6e91c4efd866a49380dfbd00f705cef34a169ca4b7e01f59c1d78600eddbb908b45d29db4b37ca769de041a8d411e8f27543c07698731108e64a299dbb514a170bfd7679eb26c1e1220e0fcd3ba480232113142a5d1a7175f5909038253ae9a2e64b8f72a1d2e93312985ed4bc4070ef5908fcbe5d26b66b97af2f8777695e8f7779ba39e048484848a5cfad001c8e971b10dbb5c70d08eda5bb2a5d3bdc0ed042a5cbc5d4fbdb0ed042dbad31f5b4db31f56e7354210785cc029ce46204ea962285e4a305821392ef8ef14b7e70bc44267c454adb3195858542d61346839d84dd297bcfd2746d01ce3eac35903edc4add7d7853bfbb3788258b3c583e1b6af8dc10be43d8046ed8c1bfcbf170506452da8be77ba3ef0c0c5fff84bcc3c3bfcd0708b5f77c80afcffa59e13a298a3170e9f52fcb9e16b720da1dcabe1db319de743376d33393c9546de959c9a2884824246cbac41143dc9b110e099b4a461e1236c10f693769b7d43e517bd62bec623f98d2d560479fe18702a64bfb70a9bb2b9d5ad95de9bd99ee1221a61391d8546adcd2d2a2035a8c408b1368c1025a717fe26c6a5336100bf727b50f436ac9eee010898956b876075fefa36235d696bc290f0438fe79a07bc4c73f7a9f9433703cb0fc7b0c3ad536a85a7040a0013280165dabe8250f380576b15f9708d4422df4d2c0f138b3dd25023d29318514819488a9c8715d5e8fe3facc7a665ff7681feb9795ed6399948840b3535615ebb9be0d5b7ff5f600bbf82503689f38041c1fa47bc4b7bc41b08b108a0ba9fc4ce072274dc1f103802a1bf0b302c71806ce36a481e36d7852229001b6b041a75a8b0a844e3596820db085113ad578c227b07b875970c01c4949583e5362150f9f40d5eb34706e2d48b14ae1a8bc2a38082cba805d9217a6c0b987582bc7659abfebf28fd482930da409d0f40bd69e6917d54363ed431a6b3fc219a7d9ecf07a6f91465b34f1552d073ba91dcf9b6974f0c6c0e51f3fa24c9243c8809c6cc83eb8bf93719a70d87a8e1af73afac8d7cb56cd72dd03e2784fed236f21ee0824d329791b70f8d0ec609c1981ba989aafb5eb70641c703b7d99a5f5a98140ed5bd7fd1081ba7b4bcb607a8bad67b11f2c69f764b9d6baa3bf6ced8ebe5ad91dede85f120c39ad0a91d8ba442b0c31bc41404ced1220da67be09785e01dd633ece8381fbfdd7b7239065254cc9c7254fb047a9424f9e44b990f5283f42f5d7233cd73ee62f0bd3374c1ff9069e00c83278fe79e1320d9e774951c54b8a387a82dde4da67fe5998ee310f6de02018ef19b843184590b54e965bf07c9675f7968e0b6e31f03cd00f52f07bd5f684a1e3fd4c877d82e561cf200db80cbdc0feb08761875ba00adbea310bc3e8b9019751ac7b72c06535486754cb1a8817a84203aade67c5f3ba9efcb3d7a51df27e49aa1da1779ee1126014e015f06c592502713035cfeddc2cade40ab720f562569302677f825d76fa03040aa28134d0ebd44e5f62ececd8432e3a9f875eccc32d50952b0c038a01556340557cedc279d1798669bc2ab625442cc62e73ba05b1c76cf7f28bd7b1f9e19d7a7560b7f3fae0154bdd3e3bc7ec06bd785cb8ecf4b9bd402fb69d9b5dc6367e301cec5e15f6f65ed17119fbb09c22a920512bc7b5171d37ff581eb07b34af34af34afffdf1604c77f7839609f474003b93e9f8056ede878ae3ccf1c96cf3438e6dd4056a7ea63be636377b547bdc481eb796ee07a1d265c339497ccea2563aaca4ca4e13ef37aa970f2555ece4dc8af67c77e3d3371303acfb183cecece6f7eb8f68ebcaeebbab9fe0d65a62b522ec4f3a287aff0bc4a2499230155d8e78b9458dd271088e7f31209ee20e5423a3ecf6361124ccd4b6b7aa56263ca94370576f3b20a3cb39c82e76515a8ca71201d9f9755482be415328bc4426621b7904939641559454e0155562e541389eb894cb8de1bcfedc588e9f53679f80aa8d2b90dfb5cf1c94b4ccd9f9e41ad07a87a37638719b22f7a78e7d8ede10197a397246b631a3b36a201a3f514b08bd1aac0d47b0267fde6386f35f05cd17cfe3d692052e2cde75f951e1e7043efdc87621ab09b2f7a388bd1de7c911232c2d7b3842222f1ce25deb999098ce958980576f3392cc40276f33a2ccc02a6661558e6197a51a4845d79b9d77ac9b1f9e11cec2201bbf9ffa8db1c0908748484848424050909490342f34a40d53fbfeaae94c6e641f0564e01bbf96aa5954b93f5ca4122a6e67f88a9f99aab977a715c79739c6c897a25e26684e6f5722b427324a0aae6f3454a3490c6f3742b42f3260f5f37c33ccbb18d71ec8d45591d60376f53635b5ed1f1199b25ceed45c69e6cd66cd818bbc4c2b9b770b6e861d31d00ece67fc05eafd66ea6d17167c56eae95e3ae9b6968eacd7fee7ef0bb75f30fce15cf0eaaba83ddbbdc62e14e19b2d6c91067ad21118166ae6535381efb8c7d9d8a9781c1f127db9dca178e31ebb9019759a5f75bc2c8432b0d04e2d783032e3e5a78cb0e891712371f8e708c0f8a5940d5835434101753f4342f380d7480e9618c5c04faa199fbc9acc7e571795cba8b5c2210f7ba78c15c349a492d463168b02d088c3fc41485480f22412488947507912290d6a9f893941b2a58a74a9519d54af66d013b7aba2f09a6e869a69179e64ef48a41234373baf49994703bcce66c1b31e79e79e0d2636e93876ddc0cffeeac02bbf821784bca3334ed51e142175cfaab1bdc8640dced136f4ea2835144269c7f70e9ef3679185ad152811db5c0050276f1902671b9e3b4b8bdfbb290026703ece27f6017612e7fbd3e432b5d6481814e0da4afc802b1805940d51630e90ca8ca3fd00b08f4aac0d3432d50553a0d19dc1898d29fec0f31456f95ec8feeee479508a443a7e2c3c8929f15dd058e373d1b6067f5d6e303aeb978610ab6228b2c22d0132c9de4650b8e72212c3e981e5e01819e103db402559de485272fc228d00aa8ba4e1fe3eb1604c60b817e5346d82fe6d00a3dac02aadaf46ed39f0d313ff85d08c08e3e086e6fab56ab3030ef242ea481e95f16636ce12509aa726fe982cad30255f94101ad442024628a9e6a3771340f0aa8da4e83208c3dc16e9eb3574e37592b450f976e1154281211a8762a9ebea3461ba31722029d2e042e2bed0f11881e7a29419c27d9b3e6b8da3e4055ae3d64ff01882020008168622aa321a33b03673f38b3defd5cc075d216bce03e0377d2169ee05adf26a566d95c6d805d7d36e383b3272da18850fc2ef1bbd9085b412aec320d76d9bbc2d077d2195e70d60167cfae43a6ca3e00a882cfde436bd1f24c8369eab59b6bb56ee6fadd4c832b0dce68c0651a9c1d6e439aa379f5f575bb636e2d3d64f701aae2b3ff0055f2591094a781aafaec7debd94f50551fd21959ebc059974952d4c09d14c58ba428636030a4d80237185150c13db8c188c20a36dde8e0bed640dd167dae4848484d08c967730b2273865f18f07b57a3b969382386f2f2ca0d64ad9323170cd120038c108481afcb1ab3d4679a7740314b529608f4c68029486fee708e59f2718e59681e1918fe8a5934796803ae270cee89812dfcc4801d15ceba539315f7f57c63a1e29f183105ff82e013231e5e4f0ceb660e47799f18183e9e52a181103d2ff20f5f9762409575f837c6e3d2401ac3ab6ab0b353462e5407d91be3caea33cb0a32df75ebefe788eba433b8e0ebc799d4e443ba49035f5e70bd84401688a9fa0b0abe7eb00522f6ccc9ebb2e0763d2259d7eb8b945841a01f31559ff4440baebd05d7e70705ae421401bb7a392f0424ccf57cc2f5f947fd0febd9ad5cd31fda36e4dabbaebfd85d2cf004d72741e28a761ecfb2fe7382400d0f55f1f53a50255fdf41d5d46ebd6eb542d3306d2942a4534a4a2d2b527a631306e6b0841d7dc38ebe17a78c314e24488bce59ab66dd645ed407b18d5ca5535698929f41a8efd7185282617252f6059304bbbbbbbbbbbbbbbbbbbb0b3aa594539a41b9103d6c21b50f7c53c6186504436b79f2453178a1977352db4f074abb7bca1863cb8e57905ddf118852eb74d279d52ed3a232ca18a18c10aed18416dea3b476983ba59336415f8c53c61865a43017562b7689519f6d59b5ebd12364b07b4eec59c25fcf2ea10a7e5a4b4a294f3437cff684c13d6c6daf6a6f6263c4f920f8aa66a7ac0da18c105eca04094306d1c3b5bb7da20cc39c9615ad3130b54b1eaeaf7ff55e7016a3b52c0b1f2d5455eb0fde2aaddb2d6f3007bba9cdf95e53cb9a734a29ebe3a4534af9e693f407f1c5a8c518e39cf1695035e59b31be17a3a4b4e3932fc207ffde7befc507bd40a57c53182b9f64fc694238352b06e660270fa59c7f74d239a594d6cdd2b2a87c5094536a384a988a517e8e31a4f119314aa88a32c62968610bce3ad342d21938eba701ae93cc180367fd9ce03ac90c2f7066922f934c1e9631d60a8306e6ba4dd3e61644de8c693423d6972f1ae4e484cf27dcd7aa84aa23dc879bec6ac4824f66216b89a3942a3a5f5f18b82c87747796c4d6cdf3e1869dac9ac4bd59933e08cebf2f5f661388e51719c55e63252c5c8fde947cd4d68d30fc94504525ec26f60cbb468278873ab093b72e8f6969ec0dece4a93dece4a1ed7ec0d573106885c4851e071e00dee5b5d59dcf32a288a111b6def4f5075ccb4beba8be19822aa4518530a61006ce4cb16a99cc1e9490287ef95200938dc3bc47612e7d8781a1d68bb10e0323730b8bb943ef361e04df94a1d36d9c72a5eb5936730c06060606cbafca75e33030d76330984b14f110fdcc83e00d98cfccdc88391603f3cb64bd2110cde9160d85f9c5999e652e95399d5a373098cf5cec3197b10dbb987b6ddc7a46ad0d9bb9530f78c00d719f38b71738fe9d2ef720a00ae63e0071f40304842802aa1e67637eb2dc4d16bb654d366e8eb95f411576fd7ae9f148c0d8c64550657abc1250850455ef3dc1f16f0a95f7e44981aa677aa67bfdd9d28362895e1716d2c0ef03b893cae88265ffe048ff7af0432f51fcf2650050f57e6cf801551dd403546ddfac06bb78695f12974f3866abc8fbb49907dcc3f984637e38bf4b14ad4355b46e3ea2d1e9aad005cedd05c7230155f94d5104815a28de0250d54955d802c72781aaadb7eb3e29af877c7e41a4dca8c49e2ba5f312bbf9926772c4a55a74defa8e6460290b19954212aec19d14052a7016b569454e11f1bcaf0aece27d50c02ee2791f15d8c578df14d845acf479f39bf2b0cc1e7b9e9bd3f4ebddba1e23b6de696399c4d61dcaae459f69698c89e97687b25b44b23b143fb1753d6e46268ef49a5366d8cfc0c79dc4458d86f173fef1522b9dde1c230df26e3ea20f6252ba05a15b0445b90579413c0e48a892f741c4481fa3845d1bc9b620f10611e9b557605eb257a45c08464846cf590953f499cd200cf7a0983d4de32c4783b5985f963eb3db108b9eb331db710cb559b3b286afc358095397f56bb3d9612ca7659cad30f58e59ee64d99b686f6f44647c3cb5f90853794914b1348a471bdcbc74c102efc09dd4450ace4cd78e592935a9699a8661524a4d5ec3de94780b1ee163cfb2ec9ac964325529dd649258c3be6d37286a167b11c4da258ad8f42058b2d9080f69cfce6d9b1633847917937fa5c7ddcce4283797d2bb173b7c865dcfbaf91d9b207d421962d0495f195acab05206155c03eea42b8c11235c357c100d1f14691f4eeb34e2969b9023f9e2ad02a1c02f52b94510d3be3452b944d1a6e7095cdebecd6ddb7a9e30ebddbe699fa56f433002994ecf5d5abadbcd3d8649bb451167371f6157bdf5a46dd07ae20a5e5ca10a9c9924fc15a0c03cb893c838038f8101803b890c2b3087235c59fd20ac26d2015b6f9b5f152211cb3febe687654bfc6ec367549b5b10ebbd7134b08379a687cf191077eb30b661cadaae15c1d239db3095e74db66157a237cfec666c3e1f0dc598e1758b208ef270e89d7e9eceabc14e7bbc2538a9b8ea61f7e33f345d7eacb76e26526fddfadb8cd45bf397f52bb332db130627a7c039cecb6dc8f5ecaaf38f403f7434349cf5386f4f185c1c523f74ddfa1fb2c3ff5c879975ecfefac17dfd5c37174d6c3d42eb7e4a2ba5783de26d2e1308528bac82e5e382559c84c23a0d8d9c029201b940a0206c1bf21e0fa114b20a54d5d35f5b10aa05d72d48bdd94f047a5490f8814959d2ab0276f3967d5660f76da1b2cdad74e1cda87d5686d08bbd565a69a5ef65b54ef1324c4af172281dfebd67fafb7befbdec8fbef72e7cefbdec596a454625865456b1b0435b319b31806185af5bc02cb0c0951e83c7b2600a2d29b34095757a29059559307d965860fa88057dcc0255d89f9041082184f6ce6ae9a17d56b8e0326785665ed4660e47b852e2bd2a7086af1b9188e37b12d34b2a128a97433d9553bccd087673965530cc0eb72a185ec6fa7863fd19403f31359f211938467a586b4c750305c5d47c2c9a59a5cfe8df839750bc1ef4d7362473383f2bf985712515d8fd4c202efbc9f57512d5a8e590909084e022101235de5c33076fa6c119c79536eebdf74ad9df76f37bda33ee9d7bc6592bbb6ce3d2965d3329a9b465578431cb7befdda4244c6f613666c1c20a06b6c8228b15740b97a42e9296f0428c2d5aa4c6597acdd60b11811e152422d0b31253f3d3c4a5f44cb33d7331953d5789a9cc82694f185cd1c4eff959c1f4d6311bad508940b10a98b212811e52a7e8e7a514b7e21598de44a50aa62fdd4c4305d36f37731d9f144c9f3d2b783eb334cd4a29687c865c307c865d30bcf499c4d975f85c2431767833e482e9b45e9f8b26c66ae5b84c83ebbb81ba53f0d6b1a24925152945b605b16415eb4a295e0ffab4c783b4056bd8b242162b48c1d62b54d50ba37f414055bd456fdd0745fc7ac2e0f2a38261bddc86589f376e46342c6fd5c357db1306072ff394c724ecb09b8be235e1e136c4fa9011cda2b7decb0711041f075e0f781b7b910b2a8c817f702751e10abc059698cb19f827e63098a4f2b07508c46d887c7c8dab65fd4d81aa6a6d11a4de2cab96c6ded8c38e5eb33ab0a394925105df803bc90a5c7026b5b759f7043bedb55ad5aa56b56ab58edd526dab64aa5635d522f5d22add2288eb4db414579b97c0168659d6e51604ab190399c3b2d62cf00a2b70b5aebd6bb70a5c6f96b71e1425c599cd4a60a2f8450d1c71ce007e146396286e43267e5085ddaa39092e82d87a7e56e06cbb953b6c210155da2d797306bca041f1fbc4f4d69f3d69c1e513a6aff41c54498c69bd0da957bb653387235c29216511ae82f3fbb54969d92cf13bf627e5e5508fdd869d951f159c1f51c4f9e1ec0e59d76644bb1962f9fa862aecf94dc119fe3d7be6ae99aeddfca6e0f797aa8d5b0471e90e59e76ee9d9d3b44ba8daaedd5c14b5c75b329b6e11c4d64b125a8f765a97f25dcaeb61d51b04ec2c2b24e10cbf4fc11267d4c2302bb3b45b58568f69cf38f07288b9842af977b3884dd7639e8b22e61ef304ae0862d31dba5efae34ccf5e91eba5980741534ce9a65fb399dd6cc36e7b1663b167308d0636d91f5cb2135f3c3a2fd8c2003631121d0f8aad88dff30fb68ee51e0363df2c0fdbc1ceba6691809d8501a871b6d3c026fb03972cc530b66df841035bbf6c5e025f4bc458eb30b69eb3ed059b6c874b56e2cd661d6c3db39acd7d06b65e37231a7eefe60ce0862a78ec742b40bd76ebcd3d868cb0943380afbf8dc8c417c6fe38f072688cfdda82606fca65ab845d86eb7d1c783d2c7a877e64b664f2ad234fda3c9af74aadb67eda05084d8bd63bb5d3099f09d9317c6603c7a3ee9b8db07c6f0b682b085957ac68172044df2de3ec2fa8085917295e6b03537a1b387b8d99a06fa1de147024446117309c711f757791b64266e7a92dd2a3093ef882fbb2de7a36c2b45afdbcc2f4e688e12fa8e0c6307d10095997b2661271377e387ec9cff386e1336921ce9e46f4e455d264403270bcfd60903554f51b122f047a82fd0996f8ecb29d046106b5e6b2f920372311c763b68560361b12e00804b81af9692f0608c2f5712b024dddfd66291b51813d04e17ab80d5182898c88681907018e5480ab90232b9848085c9fc1d7a55236b2621fb5aa86d57b69986d2122f0f4662c1b61275081e9ede3b644c28ede1c37239228e2a168dd246870110da6f12fbebf4b8b2a02bf0486a7707e217b34e0e00b702731210d0c57803b290c26e00e77521851300db85806eea42d56f0db823be98b2d9807eea423a441444404882064c179c81a4819c0998913b214a500e72224a42452c0b9880a1211ce4556505982735115b6e03e11110ce09c440892709f6808e625056be0fe10ec085c30517ff9c205f789fc70c20beefe82fbf85921239ab72c9387adbf3b04ff3ae90862e06c97bcf6992faa98a8bf60780c83b79bc79ccff6339be9e712f2db11bae0edd8b38961452411ec1bdc84d46b7f563b66b7c3adc8f5f732bcaf7ddeb16b3643dca45f6d7ef8c87ab04b6ccc4520ebf4306e41e0b5ac753ba6e25f06510eb84e0f44bd552f2f10d7e95d6191bfee632aca204b80a0af77c5c5543cbd1d53f30868219a988ac7b0a4cfc711136a214bc6ae858c587968a52572317c0f8e3452d81096e07f228c5cc01a81ae38e79cf0e6a315961967cc56099887af81c003188973be20583ba6e4a795875b1048247b263c0fed7c461b48c41d8409fcf5eca2892979cc723125ad2d48a67fa864a9d5e973a1204549c618424334d2009000f31460304820168c07e48926c9d207148010aeae484e1b8ab32046621442c818430c01060c801901989982000080e2cd37db40baa8d32a5fc42fb08139d8fa330250f957c50c8eaf00be17390744fb77023a567093ef80882ea562b30216548860a1bfa289635d7e8ccdd9a001453b1ba6702585d19365d61ce49b97c7ae675203ed7945091be151bd5e80b32e120c375cec6faf3517c91d102f8a95c1cbed4c8963e16fcbdb6ca55ae9c01ffabe4b982f3d4058d290e8a13964fc9cce9f3cd65f8b4a9f8baad3ccc3197ec37dea8115deca84d368c7b0f46e859ee96e9929b00165176452788bd0c0dd8934f579ffad60f65b8971107b124054d86eac9090dee7912a0fe578d0390b5d16825603e760fb17a4ccdf24c18bde90ca1335e0e9bcf75935f03a631a770efb020f721465010c23aa7e03bcc5ff119446e48593a7df586fd04ed6372593e428527ff2a074595976cd3c726dc70405543eb65fe0f677d77a2db48016ddbcd21b9c68b25e62980e2affab5e38fc45aa25d37c23e4f7bb416b900d0fe71f272f314ac88ee5976f54e374b0ea9821daba5db6401389c0334be23de3c040f27991d9a04fe4892476e3627ad7e5020b166638806a78977c505fc596ab794bf1d6d0de475fc7ca54c5baebfbd2b8897cd6704774a4d6ba305c010ca4ba86ae2bb17aa112c5e589fa8a77d5e2cb4544e865eb84182b34856eb29173f1715bee31121408045bd570b3366998306d790621c9c3563589e694e5dd944eac33cd230b67eb349f55d3ac3c76cd93decd7b2eaa5a0ff882a299a302d40742be6e8311a053c4534e940297552354cbb4e27bf49a29f952a094e3b2196bd3d03842a71619e1ee0c9c0c122688b4a3b78988d20fb419f91c2b510465bfb64f542bc6b0191fea26d5c4cab0b3b03553606973065f58b108b3a7ed94ac48a4e5916e0c9ee77673ce40e6fb4e3ca0bfe1712b6e82051bd80dc687dc182ab1770d3ca51778868159f0dc6528d32160cd15f191cda817f2414d7bf119dcbdb4073d03e7b3967ca93f6c044eab00b4e99a9d4d8dfcc72ab6050231801d9ae8842eb4e07ee7d24bcd7399ae5608e772f63d0b5a89dddaed80cb0b172940d6ae56e0ccc5dd9076a47b9b130838fa3d356826ef865e464787153f92d028312f1cd0cae355f3ae3f15bcb89a28d084fb5902d159b4ab8dfd08dc8000998e2d401396ac01ffaded234bd2272b5d5237f4b854e5ad8d8e8bdcc842e5a996f90cbef2aa6eac742b6c70ca4c5dfc65e13295852244c8603a93e44b0c891a1969a5b4de42c1a7fa035327e7781bedac33ae8c1f26677905ed6ab1066388d443fe1e293b494c59f9f321078df8dffb422b1fa3897ee42f92115dd33832dbb851f37750e94d2bcaf744a4d560c4a0f443e3d5c05c37a8e252a54dc9c3ff2db95cec14258a159d295649723822ee6961e4c831c65a367d6fcb3bee22058e907770f0f7140868c0120eb7372811d2a6c7129884dae960135368bfd334cbcaf803942368afb113a12d230c12f712123a485d83031f2492a9ea0bec1f00ec71fadbd3139a21b90a16b274059eefd50dc24a5e180514c27e8abd973e9b9967749c8ca98efe950f210864c5313d41f89584f9cc047328132bdebdceaa750c2e0641bb308f2cbfbf4b28630e97ae68361996c9592a50717786ba3d82265b9e801afcbf7f9ecd42ce1ca76a5bb2b0084299e36570dc689a1a457aae9eb58bf28c659a0cb49ab7816e56d4b07ad505314f73b305076a00d1156d332e76376f28da944bcf3c608c8497767e06fc3359e143580b66c806bec213fff2c412f1449ef31198bb53e7a50661ab679c8a91f1b3200c944d4280352298be2fc34717cacb8abcbd55aaba1d1d554e111afad88e584ca2eaeeea9db81e8dd8a0f648e973c6d84e6930ff9345eb09166dd2e50ba19b6e828f3fbf745f1e2af6c301bd8bf3845d6f73491ddee971a0e1dbadbbeed38af18d53ad01b4ec7ab8cd6f00dae44ad79976f425e80f37fafc06d6d5c75b010d10faabe35edd2b1ed9c53b04f63660dfc9f52c5509319ce1e8813722d9ad110e16d353c57118a720e512ea605fe05429112e48c40db039210687231f90b101a6b8e21e17d524a7d95c33cfe139e2e9f9292087af22b049e02790206b3f43dd6f8052ddf366859a3ed4f2ee6142084213583c60f12d40b997553f892bda3bec5e3b8b2a69c4bc0a67a4a0cc8816dd8276f29c93be86a879543b3e745f62acc70d0987c3276f90a6c6b29d8f5a3fb1caa3541eaa07dc7945911d0df06be7afac2d43602ebd24b897e4149822e1046101f2eeed19b6c1619e9d6ba155c93e6d3040e5e49e773a5e1ec1ba6120709d6e5fa8698a597fbb15c7bb29bfe6e597d60d6251d30177032a9e47edf23ae21384e2b017394aea94809bfd0e878195762072dfb3d53f21836b0a023c002aafbc3c33d6615a98ccc854f9cf74dc0c0c322978063769bc1c5fd4a86b5d9512364ebd625014e4c5139be7e954612dcb9cbb2c2e2a551be55e88b2e3f51bbab78097f7078d5273693fd37ceaff9c4196de1f275d0c7753417d7c2a2e57c17875503bd9e8ef95bbdc780bc7cf2fd3c1f3f7b6f70b2501cfa4cf3b13acf2f67d4292b003ab8426a64ccd6d1030e141aae95d0db971da559b9f981e364042483a7dd3939ea66bf90efe2e21cf5a775ae71588785e45b4f3cacbbb594ce43e070d762903e0474071abfe0f7de7a66306a7b4f399e12b9686d2996fba4c2db6f2d60230c7726b74464fe05dc1cae694708733f4d81837195b332e5e0ce76eab476fd668d14ac5aaccd1ec25cb4caf326b0eee91d3022bb0f27380ea41faf38c07c4499fa32fc04e7bbb0e5603340aa7d208355dc42d46f80005439715da8a994c2386b0b5603e741107a3c5faee07d0b834ebb7983a0136c629405b91ffb47c543c91e4843475b290bfe6e812a07315def1f55785f2d1ba16ab646b0d151afbda3a2129fc07fe56020f373b2e8cf8b06fceb0b88588a0baa9998260159e790c6e6c66716305fe4cb4f7522006a10168475acf838349c7859e3a61a5ca400e708d9347b4b7533f8fbb06dde80ea62ac1ad1ff77c0571969c2d4725a081b05782001a432c6045f73dba8e3f8e9b26580abc7b15f20144da2eb7ee01a5715d1d0885161209a847a98094830df0b512911325081c2726ce22fa850ecefc5896f2bb932700c007e2a8347a2c3acaaa8b17c26b5e415cf6d33374debbbe7d8a54fe8095e61f403ee9e28052b7c5f2522f3b18db2228dbd1348e7e5934a9e82f54ac8be6b63fd65096eba12aa8a437c2fb0d3fbf8ad645250ac738963472e2c72e27957f53aa722503838d2bd6426d161a45028859babc192dc0fe88305933cc8d61b49e9bf7a695918c2ae21acbb4179c870d421024315cf230644331b52f2b7c34d714aa77df1d08abda846dd69f9146a33c04f1e0d620893ca6628c850881daaacc5d2000b34d55a4f66bebe88e4f9cfbeafd7504ff176dcfaedb31532d2f954ca700ba5672d0f60d9bc83143448df59f38899994fde3a89c5e8e6db8a154a082d51fc774e92591aa8c164c8c15955dfc047d54e1d0f3947067a176419693df5ac5ef78eb704362491f15902d9393a095417fe04004294d8329afcf6687580c9d042f7e0f7c140541e9dc690217e0530fe13f599eeb8604b0358ec51169dc4a9327e03c76b409b62ad89e9978dab32d355a875e61275def3984658e20f696d99e43849496697a08dd8959887a03501702042d6ba07719a1f91d779c06cab87ccad2d10d0ce07e3e40855e3d3be71957ff28f38d16d151bc70a1c4073fa4e5cfe011efa681768fe641855cbaaaecae0fe88570b3508896094baea0644fc42a97c15a83f6c81e1e890ca8da0798948523f6b14885ca176316c36ed70f782775491ce88970f89285d6109c95265e72ca544de339ce95c4b890d1075c7d19e062c30a611ac5149cb294a16ba1d703008248d839b56e7d3d1eab337ad462bf39e1ca7d4a9c2844b7fa1b86cccdaa1778764b39dbcdabf89040fceeb344754979dae33b2033a53c24f8ba83cc915a7230af4ba30215f79a1bc7dbc4e5a5ce15796bb7d5a76bb3e144ec0b90cd440a6120302dba4321b022b688a7e3904a35410e81750fdf221dd8b754d39860084e27c7ddcd753d4d03ea202d1ce422a2b4d2327efdd3765ac31c6d44275412c99cbf92af2bcc6c1a44102ca80fa4038c2c562123c42d9685596de8446fcc1b42767967e77a3321dd13c75a4658ca1854b552cbaa89a05b9240eac5b2dccac614aca6de337bcf6a47a6dd3950043c040fde541dbe5763382b025725eb4d11cd68319769eda67318cd408a579afef58b4c15d9095f0939903e93c8b229f40d6629baf4b8cdb61dab1941b7ad9788644fc35628dd14aef52c22012868c410a87a8f03dbf5d068348b7f6bdcdf32ebf82c4ea4c0ef38ae3bcf106ee31b9737b848b150a3eeb3946ef8dc688b868cce4a502e7878dbdf11b410205b7abe58a8cd4da0bcf622ca5fa8e8b97c80ed787d5d42e266bbbf61f70e70571be60686090f66f2dfec804f48fdf1dc9094c5d96ec0ace13d9e6a86d6e945bec53bf64a6f99d70c089cb0199a4ff711744431a0b218ce766bc93194c7ec82f61fde2b255803d58a8057e6adfeee90627500a073b5a95f971021004c259adeaf8e21ca367345a8231e2eaa6bd0b192469b5a39faa743537776dc5d80d3b88bf8efe85438cffa37283ef27a2804f8e28c69130343466dc15e293eee25fdbb583ca9df155566ea0c399aa40a096fcf90d2cfb81f8799dfbef8666ed3a206c549b1ca1c4121480d99bdbf4a011dc9935c421a91b40e3c0b518938139892c06cd8c21dc764b51ccdce52228b0148e46de93fea40ca261fe123d3e5366b96623a03b2d9e55cfc68d0e0bb189aae64c847b9f6429c2ef478a0b2545cd7124b35f984b376c3a3d417d3ecf18d9637dd88982588aed19acc54d1cd930b5d95070ebd00106427ba5b2e43dd6c86c0da8f63ca54074408d2ad559859de102055a1169a993a17e512d56d9d2c7eb37613b4cf02cdb3ba17289195a0006a663cf00271b2b5652ca98526901ab63ec4ee780d37538d525bc60c31523742d400e2a922e5bd87ffbffa0ba3738088a91ba500f7a2f8a25ed1e39d9025298b4b04fb037d03b054956324e33588751431992e07663ab2b86ca76bc35645d795458415681c19454c89df660a19c1ba2c4d30ebcb2cce595128d35ed443d1479b7ac9051c033012cab89742c5505c380449878a38aa7c91036fef0504d40450f48b00410aa5184ab00ffbc28cf565486c4225d31d46c9b2096170367e9ba1cecbb953e966234ab8f83ae8e38c83f46f34f2f81494ceba88c6c6d20e8ba5faa3799461457357d45acbe079712b9caa730fd46594b43165dcc1cb3b059d56aa7d88deab174ee52ff2c45518c547438cddd4c55ce28f2af2b9c8ff34b91af6032ec77db7079e154a9c3396582c8a015f7c421e4f83bd66c516f8ddfc31df0004134325237dea193fc244a969f8d1f04c596ab150049a8bcce492ed378a4b5a94e38fe417546afb7e99c1d741006cfc255a26d15c6bb5456fa45e46905eb874e7b60bd171437f35d3d494709ecd2cdb878d7de4e59d5b14ef8fe02fe8c87c70a3f098ba650397063244af54b0bba60d18667cdee6bfcd559952efc7fa197554593c35b9b85f7f85212ba660116253a2e6753bf2dbdcff147637a1256aadbc90708156646ac3b909841c67a0bbb407943377511732b8a00850a81e8311ac17c29f6d5f7be5cbffd6e7830dd7351a9ea95baa6c5dacc4f16f0dd22b6a248d431bb8f10e06fe91639fa7a96bcc8da78884b831e0b2730b551ca663b5bac2e4f76955d7f4b43c36fa0c505fa6a56ff8b7f7a7917021a6dcc6b658e63c663b2a17376eea9918cd86b8a8b84f2c939829127848ee50b277a9caa1ea9cc94f6f0c637056cd61d5453fc8536d49737c92ebd6aef4ae9f89e5a970160e0b3674d814682a8fe662d021af92dbefa07b96952746474b506ebc2fe305d823efb5bd2651ff8baaf23ade3bb7445a73d35ebb000c235f8b2e7d733080b4cc553387001c4cc9f7cacc3e9a59562effc2a9658d50461b78d0f28b621de27e2728031c5a133134612899fda25dc4c853d1440807b1d1e1ccc2b227965c5b1bb4df5f02e5a72894ed3433158da1e6b4ae4ff4ac4c7131551fd0fc49edf6df5f85d33a946bb89853d7f7d177c30ab44f4054adac3929728ac2102f913d4efc546d9f8c6d9dd84f707d3a0e25c265c58720b04a034100014925d2e35dd693f52caa92017589d369914941f4a9e52c73ed9ba01a3970195efd5c1ab7a9852b3545563df2a20dd8c02b35fcf367123d06ffcd1ec09c473016b3ac85fe47ac12ca3f2c57cd7bf8940d71b4f59e5abe1df26facab4b4ba797558b7aeeff90da6d4694eeb1a8366576d379bd1fac53839fda7276160372a2ae55ccafbd3b16b2b01d54862a00eacf8ebe7e29de96845ce95896bf6b6365a94c03c7fa04821b60bbbe29ec3fb4c8c74bd428a5b829a771341685d2e5722e5544ddae546a5da9406226b3e220185b17a4e278bdc7bda1de48fb9fc6753993d108e79d9a8734753cf9fb174e5e4ed67a25dd83674e15cfef89bc4a73ac5a28c9df707f4e8c1f8070b8c3ed8aba6614d7801415d4b7896612d97de1d3a8c64f11ed4170338b0cb607abfb42319f4712b5b73c76611a599b049ad8f47cf1f9c316149d593907aec7c8677e28f22e2a9f0095545759c7d22c37f30c370836c7d35f2bf587425f49db78d9a005634cdf569ec502446980537e769d4610b8e611bc2832786318088ca0f1c0561bf3e1a908d55cd8492126b3c5212237470901607024bb73d30e2508ec73bf6ee21805251b2b2f2a1b513786a12e33e588a6450c7836569157c21c40fab5b36f04f36cdbf220343e02735010f33f3705e94069de7e2708ad63d8014dc83219a7ea20094e47c4955400af9570753f2dd57bfcc26010023c0cb1c28b472fb4955c4dfe8180e7160d74c9637483894eb7cdd925ece5610f4d7207a7976e022def4a74c0d9fb62db47bd16400cc8d3f592ce6b508ef4c2a47c2f78b07deb1eaeffcff9de8efcdc8828100a0f11adc411aaa25fdd57a6b885cb6af0c73a45ef76733f80ca10a170f0d7b90e279f5a44ba596ae8f6e2d72a6781f912e0638ad28236d368fda7d0dc7b2c90964ac9c0b7b13df8e5dfea839198c3583ebdf654781a5f24ec4e8bb1f4f2d22b5ab4c83f316b81b7e8329cd263e06c2f156636e664e45f21a9ee97d012fc020310f8d2d8499a202b7c29346797a358b849d454c5e17f1c45c43e8f4a1236b286768fef8577c266718655a526e3a9fb81a9ca5592e750a785837bb7528e4a5a9e0cb8bb3e8c2f2aa9059e8908703dd1a2f126532a62285c9e42bed5a5651f383808e9e2a3e6213f8dbf02fdfcda4d047f36a1779eee7eb9bf5a46c7f04cc0892ceb1505ed0c38e630a29b50251a90b75b97776b195a162727afbd2d455ce9d5aba56a17ab20ab70f48e8297d55f012fddaac899a88515dd77d6ffce31171515f390c8849a8598f39f0f23ea47ff6388ce5ed3a158a8647bcb2fdc59ad28e2630084031b7c82ac56a97795e25a7fe050a971dab86df4ab18c3ffea787422c365c1abb873d44c391f4fe735e04410476ea8dd8e8a9af0a0672e3dd4fd612d80e318f60eba90b3ef61eaa6a663b97ca0deac070e84ca409d295cb9748119d79f84017a1c3b99bd4685df2b4a690aa32cb02fdd218039c21693e5f29ae875eaa1d4a05a8b865ff720309f8a35acd7dd32b3936488ee7e78f1aab1fd30ac88caa754e80013e7ea96d2eb29c6e96e17fa0e26fd3a327a92504f76f7b185de703fe26a9bd430ce741ec6c6feb2c64310da2976234d687d5e0915bc3625a461afaee84d610ed324d842dd8ec9c585ec056a3753d6806e326c5b557704f4c6c3759ce5753ba7f3927e05736ab9d06037e49de1f8ce55ef4eac186eaa77112432d6d556ad2b8ec491ee695ab61be1e9091ba8a943637d753364231cf21706b9f8fb341abde2824b42896899daf57da47a44fa75bddcf2bd33d02c9b06a9b815729591a48f2d9daa1b4930611f8e9ef9fc60bff9cd5ae986224712e96d8ddec41d6719cbb47146b814088b757717731b0710757b2bf6b8a19dca4d07f3a55510ec6b6d25d40a717d86b24e187bb142e1431955ea06089c5cf9c9e60d6e12b1d766bb8378ef18db03b8c74651159c4cba23d14a368a046b91b3296477fe3ec47fe8fe24153cf1499518c73a1ec4803ab0df4bc0522800ef2ed3c998dc64229c77b8854a4a837e8c1671d6a0bf1a08654c98b0671b8b81b8238f7f82c8dd938a6e880aaa976f581be3b07fb297683d71788948ce8355f7e2c978bbcc7d0916f8ce6d33b8a319ff362950b6cd00d3900448e9cc8a5e9feebb70fd23ef91c3311b77c4e38d468ea2f6eda0def58beb38e616e163a39ae0257b6f94926b6311cf98ec8be9f8cb252bf27e2c37bbe4a3eaa9545d02ab2a870c6578235279a65210e3de9a5800e7fc52aee711631ba94f0c4cedb05c8160278cbe9cf2b6b02033df0e1ce562fa31eaa2e7cbaa64d11ecc3a3131a4fded0d82f01c3b853e86b360fa2cb846d4050e96e428394d4800de9487de74a5efc4bdd5a1f037d1921aa4a5b480bccf36621707cb19338bb72ded16c79c0f198294ef306b67a85ef1420ec4abb1ebf18cc6c7ba13b7a91d5c968a0b832e979b1e5735fdb60dfee7cd35d04e796b0ba6610dee363b2f31aeb368429ced04e91ab8f50644c7773cce4c43dfb6a3363ea11bbea8666f982792281ffcd506475b5a0c4e430e035d452b394f3159fe3459c60ee0f6a4f75490c4d378fc5cb800cce388a417c2817afc5e91210620522b5fc2d696233168364b253d01e1668056d8b46a3ca30f8270f3b07bc1022d3aa4da1aa90e574b1aca27873e2166695d5eb84f1179f96732b12247b53e3eb90afde40afb7b288a6945ede287347847a4fce7210a22463884e31c3f5850ca781e456db2eb236205cbaf23b70dfd917894681eefe13353f0fceb2819ef19d72307660fd96d1e796013f136f74f045956f88d476b59cdfa086e866ff28b9a597e74d8991628bdd04c269276349e94f37d81dca0d6c5e5fe568e5a6c60888786153903c58e41a8589d635e2130ba4db17422cc52c5ef8340042b4e503e8573c73afdc5b4040fc5931e85acac8d89ed491c6396f7d90d5a3b5683d9a619c07189b865a413a4f8259c413a9263f0f90d62a344346448b8bf641b33160d2e4c98543d5afc075dacfa2779bd1b32523e562235f916439f20645367f2d74ecfa89781220fe04ca11cdbd05117eb6ad83ed2f956bed461c6f4024aacb9555ca7ab108bac5524c6fe9c2b24a1a3fa8197c753d47d1c707098c370d50c82420b82f467d62023082df5bd82c83744a2fc340039b0e7b84e3a6514fa7a2894cbea2a38d3b24d20dfdb143aab627ee3089d34637a7a87db081d737c72987711fae80fe18189a616621d9ff6d84465ce1009ab5f8b293b50593b100b5fbfddd91adaeefa5ff7e1d91dca93e421f3b9f3b7c791a7e9125aec99ee520dcee8866cc6e9e687bda09fef18bcd925206977a6be013f3c6fec10dd939f86050908d7e0cd214f80207351dd537682ba6ee9077f80ccdadf62c6eefff4430037b5995986cda03313111d988450bd2989658bd94172f673579beffa577f9b8c2f6aebe613e50d167d8187a51c8d124c76fa12632523dfc9a76493568233d39b336e75b361ace059ba5514142806999b960680fd70179ed14b72a2bf084109c78a286a818cbf000f0cbd49d6a63d3db6d6f37119c8fdc9733adbb99f6e4ae02199125b2eddc6de89f6b2c91aa3d8e13f32ca6b0d4fa802cb843ab3ee7f8be4652b94dff3967c18d7c6fb6a23d4de131057cebdc2eb3d429160ec9aa043b60b81855d9ac68b897a82cc67c2a70220341f656f93290122e53d9ae670b16d995763d69ef655389e746944252e748c7e5b2fe69c3dd5b4f7b0c1b365cfa8801dd3c08ffb710c6f7db91ed3f09e134bce320e5c0c37350250a6e979967ef48b0ab149a0a443a2497e323433c83598fb336df40a776a6494702906e72d6967885604f98ab4a1b9cecca2d3294f06c2d46d1a24c64e4d52655390dec898c6b94c174ed6580622905976d87a2a524c753b86981f390ac69ce410a9b33aec32eda7f3c9725a7638962a52cab99ae3fd8a2dbc789b7cb66e1d8e7f7b0a5c34294cbfb8ad01255873a2f39abe730c7c6c1ab4e4145760d285b05a7bef1c8da94bc9bbc4bdde1c46ab852f50763ad0e5095851e89a294dbf9187045c46c4571138fc788d512cf7bbfb2a32c3c41d5b558ab2da4271735a374b55612823a590103f04cadc9e4df1004667e5c80210c4e55111a0b5b84e0e849fda64ea7c3259c9a8268d3e185f2bd9c702d3ec803d6a3c4d391b07a43881c08ab940578d254268482323485607f4e9aaecbeb89ce15f5234dfb70f035d162d6d1dd3bd32bc43dc58ab12daf67841091a334a27569a08b6b18e3a7763549db4583c246a91b054580b243d04081d8b7018014eecb3a54e876942170433502f2f69e6f284c956dd6286176cd27c66646f6f271c5fd1c4b1c3108f4635488b457185dcf207ed46eb45264acdd9e11168f4f24d27315d31775203c60dd19dfda6404e0a03d986e4ece8496a92cc2d5105c735512da006ed29e95e5c1961a36abbc4470a2e178f62952b0106ae6b196c076368d5cbaa1c61000b6ccee41e109c1aefd657687b049320f979b088fa164c364ccf5d47f45fe99307cd22e85a6b5f8393bc6b088e83ba968686410aa1edc14f376bf8071de1c91e5a1277814e2796345f819283c73ab9bf37648dad96df2c93093a8c6b460250ee79e822e30e33d6aa02ac104e562e632c4876539886808d2d14c12b8272a2a460e0af9339269f2e53603bb4f42da3c2878b59ef41a0206e9f1cda94e7b4090d359a407dfb1714a8e3a48ee49a177c526792ae1af7c27a60b59881b7abf3a9afd129a18939c5580ec32cc60308447b9c3004e87e3448cb08c52348a8ae514150dd894054aff3c6f4e308d0fbbfa71725f53bbe647546c5e131214efd2de9e22c8077bdbf6fd449da96e7560dccb6ac3ebc43083b7712d44e66aefea29d42d0c769006913e75d5daf26cd1a039d6e0be1536f686023309d928f1d5dfeba56fc2379ea6c8abaf8dc45bee0552b5ee27edd51e066051147e0bcc957aab6ef07ac059fe8f4e04a8480a8d667b02e830f6660920c1362b2d3a2c0a119c58df6920fb3dae906e89d259bd8824a3f89f2fb2a86458b3e3f125f4e5812e2ef01ccf98c3449001346f5f2273c20aedb749ea474eea4d2cf756296d48464a510b1203f4c34827f6059ecdd0300f5a5d9357f3e2b731ba5502925709ac5811e654466e9f419eed7ae0a2901942cf6f544cc1fffd802848b50632a3a7762d7f6c3091a64cd731beffc634b06c3934aaf75e85bf7366a8e617b4af7e83189c693d0ff641fc15fa952f25e68d1af9219b4b5757411fd08b4ee67029486806e3eac45688dcb66d0786699ea48284e2a5b0b5c865e9228e5481014cf5a3864820913e10e18f2225fe7843ad0dde818cf880f9eff8768099328d2a58bfd67c45ca2e2bf1915a802eca2a23082e7f8ed86b127ca691aac3d6c43ac85651eac220e00c6416c059750edc9e49394d71043f8622cba5b7575ee6a72a74b7a009912052a9eff58b6190b4008c8bd0596f0d6a5f2560aafacc4b3adbb4e96db61dcbaa0d30c9c9e65ed3f1164acc54f90d8daec098b3a849c3578f16f697a9d48b75c83122fa5a0bbdf2d4f425ca89452e50bf7846b683c23a531f11687a3a8b1d9e8835e5e8479e939ec85d0bb457d614322eacc098d57312daa14aef47707625a9a5571febfe49123119baf5587b2f7eb78b2174d9b7e09579ee70ca706e8024c58c496e4761de65932f90325797a4578cc64ed53e1aea1b99750cbca31caad7748c895677386e58f795e188217814c2010c0abd7f13b34a0552e9d40357ca4d6a2ae19a2eb1c44d7e86bad16a7f170d1974d360760196b93fd1e312e0a6a464577164e82b4f89fc094184dab0294250e56b48b054bc65aba7830280403fab2bded9d0b8d1de77417575c32921787f4d13a9ac06213a9251233dcf4668c4cfb6101f00eec685cc6d14aed21153bb3ca3c7a6774828dac6dd816db56ccac3286ba15f0b641246a4ac955a414d31e47d01074bf2711a0584d7aca16dab0af816f5a3610cef8e9963f30b2b4702ace9aaca4ad949d7c6349ac365a72611ea74369cb012b8dba957364117ff06747418305e98feddc08cc3870651da2ce6e00cf1c5f5ce9c4384d27c2fab480646fa76bbe879433a7481fc68029a690bd84b5270f00330e375579a56a7c52c7fac51c089f92c6b1854234aa2a20f6ba083b3f214879da447320e49b94ef6264fa6c0e6d391af7c1488226f0df160899844cd669841c904f30dcbdecb53918da1699f017f58c57fd2d4e6114f3d402b4e699120cfc191b1033cd96f061270c7920a0697b11610fe044ec889f1863fd67c7574f9005536571e687f4f1955cbed493099f3d235ced1b883694266a08282a94d4bc708ea8ec99d2eaf0a02ac9bdf6d6cf93dc77e46b2a79db375f065f9cf5483b099cf0d79f7836e16652e281c9dd41c4ae6d0cd19e26d0af3afabcccb1df41e443c2429c408e4bf17c161cadc1eb8815dea172097831bedfbb0d51851f954697376b90619fb05a20582598452fdc52bb93136737b2b04b9ef8a41c491bff63942b2c6fe0e13890cc6d2e5c67d6517a75346c44e443ff77d5a38a81ca90d6cd065c01f5520e6da6a0778cc6c57003099216492875f39db68cbcd1cc2a4cc958021e8639a522de1b14e451764f2fcd3348b31cd98572147a401e3065167420b667b0cba49cc70be14609f7ea74a05b8b5ac7e673c923e35c4ba1983634e590068fafd990212367c0787924bf042d8b7f98b8654d410c5e7076bbad438237f69fb55878fcbd392c8da9bd7019f867e4f542214adc4611dd9327b887422d99172fcf6e048606b2c23c812d987914271b30d3559e16758d9a45f748a2de8d05478108db8f95e38935d0bf54d9cc9f61d42060a7b414ffa89729deec9c2022203ead130e0ceefbed28f9812440247d80947af1dfa246c705b05b2a6dbd5e96dac896d5ef21b254b047482dc22fb49d1852c07359c84d7918740f5f38e597ccf300c88457c248e69e6ac277b0df7ae742296e24339353b0a6dcc4b3a10837b9475df7e36e03ab2108638ee08c436596a353af7d3799f08072dafce23efdf1cb96811cae8ce44750a464323e249cf4d7ca53746741a60c3f62c5adfe0997d61404fe2f4b8ea2f08baa1780c20ba2ffc04cdf4ff774dc3f9cc5c2a845fd1016e1928f682c4a56df9d90cc43eaa9bb3508a9b21d6a7dd2d33549354c15737f065a3089f683f66ac07b7fbe8d574ec00b91b0b8cdb54a886cea08516669421bf8c4dd5de748acbcaca8467709b6778999177be7ef16aa4319b220fc25f30e03b06d21510124b3ad76cedfee0c30762b4a6a2190a37a3bdecca9b5568b414a7208dc3eb0fa34668e7de7ab0dfea70d891f6646402c12afb243c083ab075ca392f43c60da766c8b5eb361c358b9b674fffeeec933b177c0785ff8d757537777c71fd470d6c1b92985e8bcb0e28d891cb83d46d59cc5429fd81c7580bb1eb2734fdde390ed754b470de9342fcba8f6829b6ce713828a9b92a3eebd12f3e6b7ab026a3bc45175981c503e4ef66b5c840acaff98e501520608a6f67eaa2bc3156af3b369ef9fe992a76a3d2312cb0828b47c5e80102591ed193a05bf247eb6b6f3241d884b0ea71b4abe50f4a608b88a592698b88f9ce7fd6fd5b42727892217547593c0470b5336ca2dbb078a28033fab9ab1fa857a7a7947ecc5c79b8ba9444ad8fe2819c1c2d6d2ca28eefc5416f191f91895f35a5ba33960da1da5e71f78164c4823a5e38acc7182d4da64500d4dc84f71607362531d5fa2b9bb8934152798d794cad88c6eeba0a4540d82703f26c9cecb655379ca2d829296c7e276a434daa3c3ecfe06fd3aa786a82d0e430ec8a6b8eaf33da26d17919ea312cd7a2d5da24f3aa0456a158027f57311bc257c056f11e9db17df0de95ff1e2344fe4280a14b8c20077f97099c3a87aed1268b39c3d0da1f21c077c10a541c055678bc60ed9b48f82487ad801f2b2bd5d2b46ac23e8debbbc15dd5c61b8af4781781455b3023a845aa8a53205f432a0891efd86c57db529d70c17cff95a5e5606f5d3aeffd8cf27c180c7949256dc382dcbaafb11dd5cbed44fd8ca5d88ba6dacdd98be7c6e76ede77bcfb5f87a0f7854cd74a585a1426d8e9b539051dacc8b4c5ef8f1cb72ccc6151b27717898956b3a400873560f3105844ef8a65c36c75353b913299a8d47225cc4f776f0b9c8d5c028a8cc13c921fd65429a4d04f58dc2d7820d37c8ed4d49f3dcda59dada4da4645012ef0b2f116721060f87051abd34780a06ef485b527ec299923682ea36163863722722c1b5e695e0f9557c2c76dce3385fbc160280f8ef904418d99da469df9ddef7552a146ef085f8898920bd9a49b56a04cbe2fa994caadef5b6086c8eae444f60c30d741d9007351ff929239c860441dbc9b729f0a07d4f2f46f59234ec3d805ce1ab3f8130f119181a9a03a41e6f9f7a071a10e0cd55c8a1a083d7476ac0146d0e976f8cd3bbdcd0970d857801ab37364d152c8e5d225ef9df929ba2d48c19889b50cd0cc65337254d593306f2706962b9435d5c4cce23beac0b6502c6830d7deb75c89d24c890901e709ec93e16998e431114b91d3111e714fa9417f7832eb648f588304f05cbada8188975961b0f5f14cf35dc580cc71f7faad22ca306d3022f1e6b8b1336f09289bdec1a8113d3ec10a3207b0f800e8de58259d8e19450d31f3fb0ee88a29f45044daa0a54d84423ad4eb89622f8ab49da9c60d10f3fdc154fc65b2f1c48f63bc272f90491968c0848e0d4d2a6b268d28a8166a36002a2243f628982f18d14627a17ac11730cf8e31a32b863b226b2ba26d0dbed58eb77fcc9a1741f03abff25d8a52442555f91190b1699340c92ea7675535d1968d2599369a6e89a8164cdc8d7ba8bdf4457d1f81a8efe3f258ba75540823d7e0b0be0c8f183c8ba01e7a1ee13b6c8074482091341608bcd54cfe69cae70f1700cbedd19dbf1b11fbabd5f27963b4c57a8205372a370a4051a7693e05ef34f6c829d86b657d87429165fe4b03e84784c1461a27c5578d6f64538339bf5bac204880e1017592da7f5c94804dd3ea3455049ca8d049ed0d997cc58b444f080e1df5f685d63b2ef0cc81c9cc842d3b8ee00f8d1ef72c4c7048525c9ea0adc3df1514442a9a0a831e8958bf569ecacadb77f44bd0c66e1b9202689211c23431447380990fbe010625372140b1f330ecd546d40836fab6881a0ec4aa32c96ed1facd776850c4336a92c94b058d7689c60f355397dfa0eba3fe04764ca9e4e4137c29e7fbda4f9dfac531df2316c18559d80907b8c581546c71a5d236a68d0198ba100049c569b66152a659fe1a00559ef2726e0657012ce2e725b221759919f9473a6694db75ebe63e463795fe1fbfb5cc008f8187f650b0a3ecd98de21640527cb3637aded478333b4a24d1bed7ff431b3907fda1509227598e729b49e29cca67d3586690aa3c072cfac41fc258988b55ffb2f3687dca41a180329989ec52028d6fa3335021fbda5c252053aa1b20a40133289c0ef39e707998eadee8131f94b535256b37a06e7e4fd9bd17def7cde7f0f8e027f10d539cec747034ec518347e31e8e594e2e7d00109d0fd8e918e67a2cec80a00dea7e5245ffb6d130de0ae15b3f43964a1f8e2282f449ef16fe36b161badff9f62cf18d01cb21d2e3ab0325d9551238d5e4e0b8ab7dee0936e8541fc50eae2df9d56eda0424f8e7002b00ac0dc5d2690fbf9ade34c0b46d7fd8e7dc80e65afbe2f88665e2f1ec3a7b0c907208ebeaffcce70f471a4434dc52effe2ebb23525583696e12e46771c31dee74877322a44e083d2e83a032f122cd81f0549a9c55578f15ef745ccd4b9c777c1ea6c58f912c0bf0e5a8823008eea215e963c830d36135cb6fc0278c0ec899c18d1b92fc7bb675d207a67031d65974e001deae4280de8111dbc8978d209e12050a0ac733c615ca8f5bcd2a87472431844f855ba2b785d32e6d5e0d23f5c20c68796832a733ff4b6b50b3dd5554d869a0d0b19227c3622a7faf21cd57cd665b735a2b7e82f297f5b02a8c89cc31d58c9bbe3485da3b5300372f0e879be21d0b6423bee7212401c57e55504fe3b7f83badb5585cfc875bf0a4bc5e3c3d47ef9bd2b17bf961b5ada11d2c00ac865c002d162edc2eb8c56452ad6b4618318f770ecec2e5cef3fa9543197a96a9c031a6a18e8e51fdca7b25d606126d34a83567fda7cd71517ce4c0080d64d86ca9eda84b3f679b32dba62dad73f509b7d216a38b63954aea8d2dd6ff795c30302def9dc51bd8300028e0b3c23206e80530039956a576ab8d21ee4cc3b1c3ee2f3a4a741fa371086c28b2ccd19bbf446cef963f5c848fbc62b9fd0bd01f95ce5433b2faae12f3e48fdd4de75cd4ad6c35fdd26dd68270dcf7c3273c97e77f77f8295bc09175922acbfa3a3c63c4719f0ad0831e1b12ab21b78c954e39ddfad5ea208d782f3d97fd6886b4280df7ac9ce511f5f18cff1b785159d66c8cff7382b7833db7675153b5ec14658c01dc4c9d949afd4d760300d6a824affbbcdb30ad74b23dde49cb432665cae942063500c08358f4c7321f58e99385fd43eb4096a5479a3a8752c927d5f8b1bf2df58ac59322c4b3160e4915e9ae5e71e676b4c4f5cfb5bd2f56114c933b671044ad4efb0fb156f8f617a7bbc75a43f1fdaea607c1ea75bc79951152a58cb8b11400f5442a0985ca9996c8e16802c5096ecd0a3bc1c2a0ae19e2005a6c762e5e7fcaa932e9e3b882b265c89f29fa9798596592bc79038d897dca2741cd2af3995bd5c8e29d09211998fc6e513246308e6351f456ab4785972e4586d6a3cf9f786451a1e0a5841f13429188a0b5db0db965ecf44ee9769bd5c346421e3131a0be31f1aaf453c44e40ea0874820e6767fe35e3a5e122008bac4a3117fbde531eeb057cbdd27b28bd1e704ff05b892e76760010479f1e04885b72c757b1c3ec35d733e526582a71be415615393103d94f8d4192af631d823047b2d120c235547f9895a44e8c64f555a5348c59b1d469977f283e514ca49c48cd5a075cac43a5d4fffc66b5df9c4b6d1efb1fd5d0aeeac1ed4ca6460ab9a9068e7b34849128d5b772d4caaa763ba2c57bfc6a4f230ef3fe925a722978e5a95683343bf86196e1f7038ad780d2efccdc5754a23ac4635bfe9adb5801994bc9bf61d0cf2ef3bba446f5a01fe3054bbefd2feff829d6e4ed6f9ca39124f7ff959048af964366c19c9faf5a7e311dd9dc232bf545151da16cba2b7ffbcb578602073c139a29b4310f6f4e7c550e3bc8af68fd8d2ed8808dac14a8bfb875c411d8c3a84cbf63ab8aed74662c1efde1371fba61c90dd25ccb5b5eb1410af24b752ae21609a837370ddb1dd286bbd33a912da5a54632e17aa1590349db615703470c8cc5ba4da06a3034fda5cc9ee7d2550c412febe2ac53caf42be08792ff8f1c952c5fc126bc80c09a1323f99623c54282d07a890f31bcfdccfd55b90dd1605a4226daa65be75e51b3064813c2e69f864d90b67799f78a1e818dd9477d747c819470e15b3c3be1cbdaf47c577598d87d0201125423989e098b077fbd1b08774073f4ec846d15967f9dfa99bdf2912083cef4be28be61a239f5e531a0627c739f1d0eeccfc692fef015395130e7f8879dcc82cb24e8ae96e304c2c86bddc859d917f7cecb48e946614d97091af93a37c560d59bb9450debbd921fa13fabaffbddccbbc9be6e5e46185a7e6598cb37b2185e446d1e010a229f0cdc73b99d8c3feba72b651b9060228b7ae634efa101df94b8f19b7c53de59b656656d5afedcf4f27921af2ef88e2220b6a865137f86481f251bc85a815e552bb3d1f35bf12688d7cbe45a4409e430a067ba3c8e2a57c9e9941721e2bf28243d1cff37348d41c6aca2ce320592880105fb13080e3807cb84136b723aed6ca23de91172a49a99d0393c68cc94d654e77129d2f0f1761beafc9277f6255c2d772e22120fb2ef324750cbdb7c84c0d6c59c1220ae3f3bb635aeeb748e88cc4ff6e3167845234d12f6db8840f1b80101cab5f62d0d40652392113b1f3f3438e228a4b81fc4d483614638f00e4d4c0cfaa60e9008d56716060470a6df7c108722cfeaff053be4f333250306054c3b3019b68b92cf8b2603332782ca68ef41c6092c5f05f0d3b5da3c0a4c42ec2ca6c197a0ca32804c95c0abf1a8a432cec2b5c5dcc21aa214a484301ea87b35d5219de68e765a0d56212d8a73629575f61f4640813018d7d97f024b10a19e659102ce176b891ada7f86c03d35b0680f0ee10d2b2e8c08fa198e18d51eb9f11b743084781bb9f4b8f7054f530518c86c3ec70fce4d038c49df1e0143f34fb1844117fbadf214a9edbf056a68102367604c783911fc0890a58cd537eb083d1a5257c7e425882f1f67aa2f7824ca0d13f2829a14a3e9dcf96f3c1c9fdbb2e00ee6326690b3f8bcf5e314c22ba57fdbce40058700e54241e129cea8537f4a0b7971791f9ff44e1081b475006e177587db50546678dea354c9d5966e0d22356f74008b5e1057b521b6c31397595ec83734ef762dde8b896ad764de795369d25efcf502024f8368b1968d1720ac3de096dadedd28bdc721d4c2df1885c16f1a2cceb6f17d2282629e1c7e321f00ae16301675beaaadc052f8cd76f899bd7ce7001ed08ad23672438878ad72b6b7a6b96f8039ae65d032f0fafff0b80e9cab1b3dd1714cb8be1ea294243abe9f7a3b69279aba274015f7fdfdc760dc516ed928e59c3a7cc9d5f6688557e3e383501df0b440dece645a393d345652b6d49219667d887a2ece1ba490fbb6390881a16626efd90e5e95269c631181397b703ea1b138890a72206ec34da9af25dadb22104607f35d4c9f5e6fabad1c5e7b23e061d1c551396ab30c8e6841f55eaefa5bc47c4f9b1763d365b9d112cd1b0170b9aa5dfc31fe63446c93c129fa80e2b8b655e4a87785150604bd914adb567c63faa65c5b6364a3dbc26b4876638c44a435ebd1c6c12fe4b23985b96be873238b73d7329bca672013d80c587eb1c4c8a6f5a54d8cd31728437fd381536e3b67153a2d93ac6492597a82465483402245ed7d4d45546766d6b7af343a3ab9ed4ded89c5b2837553567ce7464384453a582328d5293354c6b9c72f9a8c5f37e1d4c7fd956efeac474a2bef52ade254646685867b7cd9d38e02deaaf2d3370c035d3afd79843b454ef829a04781fc658716b1a363f219caff1b7bf7ab2dd380de92286155fd93c2c0e40363b15e48c147a5709339ec3397b53da504e0a9c5af5471ea5a550e732fbad7f56558560c4321d9da707d9dc84b8814d488ac4d5e0810e0177715bc8f76d7c6fb2af5d10203ba696f729d6f82e4f59794c1da997cadd042d378047d0b301b643efbee607cd2d3bf4df8fbc4d0dedf9d01589d8974456e4535c1e0bb019ca761cb24859577a00ecf58f94f9f6c23e1c896a2da960f503050d8506961e19de0c493130d5ddf38aa9263875e56f001cfc46f20c90da3a1e722377adeece689c719b8ea2770c7af7d14e4ca706ed260e7a88a777efadb2843c6d3cd19be949214845d5ba32bf2194ed092059a56fa9a00e17a2401a1ae9655415eabdb6549d75bf9e6302f08c834e09559ec28b7f4e053cb2da0a114a963f6d8ad7b939688302fed00b9694d66e7f25b110da18f555296b9a2143e4f9481f442a3c18a32a5017dc77f20bd12b909d664f9d89367a18740ed378a7cece4f1db79cffba16c9ddb1cbcc7a9bafc6e921dde5e1a017da21426c8f7801e8b89f4dcc02cfd8c032754fc4ee6fc91568364f77f5b715e1768f1f05892be0c9f108ac23ac0211379c83bb12b99b20061f0cdb5afe10c4df5ae051105f6044e3d02c9840bc98627481cba02b775e57105148090432a7d958d0c44a4be0822eb8224e1c43ae6a8ea7c962f033541609184cde0fd2876a4cbd76750cda326f2e01ab81a0cfa4967387d721b67e6de90dab9c6cc569193bcf05a1cac27169254ecdb2ad260dcaa3106a2ca9a61873645238ad18889dcd0cac06700a221bf10ce3ca12c89864125d5019a76a38da635b7742c5aa73ce20d0fdd63c87c36b55714990c530cf12f9561e86bc908ba8ae6329884266982bca85b10da37d4a32ecfef6189dd26ea7a3423aebcf460bd2c1d0855fbcd95c815bdb473a4fcdefdbc712c0472bd918c6db54d6b990e55f02a58a87aa4389ee35812e04dbfc3482e4691bcd0cf001c0af9166067ce8f52a6c8a33650ff376ae4e4ca08082cbe95536588da7b09b3826ca00d571332906360ac071054dd3c9b26f920bb61dbd3155c39824af4057c03a1c08006fd040f490b443f4a4ab49ef08bc33ab7e00486916d35ffafdc693459c83e7ac9979e721a9d8627d7eef113011f0a236201fd7c0fc66b66e06c4176081c78bdf1878233ec594d13f91ab7e18804c62b9331acaccfd1c967a5ba76d4fe07a7fdac77491aa7b2674686b3a07b2470dab69b3c7726c8f03f6a01f4fb8347b3a0df63ca8628ea93a0e8cb9fb6c5423f0a3c4103c546b4a724e12fafc0db9bfb5b41ef438059fadfc3ac7d914ae123dce769a198e1b7230758a3fa2c92818fa04f85407c8d29b81a00d2fb34238459df4b2842e2074ffdc0c0776e18d27d992d0b39fd3575882531e2010c05e9cc2b29763b7d880d35d2aa82bd0559dccc1b3d4665560de501a5bc683a737ed6ab4efc6073e7769220dc3f7f25f9254d02a4cd40e4e9cf4a81afc2e73a06d52c6caad40e7fdc108589a15a4f68b1f040c6375ff3c731d34a585ece21540471c1897a595b8cc2025684a77369c6fa97622846d539dd5842f1bb48f06fb0849974cb74b072a83cc0208d319d6c59449a509e596ec02f7d122a6ee905451b29cdbe9f1316ec98b83ca53274eee478ad77bb7ab3caffd29e172207ef6592de9511ed19eb95068a718dafa0f52c0d9eb9e01019d272de4f7eb7b8893fdd3af19c6b3686787d40c78b93ef0b40cc48525c8651652181645406a47546c2fef7a30d37fda84ed2b5eba6f6236d89699c6f4ddc5f4e1df608061261c024be125b49d1879f46744170f4c478ce7116b50b533bb151443b8108df2930af66d2a17707af37dc00d6de26d72f5cc33377a3dc98b36e7cecc66de08a118fc6f87eab74c2de1887177307ff974f3cf3ea374f5b7f41e45bf3bed8579a8e26b68a418f4022128f71c380f35430ac06bacad7891e68aa72d0f27ea8cc2295add51c09ba96476342aec3a151f35f8ff456cd6c00226f93efcdca23f911ade88b4eadf9ec22e2ac82269095207fc1879f9d299a8978e9f9094c97ace0761c8a40180c51f76b7a4ec564dac78e460a4854adb13398ef4096297fc70128d9f5e5dad7aed14341970d889a0daa81814a0a4d2545fc309f650327adecd1c144daff91ab3d7ecbc93743e955dd0880e662c987085c85c609052a4ed7df4ca6b1cbcec513204dc86a523a4f853fcd850e4515653e99693a38466b30f674719d529a919db1e4afb3123bacd10d3eace15cb4063dedcd408533583fa45cff7c71177071f67c965fa20d7f152b420bea819107d88e220694077f2ed907fcf47df313c68ff6a3e16d799197d701cf2417659a861f384ed94909190000654fb12ab5a6f11b4190103d26111fcf69d5a2ef319b499918aa6a2d98d5c0307d0f1e87d10250004a5304e9803da3d50c34e10a3db401d4440ac9847e843caa7cb12095e150d6e295f1f2468f4661aa0a907319418ffa2fe937b96455a9aab6030b305fbc8d6816b2549950810e1e9dbe8b717ad8d41b9965929f945d9da25c6440f2b98bada144e1cebece98bbb7d275b449c11813706736f2a2bd3652a032a2ed0373c9fa1a7185409eb361ffb4c4b9d421072e8251072d592cc65d01c6454c35642035f351be85c82728f4529a19d3484a2dc410ef4389751b6ca7ac047f092c10abc564237352d34a286870f5b570156d6f6589efe87ab07f8ee9b6bba7a40d5125dcb8e3f7a6904df7d734d570f28596a6ff1f3d9a591c3aff99658001f6b43c6f476fc6914da625fa9a73026b5c4ae3a451e7054e59172af3aa2525ea5f96b7dce00c2950a400b8b02650324676b39733a8d10a9130c45308511fccb0f6e490ff6920d8f6a7d811ea0c05a37ba8978c1f43c4618901c1c1b1e1f4622a040487c11d04c857d1cacd63c76105a2cb507c62ac92461f41e3d1d836788a4144a9861a2bd978660a482c10dac42f0b6a536b87ab6b483ae6f8709f797ea3a00d6b52670afc7bc9472eec6036cbb9b32b93d2c3220301f04ae307176dcd6ef2dd5bedd9446b7dc1a6face3378d6e3c0a9aa52d4014486ea1de5ec00c237d82dec817d7ccf3e7a7b9486149b27ab81c16ec2f64d9b6d12f28a5ae2f60f80b99c064d39db2e30c414eb63928b1ef840972d146c1a4e810c77c9741e5e26a9972b063b0c8a93b5f76d352685637b44e2fe5c0250e37a1595dfd325b6eafa8b6ba314c1ce8d2794713ef4d3ca69e877c03da4e0b830e3a3a2e886a96f960f9cb2fc1f466149748180c4fbb6f48af65a76edf58e0fc608bb9aee5422ab06f80a208c6f29601f3d9610818a989eb3492036243b07433c61bb69cd1464a37b0d11ad9941b4d072b443f63532565041906defd5d2a43c297914341d3a703cd6a63c1e52d100c9e2803b651806cb77b4bd1b164e7c4d875fe0a767703d5cab314d7efbf82e37440c0e9cd135f28ac440014861767ca3151f23f6dc361618ef315945ca75980ee64fd05ccf9ef1e6434ca61a74197aca28d4c40b050f473fc28f1616234f2d5686483e790a66843b71bead10091768953b38cc71c63bf42c1a09a44f7bbfbfd01887cde83ac56278ad39ef945595335fa637a8da407aeb40bab20cef71841de59de967e3e6a64af6b6ff38e08241d4e6f0a28f17c561be9d24e8d4de0b805205140d86c9312e90eceebccc810d3fc84be8f3b359f6df9b310bcb6ad0d2ae5ad4d0fddfdb14b13cb15362e67a13f3cdb93c049ef1fe5ba4ea812c13664cccac5b895c83a6f394fc21d57cb76f3736d340978561f7565c0270eb3ef483d7d7149ec9db216776bc6c329b5b2be762cb71ddf9867a815fe3af89636509be01ae62432530aafc60f617e3f581d147262dca3ed2f5be1b9eb661d98c711f7c766cbd150d00e4b4342d27d27ead303b97e236e3492443e01b101781804fa26fa947b8ead5ea3e2464fad2624f729ba9bbc94854c652729f9ccc5fa7532b550346802cbf5da906555f2f4eb040f7b898544eded562bf10f4a7ef858433656266a40fd88abf7da5429b8bdf9c725445d2208352637511399d4a2707b0d0d871fac60808a8f93a0d33182caf6a966e6a5e7b19227896fba172d4b039db1543bb303dda812ccbc05a84ca819d289ce45013924de2068ebb9b4638fc052e36dc6398ba813a799ed0c5fc60580a102e5c1302039d5a709190e076231dc09019f3158c07344a2335ecfeaa4cae8516d5514c81d4272fac759bdd3966f8e7027377be3282c4f758f8e7b6f56efca4b6751b73050ce1ec20236cb849ee4b315ed3d8155aeead7fc01fb758400f08360ac68cd591316d02d5b13cb817af3ca415655c7c2ebc02ec81a142e583c8fb867fcf6d8454159127fdc45b66b5c57d6b4474ec3ae604fab56d3fec65a3e5cb80e30093ea0470829d2d88c97e61a6710808424e77f9f455f20afebd39e3611f22f744604e09c1e0d0f98ee9b50e855443e030f91668a9a21be8049bcbe9057d502d271f46c0c5ac8ee09397587f957cbab9039c0fb275d7dee16b449eef51c90be4656c047f549f6078063a24a46f992a4360191ff2c127ee643443720d6a6abb6b8bcd308b8e0c55d3250f19026ae0c46e5bc2b424c9d9e7591ac6739034ababfacdc7a205fa8b8a911df3081fb9dd158abd6b0022b396497c9a6db21f27d51ba8f4043357e860bf4282118341358c1e5d607452b52fe4e2a4b794667c47276c5fb2e18e69fe3c0dc0c0b4d99403ca364c949fcc2f66146a4efa269b1b164e0505cb3d1018ab045d6ddfaab2c5f51f3c78a75c7fa751b2bc93a4a77aaeaf8546cf902cd8d7a66f945698dda9c6b6f760d543d38a7118029048790b96e3fbc8a9073b75e22647efd32a055b79a5b5b513b95f01284717d6ed03cd6f2b530de9a753d6f20ec47d2b039d34572f5c2d24f71957e6547eaa58f05429fd0c8081ddb2c0e4d55661df80767be1aa41c19e7d027533b8d6271545616639a52906343197153e4a7c9d1cf8def8d2cccb5a1b88dc6f8abdd831623ea787f81f5f62a46c7810bc2020d9e0c20f0813af63866d4ec747542b2cec7d11e105add98926034eea60c2c60134ccd711f0d4251a581a7213aec0e9cea2c969fc82ce7605f52a18ac56369f0cc5e354261a414c77c971a53c5d2081909f661a46abad807d4abc4f0615c455369ad3684e5df0943a430d96198bc512b35a679af830af93e01381460778760881761b6bd5d62bad4b07b8db36903b23c4d22307ca75bf130dd815c3b363b8be4a63be8db98e053a5bd850bc620d18c9dad79db1196cac801384b78c52db91f77ea9939caf424e0b1174bd27f8154286329242477235c90b74c144e233c92b9b8c6794a654b5db5ddf520d6c17910c52d638d203858b4dbf27fe7089b8218d1d401ba4c9eaadc8a82a75e1b13452c69c8f09403275bc4b2b9519009722c4855de46a5c583e19c0894f648f7690e8b99e3b84ec71560cbeb5ace0f0689e1f6e23b98adbfff145b0f85bcfb86afa60b52ef549b269d94ada27fe203717b204118dad2e163010ad758d1efbd800bd85657586503bb909608fe456c33445201b79ebdd89d1996d7c8ce122f4d3c01a3a5956c93382caf54a913f58d6dccad7ac0c2cae855ca1f8ff17786bb919275131c773e512aa7c0fe81b725331468cdf2c36dea0758bd58657463df0c8d7bc8b594449c11f5bec63af2da1128b9bea6511876945f7a73a687e9d8ca375e8de9993ebe039f4ccd972324e7c80d2aeec2fa208dfd5218c004523435ded1fa5e5c29c4edab984eb77d5d0b9998cbb609c7545bcf1289097dc9e24484c0457931bf9a8c64f1e553e0672b04382e243f6e9bbc07b8f2637f5f71ca6f540172fd5f356ed95ff5598cb98fe9f2ee03ad75f7f500168b5e802114b3457ac2178dd8e8f1460fc28de2725b33320e820e2732971d4d97d9c59f00f2e952b449516ae69d25cd1a03a055a219c8589e01a33b88dc8e2a424ce5bcc24f4bcd7f6cd476a64fcce7fdb8330104e481a9cc280cf2c45dedda285d1ac77a8e412cd26b867fd2d0e1bd88bf987974d3ad18715ddd1dac748b98a66ae66253308fb5e571c16d94709ad37184cd488f4623471e60a81d0e7a44656cbd5a055650a7a142ee0330bb5d50c44e2f3538476c90da32adead425fdafc715ee12d689c10309bd5f5dc44e2bed388b58d0dad27ad515d61efddd0252252ee4f4c6bfaf878e4cb9b111f4be2a685ca790b449799aec28ea41679bd3a86baec15fd26b8a0da3599d5ce37f42afe8368896baee06fdcb3a90c62f647673457207ff859ed10dca7aa3983743c95e9637c2a53317c825094b508688be83edb6973f2365581de93ec2bad9d023d2559d6a375f50c893132d66bf5d428e7431705db2eb71b9cc6e0e9360e353d4891519ad0b5db970f6f39ba18d9ba56b9c4e0cd079cd515bd89ead1e90f3d8a0f4426bd29462af42595ad444e1f4795743b26b85a7258ed8b3cafbc1874fa3692094982908de933c5b3cd323c091909a1e78ac9e4661e045b022d2e9f0481e48cc1db8e2f4f97b96c4e3298b64c78eb980383d0d15af6b5c0c358e34bdd7a1b411c71677a0a043bc362353445ca7e2a400c47d8b9bca78da5aebcce237289f5292c2ba56d3324ad188276b352bd3bf840a2a93ccef913718b7c9c57d7da5d1a5bfc8e440b1cf539244cdb9626861845bd3c00c28e0062fb53713b99b2c4f743afd04e569268e11b1cfdb801446ded759f917cf38f43be98e50a873ab7263e66ff738658e2e9aecd0ca14aca45967ae6f0713a5455a9cbb2139e12f177d138745e21482b4413817ea5df633dc02c35e78ec31ccac540b6436833371e7e40f2cfd57694b7b642db51352181ae222514dc95d2c86562b1fdb3f162c260746bac9a0b59b7590469160a1d3f2e5a3a6b1eff362d04812761fd7980446841e0688b256bc251780fa3dd37b7b90f1b2e3d013b12dd1a5be3bb8fb26f48c6c9be852e72ed8bfac17992d4ea7beb927ff49cf29b68c7ef5728bff0dbda2db267aeab91bf62feb4567cbe9a837d7c97fd27bca16a3afaedce2ff436fd4b6449b7aeec6fd67bdd06c723aeacd3d58b7b31e7436398d7ae61efd27fda046dfc8745b45c73d97a234b0eafbe3ae858c0722610c16ce75c3f2a219cb86ac4473172ec6f8047560c54782c761dfef22b4943b86f701eac88c8b6037bd6295d0da303eba6a04569b31e92aac8e3e799f0c5aee68e21d1644976e332be795ada7d480bb596bac2b9060993d8d5ee78dde7561471f41313333583763788d454b5b70e03403a41a5a8ec26eec54ef7d3a4c9b02fec0f7dd2afa2941a373816e400faf75677d7d2368b365c408559b1063e35599e8fad8a6210d460cf622e85882f0a11f121de9bc1c2af6f3a6d92d341758155906e06d5b009bb71133cfe42ea7ed9af5984675fbf52172b48502eeedce84eba1cf349f1a6476e77953749f3dc4caecf7d0a03af7dfd81f6a664f8a5d4805e55f0829c65d32f9a0513bacb83ef6af261275b0133453476b50a50e49bf8428aa4afda82b0e217ac9985a50788e1f4a4a7f4841eadd6a03cde59664ecf3971cc379bfe6889dbeace45f7bf16778e31fba232c3c325b160323ec29e582bf21a9c020c3429fc1407a8c88eb7e2218e8d96601aad0566417134dc5c392a3caa9ab816e4af73d88114ae13d88ed0337c107267839b9acfd61bd565e8048cc8b1f492377e60fb87177a68fa2913bc31fec4968d5f2e2476c349df103690c9df92337becef4c74b125a35bb580a36029ab154699ccdfc2137a6cdf4873c09ad26bb588ad16eaf19f6b781933703f70bbbeb66967b97b4efadde45eeb4edb2fc839eb41f9cc067020570299f4ccc900642a5d24d40032edde7c44898e1dcbd13ad81e3f83f01933c70c1c1f35b0df41ae05c3e138a34c21dc78789398948a1c467f0210ce849410f9b3a041f1a2725d65df942f35326770f3f27c824ca851ddf79baa0f80f9dad6ee0ab3778d0a9fcc7197c40cae9cf558dafbc366d44006bdd58f5e41f281f0ddad561e3f83a37340d650468670996987b772d318974bce9b36b0ca58b12d471ce1accebd15854bf3a6075c7bbbb02684ea20a70e23e6163b8e9bfeeeee4ff698f462a1db7d556f8ed4130988e9665f2cf4c245f713a4e00959eeca972e2fd3bf73f47b251ad2b076a4636d4d41fe92fc9ccb3064296390fc851d1c84cb3b238baa6a65466d6ab7796e849c58dfff0dab28da8f71053afa3bea47e64e55136206f4e1debaa17493723ec7b50d1ba95af7841673bac43afaea657099e48b81d21e2f2c91d232591a53ec92ed72e2f96ce3a70924dde51f03d4777178c67bbfe5ade5caa9aa957e23fb52ec7ca67e3025f4b5febf20f49d76eeae95a517c970fa040a78a5a57735db58dec4e9f5b1f2104de598f230dbb257c48639777acadcdbef7124ceed3f73d55ef1424ac523d32b949b7a23d2f5d382f88912080f16293b7b8eeb1fab2e7d5475dd936cf541c54cfe3ebacf3fd1b2bd41b49bcba4ac8742b9b1a6016d4027ac3420d334b5653df983bf4f86c44d6ad98d0e077b4f83a71562cde5253a0fd65f460551935ea1d4e29bc7f95ed206907c876486a87a43be092efc071e2a12c2aaa4b08914322e1e5507a6d7b086dc04b5293c402ab660dbc1eb0cb20d8b9c2158543aada695988a7a6076e70f8d75f9a1c3a910a4658fd109ce210468649869c2158d7a2b343de5637a88102bb46d895f2f9dd55aff6a2a33f5e6cd1df413551df8d1602b2c0201ed8474a9aced82afa0829db918b26e4e675737a34279e128767fc867baf2a78e903302314efbf720f4ad39158d47e4cfdbe2587ab9acfb6dcb05a946e0e797bda995bbfbea85053201df84799cc8d6312426df337796fda21e338c4f5f9e1f636ac54553d3a6f5e817087cffdd8ab3d5bb5a0a59560f25e69044f5ee1ef81691c34b70970ec7f1bfebcebd9db9d28a5a22c25b870e7fb1fc03b8e38e70ff41c488f920438998713223fb01788a7319e8aba51e4811216da96cb8f9617b31b304380e7d4cd105ad9812ae5cc53f2c794d212415705d6adb9d85ac522a04a7293753d46f92bb86fe529c010aa605ab9b0d49b1a38737ab1ec0fa8d5fcef18bd69db58c1e7ac898fc79d050653ab1127db09055c05856eace8353ff04d3359cee61f5963b198e50b5fa014af88da9f076681b9eced0bf6c64c470f328fbe5558eea33b7499623b435502e9a19c85fbee642ceec25e53918560473e99640465b9b4b35bff8889dc153235055016b68f3147749f4632a5637bf4c899ce05e25319b06884b17d88c0364e3d98f72c2b098a1fa83c1d7923fd8753fdc7f0fda5be1b8d1cd13e5118928ddd6595b11ed03a0737121a6474a6040f7264a1636b4643f140900381446f8088744797f8b0da78e2fedd9385cd03a79ff01f18e69848c01dfb43db05162f1dd6faeccfb769b5826b9e648de8eee5c660a266b52f28b687694ee8bc75d284f860e8bef308dbd11d6eeba9dd66844bb5e4b47cbb7fb5b357bb624da66e9dafd79f4ba16887faef46992d106e9f538db52753ae9f45b5dbf261d12854260f0e464ce4dcd41ea4e61ccd6a98004699cb3329473e0957b981691cd38990c04659e2937c8fede96aad88639f20d809217c470c942af699ebf32f0a6127ffc46c939af0bea0963012d11572ee15a1c5a1daab659ce46745f679248dd2eb43e088944af15453b6f2ed70f5f21f23dd4f362385e3d0bcc2d723f68bcb7bc57c550813f456826888dac64de1148ceb8eb4d2eaa83d4fb2615e098762649782380610761c179d3a9aeb2e7807edaeb6413731413f99d2c64bf14983ebe83f24aacfdfb0ede174b855649826f80ddee6f8590990659c52810dede85352b1aaa2298064af2dcab99a212ea2512365ba19063af505d260a903928c696f9cf77c6fe236b2e929b422f1f31d436fc16ace7fc40fff289bb748a387c2fc850e675db888d966d254288b6e1b445512755c02c574bc1c83f445d23fae8fc4664a745527a33be7cd750b7eb7584b234a04cab422fe89c02335b2cc46ba2ba639c6a48469d1bfba8248da519c62dbfe6115d80f0688364c5975742a92e86fa20d1c2a58071b98db1a882710fbc2e3b6d4f75df7609ab7184664311c2b7972a521a893f8d6c87d180001347862b820cd4a80b0e46f780ee5b4ff3b82495426bf6156a7df4e0865cad3a77b58c30452d7860d131d526cb8e7320840a9624861b49072d2f60ccc99c45070283a2762b69d02698fcb4dfaa5b440126a0d177ccb30b05b69f5e770392f8c3f14aa03c9da10685b2b66d860b823a804c174285610b03ab152cacda584a32cf3c5ccf7361815f6f0fe2a299084e6ebec828587dcf93e8fac6ac0fea1b8947462440e21390756f271062d3fc5017e82b7abe86e9506c1cbed4d51c795726ecc446716348f38bf9c76fc49deeb67fcf84f4bff3d65d4332e52a620e2a1ab25f28cbab7fcffde17bc7402f625185230391c4703f53347ba113c67234f235dd90e6461a9963697ac80c519b143d5a2ac1e24495dca065c31042d37ee89d73b4673aa3a2893c274fe0c293656647de98426f0903157b116dd3a7e8b9c16f4fa6cb077c6eed5a11589866d5f4942ad64ce58162690ddf6a6314184bfb4a7f30de81d533facd53e4644cf00d01ab316ed16648788e55c886b853b71a92c2b4f18d840599819e74d43849443c2982b46e003ebb454150d2913ea58e5e90261f01d2abb1d0fcf0beab38ff2f9027badf5f47a340abe77d75623ad13fcc7ead704c1340400a2e10c05ebd0bf13a031479a1d81076da779576dbedcf6add9fdd87f88ee410737552cf38771b2e4a0bb00347f1217139c1ada63beb990507647824053f60558a7da1cf1fc6f624828c93ad117cdbe05c65cf4446c3f66ea609e87744f7774868956d4d8be342a65a8097eb9fc7df256e9c8627db6c23fdb69186ea0efca974f28a420f9fc0794d0043ea944cf0e59305a19271d4532893db1c71e99c1ee2b72e4128c6b4d22f7f319f3dd44fe1ace92cec0b627801b29e0550442d45dfdf0cda9fb8e732bf9f6626a4c413c0cad5445701a7834b689af6a1ffc406bdbd41a216a8d1042f6967b07570e980fb00e5d0ff4f321f3be996c06bcb6213ffad68dc4158e18a58ffe7d852346c9ca7f3686674756922e890047423d6f667a747992786f24931e591ddaf34c04d43e3ba71904a0767a713bcd121331c65b7d8865cd620ceee969258b693bbeb13d87d3bec5d051bf1e324aa4044a531e785a6bca3adcdbdc34fb3580cbd04996201354a59a4a00ef76550d524ae9265b6c61e39047158f3c9b80f7bd6dffb6bd35aa4296b6cd30113b40a149c6550aa08a55793aa95100afaaab8a2958b32ccbb2ba84b904f07aad690755d77260b2cd6d6e736eda8c024739edd606e56fa40b215916c3702c1e390f701cc79de3388ee346a377a3d168c4591b33445d16864b80b7d5ca40d5d4349e99533c30a40340c508513aa665921ea19ed2093b7447005574b25579bc4013c0cb35e5e84baac216b580a453c8ced2319f005eda2c5b4c1b5dd0943d497a7ef41c0265131c2ce9cbb5d4a14302382fe7b444e0bc1c40473d1e6912bc0874b225bfb904acf2f5955d9e6c551fd6c0440d425a9d2f3930015731ea331b995dc5c8ce5d08673986d14eb53a990036d1c14fdf0a4e249de41e5026e9d9c1546615500a5551d2158907402954c5a765959eae42f5208f92477a3d69b31f51d4f45d0e40005913ca8cc2ae2276914ea794a63fbf76a04aa7678d31ecea3eeff475ead84389a7227da990145a44a446e8119122e191823cbcb56fac594b897c52a7d222b4089221264ea2d0293b7c00196244684993fa845d27714750564f89b04b72809fa901a8b3835f03b6577b6d83efaaf6f56029118ec3e1ce3e1d3e2b258b0b7e5e4767dbc14bd0eb4ae2779438619c589b7e3d6c37d9fbfeba7e3d98ec55d10fa40148845ddf66e9107b7566df17697ef7ae7ab3ebae061fcd1f7d31c01edd86bdac23599cc9a74478a43f89dc8825cf515642d1ee2a4b494b57476f961639899c26d21c4819fa4ca4468a002f0dd2949e06a143d845a416b55cc191410a9d3ce5994dd96955d22a948a3081c8109123c280061e174401090bc290e4046010826d3c94f87810ad086db46d3362a29b90debedee8f6b514a282032d075d5f8f0790cec7280a2a7d6a2914c5175e606a291445132c1e8097d581aa6c347bdcd168ebd14863d765d17c980ef5d486f4ba2f8902489b4c2f89f3d3a1f4d168741ebe8f2a09bcfc2868fa143bf1e63089d94be2372b89744debde83d491b8796ece296a3fa7a1811b8d70b6e6ce7ddbb86a411b2e1bd234b7320001cc2e4797bfa4cbdf4ee49a247a3d12c1aeecd264921d549a49adde35718e5abef296f3b40d0b45d1a3695a0aa1414a779aa73560b3ab18e1591e9ea74ffce9907a3729555d7e1b1d9d44d35362e9a1d82256167145dca8971d25765e85910e840b1eeb6978ac2a208057d5b2e7c79899a344d9a713bf63bbe2619ecfd35c9336f1c6248f9c8aa73731875b753a275ed944e7e8d3fc48aa907576a15edf625777b29aa6cd295ba374d28f465a054f454d0345d973a2e103390e676bf0e0bfcf247225f11379903d2d48ab5679ba36a0136b9344ae47a2d7ab18dbe579ba1e013d1ee7e4c0a95d4e68657a2e5869cfb24bd9a272a2c7310f709efbe52849850a15249c59d46f9ce9a4b98f3cd0791d27de4fcb4a593579d9e824b192ec9d9f0fd9cf890a68f9f590fd72531e14d09cc5514073ef404fca16729298d6120e6e1d8db3dfaccc6cbd02919229ad7dd583f6ec5abd1c7bf36b80f611bdb34a73557ab47d3e68cfce89a6de3ab3940713cf3627103ab9036e3c9024e93cf7c663f1deca07f0a5cb5e7da44bf17a39ddddd499eceab331405bb22f953cd9d4de4dbcf4527b73fac66bef9d277a2650bc5e832f8937a74bef24bbb8974aece417833ea7b793c4eb35e9a337a7bb6fe04962e92af1f34188ea36acb2db4fa75e8ffea10e8a9f2d895e9fc44badc9ae36528a8adb4922c729d18676e335ea92be781c16a4a144ae790778e576fedd7807388f12676ff652e68e126bb7e8e8ddb7d0f34e371d7ce9f492744a3aff6457dc57a36f27ddbb495c8d569ce79d9e64ef8ab4496f45a26ff1483f7be3b53a925d75a4afbad36f76747b571b7bd293232badb7f1fc7a30f5fc8cc13d0f9a9854d4757207ece6b7830fa48faed77745e5e767a88d41b2d2ae48313ddfeab26cde05c9c61871dc333ada42d2258cceae4636066733bbf261742eeb2e3ba73d6a5724edf57c294f69f0aab33146969bdc4adacf26a45d3191d947434a627827b9e819bbba35f2d9a9ac5f65f492b333abccc680c1a33c0d1e25b577a6d5da8d697eb8bd53ad36fb6edbec8af3c495f615f7edf4f5a4156763ac341be3aeb4b73a6c792abfd9bbd26c8cb05b2d9fc5a8565a8f8734b92f742b1c31b4158e185a8c6aa5e5dfcf8b4c04487f337b239934fdcd4c53ab43391e3a2711ddbc8bbb322189110534df9b2c18f273069f03d453296486292db3037010c0eb0531839136b5142a83916ece39e7a4a74da77c16c02b9574f55e1c06bbe8eb65a8f855c330f3f5342ece708428e6b6bab2bacee6809499cf2165e62511fd0092ce24eb923a3424c88e1eea843681e4c8cf0f96c245444b880cf1d9319f4c27424880fce4c8a1316326264af663122d2132a4fad41d4f9c0821a140e8cf14294c888a10e11eec03e58912a1093481c472fc406346014e39696946cac8190528ad941967f0c839002f0d0fb3f933064cc7f0283f1e66cfcf2cf3bad089330da07cc74c65adb5b46a96b2d9e29836e8b873ddabd89d136fab397b30e4b84b9ba330f4b722a03559d0dfd91cf72e0a909b42a4419eac7de3f85d1a40eedd9ccc515a4bab1859672f475f636b2200c664416f68e2be5feedb6a6a6548193a8347fa911ec64480942c48a7618f0eda1b96ec672fd3b30ec07a8f3b7b6fcc1e8997bb69b5764f5cf500b676b0352b33263ac92e66d728c7ec32e6d268fa09aa42d65b630cbb4aadf18792f816109fc87a109e18b284e8445558832482aa9b91e8819c97d3f4991cb38ce7abe19ee6f0e38c9d3e48c03b7d8e381962d2fce9a43bc7f1e7107d491e7da8995fe091e65f86128620f8cbd1b3137ecd230cc3a79482b7e1790409bb50e7d3f953490efa6a3983e7cf22d308bb58ce9f3eecd27af0eb8720ac94302d96f49ba36facbf97de7d37474effa3a8d34f87d341f029f1f274ea5de6b188a5cb2f653299ce836c93359da73fb144459378e94ba26a85f2f48a0afc07de86a6449047067fa0af1a09c36fd2b706f59dba299b5e87d3e5974314c0d34bff7838fd137360029e4eff3139cde6ef3b7da7db303d596aef8d67c32651b6c904526a126d28ced6a6bbd326ef7b373df17b893f1dbed2fcbd7ba26c4ac9f0a4e7b43707d7de67a9387b5c9e9e9fc5d9daf3be79409a89c8a62ce96bc298c920a5ab956dc3dcb3c2252a8c01288773b81b30bf50ab0b2a2ea8c8ef58f444708e81bba9695aa54a95295dad906db33b35b0a0ccae7aa85d5fbbda550fd9eb335b2995ada9f10c039379de3e07cc1667f337ebaca46ca4755d771e6477e7699278dfa44e249db9671fe5644d740656af8a379cf4065dc6949fd59975cdde99a6125087bb6675720a3a13cbac8a393001f9b299f932bcd3cd1bda73b818dcd36c29f37da8538ef559d70e34c7c86a6ba20e3753594b38b4bae43cbd4157eb0dd2b0793c86b67e38b33929c32f9304a014328392be5e534eb6d8ce1fc916120d9d59514e2a64a0e6a6a626033555d3c9da463d7d47b773e7d13b4ef446226706f0cdf576d9f45df9357b389d99d9ea71099ae70705445c30c39013a4c02417aa00842730f12309204380c987ec72b5fc8c1f847a7a6c60d0170793974010a90825cc7cd97023a115618b159ed5e26c789c2f78f4a181c972f6a6a6b7709b2fbed02307323803178c0c614607636882c813580803100c7006d0a708cb0a859042fa22591bcab11a64d005161401610813b0ad0a5a1082124f48a2062cc0369a201c98acb0f7a6a6b9bf904236f41516a0b7227cf4e6f5560490de4eb06de3ece57a0a50ecc0083ac8c113440002db00700313a481064d90900228609b65855c8f449a99b342fa6a31cc7ccc8461137e64692934061ef49de178fb41977a79d2245f33537e06d7b8e017d72295b4ccc97a5e9584474f9f5a2601410f28403074cd68220d8f457ca064ef666f6a5a3bcd240378677898b1363c435f1ec82e02b4f6900cad9dc52e53cb243c52d0da5bfca230ed31fcaa306db3292437784288c867071498768ebe12500514342109124b488214609a05c9007ade28b6542c7a3c860c333fdf330a78677ad6ccf06bbee684cdb3441fa0ec3a869e5ed152480c56e8dbda38cb78903c90210a2110210411b440b6a82d3fb37fdaab387bded8813bbb0edae5a7437683256558058bc98de40948aa80e409245fa042e8f8b583fbf62a5b78cfa68471a284b1e400f89b286501aed87c1e333029077057343f85340087c105bbb2ec9aeb3c324bcaf033318564c12ca7a51674d17c1bd964868b1a19cc573669760010be2061241938203011124656de91712d414f2ed2f45c3d811ebb381d6a0d8f94a62bcdc9795f8bd1e557b205e9f22e1201dde543d9e207bf681886567e5d162d7f6f68392d0ef235a1a4902fee51a15aee620ad5d0d0b8984253680a4da129d4f4cc43585c78c8a68527557862711187e470a72e3f1d5234352e525af6e90092342df5ee74f9e900de8657eea5f8ad61fd0e60f50bd3f5e557ec7a17f92abd3e932dc4d76b13015761c3edeb43d9c2f46aef8d8be6a470d6d321078fb4a50cfd45d86441af427cc123bd0da21565300c952a42506a7f01b94d968694a12f893652867e3e01dee93381c816dcf45ce51eec837fb807bb7eb0abe5f40c845d2ca767200e52eb2f8d94aeedf523aea70f7d01e037bc75974bfa5af1f0bc837f0280e880203c41c2c8be41744010aa206164b7440704e1090923db455c213a20085f9030b243f186120a4ddf22b28897eb95aabd9335dd46f248a39894a197b5e7c79f904d88b53b2e60419a2a95a16c0e1ee9b70d490990ac2006486c5063e2ece111b4399c00eff4a9535e52887fb00f1e692a4dad648842c2c82662fe2011414ccfeed8638f7bb5e027ae7aa836b457abea2db11d97bf7c87e52b15bf0e16df69dd9e50a752e9333dd66275c476641e80efc41c008fed842c77f94e8b0db7d791fa4e8ab74aa752a9f47da6c7588fedf01230f02b5fc9645a013fe3c2127e070533a9561e5b796c07069e45cbe93ba5878feda4b80d8f09c0ead891b141de636c50b67a6ce7f497c7765acef29df02ed761fa0e2f015bb98e1c6c6c270036880f6383e6633ba30d1a1d071b54bf03001bc4fd061b447a6ca76583ee76b6e10a1b74bb4f7b6b83ae76ce8a36e87227d9df065dd24756850dbaa357cb5add061b74eb331bdb79790a1b74b37b5607cbc676beaf2cc806988fed94fe624136003fb683ba8b0dea6c6c27b441a4161b34b2dce92c3688b33c54b015958df9a480c54cdf81818fa56c6ca774940ddaeccef7930dd2ec4e5d92032660a02562ee4c123881ca0a6026bb53b24199fd6c50b5f22d1e12774cba5f1c29d4d35d2745f349dce83a297ab3dc7552b4662f0e2fd1e09631210d4668d32f8e4e8aaef6e2cc3000f9c209ba945d27454f7b71ea921c30d1df2fced449d16c2fceac52056772410a42a068ef0534953ed1b31a50d11d69c46d5a66af0654f4b43634a0a2abb52125c7791e08aa5461c8e2916fa326a1a3b2454ed6b2c50d9d55733774589a7bced6dba58e4b6fcf41c916377458ad3d6776f61b3a2d9d3d476b6e7143e7a5f939b4995ea7eb79794db6d049f56cf1916ca1536a4e67b66ca133eaedf29f6ca173eacd7a3cb6d0a9adb5d039c9163aaad62c98922d74b6ceae63eaccaa58640b1d6e6ea1436ad64135db9047d94227ebaaf375d559e96a5936c8163a9c0a7e0bb6e7d9263541274159ebb460763013553cd2673632abe2110be0f59ab2bc2ccbb24f99c210ca2005296040c2053b9841110e37281a831580f0c3029f2accd06c32036162063e30e20324f8e10418a542d3871fe90c4f0fb690051f44c0c2900f8ac068fd2184f96308ac1774010a2e90011a90e0050e84a0270a16a27882079e98c20f1e74614ad9f1a783f67ad91a6b1792d99da0f99dc9534a27d9a5035ff2b9e6c9af999d5ccb6f520b047ec2d54ca981e23dbbe7762f396d4e5bc57a1596d3b256b36b64bfbd1b893c1abd52f13cce7b6fee9cfd829a1cd9cb59cf7247c0b7ec5b65662fd8949e5db5f91cad58e002f582e9870b28d759d32409a29a0493544d26d2581a17490c614bc2085d0d4dcc48c3faf1a3bbe6730460b54a40a5512d9394c00b60c54127a5abd6db7be5a7ab56cab44a150430dbb8315b56a9d22df857bef2287f043c97c3ad809674521e9c555a4b908551b5608b47b62520eadbe2414704528d25077aa0041f54583085343c219dcc600a6460a283197c800c5228c18f540984c068d40ae1381b5298f9a1db8214d0600d6a10c193133c600951cec0a3490e881045144800e5440234ac9ee0389e1fe0a007450883134c8010c188884110175ab0430950a2c02a14485004123ca1eb0aacd62ccb987425c10ebad6da02ab35e32181121e0ced800827708108569534b1829f1abc6004223803acd28d856e6899840447f44acb2449a0419b828f2248fc8008d4b28d63ee32910049e0c04b2208f4058f73a46905f051e402862746d7469ae49200926a4a278c528d9fd034262411822e891f4ddfa21af74466439a19aee5030cb3003ec2c09fe1d7b08b003ea4e0436863ee03125842085e2802141f4cd10215a450c4044d08a9411a9e408135cc800a3ea0a003283930034f912bc4a00b5430328235ec60a2024da86942abced0ec20e9397ab047901e439aa66094d2cccc2811849192a66f51ca84adce1b22e10356220c5b2641c2059d6a9904891e7dc3be9ed0152690832430410424433c18c24e5111413872042a10010430e98427482021843118290a0311d80e60b8810c887004143c7102a26c0941492cf9c008a0d8c212376841124580421252a8421356aa16f97aa1444593cb444df987bee415c62084256030048322c200a36720fab231c11a961cb18521409a80d1f310764926142141d3b3113eb282a66724fce260f4aca486c7f9acabcd9c40299a12a5e9271576959a9e7bd2d0f4bc837bd4daf37308fd2c423f8fb08b00424c50c2aed5501796f08b32a1b4e787a02f1e7a1801c4c71496b0822460f439e88b470548503264094890a1081dc0a85cc2e7a769ca064d3f7ff06b058c7e0261319440083d7c74109464078cde86befe821c80e0c79122621082cd80a2534946d0d314462f448d6bb6138638d18524ec4048133c80d128964072c4080b7c1084266074094d7b2c694aabf042c1e863ac0b1e67cd4c4c0dbf668fcd57a56f0cd1d6856eeb1bd29819937a4a29ad4900b729ad181a176370694dff42060c4a29189a520ab6b44c7284148e48d277c6091a8ed0012fb104c7d54ca9e1255aad1e3f7a107127341866d2996d4c56b8664b8189abbab0115f2801ac2d931c71839e2139f0881a74ad5dab95b104bc72a86918661ec60c8ece577b5b3d4fed1134e083fc90f9ada9b54c72440cface38a93e261124a2e0832488f8c1cf076099123acbb24c44421a80a8bc600714aac03d9c2b3b18b26eef4dabb9d725a0ccb2873d8ed059965d66969900de3ad7c07135536af808b5b6a8b46a6a6a6a28e523cc39abcd99555a2d5602b6ba5629d43a02b8d15a8f94b22cc88907b42221fb41129f23acad3042cd5e2b8bc7139068666f6abad650071e2470429322262698811443cf5011625003911f48210922f0e94a405f48219b30e705222842851720b1e3670754d2d0030f042901c21a86cef0896047656dcf366bb3f5fc400962c0828f1082c0aa0d6600640c5b28a201152058454257239ae89a7535c20b5d3f58ad190f6536d5882c74ad4644a1ab06ab35ab9587e40c972404456c53989cbde0d7ec9161c40f237a94b82d4a419f264de96f6fb537ad9e4d8304f0ceccf038a3d0f4accb168c848c855c5a26f101437f2d93f864819aa108b245ed0ee98bc7073f38c219a40059828233c0e64f5f2956c0040b8056b0831f25b07939cf4d258ed0f392089d9c92862e884088066980e2084c62c003513459c20307476802268d4081ea839df4cda9f5a702a93f7cd413d49ffa43824e8af5875aebccb25ab3ac6633abf6875a6bad35ab5be86acd321b5a6517967447bd595bd32ee5762971b6d66ec3f5e79a5d8af355cc9e892ccf9f9fd386e26c2d7215b90c8928dd4d8f03b295ecf71d758ebb39a667deecac7e3cfcc02e593f1d38e4919ef5ed57059a441b5afa277a5d3562b2a0ff814f12b923e0a847f66ef273b86bb6a1dc954dd44f87ca07a7b60220c0c93002a095c724a047df625776d6659df67af37a3dd9de9c16b5aba65619661bdd786d03f07aa3283bb8b82cbc76d153257be06c481e2f989d452b33e0a2abb531cfaf4a90fc223d3b7d91ac8a61f8cc7f715309f0b2d0368e1b691ac76923f1eeb47643f29843e9378ed20b215d7e129846cc02d093ac0d934086f1a6c8312d83146aae3b93b665f7549399413b658935f8600a1459d8022cfcc8cd43831118f94091288ad8e0073056b554d3de90c605bbe667d8c52e28cdaf3ca8c11023886005a2a228309715bee0840d3c9005258c0063259a89e8825ca20a2a18431226849eb004187f86be4a2c680224064582c00223c064119aa550dbb00d2701722d9310e1a46f4b284b41275bd77426e112f0ba68791a7ec990a184c562b158dcf2dd0c76d1cbf15fea0b9c4f420451d3df8405cdab51f845fa61183e2705ac54c21da49f1e24a1e6dfec47cb9386624c454c454c454c45da5484618a1859a244099221234754e09012700af1384943cdcf0109e09d4b7afe923634dc29d473fe987c4693cf4d3e261f269f36f9b0ab87298809c81c32fde8714d3e3c31872580d5ce253c0ed12a347f7000deac49535393974905bc2613169a6fd6a477b0eb9a9ae4b0ebd61c4a7a9e1f333561976c92510152a241e95184c936058810f7c487089114d982cba0061208482320fd70c214b2d085a2201e08c1084b9a3f0ac12889510a462f18a20528caa086d18e244970c2149c349f63817c8dcec9800be278c02141c306852d079c07b8107049703f56d0021452b61f6c49b6246c44cddf46a0754133827c8dbe996063810c886c3e9b07d0208625a0608527cdd75ea006f91a9d9f4d41be46d6c60c509030920639f881d0af0644fbd54cb0fd6a23f8d540c0591b3358210b9bb5318316baf0d2ac8d19a0c8c4e0a2d6c60c52e428fb6653b22631605aebe131078f758efcca9a300c3f733203d6844252ebe91c3cb6429694b20129c3bf5b2c9308d0c0b439524607e0ad3df9599366768d667008454a182380b46422044efa9ab01082a2eea40b5236338ee68004f08295b29c596915a3a5c949651530f89c34bf1b3f29c82f09a394b2466b06e3327bc79a01590224fbd197e39634574b8b50233b00ef0bcba9829a644b39d2cb73745671565b3f0d89ee76cd97b5f2ec20970c0d09b2a3c74913488efcfc905244b484c8109f1d4f9c082101f2932387c68c99182923cf444b880ca93e75c7132742482810fa33450a13a22244b807fb4079a24468024d20b11c3fd0e022204fe6d7667b777ada6fa893d256a00a84ca94264c8c14a13e688f28508694046120eea1d2449323467ef818e246068cb1c545c0696bd6e372ea2025a53d30cdcf2a065036e141275b97895a7b3737b1f44e3c9d7e4fdd49f452f7c4d44fe28dd92f3930016d9c8efae9e5e1b7956fa89f4ef7c4ebf5e5da5badd818a03d7dbbf7f28ebd93f8f272d44fe2cde9d3f9dbc103affa7696a3564e2b76c562638056655176b32d979f0faa8317f5177bfa0a75ef9be5935da16c0cd5c1ab0e9e369777d3037fef3812d03953a5ba77ba0d7b2eef2e6f6c3fddc55ed0aaacceecd3adad7d31bedbcb4784e23d5dbe45bca791100e80e0413674e60eebb1950dea1e74bbebcc2ebd439d6b0066e7a3ec2ac61bf537eaa7e7cc5ec5409d3baade989d333ba5b297a7553fa12ef9b53acb25db5b1b75f02b51320c686fedd351281b8a126f8eeaa877281b2aabd3f7c6ebd44fefd84ba5be72fe62704fbd4b89a8771d7f3e74d4535daf4f4771a7ec9d9d3aea2a91857e315467e106c50b9ef4faedc08d7a6ae57495f5784c89a8469d3bca5e50f6d07d4e1bea6d37bc39bd8a21857ab3367474b6cfe76c5667b68dc7b8077abe67f59802602b1b344f4422d2d3f4ddbc2402f263c8243dcf50e88c3f2dcb2ec486856c76c78305d5cb2f06476115636c52839eafb66732e9ba8e6b006a4fbd933e88dd6537f5241f909f0f28ef2b26cff38e5ab977ea3c51f68a785397378938f3fbb4f17d5ea63e53d7b149bcdd3fcff4b57c08bfaf54d68755677d903c8e3cd3bb772694bd2799e403447dc357857d60a8b7b33e7247e2197d3ab05cf59178c3aed1241cf4fbe9d7ebd168d4f2ef82e7ae127176668b78515f398b386d749f5f11736002a2ac4489f3dce8242b55def78e6455f6a63eeac4ab7a17532a9554ad19577d57a94a1788269d47df3ffb95ead66892e4925d7d3606fb90ea01f5ef9fbd3a1a354289a693c493bda0bdf17a3ed3880072c051c140438a846f79b9cb657d75b6e129ceff559cafbd785b5f7101f01bee781cae8c11070088ac1b5a62b8c28a2af122a8c206d14bc112572fa24bd8f20310323130e7c760a0d460178e0a9835080047851317210470440038a61cce0f420045646280860cc12e1be331613c268c794c180fcd6017cb4a0dbb54a813682a7d637bf65d0e27b11809808b39cfc09c03709f17180ccc0c0b166766162cce4366e80c0bcb4014860560630c45c6c6d80985e10700c6b2d01013711306e2221cd8d4d3e5b00bc79c362767882186b8b9b9a951a38610420811441041000104103ffcf0030d1a3466cc982143860c183060bc78f1c2c6c6c6850b17353535343434333333313131e338b65aadff2c162b0c43954a0582a0e779dc74e1a0d4d64aad9c33b3821ac00944676aa4901c924439e8c17b5c6f1991569b64d449a5b3889bd500e6c003c4e1fd6a20d4808a669b13368f720121289ad1c40994a2ce0a8decad69cede990584600ac3c8deece51660440fc3800b30c28761c20518e1836164577bdfb456c149f7e861c4c7a7c88e1db56708152a41a64c019222054851d10f8f4ca3e0d8364ba13085c243db568dd4223288bc7811c4850b201c577f709c9da93e661dc29148b6028d68fde1348077a6faa050a24479e284c7274f9aa04dbc73134d30f94e89be3313264be850e9bc6489121e8778880ad1a0f183fa902183f6f0e1fee205dd217b4677e182a9f014d26968a4cccc70510cbb70506a6390c8233c328e5a6dcb88a44578641151a982781e101cd90f6bc799c7a1593a84477e061e675a1b38b271801488470a45caf0590a50f387fa4e22a1999f66254200d4971ba2af398561f81c187a76a8e321069a76caec99d2dc640851f3e710faaa3f18860f840b021209ab91e639a4f95c065026f9216a21d6aa367981bdb884e17d5c60292a1185794991e2750885611c531da2309c82b5b2d5c70f1085e15ae40885e157210ac3e79eeae3522833cd443e9a4fa1b0eb0a61bd3b5fefaaf36911bbae90d5bff3a91476ddd257cea753d87585bcdc743ea5c2ae0b9ee5fcdac3ae2bc4e5a7f3eb0e765dd45bceaf3eecba42c2a7ceaf3de669b48832c4173cf2574417220d8ffc9438c44d0d218200e2071a33789c9fa12f961d57247bb9172b1966642fe862433bf479ca55272cbce202d638636ef1bf79dbe559acba6959a5aa201ba0fc8e36f90b9dac2b27d5e9f2ad137d054f9757a16244a8f07181b15cfea9ecdae53d96ed2ca393eef30263e9eead7c2fdde705a6b241d78609656341779e6cd0156549ac6215394e64b178e473a227fe628b478da7c4340b9d6c31c79d6bcad3cc795cdd2a8ea9da588e9730abf53e2eb0118e8a21b453130c4d7b0d70c46d7686c2d0d750187a1b0a436f6333280cfd0f14863e88f93ba3f14cce883ac92ef93a8070e63b29987c8b5db19d95534a00389054a458b9802b2eaf8a5991c37d5c602b2eff16197b1b582ffc904585fa4eca5b41007b1b58220e00b8e13b2b0e7379968c8cbd0d2cf17b8803cc0df21c01063063633b332cc61521278000b4ac04108055cb0d2b33261607408b45695c210aa0fe256451a1bed3725026c6c67c5e6039d8d8ceb842541180bf842c2ad47756ec633b2d2b27181bb4a5c6ee38d820efb19d1507800d1add6083b2efa878cb06d1c77656b0b517ed6da8c206996cb0201b20850d2a599065b9d567592f9e952d2c2b3688b335658334940daa205dc1f33187826e8675930a447da7b349c1b201447d6725bf9f826e52bd7da7e529930da2df09bf7279106c09555ff9bee3fd059ca8d277bed10692d77df59d6fe774d6633bdeceea2e8fed784f6183b8c776beb35636e8c5c5066d0f47df69e1504f7da7f4d3633b2d7cd3633b2c36a8defb0ef89519e33161b11d950d9a364c912c0b658346163c71b605da20950dba49b566cfe5cc1dcf06e574368877543c23ae419d6c5dce0778553338071ee08dec261cdd4a87c3f3522d384824171c9f9098cf0bece51f8e5289e5c731a15a4ee7fceb25bbfee2420ae74ae7fd384e39f00071666f3f52865e368ed35b6c2cc8c689c5c6826c9446df760a5e12b95016070a65739e9c2c8ed36973c2232d6a8ba354b2373c8ef4b338becf0ac1e3e8591c9e676708751647d7591a3c8e946471904816081e477a8a6334b25b131cdb71f838b68dc85a1cf3386c6de0ccc631ad1ce25136c9810778c3743e9f0104fa91497ea6f4ffa30ddd4d6853c2ae528b10bbbe27ec9aa916137679560811bbbacd09bb485f59c2ae51e86dac6d885d5bc8b5d4201b520d444dbf35619766836c8441365433c80658a54a95a2e601d637db3b71ea73e001ee20a5cc95b936b4b214704a017f5a2b92444245926813e2a6af4d887913da7e7813da7e7813da7e7813ca88b4a2ed472b924ffa6a40da90064480be1951362523ca7ab221598faa6f2dd2a41621f5a54eaa8f93a6e72960d697faa047a0501f4dcf50380aedc153980af56129740717d11e16daf887671110fd2c9a52f807ef601f93ca9cc23edbcf50cf2533ca6c329950fabb09fd34fd01d2c29242c22e1c53cac6389f17d8ca90d4e937229c00d57d5e60a9d47d5c60e11176e1a8e07a280cbd8f0b6c2548187e6b62845d38a6956f5380c21616bb090d116d45d8b562633e2e2fb094dd9c6c4514c60c20ff6e429c8f962b76381e902d113a96aae773341538a6a29e9e1424520ac7d43a2b4d7a4eede9a16ee06cadd3420a49f69eaef3d2377066eb84dd3d67b66a65da0b5ec7e584ea6ee028a075524d7a8ed6b3b3d7749d97fe4ad3ded2755c9a74034745ebacf47c4e46ea48f67ed779c129f5f4f434e939b4b769af771d172a5bdcc0a19dc34dd29a74bbebbcf49cf6927e93ead486d24e16c79481d544b9c4fc591c93c706989c6771547036c671d771e9db592131224cb1cadde70536bace4bdf54932c8e0a225454a95205c659c90698df49c17c5c609b8db5341b7b6663ac6a63a10b8cda988a0d30eff302e31d8eb51dde8f50bfeb37277c868cbb36f2a89769242f1b0378a90f15f0379b50659e3b6c2769991ce27e35a18f7e25d1e87742f1ecbd77ae0e91449bbd92c8f3b196fa64403e4dcf6b006150187a8e03c1309443750aad44f43fa10fd027eba1b509e884de3aa4695133df9134d284c64d131afb664092a86f0624a7f4cd809a7e0e1135fd6c329d34fdfca1afeff443106118d9f430e84bc27ee791df59e4770ef99d40a06d142cf161b28d022542d4360a90300c6d14186118d9444d9c40697a16035837279587c45d13453d81865cff2e33204c970f825d7713825d97fbe9f235d8754737ecbaa4215497f35389d04472641a293289cc2133c8048a919f91a791af912d67b9747978577fb94c71d66f0e8fa338048ff42c71aec41b71fee091de45acc1237d284e1f3cd2b78842f048cf22ae8841f048af12a70f103cd2a3c4b9e30771f6883462e28c1c3c5e39a5e5cc81c2ae6e8827ec22dd3861d7a84613ece28408c2a50141c4aecce6ccfe81c77957b539b369f038cf3667f60c1ecfc0f377029d01e4537a4603387f479abd9e8ece9d7627fd7ef77e4f077f53479dae5c752a83c7f9d68a0883c7f3f88247168f363c863cbae051c5630d8f24711433f2388b5aaee059cd6d084d72829faea9999919c73004418ebb4248bf6f1edd49438ef4fc7c9042cd354379931eeadaf5494e30a5b3cf87edf59958ed9d36f89a0b1d3cba93ac4ff7d877d289f05efa95425d49dce113343a8f201c05b4f63a85aaf4f4091a5d5218faecf3817b7ad2ae1f591c05f4d4d15a23d9e04ba1fe449f0923dd13bb4f98fc7ad8e9697e06f8f7f425611cbda7924a8e03c130fcc77166a6a6ef6b7e39d358b3fc04d8ab0156e78432990d9c59d46cb34b996a67dfd938a6e63b4fa9d010916c229d6c3c62a2e3f3174089029f1adbf9371e5f8852777e102ca4f381d81efbce4305e3ceff61b3319f1461cb75a44e631476a316d375c43cbba380d5677861f7d2721d258bfac954ba0e15dfce9711865ed7915aaee3b3b195a7b8ca54fab6eb10cf43050b3bcf2391b8d16329ab23e6f254b7994ad7f17f24cfe338d6e8e5b195d5e16263367c65652375a5eb7039e771dc68f4c20aef8db897175678b1233d363af7b25ab158e14f1a9d633df65dc7cb55581d36a4b041dab78e23b1562f76143ee66247e7425a05367a6c873e01045bf800acc506e960b1b11d0554a9025bb141f42a1b4ba16cd0fcc9ee4c1b546d8ba3282a810860a6398d0471620bb0920d627d36e8d26b3a3c1bdb9946f8800c50c0b6c776e61340b00522609d0dca2c28a3282a410f18c90655ebcd2a6550021860231b446d9d3b78e20417609c0d9a96a346f8800c51609b553118c0f95be58a2763af49275b771669eeb22140cc1d412607442306a48edb8f0cfa9c1f940a41f978a193a2b5dff0c8f60a49dda6067da5ececc1284bba3cf7e3495f09e5357b300cffb3976bb0bebb3314a04c62021ffedc0136f81c30c6d2a5e790fa747e0eabbff36b64ed3d6775a3c3ad3dd5274bf335686b78649736d998ad4b76c64251d19a6dcdfeecc823dfa5f3f5c8bae09181e87af49c151adb734c32462f4acfa13625cbf56759617bf69dbd275915aa47369cf6869cf5bcde2c682fd8399a50e784554a991b52ca545b04e451505753f47c0eed1bdb6f94fa06a83d07ecec39a8be519fba3cf7d29bcd099b7b8ed637466fe91ba38ef49c51dff03eba3ca8ea1b9ecd01bbf49cb0bfe7787dc3a4baa173ea1b269b0336ea39619f9e63ea1ba0cde11abce9864ed7375236876bd56fe484cdf21cb0579eb3d2a94b9c3925276c97dfc8013b7ccb8d1cb0554899f91492c5bcbc8b48a5cc7c28b294996f11a56431cf22aea4ccfc8af82265e655a28b94994f892c29338f12515266fe24a6a4cc3c28ae48997993a89232f325b12465e63fd12465e63d11942ce63b9124765286c53c276e5246b298d7c41629339f892c5266be8aa19499a7a22665248b799e70522870145026f971fa184e804f0a580afa960975fae7703a3debe53197f350c14aa70f5f3e70e53a58c4efbc7cc5e9551f88fa1edb11bfe23a6229ecce0d87798b8a9f1e0c41d4e93a4c36b683c36ff8ce7815171fe3a18299ec7508e03babb74eef0901c13044a14ea5c75c6c6c27e6308fedc8fc86c77600f0f13b01380e2bc4c7765af65f5dc7cc79a860202a449d4ea595ef319698e3f0d84e000e80efc87c7c32666660bce04cc00413a2254349b071c1a354c2b508d110519dc1f57e6dd6dda73d37e7799ab3ab18a3d13dcff33ccfce106dc4732a4dc6c66d9cadf545a6659a9d9931b4d6d36a47dab1d659d3168f37ab93ed97e33ecf5dd2db50a969754ac9649012498d8d9491aa2ccb40205a426865d5e3aa92db6ab9a8d1b8e0817a29c33c48a41225a4126e820cd9222665e6654c8e3943e3c2e6058cad042a4fab21003fe2ca5559df9a01b2912d869032135532b9c09aea86c4d940b06b86d60cd9084122e23bd50851e3497342d4601d11c313ade6ec0d38fb05bb6266e82bb4a135b363d8a50aa90453620d21788077f6c8a29e2873c7f4993d62ecba3743e4e410a2c64d1040d0188d7e98014306c8da94ce94c916dcacb556920c1e2b0c1eeba58c7a76f88c7cf0ab6685e0114877d9da6bad1dc9de50abb4a6a608183266d0d078f43adade92327c9218f238d2d7105404e09554bad6c776c0903183696843b04b7b7d0ebb48af75236db547626d2e3315a14416a492d6c2d604d288ce0a61007235a4913272268642414a2983004a56b8047a444a29a9ea413c063959675c65854788c0f92aa594b26632e349b39a65999452ca958ea6b6053c465a2ea181944bd820ab3a88e59840a44c8d30281ce206c6ade97a5a0370beded4742644102fa02f00e7af8a07b367fecc1f9b14fa0470ca264c58465723345d65c0f80038634627ccd43a6d549aed38e90ab4830904a326c84d0d576b0aba9cdad20a71bbdf7a9a7d4d3a4ff36cb7b6f66dbba169aeebbaaeebec0fa491182383539dd2c86a6667f048c5d9dd9cf459d72adcb49b340cdd0af762b97c8c5df205a3a851af9a1af0e3f8c4757a854f58c4a984619cf038bf22ce2614665e254e220a333fb2cb74f918d50e7ea92e7dcc1f1907613b04028e4bcd34e9418670107b1336690aa5c4796422a9110253db066e2927fdcd264c52a8232dd29e44ece25eb123f415c4ecf164ee68a2299423454339789c5a8ff45543777c1b48da3efb6ddf068a9348910f15240924f8c49b9ae6ec341286a3519139640639896211200dc22f190c336728cca44c26919e3f3038fa9a5118867625316b1a058eb33cc826ad48970d923e1f3ff80788fbc0d9434b2b1d9f9823c7447b0876712cfe815ed9a4d5a2933667431eb51e895a772ad105c3d057b1c607bc930aefe029cd1d4a9459c49dcad15787cc2013088ff3a30f09d1179abb5cd29c9d403cce8f87f9337dcc9ff874836ea499b7a13013c62b46c52f8ed2c4cc70ac591a0270863275a94292bd1c6974e335f71167cfa393d1248ad29a3c10fcba6118ed93ab2ff81504c3685c23f4aa9901c7be7fc1a030da6ba4302208401acb21f200efdcd1da2f4576d79e75b2352be4bbcc415f9561b4739a565b93421421b63cc8e66b2bbe0c32641a6117b32b2b32c3894580f5b7fe683734cdb1adf234f83595308c76e550111dc7d5349fe3aeb339750627ca1061f0c8afa1af991a2f148b00f930e8cb05c3f03525237d4d25d408f04e20ad699f43d8a50105c9116357cfcd84a271d22ae99137f2c44ada410a96347733819ab35cd5ee85fc9230edad4944da51b3cf2ccb325a294542a5bd5e4b251001e7593c4a105056381343b7bad15a6badb5d65a6bad1cfda4343bb541ebb791151a019cbf312d9f8930a48cfc0b1b1ea5860410385f29a5948219a552ca2774b23365206c1bf2da3b6d7ea5d16bf4dd9fad46b74157db37db7dbeb324f991682767a50c40fafaec463a697a6fe690a656876734e71372063398c18e0e866c1cf42b791b15c68abb8d7a7aee2bed36b2d36b363bfd47566e56521950195019cc21d289366794b362b6a9f16f9032f2dccc62b529ad31aefa4ae9c8a3a494057de91d7b03a2e5839b56d76bb3e3bc201e83ac7e2686474929a55ca92565e487e87a2a521880f339b52ba7027994d976b76ddbaa96d55ab9eb81bcf6a9695a5629050281402f88b74aae66d9cc448e59045d0f28a594f2a0b59c3bb8f2f555be7edec6644eda7a6badf5dc9d57fe0cdd9dbd8a61afe4df98cfa95dcf97ed8dda373ccd23a72745eed62a4625f548a43900e911b6e6af07a9b59cdac68dc45b7b4ecb543a1d6460df2ca34830d12294e857bdacd348db88f354b55a9577bd693dae6f3dc8a3aa6b5fafd9ab2d4755c5aeda2da5ab46cd2c750138cfd394bb1e6c5c152fd7f5d66a3baed55e3e7f3b5369a69d5d8a9c0eb5d57a2c04052838c109a809a809660dc26903151113f4bc8a88093240d3362ad7ba0dcf39e70c69238d9e6d19a0691bd9b7da3b3cb1f6003dca4b34a1094d68026582ea9ea86ad98efa76fa26be9cec69dbee89376ccff3b683db4fdbb66d271f580efef495a358ac9432a783564a19d451f6646f8d3e7d0b7b3b6da9834fb55026784c6869b11754a92813502a150ab5f21614eaa7af5650aa151fc2182c57592965c0b3a8a44c2865c2991a9d117409f09e08aabcaf742771bb27b6dce59b6559b967bdd429754ad9158a05f594b79d5adeb1e779b7e196afdc136f8d1d4edf589eba8e8a5e396af33cbb62b10ce0e915bb6d5ff9b67dc5de8ca94b1ebda352e2add15b78f9f9903aea77e52d360726e08abd09dbfb6ae5a76fd64b1df5d4519e8a2e8142fdde849dfa892e913a5d7e367c52792a7b51290f045dc270f5d8cbcae9122b287b793aecd357aeaa4f2d2b3fb5d80bf6e92c238bbd60af1c14572ef9f57216f02fdc8a786bacd840851f037866af88376cf94aa8ba8d95b35cb57296af9c45f516fb5918b2572cb791faca596c0e51005731525f79ca4a1e57ece9614853a3e7e545c51e12baae898d8b16e855cee6c5592d9a199a9a1922168f2a706b81deb6b578dc6a402f8ce1716bdd8c46e1adcdb466da66a255005fd4168f59a80a5934bd9ddb60c8685101bc353de7ac36474e0d69ef4dd8da39ed3361e53629def098d921e4d00b20728668751042ccc4f0984d01bc6167aaf35cb9a4e539297fc39e3b789c3d371388d21180f39de4362dab942757ba397a05e3605f69690b406ea254c02fcfa34d8037a49d59192aef7785001d240bfe75e9c9ead9ea49c1799e9e35f5d7833183068f3f00c123cff6c42b91d09cddb0991f8661e875afdd3ded5d13b5b335aba194e18fc4b7c49147aedf6d58fbec4e58cfd3b5a9653101e733221db5827793dd1c9d5ddacbfd000cbb369f475c0d3aa14c0aa5c605a5313dc51a8e03c130049b54cfb18b5fdd495765dcdcc130fcee9ddd0961415cf6da3c7d1ea715c079c95c764d148b006bd0974d514d87506a5cfcc0238502387f6b9ab5289d138d948db8960b172e844017b4cec48e88e18921add66c066a8484326dc46d355dfafc26e9debfee5ea976b59e44a9f68ea48366736a67df6a6762066ada63ea8334aab5a67f60183ec7816018ce2b9b4c8a0322d2565b7e241baead6def400fa0a80250673735445de909ba53cb0a633e1d461eeb087adee77d1e77d391461eebedcdc9e4e899785b9d6599766ea7339c191e2bd73a65566a49997a1bae55d634fd6616834eb624e99b48d3f431fc024f47152b758aeaaeb233b6c530daabb65dae2990995abd6b87f1c9380274c12e93cb74ed4612f576d3b5cbd86e12431eb7ed9f3856b17590c7ed289103c51886d9ac2422315d01a7a4afa4d24400b7731ccd810928956c730e511f1308dc184a4f28bd4d20ea63098fb4ddfb34835c1233e3a2352964d22e658b95f63bb27edf2cbfacd62ef9d6d4afa7b261172b7914e2e52e2e6797f0fc1a1d25096d4d4292d048e8f344b10890fb0fecf23ad2166e2b2b3147cad0bf8843dcd4e01108a667b12ba2a431834719305ef058396f44924b8a5e58eb8114229d8a24b0bb36faf55a3be5e8abb392dbb826e5d411b313ba9653b10508d90245835da04906bbbaab5eb0ab741e59466aefccf8a9ec0d29904da53aaf9c3f77a4ae1a9db2d8115713047d814e4aa2580478e5941cec2a7d6766798bbd120a8b2869fc108494a13f892f6c2ac7a324853694c647cb153c2c5343a21b9d8aa36b22d3c0a0797d671aa669fe0f24199d8b3b77de76eedb9864672e173ae998a680d6dc189ad6c6b7c6baaad65c307824a5441b0a433a4aaca130a4d7a0af93257d067d811608cb594982d2a41c76d5b861d777d2876057e9a4e760d7e8a497c4181e49ffc4191a1e49ef44b10890a3302431072620f79a8fe911a4ccba53b1bb768daf9d020129f5ced4453adf24d2c4d450e63e512c021c9d3402390cb97186c452c9bd697566bdca25a64d90d75e351b9ae55800b2676b767394a8af71160175a5dbeba7134ea613b30828bb9c4ecca26c16014d27b24c66d3891afa421d6583a030f455b394c27c276dd98eda9be51e4a85a7ccdeec94329dd859c463fd1d7dbb99cde159d4755eae377b4da7dfeea54b7681aae68e52d117eadf4f97fbf6d9efb3f746d5de3f93bd5175f77ba3aa3d223de18f071bda6b77d606a9bb51dd1b556797dfef7c329d9808f0ac8decddb3ee4636d3ec74624ae96c9b4e4c16db36cf239d38b34a53da1cc36c9f62952cea6d3c9082a02fd429156565ed40ba36df89a34cac3d6b8bc523f32c9a4e501e139bc4f044091128198d46a351bdf67dd3de393f1f847c746d16e2f8a5fa56a791d6f88823d807bbb46d7484e6a335eec13eec923e2a0b6d9a0f8f75b475d3fbfc74200939412075f9edc02f144af41866b31c7d9d3621a867a29094f5390c7595e8899e89a71e488f2d951081941e4c1a87964af420d24a88c048bbb454c2889feea89705a9401408ff58fec1e376f6e961d9078f5b77b3aad926a9aed95b4aa1aefdc49dae5d256a391484313d65b237a7e6c0042cd99cda9b273fb6727ab57645eaf988898051369ff596d96d5afba337abf1119385761bd6467b6fb8b71a5daf105d71642b46d8b746d7dbf0367bda0c845dad0ded23905da7d3779ab87d7699a81d25925a616b3b8caefd749238bf89dab9a6530463c41685a11ced62bdbd8ad68666ef2a1f91e1d0ce6a894f38e864eb452114d0c9246218fead6929e5d0144924672e9d4c4a67bed98c823a7f4a912a70e59e65f9b4f74da4ca5c328f4c2455705404a906a8d4ea168c7341ec18433403000028d314003030181009c662b168a42afb1e14800da0b8465c244bd424c751ca18640c31c61802000020003033401a00f623f37cf0eb6ed47b22b1875f51cf66cf98efc12064fae2692945c1bbd10a4f8dbd26ece04ca8a3d2f2f96554a74d948a439b90ddf2d34053c92a41d7d6508a3371b43d9b4ab55680a57ae75058f95bd66c7ab5e847544c487325ab82320094b45a7f42e68d5014fd804451670c3298e423e58d1ae820de0b27ed993aeae628bbdf3efb7b9951f6ac9240cb132cc6a97f972412c24dc7fd6eee9ce4b6f8764c1b1c2798ffa848e50348b4251299f008f308e37e2ab27896c33cb1ae2bd16981d98648a13fa002149decdb9cf1ee093f39caf98b8ac1b10f6932acd85f3c8a092bafea185d245921134c638dc0b6bb2cf22158e84b6e68361a64455fc099f0b10a6ed3ac312833deef4750d570733b8c54e81a2547dc4a467fd03f13765d3e2dd4f424b906577c2d38cbf0820b2d977e48f92b5f17518159e2b8cd728868e8560ef73f4f65bae08177991de022d7007e7b4ecfbfc941bf7b7d8c0ce787c90539d7a664342e5d1a144ad978394f8b0eacf9c22160dedfd8253c62fcc7ceb8098594ffdc2c5de0583a9879fe3d2693f65c668f3c629a28a157f641d73d5054101bc4057563f8cfaa000d8d83683e6b30c8d212f5e0353aff5f70f5a25930faaa04085d38f747f3f8444941ae6ed917da7f835fe86f09d6aca4e9f7098c22bb1499cf7da67e769c6c3681f124aabac10ed0357b7bff243746d0c53e2073c5b3f50346b56397095aa301d07edfb025cb4db4ef2452321dad5e292042161075d6390cc979f1b73e7d6df3a542d9583314b6b8d540443757359087420a16740362a9c7f466ce84d2bb113b746c5a6392f79777728dbcd87466f7f3c1ced25847a86a507dfc1c692a233b0bf13a91182d428c28aeba5449e74763ab066762204b121fe83910433740735b40d88621481a94dc1c4b14c952bfe1e86a7cbea493b6b3a4557689c7bfbd2c4360cb5c8012fc62905972f5aba9c488b2392d89d8b080812f5bd86460c494bad7a4542323bccff1e1d63f8270e4a267f3c3cf0c204fc625ca0886fa893daaa29e35b08c1eb58c564736f532b20a746e2bfffb386b0a958db549766ff04c96570fc3758609602f36842831161b4e27df42e8400581e85bbff65fdd888259340b271f7d5d71a64a4d1285f8714f5e8a348962c2ec5840a2d8b2e6d7352a51fac0e1e2b52c258a5d41d6a022471c0594ba0b6acafe2c9b8ebe93fa62f30b597654d02ebf58eadd2fa964f6458fa90962466dcecd3d7b2c818cb25bc9c00114e12b30742a49c8e565ca64c1d9408a965dc79c2e8d426f0eb59fd561517216997d8b9f5a3a793ecaf1f41e2294554c91a1bd0845a4c86507c3df9924abd09520d0fecc707e1f2f564546b71e3b8d4a2933ba3ed84dedb87b43f5b260247d0fb54f1793293dec32b2ef53a9dd13f17e71fa4d0f014d48203f8e1d2411c87b5dfe81faf6a1c35c76e2306a859985343b3ea6089761c40c308e26e147ef6117edf67e872da0b704ed45a77a2ff69f49a7ceba28a46db19a381a1b46ddb12ca96793c9631d7914076bc2fcfa945c9bd85d161693c65165daefc359510512e8acfc24388ce539f05bbaeb9ef281459999dfe1c17cbfbbd4ab7c9cfce3c564579db966446c786b612d7a83462a79d1ddc0fb843c7c288fc9ba2ab002d6b58f1c21a18f809c2d7cb7b1ed9566b06a78897e0d5d71992d67d47f63308a0773ec390455c403bbbfaf25f6f3b09d75dafaf6468fc03d15e8c128ab000ad16ee0cbe8d127f6b71525fa0bf2ce81d0d159d8c28c9741ab193a1269bca9bd5fafa6aec3c9fe6387440184f37d7884ccdad93dfda7d1c0f382dee58c789a789c4adf586c76974a14d8486d4f5c86968990f02378e8a07df3dfd62403b52740b8872c27c3d898752a1d6093693bfa0ae2fdc6182289e4e51d0bd342d1d22799318a2bcd59df1a8c6a88eb8245769d138fb4980fe828fc0d90af89eb64cf11f88e2b3ea44824273e148877a5048cff03dd0fd49a1190887fa239f5c1104685835092fd62315f4351620b8c65059f8f90801c256b752583f3d52cd1bef1a7904ff170f8ffa008bd520f7e93a9f18527a829cfdb731971f852663ef7600771224134aaa0d3ee7af3f34d083ab82b5898a753c01bcb0f42a5933e4e0b2d11d93b4324e0d349e72423c9eece1358e4d41fd7989d84ff98c60f261b8d5a8e3eebadbb2856d2bc2bcb39e3ae44c38f33a6d29c3034fa77740c1a65f88f14a12a5ad74c96fc2e6e11f02032cef714a093241801bba17dc9b1bd2634eecd0eca12cf28d1ea5138537690a5c7a8af0c6a8307776e1d18fee88cae06cad80592711a7507ace3bc724351aaa6c6b4812d71bbf82c7586d2dbc201dc0d2d5218cb55cf56050bc5da2a612957968a017c2ba1ef9a4b4562904e7a01d49d925d590a9f6c8221de76176a36006fbaa091b1ba9722ad1830d64a087c40490828c1fb063431d6e5dc2aa34b969ab57266c4978189672b488010d56c18ab46156f5f4d833c853489854937901601389f1a76347e712f8cf5289f4a38e225c002f19a3bc2f0359bb26d010a6e53d4ab07fae08e185891ee8e45e6c2636e3cfc150fdf3b62bf1dfaa538e5502979eab5bae4c22df792af288703ba45406f133d53790c1d3a26a2bf6974ae1f2781322551d7986b1e72e488e046d0a7f86471ca4761d6fadee983cc9ee51b3b87c1ab4515dfbd1e646484d62069af9d9dc03016edd703215056cbec58cbe345694d099ab369b492411d416675c8646b898ae36f6abdc0c3903682b664303e07fea2a6d68d88b28bde2a6882e5f9177bf211f6ec650a59fd7a3efbaad71a5f2ae53d7c43ebb199ff9097ce83d99195b755c3007e4d0d595659379fdd81dee9e91c1f17804ce55dba105f6a5add37adc0f49550f43458c30905860912b65329d0f328c165b06a02ef1cd5ffa1b09df111b03e7cd25a1f7509544f59e99677092887afb0c9e90615d49780cc13cd6497718f3a227404c4fb3c002289f2b52034af18250a2a33c635761d14f4855490fe32d3ce269d2f0c24e4be5a3f1dfb1b74c292cb896a56ba2dac99b97bfe50996844f4737323a9e217ece6236164222b03f5b58476c877524f389e94c44740c78d50d289665f35744f6749c2dcca49d372642fcd39ec87d5e9caa8215559885f93819dab9e57bd79d276b6bb01332b9a55e421b709e1d76e513f5888531eae3b04c00d0a34600637be4de3b8f7273378006c80ff8245b7256b98f44002a10b29311a27c7f1d4484e04ecd8d5e42b7c311980d6ed909f997eaf3ea40773ddcfd403c041f5f7311de42e6dde93d4a7e034eccc2e271ca01acf7e327d6a8668f0062c652047f750360de136d44cd631609a84f2501b93c4e35eb51fbaeb72bb576fe419e081a85bb1d7cb5ca5107b8f6e6179ce2e27f42dde48d44bda64a3ce83342fa439e8773dee101d453f1f7a63aaae4137fe79e740f327934149ea988e61e3b10144eeb232da7da48b37266929645144f230826c9ef947bfe9739566315035450f8aa0ba2c657941e9d41eaf349b89b27302b48d79bb0fa01d95fde1aeb8383996b815ce42e2525ecd779b75bc964a077df0d8426c4eb1dc7fd31e8e98ec110b353e651adf8eb75c8d801fd2664be5173e285fc042a63ba2df5242c3ac546fb084ae41663d915378457000776585541d4f9f698e862d31602d27bfb0e2e9cb983e057318bacbf909d7d7ad35aeaba409f8006cb22a98d12f4d061c36a2f7e40fcf3f1853b10ac17be968197af010ad6a023505bd1ddf0dd8c34d4fd70f207b10fe95bf00c119a221b70bca0b6e070a4e5516cf6390dadf4f832282a755639158d89519cfa1f947cb9c70f11248bb0a9fa2c832962cc25ffcf3b139b452557b9750cbcb4bdd52db20478f90fa593ffd189fbced97825f1c3436830c7c8a35601272c170a8c55a41c3c406d3ae025ae4904eca6b01cbae512c62f38e0a9d25c73a4cb0b4a86a62f32857767377c9df2253fc954bb11e975ad4a6533a02415c0d2c6e6803d2d2da3d30556530113cc5d5a6920556e4e8a9555421a19b0f059e410a7326f51dfe6783bcbe0c25f98ecad3e4520e6269edf621790e89f06bb3299e777ef77f0b8df1b135708805a2fc4ffbc248b4f731a53a24c7b122e292ec44b2cf0b5c371bf85e5efa4189aee06e8be02d71c91445c7bc517949db380a36318fb3e3e27b37149d51e1944208f21b3425803478eb595dd6e9a034d6edc2f8dc18262ae5c506043527fd2383e0933af60636ddf8c6288965cfca5749e928e01f9b5b4c88cd29ef54eda08f43c73d19c5d5222b4759a420ced30656756d0fc05df412efb1558d6d5190e1d62794575cb120d554de749e974da05100995f71aacd38de4d7736ebc952fb15898452649d0090f936721d0858440d52f89c7864c983b1aa0017ad413f6afcfbfcee6f8c67106a51a3c6c5ba574484e951a7d047c71ada06b5b97e9856376dc3921393b63ad876436fa9ea0566ea0cf9b274449a7c5e4b75502283667f000ff770102894bf61400cb2a2df23a7a62fea926d6f52a43c594a5d3a9b29a1dc6ea5c895ac135b53a821c2f296a243245def016c98bdc83273a0dd4225faa8281f4405a808969edd422d9ec3fcdb67a7f19d9b38d3486fd9b3d7b86ad413d35c13f7bdc2980b2efd0588c85cb4a281c9cdc0ab5214ce63f6c4779cd74ab2b64c4995c3b6cef18322974adabb94638e2852914126f3ca8be8d9a85e5f1d63756dac201b39d4de46a739f5c0107d55e61807c010e7088760ff73c8938254517a07b0dfb9b7cec67a506a9775afddc9129677c3a863016699f1c549a507011b71ce9515392c9913b3a53267677a9dba2a13e793965cd8b470bd86c76891bb5026934448276d093973b3ae27f93f53780c458a02b3bfd598879511a2811e3540fba84db9d6226c1ab2d76c72a8e8dbde838209dd16fdf662431a19c89742af6987ae3a5cac94883405886528497bf99565a083964a0334614e226a6d68378856325c53beaac18bad58b1e5db41353237e377df0627efff9fbb09a89682e634ba33a7311d3e7a1f6b02396dc83478f2353b9a59d71f9edf40194bce797649b5b82d2152e0e0a079e561960d98325ef3040043e076e34a7dddfc52df6e6e29af1b5fcafb6fead68538c7503858e8e601adf5e53646927280712ba0fbfef08d78c3e8d03e6b2765c274d8c763ab89703a86612e7401969e7aee2fb9e568118b0ab3889ec3855ad0f7482282c7d7cbbcadbf6f56e25794c1001280a8dd736c438a40698ada1707153485651a757152bb6130b403a2e3dfd1445ea39df588ea87142595d6e602514538d56b5ac2957099273a86694f478a2b6fc4d80d83b3e743643c677e86df9a13550bc21afa3bcbaf558804558d10d3d6d044ff8995b4cf095e359698b4545cb025065c69065cdd171f4363a6f34d6b24bc0b2c2e3cf422dc4bd9f56ebf7c605c423335260d1d0878264d64c817e4a29487f449997da25131bbf66ab360064a691c9c31e8ea391f9ece405b16ef8c75a94163cc501bd14cf403d50b17ccd86bf140de0b6cf208763aa6f9864ba50e82839d3340d3eb832186e0d5fc61fbb708eda7312d54ed121557a27267f911f339fee6d77b3dec9df7df56dea817736c095b7ccc14cf8c2d61e85220fc1cbea80b6fe0539187892c01f1480c592294b52de58fe4efa82115a7613f70b21a6443da123f527de267f857e3c0957006417226333078f75e74071edeea41d5924ba50476dc7a5c09ac9bdf11fcfce1171e792ad178228ae3dceb5b3509f177c51694f00ca4f986c79ce8f412b56b4420869fc4e47405c76f33610677f3cc5bb93f61787a125ced34a96f50636ab0b341e95c95a63042490dabaf2593c678f9c90f9bb75187658a44017a69c3efb8d4265ca02e1aa05ab75ab1c18e2e65a0293d3067e57676f7c2f07c971d903e7bcaef68a96d222fb4972d264af2aa130ebdc502e167621a6d13b579aad152a2cde02005865a3dcf5e0ce1776d8690602b80a93b44932686dfc452a20386bc290b10e8d53fc5dafaedfb67b36933084f2b28e6958a1df2e783042054e00ab58b93f0ac50113ba78b9e561d310a35221598e56f57593903d931f650ec97fc878d03520667eb8132809de1e11f031d51ac9a3f0636db630042be8742ed56128c2f6d0f322d8681480bc44be350418c4d9fb07b765620fa066318f86adbf19e45db6ef0dc44b20e67c53272b0295e61603021c7f1e579723ac3b35d318f4ef33a397f4fe2159f4ba13e6a5ec1b3bd1bee750550a114ddd6b1ea030e11b95330738af6e2b0c933f67ebba58b164a33e2e9b900ac016a4f1fac1055c6f4dffd9d3a7f1ee753d563c21e7585c1c884ac6883d4e37eb11945e58f867e3774f0595476f9301a0e81f4d459e484746641ee729c84312c27828819933fe8e00f7c9f250d87c59175786ba6656197603501db74c1ad81d63ecb1972c954807bd30b5a99807f9a79f730bf8ea49fa6dbb0266d5b87de1bf07305627c2058466a7ced0503045171d2d18a70c50293e1751ba4f2b10fa02102d57dec74dc13423854b59215efd8aacbdc0ce88c8e4b22c92c151cb5f258a4705a8e235702c0e8e562a3aec1a2685312882c3b5ab4a9e8943dd4049b1576f30551ab48a3a086cc08e68067b4dc1afbb74faa320d07574d7ac08f178bc90bbcbab62f29c47ee1a63d58ee14432222d207c0213a20d65e22ad5983b521301f78dfce9fd1b722458620d9c07f2f7ae1b2a50ba157012fcccf6a3f71315a6282076c1fce1986ac7a8a670b1777de1e95806d596ef930e03de7a029182685f4a370c67cd46ef55938053988e0640e08694b13aa466797f8b312bd9f81e7ea9fab88e818fb51067fce0c24bf3fee5fcab5d101c8219a368e27d42f94e76500f221fa69759625363fd07132764dca876be4646ef493cc09e2c6e4abcc125762dc4d1fc27566b16161a50c7709a35ac06e22cf947fe46e285d5dba4c26737e000d971d6707178d42cc33185f6d91c06862245050ee5b9e64ed1bd5fb73b2362e1ac56e325f2286bfa6c8528de7b03e3a74160790bc5c2a440249cd45c29e53d17a8a5d72610304862341d50cdf0759e76f4e421e4e4f4439cbb55a6bb5b9b7a1483d5657360de50812149cbea246321de4418c39f981c68baefa7a4553a1e87922036b47c42210648ea20c792ec026e246502d453dcdea5e6e688334b36c63db5fe25dac8daaf3984bcd780d32d089b82bc97480406092ef85efdac9d7424e84d98d403ab387274d31616dd83b9795d5d82f2c9eb312b009d85d14f7bd0bcb2fbc88f2abaa245ff896b1bf7fe7de89b25c7a7ab0b411356f8979bfd4b3eeb1c905d681a19907a202c2a29a0ae7141ff139f3e7509b8a0afcf5127b3cacd304776bf54aa2f74267c808dd628d51665d50ad3ecfcede088bdda8ceae8105f5959750ddb72e77c5179f8eebd1fbe576d6444135cd229270c0c460687f6129459a6a65935acaec050ea02410163b19608699d1dba960ecc6802b223c575daac480a528deb1ded50591caba94aa1674b632b8df27b138601361e5596feb212b4f25258392392c945a4cd7a294da434e43cc00cf081ee5f626ae17dc3b1dc305d39210fece8bdf389f3b310f15c335008126a33f6fab3c170b6faa587b66a9feb91355467459298307907cd7fbd258d48e4e2ca2416575ba7e60d472519c2924b900f04772a1a7ca452da235cbecd98b912e52967ac1f7971bc5a6c17e6dfb5c9a19cfc74380a243d0a651540893c266b475b5d116012c1dfa94b382c0f032a44d202c4e309d9acc922f1fb0b10b867e66fb830994d2fbf63c359414478186844508de286eb4baf69b069828df3314f451785f87770ebc6fc20c1339c48d3d31fcf5b807ff3ebd97419cd09f061c227f5d0b72889f77e168cea269a3ca62ee3ed6fc389ad11db6ecbfa7459ef259f6a7cb99e3ca0209ca3421c7e5b4260e33bec4a33b6cc15f77e0c0fe17e9e007fdcf3fd8cc1a6e5e34b99b4aafb5018134e850bdc0296816776f6357b0471517ab9d8ef2a5878a9b302c2e2edf6e38691f4b52511e0f7f9dbffc74fdb14c8ceb53ddd9422cb18f492acc4acba1158a0dc083f0f90589e14f3cf06bcc2de15bf5197b0fca2c50383f99b0078a99f38a2284f333eaade7d6c3ad91eae13a71c6e2da55c18915a32e5412a270014371ebe07b7aa0bae07676d57187e89edc27d51c4e371a4d58204686d16a68ece7dd19c185a05e60a4c4a49ad3510f0901a3582cfbed2bf7598c43353b5aa01bf9441d5517d76199d9a586251429d6d758e63206dad64755819e7e094ce8b3fd307bc231783e709a1ecb001c8195ee086e51e2b99cc80d10066afa2b9149b3bb0884d42c30af1a3a02dc0cd8d6a9d46c25815feb738c1e99719687f90598e76a1ad609cf37eb706b26421b9733d0c30b3c96e980447fa471b6cfc02b544a5653382f91fa7e64a85d7579b7da9c1b66f4a2d8e4bac740084a939b22504a340dee667ee75f0e7ec84e24f573bd3ea38ddd5d13c914ebfee726a6fb32f49508d3d22a7895231c3c921506463b06d1ce89d01b2052d04cb9e4e1d841afaa52b160109b5f6c50181be539f02abab503c589248f71d6ef63507a033922c57520ca924f1073c68e3f209dd9fead56cc43fc03c40e4bc77efc0d18b4adf5223db1e19c7549f68126d4eb951f05cd8436b594f96193c2281a23d41ce317e9ec33be1a480a1409120a0d73425e97af6ea6a6b8f52a8f8c3492cf5a5892e10e9e4045f383014ffe54d65faf903542dea47614d3a28e339b1a684cc0bb05ea89bafa7387b4344296ac3a8d70212549ee93803d9744a455e0aeff9da86d4f1aa307fe3146f2bc44af8fdab371d21149e0338b88323bbf0308fa4ac81947b0912a2cd3b4c6f19a849002f8dac585578759abccb09ac747e0a57a413c2110f4afbd0486db5e8561eb87d852a2d8e23f5906774d30b7b07d31b928cd7d1e8d33beba785c9122b796913130970ddcfbe43085d6bd341b0c1ef1c98ae41c042ed8b3c4cd184eb3cd2de750a2cd5886ddea81191361cd1a0caf0e11e0b5b51a7a1b56d6c966a9d4812862ba34afd195e09ec59f181308e68e4c69465f747bc5a7f750632462c24065af139c3179b0307a7971603f433c6cd729265f3cfc2efa2bd2cdb81840156843c1146d09a773c2f8a46fd14071afede032d5eeea98979c5a7e62526f4fdb3612b16b2f9c21c47f16c4c1c6ae333ed389db5fd929e85950a140c3b81636b801897f40665ef64cd7ea65d45b2645e698671492dcb4dc1a8e2533f156e46eae71bacba1b30a1e0b470d9094377dc4b704feb94bf3c6164287efa23c93a67ab24b0edb07f431b3333dad0f419547fb8cb4180950dea11bf46ce453683b85216ab87b31dc611bc689a07054cf1ef9b0794687df0a96775b1c5b7980fff6b698892505424cae70947eb3e19e9087a47b0816ddd19709ffc22a704b3b6d15e40006a371b0b4828cb8788f6599d7534c1be8d105d68581c45ac609394422a55978c4e722c87b9a71807a8dcab77eaa973e9be381757469d519450a0346f3ebdbaf70b81ac5340bd8a8bdafe94dee65e0ccd4dfa706936329a33a3bad859e371ded566ccc6233cba61ea9fdf6fb64c2122667627db9a31de9f8dedab1ddeff78f7868072acdc4c73f4b20d30a5946b98eda79f090015a227a137fca229eac641390f74fe8039b98f2c4c63edc6935ecbb5102aa1d5084fd91ff622678f1fcd7f93ae2578bf7b127136c9feeafd35fa8c67f782594e40bc3a6ffae3414ed9353a77d6ee3ecee7fe9fda7febf75f317386bab25fee0085e37e4b2e57e71291fa4612e250b9d0ba2ce4f38027ba7eb60540b58333b295c0e1426aad2ca3bf19869512843ce3022ade16e7be86d840e69bf86b4ec815408af8c41b1e9d65e17a7c2078516e1faa55241859926ce9f68063d77e3aa3bcab9722a18893178222daf3e28aa8fd1de5c030c6110e987ce9114dc7f5236318dfc09418ab91a752ad213e91579e8c91edf81c2f29840d0bfdf9bb8767610f1464498330f1e0edcef9e50011f3d82c9befda2d785b090532895b4a1c2ced3f6fe5abd39d2d8b955ac8e55590130a9d266a46d8b11ae4b96a215d6b62291bc517e1fadc8ccfcc0548e74db302f6b9bd89f123bc3a2647c48f7bba01cfde144ae091629bad444287eddc7174cf4d544f1bc84ad029d3eda887fde76cf28e2b8fc8b34dbacaaf0eb57339eb8318e91279cfe23163b100e601a4866b1d284c5085aecd84b8d81ea550248bf36b77775af4ce355f4f45699502dafbd956e903a8f1fd9f7ac5a79f9ea7f1b09cb118f18dfc851bbb245d46f57a6d26e9bd70af59b6711f1a37575478911986e330bf98effbe4d6d35f3800192d9e97b1d61c6279bfdeefd98b4b3d50284581d3e710a76d93a8e89c17207c4a8cd55f84ea78fb0fc689db35618498974a5dbaf0d0c80b0d55cb0e3099946ab9601bc5683740c862d89b29e9a0a9a85cb04178734690efc6bac3e28642f7b39b4182a6a9d689dc0a2b54fb6c0dfb8cc3901a6e521859d880dc8cb8b97be711404138f5687d5fddb57ca9d962f6019734fa9fd9f9481a652ea0a997152de4400e6ff9f93bf09ad3ac72bb9f1d84e9926bb7507846ede60b3d537e9d68722feb7fbcd86029ffde09acd7618579c3220da4e9f1a9bef94c5fbb96deb36b8441f44e4f3643c0909e3846d091dd582b3ddde6e4642bfd0a7f4026553049b09201641cdd0e021c5e73a4ccf3b5f45549ee87337434fd2b3bf216326d8d079f135d1c8ec7c4e0538ede7c603f4bd4c9ffb51f3c748b4e9f3e09205da7130b68f1641eaf3043951a69faa2173fee40d1973e71a0222a170f25f911c7edf7e574daddf301151ef6bda56469f508008d06f4a460107a7e8d8021c6933e5d13446a0074024794e1bc92cdebf6a9b5414a79a54d68d75fb76c471eb9815a7d1e549aa82922713dbf003ef57332f52062db39c44ed5795d10cf64240272499a6a3da0481ebea330692fac1b5dcafe41391d2b9d47739a0b0ef1a5cd47dd7347a160835798bdbe984c4ae356ecc4e187e6771064a9728cf106104aa1e2525735a0349c5ef731569720e3054503a82ac35cc9237985bb8f0f84a3e4e8844fbe9e88bab6089b27971147a8fc755f08d6d9b078ced7dc0740ef49428a80a4732a3127f532a8e1b4f4f2fb330a009b24eb27a059bd397699dea5ee94684ef040e0cd6edfdc3096865fa68259f82317d9bbb5c612a7b2ed1dce1c8daa9e80e5101d523bc4519314524d02705e7c0d7223eb0d8012fecb62eda2c650b0b304f0cb9387f218b8b829f8fb972c663e06689ad506294667af118117fbfef403b073bd68df33a3e5523c39c66594f86c7fec8940c48e69ac01d273d2a3e68a11b9b463172a954c4524da9af1fe51085a24be0b34bda90b8b3c53bcf2bcc872c5aac2038bd375725b49be6a86f1fac7d6ad71ac66673b88926451c5997b95068a21956858152b3f2feceea844bf5727dc9808561c5db2aacba01bbf8d712be937169f45406f3031049d112f2f6479c34a8ad51cf38e3de5d83e43ec9e402cfe8591aad61a557de25964a0624392ece1b214419a9513fbaa86874d250567662198602dab8fea34f07bd2053df78ba425fe3b4bf1067af42866cf33188714307acefffb14dd769f039ecd0f24854a04790d56f9d6cc198d16a0b269668fd6defe01270b536719c1738447e56ed6c1ca84ec0b41bb0fc01ffeab1d8aae20ce9d3a2a5e55f030ad07a2694c58cf8538f9939fdd0b63499eb3025409f0fe11a235ef82973a59ea7d616e706ac02d4d1e13975c00bbd4e6d53d3bda575b900d4609a2c38dff8b80a297113d8b577fdc93642041d07ac37cb76391a649b4ad890d38a16b4c82e5a2582f39e50d3b166326ccabb58e1871abd661738a6ecea4e1dd8f454447c93d1071668d61b8f230138149912cb0c1cc991c22677323766ab07279d9ca6171e8c038f185dca594c88bb3dd561287e7401f099d2e5afa593ba19f246bfc5169e7bf53a555362da40fbb85fed2e8da9f2882211c5b59f33e6bac325ba86b4bb7b38e8ece1b29312c0f95067df04dde143d7be695b33b102395b71a5803f26100d3af3e9a7773365c431e044f9494b80e75c42bfa7b9ee4acd621035b59298e1a065f8df0c9aa43c4076f90a5964453e4a0aa40e45d64d1b73d13a123d73af4baa120747dc7a936e26f361c9fd6b820e9b22143b7ce5aa354df936612ddec2a2b6240ee11760f016dd4417618a9bc55b807664ee7c1c3690031a9a2998eee120f0de4f0d9646a525047863742112e0f9c916ba81af0de5500be093234eb4d948fdfa79dcbe76ee99e62a2ced5e500b97612245da030f82f4b67c9dac1e779339e1cb28d11cf6f0d82973a2b867d9e0b6af9fc88a32531da126e944039df7d5fc8e61085cd709063f871cc373e36a2409f4f59c0ddb44aa6e383d814b1d6ede19d9e120d61a2f93a2df1e93ba0ea150a25aa3b4f6d2f6a0977818b02b72525bba66b5e45992590570697b0d71ddb4fd710f9deea77ac1bd629047b51d3d738227854f825662d693dc1ab2a5e1232f568d5b8db333602e4f205c320a28a569cde74bb7e717d21a0f89112549115e67b94809e1d1ae05ad7d94d1a6006142ebab9b9507fe10110c483d0a6fdb62bf06c0088aaf050daf87839f73104a74e118e97b75a740aa9c0ba87bec7183fc3bae3b99ea9c1902a1b414a24cf742c453f00027ec59e85f6b96a15b7fb48dbd250417b67dea799bd0532856ad1a89f66cd9cc1880688d0a2df52c17ffe2b7f78b67c8864529d41b719501d614855f4c202d7533259fa39e6b9e838c904069263b2710fb300dd36447ba48a9d5105fe29972d83e280a3ef986ca7008701547f68e9afbd5c5311076b2a805a373e400a448609c532fee7066216800fd104b3843871251fd3de51d3607ee37fd56703b7c4b4b65f4c9a4c2689fa2587919fa2ebfd75552377b7813139e3675b87197974fb2319c311837ea77cd9acbd080b93065c28d2d8772fa6ad570e1c54def9066db091cf9d65fefd88b0054711dd739e9e881b8bbab6a4c8852b9ea70281b634065dd84f2a8e0cfba816c37498131b65a3753c9af5390f483ca63435bf4814affc38c22a5377f687944e6a98be0ec21afd7bd3688fa63caf13ae4341a3ed7bd5cc5c03a56d57fc91ad42b77aee3ef279b91c7946d53d582b879709265caa16b9c750884d472fdbbdf294f6865cfaa3937fe3cdc332748ea3c0792d5d8abdbd1cdec4a75ee9aba282298c078b9c3c575ad2bafd504f4516007f42919d67c7b184b9bfe7bd34aceb3127b5702bd248c5a333a222e1ce1b512a5dfbf568f5904c4805690c665d0adb889f79fdc25d5fc4e698663d3fae1e16c8c91789f63520b768bf490c924999d326a351663b73218286c3a3a8b7d2ec52e37f258eb4084afb042479f12b3e50d4da19dee436b817a1e6c0578579b3e82fe3480776f1730c671ae7e5f07aaa92133dd1c0f0f1c2b4fb887e9b2ef43a90a8222884b52a718386733a692294ec00dfbc1b87fa594d5b327d7d57ad314c3165d99be1eef3a6e539bc98f362c04c8757b89b82e0d4b3495e75247628856d804df00bcad59cff496d880053be61df5e33ba6e36ab857646361031985e1f8a1e35ac4cbb55ac7489979c34280be5cbbf86a7c9b0182c993443f527641ba8eb9133cc92d02657eef53108d778b1127e4964a4ac0ed5d593aae4fc660a472ff70212dba35a7afd830aecb515be4fb61fc66c83d8dbbbe3ceddb64165beead9b7563870c8892536b55eef07e3ae8117d36df196f730ddbc6c45351906eb515593a331e85a41e2f89e7b1c0da882d1a1a667f04cbd8b2429cff6aff1445cc652f2e58fe74fffec18ebcfa21cca353f28679a96eb1beb845142b18def1e72b4b343ad2552775a2ccd396121d5cd39aabe13024f10e80896f98a2affacd8b671a6c4baa29deb8b7c82c114d31fd229ea6a6a725d9d8a27f177b74bb4f77dbfd19ef9ff31b00a8a72611f2c57edb436c14e22a191142de53588e1095eb86ca8d5ba84aa356a8e9663e7fcabb4ac96b7549922f087275a6a0d807d5026ea007b93530d3261c85860dc62399e18c7ce00a3485015c88d0763548ea2357a19264dd23f320c81b61a40dc64464174b79a6a418e8189693985b9b2b307ce64eaa98a1011e07430dfa09ea691a8223cae61cd63ae5e980ba4209143da9f2f77ed5b9d0a37114530009b3df40fa93dc9eb26240815632a0bad1326cdec65831635d182bc999120f3ede3e2272d0b6b6ef5053fc80ce3e5223eef47a4de0d8b2232e0e442e2b0c85ca3e3249d59adb9b36063228dd8e9ff5d74bd65bc25abf44926aea959bce0cb26fa20d3cda80546322f934586500d1865e100c31801ae231b4f2110966783b0086166a5558f66b0f8d7dd2db626f79f578fa560591443d44b236e3da07e18422ed2799888d0dd4a6c6c2fab9778c0cc4e529568add2a969032a09312141356a91aac5c4cdba6e0c39a7d13e26f9540a956125fcc848aee2f6ce3efb7af371e577b095906555442e68730e4832a1eb3fc4009e0a90599a23158cab091bcfff3dbfb7afc80527b989bae02fcd1da81442b71ee8d8f394acc47b8b10446b6f2c9d93d2e548366bb96997925995a1236972d3c24e924ed24fdb518359830e93b92182d522c392f7b38d36cf5acc1da64a68981a2466211f1c3e5e220a33c30b02cd7228122640e284cc8521fe3cca7508d34271f3de77aea821f12221881cfe1e11f0f3c7364105c9d8a1f7b1ea9b1f0d4e2d0c454216cb63aed7abd805d1c5c043cafc3a19cbdb2ef4fe267e33e4054c18dd78457428b0973f86e0d4119be0766b2d2b57c29033900c81b340aeb7b217c115e8fabbc9696a7a501bf94d0016eb750da1d43ca2ea5b293601b30c1a9245568e28c7b94eb692c02c41335079ea6b5a562efdd00a4c7a05aba83bd02ded250fb82b40b7c7a6558f62a6a05028496fb1fbda3aba4a8724242d3c1409d37d4c619d3bb1fadbb871bd7c8dc13b0e791d5c1e5e719201caadb8b76b92d459a034a86945b3061a42111635072a123e04f00af4ccc5023c51a54884ec255e512e0ba5fe1f30902d52d9e685f28e5662ec5addf2d030d663e8bf65a32a675e2f6e49f11f1408398273d37617440f8ace349c75d20f027dbe7d1ea40132c9be11398db8acab80119ed85d485cc3d3d1b0bda4017e8619984cac79f6e46f23c50c8f962c7d0376c292427a8dea20b0b30382a92192f8e1c84662907adbe73b2fa79250495f8639411d251663b64bdf9f0f008c98a25f5c9c5166fdde37b10a9ac6d732c7b57cf099ae2ab03f488d91aba6921cd6e2ed76535c9af4a7ec5f23ce7f49f3bf92e07f41b941f8f2ad1129d954f46725a0d8bfef27f005e34973f58b2c4bf7f4d5f866c79a5603521093e9af82d0939d25f70ac8ccf0ab4452409a20bbfb71a98c6d453327c2663d32778488c3ceab69bc17536293ed311257cf9f0d1c559e77f6b3322548a41e9e9e8277e587e8535367598a9cda6ddb4c9f03bffe63a9e20a8bb81db4da99b4d7756731961c506ee6a24120601cbc1f31e0901045af7fa478a6987608f0cb5809eb365d8820949013f1a6d5d2b84a86a5520d594c7f1d4f4b767b24325c7ebc9b4e90eb456ba898ecd046963026a767bbf590043ad4939a64edbc0be313d92de8925f4a68a7410ede0e25f01e166e6e5bd9666053834933fb0736dc9396b97769ea65d75299a6159f1df68023c7710c33ee6a61d53c4d8023c527c1415ab98fc513dcdaf1cdd1e20dc6cc4458fb58d1f7bc865049294e52cbf22975738eb9e36568728453b93f7e640d68baf2f7823ca03013d6ee5148e635c95739aa3b05ba2d95d4bbc0fb160e37c5fb02128f10d2426253b43fcb72937e7c4c48ffad27d4c5fa1c4185932ed17934dc39638e683f5b12ce145295829def6f90aae874f4e7b17566916c3805e09e73091261325c6327348cab0a9dc2f53614db16a058b748ecc343a0439cbe3daa4e82f97c343bd854806371b4e37f4d25d7b6823288f40d056c6cc74cf124470fb4d76c6516cba2b07f8e130863028ed9218c50029039c33e06f6745390d99894cecd60d7695bb384470ef294014efe19216dd622dbf6f3b3e2ec5b2613b80af95e10c5c8969db43ec7f67d6eaa6720a11c82f4755193d3a00e584c529b58296bc4d5088a9c091d4d01d1969ea2c198930aefeb5a17fd8b158b176db86a960684ad1ef695a420f667ff354ce3ce91eed04b8109a0a428ba6a478b2e48cb0270f444d25b4a52f08a0e9801133118f03f8ab6fb170102d624c3ccecc797de338149ad79b23c955d1a3c5e581481e3758cb4fa171ffc692c1e86fa2349a94b887dc4b502659b686d325b257ee6cbd0d8fba0dfd7aad85925b4657ad7fea4faedc7d0bf0af90c6241ec87df4f19491087484446c95a548992d15d8f59ecbaa8d7d4384117a4d013be853ff404c5befdd270239b1373bd0d8fffda3130db0fdb70d5e404430539b6ca1e9aa0eb1731a5b56e49e54285dafff4142bd947c75b13659d41121b1eddaf319b35c541a87e41aaba24a82322bd9b43542083f9efa72a631499c29abe9ed4fec68991f569e84c34d0d9dacb093f11f18f188ab9d0470eff3ceca2f03fde8ea3734bd7db899840070214b27b2c62330a2bc033d6d11a822b4538dd8405bc2ad2c4a0c70b4673d1a6640f9aa4ddb41056ee0c1af5c537042dc850f6e45a68c558af2ecb9453188d58eead8fce1601c0121e2f70663e97fe0f0c1c73d7208d35ba36670a4203588d65cc3607362b851c066b339b018b7cfcf39a91f47a2dd50985a92a1c51153db0e8b2064f24b511bf8452ab3e62d9a9225a32f8552ad329cfe4bd57c850204ee48c36a2e5d2daf6362a255ab6175d305fef26352d9853a8825798f46464e4e0d1785337178db2613b2a3c62c4ecf2e55c010ca064512a75ade7387631fbe9c40d272f8638c023f50e80f1476091ce441fb050a9c7b6850b2e19761931f692859d6fa2056edc7e0386ce92f9b82ab04182bd29b66c160bc5bef432c081b7358f03015bdd399c6ff5804937806887ae6f582ca1124e0c692e2cf6a0a0b74404c751cc18d3a49395a8a5a26d555da031a5e0578c0d5c4cd4631cb028ef6253d5c806d5a94b80f87d93d630af18480cbeb1de07d2f7fcd704d7581b8ad62aabc48bc3d056e78a35052dbf35bc318803405e47e01bfd15007b1ece88a55c6f03cb76a7d050e4ead6b2e8c2ed8e67a61b40e5bd48a9f459da0d1ae026b9cc512b0aad28168c3fa1301f0dbbbea63acb052c39ef6e20e7ac8829b254d0482a3a06dfd3ad70ad8780f4cb6193ee4d5f91212d5afdfd06a1ab91942b5d4123a85eb21c8df607ffb1d777f87cf7e9b40a1d112e1c36cb1af724e4fed4a372ce458228239d9fd4a627a4e828b65f4fde2a189240af4bd75eb4710e7a4d0107c58710a74e8712649f860e8f006b53cbf52a17d36e06bb5ccfcd528681878c2ad3364da0e3fabb77307cb90547ece99458ada3eb24fbc54f17440d6eceeffb7c84f5e4da5c6c6d4698219c104d589b97e641e8a36618b81b33828d1e366769d6158877f6f32194968adc331fea773724cc3da573f07fdcb27362188a98cf5a4476b937c81145186b1425dc475db7ab9458501ff92454c6985ec01d812d2b68a77f086acee2eabaf23bee0c0bbeec387033452d24dbd27768ac4e0748bb55d486b0cb89791be28ef8fab327d67a2123c6cfb3a7d8d6bc20c2c1ace58a32763037d142bc1350b3bb2ca170d5cbce7380bae403b55629164db8035fcf06f282e6ef021465f0dafeec327069c705c131a1d3f46d877c28b61ba3c91689ec6ff5dd83ac61eb547cc8bfbdcca82fe8bdf6ac481fa6771a352cff8a9284d4ec6909e2e8df910bfae6221d2ae272c069db470a6c0dab9067db6a0ffd9aefaa12111194897d7742c1d138bcd39a3e277ad339a4eb6576308f8e892b1bb3035ff463496a984f9855b6ffaa99eac94cb79e3acdcc875422b3769423f7105443854ac18608fb0678242f903fcdf073ccfdc8a46c4a459e7241587304e82b13dd78c35cc730163b5840c7bcdb9f909cd0d416fea0b78ed08350041c16d7f25f007818ee75a1758814595392e16d7abf77dc473e4400a466473c6b80dc77e9fb6ca3fcc8d51f8befe76b941f9927c4a33771a9325ecc65b24005fe86efb665071f3036bc2b8d8aff9686570a3bbe15ebf911bd38ec360cbfbf0b7192762df98ca254d68fc6ca6539180434dcf22bf4c48c15b541000ea23470f09adc20f05630c0905630c208c03f7b06d604c14471f2602e90155b6482656c2f7d366bafc0c35dd724deb0db526e616332af0017373a77ea3cf0f631017de385c41eac043179d5335063a87081a23f214305990799792edd3e4a5e2fd7821f9006a1ce3a13129f01cf857fc0317802bab796531fe14cd47ab028d0f05c220bcbc5f769c8aea31d09e8569aafbc2736e48a85310d4b7d3dda8161384ca07f51e3e471e2d1394527e58da22fa08a9abb5eb359e4268264259d77bfdc25b78aa979cff3a8af8b89d1340cae851e1bfd8e683ed111a39341bb725e34bddc256642c8135841f8b6335c0bc14c4c28b9446fb7c307142e12758d5f99d9a8daca468647821dceb4f42b1d3ddd8db3593ff5a149f1e08cd44072005ee2573dd59094d9f0eb4c39bdd8f0e0df931d5959f94812b315662981eaf327ba776c73b64fc5321046108eca69aa66e9a32c0505190bcaa523c6af3bba94eb0c56a10474663c2ab910939cd94f68c1cc2c5f81c77792c2a5a5ddfcfe7faa25c6d145d33b401ec38023fb24912b79270b0745c304b97b5ec1ea148df2b52fa6ae993a44e7c6ab4454589457adbac4de8a5ccd01cf483f0bb64c563a0b0ffd4e8c5ffb41434240d5ac5a56d0983cd9c9010e0e81bc6e5c68d8cf340797057464cfc11fcb8f2faceec615ff708c62a49d4597a0bc22e6fc944dede3f825dea9bd69386a9be342faa66fe3ad03ee2e162a4a7122cbd4039c432d4aaa5fa60b525f6fb973598a250c243ea717e625888f7f3ddb9a152cc68a38d4db0d97be5550286c37124105cc908818b57f2cc433bc220c9a1619716349de3d2013e630ba990a328a8bd6c6dbaafa18ed9e8cffadacff04daf8bc59e07e1a5ed0469f19d733f5a0d5cb0c69cdc337179e935d5a3266e7c60d0f20e87ba3d6ac4346af0d4ed541488bad7a287842121b2774cdd66e5bdc03f4e2919943dbd96fb24fa7fca3d4f6a8a2bed34833529cad6192b6fda17cc1fa9e806e91df7ad6cf8fffa0e835818d1cbf2cddfebb3dacab12bbbc0032844a73ef9421ff29d3e7bffe24298184909c0113c4bcfcad6d07a392701c6a4b0f9cb88189041c51764bfd280a5ee507b107995cb66722c71349b0ecb26f87eed592027516c255a8be6e33e0168de7ce1ff3bba1f3b6f3d870e2cbea77165e705e6d30b2ffa43e9f504efaa4a7e327bb53ccbd8c2378a1e359831a8811be29278a897e01265c6f96c09d6cb7ecc3d04cdea89da0da43aadeda283de0ecec51f06cd35fee639b9c1a3553f815003a61bd2f246c4e20e879d5f98e17b859ee31fbff83cb31b2a88ed962e80e76bd657eb59fb7b9f1b1b972d505dfdc7b09325a54f004dc18063c5bbb335bc96bedece552f2f337b97a2b85e7f62c7eb11d13139bec42669ac8aa50e76c7805a6f5acaaa3ec77954bf66756cc31f7a7d0e8184cf82ec8e29bad1ca5940415d638a41b6d3496a6bd3557e62285312dd4aa45fdf95a03f219784ad453f82d521ee5e93cd56a719c79c41bd268e687886865431f2672bf4fefb451da3424e686b7683a74341183b9837e638949bcea8292e1ae666a945b0bb31995149b75f8e2ac8447113e1829370857bfbbf85247a33dba216fd3ef3ca0db0ffd3e7b2bfee35b15bb61105d961f768788f8a3d5936adb3c04193819465f5096c6d34c44954a3936416e7e5004855036a2d894ae02d6299cded49800ba5764c0d8965e691e07b809420cc4be3e1557e678f7a702bf22211ad150822af32b9befb7fb4c07533c8633ec379f59ceba3779b1093f913a001ee3ae7078ae08b8c23bbbe9f605bcd9c3d1c7d33c28fcbe85bb04700507bb5acf274844fab2eabee19c0a85d0a73561bb2043ec8c63bfb226abdebc3aa1681c61c19fea3fcca85be3801133aea1b8fd8a78ea314e0dd4d1f0654349214d61a30b714184b97d179926a541709a46debc15001b57df104d6ac3d8ddefe5fe4b7b8203e593ab6e217fe46667077428d3d04f962c5711beccc93de88edcafa332470d3a4fc1bfa2c83287bc03a264c7c03464a4e60ed20efa86b667690613f24162204468a3c0821eb41387904119db1dff520d6282e98e91f6a48c4bac5564f09bb12a690b591d6488fcf62866cec0d7de271d45a8aa36ffe858cbdb4b6c580de7d6924498b3682b7c2bd827130c6afd614c2612012a90c45a0270c29edc4ca1376f2be35eaa93992f0fd238edf5a5af05adf316bb6e38376f6f90938151a7d7a28b71147ec460ad298ebe1ec963585d9fc30ad3b4a203ae5f38772439edbcb181fca7e2dc2aa58132b3b29322914c8e3ee6959cd9f95560e8625a3b12748819b0c9462a7152fff51c7e77d983faaa9a55cf0c831657516aaf424893f82ba4f22302be7a02617694cd2bd04a4657963bf78e9010c73698cb41048a4258ed1c59ef1a82a047aa933863bcc84e7d7dbb96c3728b73e664209e563de3b2c720c245befd8963ea2fa98e6b494adec809fce707c5cda9dd9d6892d3382f6622d491c80ae03f9cb15df55d995490139819a3dabb74ed29ca7c26e3389a88b7020cb53fe4a4584f509cb40412e7501cc67b21a8822fa0d35a1177b61831517a0070e013513121ba1401d1609e6d631d0d16545072a89412bfb8fcaa2cafe40a3a6997efd999b7eba76f31a79271a7472ecd80bed72fb015992dcb685a8f77ce9ff73b39918c04ff6765e350850767098a1670d6028e72aa45d812dbfdb6fe7bf7aab420a7cf8856fea29b3ebdce8980eaa2d2866e8d8c7936b4ac96b8ec05cbe71e0ec33f0168995b3561726337c0c5090dacc942c3a03d9272bfa92f8cf13b21b05292ac167082f598183028d8b6bf1ba49a2371bebbe75b43ab910310799850928064044f9d38a36fe6c31e2471e86dfae333cef2e46759b3014dbe7ffb2b085f786aa0914133da401b196b159f393996bed09fcceff1258d89b0476e0e34ce9b2a2ff2d31a986060f2458ff07a210790327dd4bfb293eb14e36b78de39dce7dcda5c41930b0ec268235c4d9e933514d9800ddac18cd11be4be765da22781f8d559cf7dabc966722c49e9f55d674cba5bed9735f2f81f4e55abf1a05804ea53ad5dcb3221417ecfe4c67a5145e518492b7a0c332343158e1ae99282e11a8f47e71254e3412dd05df31c602551b011f1219f0ee144dcb478afe897c48bebfe8d755f7e4be36b05d74cdc20d1f8f0fce1bde908c261dcb8a6cfd9b8e00a74e7c42387f2648ea200f66a809310935ee38086669495bb739ac615d646cc78e30c245eeb9fd7b9413f39b4ba86e07dbe4bebc1c94d6b55f4007d08b6655f6c327b522f0b717b69662597c782c5b546713ea92f50878833d6352fb2d23a6a4d288ba495d8bf43eaa489b0f268978a571ce3aea80214481a984314e4e9e9309dce15372481c9853f41c9002a5045b0292a7b481a02e2372fef475388f1a6f67decfae44e35257ce9e6ba87ef611175541a9b2eafcd3a177ff6c2355b2d0566d1c2593e9bf2e585544605ab8e966c563f85f23d4e8b6e76ea4a8d93b749af86546caaeb892a9aca253cd8d2729a983a521f45f252c9300f1288c94bb7a9bfce960835b2b0477fe98b870edcd92e7bbe26a4162320bb9130dff0e9b9adb4f6e8ee0f82541ca8e015e85350aea721e90d032947b84c6be482b3fc10111874c0ca9a2853c061d472f2cfb734e3e1e5113ee44cd69a1c9e5b4cf715d942ae0348a5fa318a8ca032beb1cd6653faec8914af506604e7394d262d082661c5367ae4bc5f63f05ab66b1541b14b4130622ad731499bb6a20292d04c92f8d941e5723e25343fcf81adcca4f0e04b8d49a1fbc327ab5b9e3012b8f43477320a3519e610e24e6ed7104f8e68f4fbad0636c99d40a437af2d927c459614321bd6f1025270668a0a35e6a43432b49ecc2cb993b1ef710fbd3a93688137c3a19a8c4097ba203ee936c9ff10f169e06975422a0b6d074c434af073638080799471bddd8227e71d2be93b0b06848ed47347d4c6a3cb340c42861f994066bcfd2c80042f806d1ba60e1169b161051078f856182d80e4a99f621492e801b9bb83fdb6d41fcb761bfd2402ce12137c56b2b30afb30737307cc190deb863ae4a94b91b63efb3a50db15154215e899f8ac611e24f96d0e49c0dff3527869438591f2b83ec8381df6c2b0dd8968a157ecff387fd4a43e67f588623480efac74ed5345ae280ce85a38c1a61a71b454f577c0d10a9ab9f6007b6abc26106499920207b592be26d7254525e6f4bcd02ea1b81b5783c440113ace3ba46c9a276abc6a28af82d15d219630b491f43a9e4d83021760ba7f3bea3da9671eca182b27b388e7d84d47f5032e0dfee1bd6f2bdb3b763dd672b4328b46df8b75777c0b7b6780fff5fbbf8b9a99246abab4fdb0d7574ce3c49297fd1cbc333b0ea0d7ad7bfeb3a4f6ec39c267608a56467d66fbd6b9fdf8f1d81c03a9ba3b328bc4e15349f4cd97bd2b5a9576cc018c0a64437ab4195f3d240e255714ddef0cc267f4bb061dbd50dd2418686d2100950a332dfe1b4613f9664e88ed4a10c07ba861fa802e02b0d60b04aa2bc9e594634c2cc4221387f1f363103ccc74227f1350a965220fb6bfe148f01ad9bb1155f24f810b399a6c9f2fa41000bc0283ca79675223f7d767b4716d085cb3b9fd0a7da670095023fa4313fb3a31b21ebe1e77c1e1f44f97509914fe1030e5d80cea01795d9b0ebfbd7ee504ae39100b4465db2c9e7f39153aefe759232e6f814872ccb4758e127a5b220b082a194ae51869512a18937123ab74a1c66b628a5223b2e81ead4ec4563cf275cd08d920b6d8994d952c25b889bcc14f920a4de934d5fce367d917b8df28730174802b2fa1e29024c00aa784814c13f2a8fdb88315179192c9b6e61f0e655c26df1a773bb42b949a02eb93454396b4ec25ac47e9e59e9d274b69a817c285fc78756b5600a61bb46d43435628a212816192ab311f5b8500ac1ae02091607392f0d16b52ecec8ea6c37fab4f4f1c2f53abd184ccbdfec871c131a601c83b32795d35fa6cac2afd32c548a3314ce99523e090aa7203ca3badf1583784d31c3a717ca03579880c9bc0a705d51e2594a2ce88fc3899a729bfd3d95a3f0a5b2198193381987581725ba8de3222cdbc4a9913546f78bf6c22f125f7c7cbb12fa1b0df7f3c0390e6d4074a870e4b07ff397e8ae0958fc2a4a4982c8f6438c51158d62521aa8c50f8888d7db0aa6b9867771c109475fa948f9435cb67ad3509c347a0b775dcdbc9f77ae857f2249e49d56d72b8ae78aced2ec84dc9dc8c8d6259b00f74f516a8484f8590995a01215664ab3e59c57d633358457a0bae8fedeb716f9f6e17a908401d90d0b9d41b6cfccc2cc77fa3885fc29c10ef612366f5d8f321a535ae394d590d21aaf442395d008651aaf9cc62ad168a535a6a48628a31191977548d490f3ae47e3e2bf2c51b2d2879e22272190be462ad1988979790d524a039474901dd4404a1a4ce98628e9a1714043946e5853f6fdc3633b7cb043df617b1beb1e9d3fc4da93a03acd7b2fccafa909ffb24206b6254498130c1f36b56a4cdfdf4bc8b51bf961d37bf46d6517bfa659ca63041f1628cf68b0162818f2b56439183b2865da2f412b8a75145f06fb83860618ea678ecf14fe4ce06b6625d85de90923dc4fdf15575ba9a24ba2633735eb1ed1022f655d28e8da26f0819f7b6fe45f3e0a594c42078aa3a7d099064b46c4ac56e6bbb6f4db012ac27c915857e3d6e9047aac38ce5b270411f01ac14c9d252167ae5c66b7781be4cab2072cef11b4cb450ede4a98453fc4c8d41025f615bd382546f9ff8b9d63dbf129cc7dae8e128a372de6445c5204691b36a0d8ac7ed6a7e0323c6caf24f64af7f2fa3a1f4e14f14dd5822e67dfc29c2b6634da5d22e051de737f70d097127479d9e2d5225dcde58f3a83cd06a417e3636eea24c92c5a7af6822cb8b3c4df0831923aee4e55d783a62eedce32c2b7344f32c38b44ab498f70755930d1ec5150aae307601d8b09a86980f5a217b436f1263d53e3276af67c7eaf3f5569b454b2dd7db2f395138b16b79b30fb2fa8c1375919c362f94eccb286c022ef1f6af2875f479595d3bf2bfbef29138f7bd78891344d54638f1d3e127ca0477ec86cd6d99533060d8331b886d686fdaab4f556c3821f4cd78133edcf2fe002527cb0a425e2852ed011f6e0495b2e173633e7672643f78ddf2967729350ea6b6648de9844ce5d3cf5cc952a2dcf89aa8fa25471af86258eed583383714645657865af80c3efa78cfde5a22bc6c9b2de19f72075880718328c8b0a4f065788874ac478fd2f123e01a5e2b7bd511ee85f27d2eeff5ba17ed1b4be105872305848b2e5b3edfd06ef494f7c8556f816f208eeeda6d7d752577bd3a216e59e21e81df54ea7d97629230602a868a28f9e52582b73b04fc79397a087676ff64382a2a715de0c9263fba665e7623e3b073cc45b317f4b68c9c2178500e7409f035ed69a098ba39c08c362bc43f9fc99768190ee9d5d9775a4a244d0b87698208dfb05e4b44387062c5f3731021c6377b1dec8919a054a87d6c2ac2f1e8e0d90283205e9f04dcf35df792744f9990799fe034c7d68f2ae5f008896aab8097c2fd6dd01e01c8dd59a9bdfaf4e87552c8d0b0c85545cf329dfca64624452946cb81e117460e19be7bcd30bb6edbde3e6dfefdc5c20460e9d99576346c9275e52cd137f3919e9b4aa953451030121b0e6c710050361f92f74d9afc956713006493a2cf152b5865ae140cb162e40ca3ff4e4196edef363989442b80ca6094e61f8cccef2852c065e950142a9666e632630be8c671daf0fdb192b15f82c3073f6081cd0aca64e768279becfa17f64309a1434ba7aee8c54adf6ebf930ded6379202def0e25fb86cebdf790e9e39f21e99d0dc0b8105dd961990e1580804b63df2fe4e903c05404b1aea33722a1361944c702077be13722d1f3ae9b9a1991e9921d7eba4aaf5f45a561b7c6dd6871e57620da248cd30ab0f5048ad6d1f6fb80c18a6f9ff0b495d91b5a0119a6c859917c29968619be6990d87fad66b9565a127fb3de5d82c4d591c614ea9e6bca4a40218db85419c86dfa25996b4bfdafe4693105c34208c607b9b855a4ddae686f8fdc532959051f31dbcfd8f1ea5f3db0bebda726c0e95e4b75235de3b61a2a1ee3b1f326a7d35780369858d6f5e63aa933bb211f7b28f0b44b896564c8ce74d83ab0f53f6931b1ca67cd6c243ec552163bed542934e73c3afeec225a363e0d2a3ce5443ac863219a6d29f2589beb1d635e8e47523d1b65822fe853643b3d5f5fcd3c66e059f144416f62affbcfb675d3a559b0f399e3dc3b9bd06350210a950185948ffa6e1d62240474e7c3951813bd13b388f92d3ba6199d00e47494b82257a7d96fb49684f2fca98abf444e70c6b934d2aecc60158a901c5400769435bc6be45b8bad15aa52bc37376b6527a3636c71d7cf6e7d5c52cbb3cc340d08c356a76b447d4271a2fc2c941cce7f9b950fb15f2a7a2175933c6cbd614d8f1c3dab66a72ecf3d5f03fea67dd3892eaddd4b00f981d06454c28fe69abd35d23d93ddf86de0cb56ac7efa302db69d47f72f3af752a72e056f0cf87368ed95693c04b540e5bd5b4718a3d0106426efd6b4d8eb4e03072b1556afe61ef040dd806c4aa4cf844b2834964defb067561ed37d510c301e9fcd7ff252dae6d34849d43b74ef3c5865fd7c5663054398583c1005f59e4b088633c5d42414f3765716f7e793e1c9f1be41df0d1a18cc4cbc4fb5cc2649afb0a4d0f9adca904976d80b5da8984b974f6b4d73ab412c7f9a3f1a4dbeb1ee8f2caf216d7dd40bed41cfd02e9d8bab8b36a9e1ff2ad0d0061509da68dd2bd7581d00b81dcbf1a1203f4f583e39c15abb415c5b281400e270ecf01ff220f3566502746450a6ac06f04c24fda3c2927beac825b2e8f934ac9a30a50fcd2caa02fe44d0a750fb8ab5eaabc32f20c07f600a64dcb0c9f161397a99960454f574efd38dd80e3bc032039464eb321e4032ee8afb1ef78b13f82c192a3f22f96da9088e0272f7f7936634410683d429592e94fd8205bb88e2c7967f5cbc6cea6b139607136e6422de7d4e351e134c2a8a6900890e990289c40007646e5b52fa0c1b79f7c8b0494050ace56de3864823f952a8879ac55e45ec56b3319d89e25200ac9fd8caa502e37fe192ae6dbe66a3b24ff7481953697ef9e1ed1a830a47924bffa9ed91a1aa39aa2923352038a67527ab8b37497ebc30c331aacf79121a36bbb9d7e7b1b94d882264d0baeed78119388c051e85fe438c58d94d1893d4b7ad2e671d706834a3dea546314c6e78f87c3c41d7b0e54b2a01d88c9942224e359e35b7426aab256015e9b736be475673030793d0f913b6eb8e233f856d2525c01ee7ee98b584bc220f292313d530ac910c6494c0ed0ef97bad5df8193aa4292dc14c77080e9203e1aeb7519e99f2e629f7b4abd3ac577e0155aeb71a24295d374381fc4e1678562685e3158d975e131922934b4372ab8c763f8b0210dced5ba901957c00bca7b96b21ad113e81a06565aaaaa00d0d7cb1799948e8783d94cb9c4a28a47cf40ae4e3191e626eccaf591f211056a7e0ab1529879e6a3ffeac4bdc9c04733e29d22d10819036b127a937dd07187ae590838b291a2de579f7b9200cfbb5c496383af0eed4214232519bcb4489c779d906a67d25fc8fc180bd523102c965b1bd982c5691be99188eca9ef576ce7a1c79ff68ac7f2ed127c45d73b28349e7ff1fe1a91358b4db1f7e1f98269c6fb4f2dcba4147c18806a43bd742da4e4498340ef8837b3003ae40bffd776041407e9473b7c49681550b4efff1c0b25ec783ae2aefd4411f691aa2344713be991ca5fd638af2a3b9e5361bef430a17a3fd1a166cd0d3789b46799f27d815b247fe28d6267ce591cc3f6c64c2a6b867d425f1e1e09cab0fe41271c29a6edb7ddaea3ce7a980b4840b68840b6096c527e7a444403ceee018a13282e0125f8b395e52d0fda8e83a327c3e76c38642d4748910c54b82749caaf911669da1fd03ce9d4b54843bce676ef10f758ae853aaa89ecf3f83d61a89ac31fa01148f097f90b0c4f9d7c090731f7f1676554b6f3c2317905d187d9775dd1cf08f46a1eac0f9ca0ccc1f3bc70fb4a4565df5c683cc49bbb8c41e96849a053c3f3dd566f3b9267d15630776cebec652bb9f22063f324308f5724ecedbe8da61a75491b30234c0074ae2835c4317e4fb53b21eceddef3e4d1960e363627cbcbdfaa9cacaa0dd41f2aa945536c213182e9d7c4bebdd6a7c557495c8e2531d4a76b43102a9a7d1b3f0da43c83aac7692ebb013ab4f028f9506c4d71983746dc7b144e72ff3b01cd0f7d80ff68b5e386b6f8aaf02b0c6c6949b54aa35831e4dbb3e94c961683d194e062b9de927cecd70e4190e95260d33574c243d8bb14740d4f9a6d86e5804991f54a73071a3b9650c4050b7870902308496f4ab6c1449c3240d6b43deda0613e578e7044845b0a127d166941407b1810d1212cdaccc8e1816066fba11453dc95858986b028fea8220ec876f968ee26cd1a49f7d07083cd1b73eb368ab5afd5b0c810424640c5cfd6ee6aa3d9229b381bb2ad2f5548cc302adb6a6e9ec8143b6bb6eb4b1e1d5f2d87e23866c78447a4bf54e46548c140c833b55fa2ac476ad37050e41a8fdc529d85692470a7a3911450f31103378e661bfa963d70462f867a0dda7e8a550900c5736b3fa6acd15d12195691140c138bf4a1acf091bc4ca2cd2606d9d6ce499fb11f3740fa68ab4b08332d0222d54e9ffa903e94c998bcc00e47f42161d6ad4f499da42ae2c7b3a02e3275545b1fc5440bef350794ab385a5a5970768430c9f77f346b12e4eeb9c7d028528cbb88f45ba593613a0601f7345eee0317705a8ecc5a8869c4260803370fec4782846f0ae59ddc533e6b1345319de016694f015d7af8f5f6fe150227f92525cf66dd0042be8f4f417c574141f29f8644f34b4a9f1a5110b0efc763ddc2d12ae7896b34ca15df0f5b08ae9e482b78354dd096ae428660c5900e40173ae06de7fe44910b3637caf2dd4c6ae8203fff517100fd1f5a9ddd653baccad776448e8d9560c28d54fe29e71808ea0fc789ca54cfff708ba15fa182ccad4b9221151ea82ffd2867ae14f071134471b076a208404e0d7da84565a644c4433de8a91971b510c851699784512ee6029f1587c67ea14e7b9a9142ecdbdb34102fc2b2e2a7b8d5f8b3a8ead7d9ce1e1804646ed9dc3f74069f31027e1bb4aabe398f0f854692ad22b188dd6d066ed3995db6c4de49bdd55745e497b72943ce0b9c2b698957c390e36352e4fc406e9ce703476b67fc05609e1cfeb408ba1c29c27fe71865e715a2f9f030b6efb83467bc2f2d4f5fee67ed066923a053b49a49db39c7bd7571221bb9daf6c1719111e6b29d6dbf26adc22ec4ab3c753dec6fec04fb51c67340744abe930445cdc02ac2d52c5c8f726e7a1a8dc1e7e2c26ebbaa089a69c27f83edc8d656c8136a11adbbb33596c41cc8d44b3be516875784864ba678ee66f307a64b447710a9e855e4d31856d07a75194ed1bbd61cb12fce8f858f70e6faae376f02935f61b78010295d16c7b2a333b1dc5345e14a958e0eeca037b72b4bbb663779b31e572a1486d9c0003ac61f87d78c9bbb558cc25a4bb969871edb521825077d4f7fac299cdd1ea52845034b24705f3e7e6c29fad5459311f2e1c96d7f9452c65629831f60d240a95ec6181a8039420dcdaca2cc20eb2a73653a6b851c0ff3e71300fbbac34c211b3c91f1719b12d95321149326afb4986a483f5252376d21fad220ebcb80e4396d5bedc42ded2dbf74543d30de21bc78bcb9cca3b84158ee7367d44718714249b075c694475bae39d8bf7b31f9f2837a26839aa89487804cfc88e20e30764787c0bc8ddae2ff4de925c53d8719877d8011343b7afca472ffb261ffe6aea42becb18980e88dc33c3683163897a23d4c06dd7a4b0ab1c100dc3782d503b79ab6a7753b6315205f2811665cf5ce8d4c7861b998883ac1a96dd1a204aad250e67e28b29481c39f3cdee1b891de3d3ee1bfa25494e7ab860b43010dfd5bfc5b2c026a344f735a4e88626c94c012b4a59ae9390db0a0d45bd856d911ff7abb11bbba1e4650ca85a39c5165551fe03ecc128676808da75184016d6587e0eba75dfd2a3ee3515348d9620fd73b661301b7b59541ecbd47314e9033fac23915d2fc65a2201149025c3beb84d4e8b6aa1e2ae43d5fadd208615a0e2fcda69789648070653db3b25c308bd1058e76ae647e483afa3826381502d1a704d9cbcb9086bf74ea7426292d94d2994fa2a85a4b67453301cb2c58e29b7d4801179f96d28eaa6068517cb45d7d9d0749912590437285817047e088014ba20920b186de94c055c800e1059aa396e9462b2097b68cbc5131abd0a1588f6c9e8746f3fad4a198d0dc1b46c69155bc0fa8f9eea53f74d4096d2d43bc51babc3ec390db534f266862a2cccfa856370899f791ac3b4c5a4bbc180cffe5b898b5480f273904b504ffc9dc3891b6b1f61282f7d0e0b017531d4ca8ef476e2750b18fc8fc7d000cc5c30a85c357ab19836f8ff220ac8d2c83b247a98c836366fcb7a06833b4d0c05762240327b11c6c6d61acda4a4e20ec033fcc0eb1da27da67359a60fbbbabe9f71ae2db0ec58550dbd90763893240515be683b38942d68379167cda408964b33f58fd4ecfc56f0e7e660852bf64bad9dc927bd19340515c13955e8a9792987a732753158837b6c4a0f53ebce52f8aa5f6e7b3654434798600d1b86900cd38db3741d7db1a6ec13982a23d71b06fbe2ee97fa4c4d11955e1a1f3b6b070d803c23c6828cbca7dd05078e563007a378466a01aecf070340bd6250ce4985519c20b5b543d1807b30b523ae609d1a5db644b1f923adfcb057b5a279f4b800810eaa083ce6eb06aa58a4df42cd789ecb452c843c11cfbe804b101e61378444d96b6800a13ad1f7236203a5415504f6f659cf65e61b142d5e10b93ba889e73088d1e2d8e8704ad1c60d2311231ce8ba762694733a75809c61bc43d3e0875fa568906c3ec7d2173d5f2c90d7958f51362ebb9c0d99c4a90019644c1cfeb399b8397a862b93c649bfd022612d2ed78ce152efcecf6e430151d9717f236b550a88c3561b58d46156b54d691083cdb4457577b0823317df92e48126fc3cbaf150176991da2fa8602d467ee27255e3c8026bbd08360481b9b2caaf07038ff8f469e105adc4fb472b569cc0bd264bc48dc2c7aee92ce6eae476a2cb7f4e737fd82657dd3c4f9ad4a4425475e2bca1cce86111dc4548dd782cda243915c65dcb10fd485008a0768792fa702026881697cebd2683eaa1984f4aad8e1bc888b7bd0e13c130df50783b262ce5da20e2ef33316d5029aab72f17e140cb99a9b8dd0107170bf5618c4d4f39b89e89e42f223fb4fdd4521691b454a5322106ca31f21358420e9196dccf56248aa14fdd4c30ef90d1cee213aa29c51440db3c5df3f33502476f1e944f2922bd08c47c4b56fa6bcfb07064fd92e19dde30a3dbf9cf91245da66aeac642eac7a938b957af44aebdc6b5f44448ec9d9179e067a90014a6acd68b92c8af7606345159d8f2a100de691e1166ac79ce4e4176865e8a73af03c7652a56e0a574779c806802f318462325149f082e9084b5283848d67851c4cd2c29a597990b604380e858ee0f5e005ef06643a2ee79454a10346c15661baeb2ea25a063397d9d725ec46775b0f101b7ebb63209935fdc8b1406608c83749005b6200305046df31fda21d354c3eebcd380850c96cbf735766cdb014f9ada0f9883c59d54e7a282b0990be03572522790c01f92b82646762e7a9fd5510be8f542c0a1d0db1e90e97d8895668846d74925ee8baff49077f3bdbb28ab04b56672126610d97687ad54f0045a662473f4b30e9a183b694e2f9d087100556e68fbbc40c7f1237c56dc4d4e2e8ec15eea0ad0644737f4ba1230a1fd79dde6fe8038707e35dda5dbac4443781bc65e57984d5da646b72d6c1955b8cb2d2aabc6f962de69e71446cf6ef70f37ddbc15898874c89b3f6a0e72180d91ab9ebd1a5046a8bf1a8ad5214aef7dbd6dd4b1ae078d9d6e9559137367c74fa681aa41ed41ca881361e3f27760cabba11e2b3953e374b7f75abce950d5248cd30b11bd8d7780db1dd70af0b72419fc75c5d26441939d5ab3a1d9905802e3a33a23c8b59f10d9dce3f30905c52ddd09d27e84b9a748096e8441f8548d4d207f0ab7f8dc0aaefe0eedb4ef66b02b60e2575a16682f8e0d8fc8dd68849da1df0880f06dd1710656b02c46415b65dcf231af6fec62619211e81174bd5b2a51128bf4a419c262b64cfdc852c2a530e09b36069973fb5f4e0a8395b8f3f8bf889cf61003598f4828d923992da9f18c06d8606aebebbe4a284511784be4bf8bba4247d45a1b6b8d3aea41056650f631c94ad0352415501447cdd2daaf56126924e5763f178af8ceab2561c368c503a8f8db4dc6ce76b0f95e6c16c6629b4e444552f89ae88f653a1a0614492dc51fec857846d28b2753249acd37320ad956553be1a18f2a4a78e1f42987567b542870a37deaf610ecb9ef086bc14e88bc9bb2aae03e9c5dc118cc4adabee0df2d0d11bfc6329a7e167580aa5b61d9dd6530f6a995d292dd566eb3e301891362573392436aa11dce3006ada8d2d44eae7190434104850d0e923389fb47d2446746c576d3cb25dd434e1d43cdcb48eb36ef04247d011b2bb8aeb395fecec6d8f004ec010f543ddfab23dd09caf8a387608bfc95684b790e7106e4aadafc047b3470cc7855750fb13cbddb6a45d033e4f24f863c24f902ae9d6b470853ee86e0f3179b72903bb43a514064570f15a4dfcbc88de8a269038cd5e8896cd8fc1dbb77b25f041420317e7e11394c6076ab44eef45ff5ec1c04e9c91247120041cc61b025eceb0a2633b1677374d3c4786d8248ab363d4742af227b3faced8d14aeb7b5e428ede6d5d01fc8eaf8bbbe777b5ee4d1756f9431fb4dc6f4a0057f241c3ed318c1ce685b544cb71c15925ea144486e5b97ac3890bae4ac4a4e9abf301df1719190fa08cc00fbe88aaa0d0811938e5ab770b2e2e7235bfb5048ca8c0caf6aa0c20deb48efb737d85f742937157394f58b55ebcb18e91bd59a61a6be558cc486b90f5a98467369a6dc6c94aa25cafac5acecf0d880811005089fd28ffb151f72da0bc909374b199daa560e01401094f68cd8cdd1752d9180d7e584b29f863e1e591300986e48d2642c67585476016acf0fdae42ba0f2e099e08bba5913694840dd604a7422d990a1c168fcaad2e18bdc2f17f321983f6caaf5818122f1ab167efef90920f3e62f53d7b2692fd2029fcedac0e9fd4fa03505d149e72d8e6d1e8354206dccca5708e781cebe591a5fdfdc9a9284ea3cd78ba32de407f1cc8f6c206b9688880f49327fb80733c4f1f31deb91b72fa70cead0a6470f935fac823c3f4626d4986dca19114c1ad13d1f1256f11dd0ab4d4cbf21f08cf2ab815a2fc80d493bc014718d310ff803426a87448957ceaf19af596d0b1fb0286e0916f6517ea4e4709386a0441e6ca5d7ba632859633b28785712872c0c238319b519b8fde124af975deccb73abd51f03e8a03c7e546522f21a85902afbda9120c31fc15149f8e0615ab8f9a99a1f2dde5758ba90e1da82f19ceeea65500d82a84802a69c812d06105f418ac30bcdbdb9a7c4d8a64b16e84a621c15a196412272f5ab02e87f5dcdd94e40e814ad264d8427f32c321d4df404afabc0cc1586bccae6803d2cb910fc27a6d5e55555d82d055183e4e3c2e18e79182a83240f42380f2eb413bf12c6de19d43ade7d044ecb065d5d3e83ac550dfd08b9385b7f8e2070f6a8c8390d3b0b9d758aa5d53e6a404f85fe83ff3dd259e39440e97cb457c6ccb14528044405a9ed0b30e08dcff73a6df169b2a88753370dd37a94af18713460784e187d88a7521484d0a41995072ab9f5ebfb2b4d99f07721813069e2269e6ec130b8ba0bf54cc6b9fcb169a2d272b95f9bb4719b1ea99ec663dd610920b365ac561c9321b4aa1bfb41b2a7264c05aa65f7b677a49b1bd793f1cb080d78edf5552ede3682a255a61fdca7d08655a2e93a1a9d78911146b085ad4d0dcb82fde9e770dcdde835c8a1281c14390b8699afac17819edd9e10e7b1e43a9b277ac6d6dcc39e453f4c53b76b6ff7563ddd0475edb5ed7b50865e7b3caaf61b193eed2deaa0a50e76ce5a0b4b9391242c97a2e7fc26d5355c1bffb1aeb797f32d4dcc7af978cc2e00c8f172a83ece3ec01f3db336a2efd44182571effb624367ed01275fe117f119f6f8c6dd049b8e08a15a193fedd48e6aea5520433096b9718a7377a56d0e69e5bdd91b8aad2e6d35ea5d07e77e32c70ba6e6f4b647649d7303ba5bb93fa0f5f423ac24fa56ec2780335819865f08744f6da72416c9de74fceb3caf6cdb3387c49ed9273340097d1350606cc356024e2a99ef9f8bdc73efb2ed946ec3fe2f0c3c28279341b85f108d70ecc22ef263aa9670273b05e0a655b64b3d7b3c7a19263bbcc93c0ac90973a956c3bcef21d97885904598cb84a9232b9e11cd1f7c9419033aaeb69156208c69261dc42d35657d9d9e45b3e8f73c3f06e1b13da9d663a6af97f5ba3407d51154dfc14bb2e405a26c3020bb5dfc76e1b9a1b5cc625e0bd12e39ad8945b79a002816790e1f05a2007df6277befbde596524a29652508c008c308b557fd2abea75b7c1dbe065fefcffbf3febc371eff8eaf757d17ba851e757d16b5d61635345b58307fddbfb7de9b9ff65d7c9d1a659d556ea74d77e817750b17e309dd844e2929020bdc0817f473a9080bdac6ccfb6fdeff7db6c5b7f37f36e7b736734a3f9021d0361d9bf8de9cf3db1659e31f61f167fa2cea59c74f31a7f40319427d9a83b1d11fa33959ee9cbd95fc28d5126c20d9d22106500b5c6cbed0966870a192a74aca152f867beb7c9006073370982c1153654d2f2a8bdaf981e585890d5b4de45c3af8457beb9862dba56d97ae4636897cfcb79b343e0669dbc4254d6a7558147515cb6e7110fc039bc34a3687dfc44d32c21f3afe1dd6338d63b92cd78db3adae92d5cd4e7b3e9e3a0faa2e06dd8c45bbbeda9765fdaf7ef96daf8f9fe1ef30fcbe5dfe0ee22aead76c17df425ffb8f3682b60fcbb22c87be2cc310fca0a0f21b2adff6b6a0a10f873848eef0857e875fa5421a797f6828dca78d07853ff4556a28fcf0c1fff8b96bbf5f0c326be6497ba117f578df942a689fc56fbc6e4a15b42ab49ff62e6c887dc252ff469a19be90497bd2fc7e9b648d9fe1f71fb75e637dea2165c5448a2ae823c74a7270c41dfb0782bd205d7a505d1dd30fdf78df7cf838b75e3b8b2f8af9c229cf52efd7da4db96bbdbf7b3e98ba688fc79e7ebf36592ebb553bc85fb16c2e7f5f3ecb133649e712fbfbfb69beabd115aa659590a62e804e7b41d4743168e74ccbb4fc341aedbab0a2f839d3f2d3b0f859aef169244992a7f8412449a3895f967cc4a5897f7bf9236c90f5b25db4176fad6749692f3e4983c8a07a8ae08382eadbae5e697c937f7f342d57ed40e41497fcec65152826faab505140f6f438dd834e7b40b0fab529542cbbc547dcefeafddfde15f313cc7e9db57bd9ae7bf1f7d87af5f3625a96fa4fdb559625076876f9e55fc0c11817f882f2557cfcac44ffe10f7fe093449f8dfcc8ff6c10ed6d34da0f9965108dfcc6cb4f91bbc03d7cd0360ad93d0588d40f3ff6b5deb6ab9f57fb30f3f135a7f7c3abf703abe7e3cf59f66b53d815cb6e6dbc2d58bf59ef6cbb28b65dfdeefd7be8fb5b922ffedf241b77814ba1da0fd55e3477edea357eae187bc937a7591a3f5d60927fa1c9c19872e42b4690ab08b78bb1af186b56cf7fdf7255046cae3ffd985baedac1e54835abb7d48a4fd824bcebe918ebe90013e4c3dc56d4dba163df6e1b6bc3a0d39e8e3d1d77dad381a79f3becb2c1467f8c30c6f77edff79d2b72fddbdf773f0c95cf446d2d252d7d7ec5fae1c939ff08fbe56b6db6f75a9a6b17c57befb5afc94bf1f8626c930b6c9fac0ddb649f705428a8a89a83e2c1b3678c628c87051df62c679b2c0efbf474defa7eb13cc5c7e3583fac9fa28bfb3f7ff5c317eb875f4330c80eb1e62a22b55f7499cab3c84849b45f64299e11d6dc3677a315ecf52b4daae28b5b7cfcdf7f7e9b7fe7efa05b7dffd6b190f2b475fbf789ee9f144cb76fcbcba3fc7ffbdd86f1c4b721f0131e3a2696ebf833eef184a1ba446c43dcae2e06511b62850d7fae37ccfabdf7da5c2f7e6b666cdf922064cbb1fd5aeb8b22bd16bf0d61edb5f6dea7e41d37b7bf83524af7b8c13ff7dedb05ae591d572cfb646dd8268bc33ed5b029e52e6ca7af02a42874f07308058221f845ed6f7f6dfa687c5f85faa0beefdbb9abcb925559fffba747948726dde70a5b07b39873b84f17f637481ffc5cc76a07999250dfd40ef26fda31ee3da9d128e44cb3d65804daf1bd0306480c5f5dc2fba5d46f0b4571044770048982ca71a4fd1038128de669fbfd65481414aa10451b248a61188a24507a049641a339c44f1b5f710bbfbe584107da83a6892e8260bd75b014c7b3f6fb69e1680bc3af4f640b87cc3a8e43b40739f9e1836508fe38d286cca01f4d211e9240e951c93928de2462b5fad165c98d61bc5e4afddfe39a502f07d5d0d050f9b5f233589643436118965f1b1a1aca5f9e4163790a3d7d705441be582d38f4e4388efcc40df1062cf571fca1311443f0e98ba559e367105f71137b397af472d818bfbe684593344f139d2c4591d7a10ffaf3d64551ace0874e9ad03854137a4a86307e55317e7d226e9fdeba58137a919fb72e3e093cf421721ce2381bf936f28748919f297a2954fb9a097e6906f193c67fec38f2558c2f3e39bef8a3188621c86f55a9fffa48716310bf90c42749721c3749063df9d6c49140fb9af8a379e2caa73d451fff3ec7957c041aaf71f1c73fcb1dc44708416e9fe427692b853e0c32cf143de8451bd8efdf172f3d02cbf1f726cdda8f66d0df6e52a53af233d8c9b7d123902612fde567a9bf6696fcbcb74e440a711c79eeef875e932fdacc73839e7f6fdb493e256d09f292e223bd12c78d5ffba0bf952f746ff8e393941ed5380e7c5cf8e48b4f8f82382ee423507a443e0edcfcc48124ec1771e0fd12f4e83e521f37bfd1231a5f712b012271dc7813c3bf1c47861c07eec78d7f9fe4e1e6276e5b6b473e82384208f21b3dda7c8412f408897c21d2dff7b64920af49e92882a52bf21178e8b6bfbfc1df6f4d4b920d58ea368e1b1a127f7cf229116fc052076d2f3e687bf16de2ded43c477ea6e82b6ebd9e29faa67d699e297af9422f96bd1c4fb0043dd16fee34d1ef13bdcd3c6fddf6a479a6e864ed292982edc11f61f74ed147589b593e690a591d69fb0e650396ee8f2fde1fffde1f89785505367e967dfca0bffc1cf98a5b1f1aaaf1f3d683ccf3d2386e243febf1c9f1da1e9a2abe15b7aebfb2dc25ee974bb9fffee552daa7f7bc7cc5ad3b200bd94d26eed7af94ff3efe5b165f4588ff528efb9e7efeb30c1ffc10f73d6ebfc56d5e82766e711fb62258ea97e3f0abb86ff56bf3c4e9a7601da9e3f4f72a7446ea14cce2a89c73e6da7e28a5f7432e5d4fa73f4691ea1402628a12533c85b1d11f23143c18e181ad2ee0a9bd95fc28858da09a448907d81019ef28cfd2da1350a84cb5c9aadb6ebf3ed51e35caf68f8f286162ab77fb2832f00110bbbc82d2adbd7ad26ddd59cb95407c288b7494241e50c286a84fda00d2a2d2b3821c206274503856b6a44c3921a952a6862760bdecb4f764ab9fb92c750d13a5ca587f2e36f207d37b021ea02e3565d6e4e1c101267af0e068333626b5bb789e1001ab6a2030a601eb6cec3da971f11256990d73c47c1c79d343048db21ba4b8fae860dadd9c51874e7b4e6af4d368cc6b5f5ab30d10cddaca12846d92675c61d4ef2b61aaf20401e2032225add35e13389d7a7dc8e54e7b4dd8f43377b7d4828035c581e374a58ce7e76a0b991bb48a34b9836763f9c1f6e9ea0c982f3720e1b1c36238c8a8ecb400c3c80b3b6c32161c524c8f617a0d4b9e5bd107647461e20522bb53c7889e1798ceec29b202103327585ae61a2c24201d8dc5425899f4d869af89943bf469c5ea14487952310ca4a4bfd4977ae54b5dbcf7520c7575b53e656b73cedc36d511c3ca7ded08123c3609ea35e28645032ccaf7c98fd398254e644c3bfc4e2fe49c09b3b307109c3a345cfde918e38c8de4bc260d8d4ec77a8771ee3549f2473cf39fa7fd4a3fbf4829a52372ce5949bc3777efbd7f3b33b6b5bc3a1af6dce905ea087b01eab5a3b59ab83a1524b8bdca04fac12edad15e009fa84c4cbb13d46ba77989abcb4a7a4cfce09c2929c25216199cac2074a07e8895757cd5ebf84a0b91046e5cd163a54c159c34b64e7b4d7674b1d35e93193088f6318fad9bf4bdc59f65fac46cd3d857b74c487142b5aa4c15ab36996073563ffefc75874d1329f81ef35c3651705c093805e2e31dddd11d254130a17f84dddfe74f4185eff1875c85efb168a6d0a4847a470a17a69df8f8535081abf07d0a5408f1632b7593f22761cbc41a406c0ce435eceaac95cdd5af4cb5e9ea6cd5e6285c9dc59590ffcbe14ac01f47ba3aabf95f9d9532add5d5d9df4bd6ea2871531135c9eee88b4156e497a05fe82740773082ce28892285f1c3efbfeaf5fd57b72a96cd55215ec3fc58a61aaf605757ab189eb139353285092459bef8348ec3bfb4ab7114a4aece0a93fc84ca7475f54bb342d5a6da82458b12f67f5f827ef2274077b56f81228511450a412fbe7eb1fc5c3e2551889fbfc57d162d4ac09500860f3eddd1be8509da057025d05ee885780a76292ced44a09d9a16eaeaea6fd34a5d5dfd9a0923e8ac3471f69776fac56b4e80ee62804f7bb19225a020518c2882b86dbabafa348ebbbfb423f95f5db54f57575f344b5c5dfdd0347175f5411377398bdaab96761fcf5d5d7d6d661367398bda91764a57575f05dad2b55f0b1809a51403f5cbfbb3e12225eeb4b724c99223986adcf6cb35b7ef2d89ba617a5750bdab1837971bd341a2181bc9f4d65bc202852149143952ec6cd94203150376668c062b6c6c6042e7f6b7d3de12a88e74b1c42b5e2cd6c7fb6fe52aeeef1b8667ae9fff5e6bcfda35c8cffab5b248a1eb17cd33ffa7a23e66717b7d6ceb4b9a6c2547003ff373e78b55dcdff87b2531fadb246cb527a73ffde911f26b7ee657a1e2fea8cdfc95bc9f4d15da7e25c5aadb504a29a51fe8bdf4deaff752bca130c618639cb3c639e35c73c6f8ed6f8b64a33c09f23533ba229c3061a3b42fd66a474b8260c2e670063e138559bb091f4871820b146c888f9fb039fc266c0e3f8044d5fe5d5aa3d20850798e1de31745d1d6fa514ada4b993211f1be51b7f6d62a4ed34fa16a5dbf844dba5ef64d9cb8eaf651985005d6ed7fc0cc8ef6ac8a74db69af6aabdb47c186b09ad60f906a0e39ddfecd633bed5515e934879f577d5bd75040f9731fc99df692d418cb2432bafea2524eb93bed2109d491e0a159d0690f89193f948612d8be7466e83a8aab6bedb5e9171d4d6bde7c0154c6676744648e9eb3233356c0dad141c2d5699df69030c94744bd5fac94fcf6c61863244d2c4861ba749635ca5aedb8c107f5df721a04f5de558f98b44fdac72b94e7d88b3e88fac6bfb4bd11b6b97d6dc538d3f4be7bef7db5fe8bdf62fdddfa66acf5fd3ead3f8c75a6b48281529494484c516e6c2bbf62216cda2e9bc3a010c6df8c92f6b51f7f8f65de49366e64edbe64e50962048912208008f7a647e7d84fa1af8170ed94e48b7f0e3df86517fa6d9e65f8e2833fc4371982102f3fe847dc1ac72e70a7f17d86ef4204a1f4c1de2f861fca7397162c71933a24d99ded2189ead68aa0188a21b6b9906f9bb3399053241b629f2b468cff33ed56ed606361db53f20296ab1600dbaa6c3fe27630633421eb44669c5e85ecdee2554149754920acae3ebd19040ed33841f45a97725095ede8a1d56546991d76d33156d3f1b7c35809932252d0e481f262b3c3dc46a72c6fb90f75faf6d3cf1c8d9aef1b2ae2f215461debc71a5f3318e329193ad61d638c6f2090f6d4172ed3b259d788f68c0c99f21229aea1881263aca180d26573b4df5a6973b80bae70cb6057df08abd7cfd9a467626252b3abbd291b19f4da3b62d5eb7f509fc4b5e408b6732ca31ceab467c4854ec36c94488df4e73ff1bdce26eec4fefcfafb4f671377427ffeacb359deda7d9c57af7f020ef3106cc74f7b53acbafd151fd8a40d9e98989856d80de9f71f60932ad8dd3fb1d5efa300b3bb6f820d417b4666f40ebd2765d5efbbc0260a2a59260a2c1b260aac279ba3fdd61f49d331105050d9b239da454ba2d8257cafc107790a25fd9bb439eec4f7fb374fe1c697769aefabbb499997d7da5b46acb5d65a2f6d71f9c8497a14d53bed11e1ea17541c25ed11b1d1e9ef4e7b44a0f473f74b75a73d224cbacde6ce5d56c93169aa510eb5dc8dfaf7236ed6868c6f778632ecb437c4ac9f979f14ac5737a2ad5d7f1f9afe7dff540409ea35c2e6aa4d86fe7ddff7f122eae5a1d3de10287da8d3de9022602a45aa60bc95a3ad1745d58be2819bf4f75a6badf510205d6bcdcfcf368447d75fa4b5be75b053003aed45e1e964a7bd2838fd34aa9333cddff72d90fac75904f5fd9b67dc0855aad73fa999bebf0552df9c04f8e8d6dffb9695a7fe6d7359fff93db6b96d56063afa042565850582d496b9f3b83730a54546941b597814c9600e9f315858589822b3cb4e3dff0d4fcf394b123e3d87bb9cc7ad6d4d3d93f17220a8365c4d6366b8f9b2cb73aea634d992d5832ccc2ef39b0ddbfeab5988062ff48b2b45d4d4c9f114a40fd558a01759fa6c71f265469a33b1ce0a4432ea34f9ea648194cf0c5cd0d4a023a4690600b674113343d61524653e946c12c5037e69b321be0e8220b83793d5d1a6fd5442dda4de2a17021396cd59a9e7aca569aae72c77aec64b44d4a0d63983260563c244030f4d0f272111b84106b6468c8531285e99d65d63e303b9cd963729e4586b1836601afa7beca4c4658caf2b28fda5a689fe0017992f5a61ba4cd5d9e9406d9a40c112bb73b6d3dc562655a6e751b3c6e8d05a122787989e0ae3c69b217b8e60ed2093b5c215aff0b0818b131a8870d5b0a3bef89a73667b6225cb101b53b684d0119d9c8962a5dc00b90c5741b1cd593c6e7ac45bd8be8286d134485ec2fa7923f3eae7be1519e14c804ffb09cbb40b77d3de81ff99316428edc06fdabb303c01773f05eab533c1f726d85f801e02e36bffefe32837b1fff209d0dde61c2f658bd97429698f0cabf7e28c75db23b3ead6f655fbcffbfa9adf8942c7f7deabe2fba11e02e36befd919026e8bdaa90bdbabbea764090bd87d9c5e1dbd41a6e6df39dcb0b7921fa55bbd0db96303062d2f602fecf2ef9bb4e77801629241ced48cba029cb19e8376598c0d64f2f7e64abf17f46b642bcb5ee230a5add3de9b256f7a5420831b40157c429df65e30eb449df6dcccc9733356b774633425add5da7b31ce59ebefdbd5da7b31ce59ebefc3694a52840b6e5a91cd556b69b81000d05900a0dfa7fdf440bffc96a930588973a6ca563697999c99aa5b2a9bb3d93462723f53d9105636c46d81efed5484876ebfc8888aa019eb2b13e9c784490f4b5490c5f42be9004b47589c7e1aa369eff683ff994d7ba7c209cbb4db0f9a3294765f0c191fecbe6fc23b15fa7d4be23437f13ded27caddaeda7f2ef55b99fa3629bd3a335bcc45a43729ef387346eceb8b151f3b6ae72b8718c69af2f4f1b2c35b9dfea6ffd1d7f4337d5cad3afd4bb9b5d6da200c43896dce5a6b2dfde060304bf9b53f8c31be263da218638cf199bc2bc6d8661b52c218638c31be58acac7f29a5942a61bc6fb7b2bcf76ab9d80c6551cf3a6e84b0b3a86725e8979335427063b16f53da75ce19677e628cf1eef96b5791ffeefc9ae7bc37ddf4313ff3ebf740b7be01d78bcd98a194d26b86522691521160ddf6bb1ae78c2f364343549aa37fe6d78f73d620b8435ad603270c4e5769bb8dc102d54f101f60e9a124437982e8455878e4506484e5469706bcc2bcbab0d4b05e585e80d8eb824e7b5e73bcc6f0158cafb555d45489a177fcd55d9e4041f15e61f759c1eadf87ab60591dedfaca96d5951d5ff1bae265e4b7aef2b4f5cab41960c5eaea74b54a9e2a66fdb4f5fa770fc6467f8ca8ecade447e9defa19df6bcd6c309b4a573f7338d08cebd597e69043d814192b6233e8a020eacb0e255f72ccf066876fe8b82b0ec652c24e7b54a0d829b7e7ae315d2f943081c226612a57b7df4f4145d87ef1144c65099ef20115ab3b25532f2a3b7a0d2f59181bfd31cada5bc98f52d7f755fd5a6badb5d65a6badb5d6b5fe7ead7feb4fe35cb3eef5b3f9ab55bf58ffab49becf3ea547df7f5fbd5a4b174de9d107a6cfbf29e52ff10013284cc89f6245fe9d7f2ccaffb9afe7fff2eb7cefcdd876fae2ad24c1eef86aadb5ae60a40842bd72a147423d8b5a537aa4398b7a4677ef4a85e12765a73d2a317a583f6b18d2000860c3dfa163560319c6b60f3dba2f420437083dba6f6dc01c8a8ac0977ae9b8627ea1e8d15549bb50bf5057c87d5d9318b00588ea68bf4f6b0806b8c0a339da4f5abf533aeda75067c0561f8a2b0218b09503ed805ea9b12bca46a5eab4e7829a7ed2b37eff03aea87e7fc4fd123d1798f40a869d94b4c7b5a707dd3ee8d7feeefe091419f8c00aa91deef751a0226ebf3dae38fd1ae5f859b9749a799f102a975cab2ceed8ac4cbd9a6725a182f5fa9a04a16a12041646bd7e8c6ecd24bd825504d04edfaabc75fab58a8a10418dd16b153da22f4204499274cbc1a80811e0a73074fb750b1551c1e811fd2df4887ee5424590f697a808cb6ffd9c46a4b54879df8e5b4d21e81fc0dec7d94fff58da6efff93f20d9a431894ca27dfe12f4b38e52fba2199adbeaece6a5be5a7ebaada765a3e72fbf28db1a22b553a03ac5d2694fca982e0689f4265df0f4e997b827dc247c938a9e5a31297cfa296ed2064f3d3cc57df937893f259f7ec5ba4926118a9b34a4c1d39a054f9fd2003c7dd38873f003f80fdfc10c00e71905e03378215303ced369f0b9a7999cf30670f41d7e344dcecb80bff9a0b901e71d75f80fbf4d0f9c97dbe005f09f89e33c6ebed16b1303cec31571de060278dd5f60f23078fd1ebe97e5a7d727f2f045afb9d3871d00be34791eb813073b1eed3d143dee459357c49d8876bcfd45dc89b6fbc780f32ef8f22d3079228e87237a0c3ec8e41171a7bbe3ddbec4e0833e347930c4c7803b1d659317c49d12b0e38def41e44e458fe34eb61d2f3fee874c1e0703e04e16ec78e017fd1177da3bde7ddc6393d7813b09ed781dbefc40f4183c07dc497f05264f00dc09b7e3e9c7e9b893d18e67c197afc19339ee14b4e391efe137e04e4a3bdef745af01770a77bca1c7e06b262f000f83b7b4cb803b6db0e3e1c73de74eba1daf822f398fbf53dd856f4d1e0cded2ce883b2960c72bdf83870f398fe879b6e70d3daff6421f00ee94b4e3855fc4394f3f2f3f0f3fcffefda237b993ddf16a8fc1bfc9b38fe33c0f9c273e2f7c1ef8bceff73bd51dee0160f26c8f01e739d55d11e795cf0b7a1eed79e3938fe3bc0b9e67c1f36ecfebf015fc887b810566eeeae8df4c135747bf021385aba3dfc1ac44a6cd44ba3afa43268aaba32f6456a6aba35f33abd5d5d12fcdf2ea287d9a69c2d5d127cdda7475f447b36299b7aba31f9a23ae8e3e68a6b83afadbac4f5747ff33ebd6d5d1d7e65f1dfd6c96b83afad83ce1eae85fb3425d1d7d6b562f53858bee809b0a47757f89f2d4ff467b50a40237bcf5f75a6bad73eef9f9be98beafa6ef03c35a55b9d7b4a995fb437067281f94a6b1351c0c80e8b30df6ce625747b7073640c1d3e606922846c2b2a0b11aad82f4d090c3072ccb8d2f64c6a9da654242222f53a7bdb3afae35531f61c5d2d481074d922c323e3920357981394942364603982b1c462c19a2286ab0276342505ea0087dd5c43157aaded4d0c56406396735a431bb82e64d0e505fb0b4d0b0c610ed99fac2440509d49daa9d3ee30576430e8f1e6bbc407961fbaa654169223690060f9e50999165e6298e93922e5a5aa0a123a165a3cc103858b08021e2813a10243319c31c241b63a27cadc0e5030d58e44a4b0d3554b1f0a3020269183a8181e07847a7b0518b939a5ac6a275d5462c098c3f33b8d85cb0618f9e2f294f9ac450a6a2184d34a001c0d8671d289b193c2d2b006a6286862d3588da8cf9e1076c0c99ad359512cd98f3c2d88f2c377ec4008209a0ad3b769e902103c3d2f1614111e10e19706541f386888c253860d8076063e78f0c80f21019c3666071c4b187839e3d48006971da63839628217bf89b315e8e949991c38b3045130e3765718ce85193a5ea88872a65a86a24a9f2e584cece1904dd446d3754db0d93ed266bbbe9cabdb837100d23e9ae751826f1b23a0a162636a6414832476ba41ce21a5beb5a6b18d43d32c37ac307cc1529231f303347099a1c4ac8bebce430563dbf118f5dfe0f48e5cde6b097d551b03010c4887d7993e8ed53a60c5697d314285e3bedc30d133a4e3de6dcb0d3bdae7516303d3bc630d52c32aaac9a9efe0f483a8c54ce9fd585e1e7bbed0cb581e84c80cf8e9ef0d3232490193d5257daec344d1387888e3d737a64cdd8e917bad676a4dcb4bef3850fe02526cb88131c7a6bb29c99b9e1caca101e5758ec7811ed88e1b64e428b38d92a83b246499c2c2f13b680a509634106ae214c1e80a011706723386e14319ce5494acf55cf0b3c5d50bcf4b428a957daf418b98419394355430c1cb1b30df6ae78062f107f7a8726c3a1f639be2652d702ae3a3f6ea07d41b00ed6de603d0bf57ccd0e54d91375d605c317202b547af2286181c12a8a8f589b17b21d707f7bd456df18669a73798503992e73662003d20757a64e0e2e3153a6f654a123c3b7a6aac4b4d4fa490dda4462030e1d1c7c6eccd9e92f6d5ef8093443151bb56b063adbc8d65a7f5a07196d7829d3a38c4a142b5f546a16a0337583860e1e75c204b067ec7c81362333a4b9beb0ac47a01b9c9c3149e2e686ab1c2cec502383d887122f6e4039f3664d131b2e6c50e546922d71ee38097466cbc2eea0097339d7384c719ae23cc581bac591fa9cfef29aaf387ffee8fd790884a13c1589819e8a2c889895176370fcd982c397a2d03822a74e18384c9e90905489c960c6829d38bbac956f2033c44b8d3331b038d5300a4e6d70785303aa8b9e2960ce000914c4853f61c427a526c244a489c81311a8fd4a3a94360f0541518b35212c7d4110b43303bcdd6bc14881b10283a56f1bfcbe9c73ce1fd91edda67c5baf80591d05e14ad82e61a0519ac0adb368b1193f3dfe0b980417a804d19221562789942f367bf61213393c9e66fc89a365f5dd3a358c3734e3515efda47516eae10bd5a74ebf74cc79a2e0d51aab09ede212045d00f1b18a4147ce979deea3278cd7a5ea2a10d34e67e92b2236f1bf272376d01df477c9e00438c0c8f1038609ef4d944d63da2a92e6cc4c8c180eccf0f49cb1d65a77ed052c93f01236c2da347a422b8a144c94310d200b45cd8e2de42362a60590530e1b4d3c3ea811b283c8123874908cb951bcbd2b06411ed4d5d1fd8d5fef85c13d78f6f8e1c3c4a7e96910033f8b4703de0c291963b49290ed34942d7dd8807991a7c8132cd0441d332838540922a317057525091c1e57614c0198aa853baab021e373c64d0ea72b2277ec2c25e93a82634b981e0c7c3cd8a05e72b2c135d66ba146988d3f40ceda449d7962476b979df47ceb6c019bdc1153bb13e766803645c6c08a78b12aa300150b6645d8acf9b2e281101855566b669095b1c004491c3d675a52366870428786945a44975f64522c0e0931b307f39509f707b569ecdca5eab372839fd5b66a81591d05412b6c97e1f7e470d16116ded827834895caefb88b41e106c7320cdfccb13a8a479378e3479380c3a4f5831ebe2f5782b089c21483ea855dd65386236b0f8cb2b03fbbbc842cc8100f645d370fd298ee20087e1ddc3b8698d5d1b1397848c4f04382c79491946059d957631d7294df07a5350e43203a88a87d7830018819132d2b5ba4c85ad0b264cb057988984962a60c981c9ad008a471a225c50e1a195d5655927c29fbc2aabad32bbf0f418c961ada6cb9700550d5d4d90b3779c2804d71314374844c063545c8b474c99044eacb06baa687131d5c6aaee0d009aa809f3b3ab6f0e842b605499134747041dca009739247ce8e40391ab63308d618b33a3a07cf2651c3cf26618369ef1c0543f505ca8c286a986aa07ac2a4e7af27558452006547142b4eae86b8292fd34dc330b3a263e827935c53db2818f3254b8c2f7e6a20b2cb60bcca82f8608384cb2e4f916b6a39e72fdfd86067186547f611b3af2c95870469010b0d139c29661c00a4c95359d7d81b3e5683dbd3991e576677fee0c111480e0c46d46c997166e4d32c9452e0d88f1cbae4e873e50622540b9496113d6dbe98c5e1b78c47d0ad1346bcb4fc709d3562a88bd0d9d3e6c677e3e9ea0f09063134200f2eb86280a1c69f216afc1099ea81e7ea88130d42e4e0c1327646816800206049182534906ce16133c46aca045c3284893182d50307a05d413084207b6f21614442c8b068adb51eea9ac498b09c4bdba48ac71c281cee50598094295f43b0e4f8b913a5064da8268e286aada68ed65be3f24be411c31e301cb6b20861014939003537cedc40e7cb0c5c3a688db1e12687d999244f846831c245cd4e0811a2d574c60b1c32640ed2b3a8d58212324daa6ca189b3cb5260e0a2a5e7c6d48ded83ca16a7335465bca89863c2c2f4c1a1434a10a8fd69203de7accb66c0a84105069319a2d01ac244b123a60a1a2e529e2826afc8f44c7e3a8bf9b10edafea1edf8108faac280c8784303abe92a4cd4559b2831aa1c7a8453565358535b535e53605361536263ce79dc39e72c55337ace787f21d18f2d45c83c85814306838f2a353a1031f850b2668b86992d1eaaf45993c68913355e337a68b1ea724108b6c688d5d081e3ec864003e041962fbe17319849a9d2c272a14b56901b986250620406201e7698be3225a4d6bad43fea90559f255470984225b663690997a9b339605467541483b317655176f4d1a36303eadd2045ab0a1628e28c30e71c43eaea6807c1fde5cf6aae601adc7c9f7eaa5345cbc1332e65c998d3c60e591f395aba28e103872b4a071915ec95c1932b654284bcf0c545460eb3399b8927a34857d78c235ba85249c1c09ceb53feb2531004eb548b8e2c0a66b3c482fc6952c30bc92ee3a0014acb0e272201c890c58351e7c893296039ef9ef30d3329e0171695db047e3bff08827c9b7b1c77ce39e752fffeb48db230b26c4d2d488f0cb3b2176aa6d89093438f3c66a07038f39523086b4dc7ced79b610bb6538a74d520a32486312b1bb6fcc071554489560db32774fc8834ccfe94c1282f58d3234daf8e9818a0ec74952b3c709ea0d9d1ebc223e7506b1d864d369c20a8646cd809639421641589000000056316000020100e874382a1344e145d7d14800b6aac4a62421687a2c1601c065114c3300cc3501003300c8318630c82d6b1330a71b39b86a122aca34b1b10976419fb81259ab1370ce04bca8939b909ec18a09346a04188c0f725dd12c5f5316f3fe55a3630556e1cda3471f31d6639dce0d7220150f6a93abbe8c221440f1b7d50781b353f4a9e8dbd2b6e8c6fba3af113e79aea7dde824ad26a116fa1f390a75f5413ba4c70c5bfa1b215861e0eb5cf9c5569e852baf59f52cc02bb8d6951ad2266aaa99c5225ec4aa5a2e7a7aae5797b917d155d6f0aa06625525e01b4408a023bcaa03d81b0c0342d4fa2d1c055eb6f8ba19b604741e1a87221a1a8c7c0d240e7a323eaa3f53f7ef40a3fc6cd4fd17ea670c1a19509452cbb12811b5ac0f2db1defbc3062c581527f76f26c8c3c24cff0f65c7683df10632eeffbea0045d8cf3d9e152a9d63c1a218995ef935e547962323571f68072ecb645c0be9f8b15d996997f20aa3950fe5311b80c010048280fc442a730893a8ce7c55ad601bf5481f7b664aaef09465be9ec91299c09fe1b4f75e3acff0fda1f6d32691dabb62ab444af48113316e295f750b1c02b98d039d14567216103cd9504506e07355a0cd1168482fb716d358b17d0b2d39357481ecd0c2d9a33ae550dffd5ec468c39e118c94494395837dc9a54665cb823b0bb8d426365c110516cb662e400e25e2739ac5ce40104f08f4f95baddf72b6a162a1bf5184aa08b69d55588d73c521a6df144e1fc2b59a49f34ab0a8cc4468e5bd9188734498eda00df09036f0a45a5d223af2df982a615516d7b16029b85dbd477372002c37b0a0abdd24019494121fc42c8406ef29c08bba69d073008795f0923fcdf14f8125c73685d5c7564139c28a383652d13fda9d294164526069a6e21f152c9b943c7471642ec02b616abb1d117a9328faba9df53a251907821f041eb2ef3835968198f6149e5a85a5aa0635c25004622543bfdb6da006eb15a2f92f175982f2e0bae68ef2eae89280593a902404a4c45139c63c83cf17ce54ab2be24c2c909eaac14fa206a0bbd2088693c17a24f38bda8943a70112a13d697ae6afde825de4dc6b009f0799e7941d86bfd131dda3c634c84b9c0c6e451c67a2b4046543d5ea41d17bece77a8cda9034f39705e39dfd275341ddefc89686aca9289e73797b5a20bc0440ab2fa550365d3ce114521b39bc37b059268583c804270db79905c668f6bedc8e069472a39c772f06941ce5d37fae5a6dac83e99263e8b9e1fa13314788e840dac187969e26f1ae2208431a15b465b947593c9bc42e82db20460f69331cac4954480da65c8535b187c3918198cb1f7607248d00740cc197af7183a83d7566692067bf75e4904941d2c892041353961ea51d8e16e8e72dac1c79199a73935742db1ebbddff6bc61b7911d8cb118e552abb42c28c015fe629d0011ac62a40f55f168601762109fc6df0e7c99e9cc4a5bfee6945be9107ad6403428e97bb2c31687511357e373e896413c1ee2b8a18f3d38ad23a2e30a6698e9c82afdcb19c02b0c705dae9bee80758e0d753509758dd4918bbb67b1937d279570fb5d94f88aa2e7a925d261db1de9d063ae2d6215d6c2d9601e8114b93cd4c2dd343bf2921be4858e160fa35ddbd0c58e006779bcdf2946b6d173722b3fa4d4ea18091f2e061cd1eb1c1e1f2f8191b416cc5c6565b91ef30426c568c7eed9b5af6e0e2d1eb251cbc4dbcec38f727006c81c5fff49458252dfa685b83c5a82016f860a8eb1517ea7a3dd473eec4bc9b862ff40fc85851cc0ecf581eec9886645cb9312ad3abeb1e2a8cb1770822f3ef2c0e53e63debc465f325b022f60ef3b6b15802e7cabca5e6d53f2d96586afe40e12a340ff52c503351ce04a9571bc6b29f3a8ccc78edc88585addc15382aa359774738a531f6ed5b3a0e2467f42c0a9894c81f41203c098c9b0ab3d34e55f29b5b5a6a96dff3e42caee606c9e27161ba888c0ad1644a4cd80af788ea08db29a3f5e2a95090e745bd88c9a7d63122a95616a893e29dfce451d921d172359896c378bc90eb62ed6f1985b235c5a9b3369df289e0bdb4a2afaeab5c179cbc6c191572182cadb83462b252c223af4b992f6ab3755be90793a644db974c470a0d3b7ecc5e25b08ce98273ccc167d9271ef2cb8e23ba8e2fd1a2b73ac0c1552972d702cec28542f4719e833bb2f9891517ee51b8ee2923fed4fef92f238296c8aa5d946a799ecd80f4734b7a412c631512746b777f3f247cc59b1715eba758bd6928a74098314866026a3341b2543ea3973c5012b3c5d65bce480334ba33594b611646af6151334e9ce8774e54c0caef2772f16f8e4f675975532780e436ec560c3bcf80e842b38b4faa8833f87bc61c39b9f6311d30b800e80718404bb7a8ca82c8b122ea03a05216325775c07b8c9e77240f0684fbb2501289cb5cfe859a9716b23e4d5430acfd56914164652e7bfb77daabe33a58c35bba59998140f788604885cd204d2b57bbdb109426dd84f74f211d0a7fb382514d8681e88ea7fe417c6fbd0db31e76c8c5fbbd60745b62b9380f0e580e1898b2f4c1e3711da828c0405d7272fd6ac53710b45cbdb1004a31c8b2c2bb4e27f4234401b4f204a4d806386ba2f608671c3981ce37161cc683160694090d0148acdb30edf32b6464a363a0edee07f7c5eca005e659ebc5402aa4c89403628e7c6e8997c835555f6cead08b1c18940ee9e5a413f4c6b406db230780deb0f345e142b4e9a85aab7f5334eb7d6386e4486471d0ea920278423f35e173b54812f27f729f3955b9a486212805cbc166fcc7c510d925f8c47142e273e559031d93496027451edfeb66d711727e6793cf1aa64c4366cca523c95abb8821d8dd62cc8585a8ba257f9dc10e6426929cdccdbeb2e5450f88a3bef24ef64d80884a07b7b2c9237d3a4aead01c6e1de94c15eee63b70d123ef983d237110d59fb9b9dc74ac85a8471b34bacacd4a5dc6518ef37888829421468015961a7f4184dd6c548c648ab5d54a6330aee710b0f01d09798a9468283d9be942c435f2a3bb5a70a605d248131e58865fd8c620e7c9eacae023b5cef7797628fdb43c8a0b8170f0fb72feaab05eab6a4dae9f3f53f54105901a8873f75dc0b62945f4d167d0209aea6e8508d939b1413e1f96d2ffddd252eea92eaab10504bba39a17c5bb3b4687e1669b66373487aa721a1e21de969e52480942446ae58c087c7b7cd1284c9345c50faa22258ad993e8ca38a71485c5e0b696553f47493b2e424459e3d4bff3db2065215d8eca95dc9ced0f107dc58b3b1388a55793fa4e572d21860fc8520b652466dd4417e9fbd0936c243ad004103b9ef4fa61ce3deae26152f565a3050ac5c489d87a50256568e239d17561997492dfa22215131ed26a47baa27cb7cd853bab3407821da40e93ceb32faad9aea8e9b93bfd9420282785c998856f5b08fdbfb971e842b93847bf3329ba5dad59f5e918666a82b521b50cebacd815d2303950b3500f7e3a93007c3d19a4a6935030453a6c1d7eae8502a60cb2626b6f69cdb0d8f4f4c2541158857076b0362a8561044c40f97b62baf88120e9e9281936a53ea3efc419bb54506eeac309918c8ee7a35d6c13445625e08189e218e7431fdbae70a45826468240463ae524409ca8bfb9edf3a1174e21e2eb75a313b0ebf629a734254b90a4b21c68402fd76d12b040bca835062e57d72d4f9f8f992c74c64495d31591d0891a99d661f0113b4c042c19d9deaca87e691758d5aa41311612e3a9d01f9989fa42d355020dc4c796f01f3a11754edab6568346a3f3dd13b27f01122629b33b77f0af74a06f083b4c0d621fe008373bca2eadf8d2e4879d64714276f6b264f0ce6496b8d5020507d328dbb0b1cc883d8aa175bcfed81f6e320ab1949fef0a5a46123bd0e46f90f2bb05b263034ecb2e49178703cf170a6292052cabb386ad024376c3084a750f4f39ca0296e0fae5a61e72c91e88e04d4580abf7026e2f362ead0b8dc9f248f643d414679e1261348f1827a4abd14604dc7a5e0272abd72d1e70b758457eb79881ee830693849606a5c33543ac4351a152052c0902dac569c4868fc986218f7337c2e5ee283e32a45f1a249647c230159d6e023a14de70653f2910fb430ac4407bcc202952bb754870b052f3ca948bdf25d68d6642e5c01568461db4f6adf87dbc1e1fdaada948df6104f004ceb8065028783a0a4dd0a0e412814090a4523275e64cc3be4ebb23ca5fe393639d42a6e43becb4055542f0c94d01efc7bb4adcdcf0fdf2a9b943ad918440eb4f8a258f98c23627e5da64677885952c676f2ab618fafa20c7d226319b0606104b286204790049bdbb72c05ae68a9df83fa7de6ca6fe4ca421cb4fdaf00b10879448cf318abbdc793180df21ab9bb18c9f9dc7748018f08fc203f272a3fab7b644ad2d7e00ff9243f0290828ba1e21bb4fe84a9d85b86905b4b3ddef0004d06eb4b58e823b45fd31aabf2782c6b7a325c0a15532bcb0f454b610e218d4ece49187780dca1a15e55975d1a12cde9fb5064473188a16cf97eea4749fd8524441d53b097f90d3f2f3f5bbb89ab4e621d519c730d0682037bc3e7330f933b2a5c080f0a111c8350dc2dbaaf2590311e83fe259f79ddc60e008b55c6e8fa0d7e4aad0a9fb321810201c05b7ca0d36c60603c2a9b77c896ba2760dd601fdaf07dca1839aeaf40a8d84709544c1db8dcb5843a7dfe659572a5feba93de123284a97dcb69968724a3a2b50f3cd96129258bec2c12c8c433dbd8ca28283561877a6e7f76061e901485cd2e126b0020d7617cc7a620021c6a5387e0d4bbdfc0d1a9c85d1a47b357544f05c461316e0485455038b02cc23420aec60e4b60235e86e01dfb70438ddac525517027bbd621a560246c19ec7776d9203e3a81b49ab2a86c59c10fa5ae1be833c131c280296e7f5c5efd7f9a00758b84307347a131fdcc72b6a920fa63c7ef3700bc0a15c092e421a8f50f18108805d0127b62e27a384183582ce65c7eb2e758c7865579d1e93a3685f4887a11b10e41f89e580390e8d5a3ef3f2c1857f27435bf8b3668a8c4e7a328aacf218959b508faf74e2b04e5dd4790421d9b5caacc6db381f471c2f2957e226b243f393522090901eb5cf786f2751ab282ecf8b1514ac46809726c7575767aa19e182ea46b5869a46882ef31db22e9afb0a2f786803efa67302ea2c21a11904a9a9f227fef042888c0ceee8efd50b0889298458f30240da27535a531f8b96b4199a2c8cb4e211d51518e1872b3722d3b0bd6a3df75513454fd16308e845479aa25b278e28d1d447f6903b4d765083c0f8c90bcd671df7dda9276340b17d9344bcc6bc97864466d942628951a5c0a8fe2cf5084a332447bf54509383217e63e71739d4be3e966e90d1ded3cd4126fce4bd7ad92bb23b24a3b80ddf506679790c8594a2e6d9940c1681d762235cadbab1d9b8c8ba7c9bf19c467d3078c69e4f23b4bf490f041456400caa31f4bc3abb68935e123a9eab0a06c12373cf99366b4af5149b672f5f7909430f4d5b9369ff616afa0c76cabca39f313a3748d626f5974665e7d824b690fe50c543febd2234ee5b17a5b9422b78636cba3c9819009b0d3046857b90c6ce2f3e26a6e39afba74449922c09922521b924252b4b664c03efad18594985825e4a4828d48377f8923e07caeae8968f12bd66a34165fdea133249a7b47f317d44d0da003ae71bbe2834091f26015029cab32fc13782406020d40b795508dec08935b74db41b1ddabb2a63ac92c39a4d0521c97db034e67c2e0efb085dd6f96103f193ba2f1f88c13c2c93c3bb56701c5823c73ad6c626c300af79d141764f672e431ba370a34b17136b299c77d20eed43a64390de79d8490535198fa7336252cd0e093c2e7dc0709bc206bb18f98579fd83602a086cf5063743f4b094f5a13b71a26845f0009d0fa7ef9a0786e710387884b51bd773b60de1dbc568b816dd14abb85d5058c60058190fa7ee8bc252c81ab0b2d7769c7f963599145add2a6ff42393eb0f04dcc17a832187a9b6b792da5b18e0cc089fd7b620ce99686c54f40875128360d087973178b4b420bed94dd53d5d883e9b73be80b8cb067992612cd7075f152ac45ce3c1697a87ef4b85a8f2ccda3473d2dcc106a7d733ce26ab0642692589150d7218f8cd380990bfc925523d5d84f4532f91b19f74eed9beffb23551886ed684600682340768beeb50367ea6d4d2abeff46841e90e6a7fd39c64e186a011dd2014f34d7014c496fe29d10f1065f7309c4aa585d1e787ad57d2edbbdbc2032d0c068aed7ead03be074e0b5789bc9499bf834c1fc21f275211eb12694ed7292f3cdb69780c66860cf8806168aa1fdd3945f77dacaf2e398da4cb2a359a31bba590537762cfea9791b0ef384276611c5e8132c56835830712e0729583b8c602620a7daed7f13b20a6e6a3d8c2c77347b5bc232e6504182694c7e819250eed0ca366c4e5e46496095089ca4e8960fabbffa058112579b288e9b71c88b4194f1a79f8c24b72c9cb2744cb7dece4e22b034672b7086eee4bed78885186b33ce65c2ba24a098ded368ecb2c3bffb1335b76b2eb20ef35363099599c2a54d5dbe705fe86487503090d595fcfbcdf55cc10d2a07f44f834b620501a0b82b9b6812e3bbd71e74373da393f6e7ff39c7261b684e8785e1dd6f8b304dddd1965b2936ce0f21ef8f16aa654f31705837601ed527f8e8ad1bfc301ec25a5c461f95421b1ca49316565134b7288a68766c96c995c0d656f84c5da2490c59c3909694e658b914d0f5324e7c4c76b313d7d19ce110f684ec74ccfd05221f303c146be5ea2f3300bc83246a04b53728880ad54a0e03865da9791f1b0b2f86f23a3c7668f39e9a6e7782de88d8dba23ffab35bc4e952bda84e9d2cd2b46531cf5e966605068806880c800d100b1411103604785d6f6b57052a56ce1a0a3c141034203448344dec0098588746ccc70a9b961aa8d414a6a9b51419205002343896e7b84bafb780e734207fc71efdd774dba351f2577e09a9c4780af54c7896bb35868317d21b2f1ee9b50a699b3884e75bca1052020efdcbd658a568c446949c5ed1af85e2fc36bdaf1efee8537cb47736f5e62a5be21ba3b4dbb20c866456c5c98d08e60e10f815a6c97d437374bdb2a0ecc0ec44a49327467366f86f0a2a47d3c867ea7783e83f3e22266b2470ec3fce6c5ce57e617a0e8d93da18ff5e34806fab31f189d72b9324df055e455111c6a189458a51cffe445740e1bc93a8daeb93b411727b228a81ca26bb8ee049d66b4c5503838586ba0523d59199df44e50b06a75fffee2e520950c8b8a88842fc1fc60ed8e7e0391763413f090d36316a8a12308ff6342d7510e0c1314646567cb76e8925da9dfc9d5095a2b8c81348324dcc099c1b1e8041a10a9892ebcbf08e35d9e4580b14c92cc51d9993ae79a70e2d82426419c2874d5ad59f3259d69adde7e8567d0d6ab8b29f040edbfecf8de2286ffd2e631602fdf24e5ad05202e2d54dd0ccdac21bd552dc39d6b19383a9889201180d0418607a09add88b480b8c4c9b00998b40ca9b2089b8b92295d98e85212bf5a49fab937156a09ffa3a2621c7964f787e616c2637ebd5de85bba7fc472c0c00dfd84dc2fd84978739bb4d59b503b3a9f807e4ad7441b32cca2832df56314c883ec8e5261bea592f5b6bb9ad453dd96b6c57a4c418d42dd22b83b2c4e7a01a65502a3633a1afaaa71a5f891e74f703ec3ef83d8e1355c1494afe652b590d092a09dd632d9a068fef8ce08f52ef1ec5f502bc2258ba3ea1c4120c3094bc061a1e7405d1d5bff7d564164d11753259d730159e8d28c4901cac3378810f350a8184608d32c258b8047be7bb6029e04b935800ffa9e02b64b33174e62079ec1dbfce13e5e27647dba44bbd41e5ac6e64feb9c07e7d1e7080b0b602134d7dadffe1f1e69e9d73884c2d4d45b331af8b8b34d7e26a9472125b4cdb003aa27a6c59edfe0b480bcfd041b22e22422f0bb10a27ff7706be10673ede7616f763dd633db09463856161d030511d3a552f6a870f8485d7b263bb58d3f419b0225ca4920de27f5ab8a214148a8d2316af2339702dc901e2f8137141054feea5225825dd6c4fc63e90e9d9a5530bb4b8560d876350999555c6f3f79a30ea639fed6265900b1413d6326193a71e9a001f0bcfa70122b740750e08991705aff77b2d31b991793a2e3960fbc6e28de89e7da2f01d9cba9ad161f292ae46baa0065adce878175149a548c78172ede8f740eea3f98425c86640b51aa9694f9c3be10c6da8aa8ba21055702577964faaf10f9e020c230d691883806f69571c2929d93e36d51ce53ce7c7df737013f4e682586b4e3565805fd17d1a8a22d88803bd614ad767c329af07c993af633d4fe4e1fe361be3c727ce86c7101d6ac2355fa554e9b69131c48ec603572c54b789e21a21bbf179a120c0962c9be0bed8e89722a63b0372f1517cea166befd21ea43d0e9f46e361082fd6528afecb2d04064acd4ce43667793ff6a7602e6d2562a8adcf79d25562ea14781da30016900d4f51259ba5ba9472d416c7bdc66baa6d446db31366a7f79932407116a4e5f44cbf395afacc8a2ebec46fb6004df151133cf2e2461da42633384c5c3be5c42f5384215b407d0d26fe690ba83bcb41de81239dd8014a0255be2fe37c28ebf63a3a100edd1d46e4ac47801dcc45cafc2b9b6a1cc0485ed702d97d6c166b614b90983e0c07dead43b27a6e5b7f22c296aff999b53c8de74502d3c148684f5c7499e9f274b4936811acd6bff2c3533105f7082ba400f6ed05328e6ac9296761c16b3720f4b0527d000a06877aa761a8e2ed94463e4932c62e3c7fba1b6ea4f1f6c70f3dc3e1f7212bf3164038254af8aa77883993ed9d47b0c2a1339037e4439b0a8b48ae1885bfcd81e55b57b4904a64cbf8aac2462602d9c47767a5d1900829fd120d8c9437de65a07ba2d678302d41cf3a48d4083ed83b58fe9039530c66f7a74d27a9dedefceb4bc6c208619344929a28b76c89acf4ae4738062b73d54dda966cd90d40da7c81ae0bb7a0856319a1259ae49c21607ba7a0b64c1ac83542c067bc8947494390e2b245812c5542d8a3a1292df1f109b66704bc2405d89beeb15d03afd53029e182316c47f81d20a7960d08a9784009b2e58da08e5c955805db7c601853ff1b837e16f234561dca4b4127f650f0c177f879c3b0a0ca44db2cbc42b2430bef251e46ae59a61ed47778eb6f4add5732ffc8b2cbffe6900e1616549a98c51ac5dadd2f85d80b74bf744032dbc235b974e31ea6a7d5d5c93d083f9056ef33aede9134393c6eb0ea5505492b760971cebc7b65e79068c0ab02f7613f01c66745a6fa65c00c84e808a9086d437daf9bb4bfacee9d38f9f110178d4dab204240bdaa7eafdef170912084494bee789551a5f1a087d0b73f40fec34ed856f7d8f94ecd36f861dc6080d2a898123096d439fff3d4403e37b56937dcef563fe939ba06fc15fe58253a92dd8cda3e157f8259c3b1fe8c1dc599d14950cc56623ec4171779af6e25fbcdcdb7e30184cd444647de69f4c2e3932a5b75ed380abaa8d2454bcf63eb796a83199dfcc8f146e1262f3d925f2fbca73aaedcb437156287734fe217444fd3a1348d182c2d47c5a099bf23851667a25af909904e6a2d8ea8df9f20aaddb71a0e0eff55e062c69b065fd9de898b0f39a20735ecb20e6b4e6ead8b07b08650ca0d8c504d08b73b5b0760c397864d3e76188fe2a6eea2288b27ed02de537e888257bfd9733dfcafb48ba706e06c1165ab2980bf47e0bd1fde44593e67e97bcd8f4a678be573439e4e70b2ad19f060b9a4c4682efc48b1d98ec1a175bb17acbf6b9c8bcbda9a5ef7d442b12affd340c8dcee6114d4701e2bca6ca447a1dea36708dafb52f9f42d7a7e25bbce873432752c046d8c8f98bd4a1178f4958a036c0d09c9f1f1213ccae729db6af74ef9bafc4d030c68952fcd034892a0178dd0d715c45d710dba4c52de1f0dff5f3dd268dd84b2b2a8f4ebca0a7b08efae4ff7a0f4795c199a23cb7f41ab04c603bd49d516b18691533d5aa3fa7c056d24cb7b4e27753be4ee38d7ebc607d8f4ba14ce455cf0bdd7e1a58974a86976e93cb213a92838ea1367ab9076c18220901c8cbfb6174840a0a22638b71bd4bb7377001fe5c01e7670dbf68f7fb530203e9bed1959859b4ab9c1f8d21a3dd7f293f2ad02cd42063f7ad424dfbdc6241750e2b7faa48269ad663a52b5c65352b8f55f01b34b6737b0b8541c96605e795395a27aea8dff3d1bfca0bbee71f061c01e5f637dc3e1001dda6fdd5a2a317adf990b461fd2369e42fd30544b7c04a5674edd5b77b4d4d28fb0f7ffef3a0ed432989e4b2114e59ca49df5f6385bebf6891764b1fc9826524734050ff93e1ac94d5b0ab1c3715129932239f4b40611b544ff717ae190c75607705f3b07d557b17e81bfdc57d8962d21be7c195d7152c31c4deeb0beb9910fee98085f229437b55c95db23ed9dd1a9c68c24eb4f6e565fbc3e1692a18e1e024ec7085ebe6a03e7bbd032da4860d46ff4a73877fd0c0fba6c1aad5fdbe31f05163e2ba873a4f5d5f373d2fef0f8cd57b2583860f8380b7129386bfb24d73444e5020f51daaed9f83c05dd473233003ffd6e3072092b8857d597b89443b9317ded3eb2ff94232e0eceabbcaeb92f3bed67a090915ca7019a5db8f6a597a2f03a4d058c2e8b2718c26a2e6e8f889dd6d195f522f8e2ba30f09a29b8f6478d8ac89874f77450f489aeaf5640f787840b3021ff951beeabfd6587eabcf070830e1b753c78e16b4818af3e2b27f134e6a38d9d540a9df166cd18b0bbc439e6f43a1cdf280091ed74f7d6807b9a6f06fd4d2138e7f0573d14e3a15195809793e7a17a9869d6b9139ddc3f1a1a3bcae2df48c4accd6cf144a77d3e7119107160e098cf424403e253144e248b4e1cb6f73a69f57b3b13089fb4a30416830b73d89bb37f35c2d535cabcef49b4955e5cc1a951e60badd7a4208e266c544b68ed114b8cd912e95418616e1079ed54626375b56a2eb2ea6fc6eb97075c4a82b79bb09ba8f55fb5e3584d9a77f21b076d0456c471909a767cf01798b3f074e8b2ef9191d5883b718b1254a266c66b6ac527ae7d139fff41c90630e7c01fca7f0cf53b0c21c3ebf74969ebd9c072a23ed6e4c81798838d6e0877c25558c5da6d66a1013b916b823bcab82ed907f9148d720dd650f19f89a1b37adb613c37c1b7620ecb552c5fd6890e09a9ea3c12aea8e2dd56dadf50a341f442d1b5cde88c322126f06e1fd47c072e0686f9f3d52d40550234bc77b1e326fa5b1a867ef94046c102fd7db6e3834bfc39c12badebe932936f98b739c33143bf65a47662c114d7880653a8dc2ba6e02f6f6d50b511cb407ad7402f92f9c39ae57dfab82a2da3e60902cbf1bccedf1c5baf762bf06220d2829ecea0da901e4f72dc121bbe9daa408f14e810c4920aa066043da7001470529bca842127d578195587a3bc858ae14ebea6c38ef6932e754cec817a19435d115bf22f5282e50fedc87d56cf63476fdea7acb7dec04d32ed3b989dc76787b1fbeefb653659479b5a3e441225b64321bfb22d1c71110265c6b2474fc42233cb2f67f76495b1a334c29318ef03bcd0f3a921915f49d7850c0ca5eba21c883b3e512b6da8604d9899256d3531e027c8b91c1ada4a4ede0a33431aca62f442d14566d095103612b29bbcf9d814570d2f008c4715034addc74e0c06bac242fff1cd90d18866f9d3c7cb57e87fcb36c3de23b0e371c578cc442f3a1b1451bbcdb6c472f7d609f60d07ecca7a163ee192f94530996107e2d9006beb0657567805c33268702be38d05aef98dd29f0e901c424d5e284910e49345382e6855fe2bccab8329ca0a3738f7b8b30737a9300ba419e43d7ad5970ed9a0a9a24bda73a0652149843cea6e917c795cb47569300900b41c75ae84fe85165433041da1821ba571a84b67620ff9251abe6ca62d7c429704799484db2a9f43c7a9c21978291eb8250524568550742f2438f9f772de6eafb70d86357ffeb87f7f40d5454f2e286ba70ba2b21e9c6b659d6cad98f679dd5fa179e1c24f92b5322e3e8aa87fe2cef057febd8bcb2dd5a2c54419083e8668c1001a17ac0eff8496a563088a7192ba980e590a6b68f7a9d78d082736eefd6749e0bfeb870c997a2db0160e139ce3a23ede028808ede7e52e98cb5cd0338762351596be088b2e6b9960e10f1a7e7ee91fb3f0120db6d52cec670156e2469362c8486a6dfb68e9b316a7e69220f7ba2106a0673b166fed0a69b3d721eff3129a404f82b7663491e009f951d36e736f5ef79ffd008d02e81a94d97ed41a02df44c746533b5016da660f68922b5eb186e016c3daabb6d47d872f89a253c28d86279443f0eccf238ee29f5a83c7295a9dc9b259b629936b3464a061b6ef9420727b57c24981f632ca4e2fd5388ffbc2d2f6cfb3c43eb4d1fc2b28a20ac31ac47a4385671308965fcafb8396399faa418ec5883961349e340dcf427b53a042bf669c646601d2be315eff9f48553c46b598dba3c93e7582fbcab22073d148f98a7152e80d7602432916ad64f97dfa5fdc3cfd0b30adcc1de61a39f7d78dc24493405b731772bdf91ad58bb2012c918dc546865d1b94ca75145808ec5fb371d297e5f92ef4cf478a9b8671b50aefe4330b48e6bb8f5500ab610290be2b1016cc73a3373e2ff48c95510b361f9024f13251dc0384e13488373e7b8ce7de7fd483089a9f4fe085c0b4af5fb348a0fce88fc1e87a35108387004672352cdf2650d202c753fd8bb9a73ed0c6f9c04aa9b1f2267611e9d604f8b0f47cd443f8f249fd2066f28447c843eee268613900c3471232e5869b0656f3da73fd9f65a1a23caab29aaa696331f5848b7380994ba52e114842c75bff4d38b5d01d1c28e30f120d09a1431f0469384c0218a150ac9b1cced34cdda380dda2b5348a0dcc21d0d6a9f64c8a619bb93b5c8b2bded75e67932ac52c9cf53dae3f7531f6b4b4379ac0fd55c64dcbeb3255007da5b186b75578e47a89924e9098fd0104e25a26e0939c60629a5e83676044321071887fbb578261ef123ab00841c3d6005d1b0786072dbfd303571d168119fc5f99fc1bb22662f42b514c1d97e3589fe078fd118ac420b4c97c991168da29d1a263419a5a9cbaf84f440dbda029debf5bdebfe325287ee6a4ffb53f82686cac557ed1333ef862fe2752abd79ecb3c67361fd70ef997ac57d313851bd71e2e3f23488b3d5796349d31bc22a2120d4e1ffaae8bd72999e1b0c70a013feb36c50f7063dcac2a98c72a4fcbda0cecfecc7e92189c94e8d1a66a63fad3046635d97910bcdfec9169eaae26e231bcf2506e4e2ee1916512efd272c4df5020564168eb1537a60eb757fc9cacb49a01e248524781dc7ec8ebac1eeb0cb6e4e197afd3d046a80bb2d1045b2f69fe8a9c0943c9a4436903c5d73b53e18527f3fc253a887d08f3c7eaca4e70f2d7682a27b8c055f841b6477a1c564b7fdca6549d5ebe13581d1ed8fe3b6a01078f67dd13aca7b0eab5685c17bf53e7ecb189be00ac7129448e893754c4d0ef410dc3d0ca46820bc0f5d7c86bc7046b9b15582476d3546067a31f58afc364c5f46db80c1dcb68ac57854c99c092ac14217369c2e5a6ce18031168e9ac0b5a35c396f96a6c63e2dd92a0b04f0e0c5821ca5be95c74307bb4867e34c26f6d0500eb4d6f6d4ca44b2b050f9433475cf80f61d8bc6feccfa9d3f2a052fd52feb8bc16a92fa50b62058d4211d41a8562382937efb208b57c88ab9d022952def738496a9a770b0c22f3fc9ed82f3ca48fd0539de87f1678c6ecbc9fd10c56f1d6c18421391ac51552b0fc722a66945704184fdfa27044effbc28ab2985be3d9962365ab06a020706380f2290ef07bf1b1088b8d0a669e81db8f64c04ad896e2e69bfe25a795e28015557475cd3c44b3870107d67d96ac29c4599557c9c1c7f931b299725a4b6daf3eaf6d5230872c32a4e0d8f475b3226902ba1d20f222a04e8f2ab3d388ab7ef5598dea71881ada3b5da526cc1db79800a2793c4f39ae93cc9fecdbfab0d86e5e73f2a19fc0416ab8f21d4341662cfe81dfbec943a864bb3771cc4685fe7e30fab3ef85991f010af70e8b4f14e975dc61d09fe029b3d4b4f0f15325ca48b18a842c592a24bcf8bc73c633b8e7832eba39818b2411a24ac39a520e975a6e78d9320139997da779d1d5a673ae38988a1d50b08278444949bcb702f0477649a75df6201b24588125bbc78e26255a736ed4290cfbd38654f04335a531d55b1653aae77d4d532408cba936353d7701c867dd96ade34628d091d149804c78410cf7f8f756368c460390a78f2df0859bc893a2b02b31ee61abfcd047d49090c684c960f0a345918aa704aa20a37425e68d1a207dbee46494a2ba034c9c704dbde30d1cad1ba471b2c394f5a8e9c9a68c25190a39b24b6e8a43b61168c81362c8d11173c6bdc743c85bc55a34c2306a385f706ea77209426cd5c644465ae76c9941165c1a89dd4034f6790dd213e73e690c7d95b65a3b89398d7d5a69260b21d0460496f203d520689df88eef3cf94d163c57a2c44f81c49d41b67d062c2a1049e859e2cb6f1476cfbb4f36d88d57dceacfb8f09d0210c624ed5f9087de3234b2828159e6ddc47e610c291cdc9aa4b42c53a4b69df8be46384239bc937770ef52c4b05421b1c939db25d0d21424ad61c3d6dc42e2f7cc05bb1e844518c50073a15be1943feebc9f7cf1f8b9a6bbf8c4321b9f55d21bcb0193e78d7e502bfe5d46b4f898778b7ad7708403568eb62355530fa00500e065329a0b01ebf25769b5ff99d6a0c57b00716156c0d62ce13c4b861e5fd52f20020d975bfd0f8e74020c0d720743a3da17185db3f3d98cac08bf83e7cf1f4d35e8ab698aff4c8724731bc063eb096a2ead42f3b62eff3ce454a5df01b55deb952f0bb9af48f7d08c363a1774d866b998c0c01f3a348ff7078a919308f041b1d007fdd5574c6d4e30209b319ebbb37c651f27c9612fa88af380765c682877e81bd215a263a96f235e93a288c687360fb5ac7aa1aabe043af16a838795f4dd1c974c01568cfcd91b33d309e99249d32b87166a047dd77272e9011362afbfd41013bf601870b81fad091d92954b96032f69d6b58c65cc4a1562298994385e1c2f31e4c829bab4ba175405302e7d0c6fff613fd55a5d889437d618bb084771e57a0c4c1b8f4e45676aee629dcef90c933955c0c78faad310435a5f992645f16b90cc48ea1b5c3a924ac18a01ecc1d2d3bb4fcf24fe3080c960787806b29b9341ebf3cb89c6599d61c884f4a6206bbb148a884c103a99320fa2f93b9cd2c20e0477c15af2627c0b8735bd08b0aa6e31fd7f0cd57f196b50711c75c0a170b2b0b5271241558beabf9d92ed05169151ea543215c8e468826601b32e6c7ad7daa34014506a2c078ae43ca1706ff943857a87855cb542d165d3c13978d0a5eb3ee42346682aaae7b757dd2869de980d3f717350a0be3e2490babbbfad53e367a05af7b49fe6d6dcbfaae0e9d28bb1645d8a1eb1708c82c5157bc5f3aecd0f197d2ddef052f1063ce5bad643b5ced4460b9bbeeb71a8a87853a79e1867e201f222931a27efa5310040532dbad5a2769767740653b1a90908a02ab2f08d2cc5d81fc00cf19213d6141f725f26c26967f720da91f79d14149a65c0ef579fd7e531c1e8d7278285ea5d5f4ef670370455bc7df681499eb7f9f0e1c96348c69d8c58b2dead1eec2bbe6692ab7ebf9afb291824842b84c7112d95b532e96f67c192cd300415121f45c75e4fb7685fca604dc85d551bdb440856472cabda1371d775f61b1d760cbbb42a372e4daac6f212e2c0b9eeacdac3dd1d0b0ea3b5b10868cf2d543a6bc30fb7614e12cb2e0f51983aee600e8d2aa0a032df875782beac5fb134c4369ce807aa68e6e640f8e0c3e1f93d5fce5b169829317bd632763fae7e475db9b700e717070bdd62d79a9dd3a1d80397b0fd24f54aada4294be6e5b6db86f1d44b04e2d55cdde67dfc29d3b198bd70327f0b7f8d0bd28b3f4df3a00da5d7aa3505dd02dccabb7c997b2b2131d8a5317a47dd1591cf2d368e09df6ac464b7014f68b682d4edcbce5b8e740c4a59536dfdbb725c9e9ab8af4675539d7c3fd311924b1674fb322d91bb1677f0118f864bd287ef036f558e09bf75832737d010f14b401fc2ae11a6de169215444e9816b82ad6c1f58201ae9d798c5189e6fb3000e5fceb8b5021b9ed0645b331511f362dd38baa56bdf969e94fe75d285ad5df18199d0606b14c9c220cfee709cb43c8cb91ffba95f3efa62d9e482b9cdac0f21367b581384e44429b7b2a0682dc36aa9ca94600a4007de806d9eb8f179b446f385ebf5b9b32b908ae1292ea1d82fb002205c5ad24c1334e653f5fc9e80d53a2a27f628f057584e2b258b2fb2f0c1b2088fc21655c1072def9ec26543e8dc1637c3ac2dbc4cb505592caf29663c363badf9eb2188006c1addf73ef11b869128f4901f76a5653af0b290a5d0b12226a80909521592d4964a2f97356ca38b03b9ebe6489a7c4afb02aeac3dbfced78d092d614a2fce6f3d6f2dbec2ac7a75b724a46ec52c0ba5a6accdaebbbad7296be2e03c49a49662ba3252d614ba94a90bb87772a3c3ab007ff9c672b2932ba79ab0df0bd21f6633d89caa3640fc34d1c56f3c97151a1cc1964e79620eb701be4fc40578a72fba9a3f2e3cfd67b467fd7156a5d7f1a4b97222d50ac4a48e33ff0be2dc21a65a2a718a96bf5e4455d46ad7372e076f8ef5c0ade181afa668dc552b544511e159cfac8d66a5aa5963e6769b350ef53aa699b5cb17006b981fb98e43bd1cca49ce59f80cfae0dd176b15e32e80a59ada84bccf6ebe94f0270cab7cdf3a117d5c4bbf9aed14e499cc2941be1e4c204d62367448f1b59bbb48e158defc41dca02b4ab1845d287eb5b31502d5f6410a7e355ceae091b5d04b5644d68a1a346c31b11c0b555d44a29444fc9bd008e470816709a901c7fa5bd50af3895f2d2f43310daf888ab65321e1ea82d83783c874dd231630298f6caa4948608bedec0fe46f36512aa8595eaa72e06ea3af66963ffeaad3519d1a40fcf3d57c9bacf77b231592cb8d1850b8dd886310a3321f6adb49e43140c52a4d91da457831af06c3bd9d34d964f872dae270fa88df8bea836c2a4b404343e7388bbaf23f583883e1ccc44fbc63287763de88c2f649c657108e53f9f465b2214f441aec1e8e5175515af6659d3250e40d30c53abd81c6dfcf07e7999e020c48f076b4dcceaf518d8a951a02cb9db4448729c13a8790943bbbca80afa359e9423a772be36543732e5e232123fff78b62e95823304a4fd2b81979b6aed143dec22efe1d72d1a0292aa814ce1676b533bc6c89f9efc03dd5ce4eee1e477703b0723302df43fa6ee4fe09b655973cde203fb05de5324709ee98a3eb5172dad324e6fa3e8e5d1ef3e21d0354b80a375eeecd362a5d4c8eaba314df6fdc2e15e271e11f4dc6e1e8524b3b1782d683b801e455734e757a88c4b4681395dca477779cb00e660c2f33934181f5ef1e34ec70d1baddf0db249d5af68f61b4cc505592d70ee60e5be87f73469537ef7c48a222f89c2792937467df5af1ec2b979f2e05a723fe57fff86b723377e4b0f72990e4a2b879de61173d268a9bf120d2c42573fda0ced86940e622b4dd6ae95f23b435f1bbcf9479ec4ddcec7dfdd0f0fba39da6a5d86e56764c26f82f3b29598b89df5f3b65d81e5a1237b8c659cd850edaa1a0a942bc9b71fb0da7718b9b12119fdb8a080a1ccccbd0faf6e889724447abe8020e6b7b930a20051e207e2ad0832c3ab10e02029684504bb03a767006429cd611c9e8089acb4e1cc2375fa7eb1adf00ad2258350acb69cfe64d1d67605acd3e1105719146c7c44df3ad8e1274af01df2c385d0b6a10ffac6e5ab50653b7b9c94a981a1da06edb0429b3af5e540276ebf600ea368febfd8b6c5d01e5bd71eb004ab7dd7e337c94bc34f80e4c7038906ecb003585b7767d3214692e745b5816174947bdced98bd33670af28ef0b106457cc5df64ce95dd4ede9211b10fab70b2cf52a07ff6502a66a8ad721236505bf5eb89e0e895e6410c4a52a93dd76b3e4af346a325a7b4cb1d90568e3be8353c08d9f03edd5a5099f7a991943aa1c566f37a00fc1413f343b4210a9af2120f90fb71fcbe7d003fa37bfaeab1b999479d233028bde1c5b506c3d17a3e06d11db08aaf411db76254b6afb8638899efe85b66f80b7483fbaccdcd340abf4c5df23712c59fbf9b93140cb9e4d891061f90afc1b8f47e60d6f5cf0051e581f85b79c10ddfdd1b8620d134cb30adfb3e12219ed7f45f917f0ccdd6cbfa066f5e26201ecb503b41b611abc5ecdc91ceeaba1142557ba032516f3b53dd87ba0a38e1b2731c6ba0c3ceeb6bebb720e1963d46e9f6e87c6c4ea0d21b4c0e428b4d8a94569b175b3ef7134fb68150caf6d75ea91c98e161e801484a2061637901045aef041fc89c90e0ac4c6b1d288e06ab17ed2fe64ee2f19cef5820f6b8f8e0e8e9b9399f7449823a925c59d2fd66052e59aeb4133a0fc052dbd3a18b256200f9c63edbc87ad32a387e6cbd4e3e288aa1f972007c8acd78c5c500a7b05755e73c53c787eb566e4f62c95af169485a79ae112980cf82a47a2abec53517524693121c18e2438bc206f8c21ce9da321ebc17025b5ce7e5526dc43b8ca7ca482826eb0f739bd2de0ebdd968258052fd48d5f7ecbd2562626fd62a49879c1546d4a6b7eb0b07c557684f9a4e9f4fe084f9a05dc260182fd43162f242cde9a9f1524a572fc87c402df4c1a458c0fd08c90233bd8fa2b3754354633aaa203ce141435a0b4726d52d48dc40e0a36880b941eb994ae4912c695dd646d323ac79a07fbd7255c91c385acdacdf59f36ebba74165d266805f541ca6f92728e441eeb92de8348271fec637b52d4c42d728edc30a73770df62d38525d5aa7e9ddd5712ab04ce38e597b157be5b5fd6f7de26dcdc2f3d6569eb6fafb4325f1ca627f241b57a2cd9e8b1572877b49d4fcca1cf8542e0819509b0e9635426f57bbc10c92263d0ed1b404ec9e3e14e92575608d08d15f5b4efdc6be0987c4994292ef8a16eed2b53177a7f9ea7903289821842a41ce3daeed0e3ee60932a5a3ca3ccf2f4247dc404c983d7940e39baac20f674573bcff7db86df68740cbe38e5741449b0c6560b6e879121382fc1996821007ad24e026dfb08739202b663a79d59b3670e5dd2c98c1bf4aacd769af815de709f36bf273d7e046a33ca1ddf117421c627dbf4f89f41791353604eb2aa3035c6e45c5c0dc1425e123b7e731014adaa51895ce1a756bfa9b11fb618f9332aa9fd7a836b29de2600a3bd08a7a2e2389d2f656a7a0b7a758fbfc539cd3cec669099a71bd74fb662fa5a1aecdab3c7e769248b1b6d2af16ecf97fdced685265e343a33cd51f3db98d9752f025b1136dc172fce7e55f4ff800144c8c06fba4806ea6b048c50cab27793656029ea8353a441ade8cc4dc09f4ccc513071918b568b3f84526ff27a6c48b10a71b6e5e63e1ec42fc8ae60925689412eb8a3d137a9cb94c62043d9b9762d7dc206d749edd51a38af955c4374d0b317661e64981eaf3d52b731225460bbdf902555e92cca7ced579144a803a712a9dba19283dc2b7658db86754a582967ec32d43ec40e09f9397e26000a1313c37bc98a5f0b8eb3d6e6f5496e192d1b305228e301e999360e88aae9869d8a8dbe2dc8b2a8402cac2e047674214179f833e8fa83b8f0ba75acba89eaff873712445cf08e901f8ff520ee9ceaf9539bdd2ae87afe8ca5d9571530f11e633f37e5d5b41e7dce9920e5d048b9775686aaa391e1f6c35e3f5fd7278a4827d3e14df7b3070cc82f1006676382681e08859417a29a5d6108193715369343e948d88b043aafdbd72731b604d42bd86c27270bdea10c14374ad5373bc811d1ff16c93e54b29a7b25ad1ac0f193e403d57496cd1f68487d0ed0834da3595019929300257036df61bc9dd5483cc828d35c6140a68107f5ae1392e40d6f7d2a36050806c0af0708fd8f66069426a5723309dce6d47a851f075a6d8694390c4735427e20e2081e8ebbccdfa102581ce1df475d3cb57272e39dfa08965a362d0c1d3228c3ea352105037c7e34f5321a709685bd7d10a8e6397d276010a7c51b70e63e7df7f3493d9aeb131aa600e81642885dba397de78c80911da70b5abe2b4afc0c48fbca1870ded7c3d620ec898d1f5c025d84d348f9eca18c8ce197fd6b3ab9a4c059c498a3a8acbbdd264918cb2970c64838bdc58bee6e5a9801469ff30fa893a2a303e445483340134ee189484932c1da5f8934c157c0c5a2a59e322bb6f5fbbd9bca6e9a384b23d0ddc126f1eeec8df8936f99422936cf9b73a966dc05b666252c6e2bf04416b5a19179290517832b0ac8c70168b1ea40e7d50fe1a8a20061fb3545155dc691932fd81e85f25312c48851bfd8b23058d4c9d4e30e6b4f9e5118686728ae9125eb28c101d961e1913a027618e5045f80d2eaba03e775aa8b3bb4102e896c7784c25eab37adf3d9622097e211ec88db40b96d42d6c743e582b68192460a635d6abb9f095e8c0006abec36b8edf3c0d7ee49600874667ad6d642f50854625060d085a0e26b9e068c425176a1f32dd077c486165c14c56248abf138258830b9d0175031640526d1cdc6902cbab6d50953fed82a2d543cf4a888062c5a2801d94a979ca845228526227207b78184f524224d7964e9179ad282f071f1f6a7ddc8fc4f000ca464fd29b9ce99eba89d5aec3c930bf1308f34ce3391fa10982185dc7e8103a2d4d128d19cb4759e29cd2ce9e544d29e1746f1716496cf87e199437b7d2a8cc1d7784a1d4f1ec37cc7c63d01f0428e3535440cbd173b9f03d9299f2fca300140a85bcdb342e588275c11fe630824deed04e4a46307f5d5e62923d1568ae6480a429581b0a691408c304c8b44096c3a58ea5213ee5760dbe9a6f7b0916828d8481bde41696b7f89da450520c25c53f097907d6065a02c34320be561bf1a949b59f0b07065e5a2a2f042e092a69024f6364b95b41719b7de85866eb35d48269b35a8195b746a01453e24913d9b5d225739c364c30b162c0ab9978faa37034100c7b0a7d6e60f1de9d7dd3ecd2d27ba79b30eff998e4216c99f8d5751a63733267928c5fce19b336dc49ea5a0effcf0d87c6e658da47b01e921081754d366ad362f13c9297ac25ee0c3a16c3e61ca0eea7217f1361d36db995af9737897b0a85e267c7a608aad1ddec63e05991548de507583014641e6ab55f4f4afbd6e7de25f89f9febc0b352394142dfeb9dddc8d47a5937631c2b484e7727b5c039333bf25958541c2f082876275e06abc51c5a7ae5f59d98fa909607675bd28ea7491c251bf87834e417fabb46a3f32a31d1c3ae3739bf17c6cf3e73d9665840a938cab9edc006251c229355b3e1c82160b9e52aad61e1b31f4e116b874ad2e331d9f173a6a67e7acfd2e8be6d2c2c7d0dc2fffab5e9b4f8561ac9d6c89fba053d60aeb7f6b8ce2563f168d5bdd641d1d84176dacecd6d54d090fea42d71bb5390cdcf02a87e92cb011b76be4ec181a30f38642e3d23d5b6ad35b8bb7d17f839f2144fa996a634fe0587fda2954e18ebfa7c20d218dafc9ea6623bd619619e1c022ea52a828a37f92e796d4120ffde2a878060b33c52fbf98e5d079d6bf38c5d8a80619ff5ead7f078ac020069282dfd62a662236c8bf973a6345bba35e250a3de0de87fa8a9ff6f96cdf2587d216b4a29497ad6e76956f5af31f570094d5771536ec9a7cba4cad421cd966c267432129d40521bf83aa6f2d3cac990aea57d0775d03574feeea0ffd3ee9836157d92232ed46c8930ae03b6180e2bcb96ebbf689508a65509ea3ee5136d6667e0816cb23ffc971c6b262063d1748dadff9a5ce96ace3b626da3e2fadc7c30ee0df85951d12e30a5eef3a729670e73a00ee68b2dc82391ad6f2fbfd59e3c6e7c5eee3d4a046af25f2f67fa92a81f10f7f28574e3560d1ad9edc3f5e23291a1f491c58c16dbaef774add10f1cdc28e61d8f72b0715c1788ba3bf7e695f0cc9fee616c08081e8af21e21c76ec6870f944515ad7e707ec1023d3779a53ba2f9ace0a484407f926d6c80a01206f62f587435b582734db24c91019297b5662be90a77a515616b45083bfb75f2ac1e1c4afb5be83a8223b0cc6413aec82c4c24fd76f5296a0f1c52f1d0d9528eb2a2bb5921667e7f0d26051eb1fc688550474b4a577ebec2199e3ca5ff3aaa2c59212b1fe40861ee309fb40033af121cc0a0054ab7ab384e58666ea129ef9c5b826cfc7e63a3343145451572bd2eb01f9b220c84e32b87f67e5b39bdcebb9b32dbff27bfeb65b45da7c78fc545f8d16a2c135a23899302139921e0fbb32af575b40b16c17814e41e0e2f9765b84ebeb43f00c6a024aa6155a5d308e59261d322309f34615b4f9c419157f796e2f7f81798299443e3043f04f35bcd1830e0711082850c6df58e84f009cd0f5198dfd7050411064fc7e88dd92dc05d7df5474313a37c90aab3db553451ff4a391b8f7965bca94b69472072106be050f0509d8618041dd6d2f6ac86da7ab02412c650693eec594ef061764540ac818255cb0601c11daa10256a8d6d0185383852e424c9c09e9eea1db40b141b939e9567200c3d592ec76395620f13a8648fd6072e34c931b48bc0efbdd0afeffffc73590ee1fd8f83e6c293d62b3237cffcf187431672b352b4ab87bafdfff1972c8d5802f65b85490c23ad24545c2cba8e02c94061842bb22355504a40cf82167aa29107c77fffb495c9cbe06f6281aea73335495c7bbd23261660b8b3ad80086694c94275859764a43390c79b9f1e5e9e6847406bc3275a5ea4ad695dc15dd95dd15b0ffcfd98af6495dddc6193767af328d2b9b631a7eaa20187eae8209efe780cbdc64e08c0c2f589414e9d8818407a1b2c2181c5833ac92d8c0a0cb879be4e5737c9045e9a2763a2f403263f056af5634b73222fff1952f8481ef0fbdff8b391765551e2fa7db9528022b714348c7dddd75dc5de64404284010241c2ed214d1c2858c6c04342653aa00a101e48a7a5733826c1dc162a68b130e4176e8f961e528cc764215253825de10d8cd87262c53c29630c101e7056e3133c48b56141a39a8c17112a60a87992b4d37c6e8d03ad265055f469eb4a0d2ca32acb4ed45dd2aedffc37bef1025f6cab0843affaff359630cfff745877213431226413067793cecfed9ecb115860a109b9a265d3e82384db9dd7c3c9d30c3e0b56f315252e5f1906c18e946ced6e0358eafedf2ff6fc4fdffff9ffcff2ccbaaa29316f167c0000cc9638518762da400460372c3069cb2d470d2edc89cb991a2240527a5e9ce64ce844b0ef2f3480f2371f8fff7f10d4f207853021862ca20595112d60209d742650b10ae274780a421e13a19a38c1b373288b189316afc81601852e5f16a4ab844184ea709f35db0d80663398360db93ea010676f17ff767f85095b3ee667346029680193fe30b4074f359004b92ac1a58967c0111f3821a1c5568c0b01506cc0ab8501b2101caa4407b4afad123aac6b54346022d0a0c2f341c3fd678f8f46a8c0e1a6874523684d95aa3e445e80611a325173d987c77af296468a92051a901c1ee0e04fb75f7fc39d76a35a51aaed6545b528baa51d5aefebafbe3bb75d76c808444d565d5055583d5892c203ad008d1d5b6e076300cec3946aaee978750087f36fe68230cf1952946b0a080030ccc86251f09a8e1691786480c5331945163c1901d5082438b054c7cdc908a9a61c8d714a91835303c699a6c3b8c7c21223a62238c8d861a929c992f0e03cd32206b06ad49951e39f8c8f908d34186173190669c6025c314bb254c6b488b480b49ab26a3871736e430c5e9ab8a1710d0d8f2c103102267a606b0801a38647a4f378ed4d36d4f6a06a2fdaf7bf143ef72ab3e292842c0a9303638553e786898aa0859fa4224a44207a47aa872e6cc8f2515badc90f521ffdb6a48834b32b5f4a587ca10b0335652c2d4e092a4e365f9823bb2c213a4266ab46260e05f5e402ab221c3960a6a72dcdd3dd47ae1a33861785f49c6a07bce58545857585a77f6ce8549cebbbb560ee3d723cce3fee5610cf17d7f1da17bef0ec484ea8c8ba92d3778299125053444b26cc470c128ccf9892db6e5b954c5c2f0bf06fe2fca57ce88fab1430d4d0c235a6e5c19545a17181862d68c31b383c1ebef39ebb8551e4f0713d6f144ea809ae998d23b2ee0c8f8d22c28803f727ad8687842f585898a8b254e2d80f2f2e20229ece63c65abf2785e5f25a6840d1195a001c93bc0d7ddb1f7f8ffa71e0872ed28be38c4d84231428a5e8cce3d0c04418c75d0aa3cde96d757091dc286884aec807489984089c80e4c70317238d02c153065f9c022a389ca9a1674c092e88628bc4ee4861cb2eba5cb1f972b2e5a5cb6b87871f9c20087165d901c8e356ab06c3c506e2c61018d0e32eca0e2f960ada0c88d314b5560351c0121022a3ec808c142f4040b16282a843f478ea70ea0546083b241668c159226b02bebc2d34d0a212f2dd486a2bec6c0b013052c92e4a901379833287542d4c5ffa328c7bd92e6c8275544743170a3cc2dcb11965516189064a99183099114064cc877cf81c0ce89cc131b98bc0023f12a9881e4056d05435f6ed848bc95fd5f17999cae243a6f35468d178d1c023336d0848472418446a0430d627266b2a8d838b2b2f556bcfec17bddddfde28bab28880f4b1696dc17b4b02a048ea00b3f712c5f8b3e96c7b5ebd797ee9ae856dd798d53525de5791d8e217850795e7f4df2afbd70859829534d62539724f17202c0c16b8b3beb22547b677b528a286d2c7a9446f367234a94f567b29e2bc4f3db99b4f5abf8bed5ae3df7d2da2d30806d9fed4981614a0a0cb42dc548d376c0f6a41409db528a68ed7053ac690dfd6123703c413548691ed168c2bfd1c42d33287734306fca59e5d16052ec4300cdb3ee0b82200882a0be17ac64adfa896c4c839a96d53cbfdd6253fd65ad200856f3fc8f55aae45469bb6b0f74892ae2a6c4a6fa05f2c4e46f5a9e256caabf5a7e1bd710557f314dffbf3aa8ddbbae6f7d30669e7583daabe8fab2a8a3a9826a505fd757839a6ab052aa9dd2c613942ccf9dfd999e17d36148290545f35c218261386a1b1d2bc3b07c1d668f6a8fa56f1cd5c2faf6a0ba3bd57e1ed7b1d283bad3c2cbda63f93b975e954755c2c6257c57db94df16cbb3839383edafc32b86a5ebbfd70c55607d31d6deffe3fb8d35e7c9eb02533246f1a6a6c07777771c6fa293e5f645f928596bce27447d70029593e22542b2a29413b02461614714ac2bb817ba6a0d2b279d170b4b8c6c51a221ba2019a32448101ecc541a5f2faafc98914256142c9e092db6da05930503060b4c6e4e5c541a1608cf4ad59816b0a89aac7af89cbfa6beaabeb2be725fbaafdd17987720de1745f781bf0c8237c2b0d1103622c24648da0cf8e121bb9c2d4ee16ae7556dc9ba5bbcc8a2e484e147842b089249c2646c641679f07b92fb8fc912af986348a630ce9e06b06e5e464460a2b4aa941e308cb102254b0614212b70d2418d22ab2b607070c2c970e149d251d5932b5d40722b7cba1470691203869432355e90f01aa38a5b19394055f5052703971c65c80ae503480bdbb9df7b6f8893f04fe960773146935579bc9c6e67020d989089309a779024aae0197509fb40d65aa16a504a98bcd74225598952066ac80d12eec40909578d3560c43421e175084aeb7ac15ee4478dd515345f5e3466b0a0c2c0bd30a307150a4e543144dd108940d908b98bff5fceb85be5f1989e705033dc94c655edf8e48c6f7db11d33dd30d2b2beab3b8435844584858455c352c2c2bdcfffcbb0da39ae430fdaf0a0a8a0aebc125fa60840932a538e1413afed9eb49d0c6d97723203b4a12e288de8896cd5850e89ca0c2849496c3092e420f14484e0a8dcd0a2215742b74bf2d6c753e5f1a04cf898fa1998afbbe725329d8b1960e7c2141c6c88496a41155a9a410042a06489e129cd0a495330f89ac18bedca172341d6ac5921484e061fb41976e4a0d243cf87eff24107bcb137e7875103ff7f9ff399aa3f93f567726774336d71d7e29b26ead3d060bba81a2235486a6a6a94d4e05cf8de45adf2784ab80f5c34d5a1b75337e47b4936293674b6aaaaa90d18b3248ad41219ac76a8f1514426c9982eaa231937323bd0182768b978a2e6c71119693e301406a456038896156cd553a5719d8688491358557f349359dd3e24985e008239cbe3e18c69ce36cbe3fdffff93ff2fbe051d04c71ceea4e3207105c19c0ee77618fb0bd9150f3cd18244470f5f392f61485aa0c1a4f3120308ad2a51295d3949cafeffffff65e4ff7b0ec34ff64664ff81042914c0e068b2848608cd12189eb18712212f284b32bebec9cb44d39793efa423ea041a938d8623126fc30e27b7262c980175c6a90bc729ecefbdffffb90b0e41104781297d57c644033003182b56a07e50d9d1030b7a7ae820b2440a4dc80e6ae89582236ca43be4d238f13128581f104c8384d3d4701aa5d9970f78d8a0e8bc0c81052821274a345cc00093828b91814d1398149ad21a1c74881f64e0e73c0582a36efceedd22b485b6c508c458acff7f7540359e7b7871084ff8e05145b30a622606123fd50218424dae6831a36b4115310b8982252d575a5396e8b0f515b9c588f10258558ec49bb191a302008e9c6e90be0f52f0063861273752564ce13bf12f28e7e14be38469d72d6f71775772a324bc5507480dab0af33dfdc2214d0e19239b36097c07417b648fa2ec110fa19741cc068c72117fdea535c4a5763c41adb54716a9daa86a35b523a50de1324539c21d4dbc89a2eeb8c6f8f1e3c72f62fc415b2a9a2ab0a621b54774848eb63fd3e7051fc231cca1b6fa67268bba65a6a8cf0b6421d654a73ce98be5f94136246ad7a158fedeb164ad1f6a5b62d35a23abf1536d620ab535a223ac0e2deeb768adbddae2306e3fb5792230bd51a63f0158c5e6058a90208870811318eb10636c646dfbb462b5fa6a6b64936c15c710428b74444788da92fac4d1a145da56637de2604c92daf342d38aa3c9a2eef78d1f5b6b447b5ed7d3dbda6e774693342dd2fe76f8d6daa3300cc317f5875ae72351c7cc1cd3b12c8e5934ed11ed895d6de35060b627a65b8b3c9b9164050b4018d813d3adc5e7c2a0b2aaa6ec51ac7c6d5362bd6345a0084005ab5f75e735463113b3b66b7b648f7ea4c0d5a21996d41e8116c91e51231925000dee79d813e18120b8e5d5cb41ed58eb0b6aadb92a17d717659374fbdb6116710d71e9c6b359f5aa5cae714e776dd26b1c4d6a1bfde5055288a30937fffdfdfd3dfc770d562f8ac1ca25d3278b13db5019754a29a5bb6a5aa200cbdf5f9e257cb19b9cf7aadb58d7f271dd7a22dad07e6c85b6d7dfa0500d81b5762b34b49dd45e4d416e7f2d4d5b4b11600001c72975aaeb16fdbaa9b9ba4547bc06bd3cab97675385df8c2160f33cab2e8760087a1ee8607ef72fbded9a3e352b57dd1a4fe432c73c318e79e21b93344f3266da9821a8474ae9d5e0088eda831a8ede7628db13d3ad8575a8d2b7ed89e9d6e22c61dfcf4165554db916cb9f7ddf761d802b82eb6fe6aec1cac5a5c31bd1ab21bcd6ca659e2c3c5401ead78ec17bb9aaee7ee5a23d7e43412061aa506857ed513e652ae08af425bec4a16a085a734049e0d307b201d540d0dda1b6c0bbb5b5ab762887023514ae1a8807108f9a03e2110a8501a202aae9dc7d35906d36dbaa21325873403c806a0f4465436c795c636cad0e924e924e2da4e3892f75bcaa718d85f6e6abeef855e5718d31e9f73e50cdb39452a8bae4690335e1df16ffbe18eb5a2b5013c5fa04027adaaf417cedd720763544b69802f1d0311a42924de493934c35442549265a9e643501630d9474c338079444473c908d62aac710b205aa8dba02d576d5f835ae1863f3ac98c43a67695ae9636b02f1004aa23d4f4f124cc768bb8e95a74ed2f69ac350db75ceb222dc66795ce7ac9c95b368a8e97802ef9cc1dc664590466e739b8736faac5b42bb9ae1a847138807ed09c71084b2b5b03b93680bc417889dadc513d3ed1170cb994626115409595553e199c1b66bd2c88a20992c8f6bd28834228db66b201e5e03b1db4adae70559fbf5495e5d70c504c403884712c9644432d148a6ed403cbc56b7f6b9c26b5edbe1b9c26b5b3507c42304aa01f1d0b16daf002a18e9016ce0d9cc7a20b4045c5f7d6fc636eb6f3c817568aab8e2768dbd6a9d4b055c79f6b935494d42996a122c1fc525fbab5ea048c70a4543113827acaebfa486c0da6bd7d08ad0225ca044119a3e75c7354ec941e5710d42dd715dbdd0defa369ac66ad5f56bacd66ada3a019b1ac325a9435aba766bafd5b72ef9b052269bab5a59b55e6d6b7a606f48afec8ad722bc66e155edbeaa089c13802084f4dfb63c4bd8567b379a965f4886afef93a53a364ac0eefa54e3d7984555111b43a821b2a6675db2a97e6cb1fe28b6d46aabbf9afa353e7d3c2aef6a3b7dcf5f1c3535c391d2d1668ce9510578d22de67185188ea0eff716f6c11c0ddbd1af2bc26bb0c5ef6afaab226696e72bcad5bd7c67a4fe92032058319a11a83b23d49d4f8bb9888eb8d1150787cc74e7a7d5c6c762ecd54814899a9870bbea4a13752512eb2d63ac6f455e6fb8ed26882aa06d730425e4a73ffcc5b468ab0995a8d66efe68950889bee846b5283cb17956a35d3569aaa03a7fa7b85f7f55c4674db567b3165522b2a45facb4294f4fb73fdacc8af0402f472dfa904594e6d98a59366b11787dfb54511168d6a26b44820977ca759e2a2a7a6a4491a8526dbbce534545601981cfc757ccc0c40858111ca83cee79aaa888f6b8068bcc15b315b34b2b0a8d8a76029881ed1705f3da557b567b34cb98721512e98eeef20a9aa33bd9926c29c7265b4a41a625c35d199349956e5504ce89fa3936d9920c27d3baf4de5ade2c5e3c81aa2db537fab451aee4b7cae361a86bbd555f19ae86b6e21c9bec5655a9a664372c8bdad58639595495454ded0fcd9c5cce96d79bd74806f2c3e2477eb8ca6e4fd7e6d86a08aa432dbb8532a65ab195e146196e531d9a55db5aabb631cf1ca55ae9addeb8d2bd39b66f8b661b255bcad9465333d72a6e2a5ba23df96ad10be7b672b2a50c9a19ca0b344f9cdbcab578d10696a1765eb2a5ec4a51dbb56c89ea13e7f6eb9b93a3b4cf2bb45f9faeb45de3943959395775e7b56c49b6245ba2b96d696e677daea0b9150fae10c350637183394a3936d95228c3c996ae0d003cd4acceeeac97ed3a77b68f8f4fd756e8e363bb6c97edf2284c5f8deef7f1f1112102d575797d355bab0f8ef6ec8df62c2e5990600209ea8eeb5cedce767dce539a437d28bda123cd31553ca566a5d4c76ab18b046b77b43e676e75d6cb8a566744f4d1ac6e48b437e337544374fd37b45f9f1f6dbfb6b6d7f6a6c5fad41bca011090c0891c810320c855577555577560fbac576777f5666aebd555344febb5ab35cf15a235451c62ec3ed7561d09763ee649de982739d33ba48fd7e77fb16e89a68a1ceaef8a79edb36e99b1f0c6b2efb7618bcb365b8bdb13d3ed9f7238a8129ab2aaa63e6a44029a147abb6bbbac6de711ac088b54796c97edcab5fda179928fb3edcad9ab8b29463388e1ab39a5629851a4f830c53bd7df17447b5c07d111a0364b6f83f37341412882426a71b476832245d03702093e8a226885add5b18e1fd81d9a1a781bbc0e6f89f1c5175f8c31f6822ec6175fac6d79b2b0f7c32852785ed6da144695c8d2ac4e6187868682e808acefd0be5777e07e7a47832fe822211fb4b69a7052125278603885b7b39e57101d51b1797a5e9b6aabad796a4b1f105e4dc5f13383680fd52968cfd5763cf169ac3dafa02bea33d4f9e62c9a2a826c34ce096a1c50537dc6721ba7b2b09bb46161290d0aa2236cf4b5a5e76d10faec58e97185d9a706fbdcd9413b1a74c07bc0a7afc7b56fd9016f83abc752031c14d4c18e959e182e0e7c82827676acf4c26c9bd3dbca20282887e64959d820cf2b88f6dc0f31fc6a2c7ee0bd57bf0fb59ff5f287f67cfae7bb5a05a6fae787f654fd437baae9615ad1785b5ff6f90143e013558bd4fba123bcd7de966839d8df8f262829fbf4e8a648dfe93b7da75fe9bbc6a78dfeaa29fda123c698cdc7aaa6b1f1b597df967db53c4bd8ee5339d8df68028bff59f5cae7cdb35611ffcc40a821b0aeaae6ec87f6b8291e213f7d8afbc331d056136ad53e95da88b57a3eb883ea36630860e5609fa368a34f52dfc4f48d7972b0a90a3f49d3467b6308753c63a68dd7d2dbfe3fb4876a1fdae3b5f476f8620d7fe8082aea519fdf1ecd1f518f1aeb3083d862e9fbda1676f60362d6426fb1fc9def0f7e3d96b32d823f74c4cf2886a5ffa8b8fa35be2630073f373ba23200e16333f81f9970a8f40db9e590a119d400002317000028080c054362599e2952c57d14800b4bb4405c46360e47e4b148288a02290a62208661180461108041208ab128640e3b40464e1634f5adf991e93e7f881957c2a1f99962201fe13e82cd8c2b78fdb247ee48b2995377bb899d592a4a061d724d7a6bc1cca3e91670d470356d04c5eec1beff922b6a949f8c20c66d038cc4a287536c687072e851c0af41fa24acfd3ee84bb8babc08588677555a5e717228e1b68a7b2c626327a4df86c5c2708b6e2ef7deefda186ceda396580fa1597ebde95f159b583fa5fe52c4fc0f111ec978cd0e23351758a7d8c7a061d0706f8cf036c2ce827f0ed68522617403dce3742172d5f2955877e9c5aed3fbad9e25a71096e111fcbaaa6cd30cd2d71a4737a92e57eea70e2f346b15aa750c3a8c84227130044d2c728f1140b7e92e1a13966a3b9f2d92d532c010d8c443b2268dbe1a8bb05c1a978b3a42fb5727510b52b8cdd93099f3be17f2d5a27a1e92ff0d792184839f3d2ebd8aa65bf027fbae3b2eb5879ea81f03a75d55809db8f0ba66bf8e7e98b6216726cade59199c84380d667ce3235811b8571f95fad7cb20b92500499d5f7d21d6275d13c59105beb052cf3ac7561ccc6f2ca39794de943b084d313972ec05eb1ca47270958c213e02b5ba5d071a9acbb24dbd86812d083ce123e5340a4de63225ca86580f9719ed80ccab81a94a7a68f15001251a6c4aa69126822acc333c88b119625ee2379c191a8143806df48ee105e57cc96e2a91a3236e423df71312fd72a74a3b008d1bc3bfa96bf2aee1b8276fccd8deef714e7a436f6460acb8aad83422f8e91250179a3ac22868d5c7cf5401bf078ecae448f17795dc6dbc5491c85454fc4605f2a951180b88a6b89cf15c0c099ab20064931a53c4786b46501681d1df6802ac4dd2e9f16fc12b77d9b344653d33118af02c64a0dc2f9182796d8f62367708d52b85cf83b8a8a172b2fe5b3083a46906140548852cbf995ecdbfbc0432c02329c787f3e7528b6968fed2ef70e1f604820495ebd6e2fb82320367220d7b690084c2f64ea39c61140ae47bc9e7141cf3f206e01ea4e656538ff9bbc079e9e4e3ab00ba5d4473a90c92cab62468a451d9c342734cc5cc8b7dfda0d5588e16376a2c32c358f95802a040e73364a8a1556253c7fb1eb851b1c6e7af0daf50a993393245558bc4845399246fcde05a88274345ccf93485aef1698d42a316eff45076ec66d08762a624caed5f9771d6ae66c9b174cd039a77e79c4b13374078fbd5ee54741929fcde39b67c8c808531440aec75067f276ca2d19cfd0c6f85a246e8068a9f7a5ef58b483b3c66a55bf054d66bfec78e91e0bc2847ddff5f0d2807af410cfc5a36470297e2f4b2d0e71262d71fdf8f8bd9e5cff5116b49665cb9019d3cf2f5cf290415b225d549d5e0d8f5f1ec724ba5db06a0ac1864a1fc073bc24428519418dccb6f0cdb2ae283f91deac769a657693702dadb7caa051e492538b0d8c02cc77127c922fed305caaa2535fb14c6a276c9927b357f19e492c10c9a9a9a8ad9899406837f1627e78f1dfdf3d93205321e796761aa5fe273dd52403771a6f0f387d07c3c1999bf8c913aa8a7a6a13997e13b9d9dad24a49505a67559bfc33d4b2a6126f7427d54da7fe050966fc3000f8a6917277e50a8cf0361cae3ae98afde315606255fa912609cf8c33158ccd39cf0a1b6453f8029b6ff0ffa8855d4d2318f0ba4ea1927515852d083cc135cf9a9b18f6e0ec89c8b367fcce013942f76d00540b39f0d5876f9469d9719c49753e566dbe8a28585135efb5008e97b55735aa5862777b71dba7e4b43dd0ba948c012c37867bf479051312cc42f619e1985149c69520a1912b9b0079fb9db5b402c8cd913760ed9f99ee7d0a0c20379df340438d5e2b81730c83ebc9a7d1839c062bc7efa6e8f318d2f1324fd2abfe944d16c069005b2fba94b715c3d323abb85cec468946cfb99b8614b340666c74ef61c4135b18322dc094ecdee93ba0784de51e702596d08a00882ce2f7c9d101bb4d12c1e241ec0c7a3d37956abc245dfbc5c0ba0582c4516994732163a9d24079b91b48fd2062ac80b9882a8322d0ef223a27f02fee6f8e0e94581cf6d6405efd67c837fb2fe15ba1bf523231c9cb2c86698b64cb8d3aeb64c4f4dffabbedde700eba4a2a97c4b9d4f1c75a212048150426dc4ea2ac468c4c56ffaf87026cce4ef0df410fb9fa7e25a7576c6b7160c15d6be08d9eb99866e9247680545cc99c330557d4bf652a97ee0fb4f2900567eb6a78aa6c4269e543d06fc0d7c7e1c50a7ce6d3773f3538c2229a9a7558ae4ec4fb6c54756e9a63f649b07ad0d602aaa24c15459ebd182a29bf6d980068f1d81ac939c2e3fab3b907592a907932474a70ec13abefec1605b767dc783e2a85f4595ff12fd44e18dc26fce473ca96b1acc70277550efa0591b1c99f8289ec2b69d67fa1c0fd9929d9474121f6dead4850182681457582d9c9a0a81785c932b12fdbb43764865035b4d96fff1bf3cf1c771de4dec93b52ebc2142dd0ed49375d8ce413be4fcd4accbe9b0029993bb4b2f5dd37d55a3eb7af8a0ab931a27e5da6e9c5572b45ad8e2777895a2218fe7058977702b7ae02679e23ccf4e2a6a5cc35b175e6e154f4a74e1c9704b22bb822fbdf77bc127e9d5b397182525f19894c4c07a41caf5ca87a6fdb384c03ae118cfbd07f5374a2098dd573be89011aa2058a65f7e687b94cf0ccccf9b93804ad6199e1d08ba0049217f3aa5b93fa31340ab1f9d75ae03912e4b9a0815286ab3017b8c830b9df7141c84a12073b58f793201e4c1498c3d06ad4116649a4e6ffd7cf0dea96953e9a092d28d9aaed574eb24e51d11dbd775cfd0da546065fa7561396c01367f5c3405ed465962e8c4f804a497cc4e6a6fc1dc4ffb9d47a746e26d184674e94eee084bd0b60d633aae7f539adc79b83d2a75a6ffb60df398814653bb241c4882540b3f268595b318579ba000b6a96859cfbb63a15f0bac1c92653c3f65eb3acbb62da8706369989ab50197006732e09b7d01e7f76e77c47d6bbcf8aca8a1cb4c6f10b6092ffb79315f39732e6a86b546263b791cbbeb91b0d5d977e2f7928a47579b6299f7faf29da28f57515c9ddd0da1868233b133d2757a708c5a54eb44a7215c01cf500a8e11dde93189769d0457f793b1934796c56189060008d76e48c2e0b84a156275266bc0d4fb54a177e14a3ccd3240c2aadf0f0ce650b8f14e8e1647d645eb3ec698d8494a1019ae26c79e144996368d1350e1e590f1e54f7c8e28323c62e0a503fe12aba819b51b45928c9d3b04bc5d51660525305ff6cc3931db76ef393eb8c64ef46f34dde1be27b614c4569bc187e218daca901ec7ce46286f8a738e6a461abdce17c3b92f95d9aac364a7c483f491263ba933be77aa53343db3c2275bb233e3e0df28a2e059b10c37fb06e75f08fbaf929d5c8d41dc1308ed70327174e3dd9a68396527b6e3dc3f08b6d96b84496f2b2a3b6dabecdcc98461d779fdfa53298f9d4f8c175876026cef8daffcdb71c1f8367b969d0c0c273b6f6af15e12c1c9c51816b51118d458082b232730859c347f8c8217eff0d849dfd6c744d398f9d727392f3bb9036e4cb9907045b29c13d18e24757d551cf87a6467025c106e313b33c53063769e04c8d42093937adb1d598a842b5e6790a1a17fc3b9177a29fcf2b6f85dfa3d84fe21d07d303b419ef120e8535d22fa1cd70bf0b76376cec439460376d237cb4ed75fb333975925c44cfa7be5b03fc0f4854b98ecd29b9d4e383ba376c37949b7361a91f08fdf6f0835b4b426f088c9e6df913cc49baf8a9185763dde385319af022b0a9c500bb26366426677ecf4525ff7c8d909c09c9d5430849deed9c5df67e78cd4048dcf4eadc37d68a745e401b4f32c06f80caf8c114724413b0b31ed0c16e761311670a13078e7b39738e8ec34097b1cf7545ff150ff709b241d1f5da6c78be3e8453bc59b05353ed96827906f10408ca3f6cf5f9d53198b6943eee302d8297a8c8359393780682794f9ac79c46518ea686754f7cbead14e753e543d39da899c8bc01bb8ea3251ec8dfa559080d43db940339c5af1d8809458bd1616d4d405a82908363506359987f4af227352efcfa34e46eaa0e6c252a20d2bd051ed39123529d1b4bfb8a3e6d0b60ceb79399da9d530e9a347cd089289f96b35bc3c17507556c530ad07479e5213e4514818276d983522cd15a33125e8036e00f6d86e26131437e84177efaa02a797cda4b551ca3f699b98bb64c76d3e70b1300f9af8c7adab6dc8d771d09d04a00da2fc2811f9a84bec947da584af6c17e14bf8d2377e9b4092134144cd8304fc62975c009c14a38402ec7eb115e64d5ae7f1ef27f14d5ae4a43a700db8b82641936dc246f995f5eb25e9fc36d356c9ae37a2b75128ea4757698085c5dabda0613ca66f366cc05d3c3563532742989cea937b145184f421d539d86b73cecc95d0946a7a4e5542c0cc21df734c04470471d637ef433ae15044009a49aef9e2717d6a6b317f8f06c9a1ce69b7de1f64b2a2fa3c4b826a0e4a5d8e15bc8a510ff9a8aa6af4669e6158c1c337d0b79c7d1bd26fbd500ace446eb7b69b78019fa40a3e2e6ca1bb7f9f06095c8845d0764feb2fd9a81ce3238a1062d904a7656edf4a90baa165d6fb63998017f3de79ff4754668c087eac99c09047f8ce32b1a601b7bfc21476416bb4ae1298ac497220aaa69fc6b43d21d13f4e8584fae9c89c213008e952ed16d38b292a4ef9709f8e991643e24e9cc0583132212d3c2e4e8691c267571bad32892447348a13f85a7b6e3d78c9a9ee1d25753dde59df6a865f1968088498b44b2905ca4bfc26edf47f9d584aea15a1cc2cb58b709c156583df3adac81961f6cdff7ac3b7193d79b2b29e6e1e904a1977489ac3ec9aa884e1e9d96b66826b69fbc0847a12b27238a08e05d227108e5d2413373c94a22b3adb9f430e428a1b790ab99f8216a61faa9cf4a90a43b2c91092e33512128d38865b4c2cf0703866dbafbebb9158a56c12a44b238f839865ba742e45b67db6ab41e0a630422a3fe0936d11491b69d545821f91f069aaba34595007e05b08626268c81bca267f23f3e4be7aaf1076455258093b006e7a9e2d5708cbbba2c7d6dba0e5ba806d41d80cc09ed4c21ce4f16669022d1ed0677a549e8fb6165c7ae0a31c665e118894b9c119e0a5fb563d6d6716c12bfffa2c68b4fe5cf9b74a90dcc9008a78a9599992152cebc927d8dad1b1a38e8013f9178fe94198af3cdb0488e30090d2eabe1089abe06dda83b86c452f15711b79a8cd9bbf636b501e3501340ce1664a9c235174cd7720127797589c93e83c7deb9bf198971fadc679c881837e90dff4701e0ea0897fa46f8c8d6a3aa99a0705834ab90584431f6b9c320e912b1d090c0643850ba2c805663835b67c6ee3eb5957b20427f5d402a8facab8d695242d55dfc252ee8d218eeb92a49722aabf18faa0f81b32906fdcb98e9ffa59569827b43fbcd8db7525cd420dc8b1a81767906aed3eae5014151ba2445df8f1e9b94e393a282a00fe591dc15e1324eb4c26c973a2966c8b970f981f3c14d15c4747dc92d7d0271805307f8c38445c835a4796393fedb056a66bbec05d4c09be4e2d489c764ca067e0a98eb527b96949de38cc0fed0238e4adcc7974a6f7eb8ecfc20187e65c57fc6d6f1ce74aeacf1fb03ab4381fe21f327fad3c8a8658ef01f8e94d18b769c9f80009fd19540f4e8094160f52ab03074101238efb553b5887f76c9dc6d1c1b1e18d65d0b8a9e32cd38a39261c1737b53ce99755c49d4fea56d082b2aaec56e89285af2e19765623499a907e25f3ccfefaaf07163fcb086353f6ca39d876ad2303873733b0395713ecb7384f03ddf454fbc708b1a7c018a66cb9e8adccf38961a1298e6ddd3e7391d1ebdf76c85ebe1aa0431dcf2eb78111d0aa8734999582a5008641f163ec93c3c68d3ea986508d82bcdf94ab1cfcba8eaa11b4e41f5f4d8022971c76ccd0d2dc2f392eb54460f69b077b5f22c94dc5bc58267d5467457f82e015510808edfcfb33ae9d6a9a39cc10467219ac8cc401c0c2938f22e2ce8c1410a7a4e997dbecf9d32e82a620a7694a1830b35d05a06c4e7187edd4043321884dc5d58ad9c2efc95a009c05b2b50955171fd66fb620aad0494efb2431073692d915cb5d38da0dfdcdf44928e88f3ac8b5e2c70fd05f545991c11f729f99c9a6a685f4706a092f4ff03e8e36fc667607bbb8ed791a11cc14456e1368f87f970b9847260ee9dab51e7b4c9728e6173030fcbcbd1b4f26a334cc35b192b3841175024bf6d49f7e3dd97b0636211c567709ae11388923e07e27d6204014e5d2ce42b448677305033585d515f5f74141f80121ff419acccbb79201c2087f8661b22b5087404c9d79e9f08a5982199f6130dc05fe1fc113cd551795b46d90ab2838955e5d0b3cb9b1e1d2cf4a34cb743a188e4d85571fe1a484d5d6165d1479db2a270663815dfc81a865912d4a4385b80e45dbf59234ccd72ab743739047db17d559f661f3c725a0260fa1c01bbd5eb4c3eac01092c8589c9fe003d5b110af32cdef219c7843aa0910e5ff85ccf0f08f794ac0e151589e60d9653907ba5406a4c6ff7bccae8ea94494e2524a5cfec174f394367d10ce2ea414a896eeb10c79b9a4c2903764796b2ea753343e1564432067f1be155dabd04739ca5b39918b66662595312feb360335117c69a26124552a4662a175c91fb8d52032ab2311c7783dfe63908401f2ddce19868e63f847620f4689ac07162c6a0ce4f9aec7538653ede69a19857c89e316e740f34fae62822acc5c94bb7c1379f1837e44cb0f3fc50c829e9e22bd9a5dccdcc1cf1beb0d82f1f11af605a0124f92f298b4e501a35f33c5367f9812be14352ade8cd88b543f5fd12bde3ff0e084f200c5aac02a400ac58ab8a5904dc21f99aaaf718024eb45b435cc3fd3730e06c4062c301391f82575634d4f4c7f629b0f25bcbcbbe9a3cc90e41d3d1a74393aea54df84304e381e92e626648f8ea8e22f61c289654a48a840d0e11ca4ffa24f2f18d654f99201423b0b6e314d7c42c4c7578095427b9f6019a2abf9152dc29b53a0c640470a0d70fc2a6b055a2d1534fc89537eac2e2f568d670b4e103fbb45a5878c24d41b2f83692f2ee6a67b80ef46f8d929754f3848a5175834fb6d2bf8b1491d8031cd9f00ede6b2225fadd7225d9e32b3ec66be13fc0a863e5c7a748a44951b74aee27ece6a140dad1a558d978cebffc40e825a23e5d4c7000a3cc45551c67f80875952e10c97988a8a79976886df0bf986cf6c992279d95e7624b7f2cc0fd126db2f9f5cf5cb23cc26f5b3b6518c727093ba954c27cc88b39860529e5c87331db3b4893b1fdb460808feb80870bb7a8c8080350f9bc786560ef640bb98b5000854f855526f5151df0f76cc5207992a60d1aec8914ab4335c4544c1053755c5ec539ed302fc2dcd7f13bb3db4b0a253ee25598aa0d786be59c05c070b2e17e6b872f1eab4d284e92f10273c5872f95e96fb96e84fa30d33769eec092b2f2f34ad2bb15ff9a02d4d19d589a83521cfeea648584c5b7ea556ac54449dd8a71161fda75b5737f5fbe74cc70aed20a56c36df003b31db2669c9244eda4a4797bd4e94934781483e04d9458bead27a00435a9d2d6f0699e62dae63e35bd55197954329f5e93a918c29822c27d76957a86c0c84498312e02e10167797580bad53f12d919a5dac1420df35db7c2b445330514c3b717aa2627bfe613d27095d454c75ca35891e4a3781127c5d87671368a6e60921c2ebcc6600563f3271683aa16b24180ecdd1dc4fcdc83f7eba0196333835922a564de8620d69964265a071af58085dd14dac3a91ab7cef4685389d3cca113db60f80ce4db9b213b1e879f17029e9d7f19726fa32ffd0004bd05464c920ee9ff1f2e0f20f31b332ec3a9c5ce5341e4d05f66a56edebd6a03c204f1abd6a2cc4cd3b1c4a0a992dbae1b4eab849beae57317f81fa2c046f0054c8da033891feff8840307f25f9628a6efdf980d9cff8fc38b6e05a0a1a2f9b28a672ba3afdb8cb2ed7f8bae5463ad9d84c3ff80b47dd90669c1b277dafa304530d47f168c113083c47ad9f53d281af45a24fbab52aac4fe11e9a85623611c4b753c589261ec77dfb63b8319e40ae8913d7bce00dff59f4415099bfa36e64859b7c20ae6f308b0faa8255980a7997877686e8b2d827c910eb9940d23375eadb43f7d722259ea4be90197999a218276e0068a72e3c7007bfb51e225d1688e61d8c13697e396312adf986b19310dbf7cb67c637e79e6183b88aaea8d029ed91cb9a987be303ec044a3d526f31a0830da2386c4ac99986683b8767f7665a5518485562900f04d735b03588fdb0fe270ce06a323e08bdf570d10b9ffd03a4bb81c1455f8492270f9baad6eb69795744095c77c03fa6671ceefd3582e9b56611f4c2b29c3b930e5a0e22c6836708e1746fb2f04a073d37a77e64c5c69c8825c3b8b40463b2122ab8c82aec584410f30c560e3af160cfa600a013a13577b9f93991f2aea2564b8a2e5f5a5f7ea9fc141427d70b4e4f2752cc4fbdb00df2ae4e0c8d2cb3c02e415198c23eccf7a94442f44bc3c9041973c0b107cf29e233b7136165bf09246d827ec3ec7323c7ef4e2413b534221c290c75b03d10107c9df00c4fdce9115d79838ca90573f71138d4a016885479a596b3c55107cce1678610491ba4f0efc821e8f3e2a0ef23c70aa0da13ef471defd873d19e4896868155956b392e76495b925b4f2cf6651867f928cd62c58c68ec2b91fa2a0ce1f5eb32a6922461fc7acc53f456e9731dc98b247d629b24581333dd0c9afa7d021f307103022481c7e9da120cd50827340c55705c3af889e1a80a53e9f5b59104dce8c114a6ab113a787714e26f1b32a43935f60c562324468cef0d59175b6f2d9b20b3a8db750484b4b9d698ff00f61aa1753a442aff0d67df3bca9131e908d1aa8039d4df810df01fe9a31ee5794f2f3a878eb03686841153fa5d060466bffe99592301a33f474ab4d73812fac6eb448b6ddfb50047028987d93c1f33929f9b085dc5fd1a406f7377abc7390c12048605da01b0ef9b7ac15debc909e7b36c586af003ead60f280a1db23fb3eac09d608601734e46420b77406ebf5167182c0836cba8c6c018499da9c5d5ec346ca23b86558a9bdc60ec82dfd214c5b3277bd7fb84f0484e15ef3145fbb09c90137ffebe58402e2e48d4e4cf8cd43232637abca4777ee8d67c4f453ad83750944e1f67e0b2ae9ddc3a3a9a87ba0d3e087c17161a2ea61236e5e3653691673744fec0de58f1f1bc6091724aa03b04d6c243174e50784d38f409ad4acde20ae7eca0c9fb00eb0f9f8d783f853310d40d96112e731090af9bd50576794c933d614e54d3a5186dfd37c3626def045f6e421039a51ded0dbe9fd8864d5bdc76c9a3dd708fcf007a87786e5094b3579704b00a1d0bfb316164459497120dcfcd2ee4763185ff8afe1759aed84d03c48ab6aee84d17c11a2a84978cc64b3e89dd6534cc4bb8ca95abf758fd2857817128b6cd6d31d5168c4af9eaa2493658fe77a4b49dabd7e02f7dca1a6926a56ebafa7bfb8476f34a31c3a7b3d8538535d67963d534c1629135b9e6561fcaee3a65c0f7c792475b989dc09b0bb2aa468e706df2e124eab09f0fbdbe3629d81fc747f637aad8eddc360025367349414d8b7cfe411af9de3ed929133b4c73b4384bfbcc4e3d6d64bfb33728f3e7841b5c479a103adf88b6b96a2270b9ddc2482be21560658e831c2d2fd724815bee6b9072e83b48b54cd6e7c85b135c3afa767b63aac54fe00783bd67e518f14e50aeea03d42c9c519d138dc27446ac0b85a1682dd63a707fd71fefce3308e8715f8f285cc51cb8748c97cabcac4c65c33b85ee2a76dc631be5160b11a1d5405e4311c9aa4a3c37b849e15a0535450f88450331ba90ec18db57b2200086de1b7a7331ed4579ff1ab139556405a6aa9cc86b2c8288b6bb839dfd5ad2408548d617876da042c7735139b6d3d8ad9fc2f0b6fd85649845118b7b9ac897ba6661134e2c52024db3d5089189838288a627dc37c7412b3735f0c3d474242ec6508d25bb1cf4c77e9ddb5f2cdc87faa6c02cdc43844f78a275a2d7dde23af5d3caf3669c02e53ed08df12d14050ab43542c1e2e8fcc64e1e917f7f3aeecaff30fcf1610dbf07226b3c54fb7a85577776f9dc5809ba307f974c1d95cbf68ed1850dfc365e100cddc69847c81bdc5a17e57ef86dfccb76e1207c790ceb3946d0079c105beb5c81182f846ef34e08381fcec9d41e10a21a5ec87566df0d0bdbf1d39c8323fc03ae080cba70ea1b4452bc903658a4d9914cc1f4f5d9d65a6244e86810a2421860ee7a69d906c99b561c2843c6a147290c30584748e218b8865d20e7eeab1ac6759b721d190229590a508b010c005bc41de042558f4a948ea7627d0149b92dc6f257e419abeb2ed424ba03e91339495de6e6d9a05b9ce47c49c318d7532527619586f8b008f3490c3ddce6580cf5756ac0eaf93b63859b77a73efdf192bd830feeaebb77e2eaaacccc11f1e710d76cad379ff9e83b71702cfc914d5fb7daca7fa0801c5b6348dcd90ffaa3419588772fcb71bcd562caea35006e1e394f749e0dd06bb64a713b4b16e16d15985e57314e44c5f45ca5faaf973508be22d325f58b10ebff795c245848bb80f5a9cada2ce78c617a8937366a212db3232de70194cb937ed25ed8b1670f20244c73dc599c8116b099d989d119c266126760401a0d38ca16e11e9d706ce0b8893f0ea5e9481cff694fc00117920aeaa2fecba721ed7cf8cfe03caf2ebcec428fb5b232965d28b10f45045a7cf6f74eec370932db85b91cab8fb9546805242530269fc570570b61e248663d7af783416e9b3b837821de84192a7d0c173dfce1f845f9c41ea8d335f85e8a9626f587eb1ec527e48d0e39f2427f5c2bb289020704158ad8a26862a9c8216ca70776841a8310a5451aae497bf19117522d603a7c748c30a65a7d64dc2c60b44167089e542b445e08b767fd2424bc62de2f2e3005428b058b45b4a3d85a355c38f6d0f473f8fe587e74401188e7ff2794a0b92cb1160744ad582f03565e181c522c47505d8aa183c193c6d550c6284ba1f74a7e796866c2a78c0eeb2e03677875a809e98d5468dcbec1d80006cb7633ed1cb3a058d119e967bd5969873e06c0b7f56bfcb20df1fe3c787a7656d1a1455d8d4db3648b2bd0adb07cb2e049bfb4066118630d882e2d9addb0efa936aada55b5f53a31bce5c77027e0d415a4f0ea6f020f104c832f83fcec693811fdb316c87afd121bab60e2fea8c77ce14e6efa646119435b7c422f3c6e14c1c15f2cd2f41519371c2f2a748a124ebdcc0b270b13015b2cdd0eef28bbbc745194f215c047398082d83e569097dadb4784181eb1ad2f07e8940ab56ffdbacccc9f7c4c7da2740cfd190e76d001ce848324903ab93733dc934fe0429d42ea5b130bce5cf7ede6fe1929b15ee7ffbdf5c83a56ee49d461433094c0d061b92714509ed5b0b182b6da904ed4ae17a9f2380873578b84c2cd9bf37f4a8061bff9e7796fe0bea78ef002aae6b39f845ad9bc6f5a8e922f22a6f65b81ce4aa1d2d2f31a1a83acca93c655c87380e7f1134e76cc202f8d32d04e2ad714887d6e58c3fb5498b27aa964e072943af19240b3530afbdf15ab2228a65cb34faabc9b5320d1f7a2522724bffbe71c096a0a741783b74720e0ed441693abe5b5020a54fd11643878ce5aee4dd9b1a86a459d3c327babfd08964ab519f367559732a5ea2a4f83bf9e273e8ac6427a79e6aa1c74fe97d824156b02f12b3dd4d75474263378845f9530d35b3cc21d597a2e3dc6ae05b3670d26894aaa4fb52a303b03fd06e34866f0d9b322b06133a6e6ab9f47d440541771209b8df73671432d8618c4d97cb14732e19ffc2029353990802078e9fc65cec24a5f92606309668e6d135e8e59d63d14b7f5b3bebf9ae2c78341e131114c30264f70e901fffdd462146305dbf78fc7358878a24d8f14b85d92e8c2b992860dfa6c8324459d6988fa1492360b7f9552253e15a95179ebffb88628b593a3b474ad779d4e29ae2ce83fae50fafe729bccbfe333e3c595f743b6796d4c371c43e65597f56ff8e1a67d6874824a56d276ede5ba4a3394d9bc416f47f2670511d5f064e81d15c99e2b559c05052deda9c0e1567fd2d8e5f1a6140e244818883d3179824351f208fbf41f1ba5ba6128d58e6b2acbed3190b30183e5bddf547d6bcee0744ad101c947bd4125a1b588589d161e4362ef27b1007cacce2501b4f51c94242bf0c7951d50e3d9097d1603ba87cd36521306f426e26bbefed862ab87b38d60d213826c7851473d40e40d6ee8506b0fd7da4faacc3591c02a761ccf7a7ddbe0b6b98c3cbf1ede37030be0c86ac2842e13b6924d9fc1829a068f91a0645f68613877f99ee63fa82e3beb05fb73a62bd7377565a1a536f17adce3410eab8ef0442141adb206fd7b949537634bde9d0e3318ae014c397da17e8faf3e62ff4fd31ece7df86f7b331ed9bdb4fab3cd658203ad89fad661100c86e054a198fb434aa3fee894c908dd2e32e541cf5f43d9f653321a62142a583f45f748e2eb9e1a819f1fa3f56a7a719daf4fc1b189e95fa71625ba07a6e60af8710503d632844673bb5032a98f165b51c0df839820e7e60b9458a7f94573bcc0fee88ed939ea69f367a8250ef632c49d0308f8cad7db35224f8cf2cbb8e92e6062ff9dce14de47cf82f637a15cf69d3d4c7a824a629d0ed1e949d63aa85c941b47efabd3fd078ea66104182084ab4ddd906a3d7d6b31a75dddd856ea8e82f027de0c387db451574520f0ab2c6342f1ccb6fa1da19b644cc6a68a0417a7afc2108df1a6e28aedb51419327a4b4ad8ee5d2023e3c783ef09b02ed6c5065ba9bb786df8bb2ece8e06f43f9b4de616f71e643f8268350379442ec4e9d5d76d00c230fffa4c694317220828d70bf3bdd5329c0cd11fd552d3953616d0bb1736c2dd486210dd93e9053cb808cca115f2a37af7cbff71f354f51e414c6e3afacc53b636228887446a5828b4ff1ac05d6b9ae2a153e8d3b82ea6723fd89982b60f420d3a4a36ac7af683854b67e2b84fe4159bac81720da1cd9868ae9a0043c4064d01a0aa1f6f187ea6b065412ea076eac13c21d03a45731c906c18439b716febed8f0b4a2b067f51f6c437b5051f948117eb2c4db56d940e41d58c0d6d886b12a87288f97ddc0c85d123e0eb1c6913551a9b355da601ac9a4ceaf0929db7654d2a657860a94519367811a81a535b2bf8b7ab3ba7d44208c13e97a499bdf64627144a1a219f1ea4df0ca21eede8d3f7cf3c7374ba2b98a4c74f3f78ffca87e68bac39eea6e0acccb980cded8943a603848d8744a825d269a23bf895732b070ac782c71df7101b7080f52258de74da376252a25699317d977c0927b0f471f53c2273b9310fc9a51364479d9c4527279260320298e372e9c62af6f531d1f4517ff7b4ea471cd04910eecea3d50ff6d6178d468a9d54cf43c44be164f96f95e94563cd8425b15223024509e027a0b24bddb725b9a6b002d252eb18160ec07c2a356620c82a784a4def085c0ce5845cc502fdb8fedbb58d86c6d4b6e09f97092961b6f0839bb96bc002700878705f0f05c9e60165c8ced9cf3e976f30e0e304e3d0364215ee9a669593af01f88713c18ba40fb675a2d65f8f13a428912f10b611428e09e90c846c4a7b96b70ae5df83d05261f0c458ba58a94dc7a1fee1604d72bd96ebc8e2aa0b31f2d93c0a890c9017a1e20e8bde6f8881030f2daa6c15e72fcd9fae2dc930e0e32bdace65f40c54306fa2870d874e799e4051bbc3752f6e6c59883d5d97e8ca11e1563f0524061aeb301417f0105526e74a9a5e3a5889dfabda71615238e03dfbcb34db50ad13fdb80b0708ab12afa14efe1bb7a997d43eaee1bf51eb562b24b78910043e361404f4e1220cbaeac3c9e7cddd98277615fd24553c186bedaa54f09f69ad8cb781668a9b251cad0b4fee19ec0fbb4460c5f7e495453dd33b73c7a300217ce368b57c412492f62e11c55dec2d91bb6b480c906e9dd73afe572abb77f5fcd02fc695ca5dbd9d9bf9a114b507146874ec425146db0ac33cdc6bdef375f551ce213932de73a2cd9215ea4fb3b1f49e2f50334e9a26653c8eaa173082fad924a10e59b574429a2b6ffb21caa9b094662d8cc5e7fcc5bce8e531c422a8ee4c5c0f23d4e8ac0478f990f53bf5935744785950db914408e34a333ca885e23527105154c19065fb2df52192ce96f5cbc116a697a8838d86e2e2bd0b35a6c0d20b6854901480d9755a154721f079ba22b0c208ee8746e11765407ac81291e90b704564db9065b3c4d636bea43a52b0266398363d23cda8e22671f766bc58b22794ebf116aa8b95d4a8e6fead62e1e44ce4655602d415aaee67a7609379b4f89f1b257202f48f916d6c4ea98adff212388a7089c0b4292992f377b8e43f89760adfc43ce55a7dd92a3c87897c521cf6058370fde4664f0859339eed784bc7d8ff64eb34ef25519f0c819ddab0cab8e4293fe71dd6b453672cbb504a659b4b749cfc03883e621143606fd54281eb05f2e21c9c0fa5593aed62d27d4a57cc236d1975b9cbbf896cba887417b546ba512f44d6ce7ba95d55cc34883b77f4493fb90afa96041c164341145c3e30e9c9119368a8640627a46f879687ea4418ff3b104a8ff450fb5e814ecd1e08b4f0e150f370fd1fa19bf63209c2785c6f6831411eb92c175fa83a2110a3a662aff05200133404fcaabab227f8b63676d399961e08f3c8f9f7041812be95f4c5d3d3792600214c629f7c42de58b1efbad35c0d977b40d03ac010ab2eb6bc6f96f267f2cd14b2874fb6d7e1010ef809617acb014385412037e4c956a051fb48a9de0cf658477791854f0919c919ade4a07c9ec45a480f3cde965fd5596988fb94f2969288d41ab1de72026f7df44483f107aea5a4c01ccdd8e995d6d0ad6c6d146897cdee06c3230a917bed2264c82ed4e3b388f5d8256a058569edc9b157419ed45c82afe00190f122917467c3671b07467ae797e9a5a47925ad480f888fd27535510c1976c5e239669b4bf158ba6756a1f8b4f97a5a16b8d43a39194b7fda76175677b323caf498c4071c8cc1acaea06b23691e5b3a126b3633d4c60ccd689fcce089dd3ebafd927cc2a2144195e097676ac6a721e72c337a01a1b726afaff771663b0f3bd346b3812540f7ff958501a68397faec7df3d56b0ac009130c63172f2ef7cfd742b061e4981fb4893fb15a0375a7346063d64953da4aa2ee0af893a56aea55ae40cbaf89206a89412dc8449ecc5459f88a5a9406ebbba88007043011b2164db17c84b43bf20b7bb56de6f1c50cd860d5c64df3e2e695ec129d2844e3f5ee15e33653ca0cbbaf95c095ba648740b8ce3b04539b96556a13aa70022f0de7e86cc94ba8c2c7d7d9fd4fa5692350b856758f09333c518f96f8254bcd4389a5db6561d1d5793c7c185b45c18fa48ccd19aa8a9b0ed8029455d48dcaa428ea9ce8bb7630575b34062ebc4ba563284eb7b2514911756e37a6ecf94829b1b62e08672ca9c033665e13d9d7f8ad456efd0cbbe781a427dfe3a300cd4788f6524140e8182348f78894b86c80ae85c57018b0f77ce05e5a5867c20c4bc3b2741e81a8771e6e234cde214de8d3fff92ec1b4d1f835051383fc4df496f5729a1c327d47a99b32d14d4cf4e325f0a634faa8db4de19e9725bbe53a86fa7aa87b87a665c4a66328440a3ada11615aeadb2f65fd8f32f5c197d292d0033b9bfed1496990459d341ef4f61f6582f7a4b2faa36fd53b60502a861ffeb5d091f1b72c459cf88d03749a97475b0256d1c48e2212e4f38ec3fe9e2c5802a78d09f9a11109140f4d6368c90832c0bd1647b84fc19606aaecbbd345b97ca808cc0a14876cf39db9c9d978987cd4229318636235a4d566d26dc41a5c26583f5fd55e4a39161c5b43a68ee893ba6c6ddd9440719d78515f605a0b5064d76f997d1eb47f1fd8bc86bdbd77838f988b63f174ca7f617b24334422dd08c5901b412c7952ea0cce0bb77030ad0e810ad1a19c44fbcac063dd775ae29b37fc410cefdc3a24d70ef4dee8db3602896504a94e28d031427f0779864320f131d6042633db9f4ac49b4c341c5c7627e3d71478a590d98896ac6f08095b4e1f5a6a74d95d8e528c69eb02402508cea746c6af94de092c206d5f38c1ef13242e6bdf889a695bb38a0fef49581b2742fe64d83c4db903a9eb217c488c7a33f4b6ee86cbf08a992bd6becd1fd6b6be2e255a22e65ede863b65d0728e046fe176fc22d14a4b4186f1ad70c56a26563a1dfe582baa6fe52c38192c30c0d10dc40db9c2f4fbd7fea4b5305e81e22bd1978b0c1d427e60d32180ce19920a522f2fbecdb1893a74c91b0652335ef2c9e4f5e858109bd1484bfa065b0cbbb0de18d382916cf3d04d9d609732658e59312d79dbbc91ca2198fce330220f3a3d5e81a71d74c5cb6ba5d12a0188efaed53477b4563eb70548ccb5e14a4a6fcc6ab830d0eb7c95cc90a3f405bab556b42122c6e5ddbbe4371d91ab4106a2a546d3af5b51f7be4040fdc26270a52c8211d21887bf04e2c822b2210804461a7d7391d81e7499025faa486d040c1b9429ae22d3ac00d2a18fab4f25793b83f70d098f9c6d53b72ed756c2746327d89e10ba32a33c37de2260e02f9f7b376c2e638c292b1159e839261815db6008e13272ecd7b42d52f689ae421ec858be9ec8a55aeaedeb6605cdf9c1eac8ad740181cda72dc58e8c495cd36d1f9e1de97ab4845214c6e9866bcb0fe16cd5e8f89dbf0b0bfe7424fa9f7b127456bd6280adcd4a37223a9e6a506d1fa0cde02dac7ba4c7345c3b2cb1476930493f9210c4118fdd9b370c97ae0b0552f86a4b68dca723f698cc012731f9e6f20591a36eb6a0f98ea5820d08eaf8060242b36a957ade0940a4f0b132471ff9fed40747983b242e240856a0fbecac07879e4abd3d395b8fa914e94ca200a33dceddbba2b3e881c53b5394f655fda36f691510209c338468201d846554f7192fe7658aac0c6b95b9278861e5796a56a9333259182dd714cc27cc2a6df58520bc28a3a36b3b1b13dd4aa8bd4e99a9abec73c81ac74ddaefb09ab2ea5c696d89e132c7ba17697837744ac1acc1ba2ae086ec1becbcd73eb771f91c3382f266f5d3d770d781b7071b77009d0d05646adf850a1880fe7db1d7403e25e8de32202d966bb4d74b43885cf30a18198518fcf43b5a025e07461fb47aefa327574fa2fb5c8b1da67f7e7470d316eb509b7b83c3bcbffe47b34a13b21c0748747bf8b9e4804e26d32af87485abca10487a7b7a73e16b03d37704b738eebd66d46d5b1bc1dc033f56d60aae1e8d41d42118787a6795f68961b12f3f9cdc937e5f11c2d4ff1231e27cd054385a12222ca124969b7859dd7af2e465322851f96133950726a792a799a7fd3c8b0e57c1eb759472131bd371182705cd4189a5576c316403833a7532ed0484f0b2f713193b1555c02af42a1568d2f6584af12b352c97b9e123af810c541dbe4a94246c68e4831ba5ae89fdc60aacd3812773cdd8742adda222a725667a5f0caa02f581bb56a15f6f006912124afb38f1fffc63c764ed8ffe75bbdf4baa1df4e334d51dff168438a8b6aa70e8badb00c457aea077ab25b008d7dd56a2668ec419b93309ec303ad8d3dd9477b52496d184093d2d0b65b27ac101a9975e1479862cce73597821502dfdbb659d0de53c2d431701d7dcf4823d313af089e14561265b4ee90ddd55f1ac8fdefe2da7dc9f6d2020e07b88f402f82525f0929e559ff77507d02483b217702e1b62fb70d5051107e7649ef8ca784163c05a869b39d0b53129e235106800acbaa72f707323f34b771cfdd620c44ae34ab8bf256321469557aff2018e1050ffb6c5e70ace4480454d15437c5b092d0803aeb0debb6d3aea0fbe98c44d6adf59ac999c5fd7cd3a505507fd31a1008f927bde2e78e471021c85cdf6abb40c111e8d622cc18ee2eef15c627f81d15dc9e03ee880f81123a90d68ca4d77abf0f7660318d8668f5e682b7bb0f59a3c64229dedec10337e1a9035f9b068695a98f2d046d4532efe83ec56052d0a2d90846e744d3f426baa4ab51e49fd7c40f77ad5ccf0349aa5d35eb871701b10b286048a21a5d07dff30ce56d03d8769c16822c17b692a4dc7b042d9b09a55f2f4e449cc64621d1d8adea1b8260c7f1055e380af01d0e3cfeb16edc99945515599285c404c4b647e5604502aaf04d74c29320627e86fb2f92e352d601a648b831afe1975fae3a09c919c3ea7bfe83c7f4706675d4d41243f21fd6e3c6f33bfa4089652c80f532f6dca8079dee1f9301ad06a921c70f92035f215545a20c2dcf55448dcd4463531677c2ea74c9885933b6e2424b2a10fcb5e771b3812e5383dea1be4e5361b8d01e28182acb5dc197166a5d44beae8dc537641bdde6e41690ed1eba328d36d66c9085a327ffbf543cad5ff380d3277f110149b8e313aa897370a3d6a2e43691472d1c37abaa5c407c32306e638960c02a6591e1f3290a9fd8540d82cafa6b720476c140b81a99f5e14fd3dadbd3b551a4bc8719b37d3a87d2ffe4c208ec12d99a223d56622a0738b6c340903781221ffddcb647970ec46996bfd29996cc5e5c5166888c50b315f449d04dca7c3e4210b3581d4e6c91daa4351060c0b8a88721ea26370d3b4fc244b1e09cf213897a1b79bc3d635805d30a325b53d830419b98cf6f92950303a842ad423c76f9505de3fb984a9eba6e6959fa84da933c99e4998e1a0879bee0f5970ad1c23f6336e9f907304461d3c8be1034da8ca92c6595b2872aa1be8b58bc764a4a1c3f465d7415c3d8d2cf0bcbd53033e32910e40fd09c94a406440d7bd4d9b0d8507f9302fef63f1932cafccd82e99fd8e21e922f490c980359c2873990e8b24c1c9405c92e64aa5d0c532514e78c140655545fb248ba05e5f5e8af487ffdfaea07f8830b3010c684876c7750833eff085f5a0f658fef57213ee8aaee72ec7d0d8e86b71484567cca4c0d19e9448789ee6cd691e1b41614acd803e16ba08ef41aedef25b89069364de9d61976fef122a1d23922105549c783f035c5da09177e81e9f3a7b88b159085faac06e4d5d908f9a8249be47e0c0652a212f023c430d5e418e9c572507d2ec45d63a0eea548f5326ceec41033333a07cab5cedcdf4a3cc41e789759e65a7c919c60f77c2a1d6b574b1c83a9e921872fff453581cadd3cf6c6179462f45a831d33f5c6966e9210c5ca6a583377a70b6103cc170c00bfa13fc95225a49f0368608eccb018ce532b976868668454baf736d6e8ded139eb3f3ccc381867b9829adcf38eaec02c5fab5a199777c488d9c04d308d66768a4d1dbff51534a33e348d75a7d42396ae263c6e1a0dbd84745352b6b351a631729a53a1f610ff5608747184a1c32d1a0f8e9cf66e70deb08dcba028e80a9975276c8a1690f12f0d9dabbb52caf76cfd022407c2318086e5d29ba1cf6dce2eacb6df65525d34b512b852afd7accf3215675a4d7ebe528c4eb038a74abb25a20d032930e6913de365a88cf1104d7010ec467805881d14a6e29720d968d83781ab507adb7c71e54d886b41975981e3c00a5da6e3e00002c53950939d9239c03b45ddc344f0aa94d1c2e037fd33e9184ecbdb7945b4a29939401910aa40ad40a1e940462e9b58e3108d20a580bb6a4e84012c010e6573008082d9ba08f96cd19b653af9d575004d9b9742f6c100c23d8811b18d28ac1219d37a7ad3ddc4e3a7b585a6b9d91478f692bb5a08d59db819e0769fce174eec5ba584863ec3816c06984931d115d7489bddc25f6729898c762b1582c19e5124a46b54f8c2a32a1a414f224042a4ab25c0854144bc89310a8a8f68162b184b0a05c52562b5a35a9e454cbe89354cba80b914f328a157e2cb7a06c75d9a9c7568c6ad9e4cf5dfe8a5977015dae8e88ebdbbcbf1186d421de75bab17c63397d000b1c52bd3efd405a410925f5b425a1e4b6755dd8db4664b3f6f52191dffc253882d76f609612c65ac0c55fd7cb2f9857ec2548cb57ccc62e4ccc7bbdc857ccc56dec7b89bd62db5c2fbf6034de3219051505150515051505d56a1710524a296b15f2558f7e38b5cef9e15429a5a49240b3ad07d5aa55725256ccf2bc31c6d85fb1d83618bc9f2b26a35c26ed05bc39bf589e8717f48e453de7d7f358d259d2afe79cf43829f1d6512a1f80829049730165cfb4999303abc7d5f912a45cccdaf915903d56f6fcfcbcf3be0a5e11a4f771be61cf840adca56ba53bda91403b52c9cecf8ecf4ecf0e4fd7efce62de6f11f49c8b11f1debbe090ee7248f0f5be3c71dbe49cb1a9f761914d05f97604de57708804612d9b4e411e243c487890f020e141b2c353d33693023c46b4ed8bd520917207098f91ac4878ea0e121e2324b5562437a649beb32fd72c1cba5813caa35aeb15b59a554dd5532da35152d72d052d585d5e3031de8bdb975f87b91e138bd1e65a8789bd622f3197588c3616a445ea530f8bd48d82433a9066dfbcb38043b253c79962906e3df5f4769639694bfd445867e92c2df5d3593aaaa57e3a0bf515669761b03c1dc71f72e2ec9dc7e9f9e7326f9be34f84e972cfe3f4cf1ffbe6cacf02c37b1f638f2b5c9fd72a5b705a0f61d7debb5d7c3730471dd3391ba3ae9fd3bbe59c372dd5598e5aedc245277b48ca43ca1b1e3d64e5516f78f4e051b958abdb90727bb9679b05294dcf78c81d9b6f1d0b94df081eb839cb83cccb722eb66d20cb83f4d65c8c15654fd6e7f4e657e5e1f8882e76b18b5eabf56ab90564adc62ba682fc97180fd230f3e5e5e5e585bad0ec39bbc8222945c39b1e3e9cb8b810392972797152f42289a274228ba414f597987c914e5873ab54a8d244ea23692489649117b6bb5e9e2ca2160c5dbce5491f312e1d2676f3160c63a457bfb198d8f5964bde1638c4a525bdbbf9ed057ae881170ca9742281bc80435c5aa0742277b840977452a4ffb3d2096d59748f5acfe5772ac8ef9c84157272725cf80f07b75c6058e4657bfdb66ddb167371155af8cdaa207f7317978b5214d01f52eb0bccd63b179fde75fc40dab2cde5b67d9b1031fe1213a206b8e3b518ef648d6d9d2b166362b76d6a2bc672978dbd8c705d629fc7c4607c8bd523ffb97498988e115ec78ab5a4d7b28aaf750bca22e9e4e6e5a4ab35c908aa24212c6a105d32815ac9fc69d9f461b90ca74fa4c1bc868719c643d8bbbe968581d1e68239d1a605469b0fb42764ff5a1ebff8f402863956170e2c529f934edd152b00536e16984177397d0e1cd26a3975d0e5610716e9efa8a7141cd272ce5be090cdeb73e0bc41ee90e0377ffec35e3d48270ded2421f15369e8af17175a9078b78e9a37f4d3ec993e953ecd1ba6cfbca1d6271a8cc380274c9818af014630bc31e00b386dacbb78d78ab93c7f606fdbd6fa5c1ebf114e985656115aeef2201d2f6ec53f61d264ceb4995ee3cc894fd3bbcf65cee7de7dfd47f39febebfccbee8ab562cee9cf413ac72295e5b889d2397ca7cfbc4102b9f4cbc7394a39ca711c57a49f5a4a39eadcf47af4b03c78c81d9c73f967b3e079bcf9e251fe3e96dfb07c7cb9f3f19f873d6c50ca4302d978bc9196ac574e969e001f939c2cf9ba76eda95a9fbc280fca836a2965ce5432e7ce59d2599e54f6a4befb8a88fc64f670eebcf4967fb1abdea66cc94fc2602d58f6a03ca89753bca8def19e3caadef19ea87a4aca8bf29e3c298cbd288cf1758c3d6c5927d2da5cdb46b7ed73f1ce2f57defcd5f29796cbd7716068c442bdbcdc3789a88ac66a65541291511291501213abd92cc49b78b46df36682307df4b0373d6fd823c47efd769533322b8f97677100f2a2b6def19e368fca8bf2a2c2cff1cebcadcbe372e7e5e6defc2516db26b4acab0f89c42b4c245e79d689c07e8b57f1aa797e529fd283f2a03ca806b25a30916272f45d2b3219fa017c4c6262f508f898a404d25b1a9d46154078ebd1f6e07a7c5b6bf1ac8bd40687c122cd83070f4ed226393c3dd11c680eb44789e64095b6286ed58dc7be417af8e038ceb77aa952bd9cdf7a73e3512ee7148be094b96710d328348a101ae50907484f9f5659976ddb36aac481970dc41f9da494224d5a45bda98fcc6a6597df985c9232269b40091475587fb1ee599f45fa3bee469140629cd6985316939973ce1a3ee7ac010e99734e8f71ce399dcebbddd8cb3b8ac2ec98efa51c128dade0a994eaa8a7497d52a797db77945e4aa953cf38a74e51a8d36f5b6bd14c449a8f6953b45d0fbba8a35ebc4b29054149054af6b2a5309dd7b359e0841c2d7d487ddb8e24908d2a7192fb28d021456aa71b457aeab2988c0bff75799de577f33b67f442ea34a5b1a403251cc4a3b71e462c3e22177fc1905eef6da351e40e7a2477c8d05bb110c68a8519c3c4424925944c6f9d82425ae6c3facdb05938800f7dbcdd3e9779270d856963fde60c83490d000c07f0e18d22a59452bab45c4e1ae573e5160bd7dff094c9962dbb8b7e731a25c3dcd55137b21c451d139bbb5a8bdf3c5ff19bb7a6fce62c28bf398e62678f8f9b1e511f96c9335f48430738a051bed87514264dfe4c1bebe2e10042b7d9da2d479193ec25e6352de3893a366ffd4c5acf106d36b74df49bbb80e1008cf8cd5d60e840fcd6c36fde02c3fc8dc36fce0269141ae5a3512410a71b95a76055cf796ccea54e8ec739def390480e2239de497e12a0515c28128d229f6c7ae86ba96c55d3b657d6aaeb751b6bb75a2e5e5ab25aac164b65b5004d25b6206bd54f3576515d02f6aa56f92d65b45aacd51624e5d5f43ab09da20eeaf2ea73fab964c55aa7779aa7bbf75e6bafaef5b6569f6b0687d8cab5c742c9c5ac4b19eb1dfbb6da6aad6c67a96c95921f9fb7d53bb755ddd6732fd75b4fcf6e8f96baf5f87c9d5c44201bf0e9147f745edd866581eaadd5120365ac73a078c16ad5dd742c77afa5ea5955db2b793bab450269719cc7c2b6566fc5732e81086403720775ce2300b6aafc400ab4ad6f5bbaad923baae5e2a9a5da8004e2c9e8949f3c97df08fd9e042285e40e2a3d8fe3404f82568bdce179dbe6592df1693a4d2ea6171b18ce1eabc5d2212a448da048cc27aba54a2109445ec91d9473a19c21199b3c5187bc9240e60c7147755ac3d70fe5d5532a1ff6d157ea568bd562b5f4d292a5b25aac95d5d24f3692e0222b4422295c8c314e21e2183922f129851b31be184b1b309e17637cefc517637ce39c7346d97df1c5175f8c2fc618e31863c4d7898eb2fb627c31be185f8c2fc618cf7b3126c262a4b71e62a5b771d27befc5d389bef8e28b2fc617638c718c31c68b71cf79639438c61823bef5ed54df8b318e32d27be3ec7b319638d67b69df8b714b1ce7bde1ec7b31c631c618efc5184fdcf3da9de691d8e2f6b918d70b83d1400406f3863591a6a169e89da6a129cf51ad3e011f460f12752cf1a744d825844849cba287f71e4599f35b9058084bd34368d924a16593048e093794c3788442cf42994b86ecb7895c3d4808246cdb8cb48a3aa2e3b7f9107b687deb706cc80562ade35c059dbb9ed29c9cf6f8dc0c062bd081f14d884735eebb6d73fbf567cef7c7cb44aee0d69c1543ed49bb022b63fd3dbb23779f51a22eddebd839efdc73afe3f075224bdad55a9f934abbc9a49e72d364d3267536974d39274b86d55a2bf8d667079efa049f36b9dfebd839efdcf3cf3fafe3f04de3e27b1d3be79d771cbe2f60ce7da9f36ebe3f58afde279b765c7a964c5bd6d1872cbdc39ba619c3832c3d743bbf39a792bbbbdfebd839efbcbb97cb19c360d71d8af50846db3032ba58d3c9f6a48cf5f7ec7abc5eaf145a36333469c52fa548a594c2b4a9515463953ddfc63acaecd7697fce9691565668e42928a38eea76a3a9a179bdbc786d97caebf57a3de63acfeb60307799ece6a607172ba51075b880b997d22b5229612bb8ce030a5ba0def77a1dbd3e105eafd76bdbc0145eafd74b894a894a49e953388a54ac8fc5ba1bcbb2582c5665491008c6054addc84f23df5decd1c0c6c8d23bcc755eec59f771bbf8de9c61b09c96cd24d1759ce7c59e61a6ed62aeeb7286c1dc65320bb46a41ba0614391fcbbb3da3af2c239559ad1c5e8f170839707491a587352dfb31d67cace991e3c39ac75ce7791d0ce62e93dddce0b8ca2e8f7b998343c7e5429d9a640eeb654fd451854b6ebdbcbc3b699bc717829341ae6e5b5f09d3a9b33e118c7c7dfaa21f6b5a06254bef60bcf851c951535353b379bb6c9ab4cdc39aeb214d58f31d7a1fd670f7e29c2f0c269bbe73a28e968992a5c77cf4ee637d5ec7e1bbd94a674b04b0b2cdd55b1f4e6dc11aa9fdfa2205f7b280d2135c12e47c6d8079c03daba056ea9d04c3127ac84f0a3ee0f5432698631194524a5b8e60d26aab5b5badb51586ae251d07c78d0f68666cc8c06ac4c0bc5e5c5cb9c5fabc8ec377b395ce9651476f7921a607e9ee09767b0bd2487777d1c51a0fd2d17ab6d47a2da39452e9f945abadd6ca4ad19873cee92d4ceffaa3a7b7aca00814ccd7089545ba39e79c46a47440a45d9a5fb67e888c4930b42ea56fa01c22ef931cd2975b645b6bedf41ac3d2b6bbb9a11867b5bb5e4925832d62b51256abacd203efadd4da5ae92b9bf1ba5eb69e775385a5d55a4b69cd418cb296b653ba6d9df7d1edf3ba13de3a6737dff08dc907e3cc4229bd21e7b8aeb8ddddddeda4bbbbbb6ba28ee9323ba0b435f4d33bcf7bd59d5a8772e879af187ef34b699e1f8e577b9a7248bf6543b61e3f0c41fe40099a2ab904f4a5042b90ac3b1f724115e48268b8c8d2432e68e3827eba975f527ce1829e9ea7ad21286af5f2bdd5524a6bb538785d2fbf5e3ffcf0cd80f376b5bcf397984bcc158bb303436c1463b4e9baaecbdf3917a3f8040ec753aff7c2106185889b9ba720f59ac2e09b7204eb6a29a5b5b6c6b030181da2c986154c6ebc256ebcdbedf50bd3ace1e53af2a2b6565a698f1268d41b0e6fb1f084df30f6288d71b2f2973bf7aa7b20fd4af0c05330bc6e31772f77e517a98fc12116cce0bd9968c800f6c3b6ed503ba75c9a91b0945a5be7934a9fd4fac4ca3a850c8f4c926f8a8c44a69ea713305893cedb3176af671d389d652d8cda9bb73e70129dc3b8cc0586b29b9cc3b8e4c3e5e545c10abcc018e316b7487dc3ce71d8daaf758a090fd4cb39b77290e9f560303232f63a23b00d772fadd5565b431755500593a7af5d5f08abd3af045a020bbefa908b86124f589199e149123d5cc0884b946624aed7b289e3bdbe56eaddad7b82d036d3b308df836094a58720b48cd3c26071c9fa1c81c60f1e0d94e841cb860c0bd2af57ad95529a2755ca286928ad94562b5e40a568b251a5c9c6d2bdddb576753a29754fa85e6b06adfde1b45f2fd7182c944a034c8f0cb825ee4808ee885b827511af44010377c41dc1f4cc5caa3879696272e3e1805ae1b1f0dc750e0c37a2da7fc118755cbf4670ee16a36fe37c3b9f8274ce9c76baf92b53af965a6bab50bdd67584d65a6903b66cd95284a2803e2dcaa28957653755a185a79daf112feb2fd70bafebe5ea793f84e6d0e36527d3aede610a3e0f59f09b470984f3b005bf19f9cd88d0c8d7b88343c1d318776c6fbd283b4adafd8c08f2b74db200c762a44f2baed6523077922a45c1a28b352147f5b31ed5a12675a81e6d9e8f7c02ca1375a80e715455ba1fb2fcd961628701324471856a6707c88a8e364dc7083aa49f0294ca2afcd5b221c3685e2f9a1b7f589811397cbd6836f03e516b7dc168ac10618508cf9b69dcf626d7e569b331f172973930dc1ccbea41268ddbddc022d52d8882fa7516c5a750f6b5d64aa9adb5d64ae9a7642bb56e2b11d9d711c8cce8aeaded3226a5370dd25d0541ec947a8e3faa537b6db6aca5bf7a37d32f3fea902cd4eb65ef2615512fdf9ba97b43e4f0defc7abdeabfa28ee9ddd4eb7a19013b50c9f27a8581e379afcafabc18f66013167f5ca7b420207cf51c9443cf83d184b4cd64c160fd172412754c9ff1214ba7210b4fa9975f94ba76907e000184a73d542a0365ea2d81644f13b24702cd6a79c946839222d9237b8c50d95547306b91a0b22bcb60504a002b4458814531b28c52b16989d8f46196eaf12e35745734a1436c8a4df348cb864c3dc8a4b20b9bf4084bc2a44da589a7dfd4a884df47ebc8878fa732870a3dca44e450163da57149850bc8da751366ed822cb4508bd3c6eb6d6b22fdf3b473e2e7c31c64815acbd3663a2b067aef64a261a97ffa87bed0c51ad99d54f6b62bc2fa983777ae416e6b2d95a19285c95322b2a7d4db293802d90f797ad2c9ee5a52ec15e32e3642e72cefef011d58e539ef62f2fbae7ff76b79ee41a691af44e2d2b754905b5e0251c7ec3a69ade8944bb1212ac8a7f29cc719cf3d70e673cf39df7ce6034b90bd072a3de79d876ee4e3077260781d7b9036f215b45a66aa53af99a96009b2a720092d734fd61f0fea76add8b329fb763e63f1bff6eec642a982dcf22cefe227422ce6c5662c848d109fe579fc2640a9b3409653678121e7d22b0b9c21213ecb4788cf02673a1fc272eb1dcbadb3c06b9dca2fd6b967e4824dc3dc8c74359df4913f3d53e2457951dd5c775bd1b499de604804d63bde1328852451cb627208365d164d9f376f34c81e94e741d120b7477a7b09b79da18b72851e2d9355566a69f3b8913b240f3047c75cd6b2e92f180f89801838ab65caed95d65833e9d0a5d57a2c1668371f60d8f2add5b276b32fbeb57a78d8e337fb7561fed92cd8160c8b15d26f65bf9140ace79685b12d90fb3c7c01b3bf84f45b2c976fded9180fb983fbb6a43ce48b521b521ef251e121a407c7b13acf657697160fb9a3c542cf5aa08f96715cc7f294c81d0bde7cb10f87033997b1aec35ca43129cb8f3c7c608cb7291b120fefc1618a7970e00da6b83fb4200f6ae4457a38e8624d387d7ea4129fef5a666759bbb1ac14c62dcbb2ce62f986ad67cf0e7179febafb72cc62b158d83d2a17560bb3a44b2c6ce187b0fce5af968b63d0e57e9e756d2dec36b08db081a6cd7c71d95a2f508529bd81ae0b18e69c63e1e7f2ce7a9b14adf3d3bbcddba4e4219f57e9dafcdb2e6b76d6bd96bb629f7bb10c862db07fae5f9f317ef7f4cc736b31e83d7d3115e6160fbc6ebb7b7d929ae8bc777b6c52f49849d0936a99942004092102afbc29e51096a5dda464f916043d28b963e3a8270d3d7dd8403fc3a9a48592869a7e7a2ff1a02ee83dc91dd43bed1f0cb57f50d4fec151cfa4d5b77fa0f481920f967cfb0739ed1fecb47fd0d3fec10f4d1a11c8a5e1d240b3e5db69aee20fff769aa9761a241a2a344c344e4d8b4734514d43e4218dd1b7d304e5f0ed3442486aed343e344a68967c3b4dcf8c154d0ecd4ed4d4b7cf28b5cf2c35f54c163d11cd187dfbcc4ffb0c50fb4c50fbccd00c0e11c88605cb4b0f6774f8f6199f199d199e6fb75165e3ca86d4a46d529b940daa6fb7e16423ca86d2a46d56563696ac6c347dbb8d23a06fb781644388e8db6df4b4dbf869b701d433e9f3ed3682ae6ce87cbbcc50bb4c51bbcc51cf640cbe5d46a967f5db65a8f40c7bbbcc52cf386f976192796a97916a97a16a97b192312202d9a06c506490f87619a1f8e3c6b7cb289159f2ed32399326736476a64c8fcc0facaa691b12d2d5b7c39e266d5bda966052db128ceadb614d4538f50c2351f97658503b6ca8a867b28723980f4cc9b7d7b06a87e5b4c376da613d5135a6bebd86527b8da5f61a4d3dabf154434a04b201b10151438a6faf81147fc0bebd06510da36fafc153c3a786921a4b6a08c5584dda16b405d5c8d9826aec7c7b0c15d1b7c754c538c544c54c7d7b4c53cc518c52ccd2b7c708c510c5187d7b4c504c4fcc4fcc558c4e0ccfb7c358c13cc148c1507d3b0c1711c876643b02e3c5b7c338c51f35be1d860a0cd3b7c30cc110c114c11cc128c12c69daa6d33a42df0ed333695bcfd603f3b3f5c0007d3bccce936f87e17955bdae6074befd45f56a7a3dbda4befd85f4a2f262faf6d7d12be835f42afaf697cf4bc96bc9b7bf7a5eac5e39af9d6f7fd1410462ad587939e3db5faae28f986f7f896a7f617a717a519a34db349b96befdc5e805e92568d2ac94d4cb905411144b7ab67dfb0bcf8bcfb7bb50b5bb58b5bfe4f4ec65c729eadb5d8eda5d94967a26a73409b9107dbb4b4fbbcb4fbb0b50bb4b90cb0c11884d2209971abedd8527fe80f976d7958bceb7bb9e5c512e291795cbcac5d4344bd436d2899cbedd753469f6e8c8a574e45afa7657519251cf5cdfee5ae212fa76d74ebbaba7ddf5d33389c3b7bb80aaaebe3d37b5e727a99e491e5021652adf9e83daf350cb20be3d1f652022108b83c5210bf1ed7949fcf1faf6ec93a75a55adabac93795a4d93667fec4febc9feb4a4bebdb594c5b7b7987ac67d7bcba885d42a6a01b5825a3c1eb67c3c6c29f9f6d60e8b8a65d5caf97696132b8a35f5edac26d6114be99bb5f4ed2c2722909a461a2c28be9d65147fb4be9d25c422fa76964ed3640e0fcb87f5c30262057d549366736cce6715b2a4ae4cf58c32397dfb57d4fe1d29f5ac6158fa967c42dffeedb47f3deddf4fcf3ea02aefeadbbda676efa9dd936af7a83c2b1148d5420b2f8b6ff798e28feedb3d248fcab77b41de9057e41d794a9a569d9cbc25dfeeed4c5a9592f27aa4bc9f6ff772b07cbba7d333976fefa63cecaabebbab6fefa4ba250fbba6efcea843faf60ea8bd0b6aef86dabba28ea769b42aec7c3cec947c7bb7c3517156cee12002a9405420c6988a3fb86fe79c9a2677b8a86fe7a8342d1e71dcd1a4d5a019f492236a5a25ea4a64f4ed1cd0a4d5a3206ee8dbb99f33be75389e6fc752ed98aa1d5bb573394c4dbb4fd8e9db71513b3e52ea99fc62e93e51f049e8dbf14e3bee6989c4b76320fc420442af5c89e1dbb14efc51d534b9d37ea9344de65ca6ebd437aa67fded57ea4e35ad8d9a46a360340ae9dbef50cf6292185bbefd12cd506bbf4a9a3699ee5d123399aed0b7df9f9b3369536ada488701c3bbf32dd533d5b4b9e4359754bd8073c976f5ed9bd4b6b4357d6f4f464da3552e607891de05566d54be7d2bda8026ad067d833b43dfbef51081d017e80b3e7cfba624fe984da33b3b9b8fd3d3a47db5762b3569b7d66ea9acd596b3edf46c69d2e8cfb44ddf6e9578bedd52e9d9f7ed96a86934880659231a6491bedd0ed99f49bb5497ca025daaa06fb73a4da346d4c8f25023ebf3ed36a74a4ddaa4fa59f4d22b53d3e852dbc825a76faf45edf5a8976a9308a48ff49125bebd12c51f4b9ad63a3a42df5edb2b4fed99f5a702d1aba6b54ffb549d6fa75293d640405440d4eadbe9d30edf984ad39a888889c8496968d25a49a948a99d2a695a4735fde959cea4b5d5b4917e77ac7eaa69d367fa547dfb5c6a9f4dedf3a967b207b34a042277883be40e567cfba4127fc8a749254a5eb64fa039836aedb368fa344d0ab58d742125df3e73a6f49d6f6fab1f7ed6fa964bd25ba9bd97dabba9bd9f9aa869f2a96da43fb5f74f7b03b577507b0ff56c3ecfb7b74ed32415cc17df2eb14420307187f486b58d7498d3b74ba97649d52eadda3ba76751f10752d3e21195a6c55abb2c9a34d994b5c7a6f508fa9934216d23bde9a54d9a4aa23d024d43a186b6c209ed28b4a7d0bec24dbb8faec1b793d0dd0e93112387b7088a94bff4efbdd7bde6520165e83d98f7dcfb70bceec3b93348e4f0fabcf499237278815e7a8d2272b849b552cbaedaca8a1cb6d24b977eab7a4677e20fc9f3d3b338658ca8978e95f42ce6e0a56320c74b9ad635e978a867710a15162f1d1349c746f14a42711fcead31440e37ab972e8325871bd24b9789cae1b6f4d265b8c8e11624050c38fc768126673005d1c393319a6a9b18667c71e585d0d316285eb349f1c2187fafe30fe76e2ee470d379e9f8480eb71ea71cda261be4d04a154df1d6e9cdd661d6bd465664c46f4e7bf601ce7683e38c1c5aa2978ea32a87f6e8a5e3f82287f6e7a511d77327f93a935111cac15ba7f7c3a93737ae72c8322287d5e9a5b3847258a5a8c8610d7ae9784a0e2bd14bc75272588f5e7afc79faf4940a2aac1e004f7f26adadda46e69e452a8e98f2d443685a57a3be81134440a448fc219f02bdf408f6d513396caba8b7e0b56a99fc4b55e551c4a71f5eaa97de5633c78b187e3abdd3f374d874973fa7e8e2ca53a73d13c0d32953450edbe7a5cb54c96103bd7496510ea5d04b673dc9a12c7ae9324c64992572d8e3a5cb34c94b1fa4314c666007f74a0ea3140a37cf6e89946553ea0dd69a28af82dc2243b61ffac757cbe4962f818c3a9a0c2432d250cad25db6909293cad0a93246942c9d7e4c0a638628b274d7c72432a6dc7bc520dd82c122279591e4a3049864a944961e93c8d28d488942279b3a76b707991da3145df7ca21bbc92193525229698c51ca08e628398259fe20dbb30c728d85377a06cad183cc4869cb66552919f67adda4fc80fe0f8020470938ae945cd3b2e817ca8d4229e82dc377b39ec762cd98f0d5acb33e942dd4aec4c9d1b2ecd17e2feaf08b9423e8d14a29add6d6f808fd345147f47b4308d2b2f820441dd163c4e93142ff4db7b142233ff300fc2ac82dfd210b2f4158d411bde59a22773efc954108f2f2217738d66e1fceed29657b95543efe70bc9c2587de739dd7fa703c168b2539bb553a7bdb64e458b10692cecb5fe4f0caf80223c6cedda0d7b2de5834ea882f3072cbbc06e50e5d943d69b5ad6ec916417a6f57213fd296132e1f93c2b061e663521954f7957b16762c7b34b096fd7d229190a1e231c32456e308870c1859fabc81e329a67a38b6c0e080a185afe062e4929073b2a2482a1345de94e8b8fa514e974e2985cdd8cc74fcdf77924a19fbfafdb23f13b2fc192b41cad84c09f2bdc72f6335a264193303e9d67c04bd037cc7c55ebeeb3b96276325a85fa4563a67b76c455cbfe33c19c31103c62287b7fb3220bbcf9314bcd326ca58975b26a4bd83b42c86f43d22de47c0c81bf9d8b1bc194610f61d25e2c54a409f08cc6e21ede2dd62c70a8dfc8d3aa2dfef62273b2ee2385b7eac16a491d9f6aaa33ebd8bdefeb32786c2a47db4993e85ea8aa8c5cf583b53feb44ba3238904c6123f6f8d86c2b46997404d5ba16ddaad82248fcf0f0b4d23612ae908e9e92608f97e82f1d345d03458fb5cf2d16e73c4f0d36f9ab6d568cf72e6ccb122e829084fbd011f0e359a3c6dd32ef4110758e860072e4ca5f18314351d2857961062071aa234a9796f851239f5e104facb4334458d926ed01949224415398011054a1329e295d50d4a5b987c78b0d245c87b04735582e080e0e413ab0a25a62a43bff96b7358153bbf39cde60cf870362a553c759a44f514861a4dd262450a2ab050eae147a94910a5349e7a08244cb9e2a947a002530cf1d44da02e648aaba7be8113a8b0f2d445800215239e3a919ec59efa023e1c4ad5cfc9508619503c602a9a418d1b63082d84c88842ca8e548d23222907cf39081f0ee749481e3bc57e6f78ec1e8e8287c7533c768f02cb63af912135f1d87360bf9152c363ef811d04294a1e6329663caef1d8817c38f87abe0ebb51d0f0d77f7c38b7a99aca0b20fe65f62fae800fe7c58b1a625ee881d318554e34f1d94113379022891b5cf922ca10b40b2921ba38b2802e9e20c053f7f1e150a77d38984a57a6af574e50404270504e1ff38d5d7879d95e7107f21e81b981120fe3303efb70606e023e9cebaf32fee53d3e9cd745c087b3e9f8172824fec5797c382f18638c31c618fb013e1c8cc5952a9ef39b0f87bbd4334df294524ae995299efa8e0f870ab5d29314f7554e1aadc91aad75bc2e2bd0cb5ff9e1dba955cfe253533b5d6aa74a576408ea59fca08f5c28b962f5c219405419a2c671e1e4852e826042c411b5f65935a9ca68ea5914e27bd084141c8081058d1882a8f1200c309a18d2c14e0f64506b25d6001fcef5cdefe67973d876c505bfb98e0f67c318638c31c6d8737c3898d2272cf3a9cbfc86c713d4532f4050d0139377f17771027c382e433c05c1c30b2d378fdde6c3c197524abd18e3a9cb3e1cda3bbdf33ebccb5d3e800fc7e5a48917c0481f24dd9ef0c4aeacd88288a61c7830b250ac9091e48c1fa024416c7ee4ce26b2fc751a44edba9791f8ebaf9ed1feba003e9c0bdbfc6e9e37876d4d04fde601f8703629453d4429f2a2865a510e846a3078ea3d7ad683892a9e7acd87437d60bfd83306e271d10e8f1d001f0e964af2d9b3831f4e7e72d59247f2c89329783cf6d8878329a594ba7f3854e9d240e95b4e5b8ee3c3690d4103a2d719535e4092014913326861822974b0d4c0c90c535c5832b10b28a6010c9e3a0c6a942ee93cd5e2e912174fafb8e2081a6071c4072c80aec0820c9ba77ee3c3a1205002d292e34316533a0d382289093292400db1440dcfe0b1bbd563ec32ec37d87d600f82c6630fa167dc6327017b05b00be919021e5b51c663ffe0c3c14f41417f24e5594ecf729a0f8725f4c4122d013481e28c3064b802a2880018f1a013c553103140e207b961fac4134b063d391c14525e64904243cf114a8088410641a26468523503215c7001e8b28e9c7c7bf5e959eb23152e7868b283832331aa4c5a8c1a0309d3969c245744d5da6b50cfda876faf433deb9e51cf2d6faf484f93168fa0b8f22da72d9ff9705a5070f1d46f3a0636a215cfd2f22c97f97058b7072570b041930e39e43083da9dc1ea0c18a2506125882cb51b83bf39f8ebb00fe7da78ce63d2735ee3c3e12e0f358c3d3bf1e4b1bfb0c364788c9f50f2d863fc6e9eb7199c50e23787f970b69d9dd7f29fcd7ffefa703ea32b302e621461460c37706207a824504075e14393145433740fd4b1348af2d869cf703cf6970f07dffbd42ff5dc8591134fbd4646fd86ba0f6ad4e4a9bb7c38140529a933de3b7acf5d1f8e97a5882baff2955fa0f1c26ae2c80daaaef0028d24583cc002680b22a11844d14a8e2895cae28a573af8f085142d5090583103634707e8081ed058e2e1699b524efce6db2635c36f9be70f67830d51cbc2e42994a759aa9e7e71c5536f7d38d431c6ce0240969dbffe9180c5e83ba79d7b1f4e671485c4b60027189058628a8b221d8c141551994207264c39408241de6494159f3ca23e3da37ee4f62c266141a24a9366a448cb0bb4f831028b2daad4dae9d2a4418009a3327a70c11136b052eb1da4674a45abba67d26ea29c9e5b7acebb0f87bb936682186cb0ba32c3ea0569d4b0e7492b01103a5881c2a10929a2a8e19fc74f901e3bf7e16099bf4e6e7d4a819d1b34018413508ee050a3467cb04c7185104788629054a33a40d18443bde6b7a824b226a5af4eab5f2d70f8eade142dbaf8cac5d72d9e7cb5c1571be4f0b5561bcce06bb5010fbe7a08d54970c2e2ab4780885a75137a96e474f5d537d033fcd54fe8594ce2e285af2e829e7d38556a88a626be7d2e9941516922f5acba04cac9c971819bb49cc5d453a7d46f94a755acd4f0d45f4abc88a75e936465cb53cf31c3d3a6a41a6079ea21d0a42c9c78ea11e8d98ea74b3ffbbed65add9ff8ea35b249933995b14411395eb8808a5a0d622a071b78b1c305d40fb5ea3e7ad6397c654ae26b9d6a9b7e2dde002e27399c40df1ed62918fcec7b3484ae989aaa02638baa38258494284d96d83046168dc3b7cfa34993394a9376b3d433eab4596b9f5451aaf8f65935ad262d4a71d2c1053c282a632a49cd48500f530dc4d00107a6266add332990acd13c8a103f8025d9889ff234098a1658d3db1c0dc4a08b93362382045245ce526d47534f4f2dfa9d31613a750ab22093a07215549b60eed88c09200b9407266a2d7180a18aa35ac7280f4cd42eec86e9f2a333e04995a3da8c793bd43a196394b2b262ad633bb2889253eb5a3eab30028b9c5aa7815443512dfa9549726a3651d4a2470924d66e5c7122f2a56ab904d21fa948f1454e2d5aa945cf1e7fccc819098a50dba46a3128d9258572a9fbc768d35eab50cbe2db2453c2b8f25d8d2c47adb6da5ad3b311daa9a6d0ddddd6d6158ab44c76d76a46d117e9af4d698cb62c24e27d8e9a962591a787353fe78df13595670eba5853ddc6c7b7608cd443978fde9156c1186da45330471be99d0d1b34b46c21a5a80acae886ce0d378cc12489283a5f4c2194e4871e984195858f1b8e1c31c3851ebc90610a185f08e548f990a40aa0266520d183177410b5658c30620043135049f0e0604487862655543cc164658303a00889a183209838c34aec420a2a67a4b1058727292a78dac2278b2124183829b1e2c91254605cb133840d31c6b8210c1728098222eb144dd1b49304930d8cbc50c3174c4831a45425ca8e23848e48c202092b3f18d881628a55134c55746024c9942a8ed04116558e7cc8e24a891d2825d2809a410046425396703245185f4432c4c881892b1e7488812a0419969000d2020616313a2457ecc00a26aaa2a4bc5c11a58a9325769e98a84d8ff9841f1cb858424616a6206ad36fa4a5e08b1c6e58c2c244cf556dcaae56ba5813e2a397562fa3f792a65daab67199911cce00ba410f40dc8006216a3998ceb862450a2fa830a25ff0d1499834234f1c71460f64c410c51560d4a25760d262193a4d434f40604145935abce12394262e38559144091053b568e409149395a8234f4652b568c3475fa1672e4fe3a4d59c2da2dc00c45303941a01b0285581060cb0fcf0548b3d1f47e0e387ccee699e9e6d3badd3395dc3479754932600a0232eb88003932ea46ad1a5d4a4d5301d81852a0719102da945974f3d6b1a3e1a497246174a8cd1e40566ecd4a2cba5494b210cab1a8c91831fa6e0412d76928f2e8fa2cba2e87228ba0c8a2e8162cff0d165cfa47d5138f144c90ec8b882a5164778128484961824f1a0442d7aff00f5cce523759a9a1c3ea883d0b4568d7a0811304108f50d8880489115a8b3d0b44f87c7e7670bed5b224454748651d32e1215a6262c4e4d73a9519751724a56595197574da33a3c3e3f5928691ab74488a828c9a8692e242a4c4dd4dba9a37aaaab7a6645bdaf9a4675787c7e8894346d5b22445444311215a626ead36946cda95935ada8cfaba6713a3c3e3fd4ab51a74b9a766bd4a95053225a449d1af58cf5d497fefecb6c75efd1d36f7df4e852fdd26da2e121539f4b2ffd3af52cb4bed433a69e4df0565daa9629c130f4d4e9cd4e5d462d78abba232e95158e327278a9389daffe7d38b5bd4a04729b34712bbedda9c41f3cbedd8d1ce9dbddc795f812177222cf99b45bb4f3d77bbe1d8755cf62521857573d63454d7d3b0ea5a5a69e492a4f4446df8ee3a71d07503b8ea09eb50b8670e8e0e0f9f61b52ed37a8da6f58f50c47ce0d2c11c8b5e1da70e38b6fbf11157fc4befd06d30da76fbf5174c3e8c6d10da51b4b37849a767d7c88befdc6cfa45da00b7403e802dd08faf61b3d48befd864fcfbcab1b3adffec153fb0752543d935b585161faa356a894cbd7eba294858ad10820000000f315000030100e0684a2a1304cd420a81f140010779c5260481749e56190e4300c19648c21c60043000400448466b60900d60d667591b1acf28e8bfb18818873696479b43cdd9472af7868a072b81591c741d4ec14518f1c794428da7dec44d76ce48d3126050b727802969d3b6d58e43ba7f2410cb4a2ea2fd27257427ee36b69acbeaad06a599b742b093dd89710e93a10613766e91103d42927024cd6849a608563bd58ef726c337cdb7e1e9b17ade009901c22ee88d48674dc5769cb20d42caff287181715d4a74921136d79ad24fa73c82d61e148c3214f78e8bdd9f0f0e0b1f4011263068b445e18b23adc9894e3a3a1ec7bbbf8bb36e77557adb9607a9297b16a4060ca2b843a407020b18551d67fbdfa490a3b14c228042034792ce97c8d9ff3e40e9ba62468068444f04a55d0fa6760d53f133b9e382cba5b54184f55aa004b23913701dea3164830a06ae0ed5abbb9fca9258d892e4d8306c680258700f71e89cc3cd96f49c1b84f63887a9d47fbfedd5149ccd3fccce65a3d0a6e8a635b296af92913c590b9605c906be0987e989b7c7327d03d31aa9043752c632fcaf26b6eec4dccd7ec444b2e084967add4c6c1597e170f8b8722141d64f165b7c33c367bb8399f127a418f9dc16d70c34b2d28a46330c05157c1b438413da0869b4307464ae72398a59ae93f4e779a0aa285c64071d06e2a426c65e649f8c571ae9ca90d9a6aa7b324f364b8702255ec6984727f785a4792a631555928c424e78ac5e70081e8b2215ec9b2353d1f6dedc1b8008178a8147cdf5b846a356ed41473e8217ca779ced34caf85cceae1af41fc9ad5d84da1bb19df35ed50d6d5be0ed5f3bc5b8b6a1724b6a45156995bfed8fa3aa49786db89deca5396d2e65a0e2e924577b8edef3021b61316eda96a2c33dc49b2db985ec539b344f6f5b233b90454a2ee61a4fae7c8fb1709416625792ae77566a76eccc53323397190446ca1e1e19b1c6ba6af496131b10d9e07958e77596c45f129939cacd19c794bcddddb9666bc042b8388b16169182ca60b90391b117a91aaac9e11a8e8094094c75f3fd25507d7e14fc9458df8cb38b23da495b9896c2657284c0e548b873eab045c7a972f2693145794598dc1ae07846257d39fd5745a617674f63b0a406075f2e7d5e4216de5b1e6db062097287d8390467c65432a1d019e226dcc93e90afccbcac9757f0ba54e42802967b5c05d53f33be055eb8ac514af48267b219952acbaffb32224a34cefcae466208d5bac8c754fcff0a3ad3b0658a7a47a78497eb390178d7ce14840442a28af739c0613cdb067d80e6dcf1079cad4b0f243ab0e2e5b686de1f3e986002b504b2e5aec77e0202ae7750b8dcdc40e22506f0faee97f6ad7f0c79586d2e8c902df0fb162c239442ef07a27e8e8b740ac2a2f3f2716879ec314f2d35fd54d95bd4763296df7e8792a9ec139c074ef4d6c486073c3ab6915c84d5c7db131552859e8790ba5f46ac5cc44954e2efb467a7d7db80c6c1b9c0f5ffac293661fdbeadcd85daf4e9dbea8549eb01213f5b2e95c073c886d27012cf6ed704a01aa81d275e0d12ca7b17dee04b4547d52e050be2280add1587284145bc9514eb04c682180d2178cc4c402e2122af49f81424e27badb6e4159b6329cece2669c841caec014a78387025d9b5f8fd3e6d2a48523a47e611e66936c2ecfedfea315ad0d10715151f4c40459860de5ed589afd21dc23961301b4f21bd40d5cf550e94d563869145b68eef815acc57c28510b04ce6521343e99a9c39311672e159ab66ba3b5adb57e0380c9c5e14d87162fd475a6798d82b05c148941cac139135af26ef33b5186afaa3fc03f3ea30a25a9adb2c64a0b4c8091c08ade2834a8e38d8abd8522b1ecb445f16da81152c88526e0548472dd65aeaba0ad6bc591b03ed6619b1c41a9a45bc3a2f0b12405f4f6d04559fa738cfdb856eafc8689ee10b910c2a68f8612db9a04905718eb962e99fc7eca2b51bf3bbd374f39a700d2897bc3a3ba2e7c4198587c7b48468b2e8937570e1f952a5d9740f482c8247d91c299f7cb3274f766a114bd313587387135fb25d42c5d47806b6ab304e23121088519d371e62dd8a1c6802b66862b517a1ef871eabc96ef7535a391ce28872a3afaf54b55f2581b1c440b420511638b72bcbefad3061bc43cd8e947f7e3b8bdc61d23ca151d371c956ee057d9d5c4d9e89ac6bce203a236a43efe96a4b86d91ec74e780e942fab819eace23aea1ef0c341782442cb71b652297d675faea732e61024c07ea6681083ed407435fe66c3eb808eefd6818ac607491438d13e5c9400d24236fe838d55475c500d93417806bfc204947b07bb6f4198ab26ae9861e340871b32fcad11ae0be7282ea895af770f26b93d5c18fcc704aba5973be7320c1c3c519ec848ece50ae46eb8e5acbee20c114d67ed658b5e2eb7fd194395771480e031eeffc3034b869f6a3d33e11f3a008b7982f907b768659f920b985cd5367badad6e750756ba8c3868ee998ba3dba07defdfe2ec76a689f12451218de4abd494dec3eaacc887c9d8e446aecf2132f2564f3da145fa4964484968b62199ddd06d1900c66947d8d369b4a30966181fe27a0cfbf175c36f0954db8476d97148b37fb82d7bbf6f4ee18bfa506b85725a4c0b9fb7d0051d466caa7aca34f101048378af876305f7fa7409a9636ffa1dd20a5b353b54778309523ed1e448606a18cc1fe3a1f7d0bfe9ff83b34c3c9d26dddc052e8fe98c6c2d58ffabd0b466c4059481805895968f953456c1212461c4ec98b91a444bf760694f56f7728f8bac0697917956d15d03745355ffb0510ea4b627af923008350d8fee8fef30b6a43131e7f8ed1e9fd6f174364ed4109711cadf49ad8f4bbda127b5b75d5944a4e7c615262c8d691eda0985bbb572a126609e9eb45b24b9396219749125249bb63c68ae1612fc0348764a4ec9d066e1c3634212cf2a7364e015ab76a2087edc42ed9f07b658516c73432d11e7b65b2092c9e1f633040f8003086ff98b6b64e71dc4084b312f59af907c7418b827d71d7039619b31f8b2a15680118f002244b33e75c423fde2017533f07dde82940a733b9140a24aa649cd02098e61cad5660bd6247059d4ca54123c4c520c3bb58433e43f48b6e8bfb5118238277f886d09eea14af334ce781f643ba8a755c6f74772f16714ac76c4f8123c41c601bb4dac275678fe6a6c93930d1246ca103ce189a2d1f81ffec9e471bf6cf9fe54e501bd87e2e831d68f911e6de127d9c2bc2b2056f6e727466db58e0ba147d9a7f7141a524f27b8c2e8659257eac67ae5b8c1deeb57e8310e72d29c686fbf42190aebe34a97cdcad42b071a6c199736eaf5f692a095f0cb0958c77a92e2803163de65547453d58a7f6e13bba7b82d655184724af2120c8d09f07da3eb0aeac7af9d471f0bd11d5cf1936dc3caf3cc0be787284ff8ce94c05c7c0b8cc88c75dc196b9456648ecb40938f2f0b4cddb451471ed53f2547c76a1e44f2405030312a34aaf660577abc5cb4db566cc3c4884f7ebd71d39e62a22c6736ed906e44d986d8e4426e123fce60c174bf2425398f8f1c2740c590478e060f1f740c85a315be26e8363d4d59c109a40849047f0df445f3d932bab7b2bc13453f64144c5bb05c62fad9757dcad76729edeae954ccf772d00603ae24a7a678216a670d17ce14b32ca089c5c540d9dcfa31087f03115a483cc7701062cff4d225b947b0c872e46836e6b9a49f490a111f87d53590acc83cc957a84e3814a6eccc0bb3b9b970ac79b1d93fcb2984e1a0bf9f9c00ca20dd2fde55af48bfe4e59c3cfe1f5ea1168cd17d9e6f8cac1bf3a699818d64de79401f1b1f6e3f16052b9a8ccb769acab6cd71fbb835f111293602e968de4b15aaabc0c6507789e80dac7ff0b35fc9b6643f8a521f63ee021048f1493d72d545fb36463e61c77cdea53b20b43ab079006cbbc3ea751e0c169cc2bf5c6693545b010e70176d8143fc35fc0b3214eaccf853e0f5e5d3d811178da9077a3f492ddfcae4b88e682b66b2f313b4b12eefe7124c64c875e5e248af9c390f45764044c9e5e4ac088e38e016a088a2820e7bd16bbab1a7ed6d06b309e5a8de17343167b7ec44aa7f484b32d830337e5b40ab8cc27ad0948d479571fb0c91d0ff06a3c003c8c59166c63a35d1c6e9ab6ef43412d8ea75632d0002a5c4e1aaac52d8bc50026de9f02000261b1890d7a9635205d76bca03011273f93338bb6231e1679aac3e29f2a1ac7dbe9702d50995c2ef2272ff2b962ceab8868bbfc3b32526e339908aa7cf5631fa085ccf2c92ac4f699066dd75608f81b49648af906f728299c4206578cc8af1558be56743f7ff64659a0ed5eaef6d4d0da86bdea0577b74a72dc799f9baa292c39aab0e377ea2c0f0e59337030b78e0d3ad82317a2ad7a2632a93a5b92aabf0c45af542688569caaf18d2fd504e67736aa98ff57d213dc54c1c608e3b0c4719e4f173f7b87f77723cf09ab62c5b97989c2bdfa52bc316b47085632364201ce033f3fbb48db6791734ca0232d60398c47ad8e0d8858b37df020a178f0b600880075616bbe1258848a73f312857bf5155be1fde76f53e39ffbf48ce72be1bf7934114de5bc50f982d2f48dcf0f11a1078cf38ba0ceff0a0e654d3ae4b352efa60e85f2f14c4404db996c07e6ff5fd4b5b484b01b0fd5e13aa66ebdc4ad1e39ec935884110e9384088e514370fc59f47ecf9e9eb7c477c2507ef304b30f33196875405d1c89e974784623e5a2b8e0898f3950efb13961e31ef63d6b1dd96dcdd8b497186bc69d52500d3cdb50bc9a0ad38c54f410a92aa6445cce1ea7fd32790e7ffa6a44327e145b8bd447195e934089997605941a1c0f42d9b2c275956eac7c6033e3f667908440ae90260f3fff5eb3e4bd3f8107928f17600b7b57e7e56de9d391a87ef137ee2bbb48f0f297313e44a0eb3a4e0352a489102eb19cf2a71fbfaa991dfb7ed8c1c44de2ebc84f2dedd053931a90a72918108774b65e8ca708665238d28714e3f690a2d0f29493e080bf8fee3369c3e6bff3f8fdc6c325a124ba0e885b950f19245b30692acb241a79c2c76dbb28f79c53b42570996d52aa303bdd146673cdda0204b8e4cb5ad1b2bd296ef2f133cc78eaed51478a07cb9b7ae60d14289e30b7c36059d0ffe5ddb9bbc98193bff8321f90e69199ebdc31a3063c171d79a8d389a3fee3df15355b2099213f356ffbe94de7afd327e53a3df3a7a4b62c273a0d8965076ffae9cca6cd5553290b7a676d51d050177072251a26064bcf615865dad213227878890babf694243b265547c03f0115161f14f751de4261fbdf0d609d86705f7d8e5c40c16c390519d4edc16174f3d04b2b3851356f17179e53a5343b114bc1e62083b5b3f5bb9a699fa1a6daf6698bbffec275f07348728c4410b5fa1da50674a8d6711154dcb486c10ccda60b13851105811b1163f5864f0192c802e8b6b314ad1a672200c087b7faa124dc09dde6cf7339f6c24796624ebee0da08111368bbc147e8953868f110694330ed4d29a87205aa766f6a6a5ec4a8a46a7ee07e384d24c2e6e2a729d833ceb8a569556074669b378bd999521892d4221939a386cb18969b2c53a0cad065c56c57712bd09893a7a95177e4740a62f3ef1ebf1402bd0d7c174e89a59d08a039a460fc257b5ff8aeaa1c3525196ebc6f21a846f1acbe857a290b71a95fe7f4029e5cad1d1a79bad9cba2b7ede8845662c8ef1f962cc135aa89438fa862b875b2fc61be3666911e56ae2d67eef833f8bae87b6591c919e06fc78ea2db0994cb131e1346d8c1d346ff651164df67fc705da872a8b6029b9ce3cc67a9f23e4c1fc5d2b4f6d76afc393de3c72f34636302cd38de54a0490a5ccf59557129fdcaf80dfcfa26047e3595fa37c2df1c572792491579edfa0bdf5d1727d548c1e2c0d541396c659cdcf2294ece3b80382c97fefb427cff10826d8e08d6f713e4da133e4a7bec547ca2047353d8b45f07f80828bbc9f6074fa5304e4df578622419091db6d2b4e2852ec3f47e421dc8a545a91dad43ba48d6503060ba453989e1e3745f88ea44d1440e6e2465a795f21fc5769884149e9c8fbec937896d7d4bc838af33945a1a8c333fa8d2646bf746de4b73629be60c1f606cfaf83b755d1be618668e1e9089f354a3811e101a90eae8af20eed0f8c52f76ff5b7d2b77cfdd8f4092d191426042c8c98ca22fdd57ff8b521c82b5bddd8efd92b40fb579a569a8f1dc3b4d63e2a4b7b4bb7dd2594ca2ac1c90af314cd8ca29c1f851cd1d0c90ffd21d4e25db5e1cc75f232ac28b587c3f53dbbed685532825cafc18586a074203e8331d867ebc8e495eeade0688a7275d0b64d11656904214709a7c4941f328485005d3a9c54885d05df20c9b55789f7d8241cd553763b0232fc75bfbafd0c98fd5ebea5c3d7808361275f4c1f328f59de3567d15a49916cbc7a3959511be0b84ad0b170bcedc041756baa5b0cba5dcb30871bcce99b4b564c3039558bc3db25615bc822e0738299d0d0709d13a732a1c02124290b26cef6bbbcab4b45843b9bca2e0f2d624d8f2b5bbb1cc710b43430235cc0ea2b2ea915794a07e43710fbb9f7b52c0d0b403382539ccd8a086a4cf89d433bdfc75328f0525a933934b5cf0c4aabbd1f475b62b9543fbadc9527ca6b71379824f8891324a2c46dadaaac7445081f68ec3d350422d38f5986a04db4b0c542025b3b845e8aa0b80175af860d21ddcbb00e57c6476eee4f8ff8880a0bcdbf3611c04c65cc895063b4f9659801de1a84233e40f68eaba98aa80f9bee83560b30032f9fb0e09dbbe8ed6793f0d01a16adb8e9d36dec7d826a8489252696cbc5254876e8fc8181d81ecdf4d6bad740f12d2400f62abf9bd32ba3ba638fa8ddde5c249efb84eadf4279df5c0882dfd62c382be0c4901e0707727a8b34e02492352ec1120fd8c4ccbd746e9642dc0331a58e4b0c90a62f5154be817b7a727d8cc60970e77e0b6d956b0d105dd4d2ab1ed6d56f3122d942fd92078316d42211fc49604dacace1148833b3cb8bb25126f7bde7edbecf02e7a2cd6a034a8d3fb57ab3360f4d8bb7c61504479af62d8836acecdd3898d505408b981205dcf3a07677986ac2c7ae59ca0a9c473035c0e11f7b00ae9fba1dfc4f189dbcbb47893c89b510d71f2e8f3a710af18f3f783377a4534d6f267392411e007c016d3443ec763709eff3dd067b09ddc39bc9be059d8c56ce19893f3c30cc11114a1ecf7c20514a88b88fee5340d38a0b9d63f09c8f8356c28fb3ef8627fba79446afa195335a89f43e3226be2cfeceb1c3cd90a91356ec0312555a5aa123cb5e98f8f4d001824ea5ad0c142400e0bba4a884efedad961bbad10414612b5c201e28a63b077cf2c1d24ff14c3511aa88ca7b0dd115530e62d8dbc3fc484115d3e22d02b627f487d0c5925b9554c4618a164877888735deadb5ab35d910aab83c151a9d29f9f97ee5193de085a3c26d0a70d8e99524128dc80e25ad15390a828d12d81402b144b48137172e2ec99a188862d06b0b35980bbb653d6dd129f8384ec019db0bc838c75fdb21252b3bde17f1bdf9bac8675a162f657f0196566b03b1912b9c503f4ed6176b4289721690efef5c688701e523808ea8ce7d93019bd877cc668e3acd6c7aafe2698c389d02dbe8b4d9ceec1a285a389223ead38cc80699e62abcb44a49e0f8b68bd7c7efcd1dfa598b736c7fbfdba7ab4043cf0636cd6be873d9bdab4baefd95180dfc3c6d34433f1cc3e6fd94fdd39c469eafaf5f877fee7bffc8bbf207f4520d518d785a9b1c91ad1afa76e27111822143530b71dc2cfb4c2b2ac894318be366cc65e8d5cfc28553b68c45a421b65361833e05719b34cf93e87c0c33f9c9e19305b87bbda03ac43b7dfd6447260ce460374924a0ead048a4e507fd42ed618f3f2ae0ec1d3b8ebb695589ff0752dc768244f81a149b05a1c09665be1732445a9502fd77eedacb8491c41cdfaa2578848cb1231d26629d8443682ff88c0414d5010677d900abe0ee2ce53d93eae3f72a5b6564c91f079ea4c0820dc8fbe00550241fd35b0175a23d9034821e028733fead64744e459370f25013ae062dde9bfea843256b92b565fdda8aa9c7c2e5484c20d464959cffd9f52b6612046035e9b6a6417f2bf2a60c66a944f64a758da8763f3c87ae1feda26b9a75a9821def6dcfabab4c86e3e1dd55f9182c5a58f7da93fa33089a9d47bcd610f347981184ed33abd3f6e050abb4dfc1dd0acbed7e40aac315513e7fad017326db3e9595c4a680b7433c8d7bab67d472b09ae6d33e183f51973f4a86d43606d4b0013b748af5fcf43a74f6ad9574c90d78a2ba73d5daf0ad85530fd0f8a46c56c373b2d24a0746eccb47a62fd7c606e8435bf66404d2b7de1d53e5f9021dd61d35b5bde5fb70d2482acf020f585cb5bab3d23f529e8005d0b5973ddc442b5886043435e08857b2fdfd8367c22482ba52e6259b3b323f21a45bf486355f83548ad0aa7281efa1390346feafbf2ea4966a39543bf4b71e24267373461be8b4aca54c4a139a93afc8926a0dfe8f74a9b30f232949e1581ec8942622706f83bb882643895e944502fdbeea5669dbdb7381571baaa697ae75e4a0416ed2e6ae609be30ba589b3896fd1745b1b8d90398bcb52fe5c9607994bc1b3a2203720f2f8c400619a66000eb889592afedc8918bff076fd23ae5925b27a501387c997c26844060564410da3c39a667e0a8c29f749eb44b13102d4fc3c26f865fc508245631f2cbd2a5e17137c56ae8f8da00edc4d9c5ccfceb5633170cc0af5d2acd434c8c320fe586e836b289e04e3cab98ca89984da94ba46c427722470bb3ca521d3aa6c88e618b6da0bc58afd2abfc02d1106541cbeb186b9df9982aab185b200ffadfef448f28522c9a6496f38ef2f4aa28bc46159f98e33f48e69f5ed0daf30429dd8f21b08ef5ac14abb43984168bd4389e8b14d234be0a80a5622c51c9a02a9ccbc732560fdf8b878ca37a11cdc3db8e38c6ea5bec40d1fef0276570d31c7a333b7dc90ab7b1d9b52b220e3e25ac7a2fc1121f5e9f5ebc84eadbac71d79ef546cebb66eeac1d786f57b3ec5943978aeaa70ed8e2ac0d7a2df85cd61a6815d0464a34950f626355007eb38e42d4c3b58c581f3b83a04adbc1a332b570b05d3196e92266b23e85779b3ddb4f326a1fa8621f828859640ebcf3bbeffcfe7b5021e7af4740216c4cf76c40446e366b59c54adccdea0727ab354bd36d88d236ff60fd2a2b3dacd326ca3ea21d697946781ea4ac1d56463ec7163e3eae45e922ca017dc3331178cefd5b9a1e0301a5980e938fd85b59d4a39548f8ebd4f103182cec20a59ddcc604d5482e3e0f1a791a1dca430c5a0b1600cb3135077da0434800dd448d0447018b65369c81be34ca70829d5653efb555c6eb59583d490d1a65522e6e1b30430b9ce720a5ea2277870b4d674cbb26859db17f8632d1f34fe96e447918d5ade99ff3895150b529f3209c33ab43f60c13c927ccb3e259faa61690094f82d43812b3a8090380919701aa7b291837d04d185046b1b526cd1598f913bbe242536fc8c6590892493b1fa9013bbbcade8753e95f9ae54e8716c6b44a4e2f5a8c747b8f4d05b15ed2a2efe80b9b74f441cabdf263cd8d9971032572a07b72327f5686800bc506663d279ea87409da666c60482c57b1444eda46f39454c3e77580c679bc065a740d9d7b815f136a3c921a620377402d5a3fd00d82eaa23cbfe0640c2959644b00fca23fab7ad222c14f275060345ba89b202a5e16eb57a9feace8b4850693e8f25da2efcf7d8cb8b00fc66cf17346d39dcd1f738e3c5e1d1f16b1d268a21c513bb3ffbcc4921a6c948f8fe6125d6d66dd623bd38ed96057a0fe0e97140eb5edc3d5914959a34d6638a76197104c8bdd672aee68c4c97decf23e9cea495d77f3adad1d4e7a7e7a765148779298430511a4d530cea82b2fe247275dfa3b55d48752babd402fd9485e22bf79edd8743af11776093fed5a14758bf3380c343b108cdc4ecea1ae8f7883390ed4cccf3b4609ebdfd47bd547a4acb73bc0a409356b822ed2cd36fb16390600facedf001da0cb2deace4423a8298c844947d06ae9ff6166b43481068fa7f1455ca6b07af183d40a491ed09a26923e5566bb713126a6401fdb20a8c9030c74dbd73afd046935db39766b504cf1216c0232ccd863a086ba0bcb27bd9fad7136595ca7fedcf3597d8bc6533b1f8ff622df401b289d7b0b03b0f30351387f1868ec20e17c0bcfbf2b68f095f517cbec28dd431fed757546ad37f647f1d08b40cc447b4f9d54c4fda9cde661b66040dfe47ba983d98c2eee7ffd4832c93f5df8d2a172f871ba70bc318e2203db7beecded5a4eb544215244eee14c2c4c766a3009e1aafa8be7f235531a5ccb96bfc14043e7c47d10b2099049f95d186f89a17a66f043260de3a1636d99c72f0962e9b8aaffa564aa576a16825c72c99ce717005dece6eecc61dfccbef63d3bb1d949b3cacf98f695b94c288d5b29127c359b4fddeba7d037b8608742cdee3179316b454aeb915d769041eac6d1b98f53f8ed989f5d263b34c4e7a593849137fbff55d32420d7495e671ca61e4a375f34ffcf53399877f51f233943bbabe4696dfb9b9aa21f1c532a756002a7157c439fb674589ec0acd4e6307df73d791f1a590e726ac819915433ea5815300e60925d077fa22f1eb1143374a8bc64256472e8d3e29a2bced074e6ae82c57e1cf06895a0adff535251bdc4ec3de952900ee69516f833cc73f623f18279b6461060e24ae16bbe672fd223ebb94145de6f8d502993024e5a56750d3165d7a5dc2b123749918e38d0a469c8a0f08ad7c47073772445eae3429c4a884cb26982c0fcbd4b73ea5a2d65af38f5a0aaf75618750d94873caeed9a49d1807f4f1cdfcf69041bc019ab305eca5e3b0ff7fd203383b10c3fdf3ef5610fa1a44f8e4f38316bb0cdea16a90cb94dd4e36551f5b79632d7c9f0cb78fd21b7456cdea395e0e071b9f3ca74f125968cff4d8af723ef9afde67a58ba10cd46379c6d33866b8583fcaeba055ed0152dcb3e157d5bed1ef8d78cdc09548105825c6053c74641696459d694a5df6c22a11d8ef51ca096251e17e9bdbd6f09f03aac7a6bb1728580105164230d071d23267ccadc8fbf872044e314f61308bd6e8b70bf80c2635fedce30608bc6016851609bea9a0e24110c932ac0f3a66bb1c0b190d75b6badc73ee9edfacc505e8bfe62a226e717a8e874304247445a962f9c1d12de5e10ede5491c1183a69c7151a18d179d56e7c09070ffdfe8c4630c11048f17c0505fa98500e405605ef2408ae64dabcf441f0d264a234881e5f5233ce5e6699af3830ca861ed265cfaadefb808a630d80559b6669529e7295cda3ca1ac5bf24e2643c39f15197f284315622927b2bf7d73cb2a451bb19f56c32b02114bc57a699041dc57775306cb44321ffb3c4c089a64ec346699856b49f2380fa4ea42ceb6a0caa86925578b1fd4fbc376bae72e254f69a5283f29b5a00078ba58f66355f8cb3a9744f94c6fd7abc906a38bc58106b8df6205e4793a80cd9d52618e8c6dad6ae797416205060455adac9fecd6dc9e339f8601c156c8785d66f16107f72d365e7ebb5ece284d8b2d3c61ff5a36b347e72e7c60f219a6d408d596235418ffab052bb8a4bde32fb8d22775a85b9988324ebac10261cea6236c5d5cb15eacc567d1ca0249bf49976b16236a1d8eb48c5388b25026499a493dee889291bec2229632636d24c5c06ef8a45cdc70d4395c8160e2e6980c4d6dc23138389ce26eed83302daf9e80fe06aea426d771ca7f5152fca3894d6e1213983d24f3bc0b63c206f21615106d71b38b9b69d1215a6582ca8710a8e1a235cab6bae7b62d777495a65c52b32f50d94b1cd60c515a804e6afaeaf206ce1901ab6852d74d22e98633bf0440da1bc8333fcbbf58d26e19854b84b0784666171c4561b7817b93b162c3c36677fcff33fee1932b4eca4244b594e2996ef11ac2f9eaa300b757d12b6d2011b780d90d3ea9ff9ecb487b126238e7b04fe683840edabc0168fb4adcc7fa99decd9d112e763b852a5233f9b1ca91d00fbc87219f8ffb0e130097bcd8d3d8b017c8f2e1c122ddef94ad93a1d4a41416527c4c92d6a99986dc77642c8dbb1a5ba6b418d730ad49ff1380a72d6285dab0bd1de60b02d1ad8efda673a792523c0d9e423254e4afd519e53acb8474af3512d8b37be12fa1ce882a714db8b135d455ff2362cf15374ff45d6187a8143014093d17dabe2a24f7757a66a798ada64007a5db4a8948046896518b502d61e92087ecacbd4982cf8d413686397295114097429681cd2b94a6e72ab5c2d3c9383f964c8aa09590e925113a977342ef1458908a8947b0b119b05491b97fd90b6619fb064a2fd0ae5c0f47e47eca3e8bcae5ecb20c045d087dda42c911038db3eeac70159c7130f56b01869adf6941b6f4d1ba68b31d32ab45b2621741ee9d0813192a21793d6a8255ab2c6e19aacec9d23ba23cafd7a3568fb862d4b92a4e3e2df3b94f5574ef617ad60b920fa8c9223bcb0648fd7061e5f5d851a095e2eda6d16eef0b54b3e97e9d1d96825184bd84bc7e91fe4282ec5e4c366736e3950eef2708e4308cc10480dd64ef574328bc488ac0675d310c96ec42af28b1309530f662e9404527d8128d0df6e691d0c2dc608be4bc68fb21973eb8b983c1059436bfc5497099937f423a4809301b4d74672f221f064e736885f45cd0ef373062c465a107c9264ef0085e04b58112f214327d8969c992094554de5deaf0f6dc8fb5aaa6b4f65d09e9859c19785c58627227003ef710a0e5ee46d6fcb2d0aceaa8abed18e8068e4b3c74615d6c7e9d95f40ae2da37a293f49614efbf711e349fbf9db717ccef7bd312a48e11576a69d6d0efa4c8e270cc6f46f234b93c2d671a13694e154f13678ebfe38bc99eb5149d73438859e796c2a42d7ad3e401da8ad92ee275894ad5ee595945fcf2c24ba800531d7e363065e044759d65a94e16065595688ec98140a0fd7e3582e356583f18d47732f065d8c4c13899206b001e345b8ed5a32ea0181fff656890bfc7b302e4f3d660fa8087dfb640cb3c66ba2687a97b8d93c2f9bf5892fdb0940da6aefaf7916089b97e7a215e80fb49c5a335382d95990f56dd7419e506fa95372051f01968a920b1d01f96b6f683298a1de0da8ec855e68dd8dfb2967311e2f968e7e3363871f70eed2f6e47bc1a07ccb7f02b6c634986283c295488ab594d162f3f19e2fa14669caaf343fbef581c05606966b61da1100a7dd8c43b957ae4e32d2c60aea31c9f8d04a1460786c1c158472e2557dc90141263ad168d6d54bf31572a34273100eaa11982aee9b2ca366632dfb64a55c9bf0635c266bd5deb433baba08019bdffd980515bff3b3ada9dd6ea92ba8aab2d55e9ff3ff73df645a134c22cf27f2bb908fa2546f5f8b82b9d60bdbf88d3c02a4ea0fb2da8737a13329adefbe288652a5920fa72611880d7a7f630428eb7938602016c67e15dd3190e4c1b1d928a0001c477da0c2b7d5ae19c37294ec84072c5ec519d8f07664845c1033e53cecb44b32b358274d4da147c44fa37259c6bd3b771189c951585883c68ce933c0ad1bae1b45bb56627fe1e1774a64300ee16665401d2145a6f73b0334872c687f48350d34d050992cbd578e9846a39b7bf3b5988f7534060e9551456f29b1a0b52ff43563f861ce2e69f58cd981570941834c19fc66e35622bb57c4a7cd0553d66bd31a715808f4cee0bba54e0f5a4274829a33c9d041dcf3b2f7d072999783d286566bd1b4e1e550a013b6160c18ce88376133bef0cba0a33d202a80029ba7f024f9c50b3914c5ff661461c0962715ce00fba26fcc102b41cfee18c8fba246902dfeb1b770f273d28eba809c7263e923a96e34770c2d3ff94289ad0b396e5d71a8b79a1a24641b53be70e2e7203c01cfe463a0c37acb0a3f72aaaed6d72c3bfd94b3236ed1e2ae235fdec5b560605f956db9f6415686c758014c1b0d75621b33d47660a6ba0e79a2b0b62150e27670facfee15ea9ee97d794b2c7b2135a925e6da7c2df9f2680f42eab304003bda547f192f06287b1bbc28f5f9276c3d421e151d825199d43da413c28454e9f33bd4761b74918c3081aa34dfa573ee66dd9687b5fdac7c9c80913171a2a5d60a99d8b4bab9a941adbd2134d3db6c2124b5a8d5a398305eb68f0345959af20abbed14a17a4bc1ce02bdd22caf2693704e1976a08a805de132829a20ad7caa790506412b5cb58339e52062446e997634593930c3f56f4065a94792f6d40ecf661d31173e041575f788929fbb4671602930afacde175dbf1e9cbbe5b4fa705034105c34d6fd18bfd7d6e50df89d957371b51c082c4a91d4ce1916bb210a17fef96d477bebb077e6ef3b02b402464945bd08354386210f5b02b46f7b530129ab10505c8c534fa9ebd97372e4ebde118da94cdf9d41819e5309889fb23c5361dc5bce3387185ced699508027d44eb8eedebdf9c61888b3fa5f7a11bdbea61401f9b820b80a92fb2033c2db9db082543e71e55bd0d27788c396a1ee6173fb5cd1895668c7edd413d485b0ce8ad67a828ee20ed3d8c7e282eb394edc3f26e4157c2efd26d00dec1af85ea031c335bcbcdaabce6683c10a97a9283f894778944d3a0410ea4a0333a2fc5e57227649c68f0aab81c1fac850fc574c7442d4e98589498b431cb871b6c8b4799d20ab13b72ea1a53cfcc7c35a2ba98d35b1b8190dda91b5ce58a799128544c415fd5c990e033e0ba11a4d78b70f3174590f671293a24f31b591f7e66461dac51c28df0b0c909ef2e6afcbfdcefb90bcaa1298bb354b7028916a33dd8499422d9c0d12927aaa67b335cedb459892632f427433733a52f032c102f0107df22d60ecb5767befc707522929a6c117e17248cf8da88fdcda1a37d9b7f57ab0c2419940407f40cc0a690940cd8d11a12ae70d00a1870a2cd9688d1a6216c8b56f631fe961726f052a45116a193281d83a5615187b97610ba235f27cdf2bdd32860ada516cfa5e51396eb4493b56f760c8891b4ce86d7f7919f7ba22dc7ffd07c1048b5058a74913b95798f5d6f47f12191f7ac61905b8faca8dc57ba188fe747bbfe620d01cb5a023795582faad28799afe55836babd39865038cc5d4fa265b122b3bd4a59677bbb96011a5f346185322d915cd28d3340cd3b5a551ab3053252b79bd3e0993e5fe3cf188ff177e1b0ae47cc06769c5f9880cc3037ca3badedc18466ec423d274bf96145b16ba13f769bfb60310da65bf924e771e023b127aef0523d4a708123af072e0193be5ead1a25a5f749789c07e8f45d030a3e3738db3c1a14f8a76b585e56a94d0ab8e829f03a38c111062e746216cfc0b5dc389208025f9e181dce4839ba906092f466e4e571fbe6aa74251a160524f3c66e41d8d65273b1a96c09c8934f517ece5234267a1c11544b168a7a1f51d82d2410b4881e0098bcbad2eeb8112923b9a0b3e1150cb94955250c0cc0f5e0254e2004c06d89a50f56f31608ad22b91bd8ecbe981391337221b4c0ea7e85c0a69178ad8b94c8f43761e7be67ecfed231aa8fa1e924d5140d9c776aafe8a3a6b1ac3141cc1142af91fb48dff8d734aa478bfc1490a81ad012a708c106544263311becbfb32a434e4d6bea6e5b73e43c4026e305671eb4ab81ac4fd24e5914499db8882397761f5ffceb2b7ff886bb42532ac4acc88d08826da4605c60fa600183536304b2b0f69d7dd881301a35c20cb39dd8f4d99ab6a6ba42b41b18a0a22327abbfa7e909c8daef653c251cf051deea38079b16d5fcf0d78d96919048ee1ef5c2afe74e819d13546acfe1a98d3bf1b15a8867fc2bd087fbbfa633c07f057e7a6630115e9481d1ea70d5003e4ead2022aefd70a1d45e3cd9156e75f2733bd3da820039aa66d42aa1c0528928bec1014e717e19382c7d8303dbac427144b49386b997e50d3fbd69eb29033724f62a5c80c6913bd38c12db82b0bcb56b1252144a26769a266377410deefdac694f01d0832c9cc5f634adf995a082a6bdbc628cc9b5b26b191cf1e3b44d6fba995feb32e438b65ee2954edd8581972a5937b02023ad09127075b6248fc8e638327f674e2d4b37877fe90dc6f7ea98b3081ec8f14d8994b165bbc9e81f5c19cfc7890433609173fdc23889fcdd40de1b5a02428b1b1477e69e66137ef4ad8def8293c2f3582eb3d91ec93854e8b6feca0c9dd3958694414a004e20c3181c083a9883afdd357717ec354840211df2e2d8b14fa72b161d96bfc071022d2705210888ec6450c52e9ac9f7961a9b0654212850db6029d38532a363572d98ea82bb188ecb523a8947859b791512a089d33295f47efa4cd94736c4b1e11b6b2546391994f94314aeaf434a063929918ac3c4cbf3a1738f1bb2129c8a0d32772b024e963a73b8e69de1b638c269701612cf788916afc878361b845bfbef588ed4530d7004765498608627f7d1fb7b2e6f7b91c006828007a2188e1be866cfe49c1125b0961164d5991cd3659cf89245f7772bc433b5059064052ed7ad082aecc1f3dfd63878253b9d11940ec3567233eefe07b9687f2099495e7e8b36f13effe5cf6109d6315096bb9b1d41d842e79a7ca6d161ea7c63043519883a8628c2a61240fa9ca0aaceb046050267a0884ea0389b5885c818780357f729a90eb288e977af39b80c8e930564d9a6db70ac149817a483463317496d704f84b84f3821e5425e981c7a9f285d043a384224904e963f3596d0a3ab6da8abe65a3c5f3295666745e172bb8044b248fece20557020db6ddd201d738041a6b829f6b74187e597c7a09f9a27f1888de719d577b4ebd0bf15739622954e6ebc1219305988b4a4b806f1e03807021e11915aa94e411fd3c87049876a335ad740e42c0234f3f01e7cd4ab0a8a852b480afd913d3317c334d3246452e6718cdf4c9701fd850cd622457fb5db16a816b8fda068a63e8ef9e101ebe42f18570b2bce6a5441bc8c603f14900c4ffa8485d2f4684122a00146855cca98fa84e53a48b8a18863a5c5fe536686381b9206da4a47d870aa50f2c2f3d015d2befb9ef15d4636bebca6b5a47607bd32497e1ba21e325a23b9575bba19f91c6fc6a3385f88f0ae2437c7d5d2c60c1751eccb3f21a1cad57b0b8fe29d53c26867f80796fcd58441b740dbba2a9a0aba888caea5829f31c788c4bedb7e7204c9b2e625b7a1ea587061cf45888a9e6e6caf76c522bba93e997531947890748aee631f2cbaf041abb415e5ccf40de0da90448c8b965a1c9520739f016077c4f210e88b02ebdcc5011c2f8677bd5801c55ea2aaf122c8aec5ad6b235c20563fd3700adbf1648fc4affe2908fffdb8776099828055b4c105ce05a38951c1885d094589ed5167508be68d00779535b58ad36040e7dbb11583a539f62a5a2caf789fb1133d1e791ad4bdd64e95269ada628457afbfc2fac5232329e20a7da3c7a7c976d0ba846bc38e506f3d0061fe0a4cc4713bcc3ece79575fb165010812380d0bf61dd534459c646c2013c82aa24988d38f0e1cfd40854dc4218475ff004a57f47069c528675e0d83a62ceec4aa636cbfbe2c97806c1ea17ccc7aa267a0e92574da0b655b56e1dd747d91ae13b9f03c0545eb3f489e2106f906e70c6debee75864c49da19f62a7c3b7e69100535f5ed5bbe580513af870d800a3cae5f9cf952c001f6e06413451c196b77510a8dc0fa0e805fc72660f3524c112b0e1cb479a4a85fc39e154c159630b628e529c88f12cd432feb3a0fb9c35976b43d70bcbc02f94516f93f9e2c1f2fb8077adb293f16795813daff2992a00e747e72ca8f8c85063ccf5e4361f38cd46c142cf96a7bb340a1ee521f11f7c9d7220fdce9ed0060a4a58db57095b616fcf4409dcbd22fd8707b0ccabce4193b7aba9e5666b3c8b42819c4fcaef1feb086ceb6f1233a76493cf2a414df79753087835491998d74f6a002b7026a78fd00b79e291b32ceabaab21f4547651a3196cd43fa5f8df92aabc1443114ecce46f242549439bf9e212f90588cabd4f36206a8f1f2005ca398ea9d43789e693752fa5e877de998cd968a21644a6d3e8b59f9dd6339d0127c2ac09a0fc1c8a2bd505cafa18a8552345a7d1c24598db513e96c785453c5cb389bc5934b8eeb5c74542ac92484fcc4db38b70a9856e0433c51a2896873d14ec474e3470620222b2839a7d73a685c023cc10f3487dc0c7bd1f12e623c2b03bfbd96a885412660d3bec3dd1667e946beb9084797d6d07165a66673b56ad40e2a7bd1fe218957b3f11287a3ddc93e992d81ea86f56ea69248699872b1acf46c44a65c716bc8eb2d803b48aca9670ebdc276670055453a44b0ef344cd308b4bb136e3eb0d7712f32a8d70be906013237d85366bf60a3617ffc277c04ae99d5757eb815e5bc01ba7f7b17d25c6cab43c7c66a1b0a0442faa14fe3a906874d8d50be1a25ba3fb53cd54c45c51d793e4ba242c9a449601f7f0632ce875cfd4cf188258555c023ed1e83b0b168c4954e81f6caa293602882e3e4a4c44eabec412f5252a46c8019ee15a89fa805822384e2b07d0f915234a2705a1b291439c8ea94e225bf89c388e707f39d6e255e26ddb110a5d1f11513e60883a200d1fdd88bea1aea020c2dbf089e3d6d9f3efe4527d80b6a99bd126b8e0fcefe26f1ae8b23dd50b96dfa80acd09854df085a69e169cba6838b2bd72d84b9b340d698d37a2fd6fbbe9e6c48d9ba63d510ea985a302eab8cb42b602a139a074aa34ec380243acdbec4ca101b5ed440065f62b92acce9ec871a43edae16890d1c28f115f2ecb424a8c03c4e6baa5c480d97f670a04c8ca6d3d03cc610d312d29c391e4d21eca7c91836521b89fd11462ba819712ed1196f469f2e6e65da7e14583656dc5142d29ffaa8a13e21d0a01e07fb28b053be0bfcb524bca104eed95c5c0ff91f9850c4f2f2d852fe87852208ec961cd71a6602ad115ad988aaeda050a863345cc14635dac9c1f7f87ec5811735128ff96ec856e8a426e1d55fbe44c20baccaf26caf4989cd5bda3b911d96c1f299fbbd9df9c0fff70dfb2bd04cca4f4966b2370e6eae62b31d974e8054e0245c3ac0f470461da5872206331bfb765c2eae675a6630cd1a64648995207e2dea1e09e82d01b326d3e28aecf3e990ac68562a4f002df59ed347d322827b66c477497fe5a7068e71dbe90ad601ef11fb6d250087d4054dcd15b69657f9f10b31df8cbc3b17194ad6e1cb6e5004b6b2da076359bc8d6b6838ba63fc9f7dfc7f9907484d96a671f8e97df4894738328745169a01b52cb248419c0c47e6e78e1c59e242296e6c4c8e7ce70861dc0f0322de4a98c9f692404b61d02aa6ecf61206ce9a4008de0bf7ccb5507c974866178ff9de125a17653469e2f42be5ff833453181809579bbb837d65995adc3ebd3bf293b0e90ad44a92a7e2bfeb8ff853b510594c2c5896e58cdeb396536750806ecb49bd729f3ee8db708383932e2a0a3f41c7fd49558873fc01bc7bebc7b0b7b99ee4191f9cd12c47eca954941c49db9eeb8d69ac7f95497477daeefca441913e00ecf5c94874dfd44d17f544e7f6ea7e0d4d23bbc28daf58354469c21314b25138f51cf4cabd38c8fd6c3d0f4cfa663f74967927cfb3e0eb0dc924976c9c1c61fa084b9e58c71afd31264952105f2ce81256f51ad5b2aca19fb4764c0248d8117eaad366935162d586abc96880c758458afd2f3b7c4f745ac50829eb8b6224357a9d3aa1d2407e522d01976094f56147538cca5aecd54f94aa7a5ed43692ea2e00b249cb156cded5abe4463ce69c9467175e29766d313ee8b1637672be331be34ca819f8ce74d8d21c8c28f2adfe959d31936822c5743d5e8410775813a1e53203fa015e6c64029c1f32d0d5340ca230eeabc2ef6f9a26d619b7c672744f1fbb066dfa71c2819865c3c4c73d1c9c8ef4b6844a2168eeb1c1727455e9903abf358242aa870d4cf823ee2ac83cb301001fd380d5f4eb34bff66443526e2b424c3766b6026a8d66e366ebd1b92246a424b997f5b07725758d7a75504baf871ecd1a237cbda8c9a8adc261354ab8b7e0722cba88a6c812c32e8ccc7f872b84c3d8e2735bdd38a396c2c5ab8146e7f5d783629ee3fe9e1ecb9b6f0523b5b7055d677c0d2c305be88633c7121218ea6dda1b11ed5d9a75ac5bd4c7a6ef4f4c98b52fd4c255e5d1e455f94ee0e12b31508220715182f89aac61ba75f8cbf6317c8e4e435c3a57fdc1fdee094c61d58adb51f2f5896e0e46579298236b8e4c6f97f7f38a5c8fe8ea30754bb4a1dd5c2b27a49b92120ec8f8068145e41b70972e8a719ac6496e641990dd0ba9c9adc06cad1911304fd59a40bc60918ae0942f314c770136e30b1f695ed43031e50074bd681e51d8f454ec885876ecf4635ddfa8a6a777132d6e204f5068fce9d5fd3145468cb3ca8426cb932ff61e58be5097c2af2e7c5104941c55d9c2af109141402589317646f19707965fbec0a82c1ceff9964e2424e8046b0834f6baae288b288d3bad19ffe32e5f44b8d81b7df2bc1fe3964e1c4da81b1e4424cba1644b62f40a59a682184cc21b926018bd4afbd43689187885afc236c02943ac0c4def67cb094357e2bb490807d9ee5a23eef3594b8d32bac81ce59c2a4541bb00815758e52ed67953b38c971fab0d20f544b92a169e88e0423a0ef3349340bb11cd0353c528798622990f358be4b169ac22935c96e26b99bb007bb6369f873312f1a0dfcd9b137406395d7f180f6da780d7633adfcf7651e5af13b1878e362743bb64a721c7514f6ce56bfac17e05232939421bae781b6832a5bb431fc9c70c93f3fd3839f12c49c0f35ac846a43508595843d1c35269ac080a6bb233c520c039ae20dcd41de3bb88d793b9e07764bbf8e81de0a47a68c8772f6357136333f7a8e311288ebb2e7b85aed49cb3f333c81b3d15e222b5a5bf636920e8bc99e7ad7e9b71e33c5aa409dc84fb1c7637b3758a2006128e8a1f713adee44da3737140bb931d32263d5a6a71ef7d7753b5e3aeb68f1b6d0316f699f69da482aa4a5a1226d32bdc28a30ac64bac2ad1cc02be2caa8ae86398a83c3080e6c99e016d0c5118ab37840a756defdd906ea9e3eb8c4041aadd26f25e0a816174e958014536db4f2910be60feacb69506af53525cf37d326935e8e6c6e432997452535c90e8be614feb0b9a25517fd46cb0526aaf8c696ffab383c528310c881a095a84d72da098ca411272498259aa6cbb25892ba069381adb88fdadf52cc167c8a9fe183d5c1921f2459cd1e13474d1fd3c4a722eb0bab80ce6d490590b3fd791716dfb868235b5f736b25a32dbe1770eb7d439746a045d91afaec02b174543262a59228ee16705b966a760e0772987c09718eb8ccd32acec78741c6dec23463d474c8db136194cf324662dfb72447001290c8d6e8b542586b48018d6256b1dac889ea69cf95d98948305cfbb1163193f2667a8824c1474df28fc8d2ee6877744de2b0e6ebf06bf652fa8b16980a77eed5f9eb857e91146ae264ae9c7dfbfabd5a652bd2a585eb70485d177371d926757d2144698132f628d1f7657ba7c800b8292519447b93035da282899994b529551d0bd3e9a89322fc1c58a03fe2edf50c6496dc09bc38df6f4439ccaef572ceb58e7e61b5bcd28ab9c27f2a29361799ac04d9a824197824cc88a0cec0892115688f95a66a9e96356a6c711ab98c42633c8e3640adb081ee12f24ee2d71995588e3985ca68a80d3e65f49ce27903dca0655a8489369c9e26fbe616a76c1988dad3555dec884f4635aef265203b4b8ab9f9cb9711c8569601c6a034018f74eabc543df0ec3509987ce6d00e1fb69b48113fe08e649245cb6246e74fb9c78c76bbc0821a56895bf2da60972a248a4367210571c350a22ea48e0a4a309a9f169ba71286a67f36d5b66eca0d483a41bbfe83db8b55bda4d9e5ba8e3e4fb7e93fca8bcfee0bc3ac454a6ba416adb194cabcda8dc65c2e75d6adef359e4109119149bb1e5a37b7eb8263a73466073b0713d951639548da018e1f683b50a202c9a93b548b17de1c44144aefbb02898532851286c2b66449295ad8fe9cf4ca621aa98c27478bc4de3476f6f2c74b0e3f039eec5a9139a50c58dc96f68dd14ca3e7329dc8383d50056891d5dc025144e7eeacbea12c6d27868c87ef9d7e270c3ecc02e3717bcd81bb07c29d373626613cb06fc9c16ad9cbc7e8fe423363c3446c33d31ab23e6d8311c417bf40dd08dacff9248076ee631ad0adaecb02b7d629f9bf886325692c6598a19ac1d7b5f82a5434b4f398233558ca1ff9e6d47c21daaa430f8b9e9d985cf80fc1e9217054aedb9104094d43a59a5239f12146f0258bdbfc9450086e74d65359187959a52a3f1fbb4c8dba550c14d929d3314f29c27dc50b8a5e645ffedc130a7c865d9bce406621e08e85ba6a244290f60bccdb12822108078eae83bca7512b8eac695ef2ee9cd26b669f2fb9129a595298c8fe0f9bac3686d1dc6075166c2310c8beb9ba9f496a961852ad739c8f039670e054b11301e7d7f6a93aa88160a79b035855e57b35666345112ec251967a8556d343549156d871b5ee2615a3bfaf0049afefd9d793f1f201302b807407e759fd982ee4bbfb1296b49b48a7b75dee0d72a0c76765f1f6cb349348a0142d58da8448fe1a9c91564ac33183c6c4c40d648402060d94fd12aae00dcd5c58f3f5a649025c8640d3c08c14db05a86046ba3cfc6856a784d59cd1fed5feb13385cdc2717ebc81458276c09612589dd089e2cd0ceefa06d856402e9679c0cb85b2d99da7d14b7e7234293a216d910f5680badcce13154468d76e982cb7235562fa57ad6098b1274c7668ae3a6eaf9c87da4112b64057b52c5f8f5d0b3eea0dcc7f12091358fa8662b8eb2d1c49e71d979f4ec1d79222fb6f01d26282a093c281f6d4af8ba713601c4827c47988d1de2a1ceb04717b4066b74b963d6d8a1e3cea82f1b3e113b2c27af7db09d2ff109e03a4920cd6c13342ffa656ea9aad27152f232e588c0b1a5dbfc75ad9105f410e9f62e57efb2beffb50aaeb1c3e4f647ef39aca5df2f264723f7d10d2a329036d3615edbd9489a1f6da589f765f886ad6b8e47a6b39879b6713b98eb5c0562f4c16abc8d13ca3f8d2297254263fed3672148bfa59322a39ba0bf7e7190eb052517c05f8bd0bab632212083472daed8ef448e6738c1f70b820e237205094e8b19fd92ac28ead429bd13dcf8a2b1406d14dbad772062581c87b456eed2bb035f6e18e91a952420d9c76491545646f6b9100babadf1e8306fb6402906d2980d9db0de0c8948871a339433ffe1b21c35562771c6d363cf7194006514d6b80a8134beb8fba828c0471ed191c1e099953dba77beb62ae8fe947c5815801061ca5570cfb5987c381bf11a549cec080e0ebee9040dcea7ad59734519a7ed8f1016f6ec870320d9bc11f9bfaf77e5b4e881d5935ef30493b240057549a0a6694315bd3b5f153f7186601fdb115addcf38f056164d7b5c24b3f41bbdbd7a89814157d443ddb720c3eb13b33367203c931ef17fb6d0595185e126b43572d695f6a180e0a604b3c8e7f28afda505e09c69e976afd3316a4021756cd7f5b704ef7abdad41d12a215dd6fbb9d37f395f8a97e2935b86c8fe79c67d9b5df9f1cf511be80e0c6fae6b6ac01566143d3bf9360c7feecedafa336befdf8cab56c2f8a90dc95489899522492222ba9863042dd269421c94e217421416ac321d494ef85695e02e106d83000adeef695a942e3086c000fe959c5db250541572924d6221c58080f25ff9d71318afd2691ac0bdc43112887ca0d79928b5aab7711f753cb211822f5033a9508a54b37addfc0406c054b609ddd0e45e14e37fafee58fe647fae67de249527390b8b645239dccb762b3f2324ae556f03d2bedec5a602f78a843e297d4013b64007e31a71c308772360960349d614774eb29cd6f87d2e19a681b3ce015fddcd3004dd0e30715eda04316258c188f1559722e8a2a46483d3c17702e97f4aa17bec10c185116b7e0573855392064aec31739a6a59b542d5d77715440aad5af4b9781e3d8e8defeee3c1b48e66cc0f2181dcc00699bae4ce1b382cd0fb874cf1b090765e3d2ed4c04e5d2a53c98a4b0579a539619d8d3cfbaa418699d36ddb3ac4d77151f26cd36dd07799b2e8ab8498473d32507322ec3b7a24a365e5aeb76919206ba2af5b1b33a9a0026ab6f01a8325287d984195ceb69c36bc501658a7b34811882c4683c9809c924e1e41f5cc04ca98a7476ff1e01684613c80e8620d7fd208d6367b004f965f62e8d11e0ccf7c5cf84f83a62829ec0144178272f45dfa980a12d751a8a3c08194d209bbd9377f70387b2d71c4d20c7a4bb65bdc4c82b20c69db6025d7519d81beaf2d6fa7cabbfad571547095009385fe97b9834d270b29732a03957e968025f3009884c71652c51d0e126c0b734c5efcb4c80ba892747017a6602d5a983286dcc4f00cc0478963070c546b361e0f123c359816065306e2ad7f9e7b99da574062275a4de6502024f7044bc3506ef706f31e2cb000d057f7b1f11932e13187dc2e303facfba82e0554f8f128cca3b7dbe8765a32e62c104ceee0984326900b6d97ab3bb84469900426fc868c0e15e6c8eb0fd528406a4f20f77bea483a654a8c79c3481758b092525d341655c131ba98124cace60861efae24cb285b9224f4c40149a2f35b70bf6f46f9d0f218cb2744a75138985b6929542da91aa5322e41aa085bc9835dc2037a51d38343c065b8930d0e0c3d908c286bb7e112b400efa123342f4fbcc4c6583bdb1e1f6863482509e8ab2a99de735ffe3084eed9d800e86db2e6fc36547085ca1786b0f71ed2904ae547ec3155008b577a5c361ae807d5cb4627713dab12715a4e069944b134423f8dab6db6301d00e3709096140630d4ca789377ea0ec4a35a1aa29970c71694a2cf88b1eb5ca06dfebb2bfba67f1863b6ad5ed602a6e45e33befb4663ebf06f6515872e4f7d7f20fce00eafe5be2b6f43a57241c2cac22ec8bd625b5f1a211f6cfaa4cf5ae5d1224e8e63f79a077ffff8fda597a1fffe1220f1abde35ce081a45ed0ae9dadad12d971c147827d82367c964f22e13f6400d6243fc95943d45fa0bb9a0115f8b438a3bfb3802ba3472ae2ef233fabc576a87a03b1031ead2fa415c08c4b5bfd703cd9be9119e05a5d773beb616567c0e9ea0cd892221821f221cc8c7c235c1dc40ce89ffa6db29a0371f5f36ad25a55f51e5051b5ea115341024fc1ac3ef32e4fe8d7b88a2790966cb8c75535ec910ab162a9e053ae612f3dcfe81ef5923cf652642e8d0ba42af09bc6ff38ced3c666fc03ba96ec2d75419999560a226eaeb2b7cab0abd832c049a8b929f329dafd6230568d6c8e60297a0d7338d04afeeef74c4f9ce09f7bf12d5615774d48e55b6b34c16e4d6653724bf2956f9dc1f22d443403ff83003b7e19e94e392b0b5ebead079de9536e03a42ffb9715d6ecaa27f425d6240aa45eb2034177fd2955529bd0a9303e010762f12e283bb04e6ca6f250294c5d52a79a1694892bf7f2edfbdab7f10728b852ff4b3f563d0c68d8f29f26785fdd721cd22ee1b451272797d858f45bb052b13e747b0475d580a2ae8d6c3d3627c7ad6fe1e85919cb1e8b3c89e737d27c03406d5504d41f402909839161d434b2e5361c47999689522ce99d4616210755a4533300607011997289634a486b28066fb374461072f8fa588b07297168e5d7c8d4e504ad3486b028d9267f65c53e564634634f3299b5a1bcf908945f1ac3226700ca4384b304b40e901e21a1054fb547a3029a8d194907a1b56621cf160e9fbab52774e0e4699d32161eeedc9129e1c8698a90c459aa9c99cd7ff56f889ac1fd093bdc00945cddc6a42138449549358582af19222ffa212062dfbfd02fb3af04f34af0e43bef5c9bcb9bcd359051f827980393de6c547337199230f16cf7528896310d32246c0e50a8787443d4dc82a92759a718133486e4bdeb705645cf9fe50c2e9d59933a4ead8ac2d966ec24c855753bec660648e3a71b42c8adb62b0b7da7848de7683a8f795fa7acc78726c6b4e6e083a71752ac32b9efebdb9f3e332ff50fee782805a89f4843eacc89d14b847b3265cc4490d214d9db9c6ad422cb942ad1f6b7c946e8166252d78680a6e4767371e69b7ae76d943e3580c526044bb087bf70ca78f0118d0709af5b234bc7509b83d27244fcd7b6776fd496f452016b2a92ebc440f888ca5c7cedb8912dcb904883124d3af4936f86907742605e86842826ae5a157f126fda150e620d3d3df225737057e7153b484f24f5154a7de47cc7609550342663142fc04741a63fc50a8492cb60d12d3d3acf2c90b279931e781d2e194bc2bfdb893c3d4712328d32e8d223fb95f07115ec31092e7126700826c45435c684946f878824546e7fc52e64034d8949c6cc5629a600f4b006a9329921580b8a2b48933620f41f9161bc7e6d42700658e330523575855258b4b18ce660a5a9af0d4eb19e4d15fea633d688b358af9b10add5201c9b92de5a291c2472169c74467e38a882a701909dac15531fe6189f0a8990846e2731fd29451414239374665063762f42e053b53f86eac4f18600202e33053f4cd2b7a7fa6a588420cbcd1dc48425842e7b0617eef218a21e9220e6d50d9b817c98221b4ac74e0beb4f09071e8fb1fb134afd94a43899f421d5743058177d91e138f88b133a00d9dc8fdcb5b33fe32c3e4de70cf3c60ce5577c4448cb1d328d944ce0c004ead25e76d39e056162755301080e8fd91e69442b1a135b905b171f2df304def35c6571f9be6a55aa2a6bf86353f4f96229dcbbe46460cd44d0c58dedade959a79b98efdbc40c49b602c304323c1b333070e374389b79267c3bdab1f2e08bb2e363896b04964d2b732c599b33c0cda3a022d7e70e752eef904255f07363138648c6a2d547aed206841fa9021d32ba7502f4d0e165a0ac5565c86baa2fdae841898e6ac70eeac197ed3dd605aa980272d83ded432744a57b0d5eb768725ebfda3f8f765a99f44a29cdd8c7b51e82b02ed590013847adc0419eafdb6e18cbc93403c96d387dc4d5348f000333e181f3e215b0c7bf9bde728b3a4c47e71beae4371f5d2f2a0042bac9e39ff5794c4ebfee4fad5def48fe5e6d28f16eecf2bc450e14a143289ac2af658d8823bb3eca3aacf13b699bfc17c73fba4193b58b54dc78ea668567fd28e63d6a8760828a7bda3931eddad181da356062b926f9becead9f9153e4222acdef9af5bf8dc3772a7966d9785375dd1e1aa0e2313635f9a00aa70cf73b09ddf4ce1e3024034635f7449fe0b11d187c44f3970e5f9eb771ef7ea4bcf55b40bb9b055a891879ae851aa579bd1fce004d80e208e4815841fe58bf15e2cf862d08de1ff540a82d5481e202418cc6bc026f8a8f5080a1b8c72a0bbb270bb865e32c6ec5170fcb3227ccd661dc23f86fee09541197a7c57fdff978ca4167ca85e6b74e1e1457501f062a78a643e74c827fa82798704a7f1b873a263e6264c0710d3e30b4783604e1fd513cf48442489482864774d2e0541d8a09b7a39de5724923c83e54f8f148320340d86d4da3d6c23120dbdc3ffe74f7835c6a616e8c5d8380f1d3892349a09dd4629a481a54cb450f1493bd28dda18460780f77302a7b2fa46be3eb4aee7ea3cb7902f0333b5c45b3984afe375072579407883d08ba7d7f0154c321ee0b3a04d61552d474bbf41c63d8f20f52fa3d27f77196f29caf01f4610dbbd8084ca901d084902ff0e4d711fac7265d1d7963504667712385eaf39354ff313862a5276ae32236ae4656e210a4ba5cabc6a6e747ee28ec11ed9fe17c6c001ae02e5ba8cdac570689ca5eb02abbf59826a0f61fc62193ea10b8bbffbe67b45b5406f85510547dbd6d5b45554f0eeedd8722b4ab0fcdfc00802b14837405d70c480235b6e17760984fae7c03ab1014d84cdafe063dee40b2d16b067c096b273fd848df36384ee2ea036da3e0f06cbbee843797be6abb3d05336d385dcce7e768d8a7938363faf0e561631718e99f963b75631f6aac554b1aaacb4def7e4faf2fea22ce0701cd97b0ef0fdf73634bcfa904dc28dcd3f9996f383dc89b1f2824d2b97b23aeb372604e8da4fea495533cc73266d8ab8d5b7c803ed2e99499c94dce02c15d17d76134ba57e665d0b6e51c7e4c2d9e530223fa8d9f33d1cf437737698deb89f1ddeeb95ce8c22ee26e8f169faaf532645b09b25dd3f0d065c8501c457bb16e8ca9df6197123cc3909c7a8da4344bd4489df2e68efe958fd429381046a917d69afaf2a72e04321903c3a898e56fe240f51776802b15a57a01154a866de2138adef29e952adbf0a31fe5f4eee6ddb539caa09cf6c7568a7d77c9e8453eebfd942c4f74e9dbc35757c1919ebd61a131f45c9430d860ff70be7219691884dc1047ac6660669056eb94379167a36cdfe0df090cc132ae8932428249b3ad0cc180ad95efc13623c46f4697b8d3fe48d503a72d973df3ed341d026760a05f599b4dacda569fd7315a01c78db8764c21eb298ebc659c1926d43af1a6847bf0b2e2fcc465125bbd18db860c238a1d7403815ec4aeca59aa5e5a70e81fd3e18a0a9763b5a374e1f7c148d57b0be546800a0a8293d0284f7ef4e46502c40f58201aefb3d1834a843072c33e45a68cbb38a6145b04848c54d2d35482b9d6f6cf6b522ced5ebbe8218d57756f171f34ffadb9e8599400d511ed27641e5b4d7089d219fd6c7f2c236d73cbd0232483d2d8f7e0678370501c6a290021934171d48ef163a2890a984558a99b5353d02daedd8e68893f376e2a5c9dad5058710b01717911b471b9b22ba290f4fe4e5414f083ab8035e65394407702c47f0981b0c92df86aee840643ea4e293c7ce9a7639ab648bfbb46998f16543bca02f429042af5a7cc592092b292743500e37489de96e11130e3387356fe3a5e72a77ee977ec36ce47e21c6f018470bdeb0ff5cf1da3204e5c2904540022c4bac03fed7ab7f6ef28e7d1c4c95d5d641b9b2193b2941b1023698d904dc82664efbdf70e8b0c930d2f0c32c29ec3eb23875f0f9a03c6e6ba2c9e10cc84b3e464cc94f3bf0586b35bc74dd3272787b2739e1fe69ce9413383302ca99daf73aca3a3131659691f9f1e0ab695c8387ce41c1a691f1986778c3cf941534776ce61eb223cf354e8f15076ebd653a1c75b0fa239acd64578ebd113f28c2406d93ddee37a4a64f7c8acd6759ef30966309c038643ede32d9035240807285184d8318a20c2b34e0e65681f0f9a2d30b60860383b1f6b5d3644462d758c22e4474fe819a4323f00107fe101f11388c79807c1104001649c65eed8ef80780b889da6cb3e0020ee325df6200fbe9ee9b2ff315df621660231d3dcb1b7398fd375f3d04746e2e3f5485acf20668a9e35f291f356ce9f737270d3f469e5301f37e5873aa70f5bef71dc027113ce325d36bff51033a99033129d5b27ad63267b447562d0f401c66e81b17b80b231136eca606c10b446a075325df639a03d92537cb201706f8ce9f345072960a64f7cdb7b50d6c8de1e852e1c10061618eab801c3bbda01865507931a366068538399c2cf7c5b149b4efdbc43af49eb505b0ab558db735b948d0c0c52d3a260a01d6a516d0f01d08952e86a2be435a5a01f003a510a3153db29da6908a621962c1149ed39794dd327c68888d2f6de16ef09536f887c038e8e51042a8db87ca1d764d4f6f2876f768c0df1a5bda6ca3232ef80089b3f42c1dc80873860527ede9ee6a90153ce60c50d4d3730e1b0d4614f8de150856524d21dfbd8425d8f3ddd891d39754ca363ec0630364a1869fa0a863d4454bd8a3cf2374e5fd8d3ab8e307917e84fa659ed3cbc1d7cf5f51ed881abefdb0d1f4b3b4eb3b4fc55ec86a78fc8bc8d175ff64ae957dee57ba253920f7af00324ca402aa3c84889246c0005962bb80803a3d7c0b0c7fb0b3d9d79a0b60d0d290979eff250772f47ba13a90c5149465a7ba43b4154c950cfa5ae19185b050f8cb06ebed0d3330a4fcdc9633740693c55311bcac8d3634a845659f327e794443c7df1b863cc86a419b4ec5a4a29efa2afd8d413a49d347da53127b1a6ef6235f8d0f438b7a747e36b0051b0a02983e664a265af6e4fc7ce87226ed7f7d06c311636d7f9337cf4d4d2d38517922ca9807c155529638725ba68e225892e60744ad154898ca63721be7ebc71030c5c00c506993160347f20a8e00b5b2d9b4c61f59cf3258daec0f49b2e5a0427f6856f6ab34d6bfad00805c215f5c69af4d0e1576133d6044ac768f8d23146031403748cd120a5bfe913af83112de9fc6afef3aea9467c2c81ce644359468d08f1d0f42cb4d044531a436ad234c64a20a52995934e2c4d69144d7fdf805d30c69d4bc14c179d82e88b5ce2c062412a3428c9732030f1bde93ffa15fde93930c69d2f7a4364941e11d05edebe60d71af8234a496daaeb0b7ead81e10f971c322f7ba618d266d6da696bad35cb660cb5a77c686da869f6b56ab7afda91d83ab96bdbb539b539e79c73626de26b1a0c1a9e785e9b73c6e6b69bcdaabd562db3a016b5564da395529ad54ca30f65d390d6d0fe86f4b59ed352abadb6565b6badd65a6b2dadb5d66bafd9da146f961d869eceb21255c74b5927c8a4ae0f63193154cc6df9280db95fee61f69a71479251bb9dc3e03da79db3a7f6d49e5a7b82aca0e5dec472c716061abae25a3197802ec10c5dcfd51ac658098cbac2203bec6098ad8130d0a6355b227b4e2b3bbb02dfe91343d64822c689afc79d102b69855f8cf14621b94aa42fc6b648eaf98e6db1d43690b88d2812be80a20966c1089bc79124cce3448a438f0395a3a3174a2035cde1d75d429ca69122c82a6b952dca0d2a6ada00d3636464147303091d3ee8a1e55310aa74b6600345cbbb40f344cbdb4816ac609a606c1a49427fddca386166cbc949234b03be318b9805925863adb5ca3b7de4bddfb75acddba604c418632caad222d987b2b5cc43a1080b2dbafe22b1cfecc64929a59452e658e98bb47048b0f46616ad05164d1fb5682a3b34404fdb87040877acb53166d1554bcc8266da4555522d706a4eaf8b1173316e774e6dceccc65863acf35fe489a71dc618638c31c618638c31a54a7141e0d82ad3b12d529ae6253302e5702153a52317324c1dbde8c8858c53e389bbe690769d24c4fe68cb965f6c8b0d2d2f67cc8504166260291788316ab204122cfe7219a28c2f43f7044424c164885a78a981128c7e48330326830d13309aef1c413e7e0b17671c8d41430b9cc0f8c10cbe48a424886882452cb0f88f0565ba5481c55ffac2c101b6cd993f39ab09f08d0e0a505958409694efd8e293cf9973ce7900d85a6b3dadd3156feb9c334fd78d72dc9c23554d3d81371670a92da4eac68a4f626ebbda560506c3396763da514a69d0f4d1527ce10d4012456dbd213f5a0902fa82606ff92c08c6158004980133959491db583e224f7ceea8c5182c9d8c3566d11883e925b3595be4011b638e1ed309cac61e4e4d19533195a56eb27ce1e5b6aba5baae951469b09681638c40b6b5327610a5652723d0264fe765042212e3900c0e13a4c14663ad93d50bc1cbd7c9081482974f4620ea80c806145f705083274f682103588c3b3202792178f9e431ee6404f242f0f2c9e38dd62d6e72bbdb36336db3aa5438d4f36b7c597cb22317a6281de769ec8b5e7c55055f288dbef8c2ebf485efe20b25d2edf275b962b020dee302e4e20b6f532ebe1a690bf0dde29b587620185fb8eab9cae1c9174aa3e6e1d37c20e59b5123ca174aa4f6e10b6354cbd3b84088ef8ab1c3e771a183297ace00f1d11cca2722171d2cf51453330494f9d9737e34c320bbebdad28b9fdd0a88cf06f79cddd304ebc0c9375dac2feaa9e55388329e45e7d7f29b2e16cd4366d3f81470e62be749fec77cf180c907d1d2f23f60c0e483d49869b906989617a2337e4a7de3659d5156a8bac64d998f4799af8280c527df832728840acd9fecb819f5742c50e2490d239c403103041b64d08221c2a451860698fc8de39347d3152f9d4c573c0078f0e5e4f0e1b08789ef1df6e440f9a409e24e3c1046747cf859e9f8d0d5327e3d487600430836cc2803464b05d6b841153492686206338049bac3838d4ff66643fc7be47fe483e2aba80452625bbee43005184e60f245e22b0130704a4307a51364f105263fc1d8b267472e6b98a057447ca17ca2e39cd60b2d87ec8c263e1c3e9c64d5f836266c189fa645cc37c325fbc15763903df9686890fd10c6dee0882abef0e0eb72c041259319d51c683ca82073a288ce0724f9149b9cd474e472451137347531d36c3aada7b3c1d13a7261e34a872d9a038ead705691204c7972723935fdf4e0c001f5e5875e4abfd027ead474a911730730635cf955972d2da5943d160731503dabf0663e6849df777beefd61496239a273226d3c48a316e69c64666d1b333e104ef07d71226afa84f31e359d512edd91a7f3de1f496b5e40adb5b5d64a29a54fbef9706b2feeccccd65a29a534bee20a563ca67c453a5b925a6b33ab65d6da5a6b8df425e3d692ceb48c9147766ccd21c08ebf99d93a5ec6685e9c4facb5daec95524ae79c7332a9e25b344b5a2d9d5d7a76613e69a5f4c197be71bb778bb27d6cd18bdeae80ed3702dddefe2349d0be1d482240c22250fd97e6be2f4b12e8bd1b7a5eee22509d9284cdebed38871e18ae624b1979a48c35c5dd1c7a3da5081d98a508f22bfaf278e4e869822356c5168e51c6b04a9cae12478a301f65a4daa346636e4d978c3cf3a1aa6904b2245429c27cfc9be2d4cfe3f8b2893b1d634fedb4af165ff82385a2ce32adebf4f9d4a24f8fe89a9fc7f36af1e155e499e91b79b48751a6108122d0cdb40ddbaecb3acf2b92ea34af01dbdd52d983449e790dec711120fac4f82302dd1c06b9b9769147be7a2ddf63fed3c78b2ef92b6f2c665db7fa3a9b30344dfb2694372a97207e40007cc5a6754197cdd7ad6e05154f307d0ce5abacd355f39dae9983cb17c3db928469d473522d9f6cd9548279fa5edbc51d7e1f0edd6246989ee9b8c50c16b4eae9b379a175834c97fcb13c7ca966faba1cb47c9c0f6f7c3829f3c1b73151c77c9a1627df0c17dbe4ab1db9dc20061605dfedc8e5063cc88e3e0f4aa6836f6bdbc5a76aad872f6bd78fb943654bb5822f8c4d45b8a48144e38e5cd87862c178d4d3ef5dfd3841dd7b314f5daffd9219752ad5f1768b93edf214a6e9ed189669bea811dd99b6a95f3469a9e92d520f368a9572c60b9ade26cd970d8cde3a99af1945a3a85523ac65c0841133831da8315f374ff335c384a1af4d34ac4e4d5fab4cfaba347da2144d5f99e62b078c3acd495fa1ccd71c638cdac3189a32d5088a054d5f9dcc974acc7ccd2a55a2beccd76462ea499b664e4f9d68172ba8687afa345f18464fb1ccd73c3acaf29a51e8291424da4396294d67602f29460c3d8a9a2f49860c992f2aa83042bc7474992fe924bfcc2d4d533e4b4634ed602f59651ed1cb28af4c114d3f8d6498f9924734bfd7b2d0f69987e6b7ed1764698fb0bb64baece96abaecf6e41bca4c569fbc119d96092ec070318ab12750745a217b4e9cc2cd121c6dec1833c68b580e59620c87a6e6c1adb5ca7735ea8b13599aa7e3972b4badc59406dba963ac08a67e0e0c4b6e3be0af0948e0f6199c65a6cb9e060039940d80ff982e6b7f7ee698e9b24454ad44c631c9cc310fb8bdd765be641198d5849573161ee98b9593591388c08ffcc83c0b99487efe48265212929965e4c8594233b3721e6111c8ac9cac4476844598fda6c367ef39d97b4ff6de17fbe8197172e4f22d50d55fe8ebc865db098016cadcb19700687b983bf60e0063b8ddcaaaa61281e395119fd71481809c2250a42f166eef7da1af79cc4477eccd63f4bcb300da234a653e684600b451c02360a43b203c7a2b4cd8ccd688eedc1cf1852b1edb169f1ad365c530511d39f946cc16c56bdaa2d09750114ec2eb357d31bea613ddb16fbd083146f4350fc422b5c0d99a4ecfe1aa53d7c9e12af59c734eb6c75e530b9c3f41264c9f20b72f327d46b89d4d9fa52f08dcde42992f09b3b746448cd1f6d6096e39918f03d602653301a37c2166fa3e02b855992efb20e0360508b8256d51681058082c050f8189c045e0246c043e022381a7e024b012980aae82ade0253013b809ac84af6027f0127e024381a3c0580a3c054e010e2202ad707b2c440432727b2c2502a9707b3c44046ac0ed3111118801b7c74544a0146e8f9322100ab7c74644a005dc1e1f11814eb83d46220215b93d9e128188dc1e27118186dc1e2b118184dc1e53894026dc1e5789400ab83db6128160b7c74b44a0be3d66220205dd1e37118112707bac148110707b7c25021de0f6d8890854c2edf1520422e1f6f8890804747b0c450432c0ed7114114884db632c112800b7c75244a0116e8fa78840416e8f53108180dc75db3b0f9a5b14fad2a27e7a5ccf0f57395b94d61665fb84e3e33ed9f8b20022a977c01b1579ec570037a4c8636f04dc4a1079ec5500b71d228f7d03c04d87c863cf0070831279ec5300b72791c71e0570cb21f2d82f00dc70883cf62780db51e4b12f026e37441e7b22e06643e4b11f026e35441e7b21e0e624f2d89b006e4d228fbd02c08d86c8630f03b719228f7d839b1178e3883cf60900ef0f228f3d02c0eb83c8637f00f096893cf62580178ec8634f0278df883cf640e0ed41e4b1370078c9441e7b11c0cb83c8631f00f0ba1179ec47006f1b91c73e0878c7441e7b20e06523f2d8bbc0bb83c87397e28efdcf73f8d3e323873d3db216a593c3f778cee1cac77372d4dfca383f7cf6abd54c9c396d8a40addb08dc8657fec8c3d55dae1e6d89be22908f649967aea1a9a1a979b86a1adc02656b48f475976818607cd1c58b2e54e014e3c2c5962db4c8a2490b165764b1a20a2a985230c59522025d2c378a0874a1b84f44a01608c41752a3106cf8725a390754921379c2d663833f7c3207945dc794993ee10b6007e0ae5bd7edce2766ca327d746e3f7d803cc8cc33b77adce6b805ae1e04fc3910f0751f30e73dc025b9637feff7f54aee84ab5efd80af4f4fc8ce25186120080a40000278f48408e0415300211c0c21272704f0d11312c28326fe917398f3aca365b6d219ca1fb17540253c3960ec0c2ad19ae7d113c2f3eb1589cd73dcca5a662b9dad7000ff3180635cd47a106d813f94683d801f8f9e9001044d3c02f8f320e0eb40401f189e5dcea72744a7f3275861156fd196b428a24f4e6b2907c459227dc5a82df1b875b58e872e1d0f3fc2c35590871f90b7ee0d8f2fddbcbbf43053e4b10fa1868f95f3013c362b87e73f2ebbf5508be23c1572b732061375f3f062a67055f3f0fd273e49c26f4f6990d406f992b7a73bc8d7ecf170a5f3f06b56cec3dbac47f9d290e88e3d2b3fe22a409c054f103b21491146c8e1aa75bc470e574172f8b58eebe4f00392c3db3a9e93319314e14e7c3e9e7b3ca705623197a9f587ad5f2c44eed2659a3ead8739bf58a6cb328577a9752439f9dea53fe73807bc6f81b3b528ed2d90b6a6833f07ccde026b6b3ae876a045fdf65ad47d7cdc9e4992e0e33e1e3da4560e654e8c403d1e0eb5ce74e5ebe430e73aef012ea1d153a147ac09a3eef1dce3f93a20cef1ec7454e89171971edd634888c5e4801549eb3999e5e30749adf39c30d327e7ade7e48375bac225b47354d0794e0f103b75c9624bd7eea1937de41c1087c9206e12b3397dad29bdbc3146b6be5c49ea1f687cb982447fa0f1038d480694317a09550241ce182b8002421898cc4133e6e470a8c6e9ca0197cc30b280062d23a3b007956e9d7a425a39094eb7be397d618e417b00a776e9fccde983211b75ce1ea85d72c6782ad33cc0e8d6184f6a747ecea7a7424ea672d4039bcf1949eb3cc0e8e8a1c0038c6e5199598c30607a09ddd2f4e9005302414e4e3e411a6135228fc562a64f2bb386e4dce53d7278bbc77d80e16d1f4ee45bc72d30bc9d730e9974eb3a398f5e2b3fbc393e46e8f1092ae930e91ed7c931f2f4f001c67eeb39ef0186b773c6f85a27e438616a51d327d496da763ec0cb94c1db02efd2746d11c117635b1875ed160ea65d4e2be32e44744eabce7354ceb473de0261c85f92b5ce193a1954928096537a0b28e2c981ca18cc74d9d631137d450c66fae4db63a8e9d3e3f638ccc46a4420b92502394d9f2e11688c08f465e932b5ea10adeb803f42da9a7e74c8448828294643f8d0ad90c9104f43443121c2888c235e70c4194c8e688333ba41eba102318b984ed0283824ce6075c804093810d021132d4f0580e26679f2f2e406d2d20aba58411a374e72a660c1448c2f635c99c23671c1840c199091061332d820a307dd7a0c9978b1620b265ec460e2a50c265e5e10eb9049194b90d121932f464cc070018323bc70418216484182283004d02109a27a4082a838260ff587290455e2ca1446580c1941f194800b420b8f0e8766382306340c1705c7d00c71dc900392142396681435055f3409a349d49013249f0e879ce4201caa61e9061d0e1d29a951c5bcc26908072f38c46008071c0ce56014d3e870e809d2960e879e7879f282a12737d8a1c3a11dca98d221511523a2a51d9a3a2c0aa229883002d06151106e704639492a2700d06191105e84802a926224250d293930a3c3a221c2a83850512282063714a143114e5e3a2c3ac2880928ddeab0688a302574589482a42a7cb082072b5660ada85ecc2f56507485972ba08aae40e30a37ae80a3088b282cdce08c6cc8a05051a4e58b222d60828c829ae4b0030f5e87414948042d1145154158046511d4c5081db6514e876d04934e870dd56274740833ea960b3a8441754b4a872618f9e8d0041ae07428e409215bbaf550c893903130f024035334b0012a5c9882035220a1f28214dd7a0882272030a35b31f840440c4ac4a0654a08c6202d31998289971d302123822b469034822a23784a75480217b43a1c3aea563814c4d011371d0e65e9d6e3d00aba451485a643a226b0681d125dd1ad9028460406d1976e11e560a6431966b8a1044024d90e65a0e244b73a94818a6e853234754b862ddd9250d0a44a44d6e4441b63f474dd689da706e26523d33a345f3a488d0e30375d8000c6a709014f1d249349c05303699ac2a875b23490a7a86e690105d5ad20b600a389d6d932660b99d6316a25318e38dee8d651eb34c1055403f95226ca0da8324f5e620cc07c21250c32ad33bd8069206e34b5ce180da44c1a3b04f1833044d038a08eb85299a8c20a11ad6384a5818019d340b29218471c65ba15e6a97572eb587a4aeed251163a391401946e1ddfd0ad63ea29a199217a28e0d6c96107cae816112032dd3aae1df5884c2f36e896102537aac1005ae43003ce3acd1ba2cd00a95bd7bc219a135bdc7baf7635ed5220153241028ce68415cd091cbaf535ae84e1c4d11529aea0000eed0a189ad20b34a52cbaf525b86856ace8d69b342b4740c154ad60d1ad5ba942e90dcd092d8428b99a87c24cebe4900466d460dbb66ddb280e52e1901327d5ca15d40d2c362f150ee13003214a6c8c6aa81e0a34ad93c3a12751ddba1b52261851619e366e1aa5c2a224a3e9450c85038e4ef3884418b0d1ad5f6f48844111ddba0bd620030c0c8818038a0ad228a2a20c325e70b7bb6d77bbf7deed02a9b0c88a32dd3a972a5b7c71256e8143b78e372e01a9b0e88a1fc42d8eb63489595439617618b405b76d1cc771dcb67132a4c2222d6b649e1025397a89ce65671e0ab57572d85430e638cc711c46402a3ce18d0464d16286eb1101cb74eb9b37e44a701bc76d5c08522106aee0bacd230200282044d1ad73de109c28582eb8695a39e140b1a3071d4edd3af686d898d1ade3aec31e919a33bad579351522f9c20606ab1800b4d0baea31a0a67572084353b78e71c779442e15dd3a8e36158640a95b1dc6b8c31d980a99dc806de896c7001e50dd7af416a091a931c3a7866e2d209e1147b7eee93c7a0cd0c94a641cfdcc1ad27a0cb7751e5b278b41e54b2f9961942284510c20a6f412d9548e0e93410b02a604029dfc02cda1062894e8d65f10810e60c00615dd7aeb0f9a3a606c2c3d14621cdd3acec9b96d01a140fee77c49d69f9df31608c3bf246b208f9e0a2d740b08a824a75b3f98732cbb1c30942914752bc7f823e7413307ccd7097d3c7f87a88e311db0bc3ac674d8a2c553c758115f78748c6981a5ef12b577c752db29cd258e1ebac75bc75c3702188007015d0702ee5c824d92b4c01c0f02f61c084880e78005f8f51c507b8039f67f783bc7d7397a3c5c758ef3d091750a40801e1077f186c8ce377c8f3b2dfa47eae391f678f41c508d72932454028dd3318c329e9a7c190931dc18680fc95a898ca3a3148cadf8b289f347cf3b63824fce0c21af0dcefcc2079d17549ad880f1858f29014737b32431a6e5ab0e56a0602046194138c558136eb8e185951958c90226e7152d9548d25afe27a807422cb4a044162d9f0117e493c833993e52d6e9436fd0f26b597474050e787014c60f4a51d057910f2f18e3e4640c236af0064c4e2b5a5e2ed94ba984186ded57f7deead91b0495154b891ae8052189327a5ed61b50abb9a60bfc01d279ee114667664de0be663f52cf65a2fbfaec669691ecded7cc9a5b66cd08a32db8908409cd92504a29a5943bada79442b9e80e7dfdeacf1c81fe8241a0115bf3e94ed2372f5b542b92b3c6113341172de53f2a3fa40b93375244cb0bb1d0820b49963419492732298d96b88a5c924cb2496ee9914f52c658125fb4e45a5e92919f46f2f368fa14a0bf9934a74ca4e9535b4e69a3b7d7edab7aafb7dd28e46e01d3344d8d295456f5006d9110d33605306bad458289b6d6a700fd04a334c9a9a9172388687a1c1a33c28da66fd1bbba344502461fe488359a4c37cd6f9337875813495d4febb1ca66fad4aa699aa6695acff4610db199aea869b9eb8e669b3b8ff4c9474a7348836696b78dbb0d8761ef04ed34874c9a5eab791b213b072ad9477bb5ec1abdcd3292fb815505db35472942eca131dca6549eca3770ec58e9bb08145b1ef338a185a6344bb9832f36d56eb54a65d217635b2035bd7d0452221b04458dad974291967b42ac3ca1d6a61dbd133e70b6a7643bdd7e6ff625595f18eea6fd665a8ef1479643fb21b44850c7f823b4af43e8e9ededac295835c9941052c4e4aebf1705520661a56bbd7689a0948732ac1875bd4db692526b105bbac682d8810a624258d1f506a91fbeb0b65cd3a7ae5ac67ad00256df7d36386fb97e4c9f1f5d51a083ae36989082111f7ed0f5425cc0ea2bd0c295ce81c9eb18430117fdc3688bf601e18807311fdee8fad54b29b11fa06495e9136351b074fd0b964a106340b4a06b7caa4d7d658daf5afa692145899e9f3eb2074ab4d1f5265460fa7c5ddf0212acd6275952f3c50246a94ecfc727ba761807d9259ad74e412dff3ed29d2369643b09d67e643bf723da71e6386d4bc2441ac923ee12c6c95ab7074d1c8594a4e2d7cb23fad27e5d35624d2b32476881bb3f514be2930e8830274eb86fcfde930464228d24d24f9018252433a2537382215004ab97ab96607cc9af2210504bb9438096a1015afe06896fe32e7f5fd9e58bd017bebc11faea8e9b7c241db160f23d535a8ae1051a6ed0782166ca6c8a5ea061d4f2d6c956e92a5ad621aaae1e1a5f6419e1b8b38e6ce0aa29b4557a0da8b776bc5e4252cb07c578406a792333da2af4e5444952d1327a932a2112db85e992a79e0322cc49f6db814e8a1e1061f54153037b2c18846f845570f5e4b34bb689e992f7c07cf1f6e97211d555ce97093bf55832a919274afe992e5693163417e88b25336b02f4f347b2db1f99d7b23562e96766c92cb364fc22940b49981871624fcf84beeceb931ccdec11caa80517923089507555af15b160a43bf366ca17de85e913e2b4e03d2a2ba24b19ce044eb84c61d2818425a884124ad80125e3f381a6417d701895f0936559f6f3f3e2a870c791ce68dbfdd1b64dd38104858fa41b1919b9d1450c7cd0ba8042daaef6e3626a7a9714514dffc36886ceb291e9028bd01dca714e9a06a5554ae924418724e84cc6ea05278b192f2efd940cb5bd5b6a54f5a04ea174061cd418d3459fee13724d46eefad1f3538209455260816be29e3827ee0cee294a3ff2ec50fa428e8963e2b27c9483f26206234dd3340d6be0ec2ed56666a8913ec376ca586b2a461efb17dd5b430b66b80962061c2ab29f1256f1d2e89a3b94933f7abe36bef02d170b5d5f017bda42114a7f4b31ceacccd934d21869a4d3132287d01cb38c8a329f1a9a46430c5d5ff9fc8b99b665c7f7ad0a7099be03637471dd5bd3277fa3294c17cd66f03c5b443c8e96aeb3c1c169b57efc3042ce39e79c73ce39a39c734ef9386966d9cfa694d2d9338b99c999653393b34b0105f10bd287f37dabd5dfd346288b875ae5169971a269507375f3469957a7dd2debc0148a4c173d0e175ff8dbf0850cec92d8bba4bb606572bb2eda2b4b3d25b4500131528a0b49963099af4b27509af497248b4430469c0073b54b055c791f97f485b1292888097fcfbfd48308346fea8c72a61e79ea1f81661cb882746a734e2db606cae89235d2d48a360b62765bc1d855ce2a6595b36a6096a95c7ba7a8530e75d074e1bb354685ccf783f8ab81306908c1830cd458c20658fc2abe3a20c61638beb0f2032e6c008b8f09d01e6557ad83fc0405d117cd2c39334b66d60adde98f78e732d1f4b49f08745bd3b0b6695b66ad80affa9154eaaa54666da9e3ccdab49e9fa022a91ce94ed04f4f77ee59666d8f307c7c7a218f0a61ad40df5d68ded3b4db6f60cf7469e7404db34f5cd8a66d03230cdf70d14e6137b18f48293b11bdf67a177d11cddf5758d52e347fc34bafbd86aafdae08a4755d651ad871d7345693ef9b6b23f29e8ab07a57cf4fdd720fdda9ae5fd3b44c7b9685ee95302c1ac8aa358b65bac5629bb6223a6d0b96fa4d7fe82b3b50d3bb2290aa4f6bb0d75ec3bc7cd06435f9c2134d2225a17979227b2db3ea33177d69f6f24256e621a59a85e6b33c541f6143f336b32a8cfef42efa1efa1fbb548be69c49d48fbee64fd0bc5b35d2f31381b8d7a4afb5b29a7c3df4550463597b2e0f29d93c74cf65961ddadee52258bdddc0eef747b8e34cb49dfbcd44f84417df74f1d5da03e5ebced51b3a76dc51df7717baeff210ce4ad672d90fcbe69e5aebb6655a16ba1f9abfabf7fc041589ad5a677605526b932e01319d168cfd241108a8b5338940b8357a6d5ed364526bda53ddb91fc14f65227a25219a59157ff3f447e6293d11acbb37097d4558eaaa1ff1de65a2eede559948c94577b41379d71e61daaf79b9d3ce64bab424d3a5d14ca4544f443fa510cdacecddb31097bb2cd49d7b977fe88e76eef89a93e9d298d01ded1364d99c64bab4edc99741c98ea64b7be6a4e9e727408f3f336b9b00975937b3ee85e839d69695c82e02334277646f3a7c9af624da99689746dae5912649d03a9e75f30af4f813a0c73952ed1398e7720b74477bd0cc90ae0c7085b16866ad80affd08f72c1365444a42d9b91369c78f30239a9665d9b1f4a8cc00654168bab0f484187182cf7942a89221f512d72869ea570359f42c9b592b685a966527daae3dc2222c0337037bae064658f6820b59d19c75ca475f97b502f77b21ee37b3e4ef8b6042db59320f29c90f75a7975968e2cf17c152b7309c023318ccca14a8c168a6bf3313cd7b367521fa5466c184e66b9efa919aa732919250ea342752bde64768fefdcb44a9d33cc282266619519de58008539d7524f59456614041b60b19982ed95a0a6465ff1e612a50f5991f49fdcb44df539fc9444a42df53279ab9ea1196d17ca99a195584d180113603465884a5b2789b85e6bd2fc118ec09e2ea61188c300e8cb05a292c7a4284e86f66d947d859362ba9b5de55df53df15d5a9a1619f3ac31f7dd5206010dd895f19f1853d9d6960ec2446b2f74420a0cefe1381e68b3e7b11faaacf8e3acbb22d874f1edf74f105d19d9f9ee982f21129d913a5fe5d3eecd1bc7717f2324beb6eb3502a7baf17aa17f22efd8ef4c5b697f703599a76ed16198136aecbac8bb350f7a1ef5d569debeabca1b5e6c0d9de3fa1ee5e1e52e23e54df9dcb42debf3c44efbd3550b6dd325d590af440d67d847520ebe61ed8f6e4b3d93a4d57e681f9e643bba5b357cf88937a3a7dbe1b8460adabd387bba1e3f4994775fadc1b32eda656d3955debad045f3db54f9a16dfb68117fca81738b6c2acdaf8a28f5ec7ecf445730626516214ebda83a6157dddffd09d7aeda1aa9f6cb6d7bec284d1c853ff435f1288b8535f65955675f8d3f5ca4d7e5919f13dd10804d4f592897ba5ae96629280551ad19d4a77aa0b74e7c6888f698995fd3ec26a96592bd06f3f723fbfddad3e830105d9426499e9aa8f3022b2232cdb841871e2c20459d9234c32d19d7a0ab222ac29c2b6275f129b6bd6c4c5b7baab2728eed4c79dda1377ea83e24e7d84dde8aa8f31ba6a92ee3aebacb3ac64a86d8df5cb87d3ddeda3bf3f32bf65a28d4889081657f4c5d2ce3dc2585a66add0ddfb117c2e1371444a42dc71666944f85d6669abbb7a5688302738bbe88e5d41f9e8a7112735dcd3d7b07d1e4b8f658466563d7d112cb36aaeb508a681b171368faa24a1ded02c2374857b7aa17b9a8794b40fd1b806561978881ea8808c0d361ed83cac790ecf53a9681e82618eab6c52a99a9a9a548edfdb609a474e095d423f265fea62d5b9acfa3c6ff5a9feb9707398ba77962aab70bdb3525905fcf97d3539cc9197d0fa5d06c8630edcc090496f350fb9e7f8068648b83cf39bdac0f02db45766e583afb725943bcdb77b15a864a86b50186a24925342dbc6a6262fa18da3eaa68e55395c42b787aae3d52af2b4f0a9529f0bcd7dded4f159aa9ba4b9cf13bcc7c8b33d64b284a69efabe846e4a641cb12d18036d24f19d863b9005821354df9e3a0b0427a8728c3cdc095e8e9127f260bcc4feb0c8608285b89743106edc9cc74d2a85718d8a07c63518abbe6326a5ba398f54eaf2372f749da2015360283be57973f3bcefe8b82d0586de5337e7e1b9bc548ac75967dde40514752af59b148e974ab19e3a8b070e8e8d77162b2fa0a8bd6da3016b7238934a75a91d9f79b7e3ab1d399cbde33adea552341dcd8eeea6deadbe43c70e30f60a0c6fcee32a1e37f985aebdaebb2e5573f32e875d77291d3b76a4763cf51c3b9efa8e54bedde57049d3d43cbe43a2e33436ef72a823873dad2334d239523b5239e471b33a92d4bdaf52f79efae132b2e29143168f9b9b7b37f77ee31da702ddbdcce29159383836ef1ebad0a9d5cd4d0e5fe85899c53a121ebf398bc76fcee326c7e95ae5f0eec85d0e755cf57049a77298e3343ac0d8393a5055f3ee5d8deadb69e2bdd49178ef9eca19ca194b82d021697ec0b1853110ded6c697e3a18eeff0989a5a7ee6d1536186e370a6d9c1711fc7d1bc0b55bfb7f16668c0101c327310c9cce575804b6acfcc78dedc2eb6b1f138cc6d3335b739cbcb0b286acfe639ceaad931f399991c9f39cb66c70e9bdfb372d47898dbeedddb3af0cba16a26c6b41463aae25d7645f8df4c0e67cfdce6180cdf2d74775720883357fdf8fb4c2a47a8e33b4e93230788c4bbfc0e3084313e1d796626c997e33887dfcccccc6b66ba9c2387f13836cd3c869cf67e6a66726853e365968e2399b9771d33f73ee305c991c39e20974d0e733c869cb6d9b1c36bbdf1279e2f2f470ebdc790d3396c326bc70e9b16bafbc435ac22b17364568e23b179cd73d8bc6626d724e98e85c2f799cfe490a8bfc7dede2da9de96f193cb4223090662060b8ed3a75e7bb40f3b9b9dba63c15a2b2d9a533e816363d5a7eb307cedb8033729a6edb7141c353d0b85edda53a75390697a9a635abdec1a186e47e25da3798c3c33dfc01990060cb77f9f9e0a1b883d9acfed952687dab75b4f05fb2d63958671a6cf76c2f619ef33e07655eaf3aad4ed5399959d854277efddbd7b5e6663af1969226147311220dc3e5ff38b8384bb392cea2625e3eae03c65a9d2b14cc7a72ab2506dde793cb5da4d6d0ea15d7ddce0b3cf6ad6350b75c87ae1476773da8c82ed985baffbd44303747c48808e0f773ade34f770eb548e64a2187c2ff77d91d210ecfc0875eddb9da93207e1adca273da88f3e9cae48a5919d954a4c07295aea74c96e4a09c4185240758c4931a5c304c8c699ae8945131d635848e9103ac6a4c0d2aee963a78ff6f920130108383aece61f73670a91517c5a6ee5d085733f1b7cf6610cb24319e2b4bae9ca7535c9c071fa70988b6109d3f517cb98066aee5249bd8b3d3094a1bdae939fb5fb067a99bc772512996390d8761c91e811c1f9722a00359763e4f172884369d4f65238e93a3b798f1f4451a8f75b96a287aebfdef109408d7fb9576f88f484e077b2397c9c43fc25973bf720da81e13dbdf60250e3ec01a08681fb12ee941e831cf7e8ddc8f3fb0b46392f6fcb60567cd75ab3221636748c6171821e004ef2c9471656225bca9959fb54a1b294160d63b9dc12db1546709db536e3b82b9c781d6357f4a069dac5580c47a6ebb66de3baeec94249efeb18cb8245dba47014aa589623be2e954aa9be2f0b94581629335bc7589619683a094639d34d57cc8a36da86c61342435353e32991f156405911d575c15b0d3ef9d86169ad05533abc63c4ace8a1c3aea3156158b1a56d260eb12dc8f40d968e07d331db00b1e9185ba2071544758124a380e23d3ee24c7b468f23d117634f906928aa04f9014552cff79420a403636c0b248c602030f123480926f0d0c1d73d7a47baf3a8c197f2c008c39f0cbe0e8c71076739c2c0d0a6b3ecf6b331777a2dccbe9dfe7213e7303b7d6f60d75d7a862ff40b365d69ed8f8896effd633ec87c09f175636930cd200e34c20002366f427cf12811a3e107323fbc310636b969d388b1276cd031f60454b368beaab72ec0134f2a90f225c7152c4e4b5b00a0641413e304055c82ccb4a29b4b6c5706d44c8506a5fa8d070dbeba45adebcc7e9dd9da93058eadcc66fad45aebd07da1b3af957281ef0e3e293b7af5b1a55e323bb6e60db1e7078baeffc4c2ed506b85d52aa274952bc8a47c351d634bccd0614f46832f836387366c12dfc54156058d4c896f334343c1977d39faee9395ef3a69387c9b96acc997519109f16551a0d18426e5bb53ac159f364486c647d33166e54986839519ec951e68f9b88eb12a6b208186dde1bb1d6355ceb0467c5ac758952f559eaa54d178505d2cb9db36ddfd52e1b5d9de1364ba987a1ee739dcf20bad9eb389252f891aae89a3ee87d45685093fe9ae15230e0c95c64494ed0446385b22e9da6087b5d2a481f16a1350591734b4ca91ed4941cdeceefd9868aa3d34bc47f49c737b902dff2c01457be8eb7e36ab1e7ace993b2d9f102b51559238b0f5afbbf75b85ef9a281c7fb4fbea312224b3ad9b573d7df261cffc7c6baef1d52f2d373ed61553be9926ac0dbe4f4a16c7a7eac885073a0cf1751db9f06006cbe5abe9c8c58d1c64367003aac6e0b3e9c8c58d2e2d9b885089a23bb1356d0371e6ce4ab5828fca949e5492e8f9d6cf8cf7ab1d6354923a5c35458173506a53433333e74729a594524a29a5a90e29a5d4ebe69c78c5cd39b7ab514a29fde67ccad9b473ce4ae9acb3ce5aadadb54e796bad35d31c363534339f4ac70f17e059b338d37793b65e04f63436729c872bb5dd125bd4415cacf8a28eb7e136ec75a94b2f69100d1279702605c1c69fca13c28a1594311bb139d29dd83547683bc874c54965a43635e76c1966119d9b1af8dc4aba22cf36afb531fe1d2303721a497da44b6c3cb714e38b6a191829a594ba7e224f3c8f18a594529b8caeb468eb0c837c5c143c629f7ca4972e4af3c72d71f8aae84725fd545249f5a994a8a594d2cc6e56537d76c39f4ac96e98e32ac7d50d5b8ecb1a677380b7fba936cca9a4b4a776c3dc449aa26953ec449aa22545d1a6588bb96d8a9614459b62af662d87bb0e731aa51d83a646e6ca323a3ced5ed5d75d4ea55205759eeab3b6a6aad53e550a739d4aa9daec5a96799947b7d3ed586e56ab9997655e7601d576fca572f4f2e931e6baa52d587454aec34b5b9a98b66cd9e2edaabe0d732aa52d3bcece65999669d9693db598db3e36322dcbb4943d56ddcc7a33004f9e7a6e1e113969d5362ea5924746578c389c52a95257acb5d6629c75b3ca5c9a5ae02af572b34995ba82ebe56695a6ad091db8bb9c576715fa9a994d1b38996ee6d2369b724a9565b9e57076dedc32b7cc9db9e5fb81d7799e907b4f4b394da4893495985352a0ac97db26d2946cf6904da9536ae5b63b91e694a419654a557d954b714f61d53c0a42e6c7dc013f7e857332138a14616664345946878edc344b919950b479348db40945f5618d53a9541f94183734a831413f3f3f5063c28ce9a0c6448919e36da90b35264acc18d5c7a9e8551e91d9de4d708a4e3f25a85260967a965c5bc0787289daacb67cae1fac15bc19d8394d9f2fba6cba74607220e99bc3bb354b5127fafac07407db5e40758f3f2fc7636ec34b5bb0e8a8985bdad2c4b4e566ee6a57528ff1512eb735a13d5e05a6c02b9f8d5b74d96fa017a34c9f99e8ca214547d8de09393aef04b0ebfc06ce2ed335efdd3cb74cd7fccc0c5b3a1985be66e28ecd3eabd8676fc2024d4f00e99436da949625cd9fbaa9b3031c5b2125c17d516777ebbc5477fada3c2967883c534aa3bb8491449251e4d1514ad5751def4ae242139f9c15d79af2eca94af561170b4f46c0cc749f0403c6045f0ad3355f64baa47c3342e867be08b4758ccf1e42cb5c83c207dafe22a1494d60683c21f434b5a6fb22d0edfa1381e49f7a9a5cf2889e0f7774fc7348796d340668bf5779426ea64eb1a6a6c64673fdf4f47435da6b3c21d96b2e7d714d4d41f195245b1d6b3a7e844882cc122402ddc7e3cc974ca23bf39404c9f47da5654d599a9ab2f47c77939824994f462531e5e8727842ec73d8e6be3d96d06108b289eecc9d48824c7271e0a53b946be293328c849aae29c5c8244982844114619e4ccfdf1c7e5a3e23f2cc67399c1d626f88ed9a2598c833cf830b305f044a753cc749dc61231d6de030ca5023a329a8f4ca96ec433dec9422120800004000a3150030301810084562b128ca034dac3e1480107fb24a664898c9b32009521832061963882140080008008cccccc411007bd08b97947ed2855f7f22d001f61aa652530a12f2bee402b1ae1412d2fde2855a009259d1835d2e99ce6f8b702db4f0d5e55b2eb84554ad026f4bf946c4f98653ff31af76aa303a5867e14f83c65fcc9241481251939194a78a9f5ad6e114ec9a20729a3693deacfff4c12032f1b6947d568aee1941eb33fab6e48742254dfb38c21b04725a892cae7eeab4da761bc4844882176190f991e85603e3bf6bd297d9fe867b540e1d7556949193126fe5163e3d66d4ff1b19b45264d4b7a0a88147f8417a0ed561dec0394780689ecc16d3208e6ff59ae166a9cd74562a22f057d8f2af78e05e9a363a619db7e5d98eaf9e6f307de0f36cd6d59ea393b92d486c57fed5f8aae66c4eca13c72d1e473cf0e23fa10c82674217f8597af4e8dd0d4e90ef5042f85d4c2a206cf56a299ead6b5fc60705e1164ecffe7627c80e3f06272d11e334c4c7c159141cd998d015b2b39688af695b50689b92e19f9a9f91d9b500c23c65644ee5a91f35dfeee0889051f359179fd985c8766da345dae3d423ae96d88c1b430576044e5c7b4acdffc66ee94944975021440f0083fed3bad93aac792ed228c09463b744817d986a83e7e55c8f864fb15b7a43f3bed500640cae7112471c513d780a83303455733b0675df00d9bdac1f12f9dd8059635927a83c8e28091ac8ea7f959842a0dd2c024280c89107048e8804e5608803883ae0999d99bf11e9baf980a7bf15900c216d68032fa6c02f13b4ad0aca93a481c2df43200b174079433b29772751088e86880ae0330c58957a5bd136bd69061354a2012685de7b075b53ebf261db90abbfdf09f877c1ab1ded280a8163c952103f1b0b45baf37a934838e174cf2c6bf06496921f8bb6642628b28ec7b4c079a198a2ed706054228cdfd18f6dae3abe33308368faea7816084b6f9ed50ea1e7c6d448ca56c971dce6ef3e4390cfd58fbeff3a788dfa71dd8bb032feb9e853cfd6b86c0c0376905aa95f359c5f07291bb34dd53ae419da96b5d3417562efad395f570c6b55f65c49a84cf5ab3e6142ff0af0a155336dc5dcf4f11ee5bb5f8c7d33534ca2f2d2fba42d91de1be44da8235ad7ecc9094ac236b1688d184e66579603a607305481f2c1d52925bc26b2867d1a4ff49f4cf6c94348d49bb10bd5e2c9135fd6e280e4d77df32f9e0b70ab0978ef2b4b7943c24c0d18980736972f7d7f32950dbd6d5f76d72874a1a195455eaf1cef295535e12a22142db3959c7e2caf70f15029dec13a61fe6ec216087ea7dedf2ec856317aaa57c59ecd4ba04e473ce3e1c60e25f1a16b5f05740f012d86bed2ab47bba55a0c351110fbd684a43742086997ae614f3f62243566d93ef8f7ae6379e861bcf1abcfe4ab8bbc8f47eb7b8deb19faf025a0f298ec7578bc9946d488bf9384a36330c86309bb0555f95980e495d6161e3ca7ddea03c9513773e40d147df8c76a8593c8aed0904c96e6f746af487e158ec5eb75e408550383a6fbe7166c1fad005fa2888fd2976a090c2da4fbf42827b552bad3e0a2cb865df7e7d93ead5cb8baa182f98691980395093c2b3bdd0b0d06e0a9757deae6b17f88b06e54fe4defb5edc11713f9c89227667fac115ce817f817cdef2c7324929f60049c5b4e80a75326c0cf67f520f9140936e0be8166fc3d543d8a458ac8d85deb6dd7ff103ed62ab2ab501fee50015534d151d22907f3dbe1b8107718bde040ab6f41ac61179b6e29dbe9ffdda5abe787f8d21a5cef7d389752382a863bab82579438f76dae82375fb8f280f7ecbe2b02ee6828052f07e6b182fd254c74d4eeb3b582ff5b47075dd51eff5a327277d35cf8362948dd8f7d0e8e728c62de6a420c330d7a635b23044a6e34a450c7a76e1a432601079f89d3b791f73ca6400042774d9ba433723417b0a888e5740c4d5e5ec91638b1d20b69fc8c3baf3c73b69a76dc64ace877e7a58822207d76dcc9faaa62c5d632cd9273aee1779f7349a9b8cd7321ea1f0905579f4220f2513ae23ff7afb61a0f12da63cd8b9d73ed5d46d377d912d877d4dace4cc93d9bece2218971023a830c78306b2a95e421850b06b2f694a6888289f4cd1a85e5875871c9ecd883eb95152b8404917779717d0a5c556df15121ce3b13c4f25c23ed7dfeb3a6ed33006a7286f683a3989818018f3db0a32f7c6244ee4c9f4022004ef223494c0f97a34b1306e6d3ac0ab38924fcf9bf4effbec194f7eaa580dacd9eb9dc0f03390440a81b7ce1241ff9d4f663e6728af62254e67770c8b3026d38148fb4efe9dd776e2112aa9b4189487e3e119ed23ab92fdaa1029c4ab9892717674fc95cab93d06af871e0fa8a8fcdad2262e9612b4c5f8fe937e3a1856da459356b91884a8c17c3f575e12e57644e9c1c4b33feacd82f54f44084ed16f950f4b209a75468fd700615898ec4fbf008a8f2a85d4cca184e89fc902cc556e76e007796f6436b13f74ea3b362ac768de191dbfc5525e55c10c6258db0ee61c00da7cf8672c58697dd052bade7f5067f5b1c477aa1e810e0d635eb55515609f2b94867fb04bf90c5aa9c43bcf117052451553b382f8d063522c4a5a942f3f230440e20044b8e26c1c8652dfba62e6efe1f9443af2ca303719816e2895b4ecc771bc340c32d773b2503b8bc4d99bfa52a72ebfb4dde5297b5acdeed5e250c5de5aa662d11879a8015047d0af5e989cc875bd642a89401bd962c0780c5755111630070f2b48dba6447e869d5ed54b7f079cbf5ee243b641025944698a46f9d23f2aec41524a8645164211855ac2c2cc1dbe93a24f88d822cdf957939f80ae91db8fce1c250b57ec00ba35f08243bd61db900214b7d87b63f96fb90bb2cd714022131659b5da06d6f335ed966e52ca384265f2e5de6c5b481a3013a45b6593dbb709b6367ee3548a6de9947d74f649b7de9adb187b7732339f07c9e885f47313f73fe26816059529c04528a5e4dd28013a443006ffcb856f4f55b3e463cbb2cce06c1b967c6d00ffe02da30a14299f299a9e977224003bbaa4d1fdc0e8e5b5ab3e181c055418a26bc3b4ccd6e397755858f0f6d61717d1d3af879e7c13924364db930f592f6c653166594611ffefc9d2f6298c9a41083475fe82a61b0211710589dfbe1cf5d08a0bf06afd1d24a33c439cd06cac4e2f5e5c9917132df89514885515f2a56dc4ff8189aaa6f3bfdbe9a21a0fdddad7f104cd6a79f48f6e2aafbec41ef7728146a6ec269dd583bb9cd5edfc1a18dfb64dc50e1e440f4f777c505bc5610bc431845fb77614f0515472ee0f3e423bdb79338b3d975144b97f94ef7c8eced03b1e5ffef2c8367bac7066f1f08ed9fe6c32f9077fa9146cfa7d020e90351e6f83afd58ef4d24f6fd31683421e73604ad79fe26d6bf67dda2cb13f55718b998f84072a6d9356fe36eb887fe52c73140d3f68852130d66df65bddf676e2808752398ef57baa115d1b2eb2605b50c57e8755f9c876806fac40e7e0ed1fb7d7c4b489efa541d58a3d98d4368a35ec916a8872f8ba15775253999c2164668465add38cfe16bd6d66be83b15183635462016da833866818585a92fc1b736da3cd8c672cc9928edc8732abdaf6b2be8ae1ead0783ed9102121e0941b26e6b151258ad68f56f27b1bc182d1dce82b813b0b37c19dd7392a074038cb0e25e103b5e2cdd2c932b938c91a4c610a7ca370359b65465036c4cf8dd0dd48fb116d5ef2bc509493e232bdeecfddd2424f9a086e6b143d0544db12cb22c3e59be58747ba56f408bac537a50391548af5a38d2dc9fc61b4f508a3e27371c5b2175a8d9d3cca51d70285434e4c8aaa6a48b5ad2a4ad1a489f01e70eeeb61fb0850e4c99e1bc0e4c5d73381b7278e3a264c555e0473fc654d43b8339bd7cdfc4506f31e32c6dfd277072f72aa8df2a300cf4c6b5b086fb1d01636b7fb801cead1fc2867d324fc0667698ad911a582c965fa687041fae16f08481ca42edca4b36c6b6a06c799c5d41181317bac020c7d0ff5289b81b859e3f6f69d7a8c95ec050afc27f589ac064545014b41b85538825fc53f0e574c956d044387be2c63c8c1b6bbd0e08ab9ebc60af0a437814a90c340fa796cbcce88b966146f329dc20a03a0e97d42969d699306a6583f0a985c38d2f16f506b45554d01e0245010e1ea01acdaf86c828d8edfeee286b3b08b352ac6d59646d9a18018436308c98f2139fd90fcc8cdd337a14d42cb41fbcb3e1b247d22e435aae1584d5b114770831d3db3fe1c08087100e7c75168fcbf409b72aa7ccf4e64581018ae40dc4bc3450cda8a5ff301cd6b000b7245548ffe52d6c684e163588f4576c5d1f76d6eaf95345e19330bd8c09313a72bf93b60386a47b8175ecdab1bf467d734abaa4ce25882c8542d43ec7fd034d47dffa0856a892b5ea633fed2d256a47433bf7c7b4543ab0a2ca148e909db7f3089ca28072c79970f9988c9cc4739c7be0c89e32ef64ca757b4a1e634499f4284a722ea561e5d35272f2753d75a60e6c0cd084cd410d01494845010f04225229821e7dc59ad8845449c005e168a915e8807892540a72203e2275055d209e22a9170d9cc081ad52e5fc22bc86c0658f51259176658ed6a342bfd75199b40294524aa484491b8e1deecd6322965ffa991813b327473981b1f52b952f34ddda6a8a5779daeb42b8b4c7d103e9ad41c8ed18421b05c296ec5700b27837abc3519c60f53de8bd85a4474ae0c70d054d3776be3a30067882350d04431c498096e6a659460460850b22a98ddd2975085ed8c19a3dfb12e05e9a7995fdcbd2236a381514f322eee4c8cfc7197c79444a8829bc4366d346f914d93b85fdb8c4d81293fca7bd26442aa3503b192bb945d3cd7121d288c18d8a0614010d4b934bf561ab243cb5214e499e7bc2742b97e8a430f99d8733d01c5c5ef32d7ff6a99717ea897ffb915b8b07444815d38370baf1c369e25a41aedeadbc02305a39387fc423dc85145fdce1e46c98e1f1a0f3b3b62ca939fd498852edf4e40a0cdcca950c37a0ed9dfb63bb502b13f1a669df6d7ecfdc4e64ab8fda6efcd1fd8fed9f3772900f25983d37b28688315cd16bcaaa9e0ac7ac9a92e031607544701a9a169097c27a2bc71ed587f6edbfa3972620d65d1d29982277b14b8be318985947fe8fe5efee40503137e0aba9cdf72314a7de5ed50e87fcf209f25b0238acdb58b998e3277ee9b959337274034988502e854879deffc87f158bc08f87e1d11f077a8fe2974470db18f5343d269a915eaa62600008c2b89377da589f136c902578bd99169c2441f5dbf8cf1b18706f91537fb61acd9cda50c91bd5cc2d53ec88861f9455f9216d7e25fe5c320895387a04b55aad20b9f963641f61781572809d2394f11e4748c67d3d214d4724d26c0ea6587a627fd92606dcd8e411fb5c957db18696b6f6ebff3eb3e25141361ad01b3b17812cae4970c7f8eb2c7edc4688733b378973cb1e9b4a5d599b50c4738129c10b7b5be0ff10a36d20c6bf126fa48b2675f9427aecc109579e1539025821ff365ef21ad130e59c59b6af822489e59df3a9ce947f1a407b9984d9d99e6ef8e73f1bb040c0bc32d7e344dd5631eda97a1738dbf6b39003104cfa000c8b684b68145d978f51a47fae2e085b8e72237c9775cbff1104b91ba176b0d03b35dca8095a781f7e1329a4238dadf623287189cd100d39cd45ecaf0ddd851a72352dbadb32cab955db87e66005b2987e026a4c23af408744297ab2e2c4a2e90f8c887a4c24a1ee726de8002ebd92b7f99e1c6641d05220c4860924d81e11c322d65d3f8e8b5402cdda9a630c3cda5e88b32b7538af165926113c99a4f1a5c2b7bf9567739be30784cce14f8d6ba685e1c88fe35d738c4cd1632e7a74dbead55009320a50dfdb83b912c1b6675601adb481d56fac3334dbdf18f2a4592d0adc4e63be21271684f1941dd052bd2937724a01157c8547dd827704eb9ac74b993f98bdb8dde573bd567e1dca156ee7eb59d069500a54f80c1cc10a1f5f7b6b5a2111d5cad600ceb34adecc819cf4e769a226ac48d167e52f6b0c44f420ea917e74573ec73b675e39a708571ab74b92b2e3c4504678d20411a7c38486240021d05032786a8240caa2892c85c64f001e9dc54236c18b235fd00b9dc081f9afd0df166e105bfb4ff53506b623191647d747da8439574d17877ad404c86a718c42b95dbb011785756be6d8b00e0300204575f8504761e3892020c3b155a17a251885dc9fd5a57b74bf26d260d1e7300d2ef718bde5f086b33cef4e14ca359185318721be944ca5a402629116d3e949715e6c8834198e8f5241a94fa594ba95c9a7e1b26ae357a20163896b0e76aa2819f45f437a213fa1f103cbd2c3c1e1269c42908c3f76ef01fde4d3c1c13b61b7818ff3e68b698ae51ca7481c315f7099e86da200c3e24626af511ad08d2d78efad8219457d360003711b383792f4b23d4b17b0ebaf27818273ad40e03801cdb150f07aa3c186ea470403854dde8103c510c812d4f6c2067227e7cfa9d0178d6d1fa5c2a1bde48a4e1b9e7fb717a2ee945429744343e8acec2c640397c83992dc9860d13346618ff78634f1c028c30ebd1de04e711d90112df73b902aa16a5a4b27dd152aaa9c06c6da564c0ddf10a227ddf7e634a9d0051653b1df327a8b02bed1e403ef1b0077a42a3f29d858ff44497c0332f7552f745b7677634cd3492a683834f211d56bd032ee3e389d6fe03d153b4e69bc8f488067e217b54f5f80c07902c9f8080be9b75fd9e0f097657957884d47d1dfd5813e502b9de8c46746eb953a10b8f3644a960a742392c14de6702a2f882cf0aff8f2402ed58214172d18748edb398c3e0545d2c3158e577983a65dd5e8744f9c85f83f6aee5eeaa848ddcb9ef8ac1c5d0c0e89401d5fd504c127f368d25152669dd0de371cc5dff213d709f1375f84562f62fb67941bc5283e2a72d8fc5a90e6d273c13be883fde0b03a93fc202178424bd0c1ebad3326fc6ea2759e99a538e820d3f47c35672ca5b2940b46d4301ab3adb4adf0170222013ca3a4a70001a35b3e443b9eceab6710320c26f33730d82db866945b47fbbaf00cc4a7281a5180d5b44fe05947c5d1d0854686c90ff22a0bf44f36919c7805ac2ee1ed891040272ee24649a2fbfb844149f64befbd9225bb50a025f63cffe88efa94cf900d9772fabd3e7a945e8f3c164e380ab5f960e5991e4caf47bb5caed934f6b15876e88c885b03bb88bb3deca2f691269ee15232a18213d29e265c2d4fbe183a3e740a8a6b1c973e39f6afa2a7f2cfb1fed4f9a2b4da37270032ce92d0aa52836f5b64a3e3f8ada071415b28391e4f4ec0e533e3a9c4c1ada754954f4238179f1afba1a5ef10f3ae7829d918a478dde68b8606a79b28d924928aada4c3392d4d6cc41651f46762f0aed8c75e3cb4ef93b55e4a3553c3a6b1cfac512fe8e6dd2ce00d6a1ef32e63589ad89fe3d0f0bc59a993de2c6f96d7e9a110da07dddf273d286dce525b0d6474cb49d7650340eaad5e8f3bab3b4ccf653c28a978f4c6b30c76164cc13397b9880c86c48d15be220bf99f29a39838230492bee08f13dfeca1e31861b132226c744a9c74900b1352164940eaa75825da4c3ab8b59849f5fea6d39a9c4f2dbc4a890d39bbeb851ac96180b1a63336ac6628aa73ee3b94b06ddbab90583e9894277dead1e240bb01216aefb4434d77ef2cbc3222d0f9953750c203edb946c5edd2c74d28072471befd2772b8b76f0e1c68e6c84da6a4424f101891ada0bdb117ae0a06c92c45f566a3b582a66962eb5d7e4205d9b1173e15aeea049a949676a98a5de503480f1e4c823a9605cd0603f6b7da0ed4dac391d5e8385adf0bd4c0a219a2108744791bdb154a2cbe9645bea4e09fd355d8a3e9e79d64a693bab3bae34297ab781915e253140c4151ba6ffacac3a4b74f2e5cf195c289b8135882e445d2d051e22f21c898e3fbaa2436757b9a5c7acfcd016b98a92ad511dd0abe5f8e15be5ae8691b0a596a88cdb3148d3a8dabd6bafbc16ca140d426ec91478c807f77120726438a70f5711b76162205456855228fb162c32e0285237752c84585326bad75e99310ff096e8fbbb93b6140e1a96dd1e814c79b4c6893ba8cfef05e5ab215b00ef452a5b08ac11546cfe9356ed49ac51cbdd7dc8d8848d76733967b78ee43e0d719cbb3b75872293b9268058e3927515df3a23ff05a88c62448005a4d4d6712101c91b306520525065661c87e621c40dcaa8357e4558138e1993d57d453b2dad6ad1eb5ad1fc49d226ca0e6765641074fc4880068077a008ee610c3929d99bf0e7ae1e809c5ad07e4810faee08dff5d044ce77730fbf71724580ffa30f932d4e056d3f0c135e72175d730ca17b63c032b07caa5124b52dd063f47679f54dcc68c7bedacc119fea98a958c25e532088321896750dbff6b125aef9f0efd25105e6c42cd98088ef881c039fd5286883cacf8a488dcf4401043c4f512c8d34448b4f0bc4cf6b348ad15a5d732bcdd2e0e26809e6d6edc937d9f99c5e228c9126a59799c41ca2b53d34a76002490b564ef2f2bbd1b130a020d480176019fb106261e7d116fecb4639d8959c7636f804dbca088d539ce5a17c2ddbed272be60ce4fce51ba2a1c45a8c290642bee8e6127d22051005e3f80b937835746565f0aaab3bd9a7ced58813d5e5287900ace0e3ddf53aefa05c1cb5e5ccfcaaaff2c8beceaeda565e5374a5c0138bd5318a2cba4caa609e992741185837ae69d01a4308525b1af489bc86197dff81e12886521e9e91f1cc63982ed41c03fa879c1d0ce84cbe4d5c5be10f967d0c8c9318240ab068438c11021a1e503f07d6435fc0463bd4f64d3fcdd6b653c2c679a59f25f6397acc8f3b54836f60bc584b41c3f59d861450a8ecf50870a2c5d410ca21ceff6566331cb997a320e8e05cb0536364774f988f15fa865f4bd70dd49f17a688fd593d879caaf3a612b4521f79fe1697895ef8c81e21a7e90f5b9fab466b1431ad7cdf460a57910303f93fc6ed55ba8bed08cc6d6d265e8cbe347361b62178ff17377dc5d510cde0c0b1d2545c0588619ea65e07d2072ef2f004844bd76481cab337a0e2fcbe5c661b9d2e2f7d18ee96d1bc6ade1672fcecfad20d67e2f0efbdf92d87bf939033f06c9330f43048cb68fd1e4fa4139667b5c34f02b5de80da296bff15649ffeaea8fe1ea703b8e2f019716fddab143c689197f6dac672c2920cb86448616b62438df7c85ab907180a6f9088d18b9dab5501f62264106f132d9a86c6f6c3440477e4ba680b653cbdf0f9118174b471f78cc6f58cbaa6276b7e736b5e3858c466a1379f3b83a1ba272a52187fab6bc18553990d8e3ded1a2057a56033c02a9b7bb9e1a86e12e1f06ff6670bd5a7d96cce1ed191c5355622962d0c26affd4a062fcf42f600ef598287a237ffad9da8d587a92ebc5c7ac7b434d94054ecb03eab26f271f8e164ee4f3099020665d162ab9a9563c648ff53de928281705b5f206cd2393359187c08ec6af49f51495c6c038bf8b0e6032ef38acdfd8651ee0d92bb85d7dd7613bb773cfce9c04e44860f98f877e81a64b0de53174d4dfd93731d535f86dc6e442a03b831c275a83b0cd9a8a3ab0bf815fdf2c5a3e0072f842eb2b4bcef0a975edb3ad7c0db0cc2bcc77da4a43e86dd2f62d21fe91a096e640571fab5f32d5f886204e67a630483ad02fc496675e48c42c0a52850923454c92feeba56d033e9fce0b86c204a7a7b0303d144daee1377009967087e8e6ca74e3e3d0729837aed25dbe3421e22df95f0b08096a5e299ef89fc1c156168fdd262cc35647f701a31d59236630c4c0ec769bdc9e051a26d5b874979f878ba8deac103abcdf9d423a9f019eaa5cece411556d2274757941d2fb928b0d80c0f9c2cbcb42e786c41d750f31a92e0de3549a547d3a2351e488ea7eecde122393cc0973d406d6ed95ef264944fbe8a6bb82f7438d0760b42739d3fe0fc8a44bd23aa3ad864feb5a449abb5d1fc4f87c30dbd3c15f36cc6955884e7098556a1765038553ba6d780e19d3ed91497929ce91bf824d521be8b3d3b1f2e10c33497e6728a4292da3b4ec5af51d3416b7870a98d171a0e7bc927b559452f02f66d70b7d2f38ed241ad839819f2b0035ddf37145a3ece6c7350cf694a96b631b76544c5fb6976dd2e31e8211b5f781836f8665452517257057767e3a4d1c8cb28a8184ef92d5380d5f5ce08d1b1e4ff70b5cfee9eadb1d0cb47c703e2b335cd22eb9a654e4f5e3ac62b37cc0edd4db9d1823e2c0213f9ba637140e59ef86828ac640456ec4d4c8d1a6ccae3311f0a20c21764b717a0e788bc2b0b59b1dbfa2714003620bca600175cb941abe6565ab4d2c4b4fd4a6144a70b7b1025108f9271d9e4e3321090a09d6dfc4e259fd8252609d9697d446422ac495466dbbcb4e2379b58ec63e5b03307922637a994747d55be3c20c84c61354d9247dc0a9b4c255fe0f1684e9318ef726b71153c43390aad3ece7470b203b8700eb98347bfa2843192694f991f07661226add3cd43df3c8d22168192916e1f12ab42e28c6f21c1ab684ef00a397354d76dc32983372c2b6e78c632da43f75917af5b3b2cec0e0d5ff56c7cdb7c16113a088e30ecd31e1a379a992ba20731126e29172c016d0a89b00d1f63cd302ff4eea11f769ac8abaa9c0600f7d92072d550d2676aa745156baf4d49e06d963e48d65160092bde9a2a884106e1ee067880fa9498550bbd2718079069bb9565cfee117c8cc0db3a95a088409c786d3369f11f4baec5cf7db1b5e00decc7f8a41588f6cde3049b670a7df2a2dfa299e5f43b312f7c11e1419c7f55f57a328955a9ab02d39ce3dfbded29cb7a65ff6bbab204fff0bb738fba22e7b7511674fa119144ab3570112b573e10eb3f740ef57b116de9dc7547c7137d7c8391dc301c175807708d5f31a495e92c0c60ca686fa4deed529d193fd481c4b40fc9b1f2d763b23c23a4f10fbb87fa6c713c13d7edb67dea81e97828a221f12d6c2e3eb273e0e59891ceefd8f98dd0509acdee2ace6f5a9ad987cad4227aa8873077feefeb3a9ea2f7a4a33685dc0920caec9e7f5266bd7764d970d8510bf07b056ce763c7d63918b56abbcc0212453850917ebdb6a2087aa5fb737e6d79daebb2778feec128c0d506cb72e1780f9d02364aab99496f528a0fb55bc8e42635b2deaa9a5741cb4e017d023f7d2deb8127a8e9a0665b7fba1c168c14436a29d87598e9f7488ff35b013d4ef3ad954cabd0c29a4c958eee7af53a79b6fac477fed6bef61a999cdc08135ff5460d87e6e55f3b3bb414310cd37b3453568178721eb220ee6903587a03df7113ae6880f7eabf9c5a98ea26d80a75a84ae39b29e78d3ce4b615b604a542cf9fcecd5c6e43ed28caab6e0fdaa2eda841b3fb078c702110ad3a55afa07a2d542112488cec4cf11752f2b4412e14bb223953b71f0bb4115e0689a7fee7b64f1a0463de50e88c989bbde21627ef0000031064c19a6dd896b30320acafa35639975c15389b07be12f0dcf37264ccd2c8367b13dece055b542195c126c61eb88cc9736c2c616dff4e7e73ff178ffca1a28ee597e6b135e7b8fc088bfbcecb2d43881bdf569f6f507b86320680fdb361d0a293cbab489de47775bdf3fb6303456d26f6b5e2843064fd3c1a656291325a350af8b9c5db3dbb7f1f638a0bc0d9471a91ccedb5e848a112dbd0d9a8eeaec93f47270fd364109cb784d3baf7a6b331b8b465e45815b6111e3810fb2c2d55c1dcb61b66aa9d4472d7053ddfc2465fb5687761e2bb93ab47363e801fbe2685b2af0e3ae90659ef195911633711fa68030d05bd15ac1fa2601c3bdb29bc2ce889b9e47cfb32a748eb6ff6e3f8f3a0d2012ba5a81169b0efa93864e4f393031c26a5eb039526c2f4f31486dc88abb24ca0dfe59f5013d14ff3e080ee1d4f2e05b0295667348797a54e32c295500ced59c48186194482e59547a37570be819673b9808dfaea975c906a1c6bbd8f3418d2140ac5a3e61d287701d66ac77eaec03fc0abcba8661cbffdb9bc2ffc90428957cc156c948bbc0d96e6178f582e0e2bafcf9bf917ef168c253290b0b84201c0bc5426fdcb5dcc64baf14b7d47f27024241c120a2a5b39483e7e82448da9c1aa90deba84f348ae46efc2eb080201c3c5212bc33a051b22bd92b6c9ae547be941381461025f399a0efee319c84714df0d6a144c2d732b2718024fa3fed395edac5c4d8f93cbc58f906f2804186659f181d511dc136678316381961f28cf82e594f6242668808f3bc2733192ab3312c338633b3ca66660a67f6c5f2cc2a8c29676690a036b341398170dbddde8bef60f020e122e369584a54806855b68356254606a23ae95dcd2ca97257efd81ab9175e2900e24decc53c0455aafefdda45d40d1f631ccad02d9acc423c7c02d80842fecc8f07d19644b73d6a6489337f6094950662c32e7c0611ab9a145eb194cb1111d2fdd6d3b5af929af02a9f2ff57d8056447a9dfc02e87f8c95453008bd72fb3cc65253261315fb7a69985cff19d1e53de7e9a7e8854448925137cba5309d78548bf02a84b4639a449cd15a7f3a1ae0dda00233686a854c9ed046c86a24726cf3af04f8fa4c95b17675975ceea63e4649132fe407c923148d89fc5eac1ff5eed54767e4071221c7b015102f2b8b181772764df42f05391dc1b3e2c2f9fac43374f3b5d984103b62139ea7ab73d951feb1d2612d68c186f52603ec6a9f531853d9143bf526e342dfc0636ad80d5e54b4b41b98ec79c2e9100f9fd092b8eefb463323f07e68650439703575ccf7029773b3d8eca8cff88b883a98e8ffb48726888eb15e0c82dcf1d16e27956a4ac2771f61e0c1db37633b6cafccf452c440a3e1db6715383d655d4622eceef72d8037c8e28253742236310d4138861992a4a20db94b07d55c281af03a947d1de4f84d480d0cfad1c56c8c5c3b7be97d00e495f0b13a7bc7ede61396c50ada9a7867727a70f0230461a4639d12c2206a2a9273cc41038a0075e0f20e20867bc1a3536ec9f4a63d7bb6584b4d1aa312c937d30d5e6052a11ada6251cbabcf7780b72fc7d0951724eb519b5d46c3f4cd5d528b3edee818346588be9a18a62f6496041dbe6ddd82a11b03eabc51a200bbecdab291b830317b798b6c6c92cab06c2cb053564a1a39f9d1804eed160e8898e7fe61a901727b602d824f9fce82d7e36ea2f9ed3581fc28c8242982a56f70a8917bf562d6a71023b5339eafa9b45af37cfa798e5053c9ea8af8716cdcdad5606bf000fbb2f7c5a5bc52846ebcfe8f5b6921bcea97e0c8aa0992d01f9054ddf57e32fe1259b15476852007e8040064cac56816a41cc5ac0288301e4694c98171a89a50b0d04794b4121451608e0ce46ad52c0d7cb50a441510bfcb54b2a08a6f2a8cf4d0767ef6962d8e1c01086b48670f404a1f04835bf44cc223d608b8f758ab2b015f6ccff4c562d924d37f3ca71f683823656c775c9b3c437fdd1bffc7703d98811a2c1bd18a017ca58efb1f1aca0f8ae7fbf9e3c4c9826dfb1018f5fb03eea7b47db060cf0a1845cc95d25701fb3b0e69888321ab80dca9020a5a1560a898870553604b4b20eea316938b45054606ef01b9cc3b66440b1500bfc60e7b7cfa13a5d201c7c89c356cf754f2a108606ab9bcbec7674aa2f17eca08bd351f63bc0f347eaff296a7a556947b701070ef88bf85c8d603061bd1694de9c46a9c4c92a93df99c6ba3931407e0eed376f96c4d140266c932f3ab3de1c40e1dd6f2669ea01c6dd8eb121063c4aab2366fe98e167015d66d2191f7355c16ea5dcf770bc02aa1869443ffb56c7ee3db48bc2b50857c06d33b8002aa0fea5a1f8a3980004ec225e46dc1b3be7d327b3594ab70a4e039c3ff42663a38fc5c4c7cf120bd067b7e11711cccf5958628c889ade8ef3989392cef144f7f4d01a24ff46127a3f9bf185cbc5fb0492b3c06e162dac1119f4286748459ff5f92d12597189518f64adfd15d8312fb0db30d29260832abe45330a45efe75f8ab957e14685606ea6f12901592f9c33ea892c6a9099eae44388d2fdbfacbb3cf9fb1d868e9f1c3475d36b50f054feaabae969c51035188dd51ebf5f0f300ddc067c0a7c081ee2c7e956ad342c55112c56448a183160fbe68591bfe144f934a4c65685ad0b985a2edcbb57a81ab9819d91ff466532c8d5faad2b16463c76ae0654c127fa404823d48de127455e2eb6a126edb7d4ae56eaa2e14a7dc51223f19413cb5829ed61c75a2b00440bc4abb9d5b4a1bd72b8da5829232261cd447c8aa59146283fd23a7a28ea6c6b89cf7fe99f8354680390fdea7d22341682084994957ed691e4c7dfac5f87797a036034c0cacb78f23e1e4805695ce2a81be884148d7fcb2bf78440109d12c0dd9f1443d3ef9ad510d16931eaf0e342dd0cb478fce7aabf76a7f04953d7f13b85857cfac41eef3ec781b78198c6d03f708379a7b6f99e9263c4e6b38f9e7d2e861d295eb699af74e993404347a493fb635af2f4753c11d91e536e7d5439d017629584aa007aaedb25ddbd663db00bc83998d536359cd443914c3ecf1d64938a3d55fc2920425e7e239727c21193cd060895fd7f2432e4457b520ed190f751b8d5f89afadd054e8cd8770a0f3441d761f6fd0ac91a2d5e3a27b7ded72c52d7a9f895a058aa2744566e4e742691b04f310521d1632f79078958e26333493a619459133d4e9ee89985f0bf9840ada48d9916e33024394c0d3f3e40189c46a9b350365fec8809a0ff84b962f3553ff775311ca3f1fc76b29ee15893b4c3238f783184aa28c19a47a9efd9a500a54c925f42f9b2b3803fc86ea5b95b18759634796ede36901043ee4640890d66a8418577903c5298b08586df1d9353782aa0eb5bf07c239cefad689c6003195524c50be8ea77a003d213cd0b16aee579b17a55b987c0f76a9a041fdaca8cc4cee9c28ee34b1202e55c569eb312b002cfd1ae08af8b4d4c461b588d134e24c742b4858ea81a6d965afb030fc83d15d7cf19469342e77239f833ce72095e0106c9aa4055e66280a0b724d9218a2550d6ea6d5a60c02e8351ca72eaf17b0b8c84572a4dbdebb9da58fef4b1d4ca3a5092a627c48884c8a6d938b30f8b7a4fdf1c110f83972e0308706ff95d42398e274cdca57db6a07beebfb88a283748ac550b571289d4720a20cee95a0b342798096547f199587375fecbb9845f00c61fce9239673b85288d5950e9b30159a85559ff9b291449e22e97d447ac521030637abf6c5f887e2bfcd2aa9ec8f65363030155a2bb310f3f114ef3fcb9c90c7c5d4431b6c9442813bb6ec9fce3574b2a0d96939666e04d0a0cfcc54ea95cf60786efe1ccdc8909cc505437ca9dda846d3eeecc6554727eb9d74d5b92bbda17f4a7f4aa0b8085c2166a2112ca39f51bedb5423e2ac853d55ebc393c588b900d3518bea08916795d55b999c5b45f50e4f243957a647ab4d600f0cb0ccb041cd5c6f87cdb6fdf2a097b8168faf763f4f226f20648c632028dfcd7ec22f55cfff10fc2fdca4d8d5f70c478d4a74cb663f741f93b0553c766a0eb0b0a522618838a0429e38acf24df45f822246db4fa8f56ea3e51e427477e5b6e80cd1f3e88748c13e8bee66ad9976502ece2a4ac52bd36b11a57c3f741056631682e038440f37a704c12478629a7edf40cf04589c1f6091754ba91b52d56156f6b9d283ae2405acc237c69714161c1220f02decfe0a4dac7d5709044d2a3b61f9bd242f4e35a25a2663bed283142d934103c74eb0cccde9522bb42a32ad58f24bab14301112f794646fa94812a388c283901a0aeb6c108898235a2a4a810b3d1bdbc2bea0614b1dcd22196494148746ba219f92fed0e4c64d520a5f65f7ff96f3b90f643841da63d0a423446198092a1c3940d2b9f17f9578d38d8538727126fa58e9d3338d4350afa00a2dae09a16b3aeccfe2912aa5799abcf4e40f52b94c989152f3d4dcc3d05bc70bcb6786caacedc4e56f4a1f485751b121dcdb7a28f5069ba83c7b717bf6adb20e5602aa79aa9cb64f07d38b43eb6e807798907c6ca76b7ed542ba4ea8a931c468f3a4fcfc7b354b4cdef782a5c0038641d9ec97865fd3288e1250315c345e3385cb8852092c954a1a9ac03b1af1811b1b645653996b25b99e60ebfe311ae0cce2837a9066aa4f2e610f01d99f850240240315f9390bb1ec66185234eb86b06c2cd15f1d28d9c356f78ad851f134e8933daacb56908ae18a16f855025f4c8e2b49da229f6824517cb006dde6ad47bae47e173c5c52bcb37477aaacaa423fca2eec22543bf4b1e8e30a1ccdcda0196e373d9bb294580c758db79b57417924254ef29cba27f201d4a34732ac4b27f34c728539bfb66d484dc8cd1078cc04c1b764453a4b086180206a1820e1f09226cbb4448bae823fb1b7f8a231b8a88963ea0d744ad4ec17a8addfe8b84b66062d63bbf5f778ef7b92ae62313146d081dd1243ea42b64f388a0d296776afafff69d4910f48f0a225b4bfd21fe6e2a40d3ccd8768894bde28d5056f54211ba91b7715e3c8a34e2136d0304b2234f47055b2e94772b31c2450ff5ee2d885a0b868909626d4cf4457e5b613a3672fecf6e02a00e0d1e5e7df9a2f2003c41ed0abdb9ce868e9087c23b8ea7b85fc91b59c1477984f63abbe9dd4d7000ba116ec11e938191bf23c83e8d45502b1cfa578668ac4680b0fcc01a1056785f9184d0fff48bef42240554db04b0982ce928201a5c7a909776e20e7d07237c5aff3a2591404a3c8da1d65a06f00a307bc9e5c4ecfe6b669f3cdee17733dddc4950d70c6194d805c5da353042c788ff505378ab498b396e431997dc6a215c35a1e00c5a91d68648fb9a573228cb63079e258a8cbcaa9ca3f066827d81034aede7d2d4287dc2fa4c9f05e17fec3240b1c43f08f8018bc46ca5f8722f80d9e7b49eec980b0841babcf622ade18cb8bf15e6eecb8acb197de38a039de04d97145c3a0c665857e43ee9cfbcc80759830a7280cde6b6f60a1f62cd97313a874cfd9cd37cb556d8ad6a74cb974754c9b583c7e5cd0520088be167c5e14ab3616741527748b53d2f0dd6dc21047e69560a7a1bcd3792bc6ffe3ee810bef97a3b3e4b4fdfa47a2b6bfa6fb37f64cfc6edfce926dca1908af0ebaeca34715b198ff3169f58588548e9f8fe865105d5f13f782e35a4bc1c50ee9ad41bd35ab4f564b3e4672d747f84be39ee016f3d13e68679ff3fccfa17d03a78272a925ba183bbf145ffe6ca05aa8a2a7588ef58f2b03014aff9e242182cd00008e17ea82bfb5a8bbce12bb2af7e7ee3e00902e5641ed63be39ffae4828a93e63980cdcf93bd6373061e57ad64f5eed4825ba433bb124a7e1e6a038f02d1f3bbedbc4d6cc3d9dadcbea6f919878b703c6133b507bac03ca6aa10ec0ac4b206a6c5d680910b4daeacc7a0d4abeade85d663df68a2e86df49488dbc715616fe1309697a4aeb7dbe2721d481432d830bd04e1be675698ac843dfb670cecb9082afb0f32cb280339204de7dee9865ee758c52ca8c5f40a2d502940605e3ac41fe1710025e55f5fd840897b2248d123cf1fc115e87e8fe3541c7e6263dd487ae5511c58c4c6f4de6d83fdb3ac298ff2d13d03a2151b446d6b36f9c7b02311663faf00f10f2ce788062db8eaa122a0f495d1f4e636bb1c01267a37c4be575fc4c9e3f0e994805101165b4af73d187c9a315fbba5472b1ce6957505bad6d3fb287d0134213bbd7398eeb3f302fff46151a76fa65f4c32ca36bb7baba1037f66673bc79aae9c2ae13c79424da73377bdd7ad7b1fbadeb4dd6b0d036dc56d45331bdb5217f6bca30d4e05af1bf005d9804f005be03480295f906b42efe84bf8cf39d147de368fedc119ad2c37920402add375bb8fb3131dddf1baac6353193e29f904e66499773f86ab4978e00cd8ca7212518c4c88de9b76a30c23554fe05f7a8b97d5b950769c2da6c09a10070977a5966b481a2f413f4173032a3d4b3d5c70f53ee0b1f6d33991a7b0ead25d1d14cd9544c1afc8f86f7571eedcad136683dff8b55a2b2c4f1e6453ea2dbc6ab76b61dc914076f8e4a0d31147d7719d93d039a983de1ede8751d5f9b9b86cf199c41bc819c134b7569974783fa76797d592692d65f1beee041b13bdd5b502f1621ff8162cc81bad36cf709157539a98d28ab524a1b55d6a4a436a2ac4a5f62fce31d41bd4bd708317481de73f8ff3d00496506f401c8a406a7c95f93a6bf590d55f68f97124d5ad7f381578e5ecb4c4d4f443a1767c5aae334c168b3c03c3fc0748a5ed0f70765a241a91d2810244a6447c8dbb9a1f4a351c1fb926ec0a1f6981b06e89119bae2f41288f055e57f723c2347b318384dbad95fb606a62c68ac9efafa33b850105654d9ee654aad183b834a12b40ca055812d27c0aaca4416c40e584a6a37bbdb4b56f6e4eaf5baebf6ef01932a4d77b36818878bdb98994193cb18689657c81561e55f7a0ea1612c758999f4dbe619f217828ba9b67b6bda4ebde2a9553e43bc0fef8685566e9bab31d21108f01e8008e2a752d15cc46c12e9abee488296af50663db135ca0c017f0400dfcc74746abb77c95802c1e1f3b8078e0c564932263dc3c516e00733dd1ccf5e99f350c63459e4adad49de402526cee763ef371bbb68c5754c66f333206ff865398daec8e1ac77c8154b517fe70f8c3f1867ec8561104b47f70f9c01e0b44e010180bd08ed032b85702106e345715538d7ded36111152c1acafc5ae1e2091176ff4b6fdf6e235420d8ba31acbafddc93bfc7585888453ddad806a161bb20277e2522944e6381cf4c416068875efaf01b59ad032891fea42b3d50d994ebc3375106c50a3c5b56dc9d2574fd0ba6e74988941e0104e16b5e3f84e9a22756afd8ea6a48303c01bda005b9b34c5664eb3cc9de9bfc1bc699f9d21beb67d98c3f0c840552f25e49fb3e81868ae93093614c7b27af51453c0b0c0fe0da8b75b9ef9bf3c41b61d4e0bd4ae0f703b9fbedd3b0f123f5e0dc443995ab5fceab51c6fa45a45c78d857d19a9354860e593708171cff39e09952736d33c79fb12a6889aeb6a988ec7b00698dc0dd8fa4cb237bc3d62508f2b5a311b59ba44a013257ba1f66281256d63a28b284e4fc2e52250acc088a58c19e6f4cf15e3df019815e1729847a8fea422ff9a82e7367f49faa2ef56bc71c5efac84a034399cc2a4e2b26a6cfe489292e61302ac14fc135acbca54256f4fe77211fb090ddf4769d94b7928724456c91efd4a851c4fbe2cccf1de8ea96770a9f85f3bbcd4ac272a37e5cd1f1dbd96cdf79a9f58bdf1abe94dc4c6dafafbf956ef3c202068cafd72f697298c2010fada7716962b35a2fc06a492fcb8da45f1d3d1f2f61546521afdb92696696675a43d9cb16da40be22c0b174e30960cd820acec46a00380021525ed682abe76869c5c9dd79d7379a22452845d91b9c10bae67c4678526155c70903253185a1702d966928cd8dbc54da5176fe3afab51e052d5a59c2fba96c694e9cb81fc89b82642b756f924c3417cb7afde8290a8cff188ec96f0d51cd47571957c4d54a7de717415883e28bf65e3cd7cbab869f0c707143019e6377fc9edcf75e54896175d46e3c691e24b614914d06715d5fe4dda08b2f13e2e5830bf2c6a8773e4648958bc7978a26d1bf2e9a96df488d24702346054b2add2bd8e59e68144cb1f7a1201b7b1daabede19cbceda8acd977b127626c87fef1785cacf3d2ea8f1cdffbafccaacda056f45b106d812c47d831d6732254c89c17d2598b070a88516fa537cf2f314dd02a383fbe57ca48c2f10ac10820cddd6eecda5ec8ffafbca978478dcfc8e8bdd8f0ea0c2172f4dc62994208f37d01a118ca59ff46e4ab01d1d4ebc27c9d21898e61d618a774328fbe62b64f9c5536e21b71a48d9ebaa6955ffaa789d66736e43b2e400a4cbbd284434cc6499621d79a5fee49aa14f1aef40a53f88ef25017a12fc281d78d3bca19d006e63b6232cac9721c865afed05dd7d3d8153213207a02b706a6653301c4046c2bdad66a087a6be215bcad60de19e9c6dd9cf03c55b7b89897f67f2aa3510040d3233f0855b4887dc57e2f2461bb728b4773da6e5ebc0b925bd32b71731692701f989479bacb608928c6e82319185e6afd2ed563ebb655e2b4576f297d0d4a8daec67ad8a977c83f2ccca4bc2b056928780ce76294735e57a603269bf0b8e4bcd59e96409c8a35d9db698c8bc1a6413e941809576fa962712e6a91b471d3569c7a633f291c92154459367922fe52fe476ddbf84e67232608e0989df8f7adefde80c9bf3b4f48cf569e4148e7349d13f88c425d7347523bc9b6f6d1f8c26b4db36c9719e5d091b323d0e2c57e55057df4a275c07fd44c701141cbbd9a10708fe8d6c54effd07b83d3608a24ab4d6faa68b58842d11a5ff0184e42cf5e1b0067fd769438a98dc500742de18da7cbc6960031ae2342165f990f618f0301337d7d0fbda7359aa2b97b5f5bf3779424bb689ee2a688c2e108d5d8a77709d181d26e5d3504b03acf37b107d8c3049926bbca94012d40d4bc62f7af70686cdfd95599dc3d4c5225b286efb822ad6735956bb3678fe3012951ba706b731970bbafc93308f2fee4eee8efe115a1abbc5a7578d16243bc6954894c9c89760a80c784850deb23c3262b8b6ff98916593cacde2ecea346088878f8b400b70c13b89de9ab0fc236198beaa9a10104c280710f1c91f08d6236336d64f08114702f04dd52f2fb8fa74b5d955e2c740ecc4efba8a0e0fb3e4164d8e99e4dc3090abd91af61627afa812c8f7c2ef13c0aee6ebc49f5fc4103a70aeccb0b4b622007eeaa1abbe73cbaab7d48f7766dd9ebb404d19403c53bcc9188b4ea33c6ecac87f8f46a7a0d7be9c8e493ea5bed10426bcfe0cfd041de78d14a71f263794a56cdb1187aeb2de93dabc27083111e4e06f102a5fc704efcbaac4c50ef2dc1cc212a5c7387e89265df19744ba55261e856c24084cb3ccdf1aa9eaa34baf87d592750e289e0fb5be974b834a58e68800e06d42faddf34e32083c802a4aa551675864ebe656435065afca99b1088d08859fe12c94b34d6dbe99afd965a8c1fed70222110d17b2f5105453ec217c86da4344ab5c0a822995256fc3bdaa9f77e7f47f51086db3bf7575cada207fccb431c4f1f881a3c72cdf002e96acc00a4d5b77c27b48d49e1c0588800a4279a76f3d5c4ea6d4ef573b18c494cd67dcccb4b6f803dc31078e4d967ed2b014e904ea90f6f19931e2271085bc16cde626f7d2c94462e0a8f9d19152271db13d006c2846e4175a75358002c4bdb160062bbffbb540f001114872cfea018a8e6ceaa2836f658c4ae334a3dc562d68962c15a3d8239c58b656dd3ca1c893aaf46d72d6e46d6dc6e40bf29d4c776ec77b3fed8885e21c77628ce73dad64e37c6688980a008fd1e1e0460195335af1440515325a83eb5d8815ca84c60abbbf91185ae85cefd1b7e56bc58ee19c9960652c83cefc64db76408c2b0a9010cdd36c86b46c5b5866e23b5d4060f022edb667c7fef68f883396fe6cc729fcb04f4455816d51de434a4b50af5f9b66389631c546edbc87d01c652d9a571e04a7002f620214ee51c97553bd12e96acec5a4b21e0e08ea424ad79f2bcd9e7e5f3192715d5d5b21a0d2e139f28de48591fa66251ed3ac24934c9bf53178541956d8c596542ce312b43617d505d222ccfbcc1eb25998c56824ef002a8b79759cba5bc949e484d13b0b233b56ca2995de3201257d3a50ec2e1271eb3d8040181b7779bceab015f00e2c4172170d5844d3f11212c46634e0992652928089d7d3a5c3cc6219cd55d8f3284a51f2c1577643419782acc7909300f8726badb4f6e1f9029605ad6c603577f561c3e5a81a20bfa1a92089dadad825ef32edf956c971015f753b2ede84b45b94c09db4531017f98ed330864b249e00f222598b36f11e1a17da1987ca3601f2e8205f7a1181539de8e4906df14ed5303d412a315545b8d9d0fe6efdfbdf873ab8506ca665bbee820e2a95ae27db042220c0111df4142800252111af1535ca53013cf0fa37ecbb762000c07cf3b3713b398c9012f637d0f2e84b2c58d65a473a3eb881a06f3c588007dd002e84c399eeae493672ca4ff3e26658d5f27a785e0a9595d506d4df35b6f67dcf7ad886d8fff679a40ada3e7fe46c4270989b1b9ebc234762d635498305ebfd4e9acdd11f48c2906d32270907c9dc280621b999c97aed0ed8fca95d92859b231388a0027b90240a73866f9d3c30d490dc619955f5fb77841267510887744f054704dda36308493958ab39c94c43a2c49b9b2f8410b4007d328380f48a72a0b68aaad8f2bd6037c2566bbbd8f74e5102c7b5856a704774be6afb3b6650a186543d8e19e64649c40b28edf1846f4fbf6cd8ef49c10e9c986bb4780074cfd43e5f773a5d50d73c78f3f71c897b19af5b5b249cd81e00f4f558237ae08391426452130df1d6bf0dcb1a3073375beee800fd0d3d1ac224f6638c92c6f9bbee8cae0938785f061005e1c0236d5c23493bb2206d4899832f3f76aabc9eccef78946ff996c119d5e0e9adacb31f9122b1ae51efed5d3f54fb58d8dbf9345dc59a770b6b8d36e3a480f306bc023971891dc98812b38298898e0b8ff0228e6eca726b7c4cb26f0861038c2a54d93990d76eee5d4485abec80f6149b4d26901296441c58ff5ed5d41d88797747dbc5ad1f560f34b0d22c3fb6ad113eb3b2e628f9caa4a2cd4d99183ad9e2229b1ec46e4b4afd64c3454b1f14f1aa43e7f1de8c30ce0fb9bc54da5d228caa04901eba744d6beac2f69222f0e3d8230af3c03fbff8e7a4fb2a901c70e0779d4264a23f9757d921518fa2370fef2b193defe1fc45bb250f74def0e7e0887c40940b7e27789dc7ac918808a5c29f53b99dc70c412546c828d19f3b38bc9636ca2fd8c7314692e7d1cd7b85efad8e5fa63ab1fd39f98561440c493f4edb66ad4f5df5fef9d7343a4117e125a77271b8303bd29f85140411a5754af0789a00dac22770a2efd3c817903f442d279b7069093e3e56c23918a54c3323f6e56b6805e0f72abfb0acea2d8bb04b9ec5df801f6ba0a8e02a299175713d70866412bde3bc23831c075a1d5791047ee5848d730fa8564cd9b81ecd7edaf30a5961a28b194eb8128ad6042d20d7c715c9640586318efaf54c0c524f050a8c08815ea4346ff1dc1e4abc3c9fec5d5d7107218ad8bc8715d32942207379641800da02f67d8465d4a8a21365f298ea47aad6d4d4a50aeb2e53d654036db70d2b6d7c361a0bf91aa69e5e310d11934a636ac624d5802a5b4a71ba4c6914d5de392dccae95c4c3acdfcfbe29ac67941740e5043eed93c1022a298719c8c6b3b76fd1d6f6790e8363653c7b9c46cc9a3ef43f6face3d9e35ac5377e65ceb968ae092f2aeb71b0e6cc567267cf7ea50c8eb0254005028e39ea8cb93ba56b2cb7b2fe90583eff135add13277591554e057f0719cfde2336b7285ad74a8f4dc6a043f74f35289ef292dca11b5d121bbaafce1e7ac79317187d18a14213f5ce74d35412a5f6bc001c24d3c623f7e3ac55eba6800d1d4b2ce350fa8b05d0bb1aba9dbf247da0ff5b054c63725dba36e89cde69c04a6e8b38cf7c59f1070791355d13b226791131b562efbd2671d62e2c26d00187711344c258206ba08361d393e5e76720e37d83601bd987814dcfefa7ef82ecd60bff5e0b269187ec32895a92a68ec83bf4c2bcd1427355e8b0e9f99b480b681b3a65d5f4786d3e7a27d71c0285418083d93bdd38a9aca26eecbeb2770ff5d0e4b247e27753879beb333f398e1d220be022c23584639b9a8ef3c11a048e6fa1e64d9d402c37b190e1b491ccceb871a5fe63c0418fed2fe534649d7adb3923c726cc13d012bfa1b17a767190de85f0a5756b8b937a69b7b1ae7605fd83e4e3bd58373e8b2f2650e68b25acd2d20a4c4d205db4b488fca3f6f4db8d3fc753a6f22ebc2f2606e4dada4bec5b6d075acb82eced62eebea63146a82cc7b9571cfdb7b36afa76a57c9cbf6802335964cf05badf0ee848cd6427731ce6d836f58f98478a5dcd018e01ba4f890cc8f36a72e276ea8a8d52d6e92e7401592f3c6f8398325cffc5b55ce6859ea3cfc238773b6863648d9d5caa472c0cb03c7f1894afc60e9030f2a543949968a6dcf7c2b637e153892a95b9ff35e854c4b8bdab22f04b17c21b7280c1173d1a6b00279b18a42c0ea1b0df3e731071d2b1fb7fe513b89d446965f49e6b3b3dc2cbb5a131fed3ed544898072e9c518e213d0013a97a8a36a39a395dc34c17f945abceddca81c997c8d035556608025f85b380018fb1818e1ee8c955f4d030de7c437b015061d614106923372c2350fc45185e0360edf1b3e3d4cb20f4b78452afbc9a75259c72fd7b2f8eaaf4aac747108bdbde5f0cc1911dcd933aab01ab6dc90fc701104457e2d0427a2c0ba4b41080c881816b0f650be83c38ece090c33f185e28ad9e575fdb8158b703f6596d6c1d412c2521c27d461024f022fbc6c367aee23bf7e6e3299fb8dbc9f2090bd906c15bb611a33ffa380f144ba049d0632438ffa61e4661243f2587ca89cb9c8683a2c4c667d1e062b129348fc919a060fa92ae7a73a84daea6a3cc8c914129af7fe7ebecf62a720ecbb322af273f49ef6d3f489c5a760becaa5de0b7ca628472a3f08d7e7857e489d53c5dccadc0bb4cc25f1477ac95d1e4ee2ad81a6f0093932837128665122c4479113d1ace253fc26f4f32f9f7cb7dfd2defa6d24dc0b21f9448b24d1ec312b826b2458003984f65055f6a2e660f4dd210c43f595bb4d9a7a1612bb358fa36a1806b323afd043c11d4348b2d9765e5d122fdf43c046aaffa14c138052cd054bda31d6e00367f052ef770f4f8c3704e6a7aa3c71217d8a6d29476ab14073f987813a8e155344bcaec24a76096e7838adba08989e81f8ac144b36cf381ea4519feeb71c50f45b30ee49ae47061cea9ae6d4e84b2684d52850388895c968880bc3fd02028a3fa1c9b1d2d2959df0affd21c2494d532d20911b0ce1f8ca481c05d14240842c7d2d5e2ffcc8ec00479aca48a955ec1ec48a28fb8c3658e2a9805bc85d3fc36d3a30160ad16f7a6952077452f7897b1e823e2a4fe905e794e8bc20ff0920b1dab3aaf39864e35eba6ec877c6f87a0a93be5f7fefc602aa4eee477364abe8ac3093c16682cc4b427569319dbf4f7d7b3b9b10cb7af938f5cd31b23f420b1aa137c47a332da64b32ee34715af15a71a7c9d2deeab4ef505838168662bed2d3f85acc3e99dd026500654c5e0a5f1b5767cd01ac4e08707cba019dbf5a82719a0182be9279c3fb0505b8195058b8a985de424ba6f5dcb9f3095483a9317ab75b646a547b035db379d756a61843468acbc89e15a28d4089d25107eff783cd34f7916a3b209bac6cfa87b385a7e40d32a035afc50183da0b9b3a6041610b0c718dc247acedc538cb14dd3fdb1990782307b688ac03463064bdf485c51b6cbe4f7063622aef9fa426b30338963229ebcb553508d2e03335fcf5153a3a84f7b6f02481246dac178e67a3cb55f922aa00a524dd4cd8eb9fd7a8d179a3c9a1a02df49b801e5aa1910a1a046c6d34bece620286f0c930e1385019aaa06db33f567296a372c4491181637d9ab5f72b42635f6a67eb4219011585db534753575f0f07958e59d8f96100b5f755b4cae5de1aaccbb5d5167f56bbf304645d1e8b8e68d2cd33d9084170325d9cbdae328acf930628d8a5a88fa4f9922b9f9d61d8a9a8cc923305bd10a78053254bb04f2ed70f49faf80848eb339c57ffc7d0856484c97b6e4d52e315d37b7c3707d73002549725078a91986dcc3cb0e720959926c0fc46cd2a06019378329692dfad654b2e8ecf8cc99bd8c714b9b348b844d45df2dba8bd40aeefd0e3bb45f3385f4ac87598e8d5e26799f304928bb122ee590f55be95203a551db5cc369b3c76a1ae0d62db359448d61901e5a4f2cd2c0aab435dfc2481a696b68934b988ef6d1cbb26c7e86fc6bdac1c687c878ef89b9fb2b6717693005d46b46d4c08653d7bad36679ebc44638ab22c84bfe61779d2c91390608ba9fd1256319cf5d84dd1e3674e84309189d75dab0a5070c3d3063729c93dc10f22090d9bb19b26e90a519f5dafcc42a72059d68a189d0e9a59a1833e17773eb06e7c0a6d89f2962a936597d87ca70cf08da1cb93f42e4d0f494dacaea188154a7add3427a1bf244d9e6c1970e1c8d588683021a900b0e1aa2e02c1ad5b164ef62156ed18a7ab554be604df75c6a937e1ec91d8578caa46d9b32ce44c68ddadaaa70a4aadc77593e6b6f0320ee5852f3d9c20392b2227139b8c080a05069151d0c564a5815cec57835e62668537f7301c8a378e460b2d6df5eac02a86ac4d1abfb41043e8ee5d0b895882f1b1c19e7b6dd67bf0117e209de7ad608b93e0e5dcea040baef86571763d8bed095a4d3352e6975bb0b1715e03209232de8c03d60bd0c2ef7fd07730147e6646d6428817b6165dcda840685ceb141227f8834c65b5415288147e7c1b9470b9c415cb269a24aefab5b0860d45f851c3e386b4c068ef751ab423268aca06a99233d3d66a0aa5651c9b146e8550a2a602ac68048388a419ef71c591ec4e900cb24aa0dd023750ab0a2aa4a107097ba046e81ac84ba585dd83888d00cb9fdd86cda2afb147a13a5859272a0696b0e0570fa970bc459c4f04c399bae709022bb4e0224686dba66f2df9b882289883060a9b08cb7a24046a7a05872f50aabdffe2e095a31d39049ab4dd51d78f44d9ef0d15e418a20770485512e00a685dd9e224c73f9b2b0211309071d1c49cff2db60277f2991a1845cfb9278492f55ee0a2625526b4f08f0b47c78b1d40b4bc1ed9165218f7a9c6344b66e3454bb7a699d76b9bd7775c1505e7fa1c2a6d55a0aec89bcb4a22a448040cb5b0bc1ea1d96b731a07de8955123039b372f94564b5e1a24f4454aaef8df892ecfa3069c6042569e1e741afc1c7a544bedeed16ba89098fd6bd74d9c078cae7a465700fe5280aac08801d9e8cbcec18c1181d6e71629768165bdb7db78f64ef422638be1ec8b61f0c851386b264eb523529e80782987cd0d5bb8ad0e6733b3fd5139adf5a5438d1745a14a77386f9815b9405c45196c5cdc46edfd066a5806589aa3ef6a664ce96d0c885cf8013c89ffdc6d52e8e6cf3a56f3c4157787a31c5ddc3f147e2801b0ede394947cb30dc09d6665a7d4fdf4a5d94119db7e6740d4d2018455bdaf8a8d68c5b68dd10c4d9703a8c031b213146b53f1b45227f591fad289e6be77e27faa2c9f1010b5058e212887f8c09e59f11956e989692118b14ceca65ad8d7910acc97c13403c1278a7fee263ca160277e094ff034e4b4897c741016cb8ffd40a7d5fe1f3f5b5654012bf34e55a9df23602d3471ba947dc66e767645052bb4fd85508985f85e7e00e3c33faa04666c10611cf1a6a4ee245b414b44ddb8fb08c998772f9d0deeb53c381bd2b0b05bfb9e5b48531037299360e79e5060f6602545729efa7412e7c13be9f56cbdfb84571104bfc6b4f9775d4c0482ba8900ace47095cb823cb235161ac0e694a310ce136b543d012608a3fe21e04cb59c96e4c0d7472e20ea8afcb0a21e608ce50d128c04b8f1169b4a4469c6451a8b3c48577de5c8ea6f000c74fbe27b3d4a0af2878b3d16fc9c6f232d8628fa9efb31e12c86b202aa31c906161e9b6403d79840457b82d06d10214c61a6353b3b7031c6b3ce589ce4d5a238eb7738c9a1fff22f3a478e7adc86d9f224b819cb6449683c378b92d7e8dc5d861a01a4814a137559f3b93a347e9e62ace31296d9b4edbb810523ecc474f460621cfa288f7a5a632a3f3c6b2e695c938740dcdb281df628cf98414441471310b4ee2cb2f6d8fb7e7e412b99b3349785be2cb131b179e56fd0a85476dc9209ef39a8b3fa3522c53dd4c11d5b309b60db5d964200afb10120959529909536c6130113572a0944079e4fda2275bfa9a4913966606170fdf5604866505690c0a53c75b69060704afcbc3b3adf03d89e581a87b59adbd7e6411446791e22464ee825800d2eaccdfa3581521589b69c411426c9e95c613d25396e66049382fa08502de3041e2acd783f7dd4e0202d4fb777a47e0d12678c31b70eb917c82fe6768b0e1f705e75bbd54d32adf866dda6e1ccf59b726807ef3d0392add1343995ff20bb263c0f96d4ab98d40f3a6f5ec2662b64750b57346520f430cd8c383c641bce27399c7fe89d28622b3f5697c3640fe37696c70ff1fd113faefd63505b91dd26d8ab7f10d2cc6200e8be34e3dad62a56a71cab600c3cab21c630f2ad7c25f7dccb98e08494b3bbacf1c594fa7f5022307d191112094f94c4ce9d1ff51c704c0c16ca8a843eee22778aedc0c9fb8ca5f990c9482f6ca2f2ff508b895255cf5413f35277819b2a13e94bcaed5ad726c804007ff6d884ec6020bd7f612090ec35a3598bcd6a8b7a387b3222c9bb3fa18ff4535b64bc995777b1841c174ad2d79f6cc661f66df5f76ff5e8abed1eaa7f3d14422a6e8e5ac18e009795c64e16c2e36b61325f5c6c602925967b57965d42230a94a3ace3432641ffe1dda26754d88891712f2012eb8fe65c54b6b8824e4dff494803b2da0b3b0496bb580eaa06584aee8fd01a8017af16f08e281bd5c0489832460dfd8b6e067b56c1b12c2e3152abe1eb8aeead3ed5b0991cdaf57494ec02dd534fbf6752f4ec6b63a4be7d7e18ea320966f10e870d15f40e711052d10bc9cdc912e8c0bdd8d7fb59bdb65164c1b349998ebf4940f8e877454d2f690882015f365858161fa464170438b8b1b8cca30adb5132af722d13f7bac8b5848ea2351b4f35b7a1a673f0bd051429b6376e53ec509a981f3b56e5934f8106677ca6bbf35832afce45fa389dc83bf9966807134991812f7e35756fb32b2240389ca76b6fa34ff2ea96d9882ec288624b2ae47651c0816661afcca5c0e3d5788c20761873b56f66862849514789094f9e8d0bf971055302fa6acc87f8ee58337609a08bb728c69951b9fc94b6bf22c03544ede4f9392c6b603295cc738df600a8997f6e8eee02d86ccd6bdc91bda9c71aa3bc6c6ec19c3e6ca63363020c9ae7e66a18b3b3169926ae2f5e87c7e48267512164a6f45e8785a54561b87f588892235a22d0edb31641f4ad72a5ab1cb172d4be5557805b9cd2b1d98aed4ffa2b12d3b60bbb709464e46a8361beed1b9e3aba1f00610772e86a9442d34825b919cb04bba07c14bbeb3c2fa80788beb56af0e41a6c133a222d4652a78e009120308e3e79d538aea64603d72bc0562c1d2287493112c98f297a5669b180bab05506632b49090843ca1cf133ab2c4a698418ae0ad207e853ca08dceaa3d355bddaa9fce19d73e99456f4d41c20364f576b728c924d3ef623cc25049a365b9c57405ad9341dd9902b9821f68db70ac48a57c1bae1b67837943be26c4ed4259f4b1ce13de8d1ade4f526605580f165bf01cc05f9b3ea3a338b817eab1dde490c38017f9d8f7b086721f8b325d6da7623bbad97b4bdb7dc3bee09b409ab091042f9c426cf7b2af5a9116d90dc49241049f5d9e0126803ab80519a9332a58174100b5ae97d0fb52dc4b375109737ecab6b2045b81d14023a681ba259aa2483a8b7850857328288e6e410cdc92946842cb91d6c20100143a06822ed12ffb9112d0f833c20aacbc30f4027200268bf2852f7b4f0649ddf63970fa25d2ecbbe802eaf434ef2f5b3d5f0e10a4ff6814936a864834b9ab3d960940de64029cdc1833638a55980207931a6783172007f805564182443888006f21289348b7cb959103d841652a23c2c8cd424c99246179564f9870409ac8970a6d39713541c810214d926570b63e5bd9065599665d9c76cad045025bc275421cb033c1629e3c590202edc78e947dc64215eb62e2325cbfb784cae489265c8bafcafd3cbbfb09f166dce6278a43958b1b468733399e268d1e62e6b615864daa475f90c7ee6d2e6ac5b58c70f6ef76e84401144bf8464c0cc8889f2100a2245bac6225bd2b21e6a17ebf02fbab18864800880d9fab55eb66e5db6cb75ebd66dbb50b71ead1a16140269a8bdfca85feee575b4cb745dfe0824ba27e5886b3362d3d19cc4a36681981426514892794ca73446393db5bd7b37d6d63d5bf495f56acde469e3404dae9bcccc158e6488948ef8227bca9e72decc6453c31bb14d3cc883103c48df2fb4c9f4c11174f700a34028dffb8205f7ddcd422e7d1afbb71f7a0172c3e6c190fb983c4148ee4253dee55fcbe82104f7317192051327449838c171d2c492f957cd0d6e15772a906327c7393730a76d561b7c2c92140f4554aed34efbfa08d85a51d516a4fa8d2cfd224b9c3e63884a0b8701327d7df2f57b2f5a178597e8894e4992a248e6f84a6dad01af04bdcc8b214935e469541466daf308b6f674b8292192997adc062685a7ed652530406529a29987c5b8eb88eeb411b0f08b2c8f40bd0f4f78bc2cf20c8d191a4d49dcc1e9750b526fb720f63edcdc24de942c13f323c0cdd36103e2271ca5c461803cbd52b3c6c4726adadd9475511c3f2c51cc3c5e06da6a80642d1b17a67ae2829130d0180143fff0a1a388aae63696d152d55473a8e6904525050eaa1a265aa0a9a40085e165a0aa4ebdea175bd9fa6a7b40404b882cc8b5cd65b4c89d1475fadb2e95b470583836f0287c3195707a9c360d87c46f1fd4965b07e1cb36310f880464f91b0f8829cbbff7625e0cf91db270bb2be3016135e03537e3efe10680365cc9c2fe3a173bc45066662d7e06b669b18361f2b56e611e5a1230637f994a729fe56fc813f15e282714610c567843146aa8020d791defa55283142928c21646c00431d09093a49b75c19d812d2c6ef76c626ea46fd4927117cadd6302055a328ff7e4cc05251e5427a4413601a929a4c34d898ba4ed3d8e873c7c8f0503595a22dac12c5f9ec994a5968e09d2cb4d2240273f252a530bc7274baf15551d566d0088a9f708d0547757f39ab0b52c1bf250923ec554437df1650af9772b0242a6480226f3e0f20c0dead2124dc7dd3cb505a1eec41449c0649998fbef11408231b169c8ad6342e6381501290c1f0b85012af7a7982e37254452341b76f79b57c44b749ea8cbad88064283c2419cb834de2380012211d5a94d48d30842ef04a55161f808302fa798629251eaa8c514919b1bc8528af3f0fdd0973acad7295bce2871d7c03c937bb2d326e2fa71e6f8495e92264aaae67bda60c621ea37a01f3f593666b2b453d71db411b950eb9442391d0892e791e89767d3a3250dc8ed9ee784d99ecbfcaf135c98d8030964c890a2bead1cf559396247bad6a376e92e754b47e2858b09e20a79fe46bf541af344cc17d12f9f37c289c5a4892579be4743e9f70923793eda99295b59355e579385437ac248a62e6d6feba4a65883e734f8953c6d1ac436207e73f340ee61e663e66fcc1331df01c27d4c9260932bfb1ed32e1da456c01ab232c1f521bf285ce126bfcf4993dc08bae2c27714fa805e5ed28dc7c643facb95ec68b65c5bebb39bb893f976a3f09247125296974f026639d12ce55b66684d735a8104225a711790db9ad0deacb9ee5a6c7247e10a4fec63417d937628f4de7b0f46bb3c634923b6799267c03082942c7da5be3ff97e07a1f44b970ed32e533c029490a1b9a9947809893b29039580d75e6e213a35b79359024209ea356b97ce1e5ee241bd2f3191fbd2a57d403c20ac4b7fd12ed6f65e0c0873ffe66a03c095fbd7959fab6d013de47e0f3de4da365b445b370824571b3442a6364da480dc578002727d9acc9d618e69696ac10826682300894560032c4218e0157236a724494558520427affbd17120c748032260b184294a8ad084144b860865a447ee2684dbc9dc1b8c3042d8c41082f43b946384b9391a218463ef2604495fff3dbec6f8ac1761e40733b4dade5478b85524b81d049cdc5fe909c428aa02c2b6a22a79120227cc404807ba8bce755dd841d83d0fc36e5d97b5163be8baae972fcbd3f9eb609887a22a557f3d47cd81619607db40d5f5908ac5302c0bd1db974396e502040259d7a5d9b84e5d745122dc8d3206026d9e635b86bb0f1e6555b3515f3d47bd1e0b6836ecb1dfd76b36ecaf8b2c1675f02fd66c60bf2ec2b0480466988107da288a501508a8c38dc27254186459fbf97c3e9d570f752d761bf790c73d9499f95a3b32ccb7adbb759fdf6b4f5194ccbc1c0c983a537daee2c213936b08a62557f71d772db080537a6ff5b9a80f45c9cc4c3d57a728bdb756af17773bf295997742fb2526a58faa5e7108261c30ec2862cf2003273a97a2acb59f773e07599fcf2f6b3d1ecfe71d6b2de89fed657b519ffb778ba20eff4659a6a8b6aa8bb50f66c04cbedeab0eee32eaa1175ce6e17464ead58b5c8db24a85f2746ca79375b25c75b25c7d28bdb776a36cb3cafa28abe0f56b94650b5320a3ec2bf6e18a4b73ad4d3c19a2516154650084ba820f7cae83b0ebfab52ccbb2ae7f5e5ddbcb55b597b52bd97646e4dad8d659b7f69a6544ae2b75c5b67030602cab49a69458aa9b2123538791a9d18ae7dd0aa57fb56a5dc97525539f95d073558d5859a9afb97befb4b2f2ea04a4815a30316205cf060555902b541e9042d58128c4a06a22478e1c20097a056154068445409e10030b860a48192a0ca82dae779f679e4f865db7ac5bfbb1b0bd959dbab2da58add72cce5155bff54d2279fa343289cc22b36666e4e2cfaa01c295910be0e4da8d260d758fc52e4e595705baae8cfa5834f6d5a9576feed2404eae561d4d9afb49932f86293069ea292c24575b8c329b0064410339309849a816cca10b463239c8ec1f0ccb785418e8ba282a3da70765f7475f06cc64d02b0cda9a02ddc24016742a93ab3748326026ffc8557bb04ccb1fd9a76f8f6c6961e5608108cafe01813e199669d93f4012c37ee4aa2d08a3324b00206320d91c55317ce1ee47f7f4e18a7baef1bbf1b205aedfb20086a95f98c2af03f2c5177e18b982881612eb51318bb5fcca482a242329d5c3732d4a5db37a489b964a469e0819d9ede82123e16b0edb969034888c9483861e44a010072dd4175070a00275c2ac85d12fb659a64f9f6e96795eeb9679b68b552c05e858ad71317c315eb4cbe72ddc3d86798e41ab8684d6b365b9ad1af745d81d13f9757feecbb5b5daee73fbb9b5d8e79e7732639f4bfbb9cf83fdfdf26cb0dbd8310c8391efb157cff63976b74e14975ec34e5d36a7619fd9fac53866b636983dbd830f565cecf59de75762723ab661bf9edfd77b3db56375307c31b0c774942d18c98f891692e496fc9868214322257b5fabc538ec76831bcc35baceab67a3cd4d9d7b3e75eec54219bb07d7ede55759ea62d82becf5beca07a7bc58fd6c30dfede5ee907df1a2f33c74ea79e7dd7dd61cf67a370198e1c20cbb9bc383795c1c6a0efbed5842c0ecf934905cffb90ccdf51ebe1fee41964866cfab0b0bba7761e188f97317966866cf07bf17e362da1c76cb836d73d894b1c28e307aded98361eaf72318d9f36ad57856e79ead9389d973cad16b4100d200bd7a3aaf1fdbd996e8ac44e799753d87ef07cf33ab886703b2999543c2c7790eb270c4dc39c82ae23da9fd60ec0e96223b6813721ad93d561159d734cbf4fab1b65f6e4c3786fb48b584dbd9ae8fc497ecd3b907c4262dcd8371cc8c1d93b5c3e589e262859dad636114c631b3ed26d2dc84434a2e97a7699ade476a1a490fa169289ea4b68efb18e9cf914fcd0749bb50a7cf6e001100395b3f4d9ffec2a5f3e93ceeedabcd90746e6f5996c7e3b9102f7bb0f6390fcfa97fb00f575ccd835f739ecfeb6732ddeed6316124df77366ceb6432f68f67eb68ee608fe9997c378893b16d64f3654fb7ee73245b49e92ba514ad284c27cca393bc48419502c879f672ebacf83e7d64f355e7e1f5308e392d6bc2ad26bf3f7c59d35acbc2da9c9fd656955555d6b2b6aab6d6796be7bc9d939a5b86e43dfba8db6dbe6e149da429a3912a7d5601e44cd91457267799cbfbb44d18c7ac262162bece640a5a3079f204085332f68a610f9ba8f5110cac3d8c03d311c4c9960f57dc69ea0f923ce1eef9c893c5acbd6a92fc5eaf77eb5356037f987e6d6dd578f863a442fb726437b8b697699eb60c4973d3dfd6cde437bdadfe5935ecaf9aeb7b2b533282ca16ae9c71c619e3945054952ddc78959b96d208f5b5ca4d85d87b72842fe46789300b54599f6d18a74d4ab823bfd3ad2f6d33f9e1192dd83a0e34c90d8b50e3a5ac626ad57950ef53fdea6dd1479e5e6dd4b3a63793278904f843cbdce40c85700cb1a539d9386218cdc9485f0cf99a49713b193e581175c81fe0bdc0c7123f2f7f1d74e874323a2a7732726dbc22ea4c1f1011bf18f1044568aaed8604696ee28be4767742b1e96a903c1f336d35657632b294a03416b9e244ab46853271e684d26579c25c714c733388cf67fdf21ecb7d326066b48bbddec1c893f228923b99a696655d8897add600169fa8ca6e3319b6925c6d323353d32b8d04e40951e33d2cb508821587950c5b49b50f7ae03e265008929f259ab6d8628b2db07c7f5ba8b9b8bd6c23b4e270bbcb72f4c0615031276efcad180824f681eba94d58717819c53cf023554673120627bbbbbba190208d73abdb773042bc181944114fb27c50f2266bddaaf44a4e8aa3a5a9956b9121bb0e694e4a1898ee4dc952729185060a4afaf8d11d65d42cb2b23d6a97978da82fd7e56166c404f1ac08a2b96dc606d3dc854393eb8d4775a9c60ea6da3a99deba777de93492214e920423a584795cc3ee9652ca3ed5d607ea7befbd071f33ec51a3804a386287113a7ee04a09577a6d0b4272fb758992aaaaaaaa7a09328534a50f30ff6c481b9482618e196e5b157651e456874b2a5cc585363673ce2851d22ed592ead2ab2455af66b44b77f76b5b4ae621b4099d7b0b07735a3294b285fb9a7034fd2abd5c752f8bdc63aaa8aaa2bae9342151f5ab46a2b989614e0e9279d844c96453859027f4553792ee46d2ddb2fbd2aad14da48b74901c299316560f815a4cd9a0940de60009d9aa92b6e9b46a58d3344d39d2566d7d5a6d579fea992c51974573e20ba53917679924d51b440c312994687c816978439ea7683791e729ed10e4f9894a18e6e474928c497d2b5ddbd4800fe9703bb066a55fb86699a75cc755f1c409dca018d25c90e6e6933ced11abc664d5888745a213274f9c10815042082184f0a6b9f99a50e8de1a58135f60151ecbbc169280214f33d8642bea0e3238725f7e4cae9032051279bf89ccd08ec8323f05678ae4606785c0217352d5654561da130422493b42a189352d09f8621099336693152cc95d48aae26e99b6cdc703f5cddcc7e40a23598ae9cf156b1df27b2772d17291522c85f4b9490b02a7316121a72161d92cb15ac2ed4250b8031e10dd43438e2fb2e6043087dbef6c8e1d41305f258e88219a9ba3239a9b46343775343725499224294f3e9a9b72c8137e204ff8449e3005795ee0b14c99176342225049bb4c2292347d4e47e621122aa6135c8005d4d12ef33ba8579f766404bd442f3c2749e9c0b0081d828876913e5fc48c93444473f3379a9b9048132956e419e4878543acb88122494df294240936e9db92049b3c59026ddaa58afb7948a45de6619123b0065201af794a477cb918069b3ce8abaabab596a2a80bf132857db8e24222f4d22beb973493e965d9aa8244e20b47efbc41e30b77dfc4cdcb80ce5313ee20cfd3396148e4c598ef5c1de136119caa2d38d428aeebbaae2b5eb3716949c02cf362c05f205e177840c00cdf3108f919cd552a9060d2089cae0d0e11125f2014cd222f2908850f57dceb52dc53180e11e2c25208398d7b4863dd885b7686dbbd265447a42fc20824fadaeca09158835d56d2baaeb662ac300c4323cdb5910b1669ae61fa8a970fa2ad088b4071a3891646e41158039128191263d75142fd23bec0dcfeb8eeb9fc8da630abb3154104b60d416d3760e28b071f515f1371e341bdaa2e096732b5753299aaac156732b571a0265b1cc9007fa81e136be8468c4dacc8f059733014b7c966899fde02e3dd28e2b1c05fe0c580b7b18d29a1d6993783054e730f3f00488eaf320f08ebef1780b10f7bf285a25c2c6ed4c422de0b8d2c770b3285f46abed249ad6acea62f5e8c9ef315c2aeaf618cf2d24459c2dd10cdc55b6849b7361e5e8c3eac8994deee8642ff6b0271d70203133f8300815ac02952a234171b0b9ce64064b82033dc50735927999b360fb5895b88976735b9bc7c045ea3fe985c51456e9c9945941c2912f6287d92302c59144fda38d2ec28d402480789529a0dc58ae6226e213fb83839c69c48ef82b9584e9eb48bf43897ccd94be69469a75563f6927679f6f1bd741e3b7aac8fe4786b6b289aa687349c125f3a3874719416c8b4d6d6b02abd102f534cff797b49d8651f132ddbdd42700bc971ca54c12cda853a3ccce91709a3c40b892f42ba10a51e95ac1aef41c96f887eb9d12c32336e881e4b3ce5b8dc851c2f457ce3c538c2ed1bf158e08311888b689365bfef1c7bc41a75eba22aa65116754bab147e58ab58d4d25ca4b4721cb55ab225aaf2ed4a44087a680911e97befd66825e7c0deb1b78cc8d6c33ad8de7a8faa2cdc51a3154bef4aeed4d7f26aae9b5192e3afd3dbad5bc9d6de7a4c537a6f448e8fb873bbd5dff82241d30829541ed3940af69caa8e61b88b2bd9b375118fb046e14f2a4dafa7fea8f7d1752bfe468c15868c192b547de731c61831edba569d3abdf5bb6995766957b44e1faf18a3851f5e59193d294f0b18046bd5afd3f7c3a1280c1933f20dbb62b148b3ae55f655b34e9de6b8a2e47e2874af1555fc6e34f73e6a925f14784f77ae8cbcb7878c9491b2a23d728f2c2349803d4b8837829db5a4ce66998956979ab574ea8a1930932b4a4fe125e07c972da039d2dc69b1ff1eb1489ab42a4431f5ca55582449f919a55bb188a2f5946de9172c9258bafccb3ee85ff6412d16d5eef80946c22e3b87c9a1dc87f1fa24c5851df9e9306fc9dac3227bebf44e4b5e93fe2cc59aa4c9699afe5a60a64f9854e13ec5af5934fa626c1ac5a21723946fbc3994dfa748464c999033b5a51bea55e30b00204b9757927452b1ca3a3ed4707a6f33f9e10b0020530a3360264bf2efcd4706cc642a5f4c0c98c9135f6e8f0437e2ee5612dcbe74410e5bc91c2fdf3176d42a494a5216df3bbeb724a58b86036b22fac65a8efc23db4389a7e912d37044d1240f5ff5d9bdb874fb2e9445d6af679a6c096bd53539251655fcb40a8b28f997a392422fe4ada8c277ba68d2e7edabf7c4a27aabb5f95b9b265d9b9fbe69138b28fc6ca63d6341290a5b861cd56feeb4f8dec9c89c437a4c8f1e4444eaf03bb4fa977be4e93da6e4648173f3dc22236388e8d1dc8bf8325246de9cda722e534a6994e28b4fe2e625b496fcc9bdb7e4167945b5edf2e24fbd1b8fbaf6e0bbd69ffd9e84939079091eb205661eb74e8bb799662de21b2f67db1c14439def1dd2d8f1369457662a18a5580aa790518b15655842560f5c19e9e578615e5e442f69a22ba29a0df97891c451c24f042210014cc20f43108210409c6948a4548810215240000210c0c8cc0e5427aa13d5092d204dfd40fd40fd409020413c506bcd91ca307f6962895f073ad081d717df11fb70c57d6da236519b18f2e4890aa402a9405ec8c80e6051acb6a8b6a8b608404e66439345713b0bffe011239d2c9289e16661b81dcddcca4cc356417d1917ee5b01a2d6d72e1d86d000b58720affffaf58b5818828522516ac8033d80a0870fa86c11e3f3410d3551059cf7625c410d75c0033d3811e1806573354dae48923b4be5fbd403e2c14e7c4d851a02e2d1225f21ca15a0c028de7b5683dbc92c591a5f35d4b75221f4c214382508218490a2688fe9f085fa7b410199cc702d103a49b40437bb17bec8413608640727c01c69844adbe5bd3d0cdb046f69a7edad73cf2c3f67cc55b23dc5abf195201c43fc5fc8680ef6344d536685ea348adbd9dc53a4dec5383d466a9a26ea7465661813d644148f6c9e98cee419f82a60ae583fc3e732e78c35a68603e618d311c216c889ed13c092dbdddc1d637e9bb4d9acbb463b6dd266d7c4a1268c32fcdb2a2fdc37ca329c7394a5a1be152a4122509976b11a090a83129b91647332b1a964454ab22c6abd8ed08a580291922c4b8294be461b77b845b8158976b1ef8f7ac8f8e81e32edd2f731b254dafac2aaaaaab076cfa3fafc7db73e93e5d6d10edeedd163dbe3429e36095418d396b407c19469597ba7a99aaae935b1db6d2e7b2cf02f9ec0a06af55a5555567329cac1bfdebaa794397a805c7065656535175295546d74d2c494fc9c007192bb9785132050a6cb6c5974ba2c9de49451ba349124711731c8487d2f46373dbe4689b29b3192a76bd479d0a6684c8c9fb6c7852c6d12803f4489757e568452a39032a44568c664a7edf394bb2d2198dbc826324f58036be24b03a157a3f73531840341b8a32d18ee5e933f9b10cc9d708e148182a6a59050c41e332685584c71e20bcc1ed3bd04dbdaa6b99507e019ee28bec5db0a0ec00e280ec2c5318849221531492be9256d23a10c85eeb5c16399df411641c8914798226b8cc4000707e208c1c189382fca21d3268550af71eb220dcd44242bd22e9891782442d12ea01841d38465194d9ca6ced9547037935582b053dc269a890677a35075b1c56ce17633f28ce6e6e72f1e4efdbd1711773ce0d71cc4a2b909717af80b0d87f07b893891651ee24c18c4624fdcee3511c01cee0e375ebca3a177a18e8b38f145d64496794a75c01127946f9a659ebec01dbd1aee6e0877218ecbd8dfc33e6dad4456b1a4392a62926845a4c1d1497392c2d149b422cee0e6064a8d4ee2937699a6699aa6884573f3353594de1b6b22ce0c68c0c33b5923a4499eefe1d3650d92245428914baa904dda4587cf4b21f125d24496f9d03baa5dc88b77a1f9e93d6c46386997ae6f62131d362dfe651d5e79d8ba9824cfc72494921e3e1f97449b2a78f87ca4a25dfec9c3250f8f14007a78f71093f0b0bd5c24d2502f228d86230d455158d6bc185dd3e4f9ea087707dc3d2bfaa6a1e044f150542bd161a34dc88024d769ed26bdad98851ed359f6690a6d1d13352650921ce3419b8da7a88daa813fd048dd00fe309dfab481a68d421241a04c65b7db746a03a96cd6259941d967f36c377976b2460998f30569f2c46f2eae6498e93683da909cb29c79d106884175e9ab7634571d4677572ca3391f32cd55a3e62a2462074a69972a469b7e7955c0814da013f804de4028100b98058c0273e014fa6abf1b31c8083b5668d36d8591ea32609ec8d567f40b8846f520a8c8d56ff44b1568543721c8d58b6817992b26564092ab1bd12e30573fa25f208daab64d1b21575ac895ecea5552b955b6703b6853411b6a6fbb407b6ad3a843a8a4b98a8ae62a152c5c29849cc67529aec7c36abadda653706e304973d5af0d226996eaf112d63457d9c0c8557524da05dad8ad7b59e4ea30e01129b993b993b98391abbfea4b6e57d56dbf5cafbef2aafa8b76a1affe76b9ac5a6f5fad55adfa98b635569847db5826a8424d8655c88f09159e64271047ca22a494724e0989e6fa88e69a34d756c827320992254a2211288e1801f2a3b9966f99d7035a38321ddc877dd46b9b837f9d062596734228519c446bd528a2b9eeb6240aa100cc706596793a4422775a2857325d610de21d91a50f73f7986e8877c417db5052d7e0e5a44109b38663fa68ce478dcc0677fac8de68969e20c63147cdf58f68ae77dcf4e53c8661d92cf22d6d48249a6b8977b8e17616e739b9d2cb30a88d6a0fc7ccb2014334f7aee198595e5a983b4d58f2e211357a34074772881b3a8a88325a6266f48b10b76203e63e8487568d995beb47dc698d71ccec634a96195e4e8132bdd276a1af0240c3bd0de99d4c674c71a761d0aa4131ec2bfd2269743af79d0ba36504cdbd4c9bbbae2bb4c19c5d25bb8a91acf24f9229a02027e3fca6800227b95a0b42723f8736f7859c8e49c76cdc5d88afabe0eeb97b37d75dbc9b5ca134e7064aade1bdd49b4bc5214f17ef6ca1d79896d12e19ee60a522a9582af32ab89399397be835b4b5d4e07630328cc7340cc5358be63c5b8d72d92cac1a31ad92af3f4ba4922bcef52ed857e76207f7933398e5d6552c2eeca2c855c98f09166cf2e733dae503933f6fc99f73f9f3fcf9eb50fed07ea172e2e7f3c9892f15a7592635c58373ea55a81c17b86b91eab5552852899226f2c98d84d22e8f091690e47918fd72671696d4cc4a02e477164a3dda9bbced171f5c7cbe5b6179f7220fc0074c3d1900f58405534f42b9a39e78acec2a4f3a78933f37239893afab8470f2e7c3044dfe3031e48a4eb2ca93807952d95e76b1c1214fe20ba46996f9cf27acc9c2084e9e446ef264228be654aaca16b1686ed60ac5850b95cf1ef2f9f490cfe783bb984573f39395e3836314151c737c48c2e5d13230b70f49b83c3e978159e5da351edebd38e855dba8835e68206dd340a07359fb0b90c683f60702813eaff1704dd381071efee23a58ab060f2f70a7695852a1b2452811a74107e9f0cf2b68a3fe199244fb8036ed737aea732e83ae43a77d300e2e83b0b625017332e86dd59054b4cb077733f9f37990760d7415dccd64ed3a5c6593429ad3f06b4e07dc69a024f9d3b1877ca6ece2a157c97ea6c73416e4ca0ccb2554b556033e57b9658954fef95c45e52a2a1f15255cedf397af773da4de3c203e9faf9f0de6f75ea89cc7324fb120574947e5580d5079f66b89a600054dceae7268e5507986351c5cce9e619924db968039c3928ae6e6e783a3141d2c1b71071756dce076f0098f1daab89d1492e7fcecb0c1272eb611ccc9d3435bc7044d9630fc6cf50a2f868bad42b979319270bb1e72f3b904bdc8b28bce66177771d92f8f464c4729fd729ba53f0feaec311d733ae93da45d429f6f9a884594ea62fae731711a71d9c5677b1c113e8c3481394de401d1f9f398f8d9a4bbd89298f2e7d396848ffc913e78c46595c3acb2dd5c5bc5f6067ab6c1acf28e6617372eeee226b2ccbb7885dd11c2cf65fee08e0339a4b2c17cdf4934526668b9b8e97cbeaae08e4eb8e32edcfd536fa61cc2528910eef4cfa99c7651f9acaac8f6f59dac82eb8d8b1d6a7027cc23fbf40feeb27f0edab2cd06ccefc5f8bc429b6d8f7e363944899221795af5a6ab377956544e9eefa4102e27814f9e9564a5191045c58291892305ad2105130f87c614121c83942b5aaca0e14d79539a48134903a52d535aa689918186260d500814d2d2f26ede0d0c4c922431c23917d07946490200a59366caa44103a5305360ac45c39c52e6f8b705c7490973604e1ab20c0d5392e8a8b2a96c684c31c5204d138453facb31369c20f4c201eadb01bebb9a08deb201a92a318f7779596b37eafad3e9dd6c4c9c449d217db1e2aed6adebd7cbedbdc6eaefd776a3949bd4875b5fdaba914c7e234bab8a65c5239b47efd2aad1ef8d79bc4e3aa4e6a413866ddd844732f99d47cc128f627e39fa0ff3e83f7a7a28e56dddba2a4ff1a8fef264b3b5d57632574ec257dbcb93e2914cde7824f143927814736b128bfa2f94bbf7b66a74e5a43efa48c5aaaa286ad4d1533cec5fa61eb7cac5babdc8c2b6b2a238454fbeeec8b23a68a7ba77745fd988222c858bc774c5d7c5e731cb97f4bb75b2fc19651ed025aa026d3ca65196a589524a296633cd46e7f7a2ec9f5bb757b67d302c8a62a4e269a517551a2f7acd6936a8d38b445c73f13332e7b94e3d5615a535abb066e31ebbc8f3ceedebbb1b6bd6ab538fbd1e4fb176450b6b36eceb4516575a55d768b400cc15d66c548f1755388a9e6683be8bb8f719996b0c0a599683d22c1b8db25136cab27dd34b47a33ccab02c5b1f4f7651d4c743ef95e5ba5d6c94659745758cb238a2d1c256a4ee1d65189d41c558638d31de3a23735c8e5538c94d5bb87e79ddb12fa5740900ccc81c7d5c9e41b35f71b0f6fd682dd5346e9ec7d7f9bcfef3c13c9fd7bf6a23a5e48f8cc5cf0f792beea8cee986fd7d3e58b6ad2ca5a6090594a26022c1ede25b02c1b5d67632bd59afded4dfd6c91f99fe4597ea5665655a4e549da2a4ea4561afb6fb6ba3badaceb17a5b3b7793e98c611bcdf504b77b9fa061c6369969d5ec45ddfec5638fd785d14cdd9ec2392e2c698c58f4f8c6511f5fb1665fa3c522fb784d44dd3a253acd56c3611f6fa948adcdd4821407155a42503928164decf493a53490932bedc2228b2dbc61d1ac28dc751e476fe20ebed68af250967a355174daea3d95bd97b55db8eb4c9a4c2ff629d5cec78f3cc56b208bb8751ac8c971d2e4a8819c3c7dc25d7c57b7a28f8ae97bbeda46932687f4f91d329da8db5b138545989deaab4fefae53bf166bf35afd84699346dc69359eced3c718e3ab896994feaa0e4b5219c99416b1c8fe7abd75accd539b351fed56b136a938512c49ae8ce4f72907fd5461ac26bf2bc9ef95918c25c9ef1416d18a487e7f526545354135c1a91ca14a3defe8646665f5d63164614ae90d3ddb4d2b9929610b947daa6aeb76e4ea18a5a15055659f8b7a300c779d67cfd6752ec94c4affb0d8c5e4f8f9187750effa6771472f4c2dc65d2824fdd61d54a462751aff9e3409c1742d31d7e38d97efaf5b8fd26be86e9a542b751a5f55b17a3679f3e18a2b3377bc2c72a4ee4d09dd74ef49c78e1d6328d6e8edafa68fd76661ad5ed324ad26f1bcc40ed9023399525ba7517f38f9d9e4473d9c97cf844babea7d9aab38796ed1573eb6ce47ae178b3cd8c2f4591fb1938990661fd97aa00710204d6c41e363e1987a50cf6bb44eb7cfdf8bf1c11dea9eebd6e6c13477e2adb05f5563315f1714b77b36118a08f3bb369943b7a8f50a6b93662b8b0ae53bd5570b5b4c5f8ca8513136ad1a75ad3e9e8628fae9a17cdf8b115fd117636a895aa1d69a8239abe4b1e7815dbac52e1d93eaa9ad43c54e866ef31e493a95aa7471c7e639b25d8436d7571f3f7263588fced2639a5219e92d6d953a452ffdb0ec7b7addde4cc1eda4f79fb8f5894be1eee1a4e089dbb53c31b252ae4fdc78e9f50949c2233b672e3875e01dbe3db883d9f3d132fa8c3e1e91e3e93f3d3275b3889dda3a076db4596472fc5c31d1732f8bb214b5b5aae076b93aa45e4b702bdc41202ab87d9ae34b706b096a096e09e89d4a38b5afbe1fb75b5a8e4e0fedaa7f9bddba1e56bbb0a883318b59b55ab747c632caeea0d763ba87ad1b464f698f1c4f61294020dcd17b1e7147b1ccf4ce76e12edeecd928ad137da5968ccc934473a56999692ecc94e22ed2bf62ef442b5a9ea5e7a8040d96c5512c15cd480000006314002030140c09c542c1683c1aa8a2da0714800c9ba05066481688b31cc871ca1863884104080000800000c80841030028c40171a3d837ef28b549a66997a0f589029380ee2a8978efd0b40f6a3486f6e1f963887d4a08e6e07d95dc47c8b5e3d1f71cab9c8509e1cf945109441116013e2c015947fb70b4e800fee9fd7d501a984782f0800063023142825a0ab46e2a86f88e0357dc8c52559d12476b9a5fc4566bbe93a95f78f16f7f01b49310dec7efa12adda434af0c90b3a285324a5091935a72b430d43e9b5dc08173ab6d0532d4a62e66c5353bf17cc90979517cc9fc4e6e414bc75c4d156dbe46de9adc265c8b8120c857e6218e3f2f6c9528870b36315d24b935c1c0200607518689f9faf900186924a8eb00daeb4ef28ed9267fb30b98908c71da300aab5ed032bb05d325caa66705687032d24508cda377acf3cfedb865392cc7076d89da07243c7123ff54759042b439a3cc1a4c2f21b5fbcf81bb943b0645ee915531ba774138fd5445bb0957f7291600a59366ec0d4dbecdedbc4a7b4a77fb2dda597c26593303b04a331a1cb6dd472c4c40ddecbd9d393ff5c7c453d1ea64c2038ad8616f204bb55ece1aec9a5c761204a92457509b83a72ed62c787bd4580bcd41f1b76c02958b514e8e51faa7c638ccb40d9e0f8fe9e2d1c1b90a91f984a146dc157fe7d210e77cfcb2a3efb0699b9526907d896acad728fa0cfc0ed468277ddb2a949c636aab9823242f3906c8dc69733e590a6f0c6d8a2e47c2dc185cfe7a89c3be987c3ac91984e4db2fc4b8f941a627712503767a2b9ca2237691552dad4883cc30f47927e4efeeb27105d7a39389c45d188404abd11aa6598b6e4a25b7d9c5b32a622dffd85b4ee1081dafd9126f00d84faa3eaba92991627ef20cfde60e4520203dc29fce0d8db126a822752ed81b94e02509e79d44aa11c9472edad6071bbf2535732e22672fd5b980efcd5b391ded205db88d25d5865fe29f4694fa1f2397599b351ca6e96213358d9be13a06e50b4960f6ae4b57306a5ae91300e6254805de05fccd4b4cd42000816896d394a0d96ba72a89c7950e4f7467ca28850ec7c7602d4c4a931a39bef8a176c99beb714b1b0be1cfc6a2de4ac7dffdbb7a7d6860bba5ff030b20f63591ab8039c1ad15278aba063e6985c5a4899d99f63ff075da43b42f8987ec108b52a79e84b05d7e7040776881eabd900becbbf0abc334202f47594ca54bf5120851ec211a543efe642e35abe0a7f48396b91be2cc427ae9d940120177deaf436dbca26d73ad18494360ef780f203986a33125b23079c8489c51d98e080c2609a8e48a03af510d5d22c0ff875535924f3dcd7333c5b083cb89e73141d949f1422b54170ce7e27c29fd8cdfcfdd5005fe4f90b083713a72bf765b5a4ba4f442e583e200af276c6cb4d0c1e6f6c12540b07d8e39179e7829c06102f1d098ae4651db383d6f1a59220539bf63adca0459349a4235ebed4f80aab44205c504bf40e8771e7473539c4b68cd26ab1dee4b4a11f7409edacb7055f66b275aa6a25c4b6f06966368792f0a6790a99a9715b3592281cb16c553b71f84d06fc030ef8d26fde58b61cdddab9fac1a4c66052c31d42e7255e5ad36155c1b4729f9b12447e94fbdc09c4acb42b8e54234677eb3782a723eaf842a633cf5fa83c24aed01e6e70a824de863bd30e6c1de47c7152544e74bd9a1a61640ec6d0d8d9a0231ed26abe05d7d0e2e8db0d00e644132b78313f3d10f0b35328d42b80cbcc1156c7307b9539a450d8290437391c5b8b2c5076e2a0c6723121145987b44e43bfa991ab5c07727a50d5b44f2d4943c3e1185474c390db225bd23373ef8faa458433155bf62b7c5e52c2974960ad3880d6ef192ac3178c7d9e5212f374efc3d519ff4a7ba2d84923647f02f7fe16a06246a939e0a7f69a343b23ccced9bfd53480efb1e25919501239911073161a939482d3f6120481fd8ad69ebf72db5a8ff41975b898dc61b282b59bbb16de0a63acd527aacc27d8170e97fdcb6d8cdb96e30204d783e1a5ce0c9046fd00d87ddb09d126aec186eb69542dbabb474cf89eda69be8a569f7562b5d3e89fd748375e962426c4d37b2dfdc56f47e9df3fea0be6e1cde821efe1e8366c6597cc40fb0328b66b9d178731de8be4852ee2b1abfdb22fffb70ef69161bc43c590fcdbda4f5772dfa4fdc68f7d25cb6051ab695d14d00cdfcac916f342bc266dd3739962817026e0d2bb76b99d33239c7d74e8d37f7d293fb0d116cb5a56b6e891e1bd3cd8ad24b17fba9ae9bd332ac68c72f2e4eef95c6f744003210611fd3426c6cd656d14e4a5d27862b8ce565825d8bac76e12e12bcb6c7d8f5205211c47f3a279f12fa60a9671a838a5be1d55903bcd9dd80c1947723d6ecb5ccbf247677b1f3d39305d9490a64f5ce39edfdd17c86688769023f8a0ce69aba4ceb7aa2333fa4d8704c2e8613fd526eb6064d352db87af6949c2f569fa554c80af9f0351bd60b5cbe80d95d62e8b3e409c93bb10110181d23758999c2caeb25309b1d8d28184255a3af4c51d0e605e7b66d175da79a7cac1216e17e4a8a6792f2a97379bf2eb623cebd86a3066e237a65574d04c59dd2f4de24460449e211433a192d475fe30b7cd0556fe79ea658b8ddbb83b2d1e5b64fbd8a147b08e1cad10457ad86b8f3c74d7bde36a8abc73d7c55c88b6b7643a4bb444e1b934a2fcb140cc12cd54db44af10088258c9ed8d52bcbdf69e8227cff20774b1fd8f3fb1a3f566760aa152220a858c5aa15295e6167e45f26c90c1f5ca247884fe8c9e60e6672ff833216a047e5bb74183e85cb97182889a1abf43c20b7ac232a8ca95731a1838f413592769c72a030580a9e2b3622f98a20de09fabbf62c77f95e714c863ebf510cc165b7343e7ff38096088e8791d1db16c9c35b805b8f2ea6cff562b1fea2f65d0fba506634fb4cf785b7f3e68c071c3be8fb5016c4ff5d395165bce712d30ab12778d644bc8f32c48c7efdf1fc86f2a530a814771f7bf4ed73417fc207d4e973590da1440f7e57303bade7fa35d059a0162810073988742e10f86589eac0782a46c29d75823dacc6b73bd72b0624745c5a48309e61002efb6a1c550b0587e7381251835ff61b1b60578940586b491b2fbaecb12e7cd6213cdb76ea758dca985dea5acaff309cddbe55a7ed9cc62f111dc1df80082219e0588b04a4a1ef1fc5a165a99f4070c7377e46412cf01a4249d1158d8893058af70c9478b2aba0b0510612563bc42088b6dba2672a2bd28a811e0beb839b88a1909ff2bb832e69c03224075a0e98b7453a5e20aabcdb80161c30de67d092891ba24f6fd066d6767772ea21eee16821acc726612442082b7fd6119683e968d5a3fc4cdab328a5c34c93cbaac7e1e8f16e6810cf98bd51eddd9612608a85ce27e8a8acf92d9ca67ab87f9cb1a3ea0ce277c8d75c94f97345f706615195383fc56fbc30b94161b383c9a929fe7689e171f92e68a79bd9c5fab0c0167c4fcc0882e1666e43511ac80c670bca121ab4548e7b8b16d8e98606ec0b532ab6f31efbd41cfdd22f37f1b233c1adafc9e24f7286aa1269d4b01fa10e031070bee83a168227243f7890c3125c7ac3e19707bc532cac99af93d460d67fbbcd13585d35ed876312140012e0bd31e9641a02091c78e6da8e96fbcbb052e1f2c38f73aee9b6f3ed29f1c9ded6a8c08a96257489076b5ec328b4043965a41e70cbd3a8cebfeb9edc0fd7e847d3b383f1d42ce1a9bbd0081b4f1c35416311bb3f0cf31d3e171425fbc49d667c7bba8d5e3d6e91650d0920fd29390079f99aed95078f589baaa13ffdbccf3f02b7cd5ec3e3012840ced83ed939e5bcef4b1ef3788230545325138d14a2e0dccb93fc39d87a8793203f135216b14c27e39d6ecae028b33a4c1181284961b69be4c35c0ccc5616a08494a6bf6cba102a47ede9869d3d055d2cf310e485c5a7a9c9ee2672f4533d2e3eadde4f656180dcf4bf7b323570d192a6998913dce0710bc5e922384139451471827aa0bb4326b532776cddc6ca6ee6a8f0244ce0ccc8dcb0a0a0967f2cd0f5008fadaa8dabb6dbc5d55c25adad86c9589900648726e6fde48a268d558590552839cfa935371962d66a6fae9061fafc04ecdb09ce031a0243d5083a693bfe1cf9328c36e8d6ef1d8e7b5d67446e2dd58c246e69d5ced21cfbed97a54d8db29b94754bbcbcb49edde25103ee398ef5b2be1458354ac3770ca68a5749ef1ac276171ef145b05982c9b2f80c4dc664a13a440be63f05c0ade156139eee363491fb562c5a31a88c79e2ee46a7a60d2b6d5c88459d446fb60d6408ee9250b88df2e310313d43f6a4721dd2a2bf463facaf30df3215b3069f1a2b5cbc45d262f5f876b866bf89cd60cae1b8712aef5a333411d3469655229612b63624229f17a04eac526dd480f5ac66bc34e90f47d46e5c6b87ab8b50aad1ad8994919d60f66a8299137d868ef3698907cc60fa07e40badaece069df8ec94cf38d557a25939e829db4d7833ae4cd57b6f030553ecaa359f156f630eecbe4c1f5ddef88ca9029c65c0c9464cd53b7658dd2abd8b77e6836ff68388a1342a7d65fb584b4e3ed5510ab5dfa61f5326acad7eb9e22c5185a0fd42726313422f372114fabf60b48edaa7c685b4d911f766f316b88991935297fdb8fc4803c646e8c728a0e56a154bdde44a8eff25eb2df518b7acc457f4d6c6bdba55aa669554f8b0a508c02beb2a1b0ab475d7ebd2f5433b0b33a28a91b7e146dd02ec03e3f7e93e0ac356055d8f8579090687d83ff72dc6762c991cdd024f96b524d677d1eacd7de8db5c1e3e8d7392b02bd40d83b66d8dd1041d06c054562797a6f4a285db1d649c8e50a994bc1ce50f22c9e481db06a0494c0c0fea1213ce1f1b90936189d39353dd43d2d67a9b0ea873c4f29484778d451a9af27b3ca52ffe8d9ef65cc9bdf091a4932440c1692f01768dab0f9fb016fe3836010c5cab68beef98b1f5dd139f4b0bedcdf235dd50cffbea34ffcf52d4918e71175f9705f797e1eb828fad6b7237882d9679229939af42364a796ff68ce2812ece13962db9997ec38e9a66366da20f05a75465959efd2655b20212d23e60e65b76b9cbcbd1541fc592eeb93e31aa326ef64b494a56967b95869d690e57b8ebe2f7b8a42a6c7585eb5ec540cd096711f20a10933d99427998ca62e1c10027fd3d2387fc03d347853ff851a8b9c241d240aff480c18eab00dcc64565860cda7ccc4241b2e4ce11a390f46232e353908997a8973b2d09dbf3ab27d2109459b1512a514aa784bb4669fd28cc151e23e84686985dc4b77fc111bada8aace8282277d859266af9c7c060b1a64dd13cd9427de090deecab02249bffb602aed9085635a469fac277a6d874dbd401e6fd9f7b2479930f50951aa35fa21ff50d7585e670be276b0e1d8f8e663327e7eff6d32c811c183e85ba79211b5a4480e258264723a05616d8bdc8d02a97088f75572416b5831025b5ad18e289fd495a1125eb4b9c18930215d6b8fe315335603d07740174a6e9b1b5a4b2b314ee460b1c0291487ede979ed7195bfdfeed21d961c19297c658f76be49d8675f8a6c47c92d7166b08b35fe5624162062767ca8992fd024e08800380f64a61a56d754996a8bf37e735c35f726831ec5af411cd307c11ee5ebcfde4a6879a420965a97741ea493bdb0a15b10d786ad31e94bbfaa2ee6af4f2a7fdfdac12b406b14b83ea8f275d29174a7540680643c0cd8d59d9e629558d0a9823502d378ca8b553c4138f4d400f6fef2dd9e10642400cff7c4644fc1097344c9efe1f27def3a7280df1f36d6f1e7a88fa6b36564afedf98c6ec3986ad064a515714b65ab7f0deb041bd058f6445cf2f2795c3f57ca722a4a833c975d9c459369b5022974e09e8d183f0560a2a6b68e5e15fc80d03e345ef8576fed1f84fb38f43cad9c04ae187ab89c9efac1ab5b83640fe3b9cf15a54aef4a046c4f5842e6dcd4d1fce6665bd07a72231d14f0e04997e5b2a26ebb3e02f7a16f1cb69972c22792ec405b092207bd3cf93ba84c5f20114d51f5b3a37c2ff7a059e35e96f0d81be284bb1baf58c5cf416494e480b9dcdb08acc62a82e3fb187a7df77499dc384beb2412724ed0a5d960bf41e1bfb68103d0cd859cc2ad015b16627593c9d0eecf0a268dc11061b582ada568b421da6d59995bfbbe3eda9cce7eca466e04d0ddcda3fc82557d0de2057aed75f2f04e9c0ad1da43bce4136e9c570a4e2f3f9104ca1e06c00b10ae0d2753374abb36ed9ff1bcb6dec9051dadd3a550c72379511e0a83c21a4c39b7e78dfdac9b135ed2c4ce5ff889076a155fcc7d9692e7bc753c7516f7d5fc6051e6383797b1fc9edb16979a6241db04dc049421aaf3f6f880795d81a7618f57b6736c51a279ac0b0236a7c38820cb62cbb34ef9c3929f94cdbf507c8f4093d55d41e5d9452540513296801c3d495e325d6355046946bcfa8205ca75c66b820b07cd0f3ede228e82aa3fbe39cf4b51f497ebe5e66536c9374467c56a4dd9ec89c1bee2a0c6bc3b7e2d3cc5a7ef3abb1bc683a3129657ea3e16ab961ff898419e6a54d485ae98801c8376348368c392efc6b949539c9950b8544a5e3047b5e04e80c6b4077d6a2d348eb211a5ecc80cab2c1751affac2dc786a6320f3ee0e04e28b6cdd59419df755981e6e826d6040593d1305718bab37e58e9f9bb69486226bb3ea74fe1e8c199f61c375475ae1bb6fdae92e6bb27406628e987450096ec9c8de47319346503210181bddd2014209ce96249ff7a7c6db1421f19a011d6ca7303b5d4b4ce8c7ba9827acdf8d452e0dbb43f4c291115d5c5146d68c9f3ccb569e932205960a9e6c9f81e305f28ad3c3c443da11205b7ac8a251c4287991fd8fa6fcd442aea55f293e57c081afe2268237587e6e5acd304be2da52918cbff6985f0bce42b0ae55c5a6bb84b4b2cb5d2f1fc57219a3de4f9658f0c0de3235aecf138c2575cc23f3ef8b2d188428fae390ecdc90b00831177160b15ca4a9fb2cab031aa11e73bba852d9c570c41732ea976e4fa6bf6a05e000719d976a29308f9a6650a98f235d09880eaa8df3b6a859b130e3219705e3f173d6502f56c1405a09cabea01d677674bd42fae28ee5d279f9caae0ca2766e2ac829e2b991806d425086ced2d3ba793652913e4dabe607abf919524fbe33b56f30060fb97629d2175661e5777feba0c357ee667e62c875b4db4f9152d0f377fcaf44e35d2e4923ad1ed67824d1165f47f439fed4e6d24992d5b890fccd34df6a2348cb8bc66e978507b86e96fa2eb4bcb01b12ce1ecbf9b317d10ab59e23bbec78b8d4e677d5084ab39013fcfbec689450fc68be2ed3492c2940e8aaea08713a84e72c6a282ed30a3c2dc6f0d286927bd2156fa1270c0f6288613f9d493bf33c9b3e65449b426553ce94933b54b7d858a8ae3c6d21e6495d869cc85860bce7324b5b93d66df49d128d4dcb074078d9b5a7095de68ef242e7fe74a5e4a94eef3946f95838e420d7ecf4f70914ca13fc5cb9971bde896a350abb51463acc2288dab96ed0c406e671c29a50141fad00eb2aa16f788f286b53fc0a4d09ad0d8b73c24a85058be504b897f1c7b5cc0a2880ed1f5b337eedc2bca019af8b81b81aa2647d3357bd143518c4c079f8a5902dc2b2688ba26ecba4eb2d05131949b60949e3aea684ceb4d0cfe3d04dc5e9cd4db219d4fc5c4e76c943e5cc347e47e727c000408e66108cb042fdf04d2c45e4c3c2758c5cc215a174c1db74e8d42adaa110d0425214c4a929608c024acc7af51da118b85731a794e709ec0ea43f0060aa084a818386097e6c655f0de2c976f2c597e7520fc4c10a6abfce311104613b0204227a3e1fa360c44c90386c90723b0cf41d908de4e2d22446fc4da3a94d730dc2f30f453fa2e319131f1d420e6891ea313f276528508550cc8dc2dadd37783e98378300ac615c2002820da81feca4c1e6033bd5f2aeb9c623e98077bf44753a96f564736b38233a48526074559519e8aa1e015629fe40549e6ee55fb67ebe796afca62c2cdda27457740595460f4c30042cc048420f9d98c815801a5991eed86a5240754a4403e0921d07e3902771c5aa7aad236732c2224d86b307e19a85b4103c255d68c603f96d03e4ee1a0c8b753c306031bda60a8874963473a6951c2cc821e23c6c12203714c1eba43ed881d3972a7ac9846327a7fbe8c01009a7db7dc9fcd3c6ca30ca63a93600186ba1924313b763cd10b190cea0f755340beb30b605c306b9f96ef559be0c8b49cdb92e05558304dc03a4bcfffb32c21a0cb7ecf0eed777a9dc5e4a282793f872f85474942c47d56eada1909764f34a0b95d3ed17c9da6766d591ebc7af1b4173bd1132754494bc9ad7625b13862d7fd70903f3b3d50a4d7ff57104bd0ec419fa07dac01f9f81ef02329464edd1ad8359d6a374e6eb7f1f23b5130a9fd36aacccada635598794c3bf4672c1218035e3092d9191776bb62d4a0374d461d6a6e329ca5c3ca025d8e10b8e1184fd9c373cf2f33d5ce0083006450528a880627f59335cf848a211821ff0cc316aa5ed4f6275e50c5f2800487be580ac2d1806a3155ea93477a051293aaf426cfa63ecdad8b6f186532ebf852da15ad5be7347ecc845585e7e66ab2efc008fb491207fa09338fb6adff9f305ab5334d4fc5b3d7420a12942ed37d1134f145e5025ef985c24e00ce7a563b627f487b46f59f80cb2f4a7049906731c6b6ab56a954e1eb3edbae2aff6065407ea62b6d5bad846121f3a317e271a7192959f9f104fbddbd0984c3964e0c559f32efa154f16d08bd74e16e8260f31dc7083995b9a8dcdd828c810ead415fa0d11c39f9fcb94023536c0dc71a45ea1a8811f8a23854ef7cc4308738175f2260167289e75debe60b9a4f319d9195e3d30b3c7f6824c8557a974fe183ee52e804d09991da797a54730826210530022e78fabf563926d9de4791ffca46b1aa308848e2dbad91d210343efa725ee35b51dfafc646868f1d1e5e353a53dc25242becbe4239a1a893567925d8b7a3661066f88bac9a3f819de964cd34b9f0c6f918c78d5cd06e8a10031ced0944ceceef27249d122f2c126af2c36423b2174dcc0c8e26126598e22f1af1a383b703d231444cffc8d87dbda8d2af52520d1a0100a4e7bde4163241d65bb13ea285d0413cc48283a9594701f861e7359e1d029502ba7fbadcd7ab7b81ebb3f0b18328cc03a2fb76f86f5c4e6450d4707da04fc1c75096ff99b2048d6099d550816957daf6e83470dc6ed12208c90d3c1e271b9e07081c8a140bc0f346daeb2b63b9570d235a101c73c7bd5a3620513401af7624752f119b75aad29656d9485dceb171ec6bb23f2f1703f9258e0871605f002a495ed1a82640f13161c2e4eb61a519798fbd230c41e56f885ee258f8e428697bfdcf4ba43f743934f8804ed0e4e2dca7a0d207e5e524360bda300eae6bf11ad8726f4f70ee615d9a8cd24a124bb33f8acd961eba6541b5bdd0fd5c759416513c6234261599cd09d6600fab0cf432814f5d2ba0a9f4dbfd4dcfd40f1c6695ba04065b2f9d1f728e0642afac0ba62b3851a3624bf74ae93946ed7ca3f2357d4eb678058e33f1fdaddbb233ea7b3efc2befb2952311f977df14057c0425ef86487b8f200e3d4d9d19af9e718723c1da5c26d814493c3b1ec83af872df8cfeddbfc7107c8978e7be19a70c63979bb78948cb87a29479dc49fdfe4b41e83eca6a67cc09341346b9c4d05b8b2b6cdf2cc9453bd01819bb864d131a1c878d09cf17c166fb66a2fe332f8c6b0c1e356e3ba87f7f80172f87c7a37860f439b802dc8c897bbf3c9dfced9b59547aaee3ed9bd1c501e7d9f6cd1cf7103cb726642ea7fcaac6ec9bf51fbfcd3c6a643327eb3326837db37ab0a389eb557cebe1d03f766a6f814844ae6ee66926932ae1eb9b15f3f72a939db2127775c5dbd4c64832b65605ebb3e41007d6babed9092e024c95b8b0c340e55162f889bd157389710d62b0d3aefd0cb9046026d7f3f8ba805b3863d0d4615c1de34f0ac8f94578dc28ef99b7f63138c15aee2cbf0889d0be1989ace170abef877f495c09faa628bc4ecf56450032759cd43924362b93ad15c2e2f6881a09bd1e58e152d672b0eba9d9e2b060ca518268bab092ab2dea90f898a88d3d7ea0e2d443bf21a30efee43170ec39aa2c75b83df7b778d8a4d455d8489ff5bfc48c22276f3169fd7c1e0988558575c05031cb0332bb1a13336da4b75012879b578a783e680a78d7fd9201acb7901349882dcb58e9b0ad7a0b9588c221f5964ca6adb05e9a320852dc65a6c1f496b8f5260d2d614ef76b6a97d5e82d76ad99e5718fded2abe38c6bc816144dcff01aee2dd03b0ce573e82d6b808ef511acc66532878769b4d47c4bedbdb18cfca8eabd89fa6f7981a3988f66892bf108f968026f6757e92902d01b9531fe95257b90467a1b68947491afd0e90ee80d39bd207bc4fe40fca3a0a6408a07dc86b6e4bf0e28a1d5e4635c383fc30d7b048827602838c0f2b09ecd3ae546b3278b686592f2f621c38166fed9e473fcf2ef1b254b6a2b8086374cec47d011d5220e3b730a9531063bec960e114e2f28588395e49089e059095737e158dbe4f1c33fba661373005762d3c01d23df42a31b336bc4a3838bc2df32fe1ec265262805d95ee6591ad67065c06a834a6e4e13fa35ff248f21a6c8328a7f2a6625376df2e71f93183ca43bd244094ef1d4a2de08e0edb2c88a9684b4186f31584b84df44363af047f1176518cc821ffae30cc95db92e123deb7800b841088981aa7d1e5cfc237d170287330e465a82a2d3096251504b05d0562a13e9d4f804066d6a1441c2fdccfe28db8c40b3fabb924efedad8aa22b815e984201c81344ed3c8e676b4b1eb97a4dd92925a870c6f994527ff34484253b0b083b39912ae64d3be69f866ab57dc7557ae5b88ccd3eeb0af57270bd7d4a0d73defc2dcce3fc4eab3b07f2ac320fe21c3f88e31e9cd19097bf186ebf0e03049a80bd98f9b0e60dfe0463b1f41ff76f288ae39b125fdd69c0fb2d29ad837829579cc8ea656df06a0f847c19f072a94dcac2c02193fae4dff099d206d7070cdc212d73d33e85b620a80aefa66a9d74a815bc9ea66c566f672c42d7edd81fee620d364abe1df4a413989df9c23261eb1b00a62fda088fb430c0f4834e65b4a1e332db9efb80989d7a0be28c7f031dda2ddb7cbb9de99391c111d71d1d0bd4996f618178d3622174dfd9d7f726684f23c1035c254c3a77b9ca71838817a25ada0eadf9181e6740e95d635516815d8b655a90cff0eb3f26312ee5657ba7fbd834078c14f778da6bca1e60bef090bd13d89953602a629e52047063ef825c77814a9efd42558ac13d5ec52e756faec4a7d3cb9b65c19e7ba4f2bfdb1765c79a0ccb12b073f834c5e57f6eda79a9bcd4d00d31d7cce428c875bcb9bddccd0d4de265aebf89296256e0941d1e1e5c1eaae1f39bc4d169c87de4299a20d3f1db0e8e175e22b1a30447005a3d1c38cc48f28c08025942338c7c60d8b5bb01c29883840bda5a76f594d600e204a89125dd7d11afeeb1852b8509385fd26bd46290eff449fee90d4ffcdc7b1cc0b87185e5138ff56602242131f7909781aee1e2d2b63431fd0e40f5b3d1bb3928fba423a1c308dddd7ab8d0d54068fb477cf998106d887453441a7dae05a74a549b2129e049bde50d995812853af5bdc20729e9f87fc756e608ef486ce0a7315a26a788421f47011f0c679a3a1bf017a3a41d7d3bd80c524c98446589e243754954fb4578eafd5bcd307d1a81ac38a5c201b2df60ad189d81dc0a09bd71da04d7827d2ca2082778008d81272d1a3af7caf0bc067858fe0dce865676a57804535b6c596d124f523fcf055bd0d810c30c00d0ecedfd2089da90cbbb1bb467cb56db781b44e43c48753f50aee830cef0cd22c6ac461b023e57f2a05c31a6826e005e58c53f2c94a4db7e1db58adfe8667a8e8cee1c03ed8f8141c839af5de03f99724550273b543465d426291f18aedfce241c6ce9064ea901920e0e0d775f193a8ed267ca0b132719540ea070821742ef4d9d379fc0668529effbf8c7198a4057affa5b4bff7bc484c08676aab6491099157ade1cf4b4488a97780b85483f5284874225a80c0b3feef971f6c149fbd193bb10911ded89f5031b16b8e7bd52537584797e82f088c122181cbc49089f8b7753493a1f0d2b641f91a7fe4759409da78e16ae717c0afbca19a139aef4f3962f5d402b668d05f0b87b92938160ac3947133f8265a8f514da2ffc430e8d3c24e6d415d2ac7eaa7903cf4f716f67e965d71b3bba5e2691db01966375743b1a600578d11a8e674d164ab3112dd9d60329bd58d26cbb4e48de8ab21d924f2fe804a28b845565ac99fbb164d8e4656e0327fe3406a3db2ee0edd993fa9006cac9dc18d588367a07fd905140f44a2932831fe92657e2a26d2516c3c1413d30bdae62c7cf5d307397489a7f26f942b54cc618131e701a0074289f7f945ce0236479bd96ee0a5dc6a7dd1d0e6ab8d2239561e4000ac7da06ad7cabbaddd8d823773b842228a328079820a6a7588c1683b14394b4a40fae0221e122a5fd445adfadaacc5713eb55e57a8687e7e9dbc4282b74d186ae8365106f2133d42eb0117660e98b871aca6c8f3b8183e4a4db076bdb4b16a81da078946d32595f9f96f973d2d5bd01844b0fd1a8a0d8a4c3a22d34a130999aa5965b842e1ba93785d0cf0b1673fcccf92b429e46595a70627d53bf914ebea5a198191fdd73c1fe7a85e23ad36a2b077d63e06768824f24758321754b1b8aa284a9fb044552ace5d83d2c0c56275448d05d84239d8157389e2430299ecdc5d93222a096e7e31764accef78098a8e1455ee4907608ee6f0f703d3ffc63be32c89f7f848ac69d27441c21da635b15e83a9666742ff3ff9916a2cddc71bedf0a6e746e507fe85a5da41b17d2c63a473572e533b9f950f8e6cb92ba2c47cc98eba18ae665bf2311e352c5d86c5fe41ddcf7fbdb375c2ee21564de5a647ec0b5c007cee141f23c7c41a0cdd133de0a88334049e796094a6ef109558b3cb2aa2d6b60bf6e26072e62290d4d433354301b047e03ec172001283adf0273870853763c2212e8d452416e7d4ffcbbd5533d018b96aed692922961a7ff8e56e43456055482ad094db1576ee3054f3536cfa537051c49a743e7b9da992360c803bdcb81b1224c04ea65348ffc1834393a3d6b14bf55c560b1c5c729ac1c37d80748326de9d1a02f2e49421f83f6d0564e577151415a68861322e0d78bf5465560774d273d616cd18f3995cd4bda883ff2b2349721af5ed0c1649441899b7277fcca6fba5ebef1c700b64f76312e4c6e04c0fcc6a78994eb33de2d55430653cf377785066c9027eb298871af5b84cf7afe67ec1919da54e2193fcee59cc22b85cfc512647aa3fb6e15ff00087b15069d83abdbf3a00476f22687012df35621d0c56d0106dd01d60bb4b476c46e7d7081ccc6f4353cb5ef41c8a2bab5102b0312ba6cfdcb282276d5c2bcd6cca463b8449797b6329b735025e8fe756c7568aa7e9889cdd66a6f108ac5cf2d52ca68e75063e123b5b5c01ab9e243e38b6676d87219631ed0aa5b2b01e068594ff0f0d4eca253717b1fd470e137930575e13ab938058cf622bce344c4ffabb502834e5f59a4e979ba7656c55102d431ddc348eaf002e396a99b84d435c6cdebeacfcc9a455b7000fdb8299da655e91cd09b40a5e0f31303e85c8c79a24d62b185a100486150e2400592e99b574adb5d2e72ced6161cb9d26e969c97c90c288031d463972d1f2f034bc95a1d0a196dbc8504d99ee62938d565873954b9773953b1be57da98bc9684afd25372591fb9a655b74243d4da5465bb325f19e14302d4898aa635fb65a85bc99d5aef41ad7dd0df1733704d4b8d8e5bedb19132899dfda1fff2b7f966be4067524ae81f31e6565ed16f9089911872b4008f80db43f66c417b1eeefc116935b89ce6f32494397f4c13a3a1c5208457c470e9bf53297779d00fe773fbe5561d061849a9b6604dc4dc335d3c163204652219d2b1ce842013dcad1292a9a4c5c07d426ce1613480d7c9533f5987915496904baa63d68c1496ba831f53985ebfe4d9d56a2656ea0bdbc8004141badb2e084a2d847d98e788aff9413fcd0591122db5ef7f3c82f162b615a6f6c6d693fa4af9352a2181e0cce24628f47c24da5ad9afdac7f537b3c66c97d5cecbfaec76314e4bf743c83f8c85956d6d6090b86a14b6fc93c6c634eec2ce60689a4bc93793852176ce9186dd32d4f177dc72b3e38cb6a05874c7d46453b568023aaf94b89f083e10787a3d480e5b825539861dcf87220ff7b52071fdb5479526330e06448fe61302ecf936d9815d52f34d065b8378e9d03636e49709138cde97358e0fa96371326f9d4132c9d1df09ffbc88e468aa3d129f9578cc8219be98380d7d705110d558b94a5fd92e080d566c5a07da301e15c377241207cb9f827039e7480c9d23fa6805d15fda277b521f63b43dac9a207f9342bdd80d2efaefcad44437e7a9346f5f724a73de0996f39d6c461a4ecee96512a06f51db830ca96a57d5aa0638d1af846dcb0b8d66f7ec67366b89ea57a2c04bbaf85a4994b9c62d778a458a80a420f316dcacbf871dd16c3c0fcb497b15b500c915e86cc8d212d2ac94015c53ae37902369c58490eccbb82c97889e5637da10f06cb7e555a352d244dd3dbc1ddb03699b41308a2ca0ead44efa9ed4c344baa12dfa9826b04070aae2b1129490ef9f521bf3b06294ce923c2fda75f5c1f3056c0b0ba6611e058c088622c2327876e5dc8520a4339bb7bd14bdcc94d4ed0b3240653a04390ff6c3e66b4b023de733554ca3b3f65705f85878b568c3b908e4fa5368e3255a61730442a71eac3319f8e5e23ba3c1b2728d474d9c0c18326e972dba3a3ff83c6faa64c7cef0488c28ca32298469e56edd4430e92ccdb60d2ecd26d6d3462bf465d8b34bc23bb2857ed48d6230304425152685cecb7e1d56acf2c63d4291a960bfd4991def29ee38d834b45cd2f841fdd8c34192a7c2a2faf29de2793de1c4ebbe446a5bc2b8a1e41a98027283a91ca37f11493982dd91f25e795243440b2f59fe4b05cdd6488d31faff411df5b52cd1fc213c8881889b48fbb76104e852653beff7d863e44913aa2140632d56eba766483f16c9dedfeffc9bf0c66346afa771f21a09a7b472c9b4968e9194f4f29fc8109c61a919ef4e6834978652c601fdc8c7847d2f6a1fba7e154ad47f8644260efc29d760e214ac03ae9d2d669ed53fd11d16e4532e2055542a39955569e70ce513593a5cec0b3ba48311c99a32067f6ab6c30176fc415aece8b567200636c03bfcb5c0e01ad3dcbb744df8e5336e340c029de7af4bf62a29f45304595341c0bf668033a15db02b6570f3e64decdfbec058a9f22795d2c37aa1693c13b719c713a3c5b815e2615422df9c5fa09d47bb73123e834e5b49966e9b3912e64fdb84de585d7375de484a8142e545c52568c24ed92d8e59743de142831e9fae5bb172d9be8bd007ea38a1b289f4aa7e6627c8283d25f55b0225a9e839830ae25172dfbb5954c8083069418cefd01f01087d2ea2162368ed32dc7d852c2636e7f9a1431d60bb52a4e6739f8b9f005325cd38fe537dc818681b57cf425cb9256ac7855d0336986486fbc63dd72ef1fbd78be9b6bccca310b7c10ebfc49c588c9db9a866e590ffdf6932a94db05216f7b262e65a5d13154859057cdd0adb6c6e81ea517e743c7d68afdc2017db51ec9680366a19b3d9dd9c0d519ac072ad677daf287fb5d4b4e2e64836e2f55367b87f855e53fb015cbae2be66b63b1ff7e1f56de2eb037edeaddf977e35c2a44db012da444b27a032edcd33e7ad22bc533ede42ca403a6539a2108b4d40cb493031f74fc11829453c70fee29428c9d989e31c02a6a7315f45edc8aa213d28995a2fcb7d3620e4a7d36b281f74a9b34a3812483f3069625dcf2ea58e44cc72044352db0a75be11c3c3328c05981e48cec8757ab1e057d12384c41239e2c4105ba5321da10c9bea3353a4b9cdfae880068e9f75cb5f508bcad7b61a9925dcc1bdb2d889e801a9dcad0997991aeddfcd61188e513965578ab4dd9b8080e95a1be077890fad20ed613ca61c630997ec2792cdf5a05c758e6f1e5a0d078f9fea5478f21ff57e0dfcc2d3f66ccb6a894295973d4bb9f30fadcf1831c1c86d100e70fa640d2d8448cbad28c09cffa5372aefcd993cb8387b19b2fa5228e50c3e233ea5f9d6764711b40e0dda7765646457144c68c11e0bacbe086f94fa090b5ec147cf047768f43d2cd8f73f066955391c019ea8dc0b2628174d9d655fbbe203caee0511f511cf359036d1dc8f309d092c302d1d70bcab614f551ff394d5efed8868631ff9598f5e19eb91026114d059b32246217566b5ff61b4604ce069741b80e2fb9d1bc2604c68d93c3883b09679619c0cd41e92a3c2b24348ec37de98c2e60ff026fcca61194eae15f20a6751f620670d9d35fd250bac6984a0c99b34de54129d73b60750504815a99c2e7e5ccd2cdd3a3ac1480100948df50167fbe02fefe1067cb96c72924f186af690caca3ba9c8bbf0be193e8b389cd8067ee491d507270ead6e67c810fa42a6d03816d92e6d4108c30a05d36c0ce317613167644ff313574e5713a5f370faf7230923b41749b83d581f34db327668f50ab37374603b98a32199511e80f2d60f03e130202f5e6d0740abac75b19067aa8974796f13c0b7a1f194b22ec115b6ae15c0771815fbe263a713e8ab0b3125f0f183c160578acd65296a1d825fd64a5b51a07429ac17a9c4badc2b5785073eb41f6edc69021bc27751d11f5908a2ac47a6b93d1ef5948e1d2adefc2b7870173824c98388926ba3f3061971c20012268d29f35fb7afc092f39a799b1ef2263ee4c32551f3c07368f008599fcdbc3f9d3ecd67f51249263cdd895aeb9541b8a2d8b2fcb60a780fbb6376202a1b4074f3e74014eb007fce2c4544fadeb091709c6d788b09802857fe1e2de1a854c3d482351910bca41c423fb6232b54ed7ad1afbc1491b7ae93fe63c319099ee0b308e6a9b88417a69ae1e60cc3b0db376a19da6e267c22c5b4d03db5b3250a86cf6d91d784a9f424b16fd55070143fd80f1f08f49c00a003a37afee5df79f7485fee600e113ef68e31b09a03513ccd641e40357efef6891d46f108b7fddbb03ad0cc3e8804be11ceaff69ec9088012828f6cf36a20faf49cbc5306a90a60f711d9336d17d879f65a6a7f254bf8130ccf9ec3e388c56137555291e7acc77584301730c6b1d442adffd9e4c0d61def3df9787b24bc5b062507ea5e036ce1d86b46e78e8953168baee5990048da08c777f0b1dfd650c2e0a5b8cd923b63147af95393cb67bafb70768943d7aabd42877c238bbcfcda0c85842a053c6b1fb3f6b435e02bac08514eb9372a3e704a5bc0c22b5f672101894aebb7e75efcf20a0966e3856bbd47d148a7c13921082ade6e5219a2fc434245344d202cfe2dee127ca575d1f5c1ad97fa1b4447166c3c56549b12489e423d52494fbfdac246542d99e7ae3ce3936e4016a7f3ffeb7253cff9d86925a1fbc2545f45bbf0ec9480d3dc1036e6316a83598b905587202e618d1a9376a9324d8d4a29ae6889054bdd1fe3c2b6e309a241e15c1b0e30c28df86d311e4eba6b0799d1b0b495d97826b384263d6b86dfe6b96f0ec077aca1290b039cc6847a1d4696b16bbbf889e7d86e064cc611ec9a0de312f6db11bef055c29f62e7f26cf301ef2a6f3cc8f127a0fb8f43ecadb080e7015591309c4e2695969cfc8ff5d92fcc2d8e0c0b8aefcf83897dbd5fd5bc011ce72116926f99c00e71286870a6c3ac502cbffb2d26c194d8a4dc97d5de223b1a33f47d7196461e955e37dd521491110108843771a82c31129558847b03c655610957748590936898bfc3bc1f122db114d3c8594573e51ac8a119c258cdbd1fedd889f6f3a2a0718b43c5fcf9238a00a27a0767f92c5e0c42b6c1b87726f091e504479891bb46563b4c3a70bc57dfb41218c0995b5526558e66b8ed685d2d37242a46a219fd3863387321be89e4368ae5b4f36d2607528a2d135de2ac0807868113a4e736f668f422b9fe4c5ed229d36126c273d5067c064287fd78d1325127abecc4d4716897a395e3b232290f853b0f6446f1cf2d252008b1fafa2ca9fbe240bc862f9be60fe1d5413ad909c6770c7c6af70c9a1dbcfc9f11d116edc970ed9026d05a9948acfe28a5a33920c9de6be9f225ac2f27108d1990f0c6d7f4e804c7ec22de563ca8ef6c68e4427c9cff48129e8f4b7de9c08fa5aeda547cef71ae045b6cace887efb42062b9532629ed4cca36d2e8d6c4bf493b45d4420e8bb4907d745b34ea4357f8b372e360c7181b31c466f8a5b9c71f40505e3a29a1b9abdf6395c72776d0988c3654bd4d85835a8e3c2558a45d1b97e2bb2e6918473d505c8ba3fd1d3063360a263e5a4a8f90fbfe8d9be2c10874722bdda22254f44c1c1facf22b14f603659b2038a31981a9488e332eaf5e29aec8d4217d8d975ad9e5f6351872a1da390a64249fac2a3f096efdb807efd721a542dff22f7e84425b6b3ba8a1d15b5bac78456878a63dbc1e680aaba6ca213045df44f6a42a3a840c31bae6bce6ec6f627f7c223096e7ed5127a6c8ae60023a5fa5af01cf006d4a582a289f536e8b177211d67aa632a3658d45cd20897bba65b8393dc8d3c02db2ab9038b1e05ce2ba40231b6be7dc8e20472c7ed5600fbb3f2d84bc53ae31de840f2252cf06c42dd895c2ac8e666d1fcf263ead839252306734f46ead3cf2611b464f56f5cdaed35bc4c9f3512c35aba5cc3a0339aa0bc3f815a3915ff619ac1928715bdeb5e0501721d1dbd2a98ab8e7651ebed5d06003bdb55993dced404c2ab5bc4ce2095b3bf57fa66535f4419596a530168c8d478bb0c92828c2360793a4b495db6f49bdcfdf80529691f2e9994c731625a7d8bab9e52ba41832654c7734ba51f3855e83d537a6f35f5218ea2c6a979c44752a7b144b2f6b88ba3701cca4701cd74e3355118b0562e75ae52da71b9bd167178dc1e5c5b82baf10c4c3c412d5fe5476a1d3c89d857a5569c068e746e633105bac311689d775b7b510962f956b07410039a669b1858776a18eb82dc01415c8b7c55c22b964784e70298c9f60956d8019e05819f48314759046b0573970bb44d5d9ce9298fae47173220585070d166fc2953b5adf5a262e7385da562844df0e1e26200585795792eef7dc4925c05f66e745715235329571090b4e914c82e64bc01d12135a6f1fc186c078004b43f77116474e81a08cc4cc58be2ed8a01d2495ae153d4d352a567899fa43bf2401cf41c12537d0dbd7177785ae7bb0b6b9313c8e01548e6c5c82e5fc483c5e5b1d41e6d5f2cd96b636589b0fcaeb2c840b66ffea8e7792126f36236c2791650948311d06b59eb80436bf6476e7f21af85988a681310fe601e32183e689c9f16c1a4ae3cf21c0f102871509c97090f306f869c39be532d4fcd29aaef27809b9fa2c863a82c66b60fc4ee60d708a32bc0bc0849693c358fc831b862674c8cf34a95cc930e1cd67d69c05924de15ab4a845c88512a4b1d2d17be34037ad8963b926ddde70f530cbd79781a713798f3debbbe1bd78047885ce6a501ca766256f565c6a990b9b4470900ec310d8a9974a1b9c396669feea116ee4fa851ba8c7ee7a038a3bf0753e360be15e3f0c68645b168472d50cb67450a99e1b40cb739d89a9ccbcfcb3a9a7f83e1ee9b0bc8a1e9b89d91d009aaad652cf1fc41137e64519a0b20e45534eb50e4aa55a4bce7c331dbc4ac878988732abafc4f1f069520c3b8a609f6ccb1bfb02ff2e9d825af9ac56e65e18804751b58513959c40d233e6603cefce33ef52175bdc63db7ed39b83a987a832e343de4046564a04bff69673839d5c17037868a6e694059eba80fa67b8e88892d3b341f67e0c7173501312973370978e82f0806308e94de39d12cc2fad363316ca883c1111613bd66164d0ab69ec5d4044a035ccaf1efe93e3c7af6257a4094f832439a2f8035eb4e221020a48d5d59892ee4784d4f291598183204630a6a5f991911687b272c788591b98ac8d79c550bebef5741cc6e3fd5d653c725bc1b5d2c1df3f45e274bc32e1a39858ce4dd1f8d3fac6d665f1689c805fd7f0aff227d49f03ed668d06e5bca877bd22733f692e2b916c037fbf777dda2609f928b0d00acd706a1cfa0190aa55725f222ff658c709984090f32301bf0a12d61fd3cc20af8bfd061660888b70684c8d5a9444b52c17e5e7814a820b6b6531c084c9066fa4ada1cb5682dabd3fcbe183c6187db2f125ce1280569b5b3bc14acd9b3e81f360ea9432f59483e5e2cbbbb33ae8970bc0752c582dcd331efbd20a8a88166b41a4c9c88c44bb9b7bfcc1306878e9cf068b9d3d6aa8e2a2abaae0103930bb8e15c6613462351e57095d6e7e3a5135f8ce73273910c67c2d628e613b4e61b02149f2636099c055696772c0113a7ed7b110793ee6207b81672f24a8bfb5f61d9cceb05663255d223adc52cf486398f87a0a73082bc573c4d6747db91e201bb035bf3f68202284446ee024ceb923d78c001179806d4762fcf78414aaa625c7cb93479e6f8c8ce9498fe234a3d6750a060923010cd5e1ffe1cf6c49d422d855fff5513d5af35617261def9ebcc80e1aa14bafd8ecaa3739fa1cf93dbbdb1552a941a4482d635218a17d52e4518789c06feed9de58938ebd453d8c4f576464dedd7f07b31dd84b708769a8636fa1da2219604239a8353e608854ccdc3d85b93343595695aec1b53b18f2e589b21a57b640450a895c35ccb6e09736a4b57052723d66bc4e796db03ab728fca24a27c54f77d05f29a60c6f2a97379b8e3aa6a4809cf3d332712a2b62c914d70e4b8b54a447f1330450b294d5539d1dc90d081c66d18c101ab1b7d040db49133213a52f53344550935c19ca588af28d82cf53ab21c2c88b0ae4bb035d191a3d36cde19fccc392a9048e485a7ba70fcea6e88df1a24f87875a65b462873cfe3c0108dd996c6038afbf2761a7128358c1c20473058603e03c291a44a7c8100a0f8219c3f764c3ac4575a5ceb77aca4ee30bb75993020ec571c39305e386008fc60e44e8be871e208752ae30402129a79763aa5c7aa57f1316f84f6d320807423f0380b4d5dad4433c73c9f573fb3a4b02d59151f1b92c4cd45020bec810eb7f3d3c435b2efcb5717093bcbc3757971923e44711508111dee22bb00161db4c2032c3c1e4a7d217d32b97119a5c658b5d6f5396a528acf05044084553c2da778c9910f5e401d51bd94170fa9918910ef7cd996549f39e2d1dbd00548a4be0e2e40743608b76cc27a52e776d2b8cc90ce648c0698c7a8d19c295d3c3b5d0289a2a9b16053a1a422b4225316ef8ad8544902ece6443eeb3306474b446a22fa001a3563a4510193cce1f796d725e06626be1d348290611376a963da54a2052f271b050d5834fef3873a77a7f1a252f4418fd8c6c27de3e709ee78d03a33de3eed1dd3e601cd40978740f60f61d62e8a4cfa7ceed0b3dc7338ab1a02c0e780fcfd13a7650cba929667cce79d91822e49793298e07e43b254f127685d06f133c7f1dc7540dc9a49521324d270559e97a15ed2ad4d18f1cd39319f4780a81af654e8966e13ce786eeb4c5e972b2454db28c456b1f401968b4e27982d658882d6a5ccfd5e492ddefc685327afb7806831c7cfde8c1f484e65c8c70a8d362e491939d3dba495b700d9a393dd02df3196959bc1b759f730cf9dafec21f9824ca596ec3ced4d519d3923910b9fd984dc06e7e234915aa08de82d034a92ae4f385102926e9a127c81db2bfe89b4cd6525ddbfdcfdcd654f46875d4a4fa689c0022d82e0aa565e044ab42ed377de35679b4db44b750302504ae71318f62a140cfab0a76c9e6828ef5419e78cac0fed133f88047ffa0a19e2a68ec222ea9e58596bcf2b5b82091f56b408561baaec36af2b06d9897e424276687fc08c12da1c8c5882b86b4d171f6d6a2ef8695a28f5098803fb44e4c386c53b0037386f075853eb0612a23ff7002223a20264982fb4eb6e996e22f28de1665f11f0e48648e5f6b60d044d6cc8783cdff5602f3114720ee54ce754485544c9d555b873895b65019ce2eb9dc160e67bcc9be5204a547c74ac320d7cf92bb7864c92660da95c27dccbb9881daca2f2bce27c2435ec7c4df47e557c567b836e6a9ab3bc59c96d4030b24a82c927f3e537d68161c9790adfb0d371c40845177440c59d4acb96d3cbbe7cb3d20cd96958838a3ed1cae43dec956da7fa71e45d0a0c2cbcbb92a1a8d8b9238578a8e3466ce21b0a6633bb6b1acd59bf9d1c035a80bfa5d62be32c04ca6025060a46f77898328f8082ce6e1eb9c8bf5148f4a78e67b6c460066d1716d786c8edc5d1f0810c7fa7cb0991ad34a10e4b5d6ac6fb617aa28d94eafe9bcd8b71c8563624285232e5123f5d8bcbb4320f7a89f0f6cdfc2df73a811ec3b9b7d43cd098bd34fb04bc20a936988a6f8f675499d222690d87880af070391a6c99e53b1577708a9b13fcfba1d46d77d862b2178f8fcacc2e6e763aa254da9cd388f552e4942645b216bfc49bbaf3a1aa23a2e8285c6618f4e57b1544bddae8e61e00d7e297b793fcb92737af43bdda169820e2aef8c591085a1019d675ac2f8f034e18b3b21e0808189bbeec24fe7009ce5ddbecd217cdcabcf470a3b2c741218a14b4385e2513f83c2b8ea726644b6b77a3c19fb0283d284f628db534384dfd232b009ca167bc2cf2e67e151e0ab441abb2ef12ed654a6b80e9caaffeefa9f7788ba8d9389fd4769a326918a782cb38da845d49a598f1aa4bb07e65c73556ee56ae22cc2579f6ba5ed81b69efd589db699d621f569db64855b487ed2978d0cfea40295d04642adee689766a198ad055b792aca6d9ee6076bf42c2da5a034a0f0e2d3ef2ddf00092631d5a86b37c39bb4e84733c6fc0617052e85072e5f145d3acd2e78e5eb46a1502d1803918143435f7ab05cb01ab2cefe4141394018e41a6aac43aa0ac04699299ce1a3f5892d13c88ecad4f626740c78219e49714af60a25eb4f8e9abac9e4ce4c2a9e1e3c264cd1da94427393689cf0a48823ee0c31e6592bc3515a7a32be827adfe4e555d900b09f6bc1c7a7e32b759da607be7df3bb27fe55c736750788c3bf04fb34864e2b1930993bd30771413e5f819d0cbd55822c60029adc92109893198cc8b1e26662768f79e4cc9b31590e29a8484bccf18a0f919ad940bbf5db0ecd47a91100d07d070462ae63b6796b74d0d7a2078d16d2f1c9d9f4522031ab503b0e60b170d180c14c889e663b7f09c7501a9288040933caa6e4c29046bb043f3b60dc5980545dd1421288377a36acc64acb9b4c80fdc65a1cdae09eb5e9d0c4e3f8dbee91349af99436f8f26e310fe293a98d3be97b4c17aaae5bd54357eaf05aaaf90d8ca50d0063f99eb06deb902b0796ed49950645bf52395ad1c3d19ecb937029e31237580f0d341399fedf8454266b031e356191d651a27ec0c7c7b56ca30e27f7adf5802ea03f7372b7f33a5b443d8cf2946bf56bdcf0db210c9301bb1292f1bddeb74742c55a452f6e40b07a6a492ac3fe0ad2e4050a8d94296f3af379af0d1d98d0c5d1db9d808bad68670fe854f1a5413f4b87e9832d368f0d84ef625113a77f892e1de961e1318420d9078ac0d7a7ea0d8300031d68bbb65c852b58f8085bdc2783d1fcc15570323fe3bf6aacebc00699408b9a04259224dddf8410eb12d67c18bdac9fd558d7c3caf512730ea73b40e84f6e69c7d1c81c63d5683f0422f54aaf6d3019628a7dfa88255f830118fae90ae82e44ba5aa1ff45aea3e28ab00ce016a11aff6efc3b7afd255e49dfd297bb778812070f3f75a962dbeb15f034e369cd764156bf745f9e8a42f3c08084db3e8599ab6974ab492466eca922eb12638489168255a49f3b6359bb37946619602b420d205f938ca877c9db14137c58e26850aa91601d5f88fa5cd774b4a2a829d558af2e281348720245a86b92c8260580124824991520439a44904605d976914594661d134545e5496cc7a3a2b135d67f0dd07ab7ac9103560fec80f27bcd525c42b74c9ffafd765f0719707ecc31075554cf5ff8d04a34ae5ff35c3c89dfc8ee6f56f06c063d615b5922036ff367aca707dff9dde389a9f14f52149da429cef9a451965f1c9aa392ad19d7a323bedc9a2e5d71ac7b3d9bc3f67ada226cbc78d547900f06d782183c79e56df7555c6f4a19e89ebbd698ff84068ccb17f22145285fd1a10a7bb79b1bbd61f30b0c9d5ecbf82527bea38d3f513e33c4f4e22a60dd751256300fa68ba4a16c1e63b70f020f6e50b29fceaf3726c500d08c1e6b1d24cbc89251a2a27225c7d70bd3e598b1801c23c931e399326e2bff1866a9c0ef425d9c1e30e42e4a4d2d64085ef540f1161c55ce8c426105eec051282b6bcf9b0c41d22639bec39d6939faef376925d7efa3bdfbb4d88eca9f2cd5f9a65281477f9a5b92d86043512525f310f65ef1dc0b41252529b38260b3a52ddcf03c9fd80a5ce29b4506ddc4348637d8cea171abbdc08965b3267840857c5b778ab27acacfea83cc4254515c833647b4ae1dc92e6bea865135e6e420613722000284720e40f621b33430436abb86a2eb50da2fff9d4a614502011777052180fa432b5f2a5f184de745ddd2120254dcd1f36d60b4292527a4097838d97548e0f561b0fffaabd04998f12dc53840a4609b82e11eaebd3fd9a2308cc5d6384fb37bb1095e0cb16ab6ec7140b9a52dff4e8a47dabadb82388a6c0b4f7e7bc34e2a3b8d78397d7af403eaf9a023aef56e81ebd4e05a1db3f46b962ec2eadac6b2b60a5b96195ff3e3b86256046cd60929f8a2ce0595e604924b51642f37183bc2f5bde3a9be3df69125a252d003c8b47550fb24bec993e0001e699e77f1430d2032236fa5ffcfc5154b98f9e5e7a3f6970ac7a987998986bb998fe3a07cb81834bbc54255c849c65a60dad8f4bb892215e8c40df460d6eeccd27ac454cbb647b58a190ae68dcba894a514ab62b32de27ae50c5271918b0c6be4b6514bcc8608652be101cf4b5301a2fce907fe293a48c35c271c47c7922faf7518cf791823d94fb2fd48a5c1e3ae37e03a68161396524b07a0f399bec4c7a4a012dbb66c6b5ba30a97455c3ef0ec58a8472680c6809508dc8280bfc91b712261c4532213e8a8005ec24ba8d037dd2bce82976ee55262f34504a63204f967997d3b942b7d707f7b520e005c356f36365eb8294ff70580ad16a739141f02481c1cc8903f68c5286532c5afd6f2e90a89751a462838efe58479dc2953e78be86230f52ce0c4e4f6f00bf936279b34fb5e376ce38e5f917086b5f0218614177681d06e8e92040ecb25588edbeabd37e33caa038e2c220b68b44de6c20b7b2944073f75b28b89e9afb87b94b40b482c806fad85e943c0923168ae0874d7c700ab652a84312e86a1d3fd7aa71215d936cb907dce7e04e1127e7327655349d52b955fb2c02e0ee05375aeaf3102964f09c39c4131677c61ae82a3aa34483a1122fa9bf76126c1e204892f59d434b243126f3a72854c9de0f4203165149c40a3e4a1f1ec01ae5d24a963d71659c465230241bd950e858d1a521320dd756ba19d5c8722bb97bd6e77e10233595bdf138170c7ac086294d1b50e26d43e941d71071c98445a226280a2aebf3e20159df55f2f1be84361c20b33594174a2c9d0d5b02c72c6f0c85db82f7b098d5b14f94cc2fb21ec08ac5a125beaa4fe3718dd50419f25e086c094f32d960bcda35b4d660b65ee40289c0082d935023cb9e3b54bc5f298fbae11f50c684f6438316fbd61831704b1c73f277f1aae3c4223564c28ab3ebeaf920ca22cc0f25b2eab2e766c38c7a412014ca3f83eaf922319f41da4949d7f64b112bc2c98a3138ac4473123727d5f19cb404e51f37f7f6d0e67318ab57190d6543d8bce8ed58cbd948cbae69a2ac327a5fc7d186e211c4f68861575d2c5494def03a3d40d7ce572528ac358dbcb4a1fcca8a06fae76fc032af58caff811644e9453f3e017fad5afd216afc071a2bf2e017ac999ccabdf8fd746fb07eff4010f2426afec40bd611cc320d6caf4b188eabfaacb541fda84b7fc3cbc160d2e14462b478b88fdf2a3b2b2c03c00edb347700fdacae8995f48256015b0bfaf8714348d49c09f82261a2fa2ae3c928e20c00fdc6e9e36681ed639c0eb2e41774b70f2f848b418d024222396d8ba73f6d7352d9892995e5a5aa02e72ac296f45a2bfebe15da2788fae66a87837e4eaed426f597cad7dd37ec3bd4414aa9c1755f0f979dcbc656b91f1fce2ecf21518283501dd5b9ab7a8f32fb8842c73cda997b966b158a4a2587a2b42c24b504b03a9fd3c61e4cf22f1d104513623420f6580eb990c07c7b8af2e30ca232e495fe54c75679add6305d4faba4a7d0d09d5ce417594ef2597a841f9538d0f6b2cc166379e1e43f9f218b43669ec7192a0a585a3d0ae672cf404dcbb61823d95f1dc4cf5b4a7a9ce18b94399b6ae3e78cbe7999059043e156c477647659a2d32f90636eee1fac7f034932971c8aa1caac514be89da0d742aa82601c639ba8c4f6edaedcb608170d7c61c0ef26785285daef46161081d3847a1f9e6e9795c627b2c4c668f68f18e60b041677372ec5a5dda0146ef009700c3b818b07273eda915996ee85f7fca0ef4d5aa28123d4f0c005e484a0164dde2af3c7ebfab6dd8ddcfe5eea6227153783c460d6b92a834ba3c6d6b27ca691c7872c66646645102c34a50e3a156fc8c4920bab3429b61c3e97b4f04e8b37f40ae0d7ca67b86096a6b901ebfc1c98ad3a9f54c55cd251f8570ad46e4a45ad18af11656b9909408f500650e2a03042e0720535f2a1c2fce4b5a6875e2a199a1b81c96cbb301e0b00f4ccd91b1f6e82e5b4e24a25c41459e229394c0e67f24be7c8096106f215c66452683b30d8bae84a7cc02668df1f0779ac7475db5762f9e727b19bfb8ad3923b8a0af282b7ac7a24df7ca8fe87864c1f2a05367c9036b9f05f56bf054021ed7b1b4b476db8a1cdb9a3a10e1a718c44f5b10afd6828d639fdee38887fde2d593c22ec4e55d95be13eb5e488ec2c70b30e3edf81ca00af387c76bcc6afb941024e6181a5f9ed452b6031f60746de145b10b00414028b1c7db5fda4656420e2f53cb335dcb85e82e7a344e73b706df98deb2dd8f308dcb396eaa6d2496d2bc7fa59895b5aa451072677e0448e26e7f8440e4cc481c90e98d8b1c9383281c389383c993b604cecd864a1529d7005e853f251edeb6f0e570655e04d054d1c4fc0f1c91c328103133a32b143137160128727717c728e4ce0c0c4c0817d72684c39909cda9363853a1fdf7d3e0d116a8fc5d8febfefeb25e296cb1f54293ee0faaf4163a283bf8e4b69f6b0746c3db1cb88deedf0bc045559b2e2bc53ddec5db60c88d0c5b2cdc513ab981872e73f9ea0328fb44e6e11c13c2ca7de60848bdaac4474930bcf643f602457225cb182c1d423c2ea847bd2879845f90007963d0a392cbb7f1d46b2f9630e87de071fc82a3eeb4685ed03518c81de3c243bc2bbb68d3048d4c9c01d20e6a7f4601b255598add12ecbfe68d6a095aa1afbf644718e673d565e42b4ee4938f4b4d4e120eaed875108ca8e5dd5882788e8a63d555d5ad73926df6ed43f67fef3dee782039d862743d175001464cf207a7dd260470e854150e1474a0371e693a9ea78f88c08501b3bcda563d7167e4a78236f5fe15106c744adc98bdfdf89835d6fc6aca0900f675b6a084746cf6fc086bad8f2c258fc2f89d61e11a180d5c1c2f9188952842923bafa39a0e878bd768412571a0dfc01e0a791719ad752b9c0bd05050661ff7e616c123727deced793a49eb45424b3426d49000ab7a2eb0e625bbf1bd87abc23b9cd2976feaf65f2261010f35c199c9560427ce05c1f3ba0f8fbd503f79e62dd428d3f367cdec0f326ecbbfec3d9bc6bc3ee4da1bd43b45274ccbe5a92b528b15a37184738f67b640e8016fc8b883ba61bc3195e2e2a1e0b0c1bd12eecd7a38914343f25a4dbd74711274d04090aaf6f4bc0e71255c66374f1a91e1912db89b3087db9bfbb8bc3035a724566584aa6a66f55f0b74e107d1274bd391ec75a1ce2f4b3997f50fbec0325b9d575f0f3fd879d8355f52944b8970f686f21d9f59cf977b4b754e256574a4aa870f591eab9c23b627f93cb8b1955bda4e0d5011a5aac8ef7206c139f3d436d12be1803126120e02ab4c28e0b28274b74b761a1f96ea39ee0bb074c28a249774b52a45f68468fc49d0cc205400e8e35f5613d2393536cf05fc59ac9b5a664b74e886e0a2fe415b5e3724a94eed7a2c73b055f7681d37564ae511cb2162395cf5c1d22989438a8838890cc433f076f4160c0c4905f3ffa3350fb3b93f06d4e75fb201752baa838b398f16d1374fe2f7a9f4ef3ca3353e8833a3378b33b0afb783a78f0df69b454cdbe0ce1308bf4801070e56cc2d3049b2b4bebf9033f024b41a7e956302a7a8934e02da67dbeaa33fef52b5c28da0a36428a51c4082a5168300b2c1efe7e5646efcb76f0afd8babdd39e8db86ec1aa82cbbe1a541c64a51de61ddf68a0438f38a831dbe26e0480564a3b771f5ec4d868cc4c80db2783287281a45260bf7bd5959b6581d40bab8fc85b845697732c5ef14fd5a04cb4418da2dd63be1185fe1bc3115abfa1113c376092d1b563674805a4143314f00cd8afc9cff18601fd72210825ecf08320426236a2a3e189bbe41460bea0afcaa64fc91277cd7cb0fbe37b1f8dba4ecfe5e2e3ea7e31863cacc916bc0dcae3586ec46e25bac652b30781383a0802e53e0803790881be7ae033e88f5fc9bfbb8a1de575746140968133d90d16f670e240543a3958035397a2739611328ae18a859a7d0cee167878de63ffbd4401635de8efbf3e1d9bba22539afdd5c12b90a2a241a8d52721944b986925f2f8fbf4d746185caf654b96d5986852656b101e775fb568e21566e19277a8a8f2243df6a2d82ddfd90f7e4239dd18b213116f635e1e069d7545d128bf6a5af0b561674f83bd2bf03a3f3375a1890c7642e46e01590c292026b6115b21a2c3865488c5a8832be0cbaf49b01a93d8fb41bde3176564b49ce33eea00424b290c90993bad89764ec473fdfb2f0e7562716c36b69e07cb1c573698abe08fec7526778b02069dc5940d2218f77526196ef0c537ead101b881295e1870724c756663c2224225aa4e3c21c12d1ba566f9106c1b57f9205f80e4c8dadc76b72d44fb5630fc9967f854f9a44f5f541c12431a90e06965c545a9aec1fe9d3dac961662a1656884f57ceed7d5d4aaa103c078fbcda5328a353b76a1ec9c48a6fd630b816bf731ac2834f332f37897565cb2a5e8ad940f7e7aaf44488107515fe7970543aa1debd72c113c98e6a97b2bfbe6f3747f84f490741103cf705ec80c340be10aa3763ac3f0514035780e7073a68b21f54f5c5dfa42a518f03d17a90d2fab3ce138bec8dae19780f961d2018331558dff98512fa13d4528f1722488ab0e95913ed4620b60b3030055962217ecd046d2bd570470b20820936d10702fe2ecc0e3eea3319297c6bc62c3898b1f6dc4a699b0dc4af14974c35eaef53fc9994fb40e9f987c69b96421529697ddfff98c89b54542f57f7ec64828676e1155d009a36a25019f5d3d0c41a45c39d6e7a594299a36a2d705ddd5b07a2569e09a081e98ae12df1a4e87cea7e9edc52513713cfeed35b4880b5fda16fd003ea72b5168b590cf5fc1ea64a2a5fab143377f94b0101b59b8a81871772cf934e790b0101456139da6d5f76c00cd648a8de584f68d36aaf2b5d52d7a88a77bc351f3e8e38981bffccee9568d71548da2a4329cc8f4850b5889bb36ff79854b3d1e2223b846544ac6c7f8169170bb9286ea2d7b350ef7e8caec257bac528ba8ee9f92f595b887859ebe327859bbe48ae33f775cf2d864beac7baf07614bf9f0d6b0e5501526c4c93df256c08ff4f25df63288cd4235f3dd0d9f4f5aef8c61cc7ce3b9514dd9f786a305a4c2d77c9a1145851270b0331c4bf75d444caac87b509b6016ca47241e24580ee2b00685c96330803201d1cc8ab4caae9b41057c8165694953e3fb47d4cc3612dacdeb152344d7b0ed30dd299d697159837f2c23eb1ad6c3f9de9aa07fd9ad6b5eff19b2cf0b3927d422d293fb9ff7e8b896dbcc021f23a3313b29ac9014a00d0af8ff9279df3551b8de82b271634da42e04119cd63c1db2e634e28f1c66053c7f13be2f483120930196d10f4ebd9c08fd9c5d2552ac6d70046e2eb53077f76e2f237babc122e829611ca68a7d7654f010e089ba3435a99f9bc165650c21b69371c338c9d116bb3c6a5d3d781e78083c9c4bff67d065ba86e4ca0d1ce487534bb728971557376fe7df048653e43924eeb205fa39d519844110a8679d27ca6d4ae04b54be023fcb8b0b1af16c3b6d3157a741a0fc34760f6bf6893a424f23e8228d3e125815ca4b02f24bdf6cb2136803c931d675a36aa286b0ba507bd19d332106c2aa2441c3a90d43458c4ad1a4cf7e6975b5778295f5831ef90066e11aa95a5910d7a32d1ff87781fe69155fccb60ffbfd8ab5b6d9e0878cea17ff5c54c3c3dcb77ab5ad89cd9d8687dc5fdb30328d615eeab03bca186f29963acc7aefa2787fabd4a17aaeb037f480c4eeb1739d8f408b47aaa61f5822e7034830f8e29676e9bc9ab6626285cb4c3d378ba18b48c60cde3522c78c2f73c07bd633cb2ed5a0dba48e82c49308a19650dc12896ab219522067a8135b8e10ede4f03da2668e9e104e4d127cd0042452b7842ff576ce27a0b1943c3181a104588b2472aa0661fe6beec6e9c513cbe5208350b2f283219cc80be1019e39f4efaeba959cd2e312d4e252674a0346e9160eda40ba7378fee76e092624b71074eeace31ac8af36106068ca565f3154be18bc8628b5564d195062d459e2d5ad0ac89e8cee45bb8c5df18beae207a33418e67b460e5d24616c4066cb19fdef87b62ca40e241ba80ea470abd5daaf373b9207553734017c847f0d1b052cab2d7bb5f9733b0e838f74b208008c7b61f5280d64605e06ec8c7eb441df97ba44ddb5f685c31e1324cd1c9d035dfbfa4a8188943c3e06e21b0ad01962ef1fb6b9a617684d24bb07c7879f317b9cfa218867c2f43c96e8f5b4b4bd8b3e641b24fa89cabae89bfe9e0f3d502b969812e03827d18666ce5bc0715f7c5ae41d816c6fd07de1ac7fa60b67f4114ebd576eef4ee3959afa8eacc1f72081bbdaa533afc1cf1aef3b6f93f091e7f1b242844ca8b9f807b1d29374847c7919e6eff348bd9f4b48c560b5b2ba2b71c7b39a4f33606dcc3e41a411062ede4429ba0cc95c087aa0b954aa95c9fa3fc3ea483f7949e84dba77abec3e623927b1bb5f32148a2c1d7438d1b4ba4876b14325b07ea282de50a3b2411e05c419cc430e23394c3f0e67de26f6821f9479c97fdad005626a92b6a7ff02fc0f201fb6438a4e3e2c069ea613f2636d3cd0bd41845308330dc6d4badfcb56770cee5147284dc6a16026f7c4e3edac8fb53db4e4040c8a330ec35fc2f77764b02e2923eb4cd02095d31d1cc261c417275e7fc07780cf31e9bb69c80e94111988ac6d7e06c61b06cfeb488daa73263c1974a3850dcb8ea617c7d2d648d5dda4a524428035fe58550102553f3928fcb0bfc708a6d9c31a6b9fa54130883c7e1f51f9ef2997dbbf8604dd8d29788d80e245e7b33b0475839672f4a23bf0b49cb72fc230e2ed1be4d762d166fa8c9e937273e09886e53200ce1de87344658bb9d8a0dc6b106d32efdccec21c849bdf542d208b86d872a77f5bce5881595474593812503c5f04dedb192eeb3f45967ace7cbf5883515c1eb01efa68131a59b7695b87cff3b1618b3fc2d5b38dc7c8387f77a2a2462a7a74a9060d7166bde295b5f5b69afc2f93c0eee891b259dd3bdb4a0dc842ec3383b13059d3f8595d5acb547df942699ff8ef6d3a66696633bd53936075b60d1e07eba4164cb39ec90eb4e01d4730a5aa536308d2a9d8814e037dd190b21d1a9fa48139c28459cae0d88e7c4f486a8825e04399569a72e27ae81acc90bb562a9e6962d6a1d2c00a287e4d9e8dec4fd9aa5f0a02b4faec14d520b14d42a481e972af4eb6d3643bdb972268ee8887f1f69ad26c57c226f8ecd52968e103718b5fe50d48a0f00af6ed66fea0b8c507d05f472c44d5f4f3696cee150ddc0737a56158fb37319cb364dc1867f607dc9c8e35e53813ecd2c5dfd8754ae81bdb254f98c6e66888cef1ce242cc54f3f7eb6dd76446ad6ff240a7a4e88060a7e78d6db92b2c2e086123f47acc9bf1b6afee9c3e66a3c0951e07829f8ec0fc809b843102ac50908ed8f59f09d84788e9a0df36c8a6e4b863b8a9c34a558cb9e8332141a806bf58e28a0b3d57bc269fd79c1b86dd9c12598aa81d024ea7d357669d6140f5e56da6153b2d2d7430bb20d944b62c32ca7f24bfec195bc5194bc7e937c342c29e0ca0a393ad3a2655b1de5f2d68ebcb7eb7e50ea1c50a1911eb499e44935916956073f5d822201a6217836bd8ec0adc0f75b49550083371738cad1cd9f68db9035ad76a606992863ecc2e37beea2ca5290d61e645e20a463630af1326291a800fead801d4ff618c96e25655038d7174b4d976f4f83173bb2e84bef895fff16da24e80a087239b186e6b1225780aead3f82a37840880519438bd3ab630ef7950a778d5fdfe3855e6ab90f897be3cb8a731712e4a18f83c48669c8a77c88e7f90c4df4ae61f4b21178beea74e018c0b5ece0f3cfed5f4b185e41cb00cff773bd6eeef9f20c419e948129cfd701aa6b6dfa85f49a89649243b1024f5332bc0f1e1a84b57cd11ea2b91aafee0c360ea1dc16b61563b6a391fc031a1a4518d3bf4891e1df6b7841abeceeece8a352c645c8e4f6ac2c53bba3863c146b47b14542f8e6b42d01a50553b73effb312c4d7ec851d6e0784f122be5aea4b51fb147dfcad48f5e4a2dc154da5ea05506bae737c7a3b2332a8437ce1540fb2da2076d0f42094e3229007f4fe1e9dd56b7e0c1826e17cc16e4ac01501359e26eac149708976cdb2190cbfbff3cd89e1b60973c5f2d1857ceb2d6202b4343c73729e629616e03c5db017252e7d7809b507772b023e22be02b4b327c58677729875771c08876dde3bf38fbc4f0679a87a7c3d402b4d004bc16a0eebf6be24d919a3b268d832c6424474a1740491a392b2a430a269ffa65cc29146edc57ef86522f18c4fc860e007fcbf7497ccb4813f334de3e7a2879980e14f04486cdc836aef2a58e60058357559f5b2524172ee4f47d832cd455d35da6ca2902bee21a81423992198117fb410fd528b18f5910843d832ffc07563f963796012e158f2e2c0165b3173dfe7eae916840d6cdf055b46a35513e505120fd028f0eb62c54368514db065e01540b5461590bb338c07c20ba888ac432046b5c1512f037c040832a6c70bb27474e007f321120e3cd20038c4988d72120ddd10aef9a99f02f44e037a711e7c5a30561aa503a90a9580a5116159218c30c9668aa02ccdbbff5d7f7f1e1eb91a10b5a34d889b37e5961ef6be729cebf3739f9fce2b7f1d532ffc0e506761df2b4784aeaf7cdece5e388635f65bc9932609d972ef2de59652a694025e07dc07af07393efb58b3caf5bda47f798c33fdc5c154eebb69822659a1c924b520f0f6a340868d5f7164fc1ab953f7cdf045efe56fa8b9dd32c897afe1d2c1e5d0d7e32c67e2b61c1c4dcd0dd76306072764e38870315c04dc03c235384e5f18d3cbbfa1360e505eb2e6a6c7cd8f1e32c73daf57eec9ec71a8b503e29efc15e4fa56186b1d07becbcb7fe13ed2574d7b084b903335d14a9a0bc717d6fa2e96a4d50aa3c653bb1715d4dee49ea4d1b8cd3dc91aec6c6df611ec02491757b67c5283cc16363eb4d2073587d354c9648a60e39762962864e1c718e1c7679a088279cd39e79501c3fad30982abbfecfbe4deb5b9775d177dec334ec60ba6b944c04551941a683ddc28b53a8e35dc93f6d4741fb55fcd8defddb70d9129b2352bd9f08894107a8c314229a5942ea5e46225a594524a29a5942fa594524a29a57c4c286a2ce31a4aa2d7e7ea30081cbdc3918fb838a75fa391cf0829a5304e1883fdfedacdf5ad5dea16023240d6a5bfee4f5f6ada5f5c7b778f4a2ed53518e01d5dd7e81a5da3eb1a8d32381a8de2e821e7d7e81a8da6c6638dbe35ffe93fe98bbf929b75f70eda67ced970bddb90c3bcd6f375ed59cb615eadb3e17abe3cdf0d5d341af1bd62f0ae3f0a52ea2c8b564b8301deebb3d9fdf02f1aaa05e987f0f21b6aa0c67339d548a3d1779b9a8caed1f540d77f2f43c01bbae8c2f787b02d8dc7bb1715ecec613f672ae3c8edeeb80d0cfbd1c4f76afaa7eb21a8172d8c091ad3918c6964aad8fef8c539e79c486410098f0bb91b2d31ba1006e740e6913bfd70284170e14bd845d94d05c3909eb9e8e92857727f16a40450137777771237c451f285e0a001fd7eea5ecf397f4ecb6ad96d75136bb6f5f1a755d2a7091057a6845020253a08f613209228d94e3e2d04a2e48fbebff23486c40337d060d11fbd7c0b54ae02354480062172f603cd59837b72d608b827b3e62695eeeeb6acffe1341431d1da4da885d18b520a530f6031b80c1aac2ec6a7d2ab91432b5adf266907c53d48ad5d118929dbab8fa889600a0747c15f117d9cc513823f1b6721f22885d816d6ffabe9e00f719c56b9173b18f87637712f5a409274ffdc9c88c0d40e8c8adf73238c3fdc8bd30419d3c477874d89b817f9524b765e0ff194dd220b27e1c6ae9e179f7c7744dc8b57770046c58fdff6592fc382625bf410b6898f2d11b5210c258bf4b88542becef1c93dd86deed1c79e69c5aad8f9168cff55192d2c6cd275168460a1532c86b43872499787a830b95c3a65c99284244408253a11313250a8c02c422af1e5f2298be5efd5958196112353458c4c152f2724bc9c90f07369abbe5517f2cf851a0c3157c60acb41622eb38d8c1556757f78abaaf45c9acb4344a872a15cbe7ce3cb27a4ac79603f7a3fc22e631c397802857104d96fbb3ab416a4abb0f08415b21fbddb8576ab9e32127b8af0a75d54c506fa3af48dd64febe3253f07d29d577c195f4a09a5577d69bf0df2758091be65037d1ad6990f1f05d68934625a02fc63e63546ff684dfe7e693cdeec96842c47f1b386d3f296a338130315fae1c9b51e7e1357e7b29415f4dc2c56fec832b295dd26230b52d82f5e69437cd699ef2f59077e0ea41bb904580f5fca0f4a5ceb73e886d22baea758b5a6a648f358dee5e78f05203b330319be37033b19bc2b3bcfbd7eefc6dbb0866dda4ab3fb9423b78aa0ba8ee4f28d5142a8e3fa7ff04618d985d3c7aeabb8d77dbbe86960f6bd0c7fe1bf673938f8b243c8419eecc5975c16a3cc435921843e17428c35584575e7cbfab0e2c40d5e5861027aa0bf5ba3aed768177a4bf3700db2977de5267bd95f5cc65e466254b6257bffec69966935462c62185fa805f99bc99a717d2be73d46dcf3ef22482dc73ed364e8b1320eebb29edc57f7c9ffbe8b7aae7badc940bab16b2beeb5d085cd108e3e10dc990f6849644cf3694057c63c5b968c25d31a4f0cf35b15ba5cbe91e9f81f9ed1eda9c653e39e0c72c3f4d90bfbcb64b33a57ca4c268d4707cc73e97df42f5cdfd128d5a3db4762b8be7d02c681c179f96f43fd6757f88fb2f0f1332add3b1cae31e7fc989898ffe13326a68b46620fdf6bb5caf1f2e5b72dc7af5657137e05452330beddb8565713f412ba9ecc2d530b8effe8c53dbd52f8bf9e5e38ae0bc7cf5c38baafc8c5f1f4495cf4d178705c17d0a5c4f51fe94929fc93ae8b54d2782ed22c9a457ead48a35974411969079089c1bd9b91c1fd228a4666d1e9b313177be01a5e34e271708d53177b60665134523fd378e01aeec93fc59c62604adc060303030303b3fd45b46d5fe2b6ebc9093f8b1ca7f4f2a7952be86ac271605efe25040303c3c52bc395b8ed9debbb6d303030251a120c151450d8ecddf1ec3b7694627ecebccc74cf7dd6953d9511a140245f32a298ce06ff979fdd9751992fa57fe1a87ba5dfb8afded297b8d2bf702afc3c71f1c2358c6425ce3fd378aa0a25eeab77723dfd81608a855fe1adce249f058e1965fa1538d3a338e66be25c3e866f0a28d09c308baefc1c7de46bdb7133cf7d2e9fc10a351e1d3ab89a23acc32c538af9928f382e86fbfac6fc0bf7d5705f4631a58fe18adc172e06d13c4a2fc37d5ee596ac7bf5a32e5c9b38bea3d1a84a95f39d1d6758eb3f9844b28b0b0d465c49c23af3e943258e039fbe6b611d7f5702a7a0188ca27fc5155a68e18517573e6f7229f50e5e611bbaa30cdbff41d5a5df41945abb6d41117a1d22cba0e4f4c8f1d12420a25285c4344388ccc035393437274833d273461de7e55d5efed321ba7ce6f585fb5ebe5d3c964ccd954c36d08f2e6f451c6e2c75ec9e0bf7dddcfe9651ced9c4a5ff16f7f56c259a4777eba079f45f3b740ef35a3f2d28eb5b9cf61606be357e267f76f6935e94c4d9405fce9701fed79ff1e4af880ef1ca991c6060ff7efdd33ffe0de4df419cea81e50569f080871ed060b2e3df429c2ae2c4128c6cf961e3046140d9f1a79ea487e05a3583a3fcdf61de8d10ade1be5db752c5fdb4fbb5763f5e75118cf26fae9bb04d11b45cfec1e5212b546e567db04466609dbefe0ce054ca05508c104415569871c68e7f635dffb8e71f9386fde8756f2bd3bfc8dd810521d8212b2b8b16b92dfbc54951544c85b3602a39d6602af7cae2667f7367a749b11f1771513315d55bf73c0912db541eec77ba4eba4e730326749bd4f1265bdd0bb4cfb5c1fa6b3ebdd6cfc9137f72f4b22643fb7083d4ee86f6b99c65cdd7d163e7ff80f40298d0a58c3d2674abcfbd3efb2fcebfbeb5202fdcd9512cecd748846eede663205add05dae7c6ee064ce8c28e66ab25b78a94294d58a2869233765c0927e82282112d00869224d028821a4c6841240228d7e5892853fa0a5beee888285f55e1f250193fb7d240ca16ab35a5d75c1e3283c9b59787acb0004671775f8107292220c10d58c0060db43c498211b885086210049225ce102aa3abe984ba3c5446943bba3c64c587fbd108c51f641c89b03109cb4255308e64d851e4159a0673744b91e35035d88b1fa3482b77022561ffd2d5fdae1e8ca85de88f8f51c13afc44df055fc036f19b83499a477ca98229d2c71c4d4ad52755a40eaa36fbb0f4fc1faf483f579c2a75974b673b7e6624ec8fd078ee7732ac27c17e12098b84ab07a67807769fedeedbdecbb9dfd5d356ee5f1fc29d40a3eecbd1baef06eb3e0f5eddb76550d573e3bb1a56285e3d37fe0482df04b2fd37371dff08cb1782f1831b3f0281810476fd6cdb4c53163a61a3396defdbc93deac3116a8ca0053fe8a10102a668230a1430c8d2032176fc0c2443130910e8c927754279707db4e37e9a371ba5d9b070dfde63a3cafd6e5457c82cd0a037dbac26777797a207d5f5b9e3eedfc3fd4f8fc575971d77ca8619d73ffa537febbff93f1b585c7f1aef2687abe9147379888d27d808e37e3442d650f754d2a452ca385b88492d19bb27320108d7af3ff5b74fe3f9dfb809aeff0f266071fd8108f127e24fc31013b8c091d7df02fe38388ea7a02705d6bb3cc4841adcd2e5212600713f1a216b054d4f26bbb5bbbba58223d0a0c7ea082f380212cc068923f848253663c3b2228bfcc18e2e0f61f9220558b268030b105a80050a09050b12588478a1b19c6031415cc3d63682a045f2604d45160bb06062eb14510d9bf5e00a7be5808c199466922063054bd87879888c1484800c1e7e8ca106260384857e08714f8b31b2584d2ce9f2d0185e8c314533b5612b111b4c5869587b79680c1cf4300610d609c6f0218b16356cbd92039b5d1e12638b1f3156d6c59022c3e69bac1c428c24ac88a112c2deb83c24860f605c692372614d9787ae9091041725b8620936e6f2d01526b0b0309787aed440a661b5cb43575c0064c80f21574a70fdfaf661a871b3cb435750703fefb665428a4201268a92cca0881e0051e16624000621d881114c1c4186169913d215df43601cf14360d8e07e345b3073c48e5cd73591b44f97e0481f21a3e88b3ab8c4620cc04d00e66422cbed1e18502c6209d7d26c4919a125a5841042087d28426802e16b6e7ae4d4121c3982390eadd875bd76bd0e15c33eece3c41eebbfbeaf5a67b8b09f015c6e60bf7f67a1f8039310d69d35c8365e86fd6c8416c6f93a6810c208e3c338e38c2283c1faf9ec9e47fea847e45add3dc8228c708c08231c23c208c7883104d05dae2093b0a1840dc990b0a1840dc990b0a1840dc99012427b46fc289334dfdcb43b919543c938fdf13f5274cf3baa05c162fbbf18b3eb91a7d5991ce5fd1fe9ba4b66f66b0465802f7f4691318df4778fbfb872722fdafa03fbf96821f1e3fbd8dc8bdfee4da024d912c4944b257e4114a38611c152e102a1cb5424b972732e53e1029fef062e827d291d3da55997c3bc30bb34ed31edebc38b6a3c5a47b5ab52c85d1a86611a4f0e7dc1c0172a7114ccb07c2537467f91cf174197878a92380a2e0f15fddc8c351e192bd67fcbe5a12e54f7eb14dc7e96e2f2501740176a3c3244b0eec2fd3d2e6ad82fdea6f39f26cb481faded4cee596bbbef86ffe111429767175bdd6bd2f6343d727cc818c1f66da0a046428f6430c28e31462432192b5fc87461d93de9efab298ef33994cb507c8a945042d94e9a6892ea298e925f93036b6e7a64373f7ab8276b7280c81835ac76771df588fbba625ac36f4ce3815dbb6364a8d99306c3ea4282fd384baa7bf93b741c3bea8b5906bb697dca9a56eb3707bf6a9cc603617da805a92fbb90d53d094d26d3c33cfcc77a76fcfff0aac30e9855faca35a415fe0eeaf295eb3b6b75a92ef523c72e35c28f5fa716047e8db376736a3c2ead09996f03bdb88ae32d77e3336e7b1227f339b8986faee78f48a40bd334d205b520337f7a6839bed7d78fd125c63b5d2c6663b5d7ccea67f1ad7d18e3d4784edf1afca9f1e8f8a8e18003d6f5eae32c5c8e9f1ce95d8321445893e924d43dda13b6b20ecdbe3ed14dcefd713f0dc4005d971d87db20ca35222c931f305583432e62a1203cae057a60fb3f2ecab971cf99f4c022643ab00d0170d51cd85cbeb931af5973f93966e1f2b783405ab52a61bb2661bb56246c3fd7236c7f05ca50b8fca156ddc33632509875684627f454236c7f7562dba532ebfce51cdbc35170cb4169c7efb81feac2b08ba26efbb86792e2a552cc54c58b298709e6043313536b11325ba530456f3c44614cb65a9bdca8cc3a32b5e260a6d61bd8aefc598e5a6da0a3d69f1db512f1b5d680ab95065dad439c50eb0c6850a8cc3af5b2f71cea3a0a75dd70eabababe7256abd57792ca0485142af51b039442e54c855a9778a84aab7b42a06a55ad50ab102cd42a839a5a636053ab120b001ecee3e6a632ebdcdcac6f505c43bbeee99931c3662d54669d9bcb9fb570c3030036352cac80f2544801059a133aee77e8c8719ac171639389b919b1e5316a6040f1428801718c31c66da354fe5f29e52525fdc227ca872f3bf85272f771607519e8c6af2c904097bf6377c44ab09a1412e007284865d5c8c11fd58fea474523b597527628a9799e35af16d8c6b51bb6f1bf89a74bdb946c5408fbf951fda8e04f77b18dbfdfac351e4a755c2246f963444cf4438fb01f4624861036c515405a04792174fd1d7618d112b6d95dd8c6eda537f0662c8e22f40c83d2181447f96344572c46744d97b3e9eda3158686c4e8252515c2b2629c73cee85984d6cc9a0a21b9c65e6258ec8b524abbfb24605d41d6c3191fce97b26bb6f1d9490883b0ce4e40029251e7a237503e2e486e5c9c923d10056db7949665598e41cbc25a56f76260650f4c613e10e54f690ff4e1813f13a4af8e8bf9cc89f94ccc67623e2748e0af15c6fdb0297c600ab301a3fc8f40c283241783e2baffd482e8b8b4c37ed8c69fc403eb6c23ff87c3ef8f5cbc19f5e61947b16b10d02887f084603fec07fb8129a972d549092b49405813b2ff1db299999963944ce98438cd5ea4b76512b6a375ad23643508db1075b90671fa22b6fc611b7e8f6dd883e058cd82829200c2ae1690a87e905c1d658c9351ae2c801c471225c138b28a2098924c906d045d12891ed18c7259749d88225104511a55c27eb24812b97f12360aa72e99c56f4d3659334a1f2281294672dd6a6b85407a214692325468fc145529b2a47b634597127166d8c4322719768351f2fa8f0457f02a5d79810ba9631970f6e43b072ea418e664c268599605e1378c5c44f914e3df5c32c19eff1765907bf2c712608a242dfcb00482222593b446c408edaece6a44509905a3fc6590e3c8956482716410d893423025c372059dd4ddd5703b86bfddc5955b1ca216835dc51d6e8c81aee27b8c5166c129fa7ed385a71141a335821d43c8edd9e4745c99c4659209dcf8dc8d1dc72eee27cbb8fe1f01aecb2b18e5af85ca8b9feb528c203aeeece4aac8f67f7285adbcfb9abbd317b69fa3e4640fdb30842f849eeb1f25cf03c83081cbdd68c3257b58473ec7362e06faeab87daa629b4e669d1d53b3640f6b3068552e0662951672cf9b7095765db503fb4123385f07419f0a5cf8488cf8932b5b6657d3a92f0f852174672e0f85b1c5d52e0f85b1124266011b19079b8db68cb6dc54126cb19b6984c6688be64425413581bc89f952476f7ca9b310653def989ebe7ca0f4f679076eb98103fb4d34df7b38c5694851e54a0e825a2083239c2ad24406416c100d21c18a1f76664cccc7741f8899018707661ec74b37d300d3cb9b4c6fea3e204bddcc0c325ffa52e781ed65bec80eeff0cefc184e0a41d4fc176e8607fb7596f949ee7c21987af9f99208a6244c411d7ffe8b5dc840f7a0ea0149133b9fafbc5f6721da72e73714c7d9712713f1d082298e93e3ce6f2a57eefc2490049a324875e797ba2510193172e7b716c77118e47593a9fb176edb62e30653a56ea601a57ff997ee03464630db68a38d9d22e81be961db317d0f393b2f5f924960aaf459aef7211c67baca71fcce1d45f37b4bafa1eaf1d4ccce7cf769e2cef7233c850f0aee9c53f8d0e4a67c677ebc88a6f0a1573065a4881e7ea70847620145764affc32590e3309108d6b8f3a512f34b4e44e9b3186ea60131ab6ec61fc63cefdce0661a70e3611ea6fb40a40251f36f7433de29c077603ea6834510351f5e81a8f9bc43546f70bc13c3f1ce8e24d8cf8bd64c671f47c7d717d9b9ba991962fe464c37033b22625ea6a31015bfc88e77d667311ca4e20320ad623898b7380fa660962d77c69e3b1fa6832b889a0f04db2a986a22889affbf6dd6329c26b0d05e0a77380cc468456acdbf381decb52611db4c8bdb91c51269238da4fde5e24272712159cb22619665599645fa2b87be3035e7bb7050897bf32d0e22813ef0887bf3471c040226218229a882a8f944314bf77dd0dd80ee843f77be774477dafbc155abc10398ffc231b7f0751b7796bace025193eb34eefcded23ce6571f6b3d5fa6995891cc636a402deb7b5eccccccf2bbbb999d27f63c99db85ada78a37849762a988e2f2f7129da2371045bf93b412c75145a00e621d1eb0ce7ca65a10ac8b446c43dfb988254ec136f42b57c4028aec442abae318de173f841ba540facd4520f7e86b5c148228fa161783dca31fb9a8847bf425172f2efeb847ff863e7d865175a947f8de51cdbd4a25010d621b98f21d6e2bed427750d53c8cc03ade412637b8f4e14f0b807e6b0bf01da88228fa012a50419440d8df3677e7c1091f3811c5856540225b15a682e252c5271a9393296a4b3495268426032d0656cc39e98561179d5a34251a0cca9873d2eba2d38a275ab4682f9853a5b9404ba2b5400b4263810684b6024d05da0f1a923927bdb076a2a5a03b061a0ab413684734136825d0a2a5bbb5bc2cd13cba65efa83015dc814fb493222ba03c8f4e564c500b0d275425a5941da78cdf137e431aa394314668754e5834ca0bce48b1aa695a96695a96d5aa69d9a8564d6bb6f1ceaeebbaea37f3887d357bf2d60edcebfbaaddd7b716c1ae2ed2e812026b4629a52c82a552a9668e6545a5526d4e4481061a4476a6ca52edac6408a6a8542a1863e00221f438050b081972bb3b3b31250934e21429cdccdc748a142a95cac90f970a5ac618dd63749732c6d952ced9b13dd9133a74cbb2dc925105515a965445158458d068277ce0845a4e4461d1796159b59c5c77832815a682e25215693e73766b3e589665c16ed91db51e341e3423da0834115831299df4c2b08b4e2d5a08b49e39e72c63523ae975d169c59c4fe6d432a79636e65435818d35d448038d2d4c58821226a5935e1876d1a905c2767246770ccc28234b129000001e736ae17133a7969b39b5b4203d660905c0b2e72b4c395a5238423f1ca7617c282693c934002210e54fab356da7a7b9e94104a6dac767e5b3f259f9ac7c563e2b209f68468fcbd0db3603f8201a32a44a048800012140b66ddb3603f8f0de043797fff43491566bda785cf22b8c5fb98c9f4cf723b4772364c284490a342f9c60aa7509f63bd5eb3333acc33b70f76f7284fe69a0f2549eca53792aff3d4c0509fc020b3f79f2e4090bf17f9a9335f1939ba3448992ed2ac101ee0053d3c753ad52a25232c4143b74e4b8fc34acd335aeac359d36eba7cdf33c2843aa90e1870f20ac0363849e673deb05c18b2a6ef7eee699783ad1133d4115c8380e4ce3d0c33a10cbfdbc5403a1e43a10eef977ffb6a9bc042ff754ba6cf50bde4d0e4cd5afe2c3870bad9f0fdf4e3f8008611d1ad9720f515ed43d45ed73e379710ac779018b6de8a3c685174e261dc721c0e58f648c21c6953032015cae898e1380510b462802006a5c5e28d940a9a9a9a9b959d10b739c9acb5f6362c1b4c2e5af415951010cc741e10b2f1ca72bea828b2daa1061088e83e3f24fa9a9a9a9a9b959d5d4d4d4dc709c4d8b182a59d87e1602165378581ea4cbef382f8c6e8f9a9a1ac779e1e5091a7fd8b65d676ffc608f38ce05a59431c236620594d753e466304a1a637c2963941623639afe012405496425bb7794ffb792af61d030601dbe3d0d89c014a5d66edbbf67f7d9c6a7b01d51e0355a7252937b17f529db85071a259b5391f106e6a416764dcb92921b2283fc19c48507b882254b966c399200c5eeeeeefed1dd971321ef00513fecd0759f7d2f76425baeaba26c0182418c52e292254b6284505ca225458ea02b8d1d3952089921436eed00d2df7bd0fcc3a74fa5c425c418a31573249941c29ccff91c29b2c7932c63648e1c3bc2680474294a8071c9922543dc8827ae9f955a56b2f91065b426a5135a10ded835c3174008e36645b86d34343992d8cf4473bf9717d6d1996d751c6157f79e461e36402184d18ad03262be653d9dd3f26a9866f36882b03498122b82ac6fdcc214cc698151dee366d53d35f828eaa9412e894b2c14824bbe1d1279ad52a2b4acee2ba4c53a352d5c0480e2063dc2f6ecbe38b6f17f7a83551420542b6c7f85a28daa1891ac35a735e975d169f5a05661fb2b15a517cbb2ac2b5e4cd69cd6a4745a432618cbea8602136359dd67c4c85856f7193253dcc061594b88ea90edff81144f7c10051455c8f6d7275250c19ad39af4bae8b47aa08217a311d47382851a1da7092696a83cb0fd35e8a605cbea3ea385005856f71901e86ecbea3e4300500001882e7382e6b153b9ed7dc7a5c089d0c80a28af4785bab1656b2d95d1c2941048f44c64718042fd3718052485cb7fe2940520e740ef26803d17c619e29e47c0515e2502bc8607d4e8000dcd9e8772c0c5355f576ae0ba91a38cb20918e22f650c1c84d0218410366723296514acd3dda8d1384e36eac630ecbbadc6b0efb6463deac6b0efae3dfae158ed9a6d1c043dfa2c566df43ad0eb3dd7d2be9947f440d4628817d334ed2decad975a0c3201f18e3ea3d2a125e3280778471a57311a65a494abed330bdcdeabf19410cf78e0438d07bb80f8905d4e8ecb4e0890e92e064cc9e7cb4f798328f8bd822de6e6c25ccb29f8de9db6d3c9c7e9ba0b2eb00ef711bdfa72b8eb1fc7719c0b77f17bfeddb1cde1a21f4288ecd0b923630dfe945abb6dff9de4f33a899015d67f257be86f5e3114d7e507c2a969d100e1ecda88d5b5914e822308b6610d303575c8ba8d683c461ce708eb441861033171b14310829f41ca9c85b03f6ed6b2beadee1eefdf43c8fed3a71f833010eff7edec500334ee39738da73961a9e9abb9431ce57f4343cee98485fd184bcec764d8c03a2c3f7eccc9f99ccfc9c9920506624386971f5eee3e0d5cfebc1af7bc1bf670cf9f3b6f3bbd75b9eec228d7529edb487db88f20aca8c836c7b99a9f5c97ade929208ef29fdb8d2704888fd8e5e4ac3c886b5a10c26e87b0db216c87b0bbdda56b31c81b6f8caf03bd3e33e0b0e37477b7dcdd2d77cb2d17b4657dcf67cf514eb3411493186197c1ddee848d261c9afb58d8cf52c981cfb5a613eb58911b12654cf3ddc448a262f97f406982b38bee59dd660aa016a8c46c59c982d2a9190000000800b315000020100a854302c168384f8445fb14800e749a446e589a0ac4510ea32888829031c810420800001863c00c0d0d7500df8bce59666d3925beec4bdb61a882495d7b3d5b5feb92e6d87a05c7cc9fa58032cedac95aadbd0cfce0590aee1c2c92fddaf236845abb1dad30ebe52b560848c4f6075651dfec7c3a99c252da8f457865956cdb837bac491542dcd95290378d3a9acdf43c97d3a001f03ac91839e47e07586d3ad5ed54b5ad2897562a1123fa1a37a49e6455f386daf0eacf5855fba783739d262f060a595439a234261021296861451e04daefa21c511eab9089b2225ccdbea13dc90a8fae39ab35140946d94a12409e580c14e25678a11750cdec6d4e73353cabe5a084c4d01293c81a5913ae26cbc690e86c2b7bd54716ae8a48f5f0aef77779f2c65d2d6585980cbfd9bebb3cc76bce626865418e15aa337bd1ce7d8193a4e6acf58cd9599c01d82d6183d3c150804e462fe2a6d6bad3d131e64e6440ad05b0e1a5b716b22b33979edca2c724f096adfb59deb41b04e360eb6e56c4980a810fabda1f97bf28a18aa41b38a5e646c75a89e2d58964008374125ba7c42116ee8572585d58f86796e86202411e089cddcb53d30213095bef61320875bfd3ed39ec1eef0eccc3e5b2a1f9d5c4d6aed23b61916c9a8ef836e28c5b8967a782088308d907ce422c519b21e9df8958036f12cba9c59ae7c0c525b572bc8b388e7aae011aca1f32652b177a55b108a2cd0fd93231e273c8a907cc906a132dc6969f5a3e88e487ef58a01e6af1b548c556cf7f37ccbbb1c7d6c951435c4538a23c13debfd833a2b84a23a843fec7528a42e9d194adb81c9fdf3a656a34974342d91ae04ea2f401b9c749ab512cb3d5c110f1d1bbf8f996317c3e1ccedc80f2ff60a9f676a52f74ebcdb315fd4b20df7bcf950cfc56c9ad80e7d9a2bc09bdc6abbe554119c8dd61e823cf319c330abd870f8b0025a32d465c6e82371e308a4ccefeba75c6be1b373dd62a568faf68ee63eae04e30f64b9bd22023dd58ee7099655b527d7a5ac2110e72ae3403e6c27dec612e706c3a6adc250d95b699d9a62d439bffdf15038b81af1af4c66d8b090f1bf4062693081c8d59cc5aa57fa8400c47feadcb619327785bf9ea582df026b0fb10eb73104a29c694835b1509650adde9625cd28ad611f30ef82eaed571730b52cd42b43ec03da250130516cef125dc758f91e6e9859e3cb72fc9fa7234ce9c579d091cf4ef0b5533881d514d3f61a93a8fd82d1be7d45f3cd161d281ba75da5596179e4e26d52f3140eb53955345d5ce8a09b1a6e151751e978299ac060f1f834d885b9a873db9395cda458a2883a9293050e0f1e015883395f1ea273bdddc86fa93b50ed9a12f083ad5cb37939653d4ad454fabbe5a008e42da81df0953dc29bb0579a320c29c44c77885d9a72f791a40ccbb95ad121138b4d97d24ea52305cb160142c4477169c8c918c3fda78eb06e2feac2e1e0090f6255774467ccc4583a5fedb9fb8a80fb48790bc3df94c864b4bdc5e6955ec4775fd2dbbd59aa29b69bb8f58b7819ba2b6ac65d41ab227fe07bd95d94b1b459b2a59ce02b919e44507eac3ec671296025045634e140e501a033048189642402569f19fd854722154191444495ab343328940a561161226080cee6643320901e14240837d096c5ab031201d68e20806282661298014146644e10065b160394c97189e55f12fe3bd3490cbf0436f95b50f28364121574d3e8865a837228b65a3d3cd4a9cd05a229259f458baf656ec5c2d662bf4e58673b79d4e1931318f79bc107f6d210fd1c4504c5ca549b32e075e62e3ceb0a3bdca8b24c19ba77b1471130ed28f7a875b6d3595cbe560fbd4359df1a4418ad0c2d392500efbc2fba72edb511cbab6c20bb6d5760123ca5e9b63eca280894a799d1f098df86605e61cd7ff941fd464de4566f5be4c5e33afc3d1e0b47863960b58f3448635c968b7922d39cbbf861f377fbd8fed9633f405e1d3a02c50bee1624cbbd6f11212b11ac80a1a75d728d8666f72edd9670cc4968e14d023eac1a3cd8ae36d3e5703a5584e863e3cff8460db7b002a1e417ed3fa3dc0b897b642bc834f4955e495fd6ef5459f3963a4341e08b7edeb06f0059bd586c9a1260873bc0652f4111be85c8c348f9763bf57c43892d180a396a2387179dc4bccdf071456915cb1c5caf07daf7ee0d07e43ca47ec325f2d63fcc1dc9a6f794acfdb0ff970224aa5fd87f73bf8bc529c236085c3d620077b64469ef7e88a02690a4e69a68d07a27943f2555bca43e4fb12da5c4ea135de13c961592d61b7225576a59c18fa18fff74e10ca7a1202f330994cbc53637b81cdb425c281be4cd98e15e88042073b9749a44e092999fa85199660c0b781153a2b1b237b5e1f4a4cbf8e53700a140bb3695ff66e1dad75e82a5a4e2eee916d37b0a01e4bdee07ae1246d57bd983e324cb566231bc35f6ed5865784ef6786590ff8b640a03a600cf92ea60185bd4e6351e515b0a324605e198823185d4b740eca76618489c3e5ca03f39daf7e806f541e2915882db52b8c49c51088b79dcf0edc042b71efaeb809f6851e877417e7543840b84e96066aad5009bf15800b4371776132bdd7406f1adbff2cdc112501e1c0336e41e40a00a06a7cbd5f2597e9287c838b1ed571f6c009c69f1d2237e1a5c4b3e0ddbce784d5c2eaf27e85d9a49c5fac2c51fafc707a2eee9ea153888ddf3db71eb702aed4c0af2c345f80a4da68d28d2a93b748b8b0e39657414c34c6355544c8aa9a24f3437d302aa3287d91dfd8b04d3d9091b61ed60894247691626985ba12cd4fb8c30e4e40026c840b8edf0a3d2abd064d74af90dd55b7f036231a228c2be054af556b20acd452e79751b7ad60f15688d9567516ecab901de4c7403e564f71fde157a77917506d65df77fb1efb6f99229e1b8eea8f417af436c9ee31761ccba2a50b56d361716a8753eccc2cfb2f663b76d485ed4d0e53f758021a307ea3aca82523b6aea911e71c992766b3b1a706e808b869299f65485779da779278bffab47bccd252d722a22a3991309fb6173570d9b00353784c97599d7299fe9c843cbb64d3c842762b97af4c7dae709a29da723585e996c85e898f686335d8a660aec4f8052c09fcc72a631c5a896ab1daedb67e2b370c361639c134726ed068226c6c18cde866316e2da664b08cab186f56f253017206a9309d367fde72f336a2cf5fc72884da0373721136e278b328cacb4e4b5120c6e651916c09e8b57189652b0b51abb83a79866a71cc3e560e597ad9ebb9523049719cfb3ae504bd4138de32ab41eb07dd09df2dd938bcddb8d5fb23b94ae3a8e3376dccfcc7328ceae7b70630932235594bb055dc2f9d80210c130bd2f6783ae8e3e1ad50149823a09e242e72b28914fe74f6223775555bb58149fbf37388ac048b10c3c5b8512ca8f14f2f1190ab0d8cd66474620e8c7b0d1dc540a5f2894469a5955256e68d9846fb8317b0cb823cc5023bc8bae204463375b8bad5f65b295f082b415c71b5d5190b0f1c2f72d86000bd19ea73a0a6b685393ffcc2a0591bf6fabf55cb948fc11b6cdea0359a832b019e0d1e5dd51efeb3ecd3a4c4a691ec4575898866a3fb341c2d975fa03bcd46535938d2ec75c7980821f21322f56976e52f3199040a496f32706ed12762ec9403d5d26b0172ae222dbba47c01d46191e560417836524d4070b7e92b841dd33d7eb25fe0797d6fe4724a0e2aaf017e7a19c061d83a10501a70793d69bfb3413fa7f7bc1eacafe68eb7eb582ea548cd914351e206eb2807e0d12b176d14dac2d138661c808d924d69acef0fbb389206ff2a68118b22ce62828d1d996c3b45f0764306990d1736549d896bc602fae33ee986054e581587fd909968ce88efcff7843b28d19f81c001d64b1ad426e1ec835b30b062cc6a004a54481e566b62251d6c5f3f32436862584e83b118b211f7f59126469b57d6855381c0df8b0d1bc001dd538d775eb29f903972e44626336a7af6c25ca52dcb031ca846bbbeb945f40ef5c89886a6b4718c297c517bac8aa46bb490494db4ce03384969f56809b6a09c4e0cf4fd085a24f6ded21fbdda5992456c036980e9f3124a7c936cb58540059f9610585949f314ec0fbb504f962b4d8b04da4c558f9403188f638061a2ccedb1c13693bcb87edb1763e44a9a43a783180cb7478e074a26f31454db232d3333e75374e1922fdb89fec018eb15ef0ab656e74267954a287e0f7af4d8236fbff318f4cf6475ee2b05621c51044affee1c61e36f42518993453c1380546ad4e60c61c478b2629d52ec9f37b612863763a2bd00321c8ce457e9f1db819a72611060c4cc7c6295d00f82042d143d8dc91d7f1384cd92c27e4f0ab2ae4f47097c4d5b5b5782758b11b041ea5f503d92b4b3c62dd232e6abbb0e1f345089a09bf4c1fef180a2523e87329458b2b8e232a5eed931f3b7837d9a0c1f7cddb42838eaf101a4574f0b88c70e85582d30d18f281ac15e2c2d8e85aa7e1cf7bc1911c4b41fd8ec469a75194e73b5f5aa27637347e2ddd851fd06b00bdf7d6d7cb7eca58f2d39014b613493ca7804af003450331cdf602f560422baf552de549db94278eb0331411ed60eff778859463a8e02c509005c39a4f428e4ce8b7c836d3abdb5dc513d3e4831358948d87d1da433c797228edb11fde841d48bb719b2fef0fac87561c20440ab583c7b182ca7af72c75fd16cbdfd9afcb5b5070b325df8b53a546a4663b72d0f34cc368d2fac44b7b3d9c13ff3ddca943c704f85d16ce1ea4eb9d29b81c282835f3451c14e44403b6c30008bcb9f315c0426d00bc39a27f8ba31a6f51b638c422b3c2825bdc00f44ac00c384bbf1afe800f5856853a58871a4619a6534d6c749e71dc2f3c7067f599540f5378e194a11376915baf6637aae982e82c342bec86fda37228dfdf6d2c15257bd5217dbef2204f3eb920abecf12be9bc1bbdae17714fa89978901ddc137187408fafafc6f33f408cf0b26bd0b1d400a280590568082591cb80653350dfa3b98030d57fb498e4f247d0f7a7eca8fbf17f77dde4928ed700bb825e0074e318e735e7b9f05e27bcf5a93a0ba1fcc657e253bd1de95e593f10837cad747fab29d8ef8a78f5e3ac485c7d4752b863c5a1ee23332a50ec9b1d2757a73c5a614afbf7863ddfe3af4266e281fd0bedb96fdd64c49286c7b6caf046341cb4160f7b0decc65f0e5ec7230fa492a4a3c8cab2ed2d481e76cdfc7bc72045906c5d4673025b7be087e73c668104642a02d7ae41c4216dc0f2ebc3d51d4987709533bb0b367f1475be60494781cb772b0458e310723ce63eefc6ebeb91634a2bba8f123980d2c6db0ca4109ffaca531f241ed4d24a2c14a5e7800c32f2e95ef2ed20be3b22fda4b2e070cc01c23cfd3d8d2bcaad6743bf0a52dd1dc5575f00e715966ef08484f8c645104a9149845c5014a2122b3359a9bca65add513a32d059360ccb23a8eb9974b0e288dc3b38b94c155562cc62e09469e322baaae20327195a9aae0fa394b7de4d9cb4b908bd25613a04556352ed71eddbb109a191546219af3bcd89eb8d452142ee8998bca5194e3714c5b2f07e4bb8729872b320edcebe5a20f3f773dde833f083c49cc4a8eef25455b2f013635bfb14e446072285ba570058209af6c2a8505a115079761a076ec5080390fe5796f6b5128aff6683f6e3887556b58cb6f595a40743cf1edc97e6a7d400cd5a95a1aacf5b6f8d1abe2515facaba8340ed96061faa5e10f835e42f58a0e2ea5dadd2b3ec43f495a20239405e5610c391c63a82d0824a676b9a0bf3805c361b33399beeaedebf56016e3d2aa52e3c1c9c25ff45539745590987b2863fbc721f80ebcbc2eb2fe61417e57410068cbce7eedae9d270ac27f94e50fc38c2c7133ae5e20f0ee336a5e08c004849b836cfbe05c0294d97eddac5a5198ac4bd9af1195a7f7f8f5b32315a6bbe05e2f90d93ba571f6dd349cd65eaedd0be7697ca63004eeec984e05ee8e92d02158e3415211b33b58b2d177e6df99f5ed923fe29da4cba43d248b9991f31a02b6532d81fa9bcd2ca6f1e048dd8acf4a8d93dbe207ac41abfeccb0d1b4f806ae1934609c9aca7a2e65101c518d669dbeea815d9867d7ce3d2f8d7b9b1992523c8d9cc99b55697ff11bc7aff5e15171bf99a5cc4bda22950c0fac7d309e226c75340fa6cb27885332bda871c18c063e60c77772d0a48d2656e26925e9a7c96670483bb51d512337d1abf54c5174ecefe326b170fe4ffd52672b7b277b6b4f23ebccbc8a45af8c06dd58efbdd43962956f72a73c71444fc90b8b980e9160b0aee7aa97aef85a1345025b14b954ebce1207b5268093cab7b4599ad9d0d18deebf61e7b985814a980945f0634167ffdcb29b0811ee347c1bd97d1d3dcba2ebfc8ec1d381248394522865ac4f81de7fce2ceae862e0787e56841e34c78d043669571c60966d1a35a6aaba046bd12bf4177a5be44e0fa4937c5cc8f312809e6b2d257f01b3ade17d9b3d84a82bae6b5bb02f222d0d635bee248a51478a088b3358a6b6bdeb243706910eb874fd1a108250b796919f3ed910df6d2f47a3bfed78556b68681da7cf57391e69e6af1a639b35bda20dc0542e0fa0b514da40a59006691bf155112652f166df45c48637e74426de6e7c45280052d2b2e362249e8298279323545e36d0b0e5be62135f3671f538b58b6bcb67a8b9ed839a245a31907e8b8dc3748790f71cac31942c2517968c9d3c205beb67ef90a77c1eebd762feb165b114f032b338731f4b0fd4a8d82a75a1c179a07e2ba0143ebbb17a0cc62db5567f44d491d141f66310656d703e03cd4046b71e211b32a80038a16227d4e1f1397451168112a93f13b4f250e05100a7f8ffd919c76a884cf8458bf580e7f1e11fe6061b7c80ad8089721df7effef5eef89b565fa1ea2e22a5f712a1cc9e1bdb658f1614377341d30db9459b28a1179d3ee5ccd4354110697b47bdba69131bf7c99e1b1baad37b460fe0647542ca68066d0b69940d913a3d41daf86353f0de3386251c74237e5cb5a43d62069cf82c3bdda506ff1e04c5248d47b10b730e7dfa7d082733229f486e2762031689056c6e78511244c415a4e1879d1bd353f090d167a1462efc2d3aa18a5bdae5319392f351110c5898613b46fa56be63f70b892b9c4aa3d84085c496039e55772d7573a42b0c8bfc4be2bd4f53c12223bd4c50b2923c1a64e6f504e42498bc935da72d628494bb0c966969eb236cd2956c6ea975bfa49a75a26018cd2f1ad21000d2666a094491102062d5fdc45026ab0a86ac391e483b12d12fe4a933ccdbaa6ff2c96b2feb738b4c229713feef6209f5fddccf3d06df1bbc970b3bf99b340e9e7d0251c76ba1281d5069a907242302ada53ee5318f01a7aa04eb70da5907afff7c6387c0c1281ee2de6739efd41a0566ebcf81d163eff968b285048518d8db96357b67678c55a1e36b8e3b75efabf00f3efe08cf9c3a7659bd68b9575751e8c2500aee182b0c06c58086f10352462234709c30bfd2a21205216ec0a52f71b87c7482306a476d0b092dc02b348750beeccf13650c16d314cd6a351a346335121e86820ef1f30434a3278a83b7fd296a2c81ad97a44c54c1ecf227ac40386051696b386e07eda59480ef9af929194b1b7cad31170b80f9aef82fbd28cc8d323e98876db3380d19e691289b9fbba8f3b96295d778a8c9289f34881cf426d301ffc9e7fd338c6d8c39dae3a82c43afa3d36735f68ad1aeaf15b023640f90e778146cd1321fee8e0a833cd69a628bd8b7842f09acf202409b6a44e858b5a522cac0b32794df77788c2b89f7ddedc3f6c1cb6561f1d65ed7ca88d5c2e1e42e9d5ab65a0409c1f16e9d40ec98c8cebb03787fb629bdb12c589f0a87ba780600d593ed073ed863c72ae40fd41b7be77d0ff67b5161afbf544eba53882e10434875a6a00842c5cd0db840f3aa85b7b76e7f942f9a05eaee574d3b4bcd32214cb4cac880e3ff748d05bd28f9b8a369e4baf2127677478459200dbb727965d85ae2aa3fec080a3d66315ea8fc368ec8df10a4f28d19c0701369b65ce1f7164968297be17295401a579fcd79a4e99755f10527d1032e2557789f90c0d614d934ffecc4c7e44ea5e7db1ab08145ac352dbc07dadd4a8abbf6c535af5f93b3f194e0b308c3f598a72f502ae35a4dcc286dc913fa3d20b0a5dc66c81ebd65086e6d8b97026dafd2ddcb89095c9fba6de0ec5dd2ec70d17530640505dabb9f8104b2d5a6ac29b85f6b6d686fef2943ceca0adfd5dd9571ce82361de15ab04b106ee5871c636babf52feb26cc87728941ce59f3c8e5afa49279bfb65baeb7b60373527134b588d0ef5092179a3a457c660e2163b1b23219523e0db27a104f0cb218cac50b6a75da84a3ffafb0c2c6b5a6426cf3abf2d632e72ee4db2815b25999081c43bed4c88838851040605215ca8b61da3adee43e9a0997146bdda202641f47972319dbfd97900a2c2fbe7b72eb192f19a13338690750f538236518c483b2b5aa450cb215f4465f26641d53939081414e1c3041e0b24813a8401cf9a6d1ddcd67882de7213abe5cbfba3acd51a823f0411ca92047bde1f1cfd2d5fa665b90f5f9daea1b9f3037dce3d98cce5a3b43ab3d93ec821988e70cead33f5b220cfeca428faa40ed984e7374458e28747b1b851164f7ee0e95cab4735a2e97ec6bdcc34621336871341936213db5c9bf5916dac78e6ff0a3d39193508cebc6ca77160877c6c56de27be33e4d59373d5f90e03185338bc520292168e145e9bed753de9e9581c8328a91430bc51ca9820d39753163b8e7964288edead7e1da3c97f7885d6492e35387a65ac77ed808644b2627d0a6174e04db3633eeff0e66bb55cf17691e0a5ae61cd4dd8f9ab18bd47f6b89e9b493886c4883b20a64cf0142cd7d0dd08f1cf7d45e4b08131d00e9d439dc6ebcb6d12effbec49cfd2ef2559dc27acb03a1966d051aa03641634bbd305d99e9960b91ca84b2d5ae03f469c3823acc9d4d22574ebce18c4d7e75871a1b0a086a01fd1adaa1e898d300180c48d546f3adf4eb427b94de81acb05e6281691a4f28817cff453720140ec47f8f76f9c673620c15e1e3c9bb0881d34e88421bd327f8eb1ea45974684a7563ee98bbea88f8dd9935d9510f4593e8d0640cbf19aaa0d5e2a5c9f0bc6ade5beb871147d68ddf7069249b51259d1f372b9d33464eef08837a6e2b08d0ce9fb86b25c7df4f0e20b843b07d23d80136674a992bcd6bce5750340ab95e900d4a46e676e23225c5fe2206ecba54a7de77b2e45856d92e6058a5908652427138feeb63b304268bf63758ba87fc2d794f6e3aa6a5ab511f91ee49eb1897f5ef474fc2105a9f86ab04ed76ba22ea326f8ea315ccb93099454c23877e16e7832e43b2a6e2427cf7d44cb363e8fa3606d93b1d0c3244f9c6b840d982515a76abd211219fbdfb757c7ed2c7cf5231f30df17b2b1bde3a3d7d1a4266e175e284f5728e00af697f09fa737a0a5a0e40808f82aa9f13c3a70275f91780a4e73b9279a182ad06dc2dfd30a2325b2a3f375add650a143df8dfe299a60109d2454031e0dc4e11f3a66742f0e8149ea812623c2682dfa2caf0131a1c12867b585188501069219b556c49b97f97c6f2468eed0703121e17b8583f0e6339c852b21896894120d356613cd510c9770ec2523d08b52e247f85699ffea76cb00bb0abef821ea776c82b7cec4240c30d0ca39dba74a3419d9ee1076d5263ee07dd827fee1981ae774b5ce94158a06143806079f0c02c2a38a04eb9996b1134d89a222e2da7e8a70734eb9878bb7b9b3f422b62ccc1773d67bfcf3170377103b1d53cc472db12eb1bbaafdeaa92b2e5674b0c21ea69d445df3847122984890671ecbbd37cc17796b4b39f8345bb3ed87a86afb7a59f2221aa0b7a6219ca6ee810f04b44cf44b9c09d3e3bcb80f44388bcf1ab067584a13b4b61ae4413543b2506d0c72fd44c11d7f5fc0e3e9b53aa6a9cd3f04cb88ddf4f2129bf78e8bb44b84a3f340fe6befdd28c672fd5563bd9962190fb65bd682600987931edee66e8ab7213cdf2050915df516ae7acce2aa7f423381f74bd03162379014d89f1174d8b860ac69b1631b018a52c49763764009fdb72797e1981c59b4d698adad646acc7eee991f63bff41fd9eae0ac41b13c283e15cd230164370a5acbcfb78e333188fe7fb6ea3e2a979e186e0adb14a3763358be2e455e1e6caec6abb99208889bcf797a5a74447049fa121112b727af36ca40301f0d79e04440a9cc72a6258c1ce656e331065b0c1265d2218cbd2f8a578e36917741dafb381697ea6967c2449c15f6fe620b716cfa66d562456b8dec13c1538d56d058d8b802206050dc4bac3a80b5c8438572b56f287b4ab43e143b8098f30fb076895ff0d7333e803ec5e75b689beeea451b906eab003b47b80722cde6cbc8ed3eef93fa125596de52e8b6569a80748c516648e3d644b9d6be97c5aae7f71ec3c6b83f5e617d514ef109a1addab48318238e6a94bca315224da4c9e318ed6970f22b508885fd6f360257ba583665335aa724e06eaa282cd41b1a293f42f401265cdd2dcdbfda18955470143989845db6b1f2ee0715a28b29c855221439b5a4327ab9e8e47fc40c62d4c8aadc27d79ef937c589fe0be390df3a46208ca2e90e9b9b96d609b864d8d1422cb147bfbb4b973f37749ddc9e205bd37d54e829e0c88cab7af3ab621013ffd2cfab565b0f869bf475a9f32376787535728f591af8d816815ae9e0d8ebe0859c99c17ae4875f53adb18be5c9e0a1ede77f03ff61410e939cc7bfd424b96916ac9d5c176cbb100257690d8f15abae26acb6af4bb61fd29936a8d3eebdc1945c9b25c6b8709974a4492c8e2492ba1d7f836698683c43a0058d3676b1ca04b4c8505d8f639e36c99cb980111623b66fe696466d6bd4834f700c7784a10e6cea71e2990d33d6643bc74e651a3ab3b0c47a7bec2454d0d797835fd7e567d88eb5bfa4e00179c61967495dced31946e55e29f30caecb1a401ebde76ce564aa104b0e0d532dc6c0151bdb8bdaf0f138aa039f28329b458a6532c2fc1de6b0623927b6968761edc037817fd624e1e0ca4e3fed83f84354ccd0f52854147265a0f00f075b43f50085ec4f080b2b14455f7e676b0a27eab196fb9b437c42ef6b69ebf51bce53e792a1c87084998d5d2906a1556a9ae6eb450084c7712e88720e5269dd97a018402c61740f55a83f0aaa024e0d5840f3fbe92a28c6f1c266463e5b3fe80559ffd3f073f22b9ae89c57996257752ba5227a3884ad2427b4bc0162993643c41fa9b592be1b4107190db1baab7c40dba2cc1b88db98fd97c8f01686e134c5c228a2628e54663e276851930985524aed7df84d262c0ea8139baef5e4d480aa0f4c0dfc58d0295191041b1704239dd95410c5a677e29df5c4f8b79b01805b988bd6230708d8f334851f45c3237a08c836b0df178702ddcde508c282cf37adf81f8fbdc0c54ed6a290a3a770649841621770ee45e234cc08f0878bb3bd04d38889ddd279caea01c777d902ff1516a7b225410806a81b60ca753636611cd0b2158d8304a7cf7ec74a76e66983f250541ab63b4b1525e64506050a2dba6208f65860a60bd9aca31a115ae8303a42f84a4350e05df729236181b39640e3abe0461bcce675e6a2145bb6027d6cbd5c4f042d6fd9e23161ed838453b538f5d1f1612b86be5dab77bebb95e32961458706d19119cabb2149584c59f89f44882e333e619f9eb78ff1d9e9b97c3895c3033e46a036f71bf72de7720beed7bdcb758be7ffa80f3b5356c7b724f46e8c6cb8f7299ad29eb7eead7782af6a66f202ad04183686194e5acac66076afa479582b57ebec2eda64b8d22b81fdb7a4a2dccb0ab344cc37384833b9bccbcd07b76291b022f4bee6fb67ce04453e146c758025866385220b066c6136df9a6945903b0286af3c4d79d88c38420c83c1fd48a4f2f15ca8d2fc014dc35d1146138875ed79233e58216ad784101556a1371f7bc96f7e356311d992503b3b1fcae5879cae885a79c9779c7b5cb9d433db84437af8055503ddec605bf5bff2c23fe140c3130a7ed7488e93f2e1cea3df10dcd9459527e4e504a62ff8feb13b19f37585128b51fb5d35ccb3329d8785b1ffdf38df02b7df77df69c41952ff4876967233bcbf198f465ee31e0ac300661c7d332b6f93570d50e30c5873a2c8611da644cd8116468212b7dc88706f45ef53348fb0deca48cd11573d6c930eb52196c582619ee8547d302ba13e0ea1345aeeb7b9bee1c38bb382697402b6105d59ae02533bf9e8b99c6a7d5c52657fab743c50cccbc1df76b736d52559d6a309c4f2d4af0f71a2648e3e4a21efbfbd7ca90e31535749a32af2376532be75f6c9a2c3917eff3c33a8eb92daad50e923a20f14beb66feb89bb2a68cfd9c43e8d761c296e2a1c77ae45f4a76b3833f47681fb9fb4fcc946b2559e3fa80e2cb07d8b2cbcaadba0b56e6a2c603d5323f20d981b504d44b5445f961697e491ba2dc7b43361313d4d34f0daf092856c4312ab876af1e927d4263d13e138df14dc504fc9236cf0fe4ac5fc91ad215192866fc2fdfb527085b1df5dff0d27d2cc70d994cc4073adc4c4c66f405835c6f1458035470a0d8d785031bf6ca05ddfeb41e9c6b49ad7e4f46834d67e45857527474603aea0f5182583c5c28a2eedecbd8572e2bdcc04867c92c20260d1a92480a75bd8a38ee3984b60c16584a27110a4b50c6db94e2b131c528116818444a74f3ba3fec5b6e0212ed0fbbf9bf4d8314ae8011f738ddabbb068adfe7e02f08f0fbf090dce90b39056656bae2536b57d1487c130244e69cd52fb8fb649338147cd6516983b21f894c48a78daa8cbf0d77f1a2d4f7776ddb04a627c1bfad0d04cb5a78f95c58ada0188fb0307cc4cf2a84c85b835f9f343c0433bf2e3a890d499775372accbb12e5ca3af16844d1f4fdf61ba31edc42961f15a4992364f951cf9029ba12c898ccaf1abc0f80a7b2877e78dcb71b092cebb04f96b1803dc0477a0f413fb214162262d69a2edf8f0b70b39428733e4d8281f2862061fabfe85bc085485969424828c78db2fd1d38babe49322544325cc6fea7582c5abea9dbde1331b968c7fedcadaa69fa8bcd9e5803281c165c24297882ec3b21758d12b0b2dca2b3892207f6f29efad60bd6968998b989a67540d5db4a1ca28dacf3f56bda2b2c1cc0c51bfb9630352c820740a50fc9a0da75a0d536f02cd65a389329919393128268fc2c2c05da503e762e58772cbb777d1e203b06d835aef401df86827b21848b1ff2f28d2c70d7735ceec09d5cdf1d59a05a0c7f014689049d2d94583a1f4e8414e9795f95ead3acb32595e681ca8e718efa8cfa416402389b0b6837a45e42df81bfe57d6b11d696a606254077b25763c738bb9a1e6e554c11c3d76b601e75bc7fd2137e46218f112d6ee780627532797900c55efd42e592bc3c1dc81b456334b7e80ef117e280077f747e1be7be5c92cb3393cdfbe33a3e6f88420555fd36991edf758c5aff3346cdb9c3512bf5a2bacafb15124a184a3aa51f13f79da86b6168a2ba7331c31cebd9e21771859b5104b6ea9a67d2dbca06ddae1d9ba88fe8e866fc52009a0b43e6bf67184d802c1175f78ade910cfcbb8dac64c2ade3791e3bde831d83ac61cb3e64dce5ac3b5126392014129c45ad3375081f240f62cc54f2393ea286a87efe45b4cadf8a93882c0f080f5430db12ba62fb292a89ef1546cd3c24a90b0e13c248f44dc52d44c2088dfa9488a2e06dbb8810a2d42fa47ddb4e736e7775bb7ff4e279ecadfd763dba3010c544daefda8d4b6cc88f96ed69d56c715e090b369ce88cfa37d2d13fcc1f4949fe208b9371c32d82b94290ea556e16ef5fa6ceb36fd9a301bd4acc95e61b196292dc8107728add0c4ed70eae4c82d37e8471b834833dc9ab1732a067a43cbd24425b3f3eb0fe2165e5da40ee0d28245e28bc0981eb787e1b9e1e2ad826b996c0082a4b63bd9ffb98c11240c9abd27c6132e60c3be3e71c5624abcaf700a6131df3fc93d67fca9897308ac34fdf698bc984b11e279f13802f73d6b88ae5e72cb7829a622be482c806392c7bb12a40d8bf759b9ba6db951fc4eac0758816613f41b96ec8aeca7372e53037cb9641513268a6f40a43e6474dd9b53fdb053f92a70340356e00410f42a9d84090a0da62ed987abf44b9e3522b66094b18ef2ffa905cc6c40f2901622c9ed61002a00e193e62b45888cdaab4d03d350ed4ad696c3ec5da60eab6fe7e15b694040c0d71462dd8d6f515156a2d63ba71040fdccb4e41d6c24dc2a177b9230fa295c106c652908c889163ebf234e1bc719b3f9033c60952f14045eb54f2ea4415ecd7602e95b3a7db72d9a65c16e4be6ec2b7d48cae2d67062c7637e3ebba12b7d6d456dde406e806dcf7178b4d9dec2d60fe9781038b67474bfe86412eb52ae22fe52d3df36dd6b7ba994b6de2a5226b5b4f61021f7a57552b52737edad98b6d2c1ac157954f698b46ec148bf5c28a478911eed848ab4679a9adba7cf2a202e83c6915291aa7fff8ce82f6907b8f824f7d7bd27f3af0a69c958e9dcb8c336413ea7c96e549969347cb4979bcd2822b49e85d3c0e8590d0012c6361815e0cb0b0eebb5d2239d8eb9280d846f1209c118751b01e381ad8c03662996d1149d59d275ce559981fd331c9aecc7c9722590d9db8441609428ede4789b79e489d2310ffa1fe5057dee0ee7174b9728e0c5821886430e086b80059cd78c2261cdca1279899c5c2725dd0bc98f51b9a686fb6e026b4374238002eed022c47c2c84c81c968b65ea6320564d2816461e391c76b4bd25e203aaf56aaea88a8d5462f5533fbe7fb4c71902c54eeef8b86cf0ad21519079c42ef186d7b3925e45dfceb71dd211fe1f2a20dac28a0471badd99f3a9190bf2617a06b3b60df2fc1751c7cba35f0b571c5d2f9e16235afd78361e8d4de62616488c3e62130fbed876d26f39dc7a2820bc704c60a95b4802dd5e40cc68fbe98d460e25b8198c8c4aad07b9576bd78c46044f83aaa74e0fa191235edd76e970e06c1272db5cdcd8687a2e9b0f69951145a63af59af7d04a889d1d32472ad49ff56a10341d2c451e683f4d0a42445eb3834543ac68439bb27944f64e2c1353ae906d65e39ac293f118d36b85f6b222b45d81ff084acb1562cb916844345e24679f932033c56fa1aa53a8bc67a1f16aba669a4289f7eebe313bc494d2f0650eb0ca58a5b114044899ef211b24bc12b62f37ac4933c794395194d70803cf285fb3ec6c80dae9b56e6980fd382cd735f14714111649b44955d45cb974ae50d26b40bdf18cfe93b42b2fb7fed64f863098fcad0905eb970ced6cdbb2226c90ff7c09acfed2965fba80d489aa91d0bf6a519a3c9c0e75facf4ebe10d6559c1e00b7f19356faeb3f4fdc29ae08e9d21c4cfbfce2161e596869e78e39712468e9c5f124522aa39a08e7db20f5965c478e1d20a8c062e1f9a94a9add000e89b3e522afcd7ab6ae238dfd6128d65ced1675d6f748ef3907b03825902c94945325872b0878e5452c568c986595b8975ecce930e20a1f32b98ffdc9fb04769d5d8adc42101cd4180a6c2ab28bd2be1e8d794914d3b10ad382ea48f0f8300584fe6a1fe6edfd4488d21574902062d55ee5ee3a2ad467ce1ee95150efd1d733d253fcf4e8b1345542cc96f64a14d5748eab08e332e21e62005fde3b414b71f7775412753b1e04fad74f60e444994808eeb773dd63ac8da170893ba6244cbbf7999c4c5af28cfb1a7897789a8ab4eac0a87830d326056b3d9d40c1e2297d28bf4150879561b1eddb69098d8d39491fd97ad002fd32c490fdfa8df18ebd4aafbc8c2211591a25d4e1f336fc2502d4bdae3ad8295d8819eaebfa3fe1f740c2607597b1f592378944fd54c336a530bae5a0dcc84f90ea24efd3b0cd51f025cf8606d5ec38f4b9dbad4e6b9e376aeda0574274a618a9c3826fbd4a2aef3058ad3cade38bd7b12ba9964ced3aec1aaf3983a00168219df8b27a67bfa5b9a103f54e447fac784ca9d0ccf6cbf9d46f16b09fee0dc8af9bc9345bfcaf60eeed83a4e50d34c350196b6a2025e52c2893f54be3c194452fa6a73dcfc168048c2172bd6e22ceed920dfe1bd51b76cf890e3f9cc029b3f11232b893487add7a3dcfe470921e57f0987a7138978c59f3d5c8bbc89488cbfcd4e914a770679421a2b09c60818feb3a3f7fd3bc34497f9f16c29ea7a397b788a453b0b2828540a327a70b5aa2c688a67799b0d590c5e5dc17b505f255b7e369be5bb9fa24f31804329c0c6b3036e7bd12ad5c2e36d0d8144e4979be3a757c542839e308b6a3b5e59edc310dadf5f2dbbba941dd940ce4d72dd64994f25e72e21857307dd0d686da0c7c6cbc3082dd3067a8c22056fb9cd5e48efac497bc3d0e6f19c5875e358fe39c82c4916c06a441d4b870675200a190712701b5ead2420f65d15f4849024e46512dd739173dac19b125c7f53924c0c931c5bc914df7de1312261af259d67f344d63ee3548661f840ae2e775a082039be8feae024a1f723ebaa1b2462c5063b03d90492e0ea4c06f8d3073e9299be0e800689699ca5d19b71d57640b5a66520a3d6a59f595d88da052086a665428b88d69a33253cc0a80d4ed45fc019ac1a74a9ecedb934a873511194deeeb336afe61236632e388f4b1cda388a17adf0f4113c7092cdf4875280584fc040571e27fa313dce26501fa1553d7ee27ed818a6a753c545cf8ccf298b91599741192f4e9679d6c8bc6ef2538f056958006fa8491edaabf4dac0e59892d16c9acb32194c1df9b1b712b4ca96536323471831ab51626126e2047ea10a407b6e8a40f52c961ce041a9c33345c2550168cc21cb2a5ecf3bf2bfefda61336d2eaa0e9ea29c6914e38f784f5c5d7d3fdf08d039f87426b0f0217bc8dc203a646e1158bb43189f6d2eb3f892c1864b7239a761292b7f1545031d8580f739b0a9b38adfc6a00f615a1e5934817359e5025b145be670d6632428bfc5dd754b4922cbc82f8913e3ab191e4416c569531b394a768089d19372f1bf0724099515a2144015d24d7303ef1e34a1705c7c9e07b9fedfe1d04be138489e079d79d298832aa2266dd883de91afece00aa7705ed235423317371e39225aceb3a6d8fdc7e4c268ab29fe7c9ad5a9e9004fafb44677223bcc7b44843753a9d144f429e63de2f08043edbfe5401ae539b9c892171230573d1839bda7f7eb59477d38bf9bbd54eadb34fb1b7ba4030252558b328b4f613a62972b60b55043552a831af0f5e46e6092e06c11780c342df58c3ea090c7c68faf9f1eb97078e477bb231f2823bd3b9e3394464286a253072bf1e22e5994128f077d4e8ec90d5806388a9d5410a0d71d3aaf3c0eb4751dccf556a95891e8e1808c16ec72d8daa4ad35095380d92ac8978fbb1ab1a1834f6a295a993c43551e57e94afbeda413a6d417905c2572f10e064b483b38668256b73bdafbdb5c1bcf3c0846e076481453722d7cc49eae12b50f83e0ba0d907ee150ec87b959e018d8a4b026618c3827275e77c67d7ca3436c14e5225f079e31fedcaa50cf569bcbad7ece7018ee5f9ae96c4a09e2ee943cc921e6d62c36bc2dcf3c94dba6dc239d3e73e7ca1ad5d205c83638fa708919349625e5dbd1a2933fa58115c087c24fbd4966b11b1f699a3e4e9c9086a2db1b388ff36ee2d12db19b835229eee8cbdd552f25f2a7a3d04345623ef288078643604f93a6b4baeda2aad142c39675279440c64e9d3850c709d60e3f96d6a4324438df866d72f25812d90030e19c16a098b3400b5c178ca5ddc6470b963128eb201f69bb170fe33f008c79eb5c79bf7a58e78366c665878e18e3c0fbe56125e056c1887279b6c8d7696074e0754f60be23bb785ef2fb0711c64de91605452cd04c8bb66f4e11351747a78a94327fa676cbffb5013363cb1eb82284d933cf78cabb167abb251827b0638fc47c667c06dc18b4f55d1a2ead29463e11171cba532cdf6bf81faf29a21fac65ce36d2b71d0583e3d1e7f478589cbbc6404a6b22136ba40aa714855b035ca12bbacbf66b962f66c5c7310cebc7212f1c5e1fed6c85a93742d2c7b87db7e3a7a00fb7d8c32569a7879b174f0145eeabcc154edf5b1125f57e9b758c58f20bb7ae73c490bbddb63a239a5f68aa400713cfc5525f8d5ce08e7460d699ecc4bf09fe4aceea0634f8ef053d8d65d8020df2778146c698ac9006fcbd8015c9111bab854bd15098dd9a97f490fdba6f043c0640b884616867489cc5780335c0307d5fda2584feda67f01e5dcc5f666c174c989223cfdbc5571e904beb3726050e713a88a9c24a35fbe68f0ddfd1e251589006a7c5eff23c07485248b8caa8b1cb6825f52dddbb6b2aed8afa98074c59750c43d6fe30b3cbea19e86ddc974b0d2e2ad33655afdc5cfa5faa31480901b56d21ea3cbe146903950ca1be789805595a7630465b7b85b9ae11ce62f689c382e9c653d421d7fc1ffaba72ea43fbb744675b86933bfc82142ae5de7f5e253cdf5c95cba55f2008c2e2daf7fb75f358ca4cb17ed28ff3fcf463a047cf312409834e2fa7601520be2723a597493fb54a801f4a91705926c357d5e574e073046ab86ab368e79a18e70ef9a75e08a20441c8b859cdd73b650acda10675353e7bf547b1744a0e45598214e9afc638d770a62853bdd50f28d24d7690f68da911cfb4c03555d065ec39b3258c19dc14456a69cc7c7499ca362bda89b3f3e2e67a48b3444879d5c134452ea5601ae9cc7b0432577fdb8a6dd76e844a3b140d1ae066ab2aae0189b1ed0032a36b010f39b392dd44c28eadb81c4f1815ac2f3e08032b006a0e4304e6faed94aaac514dc5b9df944d7eeb94e5074283e2a645fc53261ac9ea515cf8e2bcd81f163aacbd6551d3484307f33d264853cc8c795f60ef6074296038ff154c1a3b06edb04cf9d83dd03c29122e9dfd0264e5d4cb4fc299a4059a1f4d2a71b0e0bf9bd92c517714faab6af7515d923cf11df49a75723f207139ec1a36c6d4632079c00fcfaa1e07057f82f46c4e6be8570a57858f5df9f4cfbb24b6c47a549bb18e24ea52c02bc040556a5c652189980940f463f85620cbdb0714f709e70bea0e35d5c6a15f950ff35b6d130958b36874c364849b1cfdf72645a33146b0e0c084419b4036ea023cc60329745d14c1f6d9c222989d2b326d6443221dc8c443dde7b9c0e04276f460378ac0888aea94b28b25e0e99bddcdb420d59536331069c8905fbe2b89754342c15da910de291237d1a488a037119787b4f6af9dd0e5c443cf73b9c3166495e6e3c4dae7c741fffd2fcdfac9cb2c8d22a805fd8679e8ad38f532b5d286987287d793dac314a48ad07e20fa40a4cc4b04cb1cf0e308d1e83b4c73d134dc2fc6d2356f606b0288cd4f7ea0d853677be884f20584fb44fce4124fd3783d98e08ee3d1411493dff5544708dfda33c9d307c172a3922a1e5287b72d0ae26aa9dc1863912d7e44d70c87cee09f390c352ad7b9421909f35ab0cac4f822e163ff0402f7de9bad7ffd9f08e38c751ac925f8a1405b74ad48e23f1cb24e6b0037d75690fd477d0754fdbefb89008804b9f2b4ffee18214290ff98b27d79e88fd9c86e47b00d5a78ab10fff21c25c38885c633879a0b057e6db4a3ae1a9efe56bdafccd1e8edd892bb64724653109df9298c62fe625839ee5b26bd9ba5ce89deb644027519729178aed6a666c4b19cba24863b197809b2752520293fe78ac88284e105cb13e77e99c421c46629b616bd557703233178218f2ff0f320304c84b7451332ded852c9d97b6138c87ea137e675b0e9e598283b697b27490962b75d6244e674bfc448d47efff39bc346c1f8bcb17a68714070a0f645b1f6a3b1a687097ec800dda69a1b8d7ad4bab03705ec6d42aedd1d03c8352dabcc2ed8946d543f8fc543b8e6979d4da9b8734e9ec0db3a04c03a9ea26d0a9b29716ee53a1af30916837bf7914e3cc355cfc57178dd96e668f427442eeed6ccad4163b6d647919171bf3b9297c623a6c859328ee66991f25637cfad7f948b7f417c2286dee01a5e6f03692f06163f3837b801b48cf27ee2faa2a4153081505129514ee87b2d61232b71f49175114a0dd711b466e1873977db2e4152a2ca1dc1aff1821327f7adc2838f0b66ffaa1874192e45499f634074884c20496bfb743ef57807732c3aaa243d209f1910d5048bcd1af5e651f02ff57a290b9be116d76b162a0f302a83898c74f764486c4e06f211c590041b01d1c2c0c31be489c9042bd8c4f7d57c3fa9b14b745eed04909813fd74aa0e9c71626466d229a9b190207aba6a9990a69b558d80d6986b54e8d48401ca9022396e0db7113836e1a6d49fcb289c513e7ac65b911d1794bae628e52fa6425f47844143d39c133feeaf1c2b808d7e2f40016c8eef23d5cbaa6d450c69fd953527c33c0d6644a2253cb090d23b54492dd0400bbec33b6d08d0a8b0f5dce708e122befb64aaa694408740e890331049bc9cc58eed84e97a66e380bde69db5780998b6ee9512205f3d78d6ee8c1890dd2c0f17cc6dd3ef81ead84a28b392bfadb7c69af11a5a0ac0fead2aac6f79001d43cc0c7fce1ded40a143114ae82e07538091060013b090567e56604509659afaff5130074a44e989a52b237c3da1dcc4c8d30a83873df1ab1b85a68f7172df190673d28860d888d48d0fc7e4575701a775430893d816462647516a22a4f91214cf5fa2e02528297ecf9d9dc95580925448b2af3282f45c3a475742a61941ab1a675c9f4b49d0b0d8adf32a2fd65a55be2b920b1cdbca5cb24c289c8c32c8d227ba5962685d0fcfce6ad38e21981f0e125b304f3b0c7eceec036192e19e80a4a031aeb529e05dddd1f45513a18800f7d15949544e6e8b7c4f7e768582d3cb8cc6d1ed895b280125808326d8e886f704b8acb9e70ec256de5bb192d48166713d28286c0edc05311096b9519cac0e1114e4e7c22f379c2560babe0e231b48e07119d20a7674397c6b398144bde60a11fd1c3e9f53104cc94f6829fef1263a734331619dbc2a7258e7c6c1965d88f7300b3b1df7fe9ba8851bf9c8d9549aefead01b2d253a864010d283657ee09e4f7fe1e2d9983936067e9a24fe6d277bda962b01c48bd5376288b7866e99a4d21bb85357e813bf4558a6c4a474765c67589dc4b8dff67f30414f14d96453f52dae3698a24408ee9dfe190e7d118200d630bde4f040362f65b1911705e65842fc172e18ad8d1af26c485581ab5539aab544d6f3ab62f9d1d93560a887c51c371e3f90aaa9c86d2d35c1a61a038f54f7adb092beaccb6c385c7da61dfa38c64ff1d34a2ab78c8e15762c5cd4c684bab61318b0d32ac3308de167b40fbefb33e57c653daf452a2ae9bdcd67dc701aa1c0283cd0ab690049918c8e0c471a9b353cc11f9ae1b457ab05df76015e08da6871326a9a2b092604ba1aa8604ecf5ee1ed4cd2b3c9fdd0b40f15a2ceafaad6bfb9b0a1885edc7c9d7da3ec78acf423b9d2ba85847951c8c31cb0f7470b513361ccdc83819a4f14531af7cf7c4ac7ed5bab048a040858f3dba3b90f5ea9dc566d20b775c8e6755e40cb89dc397e8b5af9529c0fa752a1621f56cd8de67f88f87c2428bd52968ae844e508bb696883f14d8d1191b5ec52435034cd0720633be498c48d25075d7d0c6c8d4c1adcfe63685bf59dc772d9d613b75c69cef271d25a3efac5d624f3fd4af55c769b05bf8411ce9a0980a418c0142a57638cff8b48d008fcdaa137eba5e9935f4e48c70181e723dc1e8cd78ef5224d6dc42b10c37e9891a3821304abb68715fb602a29e691b401f64d313f25e3ac22be62b4fdf3a20d91563594344a6ee419132b59ff1ffe854fa03edac4f4420a657ed61d7b2349366a4766f0c2371c1060be79254ecd7164585b15182f31db61986fc6e0dff68082e21521dea424cd5e39198bc65e1fe67ad1649d5d39367399aacb9b8f951cddd980d7aa0467fe336954cb9161768498ba627f58699f78e6dbad172166b91ee63621c8bf8dd3ed4768c7fad7da7c659020a838993279eb7765c92252df583fdbf2a54d57e561b2f3e735ec30bc480c283ddb32059584c0d97178f3e6dbd70b7d53857c6cbc4822636e11a89c7d949cd670c4dcdf424e82557b9f3b9f66726273c6bcef84bb98aaa880b4a527a540c77af5bacebc1c4b12d1e921040cc552bec017669a4d3198db52bb91ed53cc031a5c2b7313429e31150dd9ef2a0e5b53f85159018014dde3a1eb174364f4b7ac8cceafc22829687c167ba215379b027ab4e69250a884a072046d81c6510065d2fc47e7bca46b48a5e80f3dbd3ed5b931fd052b80458dcae44c1502d0d31848739fcfc17cc0fed87c5fff14537f252e394276fc47f7dac7dc5008e3579899c84beee0aa98e0a98e6e05a2b9859ce6208138b5f888a11b9d945a3054daa6b87893660eb9f1c3647f18c2318fd2de2c4a80f3ea87ef2e10600e4c081389ba2397a620abc48160491d885df7790f472760e5c9642083247b23aefac829d736d727f40a34d30cd7c6ecf1069e1b865a345de5fd100d8263d47ae7aa617cc4713416a4909f915ccdd015684332f2fde25fc91fc8487ad4537d54c68398e39b035873dd7cd947ef0d796ca19d211ce539e2137912f3cac09997baa6362e026057a6413ce63595efa513209ea8fe55c2a6b896b392982ad8afe0bf2b4cf20b75949777c8740257ca4ccc958279e314988950e651f047587ece42f4cd8972f214801aa7af9417dbdb27efc2ed98832273fb9f141443e5645e162f15998b8f3f6e8de14f386045fe1030a713b97f5cc569f187d4df35d56b80ce3471311010aac428bc834ec4e0ae3d27dcc9159cee97886445637a131470e708000fbc4b216d623ebcac3f088c2e2af8e852c81a31a74c42340905a4902a04850c5dcebe65c31fb52bda5ec7037b0a3c895a2bc6e81990f0d788e78b3c090f28f260b4b5e2f3212fcc2bd048dfc43627986398aeb52a13b84e951ea744f33769e8cf67b97569d64ca613f844d6aa0fd5a330c9569f814f6db520106a02fe05717517ec868261978544f20c62a106ac4efb3535ddb292e95f352e8568f04e5b6ce79d5fe7934668ee09aa19ee12a0b63c4acf36b10266d2db2f661036a5f300f8da96ec7250b42fa51ca0776fce5d63d3cd62aea52c00587eb202f6c447a33e03169b5e01f0c9c4ba0e58f78e4e17a47fa1e698cb96c085f971c6d849d9b359c6dada52f0516135c6d7ebbff3bf235fb8193802dd5d7ed1719b1b52018d2348fb077ee932695ec39c6d0c4e6da989726ea9d74d10ba094bc8822cd1ee19065097ed921a35c631d24309068e92c356e18198085e32101142ec8076ca4f152371063a84c539980826bef0663f4aa949e182598bdb5e2b4a02cdb51f9875acbe273c105711014366ce484b292b5994ffd1ebbfa3b5066060a4a84f2d8d5cd11831f03e5e459895d13da2b05d2ee38b0b13863dba5352b749090c1ece44b0e297f44ee6666fe6ab1e3868b6f43d6610baca9076b628dc5a1d5c4f2fdaba9e8bd60588b24575e703749f880ee658cfce72d6f797b8a10aa2c48d83b9603c2b79eb53d57dfc4d6f76d67763513124985801c909bc98122fe8a219d16f146952989a69242533a91b7358f0de9cf9a1d8e97a5d066d610992824ab17553a01ea5562cb6249fc5704eab1e43c3dc860eda0f20206f331a31e1cd01d4833750f15dc222ca93c92165680e4eb2cd1590a5b4659fd4af584054ef9e276af23550695e98bc1e28da6c855f4c654485abc45ade777c303e5eba24c33afcada7d512762d9dbb211d9428814fdf725f23acbd77c2ebc81a1be38861c05de45c621cc47c9212619da2aa5f15e021046ab7fc2d6f5a1e0868f67753222276146740c6ae72d00a3951e7debc9090a8fd43fe9985e857cd7e5ef00308ec81e45163e5768ef5e36e2a3e081272d7bec935f212edf2225126b12cf3b50fc3efa6461bffb09fdc551ed9e2b70d46460d90115681df9da4525a7bd5128b29b4b6669223af172e3510ef668bef799d1415c1ccceff5f3ea0538e58debe365e3a642714947089b53373d50224104844b5bd3b1d4cf2518e965febc4e9d91ab75edc301ed50ead77529f53854266c8a916acfa88a6bf124511429ae1c99cd03f5f006efb9d8dcc280039bce31f6a90b070da7e40b2054e8b28b343b6d7dc586be20072c097d3a3545160b66e490519fcd9c0d24029c539cf780b7530885d114f12456104008a46487b3ae5a79b4a12755cb03f64a3f6f188cd04a93d986960301922a5eb8b2d5f072bfed7752cc89d2c7015ab60b90e881b8f19e76a76806c528a2d97a75cfc30c0f35596278e482f368c326b80c8901372d7a56976cc22104721a014312cf2ed5153eb925e0039c63c039112ebf52c703dd59cf470d12cdb0b57ff736b01005d4a34c6593d1901aaf5f48a5935e6de4e23cf5033c074ffc5bf60a2051a3adbe4457a5eaf8c519c46fd2332dcbcb3e48da89b245fc873c04de50c6975dcf68e719f0f2c69a7b5f262ce70e1adce2ca11495da146eb460e134bf91a4f4397c1ab5660f8c6f4d20059aadfc7864f747722488fba44f6746ffd4870e994a936eafce0073bae7b85b96e9e48ca20b3e9a341babf1afdac4cca4a8951d9f2be92ba6eefc68721041c04a2562997cb8510e7efd9a264b86448577eb916dc2bf0df83118049563f1ceffda7db8c76bcf7d5e308c5c1d22226e907d8ae159926691a0413633bbdee44c6f715e6b8b92acb54069e348373e4719127b90dc8dfd16356d3b2b71873351320c163eb35ac4ee4087cb8dbd0d47711b8ba0850525d5cb00804840856a770cbcc3f744c0fa19d571bca02264906acf2a195d4091b69292ac2681cd6210d6919799e75739da0f994b3daf96511e8346fd9588bf6a55b33df54337d45d58a5e6221b7d64a9474bbda0817966a831840c6e3211583a9e9d2d049cf80f5e073fc8292d8f6d6e90e30f5a713678571464c2f99032f7483a528acd7a93b21c314d3958701b41b1475a8aad40f9013caecc1e3d2f5f5719580d34a2e7364273c190899924200acea6760f25a14258a10930f08923068594caed656825659e14202682bb834e7adb7fe31792ba6abbd4737a329ec869329e633f0a3b3e2540bfac69219d08a87af69cffe1fbbb2dc22a7a99134d1ff8f48f5857af4be29d5b50060d7d49e33aabde662ea1dccef3703e3724f34b24bc6b389d673d5dc38ceb58ec9c8ae76778fc3cb81da2ef2e27ed6fefe2b27399769babf359e4793d72496aa137811b193dadf94ab8b0c61e1250f56a1246d8d95307039daf773b4a22855b928084ef227172207366ca24412a93c8b8e9268ac187c0e951de70ac6ede0cf23c65053f084b5b4cd6c36ee2ef4d8c4207725d6f14c4d16d92c19205880861051a54ca83c2d00688665c1789728887b4b696d501c3c009ed74885443105482131ab2cdd433da53c19ae90339363bd232743c13b673b2d323a440eafdecb540a048ce8a289c9dda8e02a6c2d541e0aa171137a8eae79ef9ec168cc87e77a65d8e9ce626f65f1c5cc161ec97487983845b38867950e20f18a4560d5cf8da385e9588b2f4deec198d1064899d9a917f98fbd78f94db02b0c6b422f591da51d5c65b4fef8caff005a55428b295dbc0f79cb642cbfff02c3d5a9db381624770acdc5f91be2742267e4756af8f758cf5c78263027e468c2b00c8ad4eb531ab844f712f919546386eb170ed4914a88acc4c11488327b07cd61087e818e6fbf3035a3d2948d5f63fb0023d5a89c964a115980b9ef68abc122020130e043206dc6915fa4382faec64c09a7ef71bc58214b46b1df930e7c03acd5bbf71c6d6aa0b6e684aa0fe09a420b79c2ca1fd5b0e21d35edaae35d3461d32fcbf655557570dcb1b5cde76871db932808ad9f8b83b3a20240877fdffe56c4b8f32aa1a26cb6c0fb9e2e7ed29a640f3cdcc5745e68be907909671bb5a1eeb1d5d27dec8753d2e7b3e3ad262c3767a5daf04093fa2dd4fd134553597ee708d57642e8abe795ff7348f1186a1054974da4a03febaa7378b91cdf50ae83f7e449fc77396b74278d71a4c94120bd3bb85671d1dd3a7529e779877cc0f3940e90f97bd23744193006f8de737f60cedb89cb0b266622c6f6df916636f4db642788b1e21a9a76213a3e4ad9873cc53d39cea3fc7cb965a113f959da0686edfffd679ca35b81113583a89e71530cb084acda4652a99b3664cd02596c40e20bc93bee53d2437b44e6548b7ac1bc3c86c98f7de450de9e23089c888b93e07c10c09d6c147bc7bb683d8ff171062d20da96f059583bce638114f757faf86405a1d0d85d9db207a7dce7e3126c96f2a3e61171e75aa275abe8e614fd694bde9fe85bafa6f7a9ee4c316ea945da4fddbd6d579c256a429ad3918c8b86ba31e09fe9ee9af6f25bf3e38c7256177d64091a4699c88ec8aa798b4d79abd4d65e54ef2777e09ca6040c123ed4058dd11a8442a8df83dc56f68c22816258570008cf32ac5e87bc31ed4f2e93970df0ed97f97b0b27d8458b6f97c7748dd447a2df637deb5c12827b1876e78ad3c2bf5c07b5a1a4adc16558addcf50e4de24b4f63352392aa3f7876685c609c76b8a6a993b4718a9ef6a465783a815ecb54dfc036c1300b919685876bc0b55c571c880254d7d0d36107fb68f1e832b299e656ad6145e5eb669acaf4759e29c5c26b6e288911e869a79b676f164cca377390f5cefde7d470b0d28f49e17c71f2e06425a58cf8464fbba88cf27b1f79017e1f1e76e765f21c394a5473a0334bf031af20a9b59200eb39a0ef5870f79f6db94a2724f7702e4efa17c22182258387c94933e44b9caf2aaf98565798ae8ca80203e03198f1784151f8df691577e0edd3d97a28f845d077a753698f7746fb153763302857423bbaded2da54c29c99e09af094809a11532d296521aa452b238aa11288ecc5bb06b4dc461472e13f6d28d08db4e4e62911dedac38aa11eae378424b2df64d892a2d365012fd44aa97017ba89b822cd0c788919a48bf057dbad6445aa889f0505f4ac391f6702b375561836958bf537f0b7511382415da345090acb142855acc518d303f478564aec0be3552d33a4bc354778a453e77a456c2dcfefea2c3654316a13848213cabcca1ef6394e280707682b44a8b4139399f05dbc788caccdeb2563f32047eafc857e4e3401a0f90b063674415858dc55603f858203bf9fcbc6cc5603ab6fa7e765a857de4d34e1e6ba1165aea980d6d6bf574b58a15e0a3947b695fa70bf0b14066eab2fa26b24f410f90b0144886c06fc146d261d9a78ac27e2a2eb6fe1179e49301dbc93b8ccfdc7f9c4a8b426e0dfb29075b91b89ea1fccb5448d6f0cb1a063beb30cf003a23188084cf2be1db5121f170622c900239cc33e1039b85709f0c81658d4c5318a7300208132687a500727272049085469349ea72eb82d3a58b0058e208400002c0b952542443db52db12dbb20587650c07072766252888c82723e4b11e658aeecd67edcb20a1503248b7df8bb1bc89c56275559fe220457eefe6ab21151dfea1b4fb93a2a948d8e052da101186f48afe903ef2d89c01290e92081629849f821448d6f0af401a44851cc62f03d222a747b2863f0552244a73981461a43b5c7e16e54189cbef2de09be0b4e03b8c014d84dfb3f92688ba42544836f08408091224488d035c0ee3f7947c4182d4d4d400010204842f860fbed50a846f0503cf21637d1f01018125102040ea0a25457ed5e5f740f858a07518d3b09335200f084990b0a38d0aa44732047e144869348b8a840dae8dace1f724f04d6f025f1882b50a79cc76d1fba875830d34d040039a1e1f528bfd3d542334ac09cbe3266bfa3d08b2633bddfeb18fda094cdf3cf54d98be199dd0a3cb7f933c92307165b043476b4666042647620c6065ac958ac9e7a598a03a261c934a2bcdf4d0c319af0f00245bb46951c5a6c5d019322bf0a0a6850540e1d0185ace78430b1b406fac402645a53431598e136adb1649dd32c98d2b6e0c3df589518244e5ca2422b4b8421bfc58a9e5c9cb1df9e727e8b2ac55e99894bd517447fe01fa7943884a4b05c21856fe58bf3b417bbda942a2224185444ab1364bba4add097e9755482400a4b0321cb9917bda7d83dfd1faa6432eea42170f256c8f99ed5785b11d1a69919f0716ebad66d67bd197563051634a9358a863320c2079468c25e327a1cbcf59b6c8f8f98abe915ae050ba2c73f9798b95cbcf377ecafdc071746961aa5c593f8e8b1a1212e2e7226642bb614a1048b8a1b4838ca3f08025881bbc40630635a490f1bb6a0e2bb968c3e98e4eeb58e73441960528f6320db2869f659042f8c72e0e2bfc73a5631c4715ee9fb428c324dd91853a36651cc676f9a8034df6f28face157c96147166a7f6e3e71ea40d3a51d34551e6769718c7217d032e9b06ed0bf05104a8bf2bf2b3dc64048187f11aef19db0cc420c14be2a05768c729b81a8e2b09225e529369dae5863cb1d1b294bdf8c7ee4470d7499c633372e7fd73ad632a9658d2c97bf696bcc2e78a5163596ae1a5b2e07576a49c304b5cbaa2fec93a727548c12242428947d6eab12c03f8dd43db4b0a345ba1d7e5d1c7674d2ba2ee61a248c7f87db0f43348177642a4e4bf05314b3cb8cc565a6226bf86dcd8e8dd437fc4c85a938ff5099215dfe46e2ef2c57f0f796d17aadd2bc5867c3b0a36dd51fa2fd9c4e709c37356bd75951b3c714d851c8f5d69d3ca706680d35e077da70d902a5fbce470560080f41cda92a01154e9083d273cb147e45ab0b3bb67eb4bcdddfd44d57a73d54d8751ebb1ce65c382e99cffde4c0ee5d5ee81c8e2e54375f5dec28bfb8feb504ce89049b4b398e8342bb0b530d8e3ce3a22727ee8198986a4db624ee391147ca6efe06e7770598638e307505bf959b1c09fcfd19b0b9345481bf5f267548d05929d779caa361a2d7a8ddacdcec5214f5fdf079def779dee7a15034ae968ba645b344ab86ffe15c87ba59b1accc35553f67d5ef53b15275a5819eab158dabe5a269d134d1fa2ee8474fa7dccd3e8a32023676e8628a38d650410f4f5d8c9ee8e2ca1618fc10848d230a22203250d014c40c3140038a1d4c587889c1d0103416786088111b9caf45e34f5aec64777707817e50619c8ec5f9a68ec5f9ba0ee88fef3e576bbecb46b45fe7eaaccb7edd4c4d7c1c1bd7fc3a203fbe0ec80ffe3afb75407ebc6b4a59535dad1f345fe7b25ff776eac04307aae44a2de295cfd2ddbddd5dd2d9b2eceedfd76919ad9bcd41c87fb2260810e93e650d08f4830ae344ee9dceca551b0f52a89d23196c61f9690736032f00e049f971a0aaae16f7e3eb8e66485327a5f3a7f410a7453904e4a1c3b7922cbffb88f10dee28a594d267643468cd7434ad97943abe14960c5a2e570652f6e0b1e3e5c2d395effeaa2a2cbff7701dd7fd2525cdc72307cb3fabbbbb27913552da663a0d3e5a39aeca501f1bb8bbcf18fb3eec0f59334350babbfb5c4929a5f41e6234165a455923bffbc34b49d901ca83ee8e524a29fde8883f9f3fba7b13299f3e9e5509c257a4bac2f2fb073fa6bb3b9d14846f0716cb3f3f5933e99cd346d650576b02f95a37cb3f479c1416951596bf7e0a0b27de6e06a9692141d8b3f97a80b1038bd3b79135f285b8bbcdea5582cdf5afd7c391857b899450824e2dbc0be6282811d45a4b6b6e3783a54f432197fe941d4a5a178a5b29cf726bda99f22a87eae4083cd17e5f8bd27d04695b3e79d2d5ab841a8e0eb87270902b7ecdef31d9920bcbdfbef290654dcd952d9a2a9ca5585fbaec3eb83f8478fff77fd737b0dbf58d902bdfabab233cc9ed9356ee4b6a9a39715ae3bcff381efbc7799cfffe61529c1f6237b549299d5f501f9c5ca796547b6bad0c636dcdd66ccdd66ccd5a317efcec3edb72d52e06e701082080e8e00707727cdf17f4b5a44d262de9420e97881e5bc2c42432894ce20fd394302610400031a77ff1b1c19c73d6c985093a468ec830b49872f2f4e992a7374d1419e810a2959b31d877b95a09779fae2aab0c379d3dea93ce784627bb8d280ab91caa2c938241099033e433d2ba0208109828aaa0503da17242455335a15a71b162d95a2bd7a1501d57a5503161f9554bc8cc8031d3aab5725dc7552d2d1d5b74ecf8b223832f2a249512aa24545854472a2454235019a9aea88e5019d18107b556ae43a13aae4ae18138271262111f80604555a4225211a11ac2f2ab866c42f8124200be046046a97281b346ec26298dae9a20023b475c2e97cb550023e24ff91fb3fb6ccbe5ce4cdd99293bad7405b5a98328aa00030c5a393f819215212b4357f8d840c987289494e0c2041d2347a6920f2ca594ac544306614c48e4ad2fe912bd5125aab44495fa86defa8609f0f3328e001c953a5c951d9475bde84441be25481d998373fb77648e9b4182db210bf229ff380c88abb4e00eb35eab75d72665aa4670d59dc2d7fc2832ee3d7ccd30890fcc3f8a4c3a8c670ef3f71ec761fedf63c453bffb1ea31e239ed473df63c4837a2fec111de68fe2e91e15f674610f17f6a442a7b1b3357cd14f71e18b862f08708f7a9efaf569c875e14e8b9ec4618e1ac272e8246cd2a2ca0496dd59c8dbf8a204424d3a36655f90c0c62cd92df1180d5f49ba7f2d40caba7fa1d0c4a5c396806658295b69f101a338b00ccd66b2eeb937327a29807ef73cf4bbb0c7687e0f7d2eece95c0c3b2629a33f7614842fac9449198e93d1184f4001349bc95043580f39549940e98ccf49133ada74916cc3a5d038d6d6e0ac2928e149d2e275b9e5fcfebc35b461c2d2d1a60ca72b35c9596848489c058926635c2424e47c637d7bf529f30f2b54e2abb0eb54351cadfd4254387e2a1c45251eeb6ee2ed469929e9a7054859ca73798c85bcc8c35668fb934d841f05e2388cbf03bb28b56b0c925b342c362cbfaa0ceb02cbeb28ecf8c960c7cfff32ad42aba8a6b0a3bd723a08525a2b57074c6b8665c96e1c240dc73187c275752dca9964f93d832af6eb54665813bad8141ea94529dfbb4b5f47ce29e59c724e393d1f2a3cf9a39b1ea324092ec2ba92638e6b2c929ab8662550d0a60b0876828f640ecef5679acc99d7190cd6e2fa3315d7dfabdf08fc347f3fba343ef21b252dbabc61296fea4bc9451aecdebac7b1f04a71ff4a8524f44d71154734ced2e5fa67a372fd798b1632975abe88719d75fd194cd1f567267f6eea148aebc2d19502e7ce208a064bc34fb5546b9c0d2b5e31b39ee9f3ea39e69969f8e28f72d9cab0563133df2a2f06642b205761cdc8ac54e168478b0ac7efc2d1c585f2697eb6270a3cb6c1995372ad3fadc7faa99dd26172bad0dd6824b1eea457423ec3f2157953a5bc994fff9337dc535aa56f3a593f03f50da7beb3369bcb263e5999d54bc3695da3b8438365d512a51243454c1654f2ce91effb3ed739b2a3b3333b2046806401629ba571bf196c5272b8e30fa62f29094d4aa284f33850094f128f122e89121d9cee8e38fcfd61dcd1c56443fd268e8e111c9f9452a7744e9d234ab61baeab4bfde8c83e5dee7257383275669f4ec3d6374e66b649f1e18ea2ccc205335c18d45a2d1a57ab45f3ff4fe36ab55c342d1a1d2cdb6624b88f63654dc6c89afcae73b9beebdc5357daa410f54f762aaad4a1948656c276183c226bf3c80e65ea3a15ece80cbf59831d6d868cb2b348d7e4aeb4cd8ab896053147a82bb370c1118fc313e7fecf564bc2eaebe094b0e4b2bf3b4ec7e84e0d56da74fa65d29121435457da6656aeccc20b96249feb3e9d4e77ff64e8699165910d4821cd0159d3dfff5d4f8bb3166e7694495d278ea2f701c7241f806f4216613267beab8a9cdb1c80db1d5cfeb103d4f5c425bb811664ce74310e2cc3ed97729b853c29bf936fe5bbe44b02781d7365d759f728a5d461605d99859720344803c9831584804b1b5ec038bde12508d61a324ef2598abce11348251de30623ff89c7646250f5e7b8ac87d2ddf9120e29b602e40d3fb5e8cdac5ec7b75c36b6e3e59f9044e67c2fdf5b31ab2d1d121202eaba8e03d48fd407de37c119d58a656306703990c845d47a1da0d7525a25cd54b3d94ce6702d23d703790bdb74e064a1d1d4b879b979f1924106b12b454563d4946a4a4a3c78dc58090a92a2284b5116cfcbf222723db09d76803e4636e41f1d21101153591cd050b79a018a01a56c66e665863c6f688321536c6433cf6307686fbcf7f1429e55d0a795c14fb191edf81eeff9f021c2ed6674b4400f72a122bfd23047729aacf1e07027a4d8ff21843d2de8005523804266c29016d59575815f13010ac39aeb8144ae7f97cbc788fbd122f73908e47a20d1cc7733a08f919316bb36f96992f9f9b9fdaa1f99c33d017a540dea071f7c0e76c064098b83da410d01bc310d069cf232238ee5025f9435ab958d487d22445e07d8492eb0bb747bf9165313595aaa1dc7d21133b363c59324666607573b1d3541623e4ed8e96a386e831987e9009ba9614b4bb5abe1381c0d666848ab9e099ba961fdbdb4c475ab5ab96ec5ea38a6a5a6b95de46aa11639ae763a58de8a650487c5752bd66b4563d68afbda751c6b95d3e37a2051eb3990c8f51d489472015985626bc6a583c77d0ffcf17fc3e2389e59bafd37370398b92b9048c7b37e82443fa24c4798f231f2ba25afba846e58cce2389e219a7150e6ce803e462caf72336f6758dc1fa1a8981d313b988bb91e4824f32ba799304da499db11fa18cd809ffd991074b45c9cce080640f291a04282ba4480aab84a2872bd037c0ee6508952490da4a843c2d80401dc0af2cd0b93172f5eaea8d56a4a36252525a4a3a3a22c4759b264b91912e20a30e493011af282bc21225f4ccccb0c79ded00d4b2237373775d5ad6662bc99988e057295023010570011022042afb817a1f600291649849f071733d4b4c895c112977f4713975f66c6534000aeb780cf419b9b02a7d83f56606735d05d56e86090eb81dd679b48e5969638ae724b5c5d5ae2b8ca2d7115763d25e2e540221defb97484dd033cf0840809d24500007789ab416c10351f0c4cc3ebd57cadd66a15e46b8152a643c76a2524084b214284d45565e968ad74b45208a2a4c5b6a1473320add1204b3e0733f028f039b8e356e07350c7f5c0155c98dd1a4e0b7c53de8f063bb69393eab2179e81b9ed42c9809df5c0830e963aae0200003f969638ae76cf2d755ce58083706989e32ab7c4d53004979638ae724b5c05c15f5ae2b8ca2d71f51b70800c4ad8b1a303099121220420041b214130d079305d57c689d50c7881c79af2cdccfce6314ef2e622dfe4eccb21383a47b8670fb5d84242b5721ed7a1c2466a180b6ca71fa02a414243aa55cc7b32a08f116f91615b076453017540b7bf039239f45b57d46a3a50484747723485690a1326036f4848e88ca42e495dbaf050550102f282b685b665cbcb83581f07b20fcf58868999077132877a4c46c861324835e5b1d5b78cd06d295bad34b86d90c4c781443131218df9293632d6cf3cdf74a81e54d8020bf53d1fdf93bb055d06742087f557d0835a742b42455758e067014a779b0d29a4bfc89af6a31db2e60a3b764eef6344a1f4cb80a06a84f92c9006394ca8c8c728e5a486dfb59a08d3d072e063c4a4c59ee08b8414eaf2125510934c900cc10377445d7e16f88eaaa0dbaf0af23a78891b7cf0010bec669d4fa7e40602d7fc10e20127798cd6a80d4c8b4e3148e2b6218bf4110b69cf822fca107888ed361122443e15d8494b4c5d6e37a4238ae0b674ccc788e54df398f598cc773d6147a6e8ca119120426247746e703ceca586f50d082826131305ef40bf8752c6a9efc08b07e5df7953161336d523ce0e8ca652a9274a857ce4304aff042ec2383a54a8a35488e3e60647f477e827a1cfe3cd51749f4c1fa3a6f4f9a8c3292f33621abb944b2957b4649be20ddb145b6c53bcc0368517db02a05bbf6b5d06f98671821386a333352a2dd69fed13f3c5b6cfaddfa4852ecd4d2dd677f2044a4fdfcc965aac53c9632fcad1f0a500ffeee977170f0a155ae992dd3bac3e2aec58a9c52a475eba95936e2dd6ff4007db04c7635e439b57b244e6f0adcf62c2f6d8ddbc1620653e490eabff428135c71c73cc21f327f290991c56ffd6ef615b93271e93b21ac406c5133399943116309088c14bd1c849a0cb6368fd579744bb4e8359fd27f5a1d46fa1632f597d9ed5679ffa4ca53e03492d72d4aedfeab2fa1d4d72f9ec561fa3c904e456396e05e2f2587ffdf7987f03a17870bafd12f51e8a4b51cff39e68848a828282828282eabf4c98a30a9d0af3fdc6c2774bdc52cfa9155cf8bc573db9fc76a3992189307d2bb8fd1e0b6e93505050d02de816740bba05dd9a6eb7a71b18cb37a69bc7b80b98262f4cb74e4502cfbc29e34022d4a7c016ba09dd826e41b7a05bd02d28a8a242be355994ac31a2725ccb24ad60cb04eac4b517e4c905b0cc7b1e9779618f0b32efbd8f06cb1ef3be1b4900d5004695911f1b99ea47d6952fff0b7a97f836d27f7e1cd6f35f265415eacbcb646361059ea36ba20477ec2218780ed9f7fcade0828fcf141b99ea59df451e736b6db79fc19044562cc6ed57917181706cfcc7f623bafcc7d6b1edcb07b2cd6149368fb152c3fabbdc78e936edef918545c2b34b3d70ca3a90c8fb8f6d2efb2ef16d449b8dff28a0655ee8030deb5c6d151259bb74ecb91dd75ac6725cfaa9025cead5db858e7ed3d9d393dec9814b6937bb6e32a1faebc23e748edce0a0c1010411096c4042d64331fcf086126994e00359c411447f48892c6b3a2ea2ae33ea9698dd21ddd1a6084fbe95ec8304b65f721199d9fd1f3b7ebaf33d0e7cd10e7cd15a4197c3667d19d7e1c8b33bdfc545982905b266fe989af6ce3a9f99e6cf5fc160679616a7d75a9cbf7ac1f6f320a269ca3befc8f743f9609d36df6bf3dd36df9392e80bf69352da164be99212a709f8447e93277d23437944c2f86538fa3f71d2223771f28465cb26fd441a6991a54e8bdce449767102856517267d23b9c913272df6d0c2caaf434b825945c918c87f808c3549a2846b2087f937f158f72061fe31b80ec4750d741f0d3ea3d9b181bc38a271919954348b90b1790b43d6f88fa93bf65187e5fa74e246c5f534eec87d715a792671911ad2d90c43e670485ff038c981b4c961fef405ea447fb0b823f7e5d62c41d77fde3cc6752161fe625c9fb7135c6fbaceade0fabc5de7bcdc185c77fa82cce1a6c81a7f7f3ae3229c0f0bf1f7e7b6c81aff91f3b9eedf3cc89b1cb85c1f642c050903e2220a9042749037f41d8dcb0fd4425cffcebfd2603b2a93ef49765fd59755dc5182f12209c8a3a4456e19731c8a09d59a23bfab451a0f3b6e761ff9d9d9b97bc2f64b0fbd216f73337a7c395089ace9241697ba9a0688ace14f29c1dd6ac3f6d06269d8e7d29739f375fac61d1c69bf4af01f3fcaf5fc73eacd6f841715df61ecdde512c01edab4c83585fa0da43ee67afe557072aa1787fa56bdb830492ae49135192a74f973e0ab84399bd54befec764f41bf5d2896e025b4ace24a2aae872fff287c29d829b4c849640d3f65497d35c3178fcb50cf9708c537f5847cadc0d7f28bd6f5e218b2933db57be6b75429e1e1776e218749d0ba7e82a28dc3e45710c761b2935129e3a6754d7edba4fc22c9e8cb11364cd9e2852b5484e14411616071e322937f74e5ff3deae45bf92ef9df49dc6ec677c7710589277f8cb51e7d5a9ce6f59de6ce49f6ca6fea246b9ac708ece8b4278fd1aeb3d6e5a2494e5b40d72bb50719abb0a71a24736ad83fb2a67fc645ea110ba179ac65903018648cbf48584dc28675c74a635de9b0cb95767be4a6913e71d393d724ea918f9b9d2ea75db15e6b5509eccb5eb9c5950fdc7eee8f6511fac4d769fd5eeb6f95fbbfd3e88fb40945717290492e5a6428f0c5211ba9a0054f323642a3c926f3b8f6d58bc765a9e74b940a7b5c90755c5ccf45e8130b7943d6f48f292ceee8ddd1bba38bcab8909b1cd6f48dd41db9e9898bb0d30a06dbdd2cac808449e0ebcfab176a9247e4c93b1b62e33ee790108707d18e306e5c6200238d23e6e8a104132080c2ca0c50e820e3efa67ecd60c76e92391d4385a847a93e8aac93425b16769435d9438a05c28308e9a5c0174feabfd44791b944d0609a3cb6d3b4d3546ba7cb556c8a871cd66355bf23911784316c8f3b5fdace0073a50a498fdb4e60da4b8bb79b5a642cf6757692c858142c5d800106152d443db821e35722632df0d0c30a4070c3114e08c9f87914616ddcc9edf7f776aabce1ba752b008e6a37e7a4e0e77de375ec2697cc4dbf5b417b2938dadc0ee3a4757ba7c1aec559d7a81d982ebff79ac1babe5f3c8c025f3ca81eeb3096ab188942ea3d297ba1f0bdf75e5874df552350c9050e432aa84a9879952073fb656eabc0f5737d5598ff224172818317a96ac9050e43d74199dbe01399170aabefbe0b3bf0a5c0170adda3ba9732a952a27a54f8e241798feaf8fb2e7cf174dd47914591adc23e7218bf4ec76461bd0e7cd1e60375761cc61c44edf2d7dad6493226adc861892cb69431c6184832febec958940f7861060e6bd8b006089e9a896b0ad4ef2308830296b5b6ed40e328461e50a28a15657861441a51a8c0108611405439011955c2dcd695b62947dc0fcaf9a3aac72a08745f1b02ef523d8d2e77db372af8cba40a01b2cbfd5eb38b6254c88ddb2f76ec25ebb7118ac9a4d96ce685acdf881af7b6161804ddfe9dbee1e90cc7edcfab7029eb3cd6d3332507a40a851e21aab8600e99cceb4fb60b4ef55120f70c8e0cc4837a2eec692687394ff735ece99bc3bc939e74dc09d3671acace2d17db6f333295e9d4a2bf47bdb4e833a9457fa4a4eb4eeb71573fc7bdc16a54e1d2f0c53344d67dbd44b2daddda1443ca2e2678933f2a69c8cccfffa55e5202a45e4ae667204e3d3333333333732f6ea763ccc569369b49e1e157d2b14fc6bf849f09bf13d6e587e273f95b9871955532e42a3c4106626666666666d904e5453133f30e1f55309efc314a998292a97364e7049beff7f738908a403cf0849d233a3ffc5a975f170d7f865ff73e739f4343cd424ba878136fe24dbc8995875abce2faa92e8f499994b96ab69b2465b34695682dcaebad1a619ae0a4c54e925474e45fb37cf0aa0ab645dbe2952a245e69a596eb184be1519242c77cc8fa997c7f60e6e3f6b7f01493ecd3df093c293019c2fb66ab45125c05f065023b3172bbf7e7420db0bccd3b49fa9528f5b850a48b246a32237ffa7f3b7c79bfab5144d8bf383afd3bfd435720157d4184175a9011c5e80a198cb4cce03444c30e21889c28c20b19332f5470821f35c2f0f2a3a48226640c0961254b18434a0a786a9ab2c50d36a800b51047133529cae8028d3124c00511513c591983690d597fbfabff45c57a14ec6c4b6acc64fd519a98410e38b03825e1c40cb26662420a315c1003154e4421eb97aaee7a88e1ca4c26fb3bdbeff2ae5cda9ffdd9fbe9370761dba1e84a5b1530e195b61d7cee12264dfa86fbee6d55badc06c195b61cb6f062c0b0a9efe1c5ff79dcec28993aa885644c9ee0f60211609238010f5264fc5d24631d40d1840408da5062862564fc4bdc733d936863737b3cd98e5548eaf594fc6dbc859362c0b023dba0b4c84c9ab4f8e4c78e720b4f07e773216779c9ebbd374968afe33284f0c9c2644518131cc9c20a24b048410c1fd041c6cf5e644e0d32a79f9f993ac657fac64b482f0f49e8cb4ab2869f46631ad394644e3bdb90cc74b1a867fdc8573430af0a2c16627938f22ccc1318272f4d5d98966e4a49728bac19c1196213f3de7b406240d9308fe63af71ec8bde7712870443d0bf4c6ef3ac87a8ef516e41e153669915921932528f0e7de5f7aa16db1e583fd62c406979b130f4e2960210c1fc20491c3113fdc207bbd6047235e0c1896fbd70fdf1ac6df75162524afc8c2891e7e20c30b15c0d023450935681f80e1a90c193fea848ec53c7f33614727462e941639156ee1a066e2a445244b5a44e2025cdce8220d2a6c30421c811330f8508315359c21e3679f23cc84554b88f8b0f871924205152cb0b00286a61f1bcd8bcf1832fefafc2d3059528465266e9231266a4cb102a2357cb05092f1b3938c4916a8d145952729ae18a20819a396b07de951134e6bd090431b4d5186f000921c3fa8213487141092b0321b5a228d18bca0052da0e2072178b0a28a09644b9a3c91310b1c71258b28666f886048c6df828cc92dae7849c10a40e0f4b3432d8323aece39e7e42abf7f2763954eaeba7b48df070d59c0b22cb0fe1eb76c276b5ab6d0b0408cb8eef78dbc7248d80a2d7b774f0e687cc8989de18c0181e59122318595bf248495b9d29603edc74e0e472890c6d54dd9b2b3e1a557da7298e18eae09e4757dc32fb8fcb3e3b77cf9458fb50e0e33461834c86c349ce0fad33c96eb03b86ea3a2c6f507e2b61aa8b8fe438ce8e070fd8fec085dff13921c5d7f9e146ce0725dc7751b9a9e5c09e1fab77082ebdfe3cf3eb61bccb8ae74dd06b4041941566c38f0d0bcadf26ee7a9852771e4dbcbd285368eb882863042405102594c9a8004415db0604113361f993bd0752e8c8c88ad64ceec65b6c8ee73c5e7fa1fe9588cac6356e6ef048accf1ee9e9f1be1e878ad2b23ac286bbcfe8b7e0dbbfae2b8aeabf4a7c3f150adb241815dd73d655aad2813d12aa44e9469c761f5bdda8ddce4be52812e06fac057fd2832b739acfb14f8aa61121f58f75164b49902a3994cca8c3ad52b7158f7ffb5f7fda95015f6ec38aceb31e2f93e15f6e084ddbd47135fcaba1f7164a96fd262f74f1cd63d6a88eeddd6bd27cd1cd67d83ddb398b02f1ed4f7c8b68e811cd60939acebdeb7cc20a779ad03ba490eeb9c568138187c34d8c949640dcb7e5573cfd33df7dd21cff7aab047c761fedff74887f5731f45e67d6007dabc6a4f17be6a586bc883f28e07f5dcca084b7f05be3059e32fbdb0ff4bbd78bcd47b3d5c075a5094359e025f1485023b87b1f77c89bad76914d885334c9a3db9f0ba1b084c7ffc4f5f94d65e49b62bdf09f5d97e44a7c52b35487a0d66a852a9b36e68a7a2abe5fdb4ce6fca55ca71740327ab24a3058e2c5ca5f25d361992e4bf1c61facf1fdb95a2e8365cf9437ea763fc537b0d5979b977d1d5aadfe00a2edcbe2bf0a5ab1becd3af341ca35cb0057634728f5cb1f2e51d6d3fb72bbfe5a2f9a03b65d22603d00d5f8980da041c970b5d2d232d2a61b9f0884e8bf25962d81a1af167c91c59435dd66aa4633440477644997c9ea22b6bf297c071e533e91bf14a9b07806e57eaf6abe1ca770db9926fba16bb0497122868ad16a5454961ff0419e36668dae1e90a279e4092c9e791b1d752c60d86274a50b42493462ecf7484c093b248ede6ca42e44b59a47fa4dd1c4a1622df9b53d6eade3fceaf744e9fd31b8c42b9cdf0648f9549385c713dd6904e36acb3327ea9b28c2ab246705afc71085f964552b33bada4314a92506ab15529b01e12bd7828d853bf032fd0afe10b05ee2bd744faa5ac86569584b2757dbf581bc3ebf71a449161f94adb0b602e7fea4adb0b685cf98d24756f6c53d06cb629b0e4c0598e93436c8c88334e5b621ac8fa79966ebf9212c8fa973071bbbf89d2ed77c2b276a6d25c917ee1ca3076e43b72b7bfafb449c1729d9339a012286832d612c6a92bf3f306afef12410a51ea66561478d248adb5d659df55ad8081713a5a630b0a7e5220ab6fa4d1c5144d5d00a531060d527cf8fcfa3f759f92c4a4749da7251a405fb85c090117338880a28b1c53c828c2a18d2d6474864b39d51976944a29f05069e338eeee4c36bc573b117240795eabd254f538aff352ae2e1c3b5b4319a52d3a8fb0e984cce1049252176ebca1860f1c9ce0c2c6535017259041ca0cdd0ffb841d7ffc107f5ca7d7260b4a696c36031748207df961e89da6d060a8c9300409fc278d55d7c62882ca1345598aa42852210a143c518412342ac0700f34d1ae6207138429038b1e6864a0403a7d408d33bc48eaa108872966704401004308862ab610f2e28905a1182c71041c4588c184acc670eb8b4024983c67ad54dcc83b992c5b2bad8822c51050cc410b1303315420c31ce1d48236be7039620c9fa318cb468d654dd664165f90a0f0b101071ca0e8d1c513b31e9a604085175985e1d6226ee56ea5b4b3ae176d248e8ccdd92ee47ad18645604545a76035955d1a0aa594524a4500460e37e48081a6c50864348a103a4ca9a1055bfca0c50d32ea2f5ccac3a5f4d25abfb0c88e5f77e5bc5e43a7b3d9bff0a491aeeb439139f2d6fa292c61b223bfd6fffac655816e7db1be4de572536f9d9e1456ce994379729b31676d7dfd5d83df4cc00c695aa4ab17fceb6e39a5b36707b558decc76afb586feb5d82d28f4ce16095fade18b84197657beaad87e160aeaee9fdbb9cf1e2c3f9f91c3d1396f7d2e9453825d9df5b9efea4f2b6be49c6e1b8e15101bee8257c397901d3fe73e707462e4d2af2daf55eb7fdff8bd7fdf73382d29bd77eebbcda56c5cd5b638ee6bf82a619cb7fe776be8c4c8a561e7c4c89d61ebab6d5ae1c91fa2b5e98e8538aed3866b651f40612ed7c92ce431b70a40bd3f0aa8f7d0bf03dda302a1c9a8244c59e98a182a4434020000007315000020100a074462a150380cf46cd60114000c7da4466e5017ca83591003298842c6180408200000028c21524342a20e7df1d4816174cf8502a6cc9cfae4b45a135176954575400c6129ef8f01525028413febcc46c0133523e42d6554ac954d85262afffceb0da82512c7c189d24de040543bfb97da868d7315e226ee6b0e7f9091645165f3e1b3ebcc0de3dfb7a1f880e96155f8a077086585624801bf6426abf0456f1c052d00659bd8c78c88bc8488259702973c178ecca72b0f9ae16036599c0d5f49969cdcc6cc7586ba79e958f5e42d65b775a5f9fdb6c95351fa157cbd165c28cb23230b608735d66e64195fc8535e835c8e0be3d4dd4f3994c9159f15ce4ef55ec152884294cb235793640fd167dbfbc4577a09d812a1d6f124b32748584d7ba312ba971c26faad3da22b6f89f54d3a32e8171965a03296e3320d40970a71f368b9f2e4dff23aa8ff92df8782a74af6b2511cda2a81d7a90f4cf1ce59186d97cf85588c78414d8c4962f290120f2492030cedb30d7dc1ba28d12eaa95f649673c85a76a022bc8c348a091d615eb1254517ce8fb1667debccf02ddcec17b5a27d919156ca1e1863184e3e442c8d9a5e67b0eafb4f816f72c84ae10c628add059ee6b9b4f1a210198786573b7aadd8dedc7cea6fb75e9367891f9c5c85ed880b15b8520023c61f0bca40528298862218ba9bbd979ba4d46065672d90cc3540d14e5ee27b3014fa1d6876f7f1428e1d472851ccf7643c5426f8f93c9843641b8aabb18c20b6f3b8f70b041727d312b4155cb017a9f683c4b5ed2665d345455ac979771ed37f65f3a5f05014a7fdc8b2bada432b4c4ad7880ccb7b2d3b099b47959730905702c556b6cba646e0a4468bb9ebede6d525803fb0973264f3f9193816942ffc102fb2bffb4aac116193dd648026cfeab615fa251142426b2644e054838de1cafaa1d0c6ab8dfdc32aae4fab9f23b028df75ce84cd3c7f4cb30796ff09af185236cc35ecd6bb4c9ecc48911034890ce4881fe126b65b77f0898050343146459561a542e4ef74d68971cc3df3d54625bc7b4c4abd0f5f0f1decb350f0e0799ee0906badb350857b2a1c8df7e9f0f142536e7b40b02af249a09fb2903d159c9273b94f377500e338c86029649a205d7ab68a34c565eaf56441ceb42bf2682d02d797109b9f7bcca50babc329d273919454a9ea9df91c4d97a92151b1e516140e8ccc8f4372ed0bca9b3edec9410fbf2c988953440574674086d7e691779bcf6f7a0822493f9d19fe32678884a9bf0a66e77c2521e60380637cb821d1b8c937812868eef6693524dfee8b767e096d1537edf8f801f7d0584db9efed186da1e616620b8e5b6fb4dde9a8b5f99da09d06a660deecad32726538b2add71afc5df0499cade3a29cea086cc544c88479f9d926348ca9742dee182e2012e2853049a3f0d10aac51ee20ca18f5f70d2910f556939cd7a030055ab177639f04baaf5486c0985230ab606c3b27001ebd250161ddea6f595d99d532d4defec1a5f8bdc37ddbc655ddcb1226025139881544ae0fdbece8953537ada3d99e77186103a19042b1247233f9ffc1842780d212903b7c9a8e9783f9a61fafb3132ecaf2120630d1740f1bcfb167cffb996886920e69f1d214011db5e5a3b8969eb54c60d06a5acdcb546cad26b6d0acf3eea97556893da7c7ae6e6932add6328040de1c20d1108996c6439a55918b6b6a0462600538aca396062e3d88ea3d31ee42b4b265d7c139c9ed1f3cc34636957ecfe2e495474388a2099cb8a321e8fe670db408ca0a5d0e4c78a4b9fd4b8afb2540dcdf3da624c64e842e90f6cb903a362b293a5a2d8a55754467ec09ed86abe7d45a8146d6166a691ffba27be91a6ba22fad75bc7837a65aab591255f6cd96a50e81601501739426a5685931a9b69cbbff62b603264596ae37608d0627f4db98c19c0491e700616ae7b9b9d1708119d52c40682d327af560e83f2c8d124ff6787e6a4de391447f896e90b97d157b436d7dcb762a6ac4617c16804d89a71904894a1a965513ab09655b5b1b7d10bd94bd86722bf0a48abcab3c9a78041758580e829c1ae67eacdc24da3dccbf11d2e7ba773ad8f43cb4bdc982edb4a252e28d7b4937259039e1456f07192fa5e74a2ef1eaff086dfd177df94117a00ade817115517d7897540e931b8155769391d36d26e52e9e1e73e8154c71a85d10b8d903d2285c3be65e519223e76cf6a0fafe368f7873c17a0ee851f4698c37dc52594aa11f8ec3f62cf64519a5891ab8c8a09375a6c4fb4d8ead8d15e9e591f72f17294ff75488f6fbbaf4f400cc8cc4239b1529c6694f5f0d48e3e4699f33721900a69a0b527848dcff948252b7f77fb8a1ca45aa2da851751033560a5546d068a2208008b5588073f136cf59477300b67869773e4f1fd4c4a21e6e363b03bdc92e73c6c54b42e75a8b476f33dcdbd772c5ff2bffc02d7741f7840e5c2eb198e66b8053a2d4b5207c0e811b4ec8867714ac1a840b30265098cfdaa922f994952440834498b581ebd9897f49f5e44bc26ad36faa373861a089ea8934b39b9662ae0fd0e3f0f4422b4bd55ecd9ea38aea98cdcdb0c03c8d5adbeb0644561b4d07a9365d464ff9bcf26e0981d227e0dd57b70b5f839455809e2bbd53c28cabc80754b3661dffb8daada07639d822f0d5a841906dcd5bed549e5db0973554457362489ad57c1f21902e114285efc649ddc2834de3a0db9f6575875b5abcb79c57ee4021fa38956590f4fc59498112241e24a56c30a7fd70a4819961bc04b65f387200c12eb809b0cdb4980f47c22ae1e969eb2c414c2e5de4c6257dc90a287b798565e2490239ae4ab55309163377274d3b26212ed1737443db9da49c422925158ae32ae297e01138a4bf879b50c8b15d45c307c8c36d1e3ef1048ef7084e0045a6320f9838310c344f162e5a3490f13c42e0f548836757da0bf3f86419cabd0c4b5c5950848272def834f70e102c57a0f0674428280d40f0ef0131fa634b8432f7cdf606db0d2584df29c42a33ef7b5b4c8e973d5e5f91cafe473a3086ae5d42ad525483b5c2f584952f7aab65193ed3318825c6438cad52e16268e5cc83f0397d5b437d4a8f6af11b14e0ce6d7928312e301bfe55f934d184b52777d7cf0c3789695df0349ee4b32089345dcafad8d3d789f12d316055b894e3c68502698b651688ac352b842d73e3affe60f3133a1f3dcc17a84ddfef1edd6d9c2eb54d536bde303e79f61164b81504a056e4dfe5285672f14ecdfce735d2dbf0afbb02d464c84ba6ad323cace19925e589805ee5c528db2a12a9f35eaf7729214117ee77680dbaead419504279b979601c249c8b2e587b722cac9db8742b5b9f3c7b8c57466381146c1ecc710a5c2a2d58a4b403f197bf1c02432132dff9153a6821808616aa9cfec0ce4ed12b0dc752f410d2069422b00b641d1bd04facb0f03b02fdedf4e356966a9ee8d72d777ecb5c04d802a51bb5107da8dbf396b98755f5fa712c12bb0bd2fd2f25bb4fb78979808696aaf5726381376b2387e73ef981d1a21864939c1ad91cd0e74c2c3e32f17b0d65479a7cfd476fe41a6d3a400f073c70766abb0705bbba1ec42f9c550311f64c5b33ef236487272b87b6fb888cff87199a9818b9120a2e2a9a981895043780c0a0dc058d8f355ba42b32992f157ee39ae988f99ee585084f0931b260820653c3c2ec907d47b2263be0440be9a03e8d040fe7dbe081786b0e98dd06fdc8484432c6f92c5ca20a213a145e89e5d2e13335d74864c0aa630787b9d2353222093fdb546e772ed08998073fc0dcf093edd5b2c375276cf670991338c65ab7db3a07308dde6ddf8538840835cb6ab7e737ed34dab3162395e36154d7b20c01b91c49cf0a09b1df9d711b12f94668bf732fa14b91ea53aacfb864505187b6143f6922e78e107c78611aaf05eef3c1ed4f918eaa7e4bb207064286438efba98f233fa461eea1ad727585548e53460de715ba8a08741afb73a67c375408cd37d34257c0489618d724a315b1626605e0e53becc349f7da1e29a10376b7615327c139aaf14e7131372ec17b488021dbc1bf625b1ff1eda15c338c3b3239e1e3343b5315d09e1ca99d6960c0aef556bc65e99812fc25d64d1eacdfce1115b8923bc76aba6d27e7a1990c1e2c6f8cbc373bdee7a9c939795a8dac1d0acc168aadcd3a6c16696c355786414273cd35ab683fe82f4eab3d15564ff35b855cb06ad0bd437d237192a14291619a4cf6db6d15a2607b621fd139225844e145736c589339bd42a74f831aba910e075c1a783d0053bbb98b0bcef19abf4208159cc785d0976ceb11f847c1962357a45239856f3efd351d7e4309c83d1381af900bca5b9f4f36e70d72be6ebe63cea432e633d354f9f035b75492a550dc04389aac462dc0062c1436ef282c391c0fe9480661ad304356650d823e4c647f4079e09581fe90ded9f0d133aae20c5f893f3845f95512bff7ce10543b30f853e07ab01e0f32ddc94c10ffe53aa3a993e5d5f449f1dec4ea5e42973f05a0edf6b869756912dd19aac15f990be202773b586b07f76b07c0052247aee59c254a8148c3132f95c3a1305e25365fb7f145fd3525b44e571ac573e9937003676c125b681aa63d57bbc44a5187792ed17a84674e9b5a522fb0528beffa7941e1dc6a1d6334995d387c4cab24cb5536a3484ed0e9f65a1ee24c8e664efcbf0878d3aa246d57f1d6b0dee40dea22c1a92b012d903ac531c13c35e7af9a95ea90d64dbab7eabb4e11095b287f5499cf6ae6eb573404a2e7d08a6c34c1981efb2ae44de7848a0956312b3217d9014d507bcd90bb7c144443648c4ac990576eb614c2c39089633223cdb2bf572d5e58eddf86579d7afd7530c853c0c328187cddc9a6ae2cb33c0c51c2fe14bc39641dadf621e86a61eb4738b171f12866755c05c835370d879cd4fc6e65777553c294b67581321e89018b6a18f69c8a448dee5cba39fa1549771a85ff76b4ef1dd2a0c95fecb7e953eb0fc600872fb12bcd29b5a210bedc40a91d8f49f7dfd94432b864899bd451902d141067abf470b313fe300a89632974416ff47fd4ca56721662568f491b14ce4907142d7a33b2fddb9d61b0f9ab1710f18f2023694a160628d743408065fcea16f6ce7ad25e58ad5fc1a8fbf8ebdebaf137b34f5876a60283f661ba9213b28001f65009d0e6c438c3707dee47bc0a59e08e997d82bc0fa32c68a2b7cabbb22861c409c9920b7a58b62c2a8b21bf86acb5ec1767d17d45b79a0bc65b43459b80e29d0ca64173c5b1d5df32d5015721fab673fca007f2133aee161991e9cade08d699792970556b5dfaeb35445f28e04a874b741d7a39b92a08c3c82ddc0bae3baf88a6aeace4d8158d89ee503db44abd5f4fdb24e931c2b53eb385d27c8cdc0ed954a7c7aace5126a3d1377d3866e38e29052f3c6279a0411773d142d11252d4811978afeddf6acaa444164ad6c88331635123b7142fb45e126f755e91a04e0e140c9aa67005e33b429531bf195500b2406c0b50c7fb2f401f82c0afbca2856cb12b9e1bb3bfe0299393241a3ec2fe7836638f3d2b6cf6658a230a3555f5d15205ee70855fec42c1bcb8ebf0d5881d17e93f5a6a2d10d60d4532cb872be867d1cd70af9e49c015553a68b34bc27fe71458dc7ff6a1557ea50d5e799a140ff2c67ee840fd2a3e079ea1855fa6926ac6b33cd40524f408ff146aa3785829bb60302a5339163c60779dfe7fca85bdc5536496ff20ee36b72054aa220477da4e6c8e3c862e700bbbb3952f30b15d27be979ff1ec06959e5a090417af4dda1f3803d72f8998bed516eb55f53307a71ca9bcc828e8ee36c9dd00f7c456c4abf091a9867a942bd74010cd887f4beded5c5e612073753702976014a3b77a13f016835933cb7e8efe7a32788289b956982be42862dd73a2b29957d689826c670ed44c0011815e7deb781e180e74171ae2af4ca5cb50ba9c245881a001bf314217226df8281144f35f9330d1918b771b62373eae4e562e94ed8c3e248b8508cc34dba03b1dbd6d832cb1ba95a70eb202d587c8a99d4f8e0071f17a74970245d34bd8e0af026b27908c9dafefd44527d0abad900ebf051b21ced81bd0a393a4e43a36d565ad06784cd511ef357aa2d01f6b0b3c6a7c767e5bcb40e87a3eb7ecbb2e0c5df4df5a05235ea5b7b7aec1416aa10e782718ed5baf1ec195a879d0701a25715de32e957b67b5197d6e26d491b32acc1c66f84effe2f019cb96f01d8dc3d4b6e45c4941d8da6ea2a408bebb3b33ca06fe4f3d384298c45f97a3fef99c3b8842dc3803b05b143548a180a17a9f2e619a588e7623a169de72577174b3e09c39239c331d56c49e8c4a413a40b3823344c3c377bae2db989698ba5a2b28460bf266ec1b60a0c75cdc4528f8b2089c29c76e6296ce93751bb62a5afa986addf9cfa97f6e1041da6ae081a3ef47d5f84c617450eea3b7bd2c8ac8310a405cefa98988106efa24ebef5c09747896151079c7ceb0d0bd9b28700dd2a06cb3f6a6da6ac85d028a106d425858dc5dd224d606452daf3885d7b1d64d315bb1e3c8682d832b5e6958ba47c7461990bdd848a47b485020d74460379dc3632b878b6f0f8bfa24846503ce6973d5dfed0a909826433a14be2f0cb13bb1faf6d0410073b794718a2efd244c25426357f6fbba2d2ef2f85d1f56746645379c536defc1a9f66dd0971911d365ad962eb0f837a6c7aafece1a7d32ea136ada45890aa2a79323055f85aa72ec723e9e66f5271033093d5f52d30f0fce52ff1407556c041a23df84d4a5fbc290c217a24672bae1554d11f77acc835a2a8dc7cc069946dd09931f4818197721ae965e39f0da1c1e68ba1a77df9367a6b5d4f08092328ae6ca6776c0d66ad74697bfd2bfa51a4e52aab2b7c696a9d78b08b4b9fbbd89d5020f67958b09f20315407f0bf2f34d8d24f75229928ce648974d9e23451521903f7f67e842055bd3accfb1d241d2b251a300dfd11c5f8ea7f03f33383af5df3d69c9bceea35a42192634d7b99f1fd8dd868c75bb478439a026e7577284226dfcbf43b4ebaaf490b4aa5559eff1346bf3479e260f04bb0985d4e25c3edcc06256a30c94a2d0084e4d30cbb8f964e51348a37a0dc6db79b560d9d0090673457a5e4dfeedf7aedd6a460bf8e322e0f478c27d9a219c3d502a09f52e85154b4859cc6d126f0f6a8cff628a8721aa964cf897a0432939e0069405a5bfe4b35d330477821ff601a4ff3ddf09d59fe2176de3bbe505c28acf8463c06761557da7e59fd29290825c282acd488be0d0fccd4a6c8131b0a9add176a15f3807ad2ef81a1e562905b9684cb4b067ab6dab2722f5b3c6468fb4d1620557785f8179a6287d69152dab06c1d603ac0565b1f414df242ed1ebfbfba8cec7c01322689ab9dfcfbe40a467d047985b11fa9358df088608c1bafb368306a56242d12174469a3f4e6107795afae3abece207c8d08dfabe38c7efdac68fb04a00ec40099f279e43725302eb4fdc7e569b26b5ef7779c18918de2ea3e48488f6f976b1b4ce9806edd56c1248f3a9409489bc8d70e58af0f41a32d5a80d2c1006dadc832aaff7c32563d902da9f1f41626d8b18fbf615b67480dd958e20da61d669acafd074cbc30bbbcc026cf0a258307cc50f20a920c5cd58ec316b187a07568d012dc003b0f67c66cfcfbd9dbfac18e505e98fdb8ceec53b1a2165d1d7a6c86a0e1315b3212c170f88d1129ed82380232bb9d34418c042f7fa47284d92131756a4fa4b97e2f9b6f3e8433319bf91952b7a91633483ec39c06bec49fd461143833ccaf8c664e0ce4b3251e1ff23392c25a982c2fb7d1d0b8229a118b8a2e45ecff6505f4863a83e12b0a19a805fd19f6207dbf53873a842d60604184c52e641e4eb02081f0324d539a4cca1571a1676f0baec897e534573485e6e6124c9bc5f55e579015222bac70498b15b82c898d45c098fc88ba2222bea851430476eed275347c103bc9f5951dfbe20844e95abd0de14c9117e810ae7ee95ca71cc39da2aa6976d0137ae6c6b41edc76141a2c6bfe6d3423a2cd2adee77fc5ac2c0728321504dd087afb02fb722c936b0256582b61d2e0c0147a22854392c0501987ef32ab60dc7561dd1ec328041a0c11422ae12eaa9d4ed9f7decd5c37c36f51684ab3e85e3d3acd1fe7d60f828c35ebb2ca02659cc9582c6afc132408e225ffaa303c868b1bd29cdac8ed6b97469ae3ca2ec176894e610024808fb419502d846e39bf22e88c6f5ef07271eb93d2fb05d9319eebbc6e533d354b4059604bf6ce6084049dea4023aea9f5cbbd99c3e521b980a573e8b54caf46bb108120689133fd229cd6158d27b0722c4f1e006041a79c17840e13d7977ce21a636b3319db9e68ad02a0aa87833486f4d66878389be7aa26f11939f5d4e744262bdf802d0af017da95105f621d04d87d1a8685116eceb67c7d382fba4dd4cf31c309bd7a52e09fdce706cb34c88e486d5bf999d10147ad80e70cf20860d4ca2e83d45baf16285e37f3cb09cc296fa86c17940617b2d25c4fc580bcb2a35820206208a269df4e1a31c2b2040e52bc85c2d2c1faee908ee1daf3fedbe1ee7abd3d80a991b20bd660cfab9df7e386b84d35bb9b793d4f373f82aafac489313def3a040cf9784ff62c93a6793a4b4ab8854c9e0c597679f435f0bac7124948cc2e18f42691399ce665431ef135af6aa5623ea1d0884b66ef6136d13d10b3677ee1d706e97a5209248ddb5a49f966e30aa7043a8fa5a91d2d88dad7d6ebf254b864ff682f224d39aa042097e1dbc4e4c6600f9bb2e0e0bc8c32cc5a61a37badc31b8f136624851f9eb742c846b150aad7a6da2870fc321f60c32767ad9509a9c7ace9e3a6742a5d687d191b555f3c955023b2fbabe2a70f0c01b93c364170e3b6562dad5c537e89a6e472cd8e2b5252aaaab7463007996973359dadc370ef1c705ff25b605a5f960e6c6b36a3d6117ef1223e19f7095d1e69ff8de4bbb06ca5c7a4cce88f818323d0a66b24092a291b623635768004162878dd234a4ef1447a33a55db454fbc0659b2e2291287cf597c003b0cad02c915464360e7be3aa08958e8cd1e756e1717031dba401cb1ea179fbb3f7ff5625aa146172ea44aae0c131f737dcbbc6d0389e6a4012d5b68d02a2087c8263a6ec401cbdb40b4c0ae8c92813815f6161871c65696276fb94300fc95eab7dc14210c252438bbde0de0de44e62dd6d38244393db2e61d7161a5c3476ecc8ab7d580fb6b7364cd012260d6c3b991ef04904e49900a1e37db989eb815be57e9c2205bbd1973256e8ba28eb0aa4e9477a489a207e81a797507a9686b3b77658dc014ba5d65e1213c630428f934965f25e7ede7a27dd124655c1ef1a1223eacdcc6f565ae08d2f2500d21087b77d74b09cf7d0699b03b0fd83668025beae0df45d3ed80c96fbcf88bca2fccba626ae36129e9b3fb3df35a32a0e8c358f604d65b48db86223a0fd4d3e3c80a82ba45dadc3d8aee6d8491d85c589093dc85346fda92ee98d7dc1b45dec1956c02d0017033e6dc4bc8c9cc2574fab1f41ec3482bc1e2fd6f3c11a8f9530550a9987bcade1ed1ee77db4c008121813cd350d68e8877bd499d17325ffaa93cf4703dfa0f1754265e539c42f048639fa8eb2fce84ecd3f5b26543f3c8cdb062af604e01ee2541a030950c88d39cf77e115c5aab35d3c9de40558f41a954d26c912593f42229a610ce51c58facb417d60480381b9aba7bef5ed55e611d99b12e54367eccea7a8351e5a15556933d98218b7ecd1cdeb8d93df0118a85c17585d31c6c241131211c23bcda35be02c01d6f37b8f26e06a80c9aa5912956110e89ed8f321137702e7ee95c8093bb6db6afb343f64b33dd3f94cc79ebed56cf75cc483934d69b51845e9952d414d93bfe10b72b435327efef2617b7dc0bbaee370ed466d5d022fb69a8c50a33757927e467999ce92f09f883d73b6d939aac990b41b3b84351b25860e609068d61148f4158f74c2458daa021728fec20edaaa70c3c795a8db25ae285b01450891c34673efc09bff859554e12ae7775efd072f0b5bb1505577e516c87eaa26c60b0ec119c7aafe474f63dcf1d948c0444e3e695e32c2c26d7457977e4cb5113c9c0273972b1327c1bb4c0724b1af2c5c6c4c652805738e69285443df404f117b208e5544b0c25406940e900cfd2c7d2d6bb1ac312e93d0179ba39ea911949b9805ea0c623505d58f31d567501f9ec35ab1be3c0b80e1f26687a171aa324e5dfda1280e540e68873c3f1c364cddb4e950edf8cb41515a9e68428cdc1532c36c86dcc7e119bf24eabea947b0344fe663d9e81b81a1e3045973f422196790249be1a5502fa8a637d5c9ed280bb5bc0840dbb1f1b117afcbec4f5fe42dffae0a7d97c1d938ce7eb3647ff01bc20f86ba11189866ce67d1f15fca4ad79eac8f8b8af131fc33a848b581255a00ddec7d14b7f03bf422268c15f71f7be693b9de6cb9a563bf24cb8165c4e2be1eea0db2d413e33892b88a0b90a66451efc917ab842b911c575c5d2b3220b3aa7f0312ef8c1dde1ba215435884267e0105f69c48306a1fd2e23ec472acc65ff54850f4027bc1998dd9269cc03a39a88ebb4086c120ffbcf2465a3a5025cef2d21b860e8c6c718fd36726420a84811088bb26ce8bab0613280c09291a516b0eefe53103d423c34ded746a365b95d1151a54d754046082a725f6ed0784bff332f4f1d108815a969bdedb61138614484430489c596ca4988568098bae14d2572a3d1a40589697316baba8131b8672f300a520383c081a8fa3845a3b84a1c274d992a0f785aa2c985eaaad89f1aa66bfc1a5310d18e49d738dace0657a2e2f1c85c2486d62dd2d6bbefaf4f46d21950093f4b470c16452382a592bc12818de8e9ce06cd209c1eb72e80f9d104a43d83b8752cedeeb5111bbc826199c888509995877373c6c5fe16f923716f144388d48d75a0958379444b585bd9a109bf99445444604d8958eff2d430ec79c174c6591365522e25231ec2094cd764cfdb4221aba0439774a3c84b8f4ad67d3cb46c85ae620146ac01766ec5eed42dc2a052cdbf3dddcd25ca16e28429836ec72a198c69f83e5dbef02a7919a3097ac0279089805cd8ef5125895892c9e80a899808d650fe0f11dcb76e05ed35fabad06ed0941cd02bd37d7142e01eb7d5c0c66d190e6620f1340f34601d7990a2807771996a615a6e7cf87183a2e40c202649597036aa50e68ff460871145fa7f069f6685412e674c86449bffb2294adaefc51792051a915f88783eb3819f114018cc1d94340e187d130430a5a516abbac10406b413a454ffe0243d99a1a71d07ef5897748ce2ae1576ad6e6ef9d2164362ab234e16d5b4dd05a01d0aea59a607342393a468842c16095089f083a1f0616846e20204a0c2f6de8c4e2f52b4704a036014e0704c5a38678955afd9de1162455eca289fa5a11e2cd385815b94074e4a24ec8819d51021f82422daabdb7097a0264910d89c870ccae30677e8fc04d5e59be2322d6970c79f7aeb3a213ee564991e69ed707ee5047ecfb693c5ff78a88020475a6e70d7cb51e32adfffec020f8495d686a9b557cc7ce038902ddfb78635213db1158e08d2771aa989b52328516254538f9341efcba76babf0b9de514821f11c31cf2a764b58e4b39549d4e9e3a65a10e65e8f545239db35bec5940ce6623b6b3999e85400b609e633be0bfd91c514e04e9c79ae45e0958c80657b782b6972bd8160a027466f8331b54678aa7843398b14ca4afaf5b0acd3265fb6702d3df986da91bb40553b3800a7066732b715d17af63babb0d2556568d99b25f257feb98bd252e96a99341e5794753ce0098cfc2f405a7e293bc6ac598530df7ac9c8a90ef47cdd3f814fe75c3a519b452faeae21ff71fe74256d082f4e01729818cb638cafe6ac16588244aa7808bfd85606ad0dd5f083abd67c26b72a1f0bf6e4a40a748da99c1b779dc290b7d1ba0dd36f619405e8af9a2bf5fa00f1594c23dc71202baea240e4ea3c3d39d6829735b0d802502c4bc7f3a450007deb0a2a0a52eb0a35ea7d03f56c3f9881f429cbc27a416090ef2a70c092fe0157434df1f59f1870c6ea785823ec7ad0db4427f648c4bc42c15a071e265e8759a5a44072ab143dcdce4414a53e2a02c0cea746a5121ef54701b44547a41e553aa6333895542c31b4c6fb09161aedb4125fda0fa0c699addb8d7fae86547cd578646460e81278ec8fe54ed347af2f5b2874b836b612c087162fccf6722b86961d60bad3b8f11322c483ca1b81ce23743299f2a6694354e0f3eb426b88189256e9874c5d72ca89106382a8ecca92dbf955492817d9ecdcd4b81c5ea769d26fb18a4f83f765a6e6404e32e3a45fb416e43b905d148e4edb64248a1a0bfa0d968fcddba75b2be6883ef9d69a9a2f42227346e4374ca89ce84b8c7a0c7527ad1dac7327a9535f2515aa25e8423df25ad871752a363c9c19ab9819fd48bc28bd848cc6e3de29ca9c99df76fb7bf52452fc19c405ac8551c3196e779399946ba83618bbf42ffb9483df687a08af1c7acda5bddfd1fda2073f7e6795b6e07f9eb6a4d77f5fee5187b0bd80a54b030149fff992413def9c1e2495fc0af12089a4ca0a8dae03d329771f2f554fbffb432f46b4025d963a63a9d20588e4d49927a36d06768e904be799e4c675da8be4081b19a159e4ea0edcdc81c97b211b2cbecf3365c044b92749bae342d2ca76ea09edaa04f3d0054f1f7a0c3b156a654da58a6b9540e974f568245358c1839712ff254801bb853e400bb5249039448f19670662c73c87b346ab7a2884625c165c3ad9aa8e987e53bf065b9733f11d8274f2e2e6d50e7370168a8ef71fe0663b6a4950a215ec9c7e21f476b09cfb8494a93cbcc48c956ab20c83e0121b3d39c0f97d88e016bd8b853f1184edf0eacd73bf69853a1cadd287886c2a5de0f3763a8e5eb3ee88263daf2e35c8e23744b145f123a8b86a12c469263287af8bb0c2a34fc5172a08d438311f212626ff60527b9722f0642056d581f246760cb7058bcb80a0e06b111b40e0d224e38cbbab952eb137b9f6c5e79152fab14b3d2c881bec7728a21838a4993cf2b7a5cba45092724354b604c47d7f1a5f2778169b79a51cefaa04481af81cf25e84a7fb83bf7e02cd21f39e0c5003e8c15815a2eebcab296fb809c35d669812729a8cd871388f11b064c50063fd1dfabde1f62f65ed2ec4e11b800cb63273ed46e13f834d58c6d25be2d054fdb370063be9db042f92c80684ffa2c03769bacb33f8b77791b28255000c20a534bf62f4ff194ba15b90e646d638c82d97970aa5936e8b6a7f682ea4c06dabd3ab52f74e08a83374bd622149d62440546f22184843a4c27d12cc24d3b27c34c18bb3e91c7761d2f27a940157a7678221709bf4ce871502ce3ec3fdc734c892dfa236fa85e97f4c551e601608740f7c0ba45ee0e6d37fedd93734458d4cd837d5aad863cfb0d824a4efec8d127e9ab6c619d8ec4cbf9a90789d46f2bd912667a505d2881203def93914c0d588a7662228d77b0553fa4bff8ef0558da59fa84780bd1d302867a5621ab600685d5b458acd9d0d012fbbeacd5082d05602b34e1882ec546d7c6b689ee745b6eb3431368f11f34b85f457fcc8ca6a640169f933544246d7e256fe4497f9069b85e34bc6d50e720d16550e7dd719f44ac66a2a922f7f7626b65f223d87fa8502e25b8d9adab8adf8d76f3fe80ce6b73020de22179332d20c77035ddce2472c24c789f3133f806d1ccfeb333868a1fb1f115597719f93c8028fa45310e025a7a6730c10a4fe029a2c0026cb599ccefd628b800118b1dc2c8fb260e62ae8ce8704f12facf747cdb5c445f576386a686fb1a10a31c8ddde9df98cd3aa9998aaef1eab36fc4232fa206dc0c096d3e516e16ea70a37a97ff2b623cd04169cec7ec996454b49a39505bd32c2f87e53007fb45e8410c90e60fef1eba0aec0868759dd1a53d7d0ba2ecf9e3e3c49b4b6c19706326e50a20f6c4fdcb6d8ee7f3bad6acd0c3a394364376ecec416e3ec222c5b4e5353d1b0c0ad56bd29acf0b2d29c9e63de7e9bf50dea1f4e778215476abeb3aae6ee6ebea958f657626e26924b46a8e222fcc033850e829190e69cc994d8d6ea8f0333b45dc54d9efeedf8ed56c83d28001cad0dfae1485d40043758520801662dd0ce50ae4bca904d7b116e2fcfb812d3fb2700ee8a89f8530028d2e49c8058a8613522a45b3182a6af89b72142ecbf905ad1f0d7c16294c1c29708b57d65ee52eefc34af2bbb22489c25f02b28e28e2202bd9ce9de55939aeaec64a40de03e0e7b16d30a3e227860036c4d192d5f8f609e2b6a2e7267c0b17a6ca10605e1c67c1e0ea9d47c8b695209ad77c7b865cb70780a98c9398255b103b9d5c3e91d27dba2011be9a1f65a5896ec7e77e30323d9b5bc9861f4a693c85bd17ad64d5def4ef1d144dc062332543415814ade4eb4542701a88d35d533436b288c5c97f572fb768bb3a9fcd676e3e0cb56a8cdfea15bbc1239490ceb44d8cc9a3085c3bb663864f53931e628fc5c544181ca816cc66fcd875032a404db8b370aec93f6c844e3814b46e9f5cda8de678e05052ecc4cf34882226049050bc579e104e0ca85916ba863313a9ccb2cf8cb28017605adbcc7c0a7ce277aef7eb8069308c539174bdb25f137f83677635af9b04469828c162ba55b8f8808554df2d688b7e5cf4944bf39a5c5f749e0e9f4b4cb1fdd00e06480ff6b2a439a205808dbbad2e0eb475d701286f5d987104139499f2d547fc81cb019b06847b3944af4e1620a4eb981335711e13600afb0c616100d42997a3323b53be0e5071cbbe94b7eea1e03d62befee31c8ecb2e28b6bf534f077c7004a0ba81bb720194b24d965361b0cdcc1b0971f8443eb080c9d07e111dd76de545bd9267f61020af4b7c0a38fd128d55e77716f9c7b05218e785e0126f33d65a15391730daf4f9f49ed9defb7ea0a7a6c66d4d0c97a35fca335e9f528338f493d2fca280c59635c926a488938aa82850daf4f1a5a221a2fd93c5a6665bac4774a2bb165664cd77eb12ab0ea868a8cb29c4d5a5a8a863b860a298215d1eab2cdf0625a8e84f7d1d68b78db2da10d20aaec80f466365f0c23c3e9ac618fc612e52d43912786894d658b7eaf861855b3fbba1d2038e009fbd4e640f0386d50a7bfcd7bee17e21ea7a01852c4dbfd34104142beafe99e0e1300a966bc2620b6601372deae7de5d4b7d76249932cd84d2cc8ca3982a7b1c485a13d773e5ea5044998af10282811c76d1597bdee892afdafc711c42e780b349274e5ef00ab625e07c5e5730901083afcb4e19d27a6416024f1139a61572923178d4f8d220019685a95476492e7f46cefbb248b0a83094e36f344236d1f80195cf5fc8770cec3fabae8e80fbe14954c775bd17d7fe90859a40f1a15067de40acf498b5c1bf65d83df22574e48f6a88c0d3d1ccdcbb66f7438309b3fcf8e765e91409db8e12cbd000147c7d080a82a3189c067f4d53681244a27fb1f0eb66e25df65b96e5e2b13311a876ffee128d2951addf4d1e6d17079fb41283433e687ee2289f5bc376095385fa9b64d0d52688287a0ae56a3f334754a2181f9854a4fa1f98f5357a186bdac5e740eb98a3789902790a0855bbc8f42e2a1877d7033e928a06370638d390d48bdd42e50734b122ca6c13bd1b25821dd21d9d2c703cd5819cd3bc4635ea1cc0f0e80dd244053a7e4fe8688e17f243f2a9fd294af5a118c57d569d424d3fbb819c40e3fb472706b57ebc5f7a9bbe69d77de5d6a64e92ce6c77cb72c7c2d4e18141453be339dc4c2fbf762ccaa2507fb11abd09816e8d840437fcee37b407c014862f10b811aa8e2a87ab0f5492fdc0e2281f25952abd12d096a3a47d2e8119c6644c7cb81dc7298f42c16914dc336e7c80b598ef0a596d1ed9108bf8bf9e428c8ab6426197834987bf040b299850c0a25471e8a0ff4179ea21b75017af530102c6e4c7d2032f9680d11f0722555d68fa15210617b6a1c8eb16ff7665e476858f08100e87ad83e3cde5abd95bd8f67f369cb057ed1093e175eb14f7937fd268684a2777e180be1cadd3906448d6634002f890eb84f57a7d0632c07d6c8fa18577d07db492e2193432e2ae7f16a0b1038cf06a75bd9e4c3ee76d2cd6962c5face4dd510c199e5da60167e02f4c55c56994500ab3b641e037770152b98f388e0bea2382db0b41c1945f714f13661a9976f87b31a444a769103041fefc97132425d6f80bdd320d45041df56d10ea1ad919c42f6522dfd2ce5e0d25c6c0a57284c5986e587cfb7e8df61a5402db3173a970cbd7bf2ccaa1f47f0d1656c8dbb5fbfb98220a35720e67d05c7aeb427a75e9c400653e598ec476ec444050ea025a7a8ba8c23821966a2cc76a1cbad0435c4c1e648f4c847416bb6e5144ea8a3d3065508b5398ef79b2227f89d611a65b439d043525bdb669be64229403d2aebf45698a0f45fb6182251308fe200f2f9f55258626b8958e038f60ce1623fe7065c59e87d2e987027f923461481f41bb0a16d9dcc4c95e03a8d1a4b239db45bd8fffdb0e166672b974162e7ae489dfac8f227b0420a1a61215afd7839ecb1a84c0835d5fec214637b6ae68d230b17ce4345cac38b6bacdb4d8fbd370490fa6c3899c5916531d90dcbb0ca90db659ad244c1e7096568f7b09af6506cc5e00f7880500665ac9d943ab4ffd65159128bca4e50e346218016c7b381b8e2ed872ca4d146e2f1eb041efb21fccf286e5807b335b1408d14ed35782ad3fb4687b6c5996046557c39c81d80cd1d19d97df5e07ccf957a6cd40059b440c05cf4c3cb832432c626e487398ea6b67590bd18794dd880cc0ef6e058f9888fdb792f5fe9f599e896b22b1da986fe6d978a5e09d9422c9154bce5335fdbdea74092eafdc09e2817c13e0bce6a4e7bb09ae169b85dd53cd221f57d74c2039559015b8b5e15416ad7f050bc316a0bec9159d7af94a959b5f05e927077db68f4a38e68fa6dc8feda75c0ebc789fd3ff3d7f31669998cae2cc1cdb071b1a02d9dfe48ff5e8530be6e9b66007e613bbd2242ff7672d581c7a1fd8dbb8c687d044e409c61c6bdfb1ee7686a3b7af09c1149de7f78c8600462b5a7aecb669adee6af82f48aee8334e03539040c018ee7122ae5f67b9d199fba8de9e82d555d180cce93b7083f8265581cb5067df415033f0388625eb044da68c64804a583c308d865c38aa82f055f486f9653936ca5ab26e18da56e9f44ffbeebf64c65ed941ea254f218f7568729861f1c6a94cbf4a4181a37bed46f9435d2fe7f535fe884bf8c8ab2ec42021ccd8a3cadfed8af9f20f625426c3c1fc2340dacdb4f93657f5731289111eb184736d4c1384530f8346eadefdf2908a865273524f53b3a79c06078b3ce2919cb5a9ce7c50c2a825b8a403fdc2884285e8f975ae285e95495124326b6bfe8a6feeddda957a573e5031dc8d6400531a0c7747316c582106cf49c456aa7948c4dacb410c2a47d48e584d4c4de69e2840499e4feb58f24bb5f5b2443754ee388e5bf9f98af3896eca510312f1141919c51424c17333b35cb3cc21908c0fd003f840f011d3943c7d561cde3bb531b935ea62e6e0913d70f463b394396cc4003d242dfe9884fd36904bb333cdb88aa3010550b54c763c2b33e52eb5cc3c8255693ffa9d96876b61cfa4b40e51753374e737c1cc9edfd8f9aa9b8f6153adb2fb21ae132258d20a8bb240f6281608f4ca6e3e43add4bb64ac2c4ef84e3a18cb44b6ed764752a3c5e84f1ed55d80fd148789771a36b6a4e699617b58b58beed73a9ae2157a005c5aeb01b3c6e92af940736502edd2b0ae6186cbc3e34203ec7285d77fd89abb4c770412a3979dc20a0c1fb898e32904250ee3ea1070b1b446b8d17a5685e8cc4c143c257973bfa27aef93c9a89ca3aed188c778aa96c382c2ec3fd5c0be1c8eb2fcd64fa33f05aaca1260d5bbf396e4718e72a73646540eb8b99fee720adb63e26ac97b0f36fd3037fad32da7633d22dc2e7be1615b0f70533f3ae73c3e8f785c3fcd3d9302b6246ab00e8c0cbaa2f4afd0731d38eb9d10e35fb8b48068fc29c424efc7876b5989ea321127fc0ec61ed32d9dc44d728aa24fa4fa06180bd25c4406961891e42593d8aa15ccd65105ad08249f27efd0977fdd1c90c4b530f628f75fa88fcb31d19648e17180c2dda71d59030910703d7268955bd5e8be93ff979448662cc20c026900b674561a0d613b633250bb10544e2294d8685bc6838a1ddb41ca4449d76c2cf68295ba499e977cfee09285898cb2b0cdf25173a0b6da386ed4d7620b3d79374ff41940ee64160418907050d1433c1836935dec9840420b3a02766fbd84cdcf112384f6294784dcb8af4615448ed0c961a8e1c7ee99940eccfe12b243e2743a83d4760849d2e6ebdfc20ef9838b5623c3e3249d50a33d44b1773b164788e5e83ec2fedba78322b049e2f53244898f40694e4a894f145d7399b06c48e28498633f7a08cd89a3861cdad36dc615bd158c4e7f8288df5eab0a67e364d3464c13c7b948db7d21dc424490b5b4f835d9a1dec888652f8d666b758ee17f2c48fc520ad975b26206bd0a3fe9dc9abe3faca91729642383ec2d19dd8146dc26e0e2c7c99197f7b5c4ba847e527119eb4c4838484c75ed83e3610815c5a2cb4314cc5fde47597e43288e4c0485b330999bf3597eb88f87d0e74121ba08fb7e024c2bd07a549f1fd94072111df544c544c5321dbfb0ae1557c13a3df70b7411fbd3a78bed8ab373000a93ef409cbfba42081bf11889d8a4725476aff41adffc82c249ecc4df021242f856148df96fbe22a059320421ad28096f5bcc759b5f6910d0dc532d8f3fba639d2447368020a002246445ce23c10c0185d44b78710001ef0a2f8a53b1408b1e8de4e28c81de1accfe78980598924a006cc66b001dc0a6603fed3a1aaa3fe265f1373176fa30788e4e79609f7c7f67bf7be1a97fbe68f8218188793981f3dd8f2e8e77a823b91f2a96e2b25c6bf0e978ce0a72fc8449ee15bb378c64c5ee07e1fedb8e636db15fbee28c86ac994cc1c02c308670dca29a2cca29095aef870c976f433efdea61dca41b333e73dce1805ba6363dd3758d04ac027f2e0e37f7ff8ff7cde058d79fa33b4c8be5b9d2040e9931509eeae37e8f86c57b9ddb67962a086cdaebdcf4a01361e07d0ff6ab7c5e8ebbabe792d13b4aa5a1ed18aa9edad75c87bf685818b84321fff47ca5b702755f9f19a9ea02130b6e5e8c8246676acc0687c5266549369fac1e10158baa8f87ea554fc31b3f6a5321d7295a4b76c31365052bba9964378ca8e9e856e7cf3d39c90e17446045f3195fe6f41b5ac27fdb49cc2aedc4820856849fd14b96bc47a7c56745b632f0feca2f99d4b5da2ebc1578479598b4e1857af38939ff9052460eeb265bfaec715ef9fd7895abc1ba5cae28c79a4846f1ec217df5c476d3a19cbbf2adde5c3184e487721fb4203093a7269b3dddafa0f3acdb214bf47704a303bb080ddcdc2add59b10245db2ad66e1df00c971a17b3356a525055aa85f51fe9e6fc6c565a176d3cd0cf514976c7a1b7fd1b551dd715a26b3518c856ec67e80784ce7165e26838ea63ae4c88e71ec9422c409d8585aa49cefc3279b442103399f3dc4f82ad79f45fbfc09c84a2cf71939ee792cd7f42c305bb6343df11090a758ef830611d73b07c97d0ac3797f2f74ce0ec1300aecd47a073b2404d35a0e2c1a572283ab95825df44895e79994ded249800a6719d470951701c8e2292f7addb289c6f9b9ee8ae7f05146cda658a2af77da64a2016afbafc24f6d85c7c055179275b5233ea06d5bd335f42f7c58664f2a686df3e529c1789c6ab306e6aa74cd5f6c7bd4b257ba3ee78cd4785399b94a1b92d9c41304add0a0adbb0124d663a860615a229697df67117536ad022cecb992b02df0846c7fad9fdfdbec73ae7a3f8213d2288b80cf41b0ec704614574dd14f998472ce96e66f707ef58e0a467298f916e123956c2478312f2a62cd167e1402e60e80f80af784728fe0cf967d171a2a6c812ea7825804de6d8a4d5df932ac497c256b31abf08adc5fa6107cfc11fd493aab47d2a5f0e84a90b71fa1797cf3ade87813d866e4f26e44eaadf3bbe2c66470a751a913016fdb65059b5f839d98ef4c547567fa348e21c3cef404fd5740b2b2a05aeee0da7ab1ec2c4ad9c0e3ad3a5db59b4a3df4448f22e273e442207f3d2754e61790c5c2fbde5e12ecd02d07009cf237079f99d4777090b80873b5c1e83fba5ef6cff52332705518fcda1a97f7a4072ef2044d3c4e802764eb957894b731b74ca18ea0b4d2e2415e080906084266b3af63c5684c6dc3aa1d15e540c45edd08da78375958423ed78924268fd553b9434264952fbc6773f21ad41356186956ae4fc66b542e5513785eaf8207ef7b89c7cfbdbd99b992a4524388c53f3a40a4fa6015f0a2664a0fa83ee751d72fa1432cbe1a293c6b72b1f157d53981a2e08e833178a750228403b9311e87ea52fb21643a27b2bfc5459c27e218e35c2c61e6f95536860e69891b3091137159a0b6a08add4dd5d762a39a52f5db292b24844eb221c5b446a86228787284a5a23884074fa5a6eacb7fb87689dca4e04140518299aceecf6378b60da5c3aba22985205437076e64cb72b25387a85b9a5c429e05d24f91901900530cb4f4666c1ce2f9c77ad3a75add49b1679ecac04263d8bc92576f7e40f21b9de4263958e7e05bf5664f3f7a05daf0f573ccefa902ea2bcfc75280c4c99e06951e3a3b9a4b0577359be24396228689929ea5284c3b3f9bc4ce82dcc1aa39c0dc4c5c47d57a0590def792b5e045855daea307390716d541b8006fe5aa563ac23b19158d77aa203923a635ddd5a3475109d731d06cd77e321e8300cd84d654c0cd69e6015d42327486fff4c0a89fc3f92b25210659579d256037e352e64fc3a55700b15d49282caf8854f75e600a31e6754b71b605a9a06f300ac6e0370e46f9c7f702a8d9fb482761bd61d3195597d15674ac83c8fef58e422de43444499538cbd63588b9b24a835325446c69633831d3d9593c3f10d88d136b051f309df66c1d38f84a5f8a6075ea68901e4bf79b0e613607f5a1afb1b1d473168625c210726e479f0d72c9be29fab0097304f6bb901c051fddfb15273f29d983eb808ae695e0fb3d27729a943f3619ba0e7af1dae3b5fb45b65ecdc598ec8812101d47c7d924d63998f5c00086add54b647e8cc886fd25615b8fef3484d51a334329d26b8b4884d383f40d392a2e7e7d7b7501c4905aa4f772b9de28737613b4507c2ad4d772747413b058778a9c179d2deda0f3b853316e388601906917cf027c11616fc3c9984209f7868810a54c9401347114b003b34f1a8fb5af7a4a0c50c4c28d25219021873817f5f366f1e85eaad992dbc95f81fb3faa3dc93f40e910249a4d2ce3e63ec6fcf9bb7b5b7e2062a2aaec7af502da5ee929ea92560e022b2d85484a45d0b53531e6f37a171667e1ce7e19c0183f641dfb5f217e04a06f1bc08ec9ef69555e6e1bbfca7926929de44447202a849f4bc3c515c103dfa4cda0c9980d46a4c036e2dcd4fa8229cd565e559ce8435d5d2bb07eac99487435307c3fb9b02c960aba1015907642099b63b760130fed9816a242249a1e7e48e7caecfd822780d9549217db1e48f1b7718cc95fde86db8c8c9dcdeca27e816673c00e91c003f0a4a2b6a286c3d662d41b0974975d3e07240d9f34948bfbbd311c0eb1e7405891cef2eddee8c9a3ced9a92eb7ef85058734166de2a0cb12b7406dc6b13cdad24f7982016d45551223aa55f0a6839b70040e85cc933e71888325d63e07247e6499a1fafecbbbc736b7ec96c1c768e9481d6ddae9e2536928ed7f835d360580e5705ac74af3c9a78b23ae5dac0374a45dcdf4d34e9d38842223fad059fccae288eca37350f9f8680a98ac039b3742a672d3e91b8299200a5724130bf6a7ae1d9b472cb36b5f156047b00a7c55132616ce9dc59081f38e4d6b7279d56b5d9032189e0270bbd7125be2bc543e51b83fdec5c86a0aa49915a12af03dc612fa668883d43a6aa2e2d68a3b24224b9c18c6fd4574a5fc52d705c26960fb3345e5a7d1951212136be1202ab487e80fc8f06230575a11f584091621180b45f6aa046abcb78f04c0dae64fa2e1761fe9a7602b5b735bd7a9dbce821a7a935e615aeccf9e9fa2235a955806bb951404be12a126e742e5dd0722a6bf17dc2d1a1c110ca72a2c7c63fe0b62850a9b25c23fab3af0a62e8678da160a10456d307efdf2b311d573ee08a1dc958a9de3d48c18d34dd272f556eb14572cfc0d91dccc3fc07459237237d28a7159c4709c952e0d4a50307856964c0fb5f66f0d62994eea9159b59ff067a0b20e508aadb1b3e7a4a63009a0ff2e3893674c8e4dcfa4394e814aa3917d7c56213a4e7b105c43b3dce936629302b2bedad1852d50848381737672d7dcc7dd201f10569af9a20f309090ced85a7aad69223cdf1fd98d8662093340b068fb51af6bd6984160e734561b10a18c12d82915202fc9ea0faeb31619a100858ad0ca44a10944e659a09e0a17d2c32c32cbbf05f93641f2a126a4a778ffe9da8edb7893cda07eabefba4876d5af5a51029e1b8d98c76c85d4585b961d350be67d315868df2823cfa6ae2c24e692277a14a299362741d4362b40230c8a6008ce207d9140340d4b43ca0c30337b0beb0492d8e51a5fc31b27c711482b587ee7313bad38060325f32d908f8397063c50582a0066d69a81eff19a0025d96b6b423f570f6c610b09be44867c627b3d8e4c5fe5f0046ae5ab9ed3507155ddfe2916c58f917e0fda770780ec6c83dd2fa1770981f42d7f2f55fba4dadb0029ece6c0003e61112c7df1daccbe8022bbec9abd922d3ffd5be5e9b0be52188aea0ed575fbb458b026d23aca766db1e3968c64ba5255d9d938e9dfc740bb5f5bd8cddc8846c5dc771dc0633ea26c862230ca4c124f980b51b336ff0961163dcc690d91b55633aa19b0a009aba04f3653994052bc4936b422807dd9a8442b604f79b507b5e0186132d8d872f80b132aa64a4dafd5a31489bf1b34bd47166125ba40ee53c8802a0fb1b5d153acb6e73d6007bf2a1e4ad724f95bbd81802946cbb613d824c457871d4266ee4c2c9949fb4014fecab09745cf989f6f413f447abcc5141ee954f39e70a534162b4953d713af880c0ed8884255fdef2e2f49e19a847ddc86425d6afca6f0ea4e81354368d89524836f5fd43d555a56d9d669525ddecdb2a37e4cb3d851cdd9c426bb4378ba8b680dded303048ac43b0cb25d3367a55d28f1e33b26bfd60c53bfd0485da2fceaec1489c5083a891caf92d173f4355b6b5ea561099d2bc257c75a2d21075321a44a01a378ae5da1a074dc0b67233ba3b3aec70e03e984f73504f596b4b085e2739a3aa016fa0b53811dc0319d21a7f6fac1253d2d8e6a3cf0c4d38c340a7c09b1da07e533693fd63d8c19d9456a56c34305cace8e882009954d99d75da0c18ee336a55b7abc5b1b26a640d670a52d15e52e66e283277098cbfccba082284823a08b61c210b6baa969c21d0314d700139c44fc508788ef19664c67cbb248d5d0180bb5724a55d4bf20a63f1ad64c80ea09c40afe437eff455c3d190fa98d0baee56580da3bbbe46848eeb04a6ecf35c2086b54588a040c50dd6b001b820b693074e5c469461d4b0f56b746c984d502781c8bcd615bb05ff4b1813084d793d9290c8ddfe15af790203bb2a81b139b1e1aea655c687b38aa5670be17b5ea251f60743fd8db89687eb2a15a8f4bbc417995ec23cf592b2dccc0325c09ff59291226c94ea06fa6c79721f8798789ed21ae3dd5ada204cd2a7729b67ad88b61f9c6d5ae27998d440cbbb09cfe29e494c1493b73a07c4b5a82bed982425698865237905e69e5e1d72e19351ba2b10072785bb4bae4446b5e5b8b54d393d4f7eb5b8a0bf7a91dea42f610c737fc86f72e0f7222317961ab83c978a89467c8abfebd92eaa279e9b936a702df16c2d27d9a3768365210423c558c24acba5ce48aefeb2081a44bd460201c3a930d952384f23c498ac4312010613926b14ec8c09e172c2d4e163a866f1b01dc1c2671e386ceeec2b6c08fa9c82a242894e6f47e610aff3ec17fde32f2c91d8f6ba1519f1db21619096b3227974ea734409b5a41cddcbc4b31b57f806e50f30797649dbc5e73222d137302f5a9d3ae5684674c3e4ef6c2697492b9081d183db97b17dcf862b35592eef84261e4ba101616e670a83e2b43763444eb89075777ce023ce1a00455923b110a280569a9f9fd0b9b7ade099108ef6a973d8ff2e0ad30e7cd30ac5ddfa168676c7060140a35af93216e7b4cb5b19ce2e7d504630e83499fc4a2c1204c3e2965b9ec4ff93862aad244f7311bfe27aa8a0fe447267061a0ead0c943249a95c48205ff2668d383d6c4ff6b1449215555b5eac6b5e49cd419733cdde7e9dd09f65e536d14cf382aedf8e7aac271fa3c35d87f68d2dc1701f944173f8692ed727015a29d5c33b8809c46f259fd5557e56b028602061d2018916967dba43080c2359cd3334909a304207dfc6fbecaca1e8215e77a47d7bc89ee85eac97001f6af6915065ff18540bd7262db7db9b761f721f3a6920949a388145e138a94a4a6b3c405e6d71ff3f609b88058181e2fd717dffa72c10968f55152c38291fa48670911043f8f4ed0a30cd0f153a6625889483c38dcf47aeff01dda5fc8b01c0e036432224196ddbbae4c1451370b70ef2f67045c46c297918035c03ff2d96554835b4adb35ef7c3944c5d3b4450917d8dd8bd0ef61bd22e35ebaec1814e58e8ea8782a4ebad270b88508be79ce8bd642a30197dc13a05811e08054743466f4037774ad21d16c44ea7e0c4da2a74594932427b82d32c85d09e91527d91503dcd097b9d377490055288e164a9771f1b283b7606c8c4940371e64ba5ebbe01c42dbed147aacbfb4086617d03f6eebde136af89a72987146faa71e54b50f6ae3953c867c29e1660c94de96f7e611ace072a5e661e2630fca3daa317d234b195b33736f1f10d714b0a05a4226cf198111cc2bf0764fc63c021adaa0b886e9a8e8c6a53cc0f20e3a9531a1f24e328ddd88653999b9770c89c77ee52c864a9b31ddf908fe3b635b9cd81c0ea4cfb868cb47a08f0512caac98ac1d0867d10258ca31a48117bfe8667d33d458aaa660e05d815e0d80cc556a36b1c7685dcdc5321a263f2be99ef5d5bb6b262ce1ee80b933913f841af502d1472cbbbcf02f385f3c64825dc65894336cfc7fa8e5221392b8f418da756e87aa560c22ed0c7d01327ccd7a1a55ef923fecdd55007c6c031af8a33810e5754001220509ccb6039e2b028a9243c5d1b52b7d5f657d4920a227598474301106f6b2e52e7f7c2c1d148492e209d900e02941d7c9c1907810720c5c17affcc1ce629cc6bd4e04de13d2d5d9ff5992896d81c00dce9dcc01d7495f539fb26beb36fc76756de398dc279559f25917f4c9c50ea66d94c11f98c5866f171b1dd6cf53320f4162d4a242e2049b949073301648a764035994dbb9db14e234f00aaf761c1157ad76aa80b547e736edc038241424a03411fbc12b70d17832220d25fc281685d2acad5a4a150f5b320f2e4e30248c3e214003d1c092e1a8f58489035a2b7c79adbe058410b158ca59dc058b10135a828be2b95a9e1a350299c6456a2696af35419e378829f518fa22e2dd874dc30ddfd45936a1db3417bd782a6f4aa55c1a9fd80c1067eb0ae2b0c3cb1802e69a871604864b614f93ddb72a543cd6437e45a1118b529223240df0e9af74a6ec5f618471009de71c0d57bf5311cf70cbe39cb541f4df4ebc395383a0fd164abeb369a107b0990a5180d05d4327dc88da734084d7ae634edd3985fe8d8a96f683c1a5edebf5bda8b1c4ca0fd3b1a64de14cfc09f3cd227e39396544bc8f906c7df88539d062c73d02e8c9b89688b1b52ec90097340770518f25bc40a908a8d28b0521883eaac2c9c6f6839021ef0520622775d4785d2c8a91443981eecc18a4d82b8ce2e9cf089bfa9a04fb919a9a3637dfe7128dace9398643f1987297ca7624578d60c04999e6c2a14ac8c7945268d473d50debc28eedaa08e73637ac3a696071d388a87f8fe94bbe742e058225f5b1a0460db24a0fcbacd726806723a23916a0e46403c4246d22739547cbc6859d83ca6efbf9b4a1d2ba64116bab662680ced9cbe88467e761f52112180b601027f036dc9d2bfabb042c4485164df92f2b130dc08fc9448be8dcf21e3098baea87ff6538153cff150c66a2dfb61e2a6341b3a545fbfcb1df27a8564dc1261ea5788cb160479fd5daab2524d63c78ba57b7abb1068b10e73f4a973f69b085f67384528d06ab299bf51f92085df86f472de34dc287d4935e99c48d6168934bb7d259d7eaa70837442e4d288b9a9fa4e92dd2bdf023bac04861ed5345110dd3acd71fec5410034a0a3e39e7dea3b3a2c2a6ddab0f72e75694a4814e26fa94a5ac21ea59b8158e8f7741de076f4cc293470829dce02e9d3acaf146d9d18a787b10374c5ab4621a51bd402a34a5740c1eb08fc6f25a3d77b160a67c93e063a7d18143e61cc075a51fb5c3a8aad25a6d12675beb3741968df01f967f62985b1fddf50e4cd9232ace1e7ef3f8ce092fea6a51bfa22b88f3abb057b5b6de992a0147de37498612f112fe470df69c5962aab869ddb8bea688e2a94b96e02a9d803fd4fe29bad71184a0d43e31326a21698e95df58d37eff6062d8ad7301f6c439d44aab68c14ed4a014458d515022a3b265758becf2adf8ec13d8b5b5896ce17426fceab4e7d48defb163cf4461adf2aa0f1d0a7cf09b2de809234d1baa75db1a98ec6ead030af962faeb74294065fcc96572da9d040ab3a8497f41e2904de0a4f00d90ad177dd83cc54101109fa63a1cdb37e817f7cba71734231eae860d144f73956f41db805457d77e577363bd241ce95bd042e41f38063602bcaf451f790685c8d7bc45be0c89b61fab7af747a5112cba08581aed671c72d2f7be35d30ce8e0ca4db1b77f5aafa73f706707fda9acf8f4b5f70c4a5df3e56ba586f696d65d1e1390af858eee13462a4b7c834e84bc497e98ba74fa1f56784c598d8c742f84c902cb9c3a22fbca9174f89dcf5b5cca1c7efad8d2006a520f4cc80391d32e62558b5346fd4a8ecd6a8561269f58a6d8a46120ee60534ef678a4f544f7e58afcd861240609a88ef2c46ce8e5fafa5a4c9902a8fdcc66a12857d05df52544d595ab3b87ec02a66217522bc7dd6623556b17656cdcaccac9cbe0e4bae97edf954925760bb0a0b185668016e32a0c136491d1892dccbdba844514a2677e4bc4174e846fa784fd543ef66f0eba712bcae783cfeeeaaec81bf759160b9b81841c83340ee21e2a4042cbd99702cb6f5bed09309e7730b8a983b5376b0831c7fb6b1e9c4847aaf9e1b37e3e2cbf1093a4bcf4f85eaa5de66161415876c9c9feaffa6d0f352e4c1e8588eef056abd7a6406e2b4ffbe27e3897bbd2b7cdd489eedbcf51cb7588556552d33b694fa68eb92ee92a2d5976906bf04b194d56b5d513f42741ce8512833918e8b124f7f2528e55252951636ed49a7e590805ffe204a3ae6e6ea68503074b3f1073a1ef7b4ad50409e6e2a6afbe32233682f77548b4a1f7059bdb4eb982fb6eea38ff8596d15081c404116ddbc823c9286fa270af2d0bea6bd9651aa219243c08ea44c0b60ca3737c1c66957c8f7e51abf97f99745826cc4e2f6c178152d1792553fecb614c1eae6762bde881444b577fab251f3191ba58af5b1db0089f2eb43e4621f97f220534dfb18990a89b3e7f83f42e6e3becd44420ead6a8497013899b34582cb9259009e6bc4846c09f509d9f3210a19e741f1259c42cebf9b7a98461ad991a68255eb90d05a7697e5d132003e433f97166295c67a7382feeaa7f766cc5e8ca646ddb83b6b635b61e902cbcc439823a3c77ed075f87dc9b2e3b324e70bca28febb7857901b00f706959c60b3eb6769edf14eec72acec90822ca3b69ec4e1461576fa51a4dae8b64a3e755ceb9652445805b828774ab108057d2beafc1c233159a5adc4a9ec112babaa0119eedd2f298dedb9334086f1518479e9f21740d188d9ffe3cc61644c5715e45aec2923f8c03f96dadfa70c90d167590f52e395b1a01816cc0ee585e2d921e41a3eb1cb260048c1ec38814957f0c52512738d0ff143fdb4713a6b0799a999ce13330ae6d9eb7dd813e5a5b1c567d67941e1251f35dff71811d042c3a0bb409366450bffc3f5a5ea733a9af919693f43989f814673361888459a0431199fe69f02115527a41e7945ace883ce35d534a8cbf9816027fcffa9827d59584bab87852bfab2fa3486dd141eccb95412c0452fd23e7f7134b80333cc9f1a3e0d564b8f170f66a9afc8e71e27a94f3de4cfc5fb5a3b8dedaa31b982136ec4f60f59506a9ec8c42e9d17b4225c7397798a14a9e89de0c1e901f645489b869bb7fc91ddcb0725a14c79eb178364db72eedecd854ec4f702be604923faefb575a9f13408da4ec238f8b3a7396b47d975d89c0a2ea7916b2cdb05437b0700ca268f76b8aeb52e613c3f65b300b2052024e5c673707395cd26e687645f659ee7643370b513d1b55aa1072a8068111b6cd93e08dd14ddbbb81b6b4efe5139a007979a8df5f2befc7d8bc4072bb64af57a4a0ebae1987246e2cdcede9fa5815831a58d36ac7cddc9f8c6a3c5b12831f7e86c97cd23296ec34b162ca04190fc4aee6cbebe68c044bed20696c45b0f6f33e0afe70214bd67964e83425649d731138a0ea869c66239b95e841b7f76d0a862a9ee11da4c948bc55a0c6db9694bc0a24e9fc56f50eaaff2b9be92928e5cc4443bad601ab93eb05af381c4fd445248360ae7f5d4d186549ee9bd1870bfd4f702fa58a99d73b305c29eddbba357e12de3068a60e9b4abd7b51c4d2c63f83b62c3624404a3dc6f519b0cd0129b049a1fc5d4b6bf605eae63b9536c52397b34b7e1c7eeb65cd549134d605f3cb5ab8048049b8f6046042f9af7b4907db0da04eda042fe9913015c9803fa9e2e8c5820caca9a0e3dea21a8e732941ca3a661f277e14596f02f2c1416df9cca29bdefc972c44a6b1128c229c3637cf8bae04528550540112843455686e0aabc457d6478bd49182990d967461c9df879696defb626b79432252903b708ac08dd0879bcf986257b59e26e6a76b2c4dda844d92c783966e8398db019913441217376370e8785a343c533de11dc59e286a8a21a822acbaa2c714264e5ac5c6bc45e562a8e22c4f2f75ebbbbbb7f278c3ee008d5a7675f7f0709cc63c5923a3821ae3250963821a2b2b7f3531c81e4c9e4433824d0fc3a275365924d2497c9a48b180c9ed35a6b31b673eef4cffab1103b507d1c52e01e7f99b3d96a53c9c5895466893349b6daa4f13bdfca410820aab0782923cd18b5eac3086898a325892c6da6a8d5bfca59d9c531962d9204aaef17865f483d0506eb9d4cd2fb0afcf5ccfeed997d9eb7ef210683997abac7effa995befbd6496627ad128efa581278e0d277ba1ffeb3e8c4986851ec3ecf1fa22b735d5b12f7149cf6a4f11fcf4f1d36f853d44b0887b6645ff7ee622f77087271c279a5c692c49e243f34903d524482da9fad3a94a356f5298014a172e48f952ab3c56f8120615345a92c8a1565f222cf4be0c0e4da651828e7fbedff9222fea2f84d1067a61f089f8eb1d87b0d82b1c6379270e1e27d24e374e39b9fa843b37fc33e3d1b4ee6fab2888fd4f830ffcc21e22af9f0ffb97387eef8925f4c34210c3beef837d18c42058412120881d1402beccdf0e0862cfc3588218dcd9095b8fc3fb9f7d3094d9821ac0bebe5e1e4ea9d70b7c7d51efc03c58384ed0f3c219357bb805857ca2f442d8c360324fa6a6a6f9d79fdf7733ccf3c0ff602f414f1ca1cbe04b10e618070bef8361f71ecea69e79ef791e4abd5ea07f358cf27a7be6d19ec59eeaf7cba6b59a9ca4baa9db1569cf5c66c17a022caeb4d5e57dadb586f63d3afbbeccfe444260c9e3cd4d2b6a8fe6ef0f8044cd9da470b79910514f16ec3f714f81c777aa4e0ee4ef7faf93d31558f62cb492aa1395501e4da306c8feb32f5c32e55499b2aa9df021d5f0a4d685be579d7c289440fe405217dcfcc78acbeee443b22675abb8af4e55aadee4905cd303992270b061ce0f516afe1527873ec0c315575c5ac0522aa3e64f6bee8ef1fc7b47097c4324fef58db27da2dc753f32c9dd5823d3b7b767b4093f96fd4c680721a408f1e432a0a748eeb7e1542149cdadd6e30236c25d230922996207dfc3029eb93b4e8a2ae3a4a64c30c2b3d9042d60890ba24e0e624ef617414927f91006fcfd51484a9a49f24a8993f773f72332c8bfc594943495e6921cca8097273850559058a1859aff6492431b2401c6117466f80289889abf043d1ae4948379461ea1934106f9cf28b287ffa4338a9c79fde84c924154ba768e9ee2f44c66996b1e67d228b192a464ff23494cf0ac05e96bf6b5583149038549e69159059687f5b77eabca2c7b728f8b5fcf08d95fbe4ce6433f0dd49fc308fc435464f40a6750444546df0dd7d5ba5f888a8c7eac081115190909111519e5ac0c9efc695d61ff01ebbffef4af175c936a52d3a44c0ebe9e754dca4955a92e5526068c298304c3183357920690254b162e43c00086935a7fe72efdb2feea94c51275cad751ffd2766f292995524a69b978530d9e7fb1e00984080c3c7bae64f7243c5fc169ad532bf5b682c2ecdb40d2c6185ffb6c9f5cc8218fd63578274b5c10629c0862cb551051f004028c1e2a5be255badd30308e2c7140b4c96464d346e72b213528e47aaeb6615c7c795c427c5d0fa10189694706251c10543ea533241832438e8a1c4362c012fa96c2f6772f969293325e7c446cc8143ab81fa47886c88065f483d3c5b21f5cc8e3b7fa25f506cbb2c4457941a9c03c59e2a2ae84a2acb488c2c2828b1a816bd62fe403ea89ecb4678499e9571d50704b617c6554f63f856644b299100ce6def42677cfb172e58c152db27f8c02990e387088d384080a71dc2d659b263272f060e158d9df891cc40820fb87a010c75ac084b4493f28843ed12405902627d95f0728c4bbbba3c87da3d63d013640971bb2bf047336a5a961431b1ff7f90517342f2c0526fbf3d023abc1713964e5eeeefe1c322e74401c4c549cc8fe325088cbba5cdd78a2720606380c91fd6d503a394066072a1b70c0a18629b526a3030b75b0a87ec8c14dad5d29b71629b97b0709ccb305172cb23f757777ef99e12a37bd614beeff7243154fe0a88091e5fed8cf2cd27891051a2b723674c96131c7c90b392eb6380d5cacd8e139c3c354eea7e1d9fd876af89224878a22beb891c2451558bcd0a68b2e4bd4dc67c8be44761b358ff30444ee7f020a86dcffc550eb8fc97cfec782dcbf030a6922976ab2bfc90eabb9fb95ffc0d3875a5739937bcdd20e192fd1b1a04a0db91f2624a3b345992f5165e4eafc8062871abce012c6183d4c61eaa23bd7af19847fcc5fe6efe3fffe3feec319d91f0485f8cc861bd27059e10a1a9e405173263a7c19a30b5c1537362aa46cb1c9269559ef42e86cd3c317a72937d4dac9c98727b9d7e4f6c18a2cf372959ba85bcb17386813a7b9a8999a0e74441d7cc8fead58d3945871c1090a2b30345162ca2156ebf70084c631a2ec5056b27f77af5c862d5b5e5974a9f2e105c90b13d93f6641212eabb57b56e161859d39576c70e20a17396081e1092c585ef6993f6e7f99eb90bd46cd696be922370b353272124c67d8e4de9225b7182d54720b1d11218992069adf6dc60e4b5151a68821a68c5a3ba1c68523e0e456301344ad63c8eda52af707a194470e1effa5647f5ac316d98fc86e8310f927c7ac9de0942d568408630ca52fa2f080a5a68530ba8489b2a2d3c5579713f6c993f60e64300eb965a8f5fb64716a935b0b94dccf038b175f16edcab7cb7b96f01c5d7f5def724d77777dcb738597762ed77744e274b9c67bbb7b3b298eb2ec327fccc593edc996e35f9915cc650efd30c0c4a0571043c511cf2172bf9ce253ee9713038a427675effaae0c7f9debef177a3d23c0433db47ba8d841132707ea9dc7dfc508ec5fff7afdce1b79fdce1b793d169748f1c5b9f4fa9778e79b1eb0c862830a496cb69ad07729c1c501f8ddd7bd085ffec00f1cc7b1f3e04806431a8e3cb28b01347b2378162dce52b5bd7dc19f3bb74ee35cf2217beba82ceed63f5aa7dca345932d1a7ba3b2384a7fe0e8104596932f562dd4da890d93175451a8acb1a2d6df851654610a273d4a505ab2cc383c8282ca010535d534cf9265868547505350371c50b7a6a6f90e59e6577804d5e4247342d334c7926506c3a32734b91bb9394df32b59e62f3c7a9a43c7061da8274d731db2ccaef008ea0954520da824384d732b59e61b1e3dc179c28a3d614535cd97b2cc5e78f41425c52345d534af92656e85474f54381ab83a4df31cf2531d28db0e946daa698e4396b986474f53377cab6a9a53c932dbf0e8a9ca0a66f5c4a6697e43969986474f6c9eae5e4f57504d9ae6366499677804d5040a0984427a8ad334af21cb2cc3a3a7acfc8143663e7aca924132532c94893639f510139bcd66a392479bb3564d933d249b96d54d3dd4ea6a9043554a0c39e4483ec7d2913f5c2fa3c2535d54ee6a86c98a2c0a66e17628e4f64021f65b523e94e33b47281bc85ad964d65ca09029a3f45ba010da171422bbeb51d9ec9e56291f6a4919b5aad48ecf397de92d1d3afc873cc242477a2283fa8d7cc8a148a03772a8b5830c87dc3fc566315a2f2c1915c4a4c036d792f2217b456e37f6094f0cb6e228c2d73d92273995994759143cda9c7d9f3629df458095e75fb0015dbb211d9960c954ec39749e385292e84f7a369386eccde272dbda563da967fd398ea03bb267d386d4e473a4aeaacb75687ca8bb8dd6dea8233d712bf0e848ae4463d2e6be2525e493472ad5fada36f693dcefcd9e494a5226959aebd96cd62d29c7de92ca493929edd2e65c1ce9d7d9288bcc2213f84142bf9b10a13f9148b193c446cabd95e278733f11786c5b92ad69dea46912e9090d499859fe6765797b21c97593f501a0f8a855e441061e7d78b4e382ef8f3fd22a891f759752fa13d54397d29f76bddec67f3f52daceefbc577776ead30fc63332b111f2bc04712c26f6682073ccfd63a2ec59ecfd5fcf24d7705412a33c9549ae34604f61bf53e418061365cf9cdef0133f327e5cd44066fa1bf4d097b9c674dd103529c5b929a53e52f48a8c3581633d248bc52410adf760ad56ebbd96cb652dace5b95cf573cdace4f933c9ad70fcdc02a1bb16933c3bfa361c9b0df5223c05d4ae865d27a5e39e7d334b90493767952781e09e727777779fde3e7dcee93fe79c09f550923a9db6daf36cabe56a75eb8a3d4458e498f6957905627e2ee3823bf08f88f6546e3c73a0212606b39b36b3ed8ebe9c46334ff10bff93dd75f77ddf27f6808fe47bfbe067ef33c91d8edf38472599e69bdbc5244f57f7dd7d91b7e8074b81daa722fda1368afaf7c29ce0f127d39f198fe95d684113f862f124104c95bc2baf27c609cbbd183bc93a4a3219c6b6afeadba7334c0c94bcfe13bac46687605fddc88760a24c02d5af725c92bbb053427f66f72a065f4c32d862935b5fe45f4bfc6655ca7bdf5d9e054d60fadd5f7108fd6bada59f73b1e05de94fdf67dfe9edb5a75c5fdd7d86e3a724f77fdd610f317bd49f35d7fb7d2938c92aab57c51f9d66eff0bed3eb0243f304727d4b29edc25cfd050b26555587699a7232b697b2bb7bfda2564aca52ce2852cfbc49cfdc6d32c8eb1bf15a15979c506b27077206d04c1b4bcf28ae8a14e7403e023c3696ec8da5694cf3afbcc89a734a27a62882b4ea42099ad0c04c9249b9fb160f14789457f6f69dcdc6a3dfbdaca10465e05a5d48eadb6b955ddf75dd773fc1213e72e599028fd2ca25d6a7df0a4910bfce72b1ec6877cfa94490194586910e36904568ba76d7cff50c4b81c76e92e5c7dee0981bbc44a5953c296355708f33aa6617a7138e028b3cc6f87066e9f3f4ca8e8baa5c9d7456793b71f248efcc5527448225ce0c958c33f324cb8f658933d394a728132065a90e31d22cbf00f1c5c9a93b6ecea63487975a2bae08256bed972c5996b8226c368c2b79bcb73961a8849102012f470de0bd372f7705c5f37333bd326cdcb061c3ae01b36ec86edca84dbca690e190c96c0e7fd707534cf1c5342a4800414197cae80ffd9914d31f192d5307fb504c6533ece406278ff74bd29727bee4a89c1c36c89bcc92372f5ce418092e029141fd53cc4006f1d0e171a84a1e949128dfa6dcf2488980c81ff2fb33903f42305a78f8905d2c9b93dbe77f8a8003c51483450c956b73289d693ae76df5551e69a6cae3ccf2b670b82a97109e53ea7e5b32088725b718a43cd2cc268f378b71926f0b1785c3e5406b14356816ee8badca83e34ead9dead074b8a9a61cebd9775d77ef9d92e253b69ca5d391c29da1aa948639bb569c0d97e4eed45a2c3ab5daaec399c999b9baf77e4f28783f3346489c99dbe50227c1f32f190e98edb4daeeb65cde07be60df0e8d9d9d4f0bd80e34e66c1a343c1b78b4488a8194d6582c0c15ad61a3468dcf0df5cab071c3860dbb06ccba21bb71a336f19a42864326b3b93ae67a4ee0c881034719dcadcc989ba327478e304d6e99a63253f8fbc09e9e32546e9ca71983c160580209ee043a2698009625ae8c0b3f656c8fb3c0b0406b139fef0c1daf4307e8844c161828427372ece3e1e189fd4f65c5ae6ad4a861230ca95c35e277e3c60d992852f0e1c08123070514f4f4f4f8fcfcd0d60f3bbe49e34a0500a8a0029e2c7164a090c57aa643878e070000d8dc19d06c46a68ae22c5600fa66e8ca310a28a0e0270001a0167c3b76eca8c0020bc850f1f8665590008282c83091912223850c9617400f010840e806668923e3e412d143a8470fa10b8484ceb86000175c40854545870a8e8c5e0d80000318c0cf1c02f8200001a872b8478f1e423e7c50dd6e9b027c175c70c1000a50803057e468dff4c80c110d0db5bc7c41d0802232001151cb0bcf92017e18c0009f0e1fce124715c39da27af203831f3fe85021651b525055d9ee191800c10083a82fb487581640320002648c943158e818177014197c07c82003508349828b5406c9203173ba2c71639a7c4262c4c4f972535009ef001f06186000e40007b0410402be0c32c8e000084000024021084040488b4021f2a7b06ac8b1fe0d6668517a6f4d724bfe90594e2dbc1c34d43cca6f713c2183445cd9b34b38b34a6f39a513a10530125964da32c8009ce97b5802cd5474fae3d019b9c8272884cccd1e4e0c952c7162a2724c00b7a81bd6ed2a463df3223af27c23fa19d980f81b79551e659921130328453e6575e41297b3ca23ae6f3cf95364f6c8207f1cb2877f2d8243ce3cdba754c42183fc67d72903ab48a9cc27378c09dc3f71255425f5f3bdd35642fdf9f9c994cadb8f0b0cfdb00c48cc66d4cedc7d5a5085a95bff26ed97369c6def4f50014cf2fd6a1720730fe9af6fc3fea2aeb316e6777fb45dd8fa1a4a1bd234b3dc55b1c8acc81b1cd2b41a762f3638c46db53fcb34cb6f8923cd3db45647a27aadd532e022b1628ffdfa9dd8637f96ab387337220b9a29e5ec97b9840bf433c955d2e0c91f97abab933f4bdc1b36d9ebfb75df7afa5e575d21cd13a45df75de7e2e04d5396b829b2b20559e2ded8f29d44cac8738af081aeee7385324fef6ba8c5134ff86a5dfa2b38a49fbe0489d8dc23752d60b12a78fcdc2ed6d0f5157604b64f87f4d4afb9f52d31b606fff4ec2928648acf63e6e2e1c9b90396463851ca6fa6f24e96b83357f98aa3dfd81a1cfbea03882c56650a8523935c3b51a4b9a7cf6039c59e122e3032c9798244fc1d898b3df36b9e5daf38a24e96b823a4f20559e28ec065ead9ef7e7622094a70eefe5a51d21e2d8e5e9eb0289832c94e3c19041944ff460e2791c789e58ffa3cf627c841bfff279547fb22c85cf6963f6e1efbceb7dd0883dd8b14d18488a5eadda5b7a3dd6dbadda461569912a86d58d3366d5dd74445f7f7fad5a2f1cebaedba74f68895c43a22ad9d7d976f6a6fad230774d0b3ae922a48d7dbda800c8376c4019286441ef9100e79a4b3923018b54ebf23941ea1df365310d80dc8a1db7fab38a7a444542e28a5344c7dbf32c827be1106cfaf2ece1e0fe43137c250296590065f76116fb9b2deb57874b30b8484a8534b942d58e4651afe3c95bfb2ca955ba1073dbbddf71bf140fea83fa47523093c7fc4382e286bb5b277058774f7c888c4191db5912b307d6ba95fd927ed947e457c537a963fdd4cdcdaf25c2def56b196d2aeb7082fd72a377465cfe572cd29d4aa4558fbde85ad5cdd87b825791d6d110df96aa59d4fcbbc0cba70888247a1dcaeec0a897a7689e40fa7f40611eeb49567f2470e1ee243e56d51704ad9e0c9250a3c974c90a50555b85ee1f9287894268bdcba1591f8b7dc47cfe8f733e3e17dde2722f1be7ae24c48888b86a3129aeb1bd56f204d7331ac62102250834e1cefcb1d3a787e0d67fe9916e7dbea5aa1196209f6290535b05e6716ba57b80bf6f2f53d4c1401ec3f1178fffd035caeff5c2f825acf7cf099d4bcf0f5b037f27ad8cf87c1fe137be67fcfa4b604fc97f7af37e2fdebe7148dbcdef54bbef76a7431b2f32f71499751cbeb6d2ff10411e0df11851cc81f16f6cc7f070a7ba6488291d7ef5c5903640df63be29225d8819c49ed2f0c8bb80b70fff5b01f85927889b70307727f0bd06059ab81ff7960c8a4f6854c6a3fc3126611cff3bd2f9cb62520882638903f090d90b5111a206baf6f80ac81df8fd3f681df7969262d292d25cd07c39747c329963047e84c1f16ce1b488211d8bfc4254b5eff12274c6c32a51cc8ff05fb71de602f6baf1fa7132ceca7e1fcae89311974bbb73df42558440421d7f5dd222560a542930a66a070f1029b248cb0221387890d9a37287c0003144d7e28438e9c3835a6a812830a54a69e94a13609bcb250cdc0464a1357b2c40033021994e07cc19d210139c51b365e5039e38815aeb0525e52d8a10931c86c3143026aa29c2122a909282b7052925a58028a163550aa40c1cbf8e04611533471a1ce1a26cc5c6046882f92806a12c4ad4e9729667c81e5871b9aa8d8e28684049d2c2d4f563819637ef8828a195daa84a1058e284fa6606db1c510677c0c09481903b3c494972757dac8f0c282c9268595354e925c0c0fe4e399f441055bb4900486ce132b669a927008428aaa851fd8d09180064d6ca480fa828a2aaa60c3840e3e6ce982c29434611041040d920dd50f4c8021c31b2f4f5859c22df1c2182f53607c20a50e27699070f2c60b0f633cc8a18528ca58f3258ad5170eb0f14083162ce870860c150c1146cc0c5764926861ce073e9ca192830b7390d6007139b3e68a16aa20c3e6c50872709832b3020c44803173637c8193c3e58a14bae0c203d79528e678b98204250649c74986335cdc90a14519cf92808cc0ad8c106260b519e20c2b594f3aa4c00507284ec8f9403e9e547cc0844a992659b47c69e1094a564da1f3050835b62d56d8e2831e19d63439b166082f9e30b13d81134306333d1ca185982b362d70a1c20b75c2201a83454e19459cc1e5068fd3edeeee5dadde649c6cf1bf9ec685dc4ffb0b2e0d94c6218185c4551e7fea149a16283957c81943e6cd0556564042cc9498242c3c0bd94f7e5601536382829b26a65c01f3658ba95a9b344b9c31439b3449676af3a5cfc78e459e42f3762fc632d9ff2c0a76211e724645a2bc41cf3a48d35a3fe138d3a095bdb3b9bf5b595e2f863475fa54bc5ee4ce55e1c910d490e61009fdfaf3e2aaa8ca33cf5c059cece2c045c59ff92dcb8127ce78f4ec764fb2bfcc99ee808161c0d1408f1803ce1163b001826558694e0eca12a744956968caa3cdd95c9412120d73b252944f963825a53c29c59d61cad2cc1ba43cbac0e4fe0ab2c419f1943d588e973fa3eb96fb4300e163388423b6faf4708413b29c47a2072218d9aad05a7501fa9f0c1e256e4e77f729652aede04ddcd675d0f40c28d33994ea26a5a4a2b82715c9f675a47a068a348a66a1587ad6be94fb635560cfa9490a3cba541cf9436699b3a4704b385ef637dec6d7f8d8335929e5a06496596699799ec6ef3c7ed8cb7c0405fef7aec79292596699659659e67cf4d4faeeebdba73f5fbecc2db49c5c51ae96532baade5e5f6009ae60ab1ed0e49654d3c62a35d5a26adad8b6b1eb4c35c9fd2e2c3c769d6c1d696220ad7c48d69a26b3ac350d29a9691dd6c535ede65a529aa6247f50e921796b6161eab2bcab736f4da3923f7ac06a9a3b65997184473d60f51087821ee2c0699af790659685475070b044ac384d732f59e61be111549cac302baa69de25cb6c233c828a927a29aaa6795396b94678044585d381a3d234e721cb1c0b8fa0a82c4db084a569ce25cbcc131e4161619280a9aa69be25cb4c233c82aab2f2b192d23467ca32ef844750529402b28af806e682e5e300878059ca2f0714ccca670709269840870e9815aee32cdfff605678fcff300cc330b451231686214f4863270cc330ecf1ea212294ebdb5cc591843c916880f1bcf7da4deb57adedba7b5bad4bade09166a7dae4317d1f08be5e58065d1828842e51914a32487e4a42aa1450039abd1dfa3b94d2f862344021f849f28042280f58a366f5eb5495e2f96858a5720d1ad6a96c031452a56a54dfb8316f5408e4ead43359a3860d1b376ec86ac864b2180f0d996c07cb643298ec05ca649dcc02e0358ae0bacdd6121e864521c25178e4d1c30b0d69e5efd9850991e0ab67b12b57f078715bb08dd80d9fcb0307286486b7e031f61fe682fb250087804b4ce8999c0014f23ee0182c0a7e70482b1765d182c78bb1fc502086bf63c70e1d1348e0d3b363470e1cb21b3b6cd488edd8b18367078d9d1d77c78e1d3b3a5b7b8cf8a8cdb759cb14979c70c2ec1b833767f7ec9eed3ed23cc5264fca3937e8a1d6cba9a525ca1c28d6b41e22a20f954d851aa6e17d7ffb392c5083af38c4c51896d24644134b723a70abba72dd5cb7afbd1b56c49cb3dddd38b93ba5d48d921ba62e6dacda60759b5b9b5ccfdce4aa0de7e62aeb882c4b26070439354ed5a93acd289accd9dd6dea786ea973a2d3c40d09890a50ca090512144a71706dea64898b420aa5928235c7add626e2e491ded913758c968888a69860f49c2fa0c923cd4e79c459b2f97a4d149b1dd82441a1c2136cf248a14081cd1266e382bf67af595c315d999162eaea762525761755391a85941b18e6ec5aafe8b84172a7d65e5d5d65d56abb6e0d952bab3671d6505d2551a9ed96ed84acaaac9934937cce773549928a190396b8aa5b1e3f494339d54c89623e2961c33de59c9f65aa0d0b38a8a9820305281fda64d1c2290cca828423c70c275560653d91410c1eb880a9b304458922e5e2c42a9d7485eec73e64a3690920aeca988325e502479c618597386baa6842478094b38a61e04aa171b97e8bf33092fa73d22220c8353b15c7292299df2d5e24fbb8693d44449ce57f4c7295bed3ddd9dddbddd9b9bc2e0cbff176b8258edd5ff1eb99d38ca41371bd3ee47a7f290249223d45ac942dd3ea94ed8f3c40b01ef0e8a11f4efe40fc83f81b75e06fc4ffc83f046a65feef2fabbca2e31eef1882ec35534abbb0dadacf24cbac26cf9335ed5bec212232c94c724cb97b9a71d759042c02825c33fd31f3944155ceaa88848a3d44fa65957aad1e805b1aa5180ecd931cbd74e8a51b34ad7f38d96c361490723f0f1ffd44fd45fd418cfa8df450d7bad28bd14461eab752362914b2ff7c900351cad9cc54064d111c82c4c59ecb818fec0a0b8fb660df5d09745fde24b07ba90977669ae5777e8553cebc97357bb3dd5fa0783d97ebbdd64bcee8d3d0406e574b045f999220bd5f9f0ca2ee7246ff9b940661adb53f7d645eed688ce6957acfbacded5669857c68018a31838ae102947d9a3479fc89624e3153fc3e89a901a4ca620667e3a44a952c4f7252703fdc10459d32514f37ece024082cc64c88d58a72b7d6666985c9fdf46259b7a458c861ef6a581464c8890632aaa8420c18946a4e831360cca01922cd126c6abe42181c4503002fa898a45a240b1386e7d3b379df5eb1c8c5a4f0726bed00c210d10ae3d6ffba2c14726fcaedee945bfef490bca551ca344b5c1a297914cab56ef0faa5cc60524aa9ac67f353437d9e985394dec99e89f0f58c626565255484e3f2de10bbab0a3cbf793f4a9d765df7f58c525927fb671bfe7c5fd43d4566be3d4566a63f4116b31425c8b84929a5b25ec130ad955a6a6112f4f768add6de4bbbead55aefaedcb7d65eafd6b6a4fd6b5badd6c517d78ebead2f7357bbdad55abd0bef7eb65a5b6bd79241ae1260b7f332fd96ecf12969811cc8ed5d77b495a907eea42e388c4e4c2da8eade8244ead77b2f112a7ed5456546bfd239b7879ab472c82e4e9bce1a8575d7b4b37fab0cb220c80da3dd5da65f658fdb5e5b1ec8ed4d6510fd1a82fa84d78d843ee8d14ba98551ead45606d07c2fbd3ea4dfbf76dd3ded9916d0e5d2c4b684316e5a3f6e25ac7473bddfbcf6c7aa74abd2121626a7a8a91b152e773b3b5d4b4c2ac45cb08245c12454ef168564507d241fba55a92e8972d6fae9599581b867f55d4bf8c537a1c59f51e873959241759ce5da5f93e4b6f57bac38a433cea2c2f5104fadfe982c49b97ead3aa256bfb279922b4fae5fe1344d8ed1d224d7af5835cb4e9f1496fb9be64f5d379a429613c7e40f69aded49bb5a6bad580484a8fa686f246f7ef7090eae0fd93a1accaa02331cebcb2229a594524a29a594938a9f4e5dd6b387b1c1fd63ec93217ee2da60aff027a90c84233d7369c529c59752ca39e79c734e39e794534e995e703081bffb3026f07c49016fce3967f55a7d6aadef220e6355563d66c34f6afc46f090e62ec43da3b46aaba5b706d9572c6a33f0fcfe590de7b7a8c4849eb950929e398f6982094ab2de041f3e7cf830414992ac244a4c486282d08f912b10b242c83a2282074759b2aa2457265429c15a5265c4870f99121e9d9ef49dee719ae9185b116e892d99be510fe1a8e1946083448dbe073929993e084da391292ed724d34fd2435da3efb393c86525aa9ae26002dbafa0065a2e117d2a13e92893b9cf9016913dbbfd9d4fcf889ace686b0a5b318689329d36a97ad53823fb1bd8b003fb463edf01b594524abbadb56ddb5a2ba350b06c0399116badb5d456aa44521e7d64b7b9ee5a6bad5dd775b6b35dd7595b791091853f19080de434842357537c107cfec83c12c2bc9a8d8ffcfcfcfc1c09a14310aefa48370847ba3f48ae83230f5adc802681c70b42ee480856220489f3f3936f961d011555109e2c714b88b9ba227729be150531bac98a62464646416ed7c8c7c7c7c72848d1ad2888519191ec93000ceebfc91c88c42961cb23f6c9b1e0f98ff337e85907534432df88a8bf839eb9b5f64789b35674b76edd7a071b04a11ea8d46c786539e910d50c042000008315002020100c07444291389426ba228d0f14000c7ba04c6642198a635992c328868220c618c38c0200014080214ccdd4460120ba346adc4421a11c1c6edb944712fc5caa9f9911bdc36fcedb969e0ea7ab09aa55f94e98a8f6aed234b33dcb83bc974d39311cdc2563de7c07bedce358d9ed4580b2890d1521c78c9ad82c3b996838c7f8ea45427e8d16d8b37bb6b457734d3b085f76156ca142d0780cd36a080dea6f53842052351f7267e9b8aef5efe01ac7b98f29ccd454cb9504ae6184a83c5691c09f61b51ef280b40acaa0baeb779ddeb39d849312d4d92a503803caad322f92187d921fd2c0aba441cd7f9668f6dc8b562833458467e2f49c316a902f26274e32f482662ac6552772ae687988826c10e44cf325a4f7d269ad61e2a56eca4de8afcddec9b8abdd02194dc6a6777ce4d419cbe7062875ab69b4c93c5a381c83ca8860e73612a42a8c21728f262158901f984868079aee88bf00a3f518331411e234cde610ff2865c074517142623b1ec1dd04220db88fc84cd47015924d464574b5f17a12e9cad080154b8036f9b263db17df3c23a493c19f7a7217f2f461c7dbe868dbccdd4b0cecef5aa6495a027f6e947f1dd3abea99912c78db72d0d9c00278cc7263bea5def16726273e7a93ad3604e5466e11772c2386c9290cf913c9f4a8f880039a793f636fb79347020258ac904e48adcdf0b450423002616f5d2ab2c2399249e92c30aed0d16879106135b4beade02b6733615be750fd4a7e279eac4aefe2513f93e14e6c6864c84fe936f204d727598eb3fc6a6c59c7f040bfb86dc0a3b61a8c7af5aff28d752b07613f15dc15a0042c9a482130d60faf8f54b4749fa95470bab095df2640a0cbe726051fd49fed0306a0b663e584a7248d1456b9cca565b97fe03ee3af6bc5413ec852e861249445566c47982024aa8c16a2bde12c7c60e64d0d2d8ee0e0db0d834adbd8cc8b1e5b5ada60fbf11aac1ed2762269b5ba030fe4bd517d01322f4472479421cdd7a9eb810bc97625f7ce9be62df2009322619f591bd94787fdb311b18d7103a85f3b607c3f82a4888da33526d58fb595e09789caf1c3d6bc7e3ea608b5091352248e5ad7c960cc70ffdf72dc5f5c0b68c2c8b411b3e8dd3efdd1bb52ec6530d3508aefb25a463357bdecd3089a30e2cbe8cdc73fb78fd41fa454550a98328f54a9d09df1b89b827fab392c0891869ef79d7efa0b3fca59ac28bc0905c2436d4d730bcc9a88b66e93c1c296bdc1d11758129ca2c9104bb33d7606d16c76cc6b1c1791846644e49491bce1cb78f0724303e700fdc37193483007c9b932196e258e5647eea6eeb33c8c0e69a822bb07a58345aadfad012a809e194460de593f1dddd7adca1ae201511515db1dd7d79a080e281d0d2e236aea717933d1d1b918623359def9a54280f9727eeca093e95ad48376817d0dc228f26c3e947becf4c479c547f33f263581e9d9b9330eb05904b1fc3cdb6e850e6b0c70843a83b5daeab33073be89eb8d5c3683c32738c737999f6ab079429f5677a63554b378ee4c6c6389647113dc084df0fd0a62c8dcf48a31b88fca1863698c9b9f657ac411315e3c1d037cd820104d7ca14596a4c15fea759f2c634394b82d4655444064820b65e91b28f622da428a4622c281753d6739be210a77e5370510e9f03e69627844c415e2a5ed1d31d15f759e328a65a07f8e5170d27d051f842d5726a6a49bf08bd08c99f6cea10d6e91787d60de0cb3c4db59b0811669af5fd89b012dfb743e6f8845cacb3176f3015ade75702ad418b9227d773cc038900d375a45122f3b697c36da537620b40785bbd12e84e55ba214ed00b8413f5a5f2d0c74b394f69b96e8d6b3eaa21d91f009d12276520797186336ed67a7b8a4686b4d808166889fbb6ca3b30c23ba3aee487a5181df2b5b9b72d9c6dd3514ea8c362e0e3a3efb568cf50689808d7b73acddb7ebe9a0ec0901f7572bcb3985920f675b48a1b940492d70ccbac471ac65d969188b6d814f1f72d35f87ac4097ecc1b2167b22fae62d65f4e82afc7922301dab8100c8fc83f1efd8216635f0ebd96c10c52148e66b6910d431537985632a74a281d56053036c213b2a271a079ccc50172587d95c6987c9d63dce466433ec84150ec4f00f6f01ca71ae2d25b2d26814826a356ae271124e125a9255bcd5a5c1a0128a3844cbb84e8293c02c822315ae03355c4084af357d26a7872a8a0cb53e3bc8e086261c5f897ef309e2ce7915b996eb9ba18e7ad6c300095500b107986cded67207b2ca8dd759d1e45190499b1b131f8420636b1c14f81ab7af78b00900c889e6b8585b8d3bbd1ed827fd08399a740bd7940f48a3ac5ee8c7e09021a3ec795769f3156fe42f5665c655b9e58a79dc748ea373b0d7c38f396e6be3aa96efe335448044ea0acc18b0358d6a1e44fa3788668bd8ed65edd896874c98bc63b0c5f2464284a6caa9796649fe2e00d38dd3ee7f7316640bb67769e3485571e93f2b55cdce97895f230ff8e72b63fdd5577d406f0f56ae5cd90e13a26e5b731867898f413ba55d8840f5555872230bc6d0c96476f3d7994dddca843e136bf0d27c94e0b02cdecf77509bff713e5b730ae089a596e1520894afa6d62a88cc83effde70abf4b1b89b2897477b1666ac683b319317c1d781214961a0514d8c9159be17651ac621369130f1db0ac1fe295b08ae1ebe44c6105f3a2bc3b2c819b1f1dc9be81aacbd387fc6db2cc6e79755620c3181fb8f09ccdcc8295365fa956c342a6359f71c49e1d2643e325ab76d69bc4be89d63ca0b38cd2e90165fb774433c626809e302b90889fbf85e333c26ad7702f73868b090f6e3a9ad96fab6949de822f6c230c91afadef2810db1c9867293040c792dc352f147489f793898fef5c6eb08c38e9d2ad5c0964be18ec9f03b8604a14124352958890e592e8785b12331c57aa0a8781f23930889e99b68d40f9148025aebaf85614e15bc543fa82b6cb9790193f244a94c734a848221225fe265b4db084244af89257f2a938a50793ba98354a01fb36085c7be707ec11471ba556190f80839091ddbb43a7da84f6f46e78378d8eec822c3e6c986cedfd7c248646dd787f2d9c085f63486805169e7e7fee454fb4ef28c6724c5996088b7c9b242b78252d3a622f4570caeb37f86fdf1f590906a9ee13f9204a58ff26e987c178ec9b7578173651f4c7b2e1a58cea3292987208fac8823c990ed904a9fc21913b6f4e08bfa65f104c9c4a1a3d56af30b5176b8531840e07b1b6c57b72b3c8e85184c66902a4ce6ffb3b61489b7ba1c860e438caf7bc32d13816a04adac1e9e95beb6ff41dff63eaacde561ad4b794a0cc8f89b247fd76f901792f4d525b6d3c0ebf06a19cb70b7572bb3da000cc08bc25834567428802f69bf4a8214ff0854df844f67c562152b96c8ce5027454c1272025c212307281775209bcf5a077b1296a65bae8f6afdcee86674266f2452b89cc0926fac8edc34c1036faaa6d4fe34fb7fd4dbc0ff410a24ceab6205a3f268f0e1bf9e0e33bae074f0e4edd35e82bf2fe9837174bb33edadcf4827b74e5db8ed01c8a235624acdf846baa056801197595d6dfb94869e9b08ca879e47791372c943bc85cc73784f7ab1b392b07d4d3578fdf6d8abe0dfb2237b09f85c3922a72750e518c4629a2de0a2b1636ead7c887361575d8254d14d9e171a7c8fc7103be2fc203a6cc759efa113afe1b8202de79219cf2c915380ef7f113d1387ac044ae355eb8416fb2d0572e6d85c24e0871ecbba9287c6b8f240efe14be94c59149d6b2b81645863388ab9e31021a31640b3ed0743ed149cc241d6c8b963b956eae0ebae04642882a1189171cad0eda4c1000283b934383fff80fdcf1318bd4647d3e5109b801cb4c47a03cc7d16b94083d0a11dea14f2c59f1130b188e8d42da8ef62f5819680dc0c1a6ac2aaac0e37d5b85ea8ed94870a774b410157c3adb8f24e0b174d4951887a0516c6d5b473ece5d634f9912a2ce8c15d429faafa152be9f6930e7172b8cbd0a0554633d99a813f91a8b019fe333efa03dd562eeb531fbd7f3bb3389c3b8b1aa7432d6e92a00aa5f7a38b5e9999f466377935635e3c819a694f83209eee756e79fd0af510fa4bb4caa423761fcfa48b1e7dd8c51fd3fe1ab9a7ec027e4046ae5fe3e63785b1024c489097c219d442efa7b59446e32cb1d16000ea326420b7a913014379e90fbc15f68bda3f613f7d84ffa1f59472939583c07c1f42c03bc497056b320f15b180a44ffcecb089080a6d613fd61fbb3de18252f23be0d4746fb76498c426c33405976749fd7c0b9826a503d65da6c895f632fa0d2e6c00f585adc000fa771b7c5b17f59bd5e5a9af71f67554c38dcdf7fe05facc1347348085c692da2310c3e377daca9e01b600c398205b1778069590439933364cc7e62090beeccf04e239ec06526f6b761367087fee1bb6594bb785056410b6120362a49744c5127ede6a63c883e5310b8cf64fb513314d570b027cbc108cb26f9f4c3047bd32812378decaef4deebd2329a5f3c5f46cd82fbfccdfa07056e26e7681da59c6c282214ff2d3335f1540cd3b6319a0c5034e12fb3fa4e5eb71091b5e49ebd90d6f70fcd3d426361aafb33ad97fff405bf10a0e6e6f64d009dcc98648a947cadfe572dcef888d17518a525520446cd01800516a062f8556af715bf49b7f45c5e2ea13c0019fad004ce34e947fcbba9b4628bc4102f47852126676a6a2b86b8d9914ea162bf4bf21815bd86b621a1a22f195add1fb3207cec951a227564d168a126c08234310ce109193d6a81e3d96f6399a836acb40aa1d0fa56c8ca70429181ec065c68e10666a512d0825f38df4568ffb80696ade33754faffae2524fbdc9b67e5cbf7c7d002c4a388174664dac7768bd80cb819c481d192562bd8a3476246fc3734d2aba835e07f5d49c6793f4bdc6094e4cf587a5b716d5ecdf57db47e258e29e55654b8f55fd5ddadb818c1467ba55002b14eca913e670f98e9554c7184452d4ba3f07c009cfb7d2b44a64f27ce3574f870e1b5caf2a500414e2fc7ca2a3d5dff04a8213520270259321ae25a9b42b0c72cc464158a11594b4a6cea180d3d7ae92239a7747c2d41e9636e38e5d1a4477aee83c2e665985c5e5991f27d72981c75a032d8606a3380e98416bd15f2f005f7aca61186c7c2b23434d80cd11c00e7785569092a2cae37387bef08a445bdbc80c39db908c38907e42d315432c20034f6bc7c1a88ba2a06bdad4de40b83b37c2d32326e9b8d833dcd603096b7004f4ce624e4a2d48160a067c0ad340be641559cee70160e84524966df4186f33617837c35c1f8da43979715ba3eb3b34720608e1271f6161a246b8aedb49f043db10986eaab507342de841b7b4dee2d98ae126a5fbde8d5dce3b5bb309e5bf9c8fdf63eb96bc0458afec9e68cdcf595d893dce662a7ab172d621dc0fad5cc30d2f6f0c9112da19fee80a111b7dbf04eb4dce84630db55bad71e79f897d70187ca620b4b91721baec41cf07ef98f19f5d30a0fbd33dc417a0b24495f827eede264cf3ab87eb843ca71b8a6e28441c426b1a3735d1623532262f35c937be13e6529fc871c8d1d42eae7fca89cca635047e8d25c68d015e243e7aa91cca1ccd23f2e26714cf3132b2577ffda85a94c0dd6c01204d4cfae9dcb02491d202455b210ae5eb984acfbe3504933b74e1271e30744c6c97f0757379e744a307b80166f2a1535162e5c739cc057f4f4540b40a26b4047b24c86c2f79aea27c3abe611a98d1b6d12226229cfc92def2ed1979bd9ca166d879ab4c87c9d9deb7c2064703173cd27bb780c19965cac43b9102e513762104b773a8626084a7235bebaa4737c1a69cdac858ecb1c15689bbad9f334f29ec4a18f22eacc4bac89169e7788eaa42ba36a405a5bd41552a955479b2632f222dda2d70f1360b43a26460c12ca5f9c3d808621d6d6db6a1d74d67e883c466f80250d8d875f0bd9586d05aa5bc4d61a0d8fb14d842129a8882eb7f859d01b8ddb054be38da0442adcc7908c9e89dde10c82018039eda36aa3e103ad60b6447270e3e84da3c1ff82361accaa00a4c6b84e3541052bc22df16eef709a648a43d01776c4153b36172de4b61919420108dab2a2ad3d517f75592d9fba840678b2d8323813e013c7833889baf64b5eb7c55bef493049cd4b0825101e10da2d85836d0bfa07f12b053cceeadf34b9c78107b2322963bdf48ca5649cebe23818df512b23ff9f57ef89ddb91500cfe9ca2c831640d931bb45226a0588d590fc7c3fd5fce2e9e592a34d14fc319facac2169d007f3cc3b9dae692fea73017851ba3b2c00a298b77314a2209e78557f607ab7def3c67fea5635d64b4fb14e46734f6b6797f3399696093e5c7df8e2dda49bc67e0fbe281c2078a66fc56d7d579e75678f20c438824967e00d84925f6e24eacc15fc936dc2295e8dd0ad4bf1d664dc80ec0b4933468587877ed95daabb65a017a8eb8a26797e748739c9c3f89d71723f3315f696a34d94ef9208c7d5eb66fa97d57ab19b54c247a74311632c2dbb5f66ba91818236a6f5084767c495815f818a1fb3c9324bd431429ed1a73231c127a16e76b917cdb050893fd55dccb48965abd59d03a5821dbd71054dbc881de27670fcf68e28f829f46147007d58a708520cc18e2f12cde53d68065f13047a687b23daa8552679d452c0c11fd1d86505329d58a15658786121d933881f35ceedd02ba44db98ae57891cf3fb04a10955f6b9fd264898e09eb1cb02876a35a78294daf5c4037cccd7c46230afef6098f2a3e8bba981853f29acac108bdb594ca244e6221d383538951cd0c642b7b09847cd5dca5b358611b9b825cb865c039a969a4f2907fd1ee15164a6ce6e891217e250ae40bb64441dbd982b191804a837a95018bf09428b5b996546b73ff3c101147352d42ab559a52a6d24cf6b7a31de2908c365a6a4432e697cc11e3fd54f40d8533bd0063983b4859407f241c83b55f6a9c1ce0a13a2dc81174dcf2922c1e4a383f4e6ba40d671ef84721384f5f16de1d7ec88f4c98474237ed90ff925a937c445467e8cf424f39314afba06bcf7b7b48ac528f23a3371cfbb70bb2c8358d502faafc46fd490d28ca8091790ba64bed2e532a280a4771ba1f028135fe2721cdd3593d97d549bb74996a981850f4dc3a46f2b08a4b58f022313d4dfd20cc14a20704e184c2f2e953e0f6b51fb776b8cf968ff3d565aa2c516678ab492fb37511de2b99a42f025aa8b6b930f104dd90f325825f42441e7c3eb41818d808cad851e2d2f04d1825004a5cf8164ade7199a9e44f27f5246b503c8e94f25a92448f995bc719e8fdf3491c33458bd8d4b831daae651510dd4f7ca389d7cb899b98e7311d319808f32f7b99942872871b2abe7a953d742fb88b64289a1810623ffb963f483702b570b3c48a9da76925131604e73c582bad30460556ce64fdf4bf18f99ade54a6b380a65fbc4010c6a436d545e10fd0bc0c724b4ed82ad29e580983b8fd0441900593948059483e131ad38250a4a38e69ab4749e95bcacd799252efd543340c8c678160e8f4996f87e8299757c20d67d4ccfc519e8034c5f5ecea2e0ca8304cb3876b63c40ead1deeeb22552c065052ca60219600d3bd26b09c2061e77224507f7a87dad575b1e6a5496a11d3aefbeab0c1183873e9be2dc782d54296fc7c31d5a7a49c22463198a84602dea84ebdc992be59ded6177b9baa9c3f3a12972e080116db9d0ed3bed9dd9f62d27df2cc0ff8e4c53cf4449fb691b99e2759a3fb388fceeb177ce3dc1b0fdf0a5d9a363d92beba1bff9c234e1b229acf6ced7413cc63841036e878f23a32bbb72c2312a58d8806694c34a8c741d2523d3c1ad036ce06fb4161e015df9289eaf5b5ce689bbfbb332d4250cfd2915d9060117adfe06fe15d031c884cf410709a5f802a72679f088b26a33f783808c33aa51d2ef611274e0eaad89139eddd0a3a85cb661f3e5452549f905a55d9050129ea5a16aadbf57bcc300f3216e32b78be3505cd841177ec01e7e93e96157dda024d6ffd8054deda452922b8d42e3bc6fd2a0febaf16654cb90aa2f7205552f3fca563617ae52102d96e7955f5126f325f183f209021a0953ba3d7bcbf41e5ae8050c1b66cbea520fa4f46655af48712ce0159c7c0a67b91528385c420e614a38c142be06d81da41e9b04bdf34d7f00eede48395fba27c2ca1c0d1ead85f2fdfd325e744fc7b897f91225349e96789401b05546a23790e541d1ce5132e45d30d19ab52512d1035eaca7e1a3a25763fa5c476da5f32768b1d4f2db19dc36f18a1ed52ba39b248b80baca8d6227bbb020af053e57275604a9cb44b05ab9efcf9a50ffbfb1bffa04a0f294abc319b1c5b1431a82e9a4027231e53c3eac5b9c9caf9f8979217e26a54248598feca409d0f70da38f6e4b0682710312f9bd7d7ed0fda9cd359337c7f38aff72d6b28657e0e3054f61999454afe2e3edf6851cf87d678aadc67870424ef8c1437e74c52272516bef1d132a2fd0daf1a4e0c1dcc7468151b7104c5cfe8b332602bc611ec8a26ee8bde23170af6891448e4e159d0ad698dc6deb007a1f93f025743e57d14eaf57f0f13ca3e99b23e9cb9efa8e09a10b3b30852af2b48256608b3146603571873d74005a1e1f41e0f3520be12a12ec52156ed3b1aa42be48b88bca8a0f8113a8b4761571a3b0230d25ac674bb98c5b17dc0a62d9cbfe2d4d2657d4cdfd224b445056e20c0680a94dc5816067c15197abc997fa191ad035af6deae0f688afaa3de65fb996773a2d3f8d548c089f42cb6b870e3717ecf443a1a6bed42a70ed3c3592db32e26d16d667bb1d06fd3b0e897e85dec6235e776df9519cf1be273c6670e752e56721cfcf5ddca0521dc76ba5ac125ef960d3ad2cfd50088e2d68d6aac6895fd17ea2d0a5d07da2c252b9ee432d8dfc4b97d8417f1f7fb1527012e225c545040fe26aa0bbe71658e79bf6513946b931c10ccf8a77b755fefe56f7d5e27b0feb3ac03f27259ad8497b076f1e6ea335e5c0ab44d46908c36d22e84d790750e403bf5c8b1ec2ea68676e98193e10611676493beb88e1507ab650b631a5b1767679a1b771b95f449f4c15839cf2c794c803f3c62288eec8e291acb3b60ac3ff5fca3a73d4f20af18834822e04930a35edeef053499be00986e6ef377048e2cd0a9b2f9bbf055be0d4a0df28abd4e489c1e8a35cac7cbc924d5805b25776a0dcb57c40e0f89ea7c8020eaabca4b4c828ee4e5bc3b34d1d39039e0223e105b93c582bc8d98d6bc96ee1944ade5fe4e97b6cd8e01adbe38664164b35f5612125440eb9dc0a0bcbe7fdc1902ccbf8a3b6788152085647f0160a57b5721f263b978a5dd874ed2e8176b0b1428ee5458f350a81db7b0bb9546a777b76d1ecec45589b53450937d05278ad82c91b00a7c20bd0ba6bf396021e76f844aa43cbc9c2fa8adc8fa865a2fb03dbcb274c8305a140a77f43d432ffdcaca4a686a8ee31833c9b24e795721cc9ab41ff3ce06ab74aadca3eaec3bd89a6b05bd30fbe696bc82fe9cedb65ed603788a25e804460ea744bad643e536e85bf68053077c46cc42cfcb36a2fa9a27a4e51d973d5ab815c5b1d294fcb27c2a3cf90463c44a007a48e22dce5b5188922e6d96648072425c95f1116390758b9860d155bc453d9327f4b34d5fa3549ef4b16fbb5336c6f729b2de08a97feeb0988f08ae57e5f9eb2337f06717ec51db0c792ef23e4d763c2e4258686b1b307ccdde1eb98118fc59e3679e6b1b7de7286f29c86b1b33f0c5485a1c6c1b9c59483d2fccb8a3b2894bb9319b2f02a2a0eaf400b1575bd892e18db259986b63c508365afad5557a9695368fa1d2f576a1fd1fc073219b561acb31a25481f4598f33a3fc8d804145150606972dc575ab3c3d7d5cf423ba1c9381bb8aecc0103b338474392874bfcc3e93ff6caba42e070f745d8e78a74b63307e10a4f808f0f07bbb03e67a4f080319251aa8e427352e660383e3201cebccd8ecf197b9b233fc6a8996b237dcd1aa4d94ee686106d999520dc252670f1a7d671d904814d992c82795991a3d16e5a65f4853b5a77c9c110e72862721e40c6119b537fab9429b5fd072c28a798010525633d718ab69d19df815238270f5153ece464fb82e32c69f224b2d7be266d035a4ca7857d484c3ad36fe131c83ae4173f0973857c47f75d4129dbb614568a71cba4681f78d802a63f90391a26b88e778f166748dca3e535ca51de66493409c91fc2c4cba06b0d3bd98ce1624e8655aff9a64a7891befedf8cb2ce6bee170309dc402430ff0c6b01b048de6a31d94faf8f59801456916217170212c8940584c3b98cb4ea82c64b276485ad1b553a1f9079a9379c5b3d994db9928ce0010c977955285529b2407a5cabf762f2516eaf3a7e5b1b0a21e9309e1b3bde2047b189f9d56cad2f2119686736bceb1b02e4d3e164bd0f611a2b19c23a6a90d202d13a985e0cb248fbd8425825c7b3b0e1250d4de4c48ce8b723db682521149f96fdc14e40620db437766fc5fd9554d6219109d37e3494012316fe4ef5a9ddcb9a2b6c203b100b53956300cef25b473632f5d490549c526ba4b840a1569bd0bd4489f63d3f06438b4eb4e6a58b7fe9eb125fcf886ac3e54d06d740d37c1087b8dcb92ce1a9060cd206c4c5906546c84dbfcb97535bf68d183c6049b315d0c8e1ba8feb071044f0aedbeabde7cda52c526f728f24cc151be2b7c187683819916981c4b698230a0fac116ce10894103b551dc3ffa3955de34fa9c7b3add33a453d9dda3a77496f21c48698238b103241f7264e680529a20c542c9d610110e3c1422aaaf420da710a216bf1d5d93a873a457b73cb85935f4c723b0760a202e0283d96a621e05da607e979ea4c3043b453faeacec05874a0480aaa53ee01fc43babadf3fb0066ec99f89a37b3fff5d63c959da7206cc8427facdad094b9a0551e5414605dc371bf4859dca1c748e790e32f684ea5a67adb21425133fbde96d994c91d661227200a15a63bdd099e4272cf1808370702a2169d654519140e82387c07b4641d824df3c4c45cfb42be7d1a5a122155c8163921e6535a0c89c37da12084b94be294486b4f3e84b7c10bef2918701550b66c1584f0b7330c35ef34fae2526a1adfcc058eeced2dcc97d517181ac8d618492476f13bc1fee62c5be4e7e82b39891fc8c8a4c8f7c9013680a1251c787d6291126d06629439ce58fd36b52048ed85da814dbf6f0850c01a0fbbb80114f0feadab388a91dd47a903caac819a92f9cbd84aa374c2956a02fedfb9bbc2f4d8098fd5d56784a1505af50c6868ce80a109af450943411e6b6039b319f13368fb9c542572c960606e45221602015a15fed7d0cd7f23ad1a076688fefb2fa807f4f8dda0cc88a0a4c04832282a66a582971501c84a06a8a462d19475087a9c445225abd07d02e20d0eaf8ec0210309c2218db40720fdd57f9bb104546b23cac205f681ce94b61873d8520500a4194e88d0afed230e74d4316f2e7b6030a62ab8d6134955d00319ae3852314892edd70e3805244ea49137725eca1a79110fbd8877109c14ea72a79fe02fb718ba192892209c9a56facaada6435d6db30a69469a6ec0ca94d9ed96de86e7862e55b385107e86a6548f694eca4f953a90055b7363b23f7a748bd129836e796311547f040c5006615b5e71200dc20ac0be45d6ff87306d022343f4344450b8ae4bc942cfa0cbcce0e71c84b060e193335938cf5914a27e66894888821167017ebe70ac2628ec8152a66a839bd18cca6b3092a52ea33843955d16bea0174b25a3007a358ac0bc6a6f879360d6a0de26911ca16ef0f4e2333893f29cb7ab1044f0ccb2547aa5d5fed43357c5a980027f019f565c194e880a2fae71f8e9462e69125e9b33c28120f232af0bae2e5bb774d44c6294006a9f8cc509efb5f71af7ca8001928a715b7866193076b9b734349f8730087abb7f77f501a1c067c7c129a7f62c0a49481c78fb200e9daeb3823515ae7433f577fdc379d61ff705cee842e918d6bb7c5b51473fe263efeec6b3369a3f968da084c3a2c3540b81a4bd30c27c42246d1c33097fe8a22963832f5932ec0ddef4c8e0e076f948b740cb24272d095b6a5190fffd978e5203762acd90d06458c5599a890c621614a82484ec3be9316f07e47e591fb7b70e5ed69329254f3c962b1bb14b2ce0b6ff9e05ddf6a9d90561ef1438b0e03420e339dc69eac0f9e01c53255c979d67e377ad1a7581f44bc5e229e7d9950fbdf007da0e4c493f327d50dec3ee72800a5097c44e39676af78f1c234e126883f450f529b9d685883bffb78e7843b9d64e25b60ef9be420ce5dd2b0a829f4c8554cc44597d9752fe33c9153aebfe3f7c713a3bb16349996843dc2c4a52556fb8a0972e3131793494b60fc75a5b0fd1f9d20f2935a9d4a433ad75c9511b7c47ed3dc3d094824d9b60076dc84ab2b2147511d66bcdf00c2e6da9e1bb0ea81bbd274b7c44a009ba82c4bf0d0f11baba6fd41d1ee522d1f234ba413d3490d2c8771f463a0126dc2bbbb73f06f0203115dddd114a7e1f7051f2217078923b14774047a0833148d64e76d210e114b47896a067044aa4a5589fba66253fd0227547ba8f4190181858d0a5d01bcbb6eacd6d516f75eb883801aa3bb6074ff995883eafcf47621afd8103a0f07a4c7a9b1d93c908279506fadfa15a118c20507276ab52553005cf4a77df4b46ada643c44e7a515fd6d3fecf1f186d8641464c7818590a129c121cad9cdd7b49b26cc4882c050adbcf1790a13fee457c2ff1b319b214dca12b7e3062194795f26f9f61bbe8056062ebacbb5b457d4eac6893ef2cb59794672def009c8f4aeb8e17a437d2c965e88b06fc9252d053bfa0e6bda083780391b7850acd5d5b9d239eff56b298884036fdb0506f44a05e4097a3e99769bfda9a60bb018131205ecf77516313e0d62b06f0983d210cfac84102e74dd141d6c94464befb979ecc8845a7806f0e0bcd61e335b47edc3c99c444b93a8a0612d0ca5638e796b9d0cf0c7745c813af08d9bbc1f7820d6beff204be400be48307bd0dd617f493b5497bdfe9ef6289facc7dec451f6e8b8387578674e2f61b67b7cd505fd3e8bf2f59011869b8d26a2d4e89944ff1353365a1d5b3c7c21b01c3fa325cc889b13dd144a5203b70de1112111c618faf67b7ff16233317079e6897164010a22a75272b02d4fa01cc98330a150fd83bb0deebf7527f453eff9c8301f6d44616e07b654c5338a25fd725e074d9460e90af5e087a52dc2531fd805ec0ed75b60377539f93b726b494a130d0244551d63d82a5ab20cbb00158584370badcbceac0b7bf38edb3f2c633fc983cbc90e3aac5eadea5f63454ed4580882195dfe566360bd7e0de1a366ced9e4040d56cc89cac825dfd8c6671e753d0ff02d8ffd9158f2a59cc4dceec3f587aed5bfcf73247630c79cc6b076614534cc038c4567158d6a1db34daa4c9c7716546cf2fce2b55d9be946b82a3895d0a4db4e5fa14107bd3a45efec36502934cd019c7f11d948b8e9715563d14e903690ec194c6abf84a837138916790f39673d316ed69d8c1901c85f17658ce72f2343fad7cc08e37f1fc83bda6ed4c529b9b2d8dc00dae7daf3131258c3d4ea3eb76ed7e81f60b110b55d89af39202a9e05f8ea8fe40a322ab441f811d03c95e397ef3fd6654aa63898a8686085d1b078e945ae4c027aa651b7e26c6c524066374d00ab330a28bdd625e777ac17a75e35b451f70d3d974bf8f49d7aacc7caad764d7883e614e900d7ac5d3baf60c742d49f2045c0d26e86e08168e1ac53b5a0c555a77b3c2885b8a0fc5233bf3e87d4526a436130f603e12db3d8c5afa5a6abe5b92079ce3b2c19921b2da476d0b857c22f53d21359f918fc387c69cb4b4e2d90a16984603c91d689627e220e2e9de8d719e9b19703f25a02822a2c4187a13649bc372a9ae6025893ee5e8dc02bec6d03b6b31040a2dbeb1048e745f2b37fdcc601d764ca25014a5a40990eaf121cb59eb3361587bd7a19b7d31bf429da2714753f60639ef2cc2c7da06585fc87136aaf46fae8d93ac6bb15d72e890cb7b318983b240f1a8d7e7b001b150544e47e248a5ecb9a473abb431d2566f8ed4923064d4cfb17ad4e6e89896fc02d274dc9ae9c1f291d00cf7854a02f3886fa9a47f71b19b71178859a4d54e234099dffa2b265c47d1e53f748145178acbe739ece30a9760d13d825c81bc30677d75780bf1c84ee11bc4ca495c570e40d44b91d9af76f057884e882219c00d7a6f70af202e5e0b9adf988a641bb325dcc66d19b9b10b496e6cc5d11b5bf16c63b59c7d32b4cabc4ef36532f16c6265a3bb58db2837221bdd93c9c6b39e065d60365a37aa8f39daecd3b98807a2ea0bf98ab48df222be51f9a8249efad39315c577b2fe1d0392814b5f054d8cdea1dd69e8c5bd9059a4aaf8e4b9ae5e946e89bf9184becaf2b70cdcfd5b2727b92b5c0532019c7809d1ff20405576028e1e44dbf62eaefcdd81149e5a05109e2e7d07073479b3d68bb6cdad175b00cdac4314357d286c727739de5da9df821d8395e1bce5c7b7451e781bf3d1449e963f6fb96c0062309cb9083c9bc17cfc72a0f7538dfb37addd8de24a693cf3bec5ee922b4b36abfd87c042c7a9ff6b0ca1ea50c924a94a09f18e840e901ff9398ae18238fe783865df69198be4f7a30d8fa0e560d98949fe5006ec3fb5581e0b81712cc2c56cfa9ecc0e8a1ca0cae8e9fce02185b96a1507347eb67a7433d4aef5e8a8f79b6b41fed825417f6c44bd05756ee1b02ea0abd4dd2ad81751a3d188a96ef77db5a85205ab0be34f16e07a33eef572f8d0dd22781478df4a5b3a0ca6188ee26e7dd8320137681b927f1b4acfbb17852ea2d26de2e2bfb93b0b05daa2276c72bae97646e55247e4bf46bcb03f89b68c911d5097539e2bb456193bfa359144dbe6e239c1d515081249bb687d7237595c4a34948afb1a4785953045e14e2b0ea95855837ccf67d0af7160152b594b45bf0342278c02dc90e280796a6c277b40a69e76449f5aaa0d597181b8dcd9a182e6ea33313f3439f7ccdba545d446433fc893c18da89ed923703e2c7d1cbf99e847a19a390004a3ba9438f72c422621c7c85839efdb54ea790aae05f0a2c5ee6bb8f035ff5b692dedb987bf961513d21c58518efc7732d069c488f96039b5b1f4e90e289af64b2e6a989b54da927d35dd4f9a522e69413362d069ea518ff4391bde6c60a0ef9a6f6b2db1fe32b162985c1b174b30292e2db704df87d921212e17f1a2a771d76438a38d07385af5d9b9dc8232c758d1a90b62b588a8f1b2292afe02efbf53fa5d909d92aec6adf93f2754dc5c4af4bafa8ff92957daec4e9796445c0a62ec175ccfd3445da38bd7e986cb53e14d77b5bbc8c8372c824fd69f494532ad7f42a671ffc425f9c320eec40c94ebe850318112f0841d9a0469c731fada623d63158cf2805bcd8f3080a4e29970bc5bfdcd23245be5606e6fcf84027e8b33a627d3658a1108480cc2bb4d7248788c2420d8de33c18a198c11a68236fc4485db3f2059c7f41bbea301e41e5579b87d6bd9934f2c3669e511499d8205e019f3012ef6f40b39b3e8779f0b387e1d26dc4722eca5184eb684ea33942c747d91fb0eea0ea9e67eac591aec296491e6a56f12632e27d006606378bfae1a411ec224802126712125578d6a2584641f78ff9e0247655f8d442edd535eb973df853c138564eb42e5952e75da5ac8e602200600171dc08be4ed90bc0fbde84df52e2e124d354fea79f043e514493ca17ce634b9d2d8350b8e7a8e9574fb49b3abfc159819284ea7a34f93c977c3c050dc8d0ffce9178359b8386407ee62eb36a657cb9896182ecc6897af043d50ce2058c1f907cb35788a3596e963cfd6e400dfa955654cff28c4317426548c25e3a98ca916a67c4462ed3c6865a246742417755bbe9e1f14c9f76a8c5a52d83ed59647f561532d178c71808a741509c887563de8a457db283369544a73d45d936dbd59a0c982bdb253a10a359babf0ca842aa4492e0f445835809e2ce20c2df7c466988a5cb16882e1d2607078869f0494e72381b922231cb50f25a88b2301c109bb5392426e60324c0ec9365c5921171cea87c424d1af685a57bd09d51291a5a125693301b7624b45124f6d335129fbfcda316bde91e6617864c6bad697f989bcc5fa4770de1e721a7002a8c4347653f4018fc1293f03583e4c7ff4b710f428019cb2bdbb152eaadc444a3fac773d4d6f259419d3a7417c200603de16fe7b2fb6b6ccd7f79d8df3656d85cbd8802b449daaec3ad72652624cdfc1e6d278e15f76685baeda4b3ee5f4472504757efff8228dceeb0c1d640f1b7b5bd70a012d1a6701213b6c56678338fa7ae360f0049c03867fc82fbc0c2201f8a416f86494106bc247a5230f5ad76d76ba61fdc8bb87892f91c6dfcc27dbebed7c58c7cdc0d12c91b6162620410c060ba56d9d8ac5d58a4fd77cd3f1fcb81610d9db9e1972f778edf8f8c93e62539d522121602694d450f33b59b97858c4fa71db48a7a354fe15b037264a61a335d299148bb8d651692af1973d72052e4de16e2f9c049228a76276bd1adeef4c98747b1caf175011369a431defb5b28bf840b55d05a0a1c14af4d76dae2d95f0360b64cbba4f82bc263cc206854efd7ee1e1b5443da248adf4d5f0ca40684b2f3332310d28635082240b0f468c8983281091bc059f6f6776b05be51fee12aaa83efe13291aadfa1ac103afbaf5991e4375e108347543c44a890c7fa3c88653ceaefa4baef8ad68739e60545c7ee25077c90c98219b0bbb8677f58effbf40e7041f9d2b0fa31938b9e116fde302cd69c9facbb4fc8071de8e388a02f86e64a25edae2891b4d579b69b4d560086058b04b1ecb5b5adf48f182c159f4b1fb520a75ca1cedf38bc7f489216a3c2a6c74aef6f9710c898896e50f63418cf6553073402f5501b4652c7e314a7369568519762b971688f7dec4e6e3c00c79fef31ce77708e2385c0013777de3e57a3d071075cc9f4c2f7b3d204ad62cd55410699148efedc6d6719f94e0094707772bf35dd00b161bb16e5bf3030d2856bc047bb379bd4fe66f838af22b54fe3067e6a08447b07eda28d847c15f6eee271a813713100c3c72e6a0d1edf6a00ce741b615a7e61c9203b76305fdb30abe22825df258422bd156299c5d78857fc87f5942be4f7e32649cacff805c52b730b340649956665c0f74d089a90344e5f120704a5001891059133a906eeabe88ab02ecfa1f2b298dd3b45bb215f22e6c68be12bf190acba3914bac141a1642ed32650da4e59d076f628eb55c5eb7333e0c17ee63c3707361b085fc2314b8c25ce7722a38b07216721d06cf2e70b62af3c5cf6ac4699891209a7bc695825c337dcc0c8f6c700e9de0e758307824ab99c268fce52c56676556ea2a9c9309687f026981151ee5d8d512574e055acd2bb08d3ed0d312d6b46f26ecf3b02a29e1f2e48b236956aba140e5528f632095fc80272866db888432f2ade94154386e4a77837c5c7ab4fcf26794e37abfd4ae5c642f6db19eb1450277598bd9d699014d0a7923663c971d0257a719c081000631086803fe4e8194ed37f856b48428b19448a409548359ea4fb5c4134671525cf3ff7bcf6d174f1a73b55cb5878cc8c964ad3a478a902d1eaab9c02d315bf2588eaa977690309042b0e922d2cae3214fb53981b9337c3b2eca245be1dc34198bc3ae0d78ba8fd67af930f2187e270ff3a1c048cc695ac8925f56175b741b0ab4292851766fc12e1b0e37a7b9b8f3cbc9e483672abe16244dd0d2500b43140dbbeca158272a4180413fca45282194d49f6c0a9b20691444bb0a3572264af1872e81c24c5c3833817806ae0d368192088be7b9638e8a9a58450e108ef317eb3579a5694b8962d1a69dcb60a1580fc35102c2fcbed90487bc9a05de643357cf217fcbf2143a92fa79811f040a8a97481291ca5dc5f1e5b3b19ae6380cda2aa13d0656a7bb00c771f2ebeec6e1f703e9d2d8a92a769006c02dca892c8ebbe4be21809ffde1a60b286bbb90f11d03da6df16d6bf3c582c38e339acb682f15682093420a97d40061e191622b3b46254fd330e6f4d4194f42a33f743f97afbacb20e8b0de98dc5305095c48f6cd0e92289349323b8f19cb50ebc3a5343e2993c5afd6ec33affb8eb0c766aea390423c4213aa4ae498c046754be21155b1cd4725886ad0d723aaecebfc8f8e2a5a3b0c7305927c3df11e54d8dcc72375864690bacd0bf2b8c576ad619a5f64e484d660eca38000296934c83777e5555a3cc4db7c44f650ee7cf12874720efdaa19611d52c2cbe9fc79f4de9ce831b548cce7e8b343ae8a52e98ca018a2cecac0868f2886785fb250463c99dba84aebd43732062bd53e91cdd86793ad16e2602f80708c49d89dd34b7f98034abc3596a860ba278bf5913598c9359813da624d8d59426a26e9102e8f0b6acdbf73011655bf8f09145584a3c00a1b1e06c6b38bc7b88adee9bb030a74cddb90c127548a77c69626bcc390b6d7425475bcc0e2e6292c9b36daa923a4855d302163760d4a56a1c90d12c209da0468220bd3b8a920e988beda1327288a9d72425bd516cd9427b44e450b787598046e3e9e9398bd5dd19422df216f39867a025b12d2ed9a9b29a0008015db42a1897243ca09a903336bf9b53d41d895c1d937218173942f83d6e2dd4e3b511b01164e2d7dc9b2f265608d0f700315420cb3ff264481ffbe2e5552ae0eb0933283c13a11fa74ca6fbb1986c9d1b774d05abdf4192d17b7a3f2027eafe06c894e983819727ce51416810cd49b4c891983c11611c8b04b36887f5c6b984cbe3dcc1e282336c5ebcb58b1f0e40b76c61fa35d2c11a2b48ac0cf051ff8bf4a95f5c78b437f70fde685c09c6344af951ee3df513a7d84a74feaedac88713fb33b564ac3137997c70b805ebb97e19db0154bbe39cac6451e9947ad0f3e0857badc64a890a7e384c0982ada826c5cefdb2e6376a7ee2cdc86bdf4bf41b5f621f36ae4b300d410f882c89f107cb16b658afe08db679c704a792798e72fb34da9b9fd4d5d32cc13efe7fb1e496bdcdb655edbbebffae151bc0ef0a2c896df96941d805e553a534182e69b901e22e5b7238685e359e5f0c04ed2126f48722188148016366bb038871dcb05f8d4e0e4c1f2719dab65f81b949cbc358594cccb83e0df751376c269d971a74afa3ab25f9493396c9891f8c073555acc30ab09c49c208036998466b2faa501dd345b9bcdbdae54b507936b322be099a24b2051940e0e1f484011cc0fafb6cb36c7fd3f55241f11755c4cd61924c0462cc7816af010f356c95e2c9c21e568ef60a3a6079055e9dc9b1a49791a99f8e1398d83c1754fab4aaf47f8b72c7a5f6d52a52f36ea75ca069d20d161c47fa798f512a467025ac3f615771a0aa935f526077a2006fd48fd9fef3f3e7dbfffc7ff057375bc7a64b0058369805413fefa4df7ba477956b49c32cd911e2b21faf6ea655eaa26524c9eb190f8618c8b1b971832662ae66960f36379f40ba16a452e9006666c9960794b0fd61182863b6d80b16114941e9f7fced129f855056eafa837a9d5144ee395e0b1a4782787365fb38bf947ea91e959a81c1ac285de0f580e56e5c1fdeaece90b33377712e11453c884da191e8b3cb9c3521b2325dac54150262a63daa89290708c094d75aae3f510e8898fe30d82fa9736d03d3f0ddd7bf5a82b2d84fc3fac84047e938933e8d3c47dd13b92e68bb4b0d53cda62fe700ba7bb367b51ffe112d5cddc6bdb8bca4f97526eee465b9d4c5635ffeed65400c5b2e6f91eb4d3aef99c21444b2de8d7e4b1413331933ee858985f13d0ec155448dfe2ec5e19f490177760d6fc0a8e22060b7ba5202582ef3b03d333e9839e7dd31855bd9a50a50faa26b3f405457de3386fe672d5fc33971ba4af3487a5448430a6f97e336e1d1ff4ec1b36c6a2e69fb2f8351d0ffa9a384a354f3d1b3cfbc2aaa6e32be2bc37a0d5b89befe54c03e088b905fab9e110ad0892b94b32243a38cf8cd0261e7791fc2c5eb87f6459c68e7911f885c59e0dcf7ad0d1afadbe162f6df4e3f67e79e9c6069c9da31817a4c8773440cf0e3268b4b42b1f9e47a8f1256960253d0b072a5020badbe200b26acf18cf3e808eb6b64b31833502ab676468101f8c85e4d075280e9cb7cebf12983687d098e917cc84715ec1844d1cd1baa4a676fef33ddd0809f81103029d80f3db873c78f70fb80b38c0ce8a900059829cd690605cdffa5a7a0ae967b4087cff5bcf53207db259b6c087eee3d85265b7de7667dca299e8e9d8f2b5aa7c5fe6e335bdb58c76de15dc22a0bc791a882d7748deaf496ea7adbf4c91977850c8c836cf7b8311d6c8c81d68a895304ce3d6bb01f6b3510ee093373d364e6a58bae524c96c6991d6835b7c4b6ba8841d6544220a36b0215e278edf0abd515cd92607781d0525b9ba426f5c5158efa626557ba4eee2e3247a34987d3c20820407f724ccdb73fbc6b8196a9d310fa98c824af55a6b812ca5e0febf91f015f374177858ffe738892c4389e9d09589368470eb96c28de81502b5aa705331ab5bc5079f3a2817ccd571b4662307b221175abc60826ac5beb10bec75528deaa0bcad5ddebb9bfeda413839c6304b9c42e056bd306b0ac3826edca79e084410504de3e35bd68cd0d54614e1bc0accaceaf5aeca902cb0b8f7fc19af60863630095f6fa57bca3172f8bb804fe61d66a24351c02e86d914a9ed65fe9f33b505bc8e83e3a0a259cf1dd1362b3834fb5bed48f3fe26d8f2453f1268f9c2bf04b9b458ffed97c0b74b7eb3869e6dae395882c7663b80762be146b0d59842c8249969b482b02bf78c2e88c4997eb79199a84c243e4d0f2e9ed44c12fe819fece760b6bf612acbf57f70739c23823d70fc8ffe064a8c6f53d1df38e1e0b68d5bd77e5c82be596e6ddda2f6f332d4cd713bb6dcd6311888ac8beda33f75d84fce8553a80c5f61dd9ffa024ca358e9db46264405fb877b10845c7cd66d6c4d33df3d31809cfbc622c91ea68458225c10fd6241abf3e48d86b21164d9847f2694eec450feae3eadcea0086b7ebcab5ca5d5f3b8e7aebe7148d1e67b9cfca25f66e625f2b0d967c9c2d9579ae69f940c2b1dd96e5e0798cda9054c9c2ff6926db15bdec1bf98c29d05188347ba00ca074d2ec500421d5b6da4218d42ea3cdd77f6bf0839a786016fd11ba3e6384bb931799ddafab9e969bfeb3fede9242ad96ff5abe338ba32857ecc9f3ed3ff743f266defd99ebbfa8929ad8d3f971d56144d7cb62722a00d7090611df699fe3ab28e8dc0db923df0fc91d80f04355b100f7652c8b100a4522391f913857126025787ab5af65197412480ca87f74b53e66ffb58d464f11146db1f51be724851c56ebcde33ba1f27bd0de32ae4effd2cf506882213ff2286baf882bf7ebdd19301898a8817337496e6bcd6078dd720bd6afdb806f1cb79ba8c659b3bee15c139c2a8b92d35e81bcb496153e9eed8f0bede6bc555446c166887acbfeb5cb0fcad08d6f88420bce73e946f4be93618ee8ad38fa876d0d3f20cff65871bf03acb2edb07f42ac0817f951c7bdb1514b308c4dfb80c7d336399fb8a4e740c7e3d5ced6f737aed66c88309fe86d75dabf9664aafa0e01f5390ab6db2bec102fe00429f9692c226fe2a653a7c401daccb564905ae75fdbf183d9ceec6df27bc1775fee21ef8fc1bff4e40235c05b244606679acda94204ef481de09b229be7b2578cfa1c6e0aef46967b169adef5a1edb4d4bfc0a213ccd527cbec4629bf229f3098d20316bceeda2e5bf7ff4021531b085b674ef29acfd4adfa0054768e41aa644cda315271fd8ddebc9c1aa0d8cecae1b8fabb30d5fe592b1503b8d5fccb62885444040481e1744f4823b421510f758d51cb36baa443d87f9d8b26ffee3216b57a8da0a626ee67dfb2793ae50e1eb3170ee37cc793ce49b9fdc1b5d86716e566c433a5e91976d77144df57ad54f92afdb91d786ef0978621affd89bae121bdcfd181ed2bd87c4f0b2e7e776f84656803e2041aa044568907b7345ee8a03624a17c605b9d4f44bf67de338f73b12905e169f005ce41ca00dc7564487a2ad085dfa9dc33381112bf69600dc4f361b8ac0c5cb3ba284ccee85c31117066f5cc7896415b1672d38fcc2c0e00563456e071850846eb22332bbe23517717f0007778264fc2024c753e7f59dfc23fd001dbe533d8c13b211ffe5bda9f623c929eabf12ccee11facae5697c4815021e0eb088f79de3928daaca379662830f66e420b7e2dbeed073075bce49f9e02fe68cda3bb2f9460cd46b36ad22029505ad74a8d22bccfb2874c45e375cf5d8b3e7001c286cdd7a61c20d8c49f5cda74a7ec5c086c914fff37b7ece4b45e9274ec10812cefad59486b733a7a76d7fcac77e79faabbcdd508fe9d478a982a63d8deb560846147e1e98ea5397129fe338b111592cde52e393fea07a7c1386a93a0ea5368355bdfee1209812d07d99ab706a2ec22dd19af6f0e14da4048c43ae3ed7dba854a5c9acd8d606880ba4144a02795fee5935b563d2530181dc1c0718164f2117f29a9a047c516c026f4263b2c7f528477864f95fb36841b3c4517b8e6e3c1ae957fe5fc978b6491e96b4340dc5f4184b3db01ccc31ce671617a125e489f25ce3faba2f9119f1a83a0f7b067bfb82450d0009dae48fb0078625e640e7cc18ca10a36b3393628ee56c1039a037f39632cce9e3be883ccd04ed0c56c071e81aa28dd1761de6195bf4d62882e231167d5e7e14c205adf9076be18f9e87e9c37e0bf0f53a18885128f68804506a027c4a468810ee067e54d136f1bdc283688c1dbdf12e1c07de3d810555d9766cc20bf472116aa6ce198afdcc53f8855e06bfc60fc2a8309f6c78268f7a00b91f1efe3ec028a30944b1e797538677cc21a80f647da2827dd48328cabf7a25a6cbfe9d69e001f634117c92a895d8408b259102bcc850adb53ad11ae0c10c2d7e4181d200870e57e066de10802b2c8dbd3ba80ddc0e4be3452d06a4f6007cbda41e68b50e743c397b72c3a9ebb755b5691cc9de06d62279bd83a5d12fb193e68cf8fdda04942d4612e8dfd8183dac769070a7908f9142159f5015e38044ff5b8cced609f03979a94ca76353004ba3d25a4ce308db1498c43513f3e231cad561480083c5ef382dcb6b388d3041189252149bcb47420d9ee8a670fbb61eac48a057ba69791b028ef05e0d0062487453fd25d18c1027efb8546772845114792367797aff9d07b065a183fbef22f2a123548c89fd59a7d835404d07cc8c037370166c1b50171769da440d4375aa5fad2aaf73974ca7a4700b6d141b65fecf95b2e935e720ecd4dc332b8ea8662344dc9ea89674c8d051a47b327a131cf7379fe8b8431228c3007c07d87d5c986beeb4d5fb6405fe5577db92c70f1f825fb4330b40c8f80380f2ae6f942a66650055a03030b563b87b7dd0b80cdbfb8196a5118a6d3ce30c2f00652652cf7e95d35ab84c288146ac4844fa53d9039864c5b5e7ab7f491c40ac8a897ff9bfda58d99facead75856bf10f1af3cf803d067a7cf776f030c9710406ab266ffee4c08d0fb54b586487077d378ee159f15c70f26aa69844fc2336448f7e87053d95934a0c06d436dc3bfc506a56f92e04b9ebdae1e42f95ee72aa126069c441241d533b19747bfca44df2932da2057c6a4ca49cf81ca9a6bffbda35f7b5da00e43157cc2411bcfcc61070064f32a821000627d9ef99995fc7ec67e4ec5c12753210ea9ddfeac2ecf33bb84ac37c96d51be104d2a2b4e06f20b08196155efe0a54192d71a50a83202b3a96f1c59f86556e8fd5397da09e9691b27667ef0d8b2c0ac5b542c20607074e398f5102b92ff2c2978c5456ad00ca95bbd27998383e97f7226af089af3e76eea660f14abc1e85ce5f57566a3496d22abb1e3d5c3d959af18443de5d29b98bb5738907ce004b4ac37fa38239b42085eca602aab73cf5af640e93e9d3aa0e2053680a95829194875c43e739cc79cf0c26905bbad3d10c7ca65427b3c0ec2293844391995f28e885f827d57746b1a28a84da0049f8e70c31dde828858753419f37b007a13c54081f2d722f8c81937038eab5ba4e6174d00972090130e7532ad1d741bf41980edaafd9546cdac6fb82b4026794122b1d6d8ba416c0130cf59f0ae5c377359d057675cf734695d791221411a845960724201028bda2fb30c52a83bd8e53b4a5f688a835d800b0c81d42b75c593d5c9298a15f01ccf1bc5ddd45cbe40c3f4f9685aac7e4603c307a18b2b07b2cb6a594c680bd33f0600937da4a1e8502631aac748edf9ce3e44aa05c759c82fa1ffdcb93bd286607810387a4c4aa434303b079fe1c4d11336673b6d0ec0777368f09702972c46c3440062940324b7b13dae555fe0da5fc48675ec29edef28593dc8bd108034dde06e4a5360c8fe5012752e419a8addadae48986951af6153212cb4c5fdeaec91ecf11ee8f14a69addd6e222847449cd8a1b41fa8a7d9a37fddc2278c67e37c5719834f8fa03a0a5432f9b057f01e36600a9c42e04b850c9b3e5ae0beddcddc57883c1c82434184f44d4468b9a74bb8b8a3f30599f62e43811fbdadc31ce392bc1bb0382db2d510c56bd88cd6dfb014b52f489a83ee51948f5a09fc56989cf922cebe49f89f756d807e4ecf1a017e86a10b0c7fba7fc7e1b761f004ccfd183d49be667b83da3085930b26a9f9d439807e6564d926788a76c567a6ee302a46c7851ebd04bdf86ca6cf4dc42fe098b61901759e24aab4a448b0b3634892b92bf51842f3556ace70102f0135c361659de28da9baad1a7148a183353b791a36ced301f6faafe4e3359f5c3d02fd316d7af3c9e9581506a90e504284674472843d9e212ae1ac2066d4f9548784ceae36f0c3782dcd39dc2e22231a8158d3a60494d1d794fcec0db157b4aeef741e319f917547bf604b2960639ad55cf9bc08e6cd0afa232b62f551b0de05caa21561b52f8ed7581d6f58e31cf4fc0ebf7edaa11e291bb121028463430885e1b0123e290e816e36f4c9d5bc8a74172f84dd1312c6797db494b976387202a29197aeb04b2061c5d9567b41b367cd88f649a8a17705d6d31f35405a119261546fed414b5845ecf977cf693dfc085671802646f111dd97dd77a941894dcbdd64841285c64237a7eeefff41431d7f19ed80433eb68561f72900c01ed430b01d84dc39434ad8fd1b4cb0f8df1c9d5b296234b6ade052dbe396346b53f8a580fd64237eef5adcdd1fa636bfa781a08b47665d6ab2c2a15ac59d0df16bd68bf4e36e83136f91a899e0fbedd8e17779d2f9c4ab3a6b8dd74c542ca8fed8dd6dc026820b1d8069680c4a9a6295935b2f8e951f8ba7e73c207627b07847acbc3ed2145b5080a5af256ed40de0cfff7de0fa2686c950b096fb631c21f47c90f99d9a26393e87f46cdcbc7df939078d2040a2e15f91c73fc8c7d8aca1a876b5b7cf57a88026b2d63601200b60806481f9934c2edaf72f0657c22d53195ba78c9283ae8a36d62796fe1c50b4d698f1d1ace919cb50ad9e1744aeb6a88fd289e094bf0ac97634541e86db65fb24ecffedee4ea5f8fed3e3b58d947d38fc705403bbf12dc52dd801e7b8fc735e65ddba2d999ea99a5c7c0b276e3d8ece9c8a921f00a3ce4787e914ef714cc777236fc225bb600e91b9670d50487fb03e743d6e1568f8b4b1d4634d4b532b06a9de231ab921a6f7ca80ec6f8095cd5bea0b6b9eb342d7fbb045d2ab5418e0d96dcfe227f002a456679ebcd89b70c031255e53a12c0a30da1b3b95fb5b564e5af1ba2704446bee130b18d8aa2e08e633c4443985a1c25601ae458f03dedf1a8c403fee814c05a22e913abed082329c4ca55aaa2529997d47c14220e402883c82485f688da056aa389b50691525ec134aa443492e1a138f5d964c2230a9bf9c15fa4f14dc25d99fb5d0ec282394492521b5ae1654fde4cb9f7c06b6f175d43180c4094939d2173c791d958229f043458136d07a1969db3d0b6b343e520cf18b794175fc4b6348f157f7dc333148cb712fb95b81fd46071cd674291c85ba02a039cbacc9868f3f0aed30d5033c337912891f5f126946fcb3d5035a1ad730d4a45338dce110b254b9683a071a3dd434810736ceb0e8f850da3ec3f40305d7b22308bdb4ee8e7be88a71174ffc650d493d90faa4521eaab93d079c0402c79c163b20ed2dc5fba8e109c3f8720f38d64de12a6cf781d1f38221347f601c1874f5124c9f8eb8605511a249e238e0ef26fed210946b4f5fa07ddc5ea37233c1c5d4ae7416c81b81b0c04b577e7cfa80b892bb16a408f329938ae042c781dc9d28166292323158b7c63740e43d5781fac2c2457fb02920ae5ec87c420e07a160662f2b2c0432a00ee051c33a87383f43591f3b2bd4a9ec8ac6055ef3fe75d90aa0e1e8d68fecbdac23b2ba930062849410f097878e58a20367a48978ef99639a932d9bba8aac45d616e23184e305ad42da3cb65e05d91b11fb848b6e2e30c9e6ad0f891caeaa0f96e69def4b2a5a73ea10fb33814c1e3fd3a517e4b331bf8c2b23cf3d6feaf7fa496a9012816f6eb4d171be8283749f083569d13e86d87f46b8f83345226fac8e5d3fe56ae3d66769e3ff0530cf7ccc9367f7caa3edba7289523d378be4d1ba7bdac347ed43b8abb467285b7ba10f4f350884fd04edd5e935d6cb2088fcfc2c5e7baa981df7b46a0fd64efc9b95a321a0b48d162f3168d40a6228830cea98623d66b159abde0890ed954967bff0704aae9ce60c01dbb0ecb5c8f35016955d6d2b31fe098c0768b2e207b11bf8a99b26cd602e81fa015a2c46a52ac16fc2019897d11531b9ef08fac6910aace8d50860fce961503698aa7b11fc8fac90d9dbc84182331340d372ce0228bb4611a090546ae560ff18c01e35116ed6f2cba2cd59c822ff357329b38da011a1e8ba70e80b7ec387908ceba47a07f6c4837c86eaf4ef1aadb570632bbb8c109ba1fd3d7df042a8609fffeef9c178fb64ff2c5bc962409cc5c300fa8031a3fe2e22dda073bc6083f09ca761346d1ea207bda4a22181d859f3a6a190aa64ad26038940d4862ce3bf1da6c0148432f0bc103b105eba839b8a81938a67b7713131427196f6e53c079e16beaec9c7ce64d9b9861550fe05f871c03c7237c2e232d7811e8cfc4fb202f2d2d9f416ecc69329396e811bf1ae63108884f61d77e4566d0c1b17c7ba05f4c3dba6400f3c6024814a24160895ccf81050752e6ad971603cde0b77ae32d2207040d594e334b35c17538df710dc7e7361e117e2c3b8a367725a341a7046c9f2a785c9b68cebf48fdbbce6c0a2cc1d2199236907ac0934183d268f7883b46fe0777b1d43d27586c92096a3b50c76b7de3be424c831e243e8cd8a865de64e3e3f28c80a6a4edbf0bc7c32a603a2da8c13c903b9b99e15f7639b857dd9930299d2bd2dead42bffc575cb945fb21c524adf95a9bd53f5e5634219a4dcf1c289cfc4f893d6e13cb4436ac65b64b67730a88080f5db8669f10a8c59d4109743cb419443171ce1abf0a091b1d39015091ac5bd8764bf0e2d99a67f168edb1d98ea26d663f1ad3d5434c2e2929a050736b6f22537f5627025d5d637c55e5b54ba2b7e27e48fcd36b5fe0d566b9d4a90dfba5f3f81c6ce1d7e9c1fcc6e70914a1ff20f1dbe0ac1d8d376e4ee54bab04ed1b13b489f5b3593579a2d30d5108fae2339959e1f6d232c6544f4eac239c2a4e88077b4a80efaa4517aa1229dac8aeb8a5166a0e4ff7a50e9b1f61b69375f8182ab976a0b9ea6c9b5d13f8a24e940e8da8d02ba6b0097d28b902f09500c0a08fc1c25a509c35fa19e161b824eeebde9bc0b1298c427ac085c1bc134c3746b55bb80224fba4196d1e8d782065386000ec0ba41bc25b4c547253f83d9733bb756088cced4459b9c47ab33a76464d1e9df010087e92662d14b062188998c826ef502bcfb81d5b2e3c913338e3de5fa1cbf9af5b2b90d8bfc1876933ccd33cf799d8fec3a4ee4b3ac85ab358920cb2e4fe59971f2669aa88bfdd899accd34085e005ee642197895c36466db0167f0f47c381e5ff3bd883f418fb51a73453ff541dc41474db18a38c880d5b61e19e53aedd72b832374b54ab0ab46ed9d39ee64c942be7faf18e167a1edd5a6b1f0769546138bba063d18f845a7899d7a01fc100ebc363acd962f64b219549a15345cbd72376e46dc86d98708b53e4f8a7399f6868974a4767956f5a9f10203f150e245eed83f190fc6a35f17fc92d4b06aff57dea49ed5bb6ce8927b8eb61d60eb75680b69334b562552e563d753a11b1dfccbcea72bd09baab04aec68f0b51d28efc1b8c0743c3edfb82904844c8d95eee31d54824e8cb80738cfb0036cacf76bd471bea64a3f73c6aab92fc201d7f9d3c287bde18cd76d84aa5f98a82e793439c703b4994004cdbdd1ad81c1d2ca0a1741a03c0c163f97dcc0102228c35e0b4d4d69b11b167512a9e1b37fb74c0ea94a58f41e7a85e2db1229966470a7bd223e10dd3c47bd15964e611ae839705aa30cad1a859732b2947d52b874672a5f5cb088c446e1f366c71953ce1ea32de4cef4ee217418a84a3ba631b735c99a073c3f79373c3e38727a9061a1787876b4077f1f7a1998dee4390d5e45894fa40e9e4e2b641e03baf305625b40141ea5032279eab1e8658ff9fc13d55ad6971305b83ad97b954101e874a09bbd71944098a69939b8ff9bc9e2bbdfde6000ec0ad93760ee4860c222ee9b3c3352bc93f05fc01f5bd84bdb9e709dd61249c8967b6f29a54c322519e2050b06ca05a4da322ac4e18098e190198e99e1a0198efe77e3f7b1603dd6be22f477c3cda8d3e518b7aedb629756afa5623b7af971d56cb499b655ecf5dd4cbdafb90bebfc27bb7bc91e288661bee30bf31dbcb5d66cc4a48cbaf5fdf661341a7aecc5be56abf4d863252e71b5d6924824d2e8b1c7461acb6c347a37597d0f46c7d7b23ea7313ab2361b117e74f762326d3f4c3a4b607aea00f393e93a8d4fd268eca8be7f9669f5bd565b37137dffcbdfe989c27e69df6e3fb8514328b08791e2fcceaf7fd7666df4dd70bf77841ca117089f801042e8d33c43bf49c8f23b7ca64fb71f3c446709fc01f650926a5dead6cee6f2e3fa3bb7d993de6e3256c0fec4f50a4f7a90fecc703820562aab35eb95e17897378c4e6a8deac635171ff56ee25f9a4d6683bec38fd26992d1f623a5b3046e346681623504050d88601fdf23fc77610e38bbdb3bde081d3a81317d0f0914506ecda070724d2b2888644145d553a7d41c500912e2293da80cb13ddef383ca5365f8f99e0884213b547e38eec20f0286a309dbdf8fbb1f13f136266cc73e5daa1d04e53cdde1ad93dcf51d88c3f4fa8c7fa885174bcde6768cc4590a1296d232a8585b67626d478e50f37c3d3b539dd3e98d23baa65f157f567f674e60bb37c458769a880b469a926d0966e7e29d14cc3654b29bdc4894e234cd6060be542a6dde5c96d31d347a1b44da461f3bc88891fe41e1a73ca1700291892886686424c32e7a5d975ff182d7e9bafaad7eda3f79069c13b73ff2e0f64336f26efa2d2b6cf786fa7720a52fa865f4971a0342280a2089ed38c8b4753c3ce4461e72e9e51be10dfe97d38ea47f4656b192e6907090a42f0590c4420047870add86800c1dbac1558c14d6812e03112df9e9cc96be3bddf82fa2e4b534fb84acefeaed9fb9f156daecd63d47da3a0e35da3a548a25a517fdd8515a4aaf78889f44b9fdfc646e4f78ebec7d62c48811231d3f7c18869db089a12e96da79ce6a603ff7d437bc9a861c91db26b86de343ede7ddb0504664bbd30916e6846d8bd9dcc736e603764307532e8e1c2fb79f860e1ececc9afd2e756be56efdbff5746bfd57e3b4a4518659d47deb7878ee75020df6fc8c69f5d269c2e6d5310f7f29b578b90b7807b83537be76e38b1bbbd28d16ce93a927b92b3149b7cede9e5bc72c74e5b484acc0d7ccd13e2b3ce0f3a52d6323b1058b5ca7d11c7495a5c139fa380be4815ba8c1b0c86dcd4f274a4fd7df887fbdcf6dd63a1b98fddbfd1b4e11c17bdcd94c27b69f1dca20819de66e95a584990b673141b19d89027556a34aee7b0b096e819b5a4a2e9f62c0e7ef876f837353b8acb2085979c22a292b50891dcf237aef05cd09db3190914ba93d157111638367810b5c97ef6d9dfc29a794f6d1c973ba0f6e1d6a3e7d38f4e7863d4b7a580321cff7febdf73ec2f7f0b512187cd7bada31478e3cf57ab5268e1c1d76f320ca289fe9c558e39352ca175f7c727bf027cad8735dbe7d9a49fe7b9b9cf2ffbdfab280cf6d11f6df5f2a538c34f8edf1ebdc03cbc4b9614dc528f43326cb51b7d4695dc10a50d42badd651d49d86bad350a7d5644fa6d38ca5ee3427ea9556eb33266b67a8d36aa9d3eaceb9c328d25d0c6635fe7aed7a6556c3336f2e66de9ccc66a604cd94702daa6ead5786d52ccb5c8b466ea9e4dacc8571cd7463b21ad6d652e6a628a5941edd84c20929a4703af129263365dedc09d98b135ebc78618a8179f1a2645fbc78417a31ca5ebc783147f0ac3559ebce71d0a39c294b08c348443212911189644bd5c2c0c4c4a4c029bc1450400105145248e1747af1a2098dc99e4ca7190b8013916a670210000108a0c90c1112114bc48dc0346ddb880c60004468dc9fbf21d312ab3251c18f35377c107614fa73c8815b6d4312bc09e4c086bac6007b0fb349589345d970281bee6d4aecc9649b53818d815a626d82b09c55626992b0dd6d91e8eeeeeec6dc56da0d3d32fc08dbb6669bb3210c231121422292eab8eb00221120e20266832c64ea2f38371c42ddb88221491aaa17361a9188b0a4a118311cf36250a918a9193030267b329d666c4ccc8c29ab719a79ea9556cbd1a0d0993a7bba015f9fb4f95cacd68f5fa9561f23699dccbb32f32f2204b918adf4c6bb3c78fa33d01f237d998497a4bd7b5dab661afc4beb4bb5fa9cd9781bc5fed2e0cd341a7abce8f2651a10dd772f1e577ccf6a5cd90c7ce77d7db1d732bc6fa6f197fbe3864b9f7f2ead41fdab46e9634106fbbeefb236035feb2fcd7a37d9bb398d5836019b33c618e79b34de5086c1bf6720ddf8357b374e277317188649f9d2bd06bfefddd0d033ffbd9b1ae2bf7723b719e6a553e690893233b053189c6bcd25c31c6c6c6c6c6cba1983158697e44d23a4c0206ffffbc562d6947a8cb73f8965c1cc06fc8efe6420849c04ac736e7c1fe84f83cfcf8defc3c47d19bf9bc7236e32391870fd19000570fb69f8fbb606f8e8f6d360efdb54b8efbdf7fab626f3befb7143d464de96a37f3a9f6b03f2782e30e0f6d3f084eedbde978b797d7152516a7925ca0b0cd0858a7e6aabad34279ac7825fc749c598d1ffb62e7e2a460c3bad6f2a374ac3758dad1da47930fc7bf3f9ce35e736347d673fd53a1823350367ce3921e5810a4cb0745021a5efc67366b496a2c0bbc1088e387c211cd6794f4031e5fabf909a31f3333f737a2b9b542a7519b1f0bbd4ed4d12c9196031c61863843146287cb0f0e17d5298f42089a49452ca7eabb22ada848d2c278cd135fea8e63ce5e3da308a8142e5748d3f8dd70da0be94cfb5f65a80539b31b7aac9cf341d3b6a90321b693b1d2f0eb9958a58ccc78d21e6caa7613acd94e05562bb193366ad75625bf79525bcf2f9b580e3c1f0971bf618f64273ae8386a4d7d2928c9eca4f4108218470b44108e1ac48462a6bb2263be3facf782186530e0d1c3a76ec98ac0d8c1550315237af851a9bc702bc516232a7e319efcd3c91ca74329d4c26fb6efc519f0018d753330ef05ab879301cae4005bee6efbdf79ef6844d6d31506c7a1a29a50442852140ccdfc31aa900f84eb007af07413dbc7162f4bd666acd441b427ed90d6b3ad9d834675b01f0b96fcc25b0f7efbdf7dee36e9bebef513470b48cde68fb9bb136a8196b9a62057b570ff684fb56435e90b0f3298410422b2afc8c400a142bde7befbd479fc65f4b817dad00d805ebeeeeee867e3b7faf2de3757fafcec795365c79bb9e16fec1d8c095aec4dd2dcb92dc0dec8e124518c6bbf07320d7dbb2fbddd84ff6f895b3db270f587ce8d11d88ed52d7aaa4745a4d5a6c67ad079b2d6b72332b3c166ab035af857e7feeb160836a9cf92eb51c1a5d43d3d07068f1be5473fe339a2b09b130957a333f250af6be1fcfdcb79a82ca9db9fd49e66b34cd599573f4774d5aacabc0d6fb1dfd145a60e1777f1b676ede524a2994c46a8a28d7fbd120f39eaf4c0ed27d4fba493ad0dfe337c90fdcba7f74f3131884add3248c94ed982fb71f321150e18bce7cd601aa3af3815c27887c1da8ce7b07e87c87ebcc4d0720241df9ad0363668374808802ecb58ccd058eb3f199cc2f90b2a5c3dea14b972e3f3f3fdd9dc3b79ebefd388fcd2acc698400802a3872841eb972e54a962c59a698624e11441034881e7aa03d000104105a6831b5e0828bc9c50e3bd01d8a8a8a882611114450227082cc08e39208e38444430c3144952ab3ca0f3fd01f72c82187201ad4ddcfb22147489a5fa48cd1210c02c8d6d0cfa3af501d42221344772c5e887cb89d63e1723b2bc4352c44d734a5c462e576aedd87050858a4b87b9c5c96483929c522045b976561f9c17204cb900bbb2e2bb7af30a1a357b85cd3ab1876e5882b3ea0d60a856158adf58a104c1a924275e7cbad93115a54587f1ef29da35837698ebeed3c3719ad00a972052d42952a3da8e284655996755d571525ac5529c1355d2fe5f480f75eff0ea8d33f478c34c70d6798bb2124e21e6d5897e634ebb59e5e17915ab31a4359679688ac5966c3ba34d688cad19c4a0e4ba552a9f9a130ea7c4ea41b377e3eea3c2093a3deb87538ae6f9408d87b15c0385b1fffdc875d5dd8b8796ca6e91d087d38f78e1baf2eac3fdc71756123f768da80777e8e1a9b3bb2e1cecd06bd3aeefbae67de0e757b732ab0bd39ecf19cae4d8d5752c2b3f2c997039f10d81077ec84db09bb922318886d88a177e8e850178541928fcd7def753f7b73e0d320cbe4e81f57b3d7b31af1f28bc20f0019d88edf5015ec61019d4c0ccdb50c8ee6fa85e6fa7798eecb6cf4773452dcba27a172eb6468645235f8e54163e6cca0916a2ebaf49f5b0d7edfc6c31dc69cdeba8610421835df9ac6d4023b84f48475970fbf42779f7ea565ee0fd0e7cf24a5a5efa8ed4e174ae7ae6fc79f7dc7572607fdc997bfb475d45e277993264d9a7093264d9ab4aa49932650a552a95ca552a9a24aa5924c542ad564c2840913ca840913265645a2c4c9559908c1ac64e18245add8653d46aad8958d3a9fdbf1c71f5dfe8b6928148f51bd99c603febbf076a4db2c315b6bc8f8fbedf8cab870a5e4417f742f6b8312450a156e7204891227eda5499026429a148156b270c1c2a144914225aa8e2051e2447a5105510951159956b270c182428922858ac5e40812254e2e2f4c823011c2a40866250b172c2a942852a86495b5cee650c19157f390a494bc9a77bb9743054e5ecd6b1c3b1a8de23f1746976edddc7cb30c03845ad9cad34515d135a0b3b9d1e9c76813a36b845045d8da009b0b9d0802fa010202ea9f0eb24551511116cc5498cac3a22746c8b215a6c254749828b5f674b2a94b63119f1ecdf5cbf4345753b77b5324a5d69e4eff9c444908df16736e3f5232be75347ceeebb7d39c0e2f166e1dcde51d1dd6cd210db10c84b7044a082184b0b264c9b5a5942c61ad554aec0629822da52c285bccd335ed3c2dc32dece5c5d8c64a20cdbdb421a70e8542a14e8fd2ff4ba9a4924a593f49dd7ed0e82c81f2fdfa5c59af28ec961d88e3fdb4c888240b24b30a4aaf879af5717962cf5b0799f2a4349eee552d53ecd435585b6123a5943efa0e8462f564fdf59976c9ccf7b9f3e9d3bf51ab01e185f1baea155d68c0972f5feebc74bedfb9c9cdf2abb0e45b25f21ef01356f11356b1133e228883784aed5071833afc77b01dc92a15ab588531b52af6fd5cb1ade3277ebad7d0c3e25141a15028d4b4f3dd0961c642b0b0a74b4a40a0214258ac8218497347f04f17b663d5ed6615457259b5041b6435c1ded2ba7eb7eaac4fb24fd3c5a8536abdb70ccba9e5e3f2190899baeb71e14c59f1e78472db9a338696e18df58435390f0acd97817ffde8b1d17ccee6c6dcbd34eb75a7d3c932a55fad94ce68ac2fb357acc3ef99a4b4fd38e92cf14dc605bff03dce879a0c3ddd470c3234cee969697bc59e208e777c19f856be3d86e6baa68b392206c98d5b5762829516ba6f002fc01e0d576bad7ac1adeb61c2daeb976d580c52da97df2f640823d723280f4b49a57cf7e8719a5470461819beebd33dd6b8f2a3e60f35eceb5bbef47a0c7a8f5feb356f6abd5f8c5f5f4e802ae03b74874e35a74597908b62a93bdf39c59d53dea87cf8ddb575a97bfd4df65d0c164827c07c17801b3b02dcf8f69ae2d65d8fbd497bcd0f1380cb5f3ae1f2cde51ffd7b312e7f67fa97617e2f9a81d47da4f6228c76717b57f6ae9dae77ad15586cb35b6deeb3286c17dfd278f4f3a4536edc52a06a355dec4d5dcff5674db536d74174789d25f42df5b7d429a596523aa2cf94bef560d0fa9e598fa39f69e0d6f7cc7a37f4baf4bd865bdf297d37d4bab4beffa319bdfe6c3dd568ba063ec98a935c02fdeb63a49447afc3eb641646bfa3376873bd843fd396384b17b06700d4ca527ef38d5956cac1a97457eb9a2f4af6dd8f66344eaa3e7c18edc11aabc19a910699be29f53b97957fbcdc58c440990dff2936fc7b08c66fece546f9623d64afb5f5142aabcbef174ae95e946ec6954fa9b5a7d33fc7a1a0508c299e166a19f1f91feb1b7ee7f3bc292d14a539fe2ec29a5e8172875fafafedbe759763d2a5a5615dd9726971b76a3cfc215f6aaa38f6e9107bd5cdb2737b560c77fee3acc7387341854bfff9b5e89c8eb20189d2cb06d1e17548d8d77afdf285b4b95ee2b48e98d6fa58ad55e33baa19bb0db73ead1ce5fab466d9f750ca9e65bcd1f7e62e0f18da7a6f9cd15bd6483bbdc7c20dba996cc4ffda12061857bfd0bbef112e4287b4146d31a3750061f29f8d9d18f8be28949e9e9b01e1635e31e6e70ba18e96c157c70e59a5c364eafb5cd263ff48dafc1bf2cb1dfd4863924c0e528e8573712d7e856bf1222f822204054a4389c274444c501496ca3a82065948d0204b093be127438aec208461ec30e40de92143554b256aa03a4503d52cd28bc44216492d6491dc426ec1e56224b72ceb7514ee27ac7287d0dda13f95500b75f71645935113de1085384196c89f10c3a2c65d03dc025c2cd6a811e04a2d893f748de662b246ed842bb524f05b03d263a3568dda48b32ec51a630cc3b08771a3b8e9f8c01fb0b90924ace39cd3a7b76bb1df6382e07337ec86d5e7dd884ca28a98827ebb040e3d7403914d10f0e35230901ddc3089e81000f98091c8430b218bd8e25bfa2d0f72089f1310b14451113f6c0134041538cc1b7a0890d8c5911bb6582f383ce9b7dc03101dfa2d638942804f0a59d46f998b21fa6d8360220102876e0c9c608a192491042557a6d0c180972a4a30610417e420053a2b6822249b30894c1c68501474bb27148b14918006d67e49c2ce2de4ca92a89041aeacba505975913283e8c4c9fc61d5c588a865d50588188355171e9c8b55971cbc08ab2bb4585d31845882d5154f34117f9e20912a1364b96204525c810391b5966084951541b0c207b6097bddb7b2c209265238c2ca0a27520a4bba6f6545112b2b8c64a6298d5821241a61b32f11096bbb88c0a6301443900359831597279e8415172551acb80ce159acb814597101c1aa0a25acaac89203b9034b9b9051ac89091288884bacaaf0c1bb586df94282d5962dbe84d51629565b76b0dac2c4961edc8e9b6297c0974c8c3ead195bacdfb7a2628818384e050a6ebf6b12b23999ec8c3dd2bda2a204b7e32210778792df118840b0a509597ce00b169d5682831d2872830e523871220947747ab3557217a1c207990f04e1a50b123f5fa2d04981688b131d649043155974bac9ed1515428cf820b1ef8eba1d4f7d026509276f89276e84222fd677efe7459fc5cf0ad5fe498d8550fa9ece77edfdd4188861f8f3f79f3e3c3e0b7931ce08a30cae7852c241c9073b2c848730d00e0b29c294530c53b53b0fe7aad653b6e65f9a774da43cb56eb1dde9e4a40b0fa60cc5a089dca3f65a2e062b3f7f1a2cc2fca091dbf97b704856e36d4dc403c360580416e177edb916221c581c3a76d0bcaa511a8cf2633418b5893183a6566dfe5f3331dcf8d8f53c343436b09de961a995da246cf7ef830ea494b640bd17e59bac7cf0bd2ddea3de1b04aaa61cd8ce34e3def3b67909e627fcc462cc6ef1c99e7ad81dd8ae760db85da2813d9570507242364b67c852ca0f50fa723e953f4b22c057b00007d6cfb781beb5fd1881842474fed4e4104d02c11a9641608fa69341979b50a2e5be269250723b29c4e52694005d29c463016ef16e8a600d7f4e7b11cbbc820f947045f5a3c3453d7c401c164e808323847e74b885749a0b28437e7e7e7e6ed069d5163f0d047160a6fc9065881688d32b2e22ea2188d35a600d7f6b51c9c038204e0b3a504248875fc74e0ae2c0661d5ea9563a4fc7765439b30cea029b21cbf57f990fdd9cb6a7e7d8bfb1275bb6bce60c7ca1d6a309dba37d5c357434e7d7c55238ca2b8ab273a9ba46e67a9f7b597fbdb5c9e4a06f516b6323fe3ae69357d483526b4fa77f8e43a1523775bdc57c63e81a7fcb2d69499904bb646472f0e5716d33b654731baa3987b54773fe392d7df4286941011209ec0b38cf711ee7e534568249042c2efd02dc6079f4d3ef9adf2a02926b3d0e1f3f3f3f38b0c3de3abf7dfd607ba6bceba48ff98ec7d403b3f15bef317de32a81ed9e90e949ab2238b98f838872ed779120b7f4303fab8e96617ffe8e9d9691fdbc99f637e63b6b3dfdb875d4c68c9e357a35f347a3b71a67a3d1ac3ae65b7be9a675d75b7d6bccd6f1dc98b7b48e4d37603e83c1768cc6836e3ca67b3df6d7cf1c486d94be7fce39e75c69306fd278f4c33c49ebfa4958bd7eb0b06be6979ab0f2e3b39dd433174a5d4d2417da5f7683af7d184d2607ccd387b16ec43ce96f4c4cc974ed5f5ffa9ca6305a69b34fab9ad53260ba1dcfc5361ed3656f194fffce49279d590d3abfd2195a86170088dd28ffccaab8334f4821dc3a6766264426307fe4cde1124e2d83f9698591096b499a4c8efafc3c1ffbfa3ef5a7e6fc3403278c34dffb727623bb416a92e6d7d99ffd23fb4767863c92590dcbb2b26c6659f634ab3103ad9cd9d8ba53dfd1a5d139df3637ff5dcf6c603fdfb3fa2fabdf5c9457268767e07479c0f7b9f09b6398c137c9f89f68ba46e9b0888e383bc1100ac87081e6c82fe0608ffe333064211ca4a30942d353548b7a049e46a894ae3665b1643310000024c314000020100a878322a150309ceab2681f14000b898a426a48170b845110a430086220c8106488018620400801c828434456008da10c2e8b5186d0f2a52156fcae6846a4b7360e8f38f372003d435d292ae013be2d96f21b4eeb169459f9c605c5b7854e83a977e09c059f833b5052183444ab30307a8703cc2b489762e7c32beade515a6071a68b68212a11bd2fe805eb6c658bc54cd669b4c27003c32775b079a4e285a22e0db1e277453322bdd150975c0af393b3c2aec60b78c5a29ee68e616d4e944c547803a561d6e6b8d0379d5eeb97827f1bf7b3e1db5d4a7a6fb25491db74d76e4fe430fd85402340eccb4d9c4af04d8ebee59a4d1a70659545084b80ee91e93bf89c82cfc12dd052183426fa4a0e362f89bc57d44d1aba58fb97a019d179b7660ce60f1b4e42736939c1cf81feae530cf0908961082cbbf086c8b2d2108bb42eb421a2bf335e8fb8c3777cabca48da8afc6b2e4b738431407be243245826e8b4e695c020e294c16ac4fc98b87141075f71154bdcf8d860e3401c2011959c85f9144c50c95e9193508d10b88d5903cf265db7e1b4569168ff632d15df5208b3891b7a2453a8e1cd5ebdc843a2a1dd2f27f0bd1cbad4f997757e2faf11d446b3f00051781670085f07765ec6e1862e7e1a5af71a82800651c780bb780787bbb337cec489ffb1af2102ab8ffb5fffe1bca3180ac96710d39b1a36a4dc1c5fc49c68ec8cf52269af0c51b0597e6082a3f6a11c668b45a398cf0cc39cfd4b215764cd14011c952b06fb084f3e5544976f9f533868b68fadcf1e54303c33e6ec5169037885052f21abfbec518f136c960a981b0d6ef6e8f30535df464a52eb21c1d76b387bd4367e169732608148e1a382127cc3309db1a88506bdedd2b54142b361dbb5f69487d1d618a04f546eb1f8c4d6c8029addd4a18f71c74d058f5e41f4fde4c3c04c0aecf4653bc4fdf8c1e9fcec9d41c719c94614a43b2289e1e2dc978008d3b3522088d31fbb80dd3851976b020f754dd0a4427a0b0e5597ec6d80bebbda40a952837befdc0610d93f047e21cba24d0bfa46b7a090170e5802469cdab6543fba8217291209c24ec7126e21b9edcbad6fd3073a8bf545563353fa5714c42da8330785e4cc4be72b6830d6bde80bba4b30f92ef456e853d53bc07d283c97f61b8b8adb82ec9e8ede6ff0e0e8305a0595b705fa5aea72dd1aa04a85f4141caa672ee9c828dbc796757a443780c83b292a23b91eb2b9acb76e05869e0eec0d12cdff2af3d8b4966b8fdc0a0ed59e22ec196484bd934a2cf71eb92b405487a5f4f73ab18936977d702b58483bde833b7f3370c787c0a8ba35d06f90a464606a4a15bd0587b6ae6dae76bec4d5cfd05585370587649f51552e3aa1caf9ede91d3a73fa5c51004bf4c83739ce30a9bfe059d12d966ee66eaf1ed62b1d28ffa1dde7a37bd1de5edd9a8e873ebf367df59015845eda0d3fc414bcf752f403eb659e400918c59c99dde08c1f48f3b77d09c838bc6d53e070bcfd528c1c417a4dec60c2854221f6b05d8caf15af1d099e8c2555af8390b2aa256857b0ec66c3494203405bc60903ec52538085aa0430169a2040ed3520853d3413af56b4652ce19ad60f2a4fa0e30032ea0546b4d8de640e567da16606caa9b1458c91b5530b24676ba383acea56e4a4bea667d3bc3d20a82bbc11a9fc2835721cc7806d195b862955cde894400d7e7129b67d6638010008bec425fb212bf9db32de3ad22818ec38da4911775834380e53cf9de437faab853e0e675a98176c73b055c4cac52d11fd537fdbb0b85b4412d2e3d871a6c3c3f56d4ea149aebe668034f2384d43b67e5db24f69cb4ad7fad21a4739c842c4bf31e68ac3bcedda9b71b6030011c401585133e677f2d3398a408d192ebbeb16f9ea46df82908bb62bdf830f7bd4506a6b81dbc9d559b4df2a6e7b4ad950e9ec791b37cd9367e1ac031f9233255fb249ee0de2d629a60b031365be58ad71f002088c219c4dc58aa763ec117200264c097aa0204346f4016da18954278d292984961d6a5c385a8bed6e60975bfc47056b850b5aafa1e3f3d593d18dc545858c2c86ad164b5e93ade25dd37b360f0d800ccd6229b486709ba84835558d984cf0caad61dc8a1ce3b851ecff77d09b1185e0b63006cc886796d2c5d24732ba64a1ab169093e8a84f800ebbb15827adfa09918db558a52fd92e1882de904a848965fec0ff6fc3671cde7011fdc43b93277bf8cebe139d1cb59458acd4dc88c7ea446161eb7c4c8eb330cbf094181053edfee48b3921b6882c859ec6ccdead5ee0563b100487273f061764823443274d3f24834e6af6f11309198019e81c0092639ce152c392dacc5bbf48ac1db790d855a19814a32f88caa6082b346e2f080a04865936fcc1d0ad422c8448d71067c7ec61c65ccc07fd18da86683ff965ce701b66c691206102d11be4678c83cfb66fa7cc2c328eebc602c06e8e34e2ac6ca87229b814ff750cdc645dc3c20e5303c07be134ac052e2764580ac7df88007c0ca9ae5db61865f01e7e5fe36f17c8a857a6e1764b5f719f0f803b6379810c2ef52f6a052216d781c4e2e794af759d40e9d5b6f1a0214508a222a7776a7f5443dcd577f1203182a3f66a54416fe0b7802c0d8d505283287a88d35ad71f5c1c7ab255e653a028252cacbe4aeb1317dbfec6bdb52e8dd39a6ce948951a1a7d958ce0b6c35e47331c622f0af5c2d1c66dd5e76da813bdff6c960614cb36022e653b07a60c6ab5d342e7f5cf5f78c16002505b0a12c33b284b407f05c9de968940421a7fea4e0bfaf86787de75561a4f0a8ff953c7a8b33e224f3e8dbd163a71c7b5f47b496dbb31429b8902f0b7a1aa4cb9ab7bb47b6f9842a120aa1c4eb9ab5c049863b83cfafc3cc8aca1fa84293a8d8620a628fbc2e9063b528a12f9a0116c12d08bfac6e00da79003b1da701ef4ad29cb9ccb24d0447c194c4189c22849303207acfff8f6d34f2ed83c4588bbc21cad3ef5be9fb0982e0b0e78d046525cb1da021b99782968bf254517b40e10c4be81ee6e2fd9676cf3e04d410b378613d22da6b5006c72128608c870d0f01b08992846ea47159cb05f3393cab48a6a2d2dfa5c3814fb02944a42395df45ffc6448ee486b40af16a41bd19ce18009c1a58bff99f9549284aaf804bd459b5d9eecf128c4d022c994983e0b974695a8382904996ae7efe9316426ceb015f77f11c23213995db4ef9f6aa990bc7f406e4010c2f44e6e9b62c60c0c29775dd5a5999ee7f1e59a3373cf00298b0564d7d9932c0d9cd67ef933e6b96b19abeddfa1e8fe8b2016e0664bf1c4b24841912981ecc610be8eb0339dc265089f486320783b01aab52344a1b56201318f59162b14226ae4b0dc214c3c1e089c16b540ea1341c13889b681e114f206d983e0865e9c5b2b9d3cf6206d3e783ff642f3ed8f48605d093caa267fc62949d15d4830008d0d0163c9a0b666b0e0293d8a586f2054048dbff45d90171d5f4bb00870969bb119293123933913c7b93b76e96a0c2688e2082620a6bbe061dd1151c0f7f8fc9ea6813870d087360bda09b8a4d849bd1442b61b2e00c520cd70d5b02605f642ee9f711e3c55242397d7d3a619944632682d14a69431f4188300b7c3d877d739648cbe6c4ee456cafb0b1e4b662600aa77d48a93c2efb7798c0ac26486410840720faf17f47beb79626fbb36284b837416bf21548a664696a2c4f1159f686db8245909fb7b884c3810e55691ad8346ac846ef82b108a26e404e375e1a3da3b5ff9836a9bc5972344a801a5a2c7e0a9c6e48f7642f555ac473b8fad668900af9c51cbd69339444505d07105e50cdd1dd26c63853dad561b5cf3f5b05addc1c97b43db52500b16acd04b1c2486bfb08eea3e7d08bf644bb69910aff199949e49e5c5b45a58315584623e540a9493bbbffe16296610d55a728a68ae1cc063badd7ce62b3942787930629b955057c50aeb45866338010256d08f2ff91c05db524e97b847333bb3bf82a1035ae885e622815e2e780082ac8048feb560ff90b3dde2e1d83beb8a8ecd5ccf7070dfb2e4f433bda7e8edb60e570a0a43dafee762df488f6f144d9677a9fe3705c419ecfba6f21f1695ac8802c63dc98b8c66b1326c426e162fcec42104d1e953c7e298d68842dcd6621d44b689a016ecdc4889231ec19de476705a3322f51820748d895259ab03a182a0c39f06a9c7f5f9796979dc7168900d48b91858df857415c99093f0d76f1b736da112e89d93e371b5738763afe404a02cfa75cf53abdf74f10cd03bf8bda5711f0d6004b1f94aeebbf4a818dd3bcc67c3d3bd0bbb382f3e91790f9806bc480a194241bd9276b022720b2d1ce0f543261cf7180af744a80233f2ffebaaa9b8556222064a240fa91d806e4c9acb582e25001c343f735dfeb6d0b73d5b81a4148d8362f61c359e322b432800f23ea1c04e8bee4fb6a31774ad106779625a22300370426cda621c8691f0ec8987197a878ce9e8a402e53e0b6d1ea35031218bf376dde1ff71afd3849f05b0e76299df9ebe870641efa82b99654a9650874e413d01441d2a443a40a6361863e91b403e26310ed99e42124589c030584898b1aae9d88a07485b66dc80261aaa02515bb2f3694b4f446eafb17882c25dd04fb5f897725776e9f75c66841934cf8b82dd7357529b1ae6a7aca74c20a4bb38b585d389598a3b767ece97dd623009843b1d59daf99cce53239d9c7adb52cf1c48588126131f605617099a9ec602f0ffd65cb500b9c58bc5d2b603407f4590752e8b78cdf250f612bf5a97c9338a28bf76f5751be786d3a450e759acf1a443dc7e90b6216c5147e0546c4ad4d8c8e17a5f01075e9ba6a9ec46a01e09c5a6ecd7100f13b6b2f7e821857767277775090cc85b4130611b7f3872b811057ce6d5297a04505abf9b5e389f36302a0ae466758d5a6bdc54d313eeb1ca18210ce368811d8b48aa6789a37941858e4bb2f196c41ae208b96e1edaf174e4db6ffacd6fe69b5283ec6038dd0a15203275a49fcf96966292a886ea922120c2242ee39edcb38f594f98f84ff9ac65313a70440c4a452049fb30e1f93e9cbfd1c6e14989aba6f4d4fcf603aa6db7abdf02cfd19fb4ca0912ceb0745a69fd31ed502040f39e9c3c1a468f23c02e135d58d772182630a4a0c8b89928a6697aea8724ea4086d2225ebf5933808cc1d0bcbc4fd01d81085fc2dca07d1b8da976da83dac0badfc68982e60a89547daa5b8026f4c6a1510c01193b228080394bd2aeb9074f8183bad4fb62509dd80284711c1525a72ad6b21981745ad686f30a493d9b9c08b6c6a6684f6bf4ed58af169aeecd78afbfc893bab8c8f166e7bb34ce64cf0c38858bfd674e90aede69e1dba168cc2766fb61a628c4f193308aee9eec1793334643d157a74e9439bdb47f23e7d0fb80e8fc51befbff548463a171416cce6894c4601c4711a5265f3cd8959dea20989156e4cfa3cbba2f282331cf07a44ed042097e6073ba6b39598e0745bf7d55082e31e159b91b2bf94967ca6cf19b76a9a6cb81cce913878a4ca6262b9331ea623960a3000c26658c5a2b25a4e88750bcb3999c8abe88a799cab4e33599f27fe915a662799a49793f82de0d2012f62eb82355d2ce3e9f6922b13f9d5c00e9eb2187ec108ad135e411c0807c97f87c22dd1b1498dc624e0b44ce6a8b55d7e5334cc22a31611661432cedb2e45d9181807801a301c49cb3bcb3fbed1ab30f7c5f23bef8f84ccaee196be253336b9c210e40015f0b864b24a65c2ef8200a9d1edba08b0919d34e2d91a2fd08158199cf099f7fd861c0d0b5135906ab8102b9de2e2ffd04b3092478bc8b8da32e4459bb7fbb8ba47e3f638b876aa60ea156105b8da2f136385a2c6a91980b0ef153e887aa38fb24da81bff1fb67a724c2d613fdac1716ce729158c203887a85aa9b4a40ed041e39c1c1356b76bb54fc15c7f61f6a7fc703855a606b82bc54b287bb3aabc8e8ad6352282140192e50986b106d6b8b1531f48949fe7f59cdafe09bc90278608f77e95ef8424c93e7cb562353c0d9f4c8b8faf09bbb6440b2408ad7403b0168d0c92b85d188c4d79e9106db05147ba5b79b4ef407f175749199d0c1e25e15e6bcff487d037f248939190c483558028494ec13a64b55bf6ceac926bc3836cbf3ed6afda02ae694571b0e58a7fc7d151b04bdc92f0b74c1f4efb0c6be5eeed0604cc986834ce8fb24bb747af86fad50c76edf024849b68a1064f50b57b3f4e08c05d98e1da13d4d01932a8baaf6f6787e35a7435d22c7624e0aa9c425b807fabbccd3737b02970f2b6dc5013ae0784d382f937f83a3dd42b6ed95f624174c1984a424207bbc77d58f571af4d3b0e1a536901c2724e33d4a8ec7c8fdc3aa2fa396690c9227b8538a43efbc2b501cb2c27cdde577c6f2258a9362025b2ea5a076ffb0d7c9682504f61c21851c7b299d652eeeae988e3855e18d1636fe037bb7c9dd1502409333b02de68dbe345c0def4cc56eb08d86c13faaa0d201bf7108409e2ccd517cb540f6c15f900f66b00850b740785820e5cfda0cf7c5e2f8095e4a15925d48799d8f185206fb3bf78b6a2a0efd4bf3aa62587a2f0544a27a282114c5530921289f540049ed5cd1454c280a658ad42258284d1513fc5c494a2db357b62a5e3a53b678d305de0ba51edf8f513bb695d606d2ddc055160e3c7ab64c93c0be508bfe660c80f4b73f7c50bfad2a6ac5d8dfa4c41a52608a0da81c495548c8caec90e2d8516663bca2c2c893006aa703d599a7b103c26de696893523367d1f6dbea57ea42a21ddcbc095c5686ed1cd53e603d2d466adb5d47d8043093712fe5310080f7f4958c44a746ec155185b4adf3bf1710d31d27a4b0b37e1d6bb9c0a23f652a2115af1d0f26aa533ab0ee85e2a5168060bcca461d132d52034264583eb19900e51d9a3339292883436e929460fdf29a8ae1b3b4b7948d60a08ce0b4970a373422ff70e3e23f08bfb5fdab95a159aa59e3b0993a8024c6fc70f7afc5032752414acc68abd1693580900bf2296937cf960abb50a9f4282356440fd5fb4711add63000809c83f633cfd209259c5d5884a3981f1ae891c8b143e3189685dbb3248c6d580799bc9c7179ddf706eefcaeba13380d97aa8dbda2189b4cf44ec242baca537b87c866c13aa35c0c0804ac2c859bdd3c97146805fee91d03cb6857e5c06a9e437da871b273c229fdb5f13327a6120acc0d22d35c48afed917446fe9cdb65240672972d2af4c56ba07d12f0e00bda250b7b7c95da05b257ae2618158f9bc650060b98823e3a9259c196f316ad13a82ad69e1a6d73d67754a381d64cbfb47cbcdf5d88db4596b202ccbfcb932f8d94e1ee013927ebf10fbd2dd4bacf17f3dff3c2add79ded4f52250ea138d5a552a8acd91e5948253fce01476edc9e6768ed1d4eb3c59cf2443c7a701ebf976f6dd67d39745790b2e230152cd1548cec15d72282a23c121fc7f55b1986f1f57adf78a2df4026e6489f304086d6b3e2c490aaaa10625fe15ca7cc59f22bff574c4ef557be6318d2d89cf6db64c5511d2b8630cc4a7e72a4cc2e09125bd840528ac7262d6f051d35fefaa3f327bfcab9a4a614750730d002d4263e6159f0bfed0b1f497e89f7ceeee574bbabc3f66116b2c2d4340c898e346883a2157c4bfa9006f79a3168a12a54340fd2630daf78f2a1abfe53702c0dd4e373c9a7c0c1e33d89347f076252dfd2c31ec894e88f7bc0b3e19f5a680e9d3f6f4550c1ecd4cbc9a5dae4686656fbd49cacebad988db15c358cc5abe0d1caa2b04232ddf15ef9c89bda984c8d4f2ca35f1ddf3c4102fc788054a716b3d17e2978a7f7e1857ace7ae87978bf4d72fd4a95cb2251c8cd89c1065c477db1a0811ccd1e2bb2045a2627c569858dbb1ddc01f68665c8a9abd9c0e9b4b2779bff7ff29896e3c092cf3715915a61c6599272ea92efaf771ff180b72832332b052ecaca4473a19f29304749c03c27f5584c39a9bf5a7f128817e6c7920572ddaa442de7bed9efba629e6b4d1856cbfb0a1ea5c745864e6b323a23dbcb944e797594ccb689c668d2c507f7257a00b059e53b3c7da7f26db93f061713edbf161ffead3d83540ab91a2efeb1ee568f665bdf7509963c72f9ebb665168f4b388b1cbb6ce02d24b8d9010d7c6fdc47744cfe4d1be56173ca74669d23fde1814d8b8ba74eafd796ead40abd102969747c9a2a1b53b947caf18e08156ef939607a5524dca88cd460dbed9df80243b07fc6c92f776ff156d9465647560acccc5444400a094e24e4809b861dfe11199e9ccfb28fdf876581a24ddedd800c0ce0722a188289977b7a0535ae19d96e0c27a47107478c49913237e8275cd3900b0b0f465198609e59a3c81d0a8d75bbffaf6edc5bb8106a225593f76f315f5a5b9df38845f25398f548d8bc9a99714f2b08d7bc253064b2663f36b7bd76b1cd9dce45ed807cd3467e94c4578f2b141e29bc1cfc720f6ccc3805b42525cae28062882a125fe6811fba84724f30cd1f9bb68841b269f85f646d4ff9bb8909392cf6ff749f11d6ea0f07ffa892d6cbae5ad66c81923d51bb790e9ef80f240683941a14bc73871a17373b3a1e65b8b39cba40a6ac44bdce78c749cd00b2dd1164fa542890472c6206079a124f4910a0f9f4db3de5aa310ba1b176b4e5a73de9e48b9ab7ef82d26089469b6012e39485eca2cf996027db1b092286c9ec296b11d9cb53fd38425dd407ed763f458f9b6437efd36db69c1d981075d9ebed0f1275c5d102c16192ffe27263fa812cede38eb9e72bcecdabfc6ceb29cd0205c7b8748900f2cc85b2342f3f8857e69740921e891afba20fe617c06aa06cd60cdc52ddea56f95cbeb8a727ecbf664cce5a564421cbfa13fc32263898c7381921109d6a893a5d7d34f9532f753d4b68db8a32e57a25f2c06e5e294ec5afde93145e119e51b8212822ed566967f140545a0508f268326b51a145302761d844df8b083034af19849cf5b6c69b9c7d767a10bac2135896ae5dd028d9241972db46f95ba3dacccb333687dee422a7621fef9fc6c933921ac08e8acebecc47c554755ee6e75722033524061c296538ed7fe4d21cb661a63ed4d0dff259b6c92fc112f082538010bd85626bc518b00f0e4c893cd66f46fdbd97860b20a9f43d9bdd9c8a3638e6d72120f8d7543c884168d8eaf9de3e047c075ad9e783032c2400fa63c88b5513b8359dfcbc7e32798f082974964fa02525019c2c8f66ea1f8a382947d5fa8b18dd906f39fe7cafc84b737999f6c507d73d79c0559a126acd0d04cfc61307845054488c957f4346342b04d85ff1f431f9bd4c1dd120078ac87d07d0c26a63b68da0f02a745e597c8baea971a7314c4d77c1152d315511f9dc785d5d116de57a467bd9be1256f54b4569582a91ce40e421a0408a4e89b892b305d87b811744b02dee0dee18a5206fe2788a0157d7cd786a368c1ab768767c50c260f0b358fffadeeb6c32775ede54c76fa3b201516ff81c29d32b6735f1efd7af90197e8bd6d6340f2643621fc0e8aad78ae5fc11c46f2197cc13f59a7c3a44d9f9ee28e5af3f0660b8ea7511caecc54e452cbb549b77136545e4720ebcdc00b2a6b88f628a70ee3825ae6d4d3bdb63669ff58b3630e4b8d3ad73fc1229014df258accd480ddadcefaff8fa4ba854bbf56c6b5f704c0132f52ceeb44d43a2405089ac361c0c8afd66afeb037c6ad704c0e64c33fbcaa914e4b5ff1be8b22d95c399d09ef74b6bc385fb8c850d50c1c5151a7311a7863be6449ccdda022e55b8c0074e363f07e84344d938cd75f23c281afe8fb4c21855fae5b7764e98f20309a1bf34ec0181259859d522211cc40c9b8ff852f36428d730917ace803abe520946480d2ff0d10f4d05a302b1d9ddb83d0097a1199e09ea46fb85b964d6a6899cfa541c12caf240c1ec950b5c3c6562fa98fb8898377f8241433f8ff9d4c803bf14b08adb1843fbbf7c93024695ede503e565bef155171ec7f50ea848540b925367a1173f28e2a6a9b6aae700a4ace122a52b6377f145b2f0064cc6e4a629cdc2008302ce8cc7ea3e280838fcad738ec2c4ed848088cf6efb8f39c5d95f2898c54e4c5d95eb72c9a260ad6b1c71d30ecc786f2b6f4244536b984b6c2439f9b7cf36a149d301159b02c2880652c1324ccc0abb9203deb333094a638bf52739b8e3ff44b4c2c1b055f2ea63a6c014f194e12188965b1696cb0995a1d3390d5cdb17ce02d7f78045316fdaa6fba640a47071be7df73fe9b61564af00f995768e746fcf6949239b801a93db2dad8e803dc426876fd737e70c7dfe6cbb22e91e419f3d2823d0e04ce5bb52845e0bc4a2fe16e641e3aec703961a72a6c14f358e02e160211cfdaf37b1d337b9b95630e0b0d6c4f22307882f136a0812da72667753f67ca6483cf4fdb06d6a84c48c0d36b3a58947ece14f33f295ab8458b1a06fa318735379ccc080b86fdca99b1df15e12faa35ca99996f51f3ec87d3d34a66ca4d9775963ed56797579c6daf967aadf008bbce6fc155c952ed3dd06f46cfc5f91eb8c2e9cfcda04eeb200e3210b0008767ef53b53201030f00924112356cceb1195420d4e5c4c7e774dff3d9107f3535cf90b9dc919c21275423b6394ab0c7b952ece9139672ccd2e6d2c2b814fc7c433a95307136aa43269f0faf371069e37ac7c22537bac26fa6a4ab806fbdbe10b3c8d3f8d091d78ad557d0c10169bdaedddbab176f28f59efe49ed821fc7d2083315b9fdd2554fc192e0f8bd8cfff214257f8c17fa0fb5a9c14eba86411affe2dd7178ef154d75d749ac400f7037cafeefa3dd3e21428f6768d9faa193922cc2121d13d4c295b241ca63d07439e98aad329da63a2ee83bab032bc2a9f3932f4635a691b5ce36336c1033ff858981035e4a26cefca80fb550df87a53ca207843739f268b9ca8e6c239d0ac2236a590f03b3e906f1bb125274b36cb50201670cf18bf4d270c91aacd1e51fd29afab450f40656ada6ccf24d454d351af597504dd8285a0e02e67aa3377d68a91ab641d299805fca9d094e8ecf7d8b402ac6fbef797cd9887c1ac9a456ec58b4c67b8cf73eeab67b5511718e1eb88b31103272c28494859ca84a501f02fbcd2d3134ca675becae0074d95ed8c58be2201ffab9d3b9379b1531d3144ec3e68c5839d68903986e5617b347c24ee8eca6e8948cf6680d2d140decf240cbf5571a0ded58f0f31841d838689e866619f3b21c2f0079a3da0369e8f25827e4194a9180baa15f2f607d8bc8015b9643279d9dfbd9064801b504349984ff1b229f6edfb5149162aff74e8943c1b97787902a9c73b5ef4ce202ea02d5b11d0eea5ca0b8fc5212d93849bc3923ac033199a828918caa42373596269099b78358ee9d03c681ae90b72627bd69c3a58092077b201e6f24438967ce14fbc5ac984cada0506e42f6dfb30ad0466418ed4777268f05739584fc98f0da330b97b5d8093b4db8c173119566dd511a6906e54b3c050515baa2d7984a740f81315ae962a3a900a759e75d83d52cd0dce5ee14ce4b3f6d5b1573c9e1c3dd88eb57ca789266551516e1867379f0fbb84a26fbd9859f7e583c9043a4b28d031bfa30fc601f32f2ac005f9eeb21d83f8093aa38bba6cde40a3b38c6322050c57ab5f4a448c3448aed9f5f45058eaf88ac0f7d8c9bbdf0ecadbe0030356d97343ce3cf60f51d05106ab010bcb90b1c498305c5e1ecc06689efda9035817d9af3a6350170117ed21b33120f4323ac9c5eb0780d1e4a0640d2004c831ce7cac1b1df0e08ecea7e1eb14d9404cb8ea7786aa678de638eec08ad82ea63edae144d10b3037ce711f72c25acf2a65555e5842867eb63e9a72426b58168d4c86eef7ccd070f7e32becb8ff584fa6755b7fc6868d045ead3960b8c71b6e92aa91a1a64ce4adcfaea026ca1dc3e2ddb48423981ef2a887edfffb4a654ad06e4b228405fd17939880fc491377a78598852b5af54124c8794ef021ac41c6cde43ae0a9708c3e1d436cfeafdcd978977be098938158ab13553a7b1dc968921d9db95af20f252f2092708944b16ef8dd06b6708216959d6eceed16c6af7a9b20f22bf5eb16682e648cd8186b74294734dd801f49ad7571eb19d242926864280b3a80c207546c600bf3727bd5715373c7934e7c20905680bd79613deabe1b9d3852887fb443fac81edc86af814e5b175de702ae942e3e79d02908adf4f784a6cc93ca323c6f062b73f3b21ce398239d9ab802555129cd7dcff6b575aad1d93f0fe6d8389a4237574e77ed1202a5f41c6bddea76c3b89748f474b737b0d81e21999f329db930dde0b778f90e836fee805db606a992a3901d38267ebd3b50e4d31b385466c0ad7a2257ce470593c6b11a1a140405bbce54a97de4c2b98675fc048d28c3f40d04adb8c0cb4b4c9592f1cab089e513a76483aea61d2e2a48f884ab4ccda4d7eb511759971ca9a002e4d743f16790c5bae99cd096955cdaca20b694395f0f516cbc179029aa22542f93aa8d34392e138d34d75f24d72565dacff05c4c20576e178acca0f82777f1d14d842e63b2e28de2a3efcefae6b761f1c8a87460b979cea11eaf4fffac0b21e51b02a321b90b390029a3479994394ec1006d37ed37a0d7a4b9b856508120f6f5cc1d71890e88c25aab61feaf3a53b270b2e2243a3980faefdeba0a27c311cc38edf2b37f5315383f9534d0512159d63d8082badabe730a483b382cd685fe0019585b751362b70e58916ab208e400065336d9975ec3ca854a6bb0bce2b084a538086bbc91fb6ad660ce6708e804ff6fa6ba35abc2abf1817cae2dfbf812d6fe220b32036e3700bd1e08677d0efdc7b3a8c85c857bd1ec2ac3ab6188f4a0b5e3b89aa325bc2a1c01a122e37c204166705833421677adc2879ab00d2190fb67a5349a3435c158465ae7c0c11575b295c1efe4e034e462907fd9c51f57999b590cdc09a4409cd0b8e639739eb41fac1b0cac578120c121a29a2af2cb2d532c229d8b38656774efc4793fedf23f22031ca5d1c27cac08e87e89f25f588c6e7a344c9b54a4b90d273c24b1c869f00b78ab730b61ed7490789003f3e688f39bccf91d6aba788a7c80f5c20941736879d834ba2ab1ebf0e2f0a78f6da759064a788707c3898a8f898d0cbfe18b2ea5460a744d0aff139b8cad30e1ee1fe8ae0313b91f0b501034274a80b18fc24aad0a1621ce2e0c921ba61801eb28fb990e25d2e06f4895e0a775c7a7b587f3a3e60706e3c00d037ececd102eae1530c541d8eef9242184ea40362a1f201b8ea5c986dd840f79d8487df696cfbf13aa3e00593ff1bf2ba2076f3aae353ccb83de9901b56cfaa6e051f48c3bdf2804b700421384e19e5172c0ed3e9e08d56bfcb190633502c436625446e15228db066d5aa8a82fb88dfa3c80e691e71882e461ffc6344cbad0bf586b6c78fb8c4095e7066599110add863cffbb310b8a5109dd9879bdc115892e5b698f58521c55feacb8dbbf4203304d49036e465f8a1fd868ed7d970f0c04037ff94d5b3ed478fbf2e0ab9fea9ebc24f2603f908b3fc7effb31bb5070dd21e28c510904eb62110209ffb997bd4309e15f743a20f151416ab4afbf1fe4e04844206cb2927c38ad6020856248ca829c2db3286adeeaa009867005c3c30766e8f3e5eb9d6649904adba27c0e91b29fe490525ee8d28ad98e087e28e3ca1e20e80f210b068b3560db5604f77208bdd1228f01be56404a1784e844e9822e87dee3a77d33506531fe2eddaa1dbeff02cd424bb8e8fc491dbbba409aaabed3dc57fc72e5db94424d6699b6ea2324b0c498909b5808e2d852a226cfcc82077556cb0ff03bf47c2b20e6792c1327470fe054cfec554a79e64977489c38888470908ed9f9788b54b0e94494373a8d39c554ba7b36709f164e8dfe472d4fff061f02eedc6028ada59cd49c7044ec9c60753f2928d2b019f2a7b65bbfd32ade7a054e2b8372c835fd28eb26410435fd5541a93a6f0e53ba0eaba83833e2b05282374804b4eb22029bb0977c8291f770b4f09213aecfe64b5251bdfb5062ef505a97436468deec1cacfe2675470fee135dd6b2b2ad8895be70f8e0500158b811dea677ee0166fa58a6f953f559eaba66fbc13d949c74a7a4f35eb7358615dfe1f7717cf002b21ebee10a7a8f090604331a5d1ec818139047428b7037e6823a39bcd2164187f10509049c10c7d4ce76da72f8f45f8a5d63256fac3552a1d7f153e89d1ddbf021bfea234de0ef292cbbf8b520b9f95ccd8eecb3e4bc6a204d0957725afb235d66969187a43ab94f2c76146be1e1c322e5d6a0917da17ebf8a34f1e86c7cd87da8799f306616702e7e4abe4810fa903b7843f00620ab10a05ff4d3d8a69879aa08e7046aee99b219e3e922f10521b7ddb2aa972618844a5f978a2f33fede03c4069ea7df84692390acaba028a6f28c165b5aa6ed7f6ce2bdbebc68c2bb6c4428dd10dff7b6f56b21fea590e370eb7cd10286f08468962cf165ae9fe523312da40895a184ff2b3c1f604014a50b9ef2d3705a12fc1727e26090529dac7e6fcd2774618c7e22b6f481da0e1f9378926f148f84c48b5858d11aaa2a869eba0a4a116440d5a09690df80eb2a12666f33b5180a8f9d7a0092b6260eb06628690572864707037e89145748952c2f3c58d9a2cf7c8b68c392482c6b299ae264bce25e763e18ee4a346e0d71477383edd7aa0b3d5f855944e3392537c438926abdf8c94fa8366f8c71b7ded86314aa19ecdcc97670c96690d95c28c17184745b0169b45447f94826bf9c6d585fcea216eb9feda5e09a6bd1e9ae4147d4becde4ff962bb5e421ebdfec777b3ad5dc2abe11a0d0108888a8b6a432ff52be326a41aa133cde185914edda27dd8f58ff56390d6324fffa79612862604bfc5b439709add1dfda34d30869e16a95dda9a94ff20bbd63bdabed4d2d20b4c0f58038282d479b3f0b08961f56900146b25791ef477f208fad1ee2559f10cd71dd0811fd0b355085a9215f421e14d334860d2804626b98b8bc96d360302660ac5b233f9d032846af9a9ed64cc77d87639368459f3051e7996c8206eaa776c410fdaf57e56d00fca0d6c464efc6b765a15187289ca3ee5967b7050646c84f32151a630ffe2a3d812b2aeee85705ef71c2da89bbca06efe8531b946e5f2c8f3bca0a810cca9d270c082487bf9b4d116e879ee4ce0e9befb74c1aea80f64b2d5311b030017e771c83ccb7725cfb2c9e94f7bcf7eed058d03051a0479b9336d8fe05d068724edfe57356e430c29a60a79ba3d329a285ff9d8ff9f17394d821e61ef43f212cab3e7715cbd28efa9c29a368501a2c6689320f83218e6a41d85fa2074642506647f8a5f432ff987502070a87b08620b7a83089da6586da35a6367d3c85dc066b9d96eedfb43bb112888e69c7299a44a5e0530b8dfe0b7e03ce6e8bf002c01ad1e9f53069d407d029b7bfceb57ffc0170ed3cc6439caa434134623d3ac680d02647d1036cbea87958081981f52c77bfeda3d38cbdc06d4a9e3f8ae8cafbbe5eef352e149c052f3fbf16c440ad83afed035936c006724405019e6664052f7322899f9ce488a2dfebe98be0e29cafd61adb3f1fe5116a35ff5892aabaefa7eeaf89dd372897a7acfb687b98a00cdea582a3141936b08feaf9459839408b35ee68d55521fd1331669ea2bf3d08d6429ddc9e6bcc2657fabf63f050f6d481f3a4423fd2e83121809bef86e5c3f1ae51afedc59dbeaa22c4fb50645b506af983fc7de221c94f7206ecc1b507b12500dc1a40c67a54672557419213c0ec4e254b6e6c27207319480cf15a7fd3d993140698dbb0c6186240423c80522442a024b0e91bde7a4eaaa098142eaa336b05358f94f86bb60e9966125810c99cf7f6a26fb437701ac192aec38f443c6962a2d32ae953f3c824d08da3c8e5ac861ea192a4197a7327e16226316e324618d1151468e37267d52567e34766d92a0d7c26d4005ea50f0686ee8e53ca84bfcd2e10993aa4e45f65d28a3f148a1e0c2c9d3fdb578adbd8fca17e7742f34f8b083f505577fa48699fa2a88dd3e6a4813284036570fa49fbc9917dc483eb4b5a97bd10fb1ad158444319571fdff4b0a59dc26d1d60459622512dfa78ce768f6b8f956bb241dfcad4dc202a2ad797e1d180ccf284ce28f2979147b4ca5354af7694ad4ff8f08d4c40671a083a579266ff06814a78f3b61da5c8b3e83453a3f8372c80a5396a91f66d24393d2ef947836a35c27a4c13fe164e69c082faed916c98cad577c7cf021672788ddef565b4420064c4bafa1fefec016d31d0ad056c3adfe54fcc40080fe0999489c12f310a5146176be5c49ad35e7d77144f22632b415e801d14b653d753cc27718fa43f99e30350901fe096958b70a8816d0e6dafddf5647a6c15de61c1491c18a1601a554d648c67ec8bd0feb62e4e1a8858a3a26414b4911aa97da4e6b791c0bd1aa4165b0ce708a2615519b46223b3bc1683c33bd649e1270a6e85c81b5a13d8a9cf764204970803a8c2579be73741b4f745af4e096bbdc050f3c584d3fb31f244964d8995c7882336b28c86966a22f3a9b01dad54b89a766088452841d3ed68e533250dc5066925c971253ddf324fda761024b01bd6f82575943e97b373254f85b9de751ac32eefdb12478a2fbce73b0d9314f96d1361284408e10a92e102ef57c7945b62071bcd35595b05cd9dd0b5ebdd521e193c6cef318e5dc056a8fceeae5d3581fb4053ee3ed22d67edd7f9ab8c9c468c118033098ca8f16c4e6aae89d1bc02dae77fcd029588bf57238628c94b6a8f1100fb0c7be22185b130b0749ad51b32866c3ae496dad6cd7b32f644320138cb2a41ec9b5d6365974de78c453a176832fd4b32024264626290d768efa471d36d21ab28aeda31d1e48107f91bd114cce91b8acc0210b8c0ec4ebc28342ba43edff87bc745bbe31ca5323316ac53124ce842bd10c2aa1f7f47844e5a968963b29b16090c52f9f3ff7c50e049899b6d6844d0a9e354f4438d6425bff2c52bed60342c6c5d52b5f897e211edc5d0bf8ddb900629c889e787613214e03547e9b9e7b9cbb1e5eb2935d143bfbe19cc8800e673b2fce32f192e0c038394301dd5fe9643932ef5587df13f6469d9d27cb0f56631ca469a6bfae04a18df8a55fd452495399d5eaac964ba5792dd525857564f441f673600efa514c2ad91119c387af0408abe26736f32fdcec577196608eb5ad4c2e352e1834a13a6085a783afc0d6c9d03de9f218d66d3669ca2afebde3f0c99750c3518db6b88090c2c8e4dbdea43ab6bf07d40d930f8a809e1f5fedde9a9c96074a478d3f0609931e36013609f05f10a843c42037c12b3f09ce2d0b88e81066cf27b17efb1b401cfbde8ba14294b5b647ad1362e955ac10eb093909946b7ee1b71cd3d74d01c326b5c8f7699263b54f3f5a02a3d414f95a80d316a9ca0b9f70012502136a096c4e79e1d29ff25eff439fa767fd327b6de5f0e16996e2cc80044910acca3289f11874ba05d2f403fae7106782b15b9f2387168245351ff55c4ac59f7982f1e129f1324c60dfe73ba9fcf6187be8c4f8657d1efbae2bf19471741488eec79bca7feef38a71b432d6e0a3fe4ae831332be151ed6bafe4873a09c7d03eed96f23377e03e7cbc479fd826bf0f2cd8a7fef39d68fe03cafdf62a964008d6723aef3075fcd226a3edaf0ee14040ba8e9d803680a402b220c611feeba1a1d28bcb262b6def020fbd35f40596368fc0bccf6f4afacf0ff7da13432c29d87c44a4be98e1e3f4f1ade4bd1ae84326706e4167f55cf2237d6a205e262f76f3d106397694e615ea0a450e43430b8f4ac352684250afff69ebb0724e888f45718992a8b1523686ce09ce0c4628bb00ba5a5438b779997650a43ba60935d902e29c9fe1e46135e89ce1338f6788440837d5ea4808af09c3ed0a80811558cf2ec6655d9e052233fccec572551a5e3b3d208a9307944250fc02804154ea37dc940ee72d040f22fddb6df8cd424f236b03965f24b30a0466b208e61f0b355442de1170629c36b1e169deb58aa0c59f075c88773570156a818c5a5f3906e7aefbeb410414181710424e47330f50113d579e221b0261118404e82d249749fc957e59b312cf22540d412a8255c916e7444f158e127db3142b1f180616a999f8634c4f00d04064b0ba0e423052372b1f765247f1dd6a19f22e3c9c1a29732b47b8993dbc2bc720a2bb0e9085d6af45af7bd77112028f77b30e6b788baf79f58907e0d99094727a3c71eb040c2a20e3e9978735018a13b54de8be1b36814c0e910d0bd02251a85ff5b30b461c8b613c89e93a006109e29b8fe105d3144a82ba15f16a0a6962e8e7ba5240f8f51b03186d5eca61163d5f1bd43d4b57910ca849060f4f3eb1a246642f5e427ccc8ebe7f8c9293668cf45dd8c95c8c8a0bc64c96a16b100322b04081bf5b6c2858d05212f1134f1102c6c4288c540e5109c636a0f4ba3cafc6e1d09cecca6fe308a2a8fd32b7fe5a20848e128638097b8a68905196840b3235680bd070784f766ad6874aa7ec7509dcec0c043540dba6570cfa41df09af517135bb99290bce4db54026f6839e1028e66637be289d97b0f57ea86042187224478c7081177e1b6347877da869ab85d163aab8aaaa8eaeef54f8fb1ccd6427b039fb6227a1209139acb2a55a0eec38991ac5dd5a64a628470caf60d17c8152655a5938df1811d8bbed073eeee2e3b885be7679e7f835dba65e902a8370f12cd7a320f4586bbc46e92532fdced81bbbf1f82d3579f24d3a2fe4e04816798c47ff0923f541e44989f20b1cf4cb1bdfb9345e4d88b86f869e16ec9a35808ca095404bf332415969e429418fa37480f7ad2a2f656f0e2207e983236562275bd5e5384dedda348e4e3e1d9aa39d41a6a6fef83ad235eca68531068643bffc8e4ea5c675bb634f3a55c4e3488c022908c39db739032a9e467e1561b33689b5650c3acf3d4071ad5a1590d1f99c19272ce60534be039b0d56d5c7c8fa42ee9e58a5ba411aa769022ba9a090d876673962faba660a9a247dd9a423149c2b51c15c05457b05b360b1dc5fa1e56a937493884e686f1413ab06e6e0840adafd690f7f0da7a6f0efa9a258a41e4223fed00387d2a4f545148c2b4f89700037921c0079b5ba04b30f7f033b172417f582a69358f947452a9fa396f15a66c68ef9df467340473227558284de695f1ed38d4d1971a9fbb7b665ec9efce1d017784ed2f289f9a3edd421c014708b05e5d3ba4e67ce15b71211411bc350352a82246eb14761887586b9ce40c6a51ef73f33263b8fdb37a8a9b12197f980b4ea3e7e6710d4dbc7b54103ae2e2cd5dfc2b495b4bee1b5768611a8e76de4a909a507983af61473229dcbabc5f152e84305210abe68d9bd9e0794ac52b8572ccf5cb112bd9ffdfab204aa8848d7ff168f550214f0ab351b568c3e4e5b645658771d1c1913204a62c5600d1487d7c4ccca0d4b06e13295c7281fe4262a71c68df2d4ca0cb3f844f911437c09a25944d55ad79e152c7ba7614c87818787e51bcb812577c125b78c2228f203fbcf394cfe0b262c4f3ce59ea60cb915e0bf6c1c180a51162bbd3ae31637b6c5bb13dc4784a4127cfeaee095df4cd4a75aa5a8f00277971fe989252ab7a8427a7e560eff408ecae6089b435caa1c1ea00311475c7056bd214a26340a79337da7df3b9065b8091e42fd814ff7ea30c0fa69f679ef75e835e160ab70a29f527bbf8d79db3ce9d94d48bd29933c389c410e5c9a411e3ccc38e499f88998428eb11bc4719bdd0650c86f2f009caa9d0cc9b0290702a77994027dd4e3ac01b3a247a3e4546d29e752a02a97ac9e73b2e3e1cdc037fb692121d47dc256b9e0e28aebb8aadb0c1eb72f4c8d2066cd5c63735522abd9102a3ce376624c02a38751b4c869cf595750b38e82ae518d9b2a21e3426031e119e2c501f6c59e41ea698919700a8b4c928d5d85eb8077d490ae4579c9949a2c53316c6a1d6aa6bd437f6308c6764bcb692f6989ff60a034f3fa0c9ad7b544f2e637163ec44fb29e9e595395f205976c88fc819f466cb82c1eb8625823724f07e375bbaa1e51bfe209712bc169bd68c7bc6acc136c8afbcda85e26be0feb387391cc7d3eeb70c1ae03342f2ffbad0f507079824169518835444de6cd96ac102b6b0ea14ea17a5e5db55ede8f1a71369fd2e41e7d600456f7361facaeab02f634793c5dd2e8509775756663e00ad275c3c0e0162a4541a41d66414446072a71980fff25e258a4610a1aaba9f251fa363a4179dfe1d6251336ce7a22b547ef02a3819993804ec249c26edb666dc18fa18032e66e0b85de61cb3cc6f32d5bf14d467586ff0257db038d664c05f2f60cb3814d543402a1fb0aa0ccc71a6907f0e0c7fce960b1259e8bcf4a766386276a8ea6d1d5ab94a46447f462f7ba70c9e5c4205ca3934847ab17db82850520858ff8edcf45d023f2d24f4b8840ead00aeddc6537177dc936fd97f092378b9c074728cf89cea0f73cd9dc060ef1f165b3247d542df94ac873682981442d2781ec63d6a584408e1951f571e2235ffa401b42055c8256025208a025d3f04ae01fbd96028dc78a4ca5006539ce53906dd570ad8f4e9882d46187311e600d4be3de4668924241bc77fecda5f57f8ba0eabf0cedee2728f3c8e13e81320c30f0276d84971be934dd622536018269b5705c30dd4f679ae5bacfd2f2c0c70c18a3f024797cc5488f3b14d07aa41ba16e538d9390b3cb3b2102c43cfa28b718123a834709b923dfee880e9029c99f3021a3dc448aa76daeeb59b244f15eab47e7818a90391d595e0251bfed2e4bf97d8e802e3e912a9f02c384b2d630e32c349495068e2c5bc6bc747976ceca605cf369b71dbf26f59eae2313cc04b8976eda0d26348ebf412857c2c8de8e4bbf7608673faed7d792af5fc18bc87fb2634304f80c85ef4e50a86a79325a28a2fd01a2ce751d04356aa195777dd51b8ec773c9da19199d738954a54842695b69f86842e7c69d23e1e7963c302cffb9d84651353cb93666bc8471e53cf3573a7ec3af10a4cdbf60c8d272c29a7f84a49e6b2c2d3a6de919f06915275152f2bb39dab34cd970f4763476f00d150ab07c7aa799d072060ff3c1e6b47d995e2a64f247395ffa7ad515663fbb085915f8abaa4c91201a48e26988223152e00c9be018bbfa5059a1376d864daac66313ca5a3752c888c985bad7ebd026cf45eee8e0ce966287a42233893da59f228255d20239bfe87821633053d69fb7022c27d02fcb93981bc7885f64736ebc7a1098afc3e3f362d04752f3172fba474762fd4c06b5513b9595712c0a826a44e027d2ffaf99a0ccc4eff355104d72988392a2837f7966aa2d8d2f9ba2e2b8abe1cc54a8c6b19f396a988e735d8ca2d0b5b0460a9d6fbf2ccd2fb60fb431a3a52d027e66475f44812f27fcd39e288e41f0fd1e54e3de73ee1476592fa4c1935de7ccff038d4582660ccf5bebc5e3ce871f47868d50c42e53a8e153c1ea0191c44972043aae8bc7bec0e65ce5f1aec8d112ec61720d8ea48035bf7d256874a8ed20158415cb2dc7f6b26e2cee4fb95ba2876c8c2fed5d1f79106bbdd49602818381eaa35f5731d55be152b27479ce4d99c5597a92f0dac34b05d4701357085da4ab4496f97e62f61caa341e7dadb8966189263d6c22e45eac3d17b8e24a86183938e2a53eec4450a63aaf4afa7715e7de247a020d6e84c0e4820d9a4415732c88e555cb98fa019357280647a5859dcf4edc4280c00b805ba472451e6d8c1c74aa94571d0517e51e40808fed35fcdcf40419b8d54a411aa179b69187f565d4dd7f5451a1adb472b0c9282973eaad9af80bf9ab69727861e221a8487b78e90c7132ef893e0b66b28684b894b573427ae734b322a5874da8bb7591caf2f71e4df107f63739591daf845447eadf487eb38a5fa99276f4d72720f2e9a667623a6d368746a53b3f214bc06061399b449e7e4777167d3c0eed1d9e9224a4f27c98c4132e211ece204016fb579fcb378f3d1f9874bc79d5f2c17e4b3fc1be39ef1c7f4a8a7cd5f601bf80205f5c3bac027846db96a461d7e403c1926e6ce5ddd774801aa33ce107c0f35ed91b5698c691b7cdcbcf4896c30897af6283d47e42386471ef28d2c74293688f39108b8fba9021b3eadcb91c086c0cc633cc7beba76bbf18208b9adefb3e4a8a401fdce2ed7f987c4af432d64f9f135c805059fe67973fc0fa1f99e4b304f032eac3d43fc3e5a3a87f18d6dbb38d97269e8ad73cf0c0fadfc5fe1fb6463a16cc4c3c3092fa09ce27ce81fbe1f6871431508638f4cad101f080211d69aaa2125424d7b1aafae9b77d448404471b0a0877963f84ab0067d8d947841920dce93672d8ccb0a0234247eddf1e45079a643b3a76f50f4c0392cad1b0faf566e6c24b9b02137f01ae803d02a590b787ffca26547043d1abd658764193903cc260046128c915c22d86c4a728a8d290662c386eb2d73f31832bd5ed99cbef804bdb960f4bdd1c2381d6f97671763d3dc05d1b76c11ea70ea15a5f1752371e4a359d4bc76368eecdd9c35de2ff3b77670288a26f64f36b4d92618d422c8cb3408c37f41a8a6a84b83dc394e55d1b6d8804ef93c3d9ca5cd43c8aa4b086dd9464607d72b4915000b60b665a90808ac085331993471be17be7302d9b8a68a14f6262658bd6d20c5ec07bd342c806e3fb8a20e166bda49585b532613b9d21b7cd349b32510f6b140ecd3718eed28645c82c80273cc54ee580615f1ecdcd0dd43ba0db1765718c50ea1933f942ef7d73c80ec4347dacfe8217c456e087f5dfa304a8ac039b8f05fbd373be5d0dc0ee604c9961ccb570686108485822e1ba4f2de5b77017c011304a1c5fe4334b9044f94f0a47fc14dd30bf77c8f2e037a3692fb53be6152a178350301af4c493c14828aacc2af535192530e3246eee52cbcafef6c26ec3f6d04c2de577ba1a6547a0afc2e941f8ad1890c4dc406cd7747f3f3450757c194a517f72cf2dc4f361c0528dc476d64a6e73b52c6c6ae763e48da724f7829efac12d57ae361c26b1acb0203e414a342bc42c44a5939483824980ffee97098d416661bc9a6a5625e69231bfe0dc710b0cd7f734b0d64172ad23366db07385289ababd33f806700294a39e2b00cb071e8cfa3fdeb9ef8e23b1bdeed00e39c55b560be712e935d56bfeb403f26e068af9b5e44f7bfbfec8fa6b4a6368846e59f4f984198aa14b5abc22ea321e195aa83c18afe9d2be695b049a5d0e2bc46994b2b8c29712fdf82a88a0102f606058b39e3b413970bcea94afffa6e94226b3c777c54f538be5a177c59eb92ad69bc9b247b015b24a76b3b97edcf5015796e76ea214a9305b6c43d5919321bb694e4f3fd2233cb5acce2aff700d935055ccada507680d81d6038137be4eca5e648601c746cc335c6383fad1caa1e17ec334c452a27dda29542196c1fe2a3c01d196121104929b8811a54926e3ef1761d4d732b8af5f587f825d78f22e14f6d084a62252cc6cb7e2855dbd6040905e17839f1584c1e7743e5355186fcd75758b4267d1587fd8b4a4606d736d7f85ab0479b2c939166a4ea76933c409b266803c43cbfaa01e946986606a3d40eefa144329d8605a7c4f4668a985e8483697fd44d0e012beb42a245eb302677b90fcf0f594efe94e015248aa06d66c3f1d40d9c520e482d9e637bc677980536acf9136096e047572d46a4ad851d3711e3ca20d2d7e0334f56fe8bf286d7b34b4b39c2692f1f19f16dc0685d3d1e19fc9b1cef3a2793bebbb5dc23b78f5769c9118f524d4bd43bbed3d32429464bc642ec1f3c3808fb03be5167f1701ecd4a8bc38bf9637a34ffbc9029ad49d344198c78130b074c51d13e1dcca481d0d0ec650d1eeba934c4ac2846bd5b460c673d8791f598cfabeed29191ab0ba247f7934c039dd91e33a7b1241b7248a72798070c541104083c47a761383d25938aabff15d903ae623a788d1c4cc7001b8e188ce55382aa9834ad05fbdc93b54881960127260f8d9b7ff9094e3a1b2c6d9fd9f47920657dc3f0f1cc06aaffc8c905d65ae363123984655ded204c5461400ef1480972d72df5006d4330954cde33cc4d31d9b78e815eac7106d461338dbdf4da29b341ecf30153538a9a47e9a838d05f6079dc28ad452fff763df1d7664046f9af1cc71f1a04ae4db76e604d261b2b822f2a48fc5c3dd354a3201b1fa718caae67d3e7ee9df45869b4098f12997d01709b8e963adf1bd634e2f1d73f48bbe8e6fcd19759d62189bf8a2e0d9a5ed0867bef30a2baf63a121dc5b464ac8e60240230126a57e7f8e4b08f0f3ad7cc2a1e3e335b4b45edcc3f7bd2ac7c9d34940f03fbb66ddeb87812fa6e172433b91d982f36fbab67835898efee4618bd9fc8faaa4e12dc0b605340453703f9497c34cd50d52e1a4c350b4ed8da2244f8788e31f8fac8cdcda6a90024d5e4e51c3f7f20c50c5b3730d0e40deceec3727c929e2547f8360168fa99b74ccd0b31507f81ac98aef437627238c3589c613bc0414ffefd4301029316b7fe649390751bfaeda7eaa5b9cbbe063e0bd0f9790bcf6d5d5b73485a75392f39fa588d835cb7c4e1a32c414086ba80ea222e2dd4cf2d00568dc1a54faec4a5b83c99c3d3e1b1805e1a3c2d0c46a76aa290f58c0184573a2b492a4b71377cb1b03ebbd928e1382047056ccc630c388704568dfe03455974936af4e90f41bb49348c0fc6f7d646c88decb869b9ac56e70793981c3a6b10a9b185cf2cb4efc12db09b880d4fdd2aa1450fea5505b08a6061b247952589433fc3c944534331ccfd460b1a38967ede63f72bfe159ce85728d958309da42cea3faa6795ee218d5c91c81126d32ab30b788548557a21eec45e7ae76a619481fd3e58bb444d2b59b5983734b64d578d9c2f24343bdb31f0d6555eaaeccccf0caef7130bf980e610661ff398a11417b8488e3190377fb5a98954356822e1c06eba0a88976fbd9df8b75d7eea17e89586679103056c223a572111b872471d75355c34a46f9ede3675d7649af6c8b8241580881286f218a428d9a78332c86487030541837a76aea1c6520b7e224254c0a9b0dc27860503d4069878c96b7ee1e308ce1340b17e2ca14f12d26269df47223d395ce95ec1554fdae37e58b59f0ac1745551f299243993308683b1cb0e85ffe42692225f33df648ea55a24b6ce80f587ad671d5c0171701ae97eb7312c68c3d92fca84d58c86556ae7277cb252b8693dbddf30a5aa0769424f28e0c5eb4b4ee6684d80f3247155aba5d3ccd667d7c78d65a92a429a6008a585c83d68ddc3f839b0efee64fb4659499e581dbf007d9b0e95c958b4f80ff7e447963f203b9cdab70677015999d12d9ceecb2430b686a4c59066a95779591595ca7ee86430bcf8bf7c78a4578c6b77884e03b174f04c0af9eb691ccd4988f8f3ad41228d8ad161c68b643512c72420cc988198e62587282a937969c34e80a11070d4d8dc90931524b01f006124d0b3434352627c446b01641b5361f0e5c55d26c104998b8eb608342935b36b0215c208c61624dcb7bb8f88ccbadf331a4cb1649ce927ce70e43a409b5ce36bd0b1384fb777a51b5b714e846e06a1841d3998721662e04f386802ce8b5b6cd8c033c9131f37cbf0c0148d39c21ae210358d502f768ce10db48ab9f4bfdd2ca9802a99a83f7d047a8e36433434f6e903772b46eb5cd75f3c41ad2cd520ad859ef3981056b0e7933348a4f3bd0a7ea55d24d37a4b5f8a367e23cd302fc6ce3d4f22fc838cadef7e2704320cb7a2741c9f379f3da9f955db6d3de6c2021b58b48e7ae23d6d64cf9125ae3c52063c583462b7cb9617cc9b8477e61fbfc731d68d0ec1b7dddfcad0c6a89f8fc78852e9ed7812bc1e33172bea25a0439e37b96b155d57fdccf86a3dd813fadf1e044682fb83260be0a92c6e020c3bd8ec0195004e202a5bccb4a24d38234fbb2a5ef2ce79374124a4c84210df0c875e44e3c1d88d95c42668e2f36db0f632c0ec4abee50cdf5440f66223ad8744b95283a7dae7b73b20eb158740de1f0e2a4a3050c48cd406e4ed847036b4ad12d28448ee327604a5821aef10837d2337e6b539486af1da8845a94fa93dc1858cd00ab931f1bebb326459d2cdea40c78b35facdce98b7c1001079b03310e5f4fb7874dbfb40c6f077836702061d0e525e3a7e910b88c848ae71e07d243bfda9a02b5daabd7687256c6774135d16705c489fdeb38d57f4fec5ac6aba23c8b8c0f9ec933a577c4f3eda66a8f25465b6f2416900fe75879f01d10dcb8bc12b5676ee714841c6e5499a63959a93da794794c790a405f117a0cead901531f95d404c195a60821c2bef01c98fe4d1a92c7402f13b1ca042760b31edfb194d503ee2b9e23701db3e3f2d21ef391e9fd7d557ac718dbd96a6dd4fcb3ccbed7376bae3e10f6295eec74a5624f256c321f7e440579d42661a55e0fd2973eb570f2e73ed3dbe4987508a1e9873432b130bed0ea907882c15b492a4ebbe7a11aed3136b171213514537d27113fc068318cc37c7e6b1dae531c542b45086283b101abaf9757e8799ad0fd665175352c7b2dd1a891e8ba1fe41eb51b452085ba453fd1d4241d10a689b4e93e7bcd4abee8a188d0ced15d13aa92dd98b369515d74e7cc18f2de6a4221afbc3b850ebb51d2a6e82c7d79492729c3d02736f1936632bb513c71a0b1fa33a855fa8f37442b918a6064313c88d37812c7a017a45525a40b4a8dad04ec691f87094b9bebd94257447152663b6312a6fb6f1c37d4ae612e7e3b9692132d1279a179d938ac71e29b4e4e765fc24d37437b35c684297caa58cb1f7d9903c135c34e8f6f4a683a27fa8963f51cd52ca602177b7ab2d53c856cc4c89345974cf5c31b1aa5a73119c5acf321cf672d4dc535d64d4ed930dd0ef82e0dd3c6730b09f53422440019c121643cd2ff620048bde19b192ebd5fb3b1319c10528a2db97abc2990332405712c113e2e054462f2d30257f8780b7f6b77234f8c96d26a82bdce01c4439120922a0cc4bd013a00513460500eba9236e533ba503b8f850eb9a8c0e85092817fe30d267e43b009e67dd939f26b927714a42aa23a7883f34300a2a74728c47f85020062d86100a24b25cd3a56c27b9e0d2dbc4f59e1688335320671f4a1d134494dcdda264422bb376dda010f0338032103426eee16838bbbc1f0e26e3ebcbbf9c0b85b0f8e2143c6de27d7de3c2eec10e6ec0f6a6dcf90110386b7dfc5c268736163214ba265419b0adaa68296012540fabbdeb9402e258f5faf750e7177a7faa57eea54ff4b4aada5544e199fff0e1052279deeee320698310e6fe89c47f49cee8ec2819a43e67477f714f43ccd40fbe47bcb47f882ca083b4af59b4c25134cf7dde91d81cb9572aaf8ac781d877380d8451a2c960d78a4690af0bdfe2666e35727041c20e240d85568044492f9a6016422ad5811971381ab4cc6ab380e55bc4a0b5e052b7940bc0867cc59ad0b26a5945886651996816c6af7c8eb51c5c060281ca85b8252f0f4e8f9817d0eccf52fa1f7e38b49393e85efb5e7883a88a7478f1ffd70170f76bde32e974f2b5dad44b556922d11bef096394daf4d2ee5a4a59b4d69257bad7fca51f141edb158311ccc090301aeac8e5626871222f0000ce28bd0e8ba3457e6c25c5d0e78a36373c1bfb22dab21082c1800b8c2501f2693033ef9e29763eb8159e05a47728e38236a54c926c13b3049457418b3162949905b7671898139f346a662318717ee3accc126ce74f22c66c1150b08bba90566c5357202e2214665714b496a77c1187d2c16eb8bae5f0100aaa21e3222e508a34ffba40c0bde44bde960695fe9ba7c1a0b97d44db96898ad19a5a59b9d98260b42526ecfd361b1e47c68133bfb39376b15cd69fcf9494ae93fa5ff5252fa534a4a678437ffd75fca3967b516bb16c3b010b0d26b4dbb71de48e5bc917eb2542add38e79b283e5d7c3a9d280de1a709021910a5ef39704281593ae5676e4bf766a51bdf07164d8bf046caa83dc36c35c1b7a5a9b5ecfabbd63cc217b22480f999206127ef2d9970afffcb78cc208e9c262d6bf92c8e450be1573a2795f521b41062762535b6aff2ec424d06adda8b65da2d59fb536a31e1d3966576aaa6dba9aaaa7e5c1240d5af4d251214f04d9b51d7d402512d25bcc435e79cf5e79cf377e4686e2bbd10e6e47ca6dd0ec20aa953a85d4a2985536b81f0664ed903bacb3993f090464077fcc45d3aaa34028632f24629b10bbbe650b17be23dfe87c4bb63d610425ad582b8f374a7315723e2bc8d872e75f42378843178a482aec5c39f06e674673f0c6f525788e8665a50eb197b318a4b71d002fa7fc2429f92523a2391546b05a7715a2f2dd46db103efa4f402a456d182f0218bc562592ab3c34d564c8128269978e0af502d1a425888d32f7405070ebf414f88ab1c5aea87f2e5f360c99bfdeb83c21af439b5b04de919eb028c3dc5693ab885c2333ca8f8ac704c2d785732a66caa646a92fa210bc99f9f9f189d682da8edd5186b416daff78039157a2bc338f99446a7f17962945c6dc199163cf00eea7d2e6d416d318a4bd5259268d55363d82cfa7eea4f11fd792b3f23d5e4a94ca13586d65de779ac1388b60d60f75a509b8a7ef5a205b596b968b1b0c779bfba69493932daa2e0bb41397dd08248d0833729277ee5410b6a2da33ad88ab0ebed89cbcb85bf9269792f5c0cc61ca75944dcaf740bea6c1b8259b1c10a0d5a509f84b0b8f0572d5a50a8850697450b6aea04fe0aa6b535c1ae7f80bf72693179f9d0030f9b06b0eb6d079a9616ebf57b36b62535b7253d08f8abdb824a6c2b890e4131ee0624e36e48f60c390307fe0aa7155bd1f384c05fe1b4f6ff0ae714018d535605d41c5c514d656cb4cd17b58d8d9c13cace1dc2b21482fca7bbc298348543a584128ea0d11775d423c01c78e3b4434656943ebd5f951023152ab42442e92b8109a4121dbe9cfff8a224b452a7c4172b1cb9b1b3da1f4218527bab521d93d8db16112bfdb4786bccfce46767d77596561a033f5b353be5476b6dad0eb5967a65efbde31234aa16489c86c628c3b2ec6344da7bfb6c1f3697d2d9a6a16d62b2b3d0de7befedb3b7cff6210bf964a1bd774b113e5a9a9864a1bdbdbd37855f877dac117f6b4e1979f0d93b0bed22945cf161fbec0fb0a0342a3fc1af858e3c02dc881269bcf1dee3e738ef3b81084f9da483cb483df1ed0876bde5807d4fe8c150a954aa9307ad188174744b251e2447f2bccf48ec4c431b0e745753946a3786697bc3c076c366642b825d6f369836cea9a4996dbb0076bdd580da2a546c179a8d88cb7ed986e00d350703b3fdb0d8a9219b0bbb8630e7e5db846c4136209b05b0ebad023377a3a183bb51c083bbcdf0c1dd7e745bb5c9a0da34f8a509a6a9b9db046cf6cd7f52ca1265a566a078ef710f8d4a767389bd79e8bdf7de1c0f9dbd4d4df6de7b6f081f3e34e1bd378fae9350ba7cffffa8d3e9743a4d749e05d2d6aa594c9bb14520474b18d78f5352873106315299b2547e7d392746abed40f094ba37c944f2105a9d52af16cb342de338adbbce3342947fecc6b06c6baa18adb32b0bc94132906c81d3e6c49651b4565a2d86d94a97e40a60d7990697174a2915e285a3b5d26a6da5441c0ca5ee43302b287517b28205a5ee423205388cf30cf94796214f20c79061c83eb24feec912a0d935b4565a2d86d94a6df20b2ef60b985dc811c810c80fc82dec19940a998143a9101c4add656471c49cf325a5d09473e22824f4f9a2f445ebcb3660fef74a68562d9665daa94318b3622eebfafa4734aa6ebb0bbd2a7d514aab8b524a299d74be94734af95389bdf7de41ff441af4bd5d2e17678b88523adb24b44dafbdf7dedb676f9f5db4f76ed1235f43388410bae9b577a494521fd4b36a5d167f2b429968438b9e57d193cdda3f1de6d0222279030a7eec73b9a0b88ed4ea1e941d9059f05add629976af9661b60a651e745713946a3786695be615f28eac42d69179b0546babc5b20cb335690632a8b5d627aab5d56298ad31a8d57d8a5add7f6a75ff8141adae17b8408a285ac0822c50ace089adba42ac247f617107e244135754c044adee3fb5baffb87badee3f33b220728f52470d8a931f1ff0ff553ec771f752090286c59c4d0d0d4ff429876a1228d8a8c1711cc781a0d3e999ce5e8ce25243860c59a143c723d11e12684cfe4acc81230150f2f60f1fc6d7ff4749c4fdfd6194299bb2291f175fec92563ba47271f620a58c28893a92b152edf127ad6f97f88c27295042ce181e4ba3a07a3a8ad6dc094c5002128cc084b54ed2f8b47560450428159dd64bb40a974e6bddb9bce8176e03180d42c0610c820f2481c4114678a00822aa74aa4e6bad597eadedc04b388410484100114346a7b54bcbd89dd62ebdadb59d8649188b08d8b75b3f93b249d5d4a066f42549a839258ecda494d182ba86e6b446757175e306bc8214a36d01639665091055f103f18739ffa3224c0e155fca4fa251781d8c56ac4ea3775d8761b0a9a1a1f40330763b9ecd4c1767708b079a8310caa8a2b1b932e2cee624f00ec63b508acf351733fa55a8f90215550e2ff45ee5ac57d18831a6a65f110da0a0a6e38033920929bf4e4969cf005e58c10f113604e9a961c914342821229214c3103d51825c5682286284039126a41220667062c90a4056f8d971c40413240e65f16b7b35acd6d65a5b83d1642acd7ad6c3af97a16e26c5e1ab2d6b5b8bafe56c8abb4260d7f85aedd94d0675e2c0a2ba196df1cba22ccae26b2dbed67918d003bf6c8ab329ceb31dbef8e2fb9a7e451e9b78c83a9d6a16c745427b19c2319a9c6097fe9ac2e8dac7581534f9ffdaa30dc18e7d19d2f0e647100e1aca5170d410056d460b6f601529a5943213815d4be952a696c0ae5faabed7f15ffe4329a59405f85e26480e42c6e7528088f1b9141c2573a04bc1f8bccf8f607cbcf84c462e3e53167cf3f90dd86d6c0d4693a9b4ee73a32746ac0f3e97f232946ac283969b7aa20353163c8339385924d8f50c920c48ca7c3ec52289f95c6bf9c2c0a03fa7b2810a0d5c5a7caeb5979bfa3c0b660173392059905df16541302c52d79405bfb470f95c8a8acfb5b6c13565c1a80fc68735f2f2e74ef2146e9339713073750fd8731cde18993e9732835bbed2e7536c775f86a4f6b9d654d79405679fc53ed75acdb5b9d7d69b6b91e40dc0bcf0d1cfb5e6e26629d8756a7e2623ecf2f323ec9a03928db0eb871163f8878db0eb6bca82e1364920499229a378f3290d92ee45341eb5817af505cbf3bcea5917dbab487828ec61cccb6e309b699de62457a45b0079aacf56cdf72d79557cb5bd6b694a9e951dacf7c269a4a6782ebe9777e3d9e86cd5f7321d12d55753c31b81068da88a3a0ad18042341e12c541d3b2108e5a8b317efcfff71de932df335343d4a038c963ca297980412de66c6a687ea83409146cd4e0388ee340d0e934d04c672f4671a9154544a921e6cbe572f108e5ed15047a0cfc8a5e3b4439d3751d9512a6904043a7867c0571082174ff970b175fec83568bb92c17499833c622454f8a88a4cb05c50514949de42642f907289a9399497e651f720f99072c4959037987276230c5cf4f5e52ab2b2bc949b20e39280365243903f948ce21e390f4efaf8c017720f9866c2417c936e40bfcfcd45a7f3666e25fce5a4998e99062529462a8044e5d97ae0620000403180000000c0685033994635918e665031400153a8c30646a3e14892391501c875114454114c4300c823008003114a390638c497802758a43b48dd94e5378778aca42820ca2ea0fba367ad68f69e4f86dd3ce84dcdb49ee8f071994eb2aae1f8dc99f4aff66fb79e8fc467d4d35eb5950a074877e6e25ddbf80d46ef53797feeac519e945be5dd790ae5a17b7cb9a4a9c9654b97b6ca16b6c5ee0a1ab2f516f13a4e1c8923c34256c85c801156e6a500a5618765b33a070ff78fcbd09d6af9bd5618d4fb04851ada8eb1867242722690ff74091835d266b6c84b046a8849d0f82a6f5af776ec2c9807443540cfb93b9e4baffe460e10324603871b4c8800528907b099bc506c08e676d32907775334244b778498b0fab56b8e9f5b5dda1bd91ffe58d874d8c0b2a8b793ab6d852fb2c7d9b69affcd033e3bd9bef63c87b944e42f9ebb7a3d4eed6b7e3d0f77126fee465748a08562a92394f6043b34b23dcb9146b5be687a2eea16c2708c0c0c66ca23e2bc471e9d0d0ebdd6e35ae15f7faf488cb5ebc234de1cb8da620131140e9fcdd182576b61e73bc2f503efafccf40e8cff4730bd1195d2f4a42f3798be613f607a783320e2d96e23635d081cdf66ec98cf108c7e01fc2e7415240611ea0da62e3894ff8252d53310252094cc662e4df9d17594a412478899689224a01c0fb9cd923477f5c8096943673015ef623f3cf92ab3136460d17c4b339c1c95517c196129d8bf503ae42d0d5bf1938d90d2c7caff541d418451fe03a83a86a1591d0ad26a9a15a8cea242431afb4b07b5d1005d3690be68834a55c813ca2206f210831a4dafd27262bc558884bc2e4e5b21ece2bf272bdbab64b13aa0856dfcc1b5257219ba97212190d744e64e43582b23a231e730413b71138d99e49c579ba44632091bad3a44769034046148a10e01ff12130742f6b666cdc50f73feadd344e2c8d43ed04aa069b6c0e177db7f1822bc769b51c234c2f463faf1a33f48fb3bd83cc4df4b123e479bb0847f324b7ed89d56f8928bdd1108e8d435f6445678440af5b796a541267edcc802d30de45c71a24d6c65610f3718a1c05c1c8ada3104055595c82c6e20a2008cfdb107503ca417c07685c688cb3d18f78a202be80c88c36a035b3928feac0c9246e732c65e6d1b27236b1e0d16498d8f184473ef181986dba834043e86871f1e822b8b7916e84eb8cf5151eced2b0a961bfd182ac48cde330581d73a34982852a21d156b4877d53043f76a51b09ed7ee3f9b9920c0421d37cf06139c5a6ba2611fbb92bb35bf16a394dcc7433c8276dd6c0f1116f340f695e222d682da35f1327d65bc042f63a2ec051a512a3c50452308cd5724c7cbc5e860fe467ebe373a0d0511bed67f43f74faf1e4ab929574e8b7741fde34637df73ba5263a251118e579b983f5ce9e20a8c62799bf3d85a0ba6e3ca56e2aff99ac2a36df8ddc7c95a106a2e1958c04a96480a9b3e1b5bac25a3c3239c823a1c41b89333d12e5614baa8eb4c98594aaa98e4be20b6e64a7a636a05e8ea434caa58ff6b49f9ada865b01b7b2c76b90880aff1d57fa0e8c3fde2b88446e2d2c405b81007f2741daeccbe72291de8fc4d9768f867e4676de6dbc60222cc906dd8d839db3db50b1c09efa2480bbb4a9660853451e7c34d966b64ac293bdf406e94d7eb7649ad107d0e2515ba75d104cae39bdfaebb80fee582ff86a5b6f9120c906f83e23a896e36743a61a04c08e9015e467e8d7a53161d856d7512464080f7e0213851dd02b6a7b7955e3cb9fc31d7aa415256cbc7e8732cb00992109d45998f6a8cf77ee537fdb040ab1eea08b54f2f29e13eb73a1eaecae0f211d3053870d90c074e7ea5ae3b90703c23f836d0e7b07ab8271229e03ec4592d06d5fb94d3720bbd88a7c23c3d0fdf53f3542782ff63f37e2369b36d0f49c9f2037155303384fd8b3ea2860159d393601a4722b6639d83700763a6af5f338aa9fbadefa78b113bb1fc9dac65d9dede309d026271855409176e8fa4fccf13358cb2aaf8f24c37fd1d4ee839176ce1c00b866040fbda5765d6d9596b868d099d340a2375fb1e7e16b431b1bb6d88dc26d54541108fa84f86356bf37a76663442a0e00c7edf734b18474376e30441f4be2ad7750c4c7bb1395ed7f455692ad1085b300d2083e9020fe1b7cecd558fd7ab162bb1968b36c14b4de6784fd882b80bf3ce3b0930ae3d883893291dcdb7c332d5d02c1f96fb1c129a373044408eb7a0f852f3014e734ad0f2a4e888c69441118c68698b3f0e7b5013b6a0f706b7d3b755a7e24a3ec4ac7cede5874ef0986227bfecc29302c8c182c34d3c5a92ac0509e4388f1128942339718ab984a5b0d29249af712a1a9ac9db771565743f61530e17935443c7b5a23b146c5903fc2cbd9da58bd56702bb72c2030eca71f23fc276b0fdd8ebe2dc28d95026bb422277b85c57754541ad71c963781cdfd0dd3546fec889b6d325e7863ac977389e96346ad1d4e1a33900d029aad3bf23ce721a9a92d744ba960dc3aad3d2b81456933f17e37ab67bf3837b39538f32f2eb81e18ab7f7a9565b35388c52787e640610e6b78fc1713cad853acc6b31551ae61584c069310a7b597537549e63aed6af7951b8188cdc690bfd76ffb8e31fd3c76be4ac6d0cf3c6c05644130cecffa371646b20be091c8e21effda467f12d82e80cb800a5704665f32233f8e83d9c69432e7764e30969804d223e431cc7ee739dce5bb8f1a8164f1d6018b766229336ad3c0d6fba227d73b989f1a98e022d732e145774f85a8fa22776364b2297c157b7f20174f77a2948c907bf5c2bb28a05414402e848d49efbb9343aaf7e01b8062f903f36e1072bf7965177df78d5529bc2e19f88e950db8eaba01f4ef2bf052f90ec3ca4c43f54110fa7f66e4e0ad47502e18ea46426ba9eff89d1346e460381177fd0e0a17dff6ddafd0bfd7ef260f87d2a8dfcb1b4bb0a782713422633f21bc796b56c7ec7b1b599975e3b1e9b1f60368ecbf45f0d96505b4f27ff7ef34f1148f905e4d2542dfcd95ed7c256effb3bbd704bc11a3fb2d0936bba990ce7997d1bc4670ed4ae9be452e661aef5f2678a7d0ea0f2541f649060ad98478e5fd4716ec3f390d06efadeb6b2176bbdddce59da22dc2b78aed64eefe9474573ce2682f38749dd79e9aab8b7d79839bde1181f359d77516849ec01a9c9cf3056f1dbc35ff82565154f98ca9cd8566e71b302bbf88f02a3d3f5eec49e1edd20199abe137eb9b1b480fbfee2d54651b5e9b9a0fc3fb8636cef04bfb8f798a373cb6dd0fb0881d88623a8b03f2bc65423cc984d0f0bfc3a1a9fff92eb4b08e783a1753f7cc4cf18715367ce1653113af773c86ff86ebfee34657d3188b07891cd6e04a0391163a411383b85b90c0dbdae7c2ee866b12712644039fb228eb6a408171c44cd2c28c850aa2df42d9b02847e4de7a48f45844c4a9dad1c3af10bf66a0d4d132182bc524b012b3c0a90cf0a27822d17f8ee622240935097e83b86eccc6846b5d7020412178de28171321b2fbecb636ba61acd360c390501e3c36b5fcdd32bf6512fdb39100e042bdc1737d9b127e107489c7874f0d627f0e411a5486ed8822dc96413c78a62c0ffa39e895ad161ffee0a5bb26c4845b487d01f92608a31fe8c14e59b38108ef7d479ff77bad7bd06360b25e8921c068784fd098d897de9a0085c7e58f629426227c0c5206debabae78bee724f4365bc2708fd0f2fe677a2b8876789dee8c9530138860a06c070c10102d4325c8000dfdb4e04fdd8037283cf67eb81850750074501522dd561ae364ab6ed40e67945f29c61a0563dc0db67a7dcf25729f82ca50639a590f4381cda01420922b1ab2505a0bf31613feac0493f3f87e27de0030e1098e57bca03900aefd06a6d396e5206b264b26f23767d2b2dcc4605afc6f347d40426268cc472cbbaad96b7f01ed3f941400e996c173486334c46d79a7b680ecd68a9f0b9611d9b85fff86b231d20a07f8b66608bbf63b3662b672b233790af42c4e1c3c87d35fecc1ef66c488b9c037803d5f374392169a29dae896cf6255ccbbe90c04826cfbd5ff5f65ce22ec650b563ea6569d3cc78f9b2b2976f2de56c9dc70378e20523441ab89f34a0acfbc9046f209149fcb4e05f64e5ae03bd5a61765ea66bde152c6c20d60068d013fdc51cf48e7dc8928bd25068b5cbcd098b50fdacaf3000762aee9a5982da08f7069528bba0772998f7c39a9420f04517c4856fc9067aaf17c0c334416a92d271cee1fbc586d2e130b81c2805adab0b7a408c38288c6c1155dab278d5bf3567933a06a177623901e130d905435a93b5bf5068f0cad6cc1ba8ea27c8d3039b5b7b9a1a7caf6dcf61e973f2690a9b4afca1321408309788f49f42dd23cf9b6ddc19f66a481e5d3a20f5a9d4b404651ba302845b1e69c23c96327237a7aad92ac0419655aa09f919495370e2282d15eba2820dd275b5c19cc5b19c3d81d95e57899465ba84a2878411864b047a083861b86558858413865acd864f3f375a2026497e6cc7b440d9448e10820a18ab2076a406c94d7cbd9c308ce523a871c1124bcb72d412e8adac494cd23403fbb66049c365e8bc63016abaf7f5d2019a8bfb5b92028f3e9272361cec335910106d5845c223ed839609e052a9049cb3878bc17bebda95b7e11f693d11c2f02e010a1741eac4f4ceeeaddd11ffcc41c21ee2d82056107557940023cb37a7412d816f12c5ff2d32349a4d4b39b805961246dfb4d4d8b87ced5b6dcbbd8174a213718fb11722c818123b07e81a65e15b87ffbca13466150872e2f70e98395f957f75f88ad9e59cf956fa76837012f76ad11b6071525401295fdf0875eb6eb3585117e215ae15f0b55161b624fd217453b8d6040bb94ba91b13d073070ffbedbfaafec569d2dcb1b9d96d12f844b6b1c3da6e9428a0172fb13ef15863b933c963a3f102507bb34e0b2a85b58860bb16fd3b4c944cf8563e2714e6b292a10cd9822131d20a9e2cfc4e4d7e43e591b32c914c429208c95343d2e37f7bc3104e80a4f5fb70a9e666f0f3ac0eb2eb7d74123a43c636814629e51fd703ec65b2f300cc7b6181bec799a227957c286bfa4653f747842c5bfb09f963372bd4bfb462026dad48076bdbac2491e8aef5fe97f0576b2043084e7be49885c2f1d5b5f43993a8519ec87d0350ea05d0d927a8c1261386084ea24e73e57291e5e720a585d23cf656767f597c448f294e70e43b01defe179d8bcccb34411486c6942b4584173a448cd03296b2a43cf2ebf2396ac58491a8562074105f960dced8ddb33d27b27607b17a07a79a4b1398ab8c296bc2b4144904e1f1ad4e71261b2bbb7cb6bbd615d5a1b71d07d6f16753ecd09ef38935370571d000e3eb482b7334843cf562cc9d8c86350920dc2db91a0d563e746766e213c6fdbc75a4087488d47377d7ba069e0a60c9387b5a1ebfe0bf4b8c2c48d216f3b4357beb22166e9e20a2d862ed4f216c9c5500778372eeee6b30746c729fbb18c0bd878553c2ffd8aa9e6496bb844e129f025fc0bbc10381e3e152085eb185d4f758aca9aa972933d5703fcef8c7c762b8cf31f85d930e5ef81bffc2bd58fa8800003ba5ca6b1f8f45eafabdd1f30cd60a0ea65f90820e07128f0c5df242ef8cccd77ff738356c7324721884daa0ce662943e870a3cf0f2d1268ff70afa3b98a1de19c57144b437f4e26591fdac6097a51147a962c58b06429b293870b3e0b42e1151c926cb28c794eb1dec25c59d751d21209ec2895cc4e98e4006b388621db14ce12a695495d8e768f00494c4037603c38702af1bc42011be3c45060a190f30a0d4cd88e5828208ec62df2702b37c97815d836fc74c3c808c4a9e7769fbf52e4fb99264fe04bc793ac644da67b579f122fee1e950fbf79b4f76a1ddabe4ece4299e44796874b5bcccb828a556d8a60a4550b02e218703fdc6884d2a7f5d1fc0f67d9b5647756ba3367f3ae4daf105003a187c90d49e40c85e445b711c0ab799f79729f2fb932362224644be25dd2b6780bd399638fd9678bd86028c000a6c56686ce9c9e2ac069c03346f398d18c1a68c292006e875ce658a1379df972f4c4d3cd6a1a83a65f92369757b6f0d0d948607f5b4f14028a8a88e5637549c6bf5db8f8b6bfc042015c83c53909ae0f51f0efdb6187afe845da9cdb2f5da4b7aceefd71b5582c88f53a4d4218b13337d676a7f9eb493204c03bd0562d2b0abce4808aaccf050ecbddea332d93d5952d2b72d4fa8e06c1696f464b62857d373c1814651385d9e92de4d68e138b5627a8cc6af286ac16754d5b220cca1b9a34db2f4573fd2d282c7033b89e50df2924ab3b05f57eab3251f25446dfd9d12a5be95ac9461f7a4e9f9710dd6545757d2c618e117e97a538ad39e95cdb780a9dc11f3aaee5a2d5eefc770c05da6e151b2ba36edcb6c7759ff73b24b760e1dad3ce030534ab92d1cf35d23d2be5b0646ac2ac8f9c47d69973a186e641b65dcfb032f8ca7db5d5a92d02d660eb139397a8b2c95a421f073cd69410888b7081ad76eefe4c4d79c555caa9869a3e83ee7518d80dd92579c670d8d6f0fa197b85e87607a86a054907c6791ca88f7143670cdfec15514fd1f9a37e31be2e7cb5977bec9be9bd032868f5c2b23b81178e34a724abba7c56600b872d23748216b538a43e4590c1122f8a53053b74059c097dbeff6caade54f212b9cde9c41c9d51bd58b2946e42cc834bf24297cf857732d612cbac258087dbdc04aa88df7cbd7f5818e875e25c4013e1d81d16f77073e30c5dd5d085bc714785af80a753240b77b4d42647afe9d357b110d8cde6434b89e3bf3c811fa804bc4e0753b5f6c8da3b5b2b23043a7199f9c932c3b0cb88d7050b8065948486e65dcf35d8a6f3eb3bec6db45962d3fdcb9fb45970aa7ab68c40e8f8539debef7a03210e8428b8401d69b0758d67f5f5b99ee02667318fe808fc62a1e0fd94fbff0f7f23ccb359cc62aafeced29ef76a04837f96913ec5a3a05686b42b2b4d01d4e8037021bb86a12d68881463c4d37dec4d81bccfd828d89eee3b1ec15756243629a9c500c17b0b1f0adef836fbf92708a0cf669df7027fda7030d3f536f740233101db8148d30a9e8a6e4db3905306d8de8bf2f2aa0a89ed17af38d14f56a33f8e426e0f49618c53e24d0596c3e4ab0423a007f667971a7b93262cb472e9bbd4907224b95a4c64908e083630bfdf282d2b52781b47487b7c41f584332536d04c0ba17eb64727fde9a72cc0384698387680133d9b0ca8b4b0bc2bba48c7eebaf1de7e7ecd820fccc169d7807f4fbfd715b0b113e97c9eb107ae27b74a5e61f7c29fa592625d5c1818ae07d28f0ded1a342baafeaec242595bcd9074b64e3e64e3f4174b9dadaba4f9ae9e2f4b39c091b1f4e157e7dea2c6b6133dd3a06a47254af7f04bc489cb8f28ed6105f97cd591d5c3c568f90f07f5d99201f60adc7abe33f87dedfa6436389557b02ef41d8ac53334308a0d8b079949b9041e541baba0021103626e273417b9375c7c1cb27b621fbabe8019ae2ea947ecbb30bb4a1a1d7c452c08618c303a7cf7682a5e42624a2856fa7de27b8b9aa68474d262b731ee41c7d49a10a259880ed884359486d7e0058940e85ecaf2c46bc0ead66c8dc4b64f374f2b26524ca4b58172fb6dd31d8d14aaf17fa84b23dd3d5dd070e1c7983687dd9196ca175f482fb5850459caf666b19600137bd3c28a8aa1440be1dac515192df93889a66b9da75b07ca9850310494c5bed1779f1f7dd3c70b6f71dd3d40a50fa9e332dba05a0aa27cff975a584c83b49e4ff2bbe6e6ea7d5632e0bca6947f0912a27700dbba80e571cd87adacebafa1e57abd548fd7651d1beec4f19486f2fc83b3c78f4222aa9e7d2a5c146cae8c42ef829a355f8f9745e6279e2832438c19ee9821b6a65f4a405782fe977f4db22e80f540a83ed76faccd585edc7a2376bca38e32a9335952576ac35770e1e63684df61e10fcefc2384f8f67555f6a14b0792106f14846a1b39eb1a55cb3d865ce6baed952cadad8152c3da417e0768449346ac7e573c90c59cced6a7099a912af86ff52c117780c83f4378ed1b31511561a3169edbf674e6e68065020fc0ad3b82f3fe60a89f292df7a94b0d355401d1f33ac884318d7305a183ac6dc030bbde98f4453b60150f4fbd9e9c0276a0054ebc51e72c253df8d16e624d2314329c180f49088e1d0cdcdb8a19ec03425c1911f6b58cbbb79b506da021ffed26c2a133e88dbba9b1c7df0c11eca12a093e55c5fc29224839ab9391c8cb8777b3bcc74b171e71831f4830f754de73453f418ed5d0bcc662c2df9be0c1a6b5728f87ceead855c6bd19c67df0ff43a711f128e2b03232e79463f24331d142c75b2eee38398dc2fb276c8db56a7a6b954b74a5da72cb655c699d7f875d70f567abc06be61885bbab464bb927a1d659b96f4a14dcdd8e396a83832d296e8c0a2cabdb4a63e32ae6908b32a6dabe72cca01bcd5729eef9d44787cef84479bb34c473c7f7ce563ab94c5b4054acc3066eefb4187fb206cdab9d3fdc030483887eff176951cb6c4c618f91d47f66a3d1b46214534ef7a61cf0c25b982cb742c649ea36e972de884ab3d8396477598e0b8fa0128f5fc8b817289f2f4079d1e7bef1c28ad5889638325dad86485b230e8ea777d4f5e78754a12ac39c3a86662897156046e2ba76eb82635fd415f7a64c993202d1ac433eb16c0675574cc39a07c931ecd5f2485230401ef9ac6cab44dc9b6519cf01b27663ce51b0c1b05eb05a0b1878509c838ba97d05d93e078583a2dac44b436da0e836c87856ffe69c9009827633fd7be33c8faae83c4a9b10257622f78ca4cdce751366a2881d25ef1dee6f3c389edad6805e768ee282d2b7235d432279013fa6b8aa536881da59bdcafb84b58f7547dce4616f332dac389bf389e1d5d908d1e9aef02eda3a66689f9c4e981d8259158bd856837ac5d8f5a8ee2541718d4c880c1e59365661dc7855935032cf1edafdb5cecf7657c355ee63a02cfe1d920c768e28e664924ab6b508d486dfe4d1fb98e5c506bc31d5a7ae6de0c31b7022da11e496db6e583d348cfb7ffa2e0752a356f850ec34a69615af3c0384bdde0dbe0f46f4ac02e8a8b4527591e4053917fa027bc3935c1f24ce30189c1144c5d28449cb008addc53f887ced0795021c6868fdbf43ff8fa1c9bd6510f4b03396ec265fd07ab35f0abc7a79e4dac4f34f2b470047ab7f1e3204ac1cbedd1a89f0b099bb66276da468fb2291d94e062e802a3abc0a81ddf0f4d09e6617fe741aa00d9afc2bb6d19c8d0fc47075c27e520ab70e10a4b0508f0fff706de20622bddef6ee23e2360206f31af657d056fc5a977e17c94513c7288c3217af8a002eba571751ea20f6547076fbf6e8677355d9eb8903f8fdd164a585a1007c43fafa5d08a6d501c27353c821c584125df70fd80e979940761215f2ebd106bc67ce27626213258e50e4a71a550318e5eb0d78276e83c74db070c403b1960eb2c7273deddc2663e83272be51498201119b4ce16fa16ac3086b5dc592ab91aee6a2322a84a0c418136699b9dd5ef71bef32da475443c490091c409a941dbca0239ba47c5e472b0371a64652899e8b8d885cbad8ff32eb15af2ee3f2a84fdec64c8c148579b17fa67708338343316c42602f25a1318c00126197b15d14a09d76e95cd2d960d7c44edc414c713db3682eed0158b6de5f8856429f10d09818910ae531dce753283a9b59140d1af865a15b32038998426d95bb15b1a088bbf9ad859455ba89c5be31a06565dff388cb5d234aa91faa0661ee3511d4eaeeee920809abee7b5b9dfb065535d3dc3db341ae52dcae99e114ef9ff62b15f11fffcae6b30c8da2985fe3935efe8eb43c473e7d660b04e8b05e38cb30e274dd656b7221af5402c809fc2654fff9ca713cb1b1210305dc7dd6b96dab3063da2a5178ec869691084b6bc89fff26de38f7f283baf7f39e4e692296de6951793a2fdfd241a162a2b4ef6c5f598344d475818b1525bfa1ea08c1ebfbe5e362a4c5ef38045787844f2e7390acc07ec32612a9a46849960f69c5f18964ab069af630f3d3687c14f341789fe5186a9609a8ec2d7d75faf732c098ec20e3829793e3834bb834954fcac026f0357baa97d0d738920053898a80a8aced9e64fd0c4db817f69c217760a480b154f8ae963a1cf3c86d09fb8332af3a15361a0f40fca69ab404e8336034780d0bca179fd61c11671539dfa110627bb43dc320acdb014b8dfada5361dea98408926114bd1bf05b1fdb53a2a8b1f3b5b68f504bc957c0626e52fdbb65f6cbb286a0911498d9eb337b266b2dfd9582f8b9e0d78cd0bd487d7e3ef956ef2d66f23609c6fe97e303325bb1604e8ad2cd68c2d939e18ae7e40ba0938ccc95fc7ef4f2f6a21f570cad90601ba446b92f11c5e3ff87531fa6df30faf910b157544c24f660b463602ee1dbffa4ab2f90fad2de583b11d9869c55ce0d29435ddc0b964390d23a24649252d60afa91711c36f2d237a7cb675492b9d7310bcf971062896172f8f0099f85b85d5319c45e94de9c8f109dcf5fe53662009b20c972b3e34922c0d69e548b04948888a9736fcfda8b727dd960b16d241f6ef3c0d5866a3211d872d161e9c9eee2666ecdf35d7eb706a7fbcec1e436db0910256a50b727fd197cf1af019ba1df13c51892cc53a61c543cacedfb7ab29ec95e69b855b204804e8b54cfc731acd80e42e1e275f1d419658b2f6e642e251376cb4e51424d2cf191fdf8430cabf4907a648846e8440dcb5db09f676110488bada841cde9972393abba1f3219325f8fe0f35fab76a2a98e26d75ed2392e47067cc6fcbeaf1ad46b82932b3082f121d657b3b4584bfed8c4051a0eb81a71386f0de386d55e132eaa41bd2b958a550a97b6d5e3a8791bc0fd44ec14b1c1584c1cc54d0aa41eecd3b531a84d20961ca1a273a6e0555e501f2dc30f18b2bba7a8e6a4907a05f5c46061329dc85e3c52720b2a6f4254fa72e87bc93b7f59a883d7857f9fa829165d33684c1adc11a83d004a44c71a2d5572c105dfe1519f008a6e0250d459e9ef931c46e38f503d1c83a2e5a5f9699fb1d074efeea63f0c3bd1632ddb124199a4466612751ad5a4ecf36ea717c04bf65ec7ca1227f7638cf1940f41213aec4409f66022e68cbdcfb25bf796432488185d97f12803d1a1cd5d654139f4188ac798135cedbbb79ce85f4fb37eebb1e838b14c767677de9cc3c015b2b4d0fb26221e60aaee38f1302bef2400dc8fd2d35d50ac51eca9ea7f6aad529c3e023daa8f9500a4cf6ba3e47003544a8d4f1a643a0b67a446a1357d2ed2750b6532f5f423d4034e99602bca9208e5a4f2306fab324e13a148245d6b7171e0e39281631cc7bab39543898a00c686ea56272bc2c2693ce5a637311aeb985dcc1b28c956fc07d0eda89c05750156b670dae2ee418837fea673deffbd10699c2227493307c88208aac0d34ab728d29dd9c269a28d41608eaaa7f436840a863bb6cd6104f9a9deb262f2426d83c15947c5a63c70fd0cd0c2e943bd6b4b081bf3988cb8d61ccebeb82c509de8169498c921facb7ab791d2b8a6e7012c9c264ff5a7a4dcca7be4bb29c415b11bb5ba226ce2d6c75ca3932ad52302c0ca2a52328657613d4b3a0afed3c2e9c2ebce9a5d2abd31b809abd8c693b085f51457b562fb37c0b9362ccfc0891a1d09e50f29155abc6d9341e57a9b3027f0b052bc46b0bb12c5bd463cca8d61266e435076fa4a07985413505a8d527071e72e231d4dce57f52ec243104c47fd2af3ee325c1d297bb9982036d0e3bd1e16796a62ebbf7e33c2fb2dac73a928c576c5def354b8beb236ae4466becdcc036769ac9a9f8fb7d10d5e3f418aad642f1b742af3c5881ad6a96c66b43a2f56cc5495f3984a37397245f384dc8c92c9d096d48fff63dce7a3007e05fc748fdcb0671bbb91feb30f3d03e51162a4ab8b641e982d3494a704438a237548049f5b382769bf0f8b2bf27433961858eb60522e57f541264ffcacccdeb26c644f04279e14099c761b59d98d2625108320e8d528259060fc8e85ecfdf22cc790aee16eba2c2b7476d7ce9318d36eea249072c35e3ab413a90f318f7614fd1460d62c5f08276c086f0fd5ce94a0e39eac7c3c5b29e2c780c5f2b64c00dab74c7fb2ac6448da114dd6c5fda581629fb408685ef1205c301d63f0b2778867d5a136d47394892b1b0fa933fe7de26f77bcc856eb83ee5613d6a3906136de7c588a7bf9cdfd4ffade990951058381139cf99f6e43ea3a37be7c6e9bef7cf98264f2a20d1fbe65f44e0d9d108030211a952b76236e30ea07c580130cc0566c18e80b318710b61a8e3669153b111dd9fa75dbed6ac90c924c07fc28c6eaf84002f8afbe5eb0b5b3ee7d2db096e89d5875e526dd8ddeeca0feba127273963539c61e3bd791add992eef59fa70fb2d4e715d807b49c3ea89e181e71d088bce92a591cb09dbb9b7653a233ee364ac429af003284a358bf27199118bf9c0be239f326a05e846f3a109a9f680b1b17512bdee0b51fa45a3aad73fe181f0b386202690482ae6894351198df892301003b64051ca21cae745ecce9841fa461468e0504ab55df123db34ff674c23f672d773cfc3ed74a89e754d761ef7ad4db5f7ea296bd24a97919d8c050e1abb4509430e04dd1c7a9346a64248c23b23b066736b71a496104c0ee39f506c96e435463acb12bf2938f697f618db4b4a33cbb28c79af397eb208cb9d9fce5e73086491768e86f8ea0a3b3fcd2167ed0370d5ca97f3da88a30763d412dae78e2eaefb3baa5198c638e570faed5a113a931dbeaed55fda4201a10f84374f790695fcfa0219a7daf27cb8d93932d74541bfdc70fcc69bae8e523d994b7774a350195aad7465449173d6719d04576ae5fe0bce04fbb678e341b6712f24455d3ecc2ffdb561a0e05ddc84b1c2f6a2ec1f1d83917d16e77139b60e189501c456109d2bb05e31de151d5111ef4853b2c719ce24398d023c20f6fc5cd7385681f44e6b90f76fdb84d63497a506ae82f136d2c272b351aa21efd1acbaff79b9f2ae4729417227d0e989f5f2ceb6de1dd980d0ececc6395dd66d2e308f1e0a22113fd370eb7098d84b3260281dfaa51ab7bc518c6bab073ff91022ebde9d2c0a6a38c10c1b044deb9f3bbcb01c0d17883efd56ea65348437afb435df0f7d2c5500357b1962ca3b8547b20d4df41f0403a5ed96d79fc14192b8099afccb7473484cfc0efe068c6e494894ffeb386b0d57c20921b2eb6ac1f807b2e0dfc9afe6e8b284f93153686fcc588897ef52eaf4f7ac8237c426e11ca2ca9f648bfbf0e3ad0eaaa78081da321a16ad5df2937edaeaa8b06e8ab367d21d98b7dd4bf7ca92ac5d7f08d6767d6300ce93c8c98285eb859981d245350cfc5c9f62c3a57e9957d7e1a17a28f0e06964eb8fb7685d82f511603c08d0517a8bcc815526a20da89fa7eb2b8c791bc1f8054a8784245952ae5fd6a60aa93352e641ed7006ba9025023a9139461413470c9060a28ddc66309ae88d9964c5da6898b60252b76cd6379f58be5bf7fa92ca79ce2bea1a077230200c2272e04c546bfe5dc144394835426e99795fdd51135286373a9dd81f110ca4250ec532f2a59cee8598dae887b2366783183e5da2f0efb973baeb6cbe7e2b0dc4e7a3f07720bd00fb0374b5da3bced4ba89a5ef3a70b1890c81932feea4e4c6d1b3e9e205e22de697d6adb5c77196fa37524684304fa2a9284b6847f3074425c95ee885bf23f56878aea0b04e712a3d2e88d7d371ad4dc7dc1f92891af4192ba577f065e511a8ca01d5b10df57103d154cebe04d443697a91ba14fe2538f382645edab283a9cb7d754be1c79a8683446a170a202a138a9f60859ab4d7b93dcf494b4135fc19c70965c295fbe145ccaf040ebb2106515caccdffe7b0ae41949d87cc6029b49690d4a26d7dee6440492149b5af05f07067923493f5af48589c1b3d0e654a00e708396653a7fc4bf25f1b2677dfe703699f7fd841f3d3b492024e489a7c8d45e3d309c70f7220710af07c3227b74715a05eb811b3b1c2c849470099c521f6258437b18ccd1434cbd4751aa7574f6f41114684458189580c6a2c8e51965abe348b0b77b197e7324d8f115b865ddb71c0094d3295d86c732d45b74b67321460a5d9bc788f16722685e44332c8087668fbeff548d18371933bfc505cdb2335bc6c3884d0830819c87f997675b049adf37000ee4c873d980a3553da27b4150f4f1981dd39315351fd327e2f075b4b3fc36200b6394aabf2773a60985c899436f8f15879d650daabf94c49a201a63f8f1bfc63419f139c729553b164f96b3a241232c88ae26c522989b884865c3082d44f1289099a0d92f4c316e1dc5749d3599ec78992d6aa95b2a48c7026992eb5199d48c9517a27f0fcb850ebd385a8fdea874e81f84699e5d3202d2c275ef8d6ff40572f68003c522829af9cdfb82f9d157e93d3a80be7a19a56c0c461647f6c6257f2161dac2968569c1c2c750245979d7417aef461d9a5d4341e6cb47e71d76221455f21d3f2f94829a97575068fe2f7eab670f4ef3c04d40fb3abd434604e571f4b5f9f66a366b84a47565ea1abe0437359c23797bf6f3efd84722e1eaccc9b65363e662e61713a0b74cc7dbc932d6864528608948c95bc53228fe4bdca2a2a8571f5e860a8a4cc540994422e63a6a721f7714bdeb0f449f6a81aaf4bb5cc62bf6c4481ef5e698c9b0d13191f37e8b40dcdfe4959604a8bb1b5fc175930c1462521e6a6d8edfea51831ed5b3e3e07be9a9134b39590dfbfcce4e27aaa70502e5aa7946b7967df583e40908a90734b0b6485c29758c9985af60efb608c11e1fbe927713e70204df76c4d4ab7c20db53d056f01570aa58d027acf5083dc88d0f7c98c5aff8105c27436fe8f5d70283e0e6b260f10d2ba8d6b4b1c64b9693f88ae0f6dd13dc3236842a228f9fc486cfd27a1eb2de573ed0a111df26a4f3f570e92b1e9765c88692dbc060283b72372cfb0ec33eb53ed8f0b58112c71aba8b0482a4977c9e91d89c483941f2203205a4432e05b297a654a0b0d705ee9c6a3a89adb1816ca55f8e24206ba8c747b602284886cccf9d63633ca734ac113dd5e57855d43d050fd45b2005be86a490b16f9980ee512584a8c204d62f8837e4494d0c3fe676ac6ef09d2c442d611d87e7565b8bfa2ac0b746c3d1a76d354ea7478c068f6f41f29be8b1b21a18e2b27a71c90fda6fa2370991e379283de92e7f0ccb9aec90b9d1600cc9fae35505fc9b035a4dda775a2014ba92361bc41f7133387d4e3a549f37b38fe6e1ae40276cbf5a94fc9e565265a02b57fa1508dc0959193c462f00660001004f81a251c960e89aadd73beeca586bc8fe7540ebb6442dee731b4d8b4db626298908adeccd2d03a207ac0730073207665567c821c3141da529dcc5c9c9d1c981c1884d508e371de91011e9c8ce97bc468988a883398a42494390476cd904b1b00da9cfa4b1b07a18ed4feea349d62c2929edaac5973fd8276b11dec42622a4a323a1a027f857daa1788d13fe5415f7e10fa37bfcc97d3891fbc0a1a494f311eee4cf0a8ae3d4c7d1e00fcd6bd904c99c8983949498f08f044a69d9c46b344bc3723de4c10181d1ee3f9eb3b2112608ce3400b0accc2db460ad55420ac036c48f8e523a6ed9b628cfd9ea57f1263f3af259aa304aac22c8c33fd35ec53da7cca269659ab522c8607ab480533a3a5971729cb8e44ad9a7401efe305a8529314939a608b9bea6b32d7d641319a4e5907bb59340f53fe953256bcab4ce6aff5938ebde796da04c3f81a902bda989051a826304e271477cf890079178b494b4b4b4a413252969c888c8c8c828c7a8a8c84748484808c7c9d0907c92395e0fe6925bb09ed983613d2be84516ccd72e675a109d9d2677ca3ea5fdc569f8f2a6a6d5d43ce08ef8d9a6592f6baa76f5d0f48e10d50a3bfe8521862780fbc01abe6c976b5e578602c438c08d1b2d25ab5519e24ddeb495bae44ffa34e1d81fc7b1404dac929d09d8347c3579d3c6da523a6f2cdb42a20379c4a77ae72259009e18d6989abf70c4bd31492288b982e94ac1a4801e229493ff6cb7a186f8c54ec53cfc6cadc41e8403c14c35b3c160d1ef4ac360552ce68a1c73858625cf1539857958fd64e655b3f545f8333acb9a6c5f1556b95e54c725a5a874f34adb201d1d7d718a728a8a8259e914a010116931a5ca942a55b895ce21141424c5d1d2d1524cd24ad7c0a866dc9bd9bae8e30379f894c1f619c5a512fc217f48d64c23ba9a47ab95538c6d88943c31bc97d54f7a647c8cd762aca4d08643638f7c7baf0c8dbd6ec432747d5dc732347ddd8965e8f9ba15c7d05095c11786b35e5202284839488110144048bca6864944ec70c4ce3407a8304102d35ee99a24050942549c7a72582264041e70e1e5c908259ed7b5386b023865e1840b268eb085d36bea9a94a58813ec4c2be1a2670b16ec9586507811a50989212bb84079a9740b2f38a50a1e2400310220a0e0795d0ccbd0f275352c43c7974af7a85ee67970bdb867fdbd588686af189a07fbeae9e1c1f58279187f6fdcc02b8d836a29a46592ac51925324152ea9b8d7046f862411f066873c0aa2caf69758c84e06c19b2514f04adf50a994e08003c736c4fe3d418b3677564f570ff7dc87a75f54a5fa4f0152684812416982fffcf19942db699a58f7117fa5ff9544fe079df0b559691b3778a56be8d081575ac68b6a0a40e0841d39786c455658699997d54f569f6929e45e907b301a0646a200fe605204042279e20e873fecfb4b21e09dd13a3bf026e2146dff95e65e563f81f9192d7d6056af923deec33f46eb600179246b788c3ca72789ec67640e0c51519643e582c9d1d161818518262a4c301851526201b3b00df941847484615e9aee3c48d6787e7f0f729cf847474b4a4276a010b957046f623c22228ac1227f92e787f67332d91fabd7d44f665ef6b815f79140eec39db6c89f0cd2ac140a92536bc19b98a6fcb953101c93a444fe5cc9a1b8e7442b9d5f567bd2cfccabb4cfbfb21fb937d3b9120eeb147327855c06b5ac27590c6f5a364e4ebe65fb5f201808be1a6eac7a652d85dc897b44ee691d8e2bb9870e17e6d93ff04aa75e563f513dd5663ef366b4f5e00d00f0dd5e5867a0f5d6bd1602b00dd13e26296f43b2982bf2e7474b4af0b5d2d82bd34f549f52fd556592e74a90cc712525b7621f8786f59e046f7a7c688eee8e1675fefaa2d2fb21bb1527f7dc9fb40a5a27599ccc99be714c527ee1982264f93adb3030508a2c579abe342d9d48222d8bdc3372cfffea0cd89dea9ee4eec9aa9331f97d23e2dab693435264d913254fdc3a2b04461b813ce28e8eac790500aff414c00e5e6929046fbcd2fea256f6788d4b1e2b74f6901d447414c1d671660e9e4e514f3b6a46e944494a9a53aa30ed2ab34a8e5151d13c5a4ada4b7309c7c9d0d01c92393f89f634cab269445739f38157d9ee1e5f04d28137f12f0ed70e1d373629e4a859c1c37153dacbd0fe8aa1e14bf2c89c1d96e6017dc487a157d0477c4d6778f32dcf0579c49fb1323e767c2e67c7156060ecf837061408c0394dcb7d1ce950b8b115f16ecdbe05a061009b5934079821c68d1b2d2979a49cd247f61489db9de08d7f8ee273a7ed2f5f0e39712705cca8542dacd2f00503f39247de684578e3c68d9ad2d08b7f6347edc99af8f0c6012def870c837bf18db8175f32005bf7d1006c1dc0e33d5ba2b65b696ac1e75f19fe90b1852c836490f738f94f100fbc899fb50570601120861c154ecac78679b8765c2dd3213dd6809b2b608b0b5bb30693fc71344db8ec361e3794a59414422825c43027654a6ba5b5d24aa95b2e734379021c6744c69c11d9e51e7c496d28f5b8a11c7385a45462ff04eb9478e0256ddccb98cbf86386906187279d734e4a6bad76bbe0cdd3602e0827753abdd62112897b50ca6e06f7a094c1e17379c7bd20eec187989571d642bbd73d970c14acc09a11fee02104de641b9a88b3fd1d54c7cd2a5a6813e10f9b43abb91ec6ac77e9e8eca0b023f65c37766eb59cc67379efd2d93e27536386068c1956e6b064962163b060ccd498a9289cdc611b314aae9da4f75c2eb712a65b9d90df8337f169bc26be2a3554b857b38dc429418021028901ee88b0073bfea7c92fee8c13aa108144186477cac91eb248a4d352bd64cf1b5c42f72dae8cda3d513dcca0ccc042ca9f27e79cefcd0867adb5565a55341f1f6a215e33ab11c7c1387b0a25cb320cf3526f3f1c6fd8f753fa9bbbd6bb64df8c05119b5e4357609bc89f8b0989f41def117ff08911283a0e851fb1f7a7812f1d0001af8111b342c62aaecafede2ccc054d106832d27d4158ac9c3308e3cee0d630477b08bd9833614dc4d08bef5d863551eb01ddc94aec255db25d8bb803fe4c027edcd9a4fc5996a4dd476d8c1fe22a1bbf0330fe09450412378e529f6e8a7dbbf6b3f63fcf65c5304ccadf3ae8def672c9b6d956d31f0e5bfbd46ffa9b1b5f0debfa59a5f4c99db4f02aae853bb99313120893d019a77b344af7923cc001481e406b922443dcbd2aed0b77047784f625523a638c58ad15ab75565a2b85b4c69f49ab8e4fe78414881b93e453a82012ba02e50acf15a02668616a825313a63401290135c41d2184418a1ee3aa052edd55b03ffbcd0da3908822c24695200a88281fa80f9720289992c462e54b0cbe047d51e28b4f14972f445ea2bc6cf1c2e4e58a17a73929867941f2b264bdb4c0cb8f17222f4257d33e1b1585ef8de2b2bfb9a398368c72c2445152f8e0295b1d1b959628f6df5a8ba1b84f64156933d228132915dcaa84dd2492d7e2ec5b97b52ccb59293d4f1617bdcb7a96f32ce7d158cf7296b3195b9bb1ed69a21263c5e72d673997f5acb573da20210a4b1450171978972752e687398304a5b4d68a751902934c40599141fc3c5579628a53000591376bbf70ca2294e5c721e4c20396ea8595cd6129e5c430285e08c1c6e4204bcd407bc1f502092f8650f222e5850faa5454be4d5871448089d1414c0db82d45325b86626262b89999b9590c634b0fab0b2d5a6861d2b2b439f7a2162866cc98414383869619684142cb0f30517a0bad75d7755990984ee86207b10ba42e96e8e2045d8c208b1759b08859a8885996bc141cc2fc2cfc2cec42c55ee17225cb95a72b5f5c59ba82f44484054a1542fbc31b6259da9fc5f2b321161c6041b2e9614908def8a0089fcdc5c83970a42f94a073fa0aa0119408127cf1c3173ef10b9eab69fea58bfdcddde58b12f667b32f55b2a669f7227d19c2c574a0e209688a1b81c8fe5789324d3b1425d2ec71b2da504a8f5176293d413d3e2a2d5474b0e2d1d889a55025a14e4ca3020a89094b164311ef135945da8c34ca444a05b72a7189c03aac408a0e4eb6d9650b293a34518ac29299b0834a8a0e3d968b2e72cc11a430c182af93a551ba8205a5124566c274258bc9714a57843827324c56881918accc0b1824308122db19738a8a94a766831ad3c66f11f452980c3129fa828909119673efc95492c2e407d6175d7d92ad30e1840fb4722b8727263c713239e51ddc98ad8c022b07264f4a0e46d4648162a5490e2b3d6432c03680d19202ce641053c5064bc98105527218c2e6d0644ac9812707a049450a8f95a4295146fce1c3527890f23ca2999c7b4f4a52789290c2f3641eb139f7a4f00049e119828212c5c3fa628b141e1f6f0b50972d79e68b15a28e22c84d48ea614305541037422c548c88492802ba678297c9997b3ada1f4d864a4f44dbbe0cfc11b773ee45ef91f2c332527f8ee3389c278e52e9054539621cb4e3d360913fec354efd25a141cf614f312c6e1be84e42837e0b69b1e8149b90c42ab1ca3b102ceb4e825100b9fa5e6badb5be8cbe7dcd0e6767771cfe1730604029a53096c8f1b5212062fcf9374ec731665d46639cdd8c12a8b6d8a1185d9c4894dd8c1a36dd78b37c09538f96526a337b03a5df711886514a69b59236515a659358257da96bc452524929e40106144ae90e94623aec1d9e483521bf7e955d92209b736206125eabb6f89b5b7e78c986431ea9a5534629adac2992b3b8309ec81f9e71ca2f897cb967dcb10b1964b7eec5e420cf39e79c19bc89d89c54b5efc4707fd3e73b0e1164f933683eba3df736debe15a9d1d92d4c7a8d10abf513b06927f597f3344195177652beb421b38c9575df0d74675f5f7ead5ea576d66ad67ead99077666e16359d5b0ce5a6b06e1d75aeb4398c15a7f6accd6395b9811eeee3153f2972402b170e6266c49a7efb7b52c567c4a23b72be532b7bd1003318cba8739233a3b09648a92525af99ee3c86f390ecd4fe9eeda7dc7dbadedbefa36fbaba7d768d89744d3d7abc81fde53f2b763bf637867255c9dd502bbdaeca3d9d1d61836000416006168cf2478d224ccf9207f1c0beb701cce4862156ed38c252fdc8cc0245bd35a1ca5f429c6fdc0053a98539a986c0a6685a3f4192282527484e4de153157604d99a6d4147345ce569ac590874d614d75918e8ea4385a4a5a5a5a6d50888864306444646414a3120a0a3ac1f4119a4042323d321d7fdcd3bc8a3701c1c37698ec7f58f9246b664fa5db4b49b4e10b06ab0a6b1be24d997ec2c91fef493df711673eb5afa552a914075f2b583718bdc48924285d789288d8e188d706a36368e20110549094a58813bcaa6e61a7523abe2ea7f36d61abe50f50d050353a4a8a92c91e2408e08dbc815b16c6a280c23644a3369e0b854fe91e9c84049235413cfc4bfeb80fc924a94826c7b1d2ca2a470d8c6661ecbe29e4b04901e826a57d8b47f9160a40e0041d29b8746c452293cc3102841b2104108837f9f4007134fd49584b2259e356bc29f55b40b4afdaa7543e7cf8f0e10366aeb48eceadc8fded6fad5757c0bd24d65a0bb39a59253fc89650d8e664e569686fda4e21643c9fe6e4c2f5352cbdefbcf37e26ffde9b44878bc945dc4159f673ad9fdd333ea6bf14b6fcaabfbbe5e4623a4d2ee613f6d9175ec7522615f9b83f6dbb5f7084c5bdfaaa3feeadceb2573d9439334fdfca1c99a757d3dec21f30af7539bb732b423ff5371679139ca6f9192da3afb619d908b04d9caa386378b51981db3b18d341f720bcc11e6bb9ba8f45d9f155f7317cef7dda291b84bc7549eedd696f47f1e3c7f7eb17f73d72f7edbc89b8c348c67385290cae31f76f07b50eba076ffcad8e483b36117714394e1311c8368426f94b18d782706794a00208d7df3abca9f3064a3781aa422825e6d5a9bbbfbbbb6371df06934b553cb8b00595716c561150f904a8dce90d956dec08956b6c1554a6b131548e91555079e6679063a0328c0a2aaf545039abb60a2aa75450196f1a2aa89cd9ad82ca1854ae5b0595e956416587ca510595e1964f699cd3dbb2b3750729a594f4088b61f262ece4564a29a543504a29a594524a29a5b4c29a940d3294524a29a594524aa9c6eace28a594d20d7893035bce499b665e5084cd39273634e79c13ab7556cc665992146c4adf4b6a8c4c19a594da23589105a1ad54db2c20988ed1ed496d9649613339b54cc3d79d1ac746e1466b6b36139a73ce39e79c73cea961ec992db36dd6c96cdf44b6fbe573ce39e79c73ce39a7c6f6d578eaba6f87e79c736a224b36f6537f75cf971856998a90e3d7b061a32666af0356abc681c28dd6be3a5b224ed8ddbe1557adf7ef6b71d536f6cd70d535f6d570d534f6bdb86a9a7d31ae7ac6be1bae5ac6be295c758c7d55b86ad6be19570d63df15ae7a66cbec4ceb2aaca19ffa6c90d95c88c15573fb72b8ea987d6570d530fbcee0aa57fbc2c055e77d59b86ad5be3170d5a97d65e0aab77d67e0aaf1be34b8eabb2f0d5cb5b66f0d5c75b6af8dfbb86a6cdf13707dddee84dbc255cb7d6fe0aa7d5f1470d571df1c355eaa7614ded0af1ba0d4d6d4504ab398356cd8a8b552574194b4860d1b532401993ad95aac6216c8d6a9ded32414a82a7dc8619b5959c336b3589606c36836b3625a1ab69995e34097d61ed6650406197474f534574d0ee9231414049382531396272844441c360426213b46b2c6d270c6363e3971e24342e00f8b4d213e64ad8d4eeb3d2d624d6b796f658dc6c29f79b6874b4763e1cf3cdbc3a5a3b1f0679eede1d2d158f833cff670e9689ad5340d5b4d73b574f4c3604406978bd57a4f460d8e06e7696b39cee3b82716be99a60931b2a3b9743c6b2dced8667bb3634783491ab62dcf693967ff5b9eabf59ecb7233c0b1916371e668b0cd5c0c560b305ef03310f26731b602b0f10ec938c8240c005ff7b70de1966c7de29303bd5ec33673387334d8722ecc97b5d95a7f59ed6bd64159a3043d3af448e57f184b89d3c3e59e7eeb299df9928a9a77927e4c23b2c6bd1617c4e53890ab87c5b26847d6482724913c62a57004492024867e7c7cb22779b64810481fa1a020981aa7262c4f508888b81cf6e10ff93ec5957c08ce9445a4234ce3f77614d073b927556985c6c04edc0950901e4e85906b4f940d3cebdffcf28e1e85472a71078e53221559bbd81094986a529424cdb134f953566454b481c0070f3919ca8f04d04a9523907b4d82e8ecc09b96731e9f649731843f6a5420890cceb47402e240288f1c27e33a0b6f98268c49b50c33b8c7d120f770cd90518386ce9f5b98e613320e3cb5f3c427f71cca6b9c738208de73df1abc45e21eec3eb2e768906d966dce287f5ece91adc8dfdc4f11c7a5a8746dbe6cc32f860e1436eb3d5736238fac11e245178f960a2728c16185f8d4d1e42af297a5de9e8deb060bd8784fae2a7c7033c0a141458e0e0b36b37e006151000241003033339500703b2d0ffe90369e7badf7bc3d5beef9bf042064082633ed3efc5c85560443c77972a087dfca54f29769dc93d7088e9acb34c89cc78237d1051f407c014fcf894f5bb6cf1554e0e17a1b3568ecd0716393428e4e26a950827ba313c06610ab74a6e2ef78f4f2658afd592f5f96be445102eda1cb08baf470f1c2250b172570c1820b5346c4658a2cd3348d0b1297252e47140717c6193d463c239c32e51d4c42d4e26e0f229f5322f7d8ef729cea3ac61d71943f6b30c95f8f2d279473bacfe9eeee564c79a7b4b1c6e59c11d20ed3cc94a9c81fa65c5c992a7064c77591e5865276e0815c70354c1e9e20f60ddb0b3036d67d1ad8951ee176b833e2c33da74b29670791aa3819a1098911aa20a9121fb662b4016ffc3120e4cfc6761b36ce192b76834b2d17c62132c481124db6de1007454f5630c9b9dde77115f7e6c7e99eab6807bc913cfb8b519222927b46b1a88afcedd87207fc211f63cafe438e80ce0259bd8968148bbc8968f483f84394f4f5c0d8a3b1d6871ff9a9f78729cdc3bf92b875cbf82329a55f7fc9b6fac39bc649b07c89e919bf09e70dea160ad42047d9de4504129fea96180308c4c61d6e99f83005983cdb0e9cf6b7644b01c196ed6d28a587a32d05044c5b7ef6db5b87ffd19f53045fdd348727944065e3874fe18ffbb0ab9bfec419984e760d2a21f69526d87792605f1ac4be1587606b5b916edf2b2b2623f52d71b2ef43293f406c4d7f30f55ff69e821ff61bfc2ffbfaa9ad48f6db006238b2751ffcecb36dc8ed9e30bab488751c7ae94f1ab2974f03fdb2ecfde7160391acfbe043971758b225b417ce396fac5966a20c8b06126157493f6e49a5dc8ecc977546c24904ebd3624b8164e484d3cb9499cbb2b6529f0636ed7c501dce39e19c10aa90fa34b09370e13f9c7807fa347eebddd543cbec9065530564cea5b2eac8137bbc463200ffed9424611fc7cd00f095658dfc582fa6e3be5a4912f63da0bdee57fdbd906ddbc1d78ddb91d59e1f311760f62c9282d5ac36e1f5d4ec7adcc378e886737d4cb721954553ab0bd85f15dd54498c7e22c3d738c8fe48648ec6c16be4537d030c8c89409c87c364ee967f6770d5da890c7f685bced8280eee491d7d648dfcba451e78233fbe206bfb8b3c1c97fc41a82d1f2a711cf8e3266ff938a4b62135d31881012a65a151199a864593614506163168e804d1c982260bcd951935e8535ab5a76ddc939f37eb678f6556a6acb111b135cb741adb91fad853892f4e7d0fa89b6f71931bd5a96f490a36d6d508b4428207fe8c98ba7cadca2ff4b923514a29fde31643e6f2258c707a2c6272324c727dae3ed558f745b9a9d75a4407ac9da431ceb7d4ef84f2e7c72d065b5dd0b65389452a82cb75e12aac8f69e8b825344623f764cdbd53d33d346842bb5f17005fb7eb8056bd38c57588c32c88c01b10d1b1b3df522c783205f93c597b22f5e96b5ac97c0f682fedb9ed056a8019b4acde94a63f19b67d9ab9cc4e2be9c76ee52563b97d970c377c79a69a5535cd8dc1da951b119805117803223ab686cdad886bdbee88cb86e0725ef27c1517956bb4946e4046875c5f86a88c19f9ec0627866198a5349b710123f3b11fc05f00033636d6d160ffef27d1b6fd8b6d2f6045a0164b08b10403d462092176707724a66ddb61b8418ff548d6658bb130c37f080c4e092c791202eb8eb09fe79c15d348a4f0c11e4491b48d905882c512961d96a03424047bdf06b064cfc7b608402198c760d78e86fa17a81d066cecf9b309f94a7c89bb14ba1b9cdbdf7beffb36e46ef4beb58fcd70e1befd6bbf641aeecfa84c0306b7ef765fdc57890ef18b5712db7b407bc9ed056a00215ef2e18624c692164b08b1a4c512412ff99c172e2adfc734dc9ff76b6aeb3e1936be9fd160bf668e6bd126f7ca9c3729e3cf8f93d617ec912d392d396e2e685dee38d7965d0c78e3cf8a0fff63492044f863cefa37d839a70d3b3b0375d710936a883618c0129b6f3ece716a8bb1dd5da6625a1a63c547b02ec78e9b8fa1861cd632e945f66be38d5b1199fa10b06987dd8347f25777eb9e0d37d85dddb36167d7606367a0eef855dbb08467d710801de70eb82d39be85596c1b7e831362c7894364d4d667b8009f3eac344a39b723f4e75bfb5ff63bcebd906d19b6ed6a8458111d1b2302b338b2c49df12385b3caa96b9021bcc95eb3af3dc6c588f58c179c481aa8f42e7f1db7627b11a0147feb4ad8feac47410c3c0a7febff710a231c222cc1082dc8018b286ef062bd124027f8c00f4540c4c0084ec0a429a092acf861c2698859c50f27738494344b1eb6ffd4f0e6e18d7c977cef684b860953c64af68f52e9725ca4e22b02b975ba935404928a3be443c71609aea32017e4808818fc00eae50f01c7998f241a21028973c7f3fba6ac2072fc6f09118c9efa962c19dafe338907ed794392179726c6241eb4e54f569396b75dca2d3f1e394ebc34c81fcdf61c300f39f280204ff8dfa473ce39e79c73ce39e79c73ce39e79c73ce2c40d8896116a3d5ad486863b436b35946e33644be0f91d6622cc7b16fada5706233abd33ef655dbf7a3b8c376b1086eafd591dcab181d82d5107f47ce8f9a1097041a1b9697b96ff53451eaaf29ad907ab576134278635363144cc3a29285622621b150c41df12dfc19c53d6867140bb1b4229f94209d9420ad482b558b1a93377147e4204241868204051922885010a115966884c509c82901e10fb2400821841042292184504a08219412baff6cefbe24ee59a2160d29edd1434705970ab1470eeeca8b1c67c097738fe69fd6ce69e7b4ee9a9dd6eae8637fa69d764e2965b769b8f1edb07bf475cc90b4d65a39fd314cba94ee532a7180cf20c3e7da53db57de6bb3dddda76bcdb3f79d759f07ba6fee3da7e5a0b8bb572933293fcba494d25a29add4b5baffd4d5ba47bdbab478e5c50cd48d51d9268a890944a937edef8639834a309b4ca019348346e00321a510166de840fee3f383032d21042e087988dd511d893e58fdc1cc896d9aaf5ed33ed5bdd47c2ba23dfe0ba30f1a8b6655557f5535cbe0b6a96c6ef43dfaf823ed38847ce38f8c3ee02ccbb2c7b22397be96e9647757e2df84d1871cb123aec4f3890e61d8c74c27c7b11203a37ba8f42dd844ad5433020000001000006315400018100a06c482d1582848e34c301f14000d6f8a44665438164923490ee3308a81300629630c318800648ca121a2b100e9ab718d604e2da8dd17c6189b0ae85f59ec21c483294034f9d64aa72a48ee05c0ee4afdb053ab62a322e5f26f56ff67b106cc54f60d6e2193cb2cb56ef4eea7b31099c0836dbe9bea4b3a446f08731097901ca5908de83ff711fc60c5c9160ed6593890dd3238c8b2bb418acc4947ec4c4ac22da511044b90729e1a2d804e15030a8d3a82016c817b283820b7352999879b063c3b76c35c2fbb61d4274cc8ad013f4d88b4facbc22cebb3495183ea80f26840e1b2608a9070c4cd852e29955105f0cf7b6b659d7357669dc250793b39a40f05faa763d8738d1fdaeaba38aa17ead01c876643c2bcc5254f36e0cabb5532cbcecd5365ac446fff9785553929e7c8fac318921a04c9dcf50735457fa11d5dc05c765ae86ac3d64ee381cb04e8e64eb17d62ff48b548a7ac7b5b7bd28f5b909c3ff540d9a348c06e8fa461c724e795d30b7f476b35fe0f7de4cf0b77d0f1c4ed635933691ac388de7fce58cd67ee11e071e3c6a2a8b43c1bb0fc6f454004326379e338e41041c1e8a758daf9167299e98d9a6cf9d105ea8ea9fce4b8191edf38212bb56d68325710ad5af5c4b064f74674f5813a673470abcfadd84032bd41f14c72c0292e32ebb2c6235d19165c5504bae68cdd0006b74fe6eae66f8189e11b2cf99270d56a7a1a07f85bb447e9b706b50687cbde25e873af7e9a1f22cf6d9cb33217231eac2e703cf2c2773184f032a3390c5370d37c2545b1debc788aa717fd312f24f58dc9bdeca8c4932b24243580866c1cab75b3e485d8a1e639c2083fbbc429e2e708d863c1254b5a9c5825e7cce83263d687806c99a8bef562353461485a0e4e37244773ce672207ad603122408b6010adb11c4b052f1addd13dd4d3aa2c341bdaee45b6bc041c966ca926e071a87a45ae31b4e87149b1309ed0888f48032e760ea87bba0d2ddc30e43005053806937a42f6b242e12db82cde0ff3d471542701eadce426a50be867df16c61b370282612842f36fdb4f9e69042f2ebbab3c796de2fbe69b0f5bc6055624db14bd9ea5e99dd66256c164b797a01b4d590e42e860ef103333c3a39b5d187e98c28993fa76eb27206c478ce9e73548e89c5ff954180d6820dff3850128fc15c8e47db1dceda9998720fc72ebd044c976a2e6f518346f3de3f0b41a07b6547f65a92aba21f281b8b7f39a178ce9f587362598edefe0788952e0e9c60830cd374c9d2700988f1a71ee6d895295783b3289b70aae8b52a299bf4087b66e8e7807173e7247c3f2f506c3bbc0e9ef7d18fbdd9379733f329a28c5cf40a7d2513f4f3419a97ff6c80ad6cddfc6eee9f92e190ff73741dac7898820ed33ba46e9ce3eaf9f668404e4aaba2634681a1d830cb6e2a2c09af660dc91e9f223cdc0d1457e10d19331c7e122ee70eb6d50c84965f66fa5f2878bd8f3055344bb311859706028a7667f3887aef004e0e63a8b5616837493d1b1954e1008a3a49ed4f1ddde3725a6204345f12dd672ff6f4f880904bb8d5cf97bcdb09902838b83ece72aaa2cdc197e5fb0ca781d1357a2414b7aee403d4e8f242cbc8dcff114a72d1426bc267f606b35c22ea8409514a9435ded82ef0599f8171b1d06a3c776e51b9799772f00b936c289ece7abb5cbfe0b8dc6635eb6b2ded633f731f92cbb0241325480961825bd00f84e60ededaa252422faa8f66c1877361853f0d27f0ba8daf9c6b4302f07c2545186bdb2b56477b90feae8456017e423b9333c336afb1c1a2b5b9b0e28fae1f0834258592e4866e5a18117051c70db74435a6899bf58bb7cc54c98273309cb272660467228f8edced16a659aa4bb6143108c410299ca3b8fe4ad031478cf5406f51aade5ed291e7b68117688f4c5a5d1ce9944b59f925003704ee533d77edcd801c4a5e16315d8bcb31b981b8a44977a860c3a9c6c62a440eadc0674ef0210c923f42effa2a5fb55ef59c82f79bcdb269288e4da5ea2293896b2bfbd0ebea2f2ba7325ca7e0d2ab93c680b0daf33d747178569eb8ec78e2b9db703170819b95ff92e33b0207df3bb20c7b26c238b4987a41ca18e24344aa045241f280613aa72cfd56b5edc35efa7028d0a467621a24efb18e34cdc24b9a5aab4913c6e877c125bc13ac20156398fa82bb67723833098008b8cd422c229703d44922525042d6c8252979119ee45e4392e8e141231005cc16d876fda18502348d2d49439e03dc5845e8e4707511dc90b6a4edbc7225b0d17d469feacf7a8e2b9e026205d0f07134b44307013b054595b2034a1893aac494a4a33c1580f80fb7fd62205e5309dbae5a946cbf600765829da81de3eae57eeacfab974b409b8695349290e1799709aa77b6db65ac258b49136263862090db701293fc5b1f0cae9a77a5b6049bacc5d2b8dee37ff5aa8e3dd74d53a1e830bf01a38897a9250949ab18701a0b99c33dc3671f85c415d4b2a16e4fe9f477704b55bd4276831ac8874da62f60926cd2445ada1fabebacc1bccc27b0333c06599a6dfde4c6633bd6fe72bac3f66edc3dcea55bc2432684e66e90dae93a7eef3bb1e024c814a43c711f00df62207aa9ce9e7e0226939199c89bb703d8a4656fdbd76b7b80cc61b6c79517942b6bc4c3af1e20c84a0e8729f7cfd9b9a52c58ff2ed477efa1edb8cdbeb1bcd5075c89c3e509f329bf5a99e31fac32b43c188d1a2f14db683ac2335c9e2e646a0108ce7703a34bddb1d44ddc52a51664025f420b2770368aa98dc4143ebb1b32ab74878ce5a1e78f453b347cca8f9f2efc3dd0a8eb1ab4b3f9ac23773abb5b213c4dac9c3f54d423ae0e6f7d50ffa294eeaad18df0efabdf46058ca11dcf0e4e6410601def74dde12b4e439a5b3f3c842c2db371c75110f063a92b5a0d97ffbc045f1c3ec7942681cf4568ad1e778373d62f9e7ec102654394beed81a37d14361668c40a59ed5eb9275661dde49c322aee9731e5bd0608a1805e192796a55066bbcb64d08dc305ec3ac944c76205f88c4294df9932248e151fa56ec573de4e97573cab4aa3abb31bd09f5a9a3e622da8a10a590517deaa9a77980ce0d83436b1991140fda0b54f1721d71af5116129690db827ef82eff0c3d44af37406421cd3cf3993539f5397c562c7601e35c5318e220f23cae0523d0519e030823ed67a1480c257f599c29e82c4b6b40f467ccb7649c1896140bf26d794b658b6d871cd208150cf884a4714c498f0ca14e36e6809d0e02f9fbea198876a2876e9a95bcabaa13c831e5ceaa8ea3c40b9782954ce985c38b48ed4b93ec9fb250b78030b21a0f31b9bd00b51ae31a46f804bb30c927c174ca2858e1099a1cc0f13208e0004d0e86b972e6dabc25f593c237372c4234e1e238bbd430ab68c6c9f495b735d547bcc415005b407c5c6086a9b2f371c0041c25857b26a0e8e79b88f6c52514c4a107cd2360ff33f8244b6fc79aaf62433105fdc8a942c6846f54b717f84d38d38cfbb62f290d5de98de96a080a6990f690da319862742d7ce77487ad73d7d676836944debfe5c4ffe9eb339514c255c39db64c78ea5a9e019b4b98b4802963c39b1b995b92f5c059964dba0b3a83dd74449906a8bdac3c9a2380f29448f58777452938936ea3a5195dfd55ae4ce9cd74c7bec3130afb7a701a531c4ef7b4db2a27ca448536f6797aa20c5073abf1dd15a4e41671d960cbee940d95b0512584f35e2fe27452ca80405884e7ad11bfb3b17569f5583a30525ee7133eac4e14f5a3d604f30e117e7a128506bfb21f27a45a69cb7a6552787390dd4a21231c1eb4f8854eee19aa99543bc21622db6106fac76b62bc10170244fca5a1f56793b262d37a7e84b66f266ed985579bb1465532362c3321528a62b447213cda66160cf43b74c24b1f7289d500a9aeb11ec2618d739d9a67a428ff261d6c236ed98c001dd81cb533b4ba8263b9663d192d8ac1bd628af991473dea34d15cf1d589248013020cad32f3858f18417922c26e31223d150c8e98bf63e5c1739a9531f9fde3d0d06798626c92c87ffd58b81e1c3df04ca6bd488c2099c863b390b2a669112adba541766612df158fc9494550f28e635b5cb9760e9989f08692bd45f074cd5bcaed98c42f9937348bbf9c6acaca76734ec7b9b9e5fbfc5ce06307094873ebd6dc08c6b971d8a520418336f4cf747976f46c5115f89e7eadff00b5d26d30a8fff39b8c3cc39d009881374e1c61ad9f22ee1dd793835258bd3883a03d3aa603bc1311e343bce37d023b746bff12341aadece5b89cef4732da9ee0613fd0a6e083039f1efa08d4053f20a8d2c480bf019012ae339f459973d067cd09858165344652ac0140d629ec756fd8b9f3a2255e706684b9e139428728bdac206fbb58cbb52ff03eef4d706168108c3971f7e25e2da7e719aadd037e03824357044d91921bed378aa32f3a929719282217b8e1ec1f36792064417e6cfd1f0499ba242c64a3b6e8b1a5ea6335d92b73501189c5e6a5d0c334ee11f64d5665a7641d33a580d5244b33c0f9037729274a88f5bb12a10f5c220d1d71c963fb61d62b7cd7a937b2748c0824c46a98bdc0031bf2a969b2853d42f75c64ba987ecc1f07886cb1f320cafa26f9c342b70304c930ee434ed5559ff1e080b807ab1691c2e522d50485e5f6f8bdeb21731ddf4d0dd70ee563d80fbd173636ecd28ada70576db0e3d207377e152abf9c466ae16911e94ec86fab0342ca883888cbb1f22d6ab9b521009769728c275e19c8f656122440f7fda7a53e29e980ecddcbc2b3d54f5f8f606dc5b6fc92d643fb68fc7adef100aa4e52f443fc276df5f3efed4222bf31766325e399e811a7a9ad982619fa978a50798e44ca5dc56bd2c7fc7757edbda59401abcf649be089de3b987a8d9c8ed34887f40bff114da1ae8e8079c95f2a7494292ecd1bde51005e4cc1d284499dc33692c63432a409903a5d08699abdcbc864c575414adbe41de2262aa29b8a42c3b4dc1c399cde213927e54429e5da672c33c07e27e427f9e654079f0098429f346045aa08fc59ffd5b53a21f0aa5b1e368c9cd658fbe435b0a8440da2841332aa9fe08ca79f0ff6cf74a27aabf826acb6c870973c80cd282473c3994a8a2bde04b0c3d022484790201c19d44e5161931288c14e19676a53dd23dda6a112d927fd61e796aff46d66db9cd0dd7b53133f86955a3d4d2d99d51e6e62d5199e729037a39e2acec45a3a4a53f3586309de8d8062ca4bdf8b6a87ccdf3050f3b64ab4a890ea219f9300536f5ff957884eb6cfef2bcaa105447a4f48a68b12cea57af19e5248ed3f1bc2e8c76bc368aa53546ee8818f4d696e2bde1305a59d5fa9e2fad6ccc224ee81c2a97588c2b5dee972d9c59cdb11a5fce0fb61a774c3c91cdcaf10b8dfd09a3d7442cc0f811117aa81d2814bf39465d51bf1242d922d43b94b945ee0dfd3814cc5551dbb018ec2d01429d1aa35bdc7e5416a8ed54ebbf1d7dcf873ac5fb3c2b67c25f5715d256e6b8b67308d7fbba1a48b2b01aa352392193541c21596db78affd788113604bc46fc635aaa66589d449f6c8d60c9a9a34c2dd60276e8f3d74a760c3ee8b86708437e5befecfc18f98f33a6610461d94ae3c103dff6385268b0831d587a5723952a0132b220b4618fbd4f98fc04a71b8cfea2b865ecc469b96067340599b95e92d6c518ecf56853fb89c2ad87bd908815a9ca8ddfd7e120d4aeddd693010d9ce357cf6272071bb2f571711285ea09f146f1477b79552a6f63cdc00e1ac5b906001e7e001e95f0730ccc472985745bfb4a3ed0a11834affd70c3bfc9033d941c7cda2685a8444f6d7d6bd70de8eacd9583ad19d21186c2b5c26dbbc09bd6c31c4470f9d7fafa677f0026eb241e63f3888d68748d94e075e95b282847a64fff2b1fbecf5e204692015716fbd88a2b2b6a0a47690547db03e0eb425f765b51cefaff6da1d0757e0281b9530881be984999ab5882f395e1ce0459ed97863775b10b70b9403c7b8023b0fae4399ab0cf0045c146ace41125f6b355ca7160cbd827a1210901f3a69ba50e12e90b5e56d830e28f9962a73c5f905a57dabc4751be8e0db00e4771bed6102454df8b7e054f9c0251d16584a81d19a26d4341bc7bd6a62266a72d167a5a46b3c76a2d65b729d50df60c67af456bb8fcc31cb8c86fd64025e85a80cb9a0dc851b78ca9df9e459e75b2d6ea364cf52cc6b65d2a8c0f9c3707b16306bfec320b4b5c245d672cf1466159fa98a1da7744253e74ca12934189aea6919819c8861880f8d50e035f71631d4e9272026a6e68cb3651494d6e32675134d9a489081826f816b2ec3ea3344bb7a21cdf5781874be41d6e1b888604ad780556b5b15bc520f3628d8dd1a28bb463e10e55035039c698326dfe15d54c94463ba43273c7c2d7a281751dc232ecf4c3f82b053b878c8dd9a773f8e1f46993d70ab1141d8d25cc5ff8cbb6ba74807e69a7c63315c260c95c38274102b28434a7589ae7f9cdbd7763944f40a28f42bac206eb031f3f0444a9218f3b3ccfb1a4eab13c96faa8a5ef62a647b32a9ffd0f09ac865f06c042dfbbfd754045746f5abb55e238de569c401f15c4a5caf637d61234bd46d4d8ea18a85e153f33e9d1d78abe1cf45dde85ba8e54251e7eb569c42a330a7ebdb9aac415df6c5f1a1f6fd02f9ec0ed14a014ee04ff06834c4cb95d344641832bedcd2a5bf30b6daf07b81615353baa3a7857e84981446d8b42592b63ed1181c2a0040074e8ca283cd1e9173dab62646bfdc69c2ea8c2a946d4deaeaee1482836dfccfd2deea407913296c538e9f04fcc9c5f83822b8dfc2a88da6524e3ed4a0002c32dd3ae18b8cea9ead9c3c5b6f4fc8752811c838f4e94a67f722ee8661f7dc9183acaf559cef53584917a3c24fabb57b116e4715ed2f13f661f2e6215e343b3cdcecde15f689685925c1f1412f1156537436a739a32e11234b5f6253b3f1be3603577d2b288c144d15143fa0a0a7c602f3585d6d157009db7b451b9e6b6970c559f6d274c3129a7ea3040e9292e655fa224c44dae146f2afdbe6556e86e4502fc29941b820422f529cd02446c0f365ed475b9594779660520e52b7f165af80fd28a9c1cc826ef4816de2729b50f2849c3577d22171fa028dd73b3acb17e0824e9fca17826a657fd5245f0a02bf510910195f0af1706c8896ef65c245bd97ee6e3308b58c0992c3b464a2196a1ee812686b820d834b2f4fa1c704680a3e28f88325b7a411d4073d680c0054a442e13a1a37711f094785251ae1c23342ab807ee89039102f8206b50469d0fabe077c91cedb641a79b1e1f0b7ddae806e6b4fe8df7540c25342a569053a02f3c7aea5dac0e691cab24abbc5439325924d341fdfdd6bc0703d1e8cc711eb789ee8364f19d1892735c6e3d77f90bdd672b98fa234c0a315e57a969756dd54f5cd3000a4af0141bb1ac8f785a3db3ff10dac3d3f0b5cf64f4428738ea25aab43503c3ba98b02b31f6ee4de078afb3e0988144463f56f86e6f5619c7b945caea07a9e626284baa7e0d43f40380ef1194cf51ca6deae736137e3f614996b3e52cabe4ab1e57167e05752286e800a673e236a4062c4729a6a1b89ed9c10d7d2df3bf39658f0a8061a9cd9a5d5336ef2366c1da1c715f7dfc794aef711f90e576a5abe29f3417a0933697a6042dfd1a410ef4f89782744a790179854c22e24a2ced9ff898e5e8871f0ed4b8f1ecbf132f63e4311051a65f619182711cd1517485ecf5152a7d30985008e5d06e32f02835c8973acd27fde00b57e9b509cd7db6916bfeeb9e85c8197e9a0060e06a93ca7508262a4e424d1f6ad1920135220a1b79111dfaacbdbd0a0ff457325b0139e98243ca2fb06244d721cc1b2d89e3449e08aab7a641b5c0ded3e8a8bddab474d42f5dbe8eafb50429a2222e3c48a8da02df6adcf6a3df5ea4bb9d58d212bb557fc98512f0e767549d8a99f734cde6f96355ff10cf680a3c39c185ec8d91fc33ad3d6591b5d44286b227b74717e7c91149ee441ff5786c72a0e2518b63ef5a69d121035866d180c74bd916f4c8b99e088cb6ee256337d83a4e4e1ad33a27364a5622ee5342abbd1a56c0654e505f929bb9d3374227af39fa0406a4681823660eeb515c60cde5fa2f8996d6e054501837d7bd94d38d888e056e19e831e4ffa33d2a3ccc2c635b185473e2e52e46840bea0969710a590d6ac43bca4cb2f22ec81824539d596b4c73cba1ff11d72ae88b43f12eddb5670fc8b5b5e1e860ff4538bd44ee9344fc18f8e0506a495441ab24f754509187662682f2af02ca7516684673a31755f02f316f90c06e37f17a460cf25667f44d3c608543515396023da8be051507ad769363b13b53a7ec070ce2d9e3c8260a4f9e387060b0b0e69511af6cd37af7338feb9472c5b6355a44b206d6acc96194b9875666ede49243925c852e5eceef608a9db4c4554ae26b71de4c3126f661c99c845cb8d069248587e12cde9408c42183ac71e65c6a262d0403cfcbda66286086a2a9a96d065cd0cf9cbd58a0eeaa1ed711c20811cadff025a147f5f9e15dbe75aa997c2e422be410c1fab28439b146877ab2920c0ef0b83b408c6ef2823a1f215cd359fe2fac3d796b9ead0495ba439da844d2f31b710ef36f9fe0e5d3dc045b06893ef61c4cafcbce9e41cfcf5356a2c744eb52f8a2f73ecf7429c160dc7520b854713e194eff98702df9854b4688068175493b242f22a63172a65a24ceb6379df5145e491cac1133442a40d1e124bb1dc03f28c24f06fbe33919d99d717a99601fe4b1c693b78a8669ce6fb082554d8ec4244e8dfb06dbea836485167a98580f494d3f3dc5f993534d0aa36d24e0d025686500e1345aebe190b080bdd10a9b9e2397f44e00cf3cb17fad0c7f18b3c7c7a3d13aacd9bd69858a774257427f62fd680ce6dd88a98d88c187235bfce5fcf3afe9526ef788f1b6bc95d856013ae10f0880cc06a816248f558dbeb013f82ec30676a1920268d1c6a64791c63247423c2f51c22ffd2089c8f1ed9f8d070974bf6deaab54805aa5ead4db15ecf15bbc2b2930e7ab1558ed95c454ca23d28d37d98d9409794ae5571ec9f1f083d0a796c89a058826acb6410da7ca29775295a0a4c369f3f4859f77c9f18bc3991091168fb60d31f1f388ba90a4a699e7a525a5602d682792acd7061b5ead891c75d1aecd7d30fb430aba5ed86bef035fb084b4637d86ab66cc250886ef29e7e0ade9695f2053a50a9cff8d233bd9471408b04d78a52ddb07aaa01b3fb4cf1899ea310933411b051a7fda3a4d81fa99718ea11bf16db37a0300a78aa0cafbb3940a56ee676abadc7d15ac2a84ebfb7610e62a2caea2d4d190b4adc3dcfba061b16962ac5fc6ea2c2f61fd60668ff66bccbba8c40805108e1edb06ebdc8130eb8a0fcb4cbad22da96166d064d046dde6409c906eeb0ad62f4d67bb7faeb12a77ff6762b9cd309a12e0c50ea27ecb0c274c19570fa480a7b006d45792680339b81c22c8898fb404640d9c391032890f5523648d252ca432b3281fe4039da26d97608ce4a9fbbf5cd1546b1b5105a27863e76973380cad2a56282da92930f420c67217c815f26600f830b576c8e92f1002a9ad210ad1225f280d941d6890acf4257ae240601e17181c5cc6e7fe97cba32affc0dc5521111142466ea2d0d70aaf53c4f339001229f2fcd8d36df0790cf3e5745143349ed30cc0e65480b952bfdf3ce73abc12340cad11110c08b65e51dd6e78f70e26bff7b8ee1eb6cdddacc71bc02a1a1ecd901f71ef86b69190650b8c810a0bfc05d09fb3fdcfc8ab979bca7d0adaa6d7ace44554953289ab272bb19bc222a0022311956b7bd99c84a1e79213536073dd9c1d8d1b868cad0769122e6223d0a6c399f08931cacabe0de9695f2f95b483710ea9f1808a86f56f41d9acf520567dad084dea59bea4ba2f52de0d784b3ece1d67af509617a3d405bb1f8eb830a13e6a6c8b97c184aff034e76c964ac29d9cac0acde978d14e1731a7b8b8c93da1f1ad10f0923462abc4d9e96814be35d134d23ed85ec6f9219eb62cef64d28c6f46cf20f9ab69aa2198eaf23c3595fbc202eec44d819ea6e9ffa6d53e6ec7f1289d200e0003b099658cb02f0011479ee531657d75cd5ca55cb24b713fa0e9e06f2e7e96007d4459aabb01fb653a9b2ce20c31161607efece304e8661e26e233c87df2800ead95cfd177139b49ba6609425fe02e00e4b65354453388c4cba60d3b4fffd505f52d82e2d291af171ef68a955a693f2e4ff9d86b056422fd731d909e2368953542ea272f5c5784bad2023dfbf1445ea480429bcdac2e951a80789690bea425db24b1fa41a9d662b8330f3595df77b199e16f6143f970e53895d218159ebdbadfc9a0a7e74ec30736490b10c5541fb0df34dc73612248b72533b4c99b93b4cfc543ca406b2e54d4e125c7678a53fcf24a45c300bd8afa9597947d590b3a2463b06b066bc5ac436f8c96a053ce8ff391d56b39e6c7750efa2cc93a8405fe2f27002381716b11c50a485f3b294ad23aa852e105b7deb87dd3b38edb58bb810e67a6a255a0d828795f06446ac8d0386c4e1293830c7ec5358cab14913ddc8d6c10156c89e96230d1144ac8514f39d362d9271dae26779370413e01ee0a78f08596d3f96df8878648fd843d3a981790fc12eb553338d85d80cc68d755b1f36087a0bb1853402c34110c2b287aa707977d26b7e42bcd46ad0e530b27bd21d621d2961ccde5042452667feea61e0ed49a83d130631a9fea963865f827f691477a56f6cb63a0a62e9c0c16f6c0a82af011921de9de29f8d40e24d08c4c2a9b1cdb8106c207612096a70618f92c056aa79dc8cf8994b032d55b86b01712210abc68929a82df1503644a35b40870a6dae630e899716ff7521ace91eaf0c8fd63f554f2e0505a2f8b6c44ea6621b09f8b78b1ae8cacb9e72b649ecc8b1146e5dd7738246439ef10460a2f83ff732c8b6ad20b1e913fcb163e06d2d28879eee2a41b651170e4fa52724272238b4276b912b39da6cb3e8cd5b0edf616e9ccb0a0d79f158f90326ab2bb61d7b22409f57ccc043dff2a9550b0440bd8ef3143a40a212ab8e9b24d073c9570ba3e3a4c195c88895278701cd4792c93e284c539c885dce2e5635060c640a516bf27097dc7d5cc28b3b27920ce048048715eaff8dcd1c399f284c71c0e5d96cea6bb8f262962a5c0961705c20a72fe07e95bff425141ebc181263b044e8842a58e60c166c4e20347ff41c1652c1e6687d79c48534ad82b4858dfdc03656368d9a397cc4db1c8d9ec18b729981e55f91aaf7583d7f319cfb46124b9f9f2ac66303ad1443e57d2590d14b1138077d25b71d440745d0cf5014be594935b0ef19bdfb097300292db51cfc19b0c34e512999179e20c92365e025cff8fa88c2fe1eb0fd2fb4c789435b4d442c84e2c726448d6032f493c373e28ccdfa8c0a557eb83891ad5fea9cc43a90a23b5b85c4575803d70ad9c8a315eed453294700b39c3cba8aafdb32ae124374649184e4f5a43ac7c24354f404b086e435a3b72d4f0a43e122ba9e3616f32d582025af7d4b07615919fa4874ac908994f5c69143ae79fa5544528bae93f20a5fcd73e7ebcff8aa243f263dec9b9a6655a4bf2966e9bc7bed19340a0d0a4c50460f3ccb662465ad90948aaf70a1062df26d052d1d5dafd9f622b6ff2bbbcd923a9f2faff050d94c2b91d12b5a80f69a776d560c572ea71efc2d9bfad6ee69880eae24530311a05e9362e82b767ba16b4f08dcc456dfb7fd183768fa8a1eb409bc8a07c7d0259084329b9339ba9524c711b16bcc27a02ff85870cbda464e11c0722f09ee07ad60c389596d6943949bdb4f3906e17b6b518bbe0e4dfc31c89ec02a510a9d2cae64191bc2fc8a4d4e102994965a99263cbe500d1c396ef8adcbdcfbb6567db6f9907053bf1ea2a2b2504f8ab436c81a9fafd2143ff3f6671751f7cc93a87e2293100834348d58c7e6bd2f897b94fcd17c8757b681394fdfa41947b66b51e0c0212f7c812983dd3ed1db1dd69afd5b54f65f65da2229934d2852b734fa2bd1d070d93e919bbfb33a8dadeef64ced4ce48629ef496aec30cac8efc71a0fcc7d7fa9793d876e3d32699c40ec8fb153b86ca2fefb0f6e8f2844432ecffb622806bafba11c8d5c4c3cd586c1bd9f51ee85285278e0e55ec411635b0ac160228ec782ca7c08f8fb217fbcc695694604500a9ba557c60175640f1e50cabf1d0bcfdf69ae9ab7d609699d5c2ea61929640e0bb91b11057471995e7bc07740f91223f31db8d1445d04727e4cccb28e854143e80b1aaabb50d03ca28afdfb2718803e1ed8cd683dbca11572f73779c76ec07aeba2e766f7330055a3ca0783ea726d4e92bd3ec5580f0b2426151b827a31cbcd34f11a3a1cc4f722c71ac14dc5bf623370cd734c8e93ea752b80a4dce4273e215b5031ebbfb466ac21fc0bb6e74e8e5bd10d1b983addee1384d101d24b15c0b71362eca0ca045e5e553726c1950f173a71f4d18fe1e1d8f27641b8a2941fdfd6dfdca27d6c8c680c0d19acd0afe16ec4bcdeeac8e07315d4bf21097cac32a9819e32464b8c54c08866d5a9c7ac4ad3e8179b008ae2469c76241d08642b4211d966f1d76e24b12ddbb44347a23044332886e567262c44f64e877fbc8b1046bbde9decd17141a230807ca6cbc7d647448b0a9fba7c7554321815d685b401d5045e241676846a342e73157c0e3980edd51448c76e6b29750d72eec852f9dafa5d422e6862deb756514962f1a119063109fcca1a794ff7414e2e3fbfac2dc02e4403ac44cf7501c187881b1594923c6451db3e3ea3a447f2f857d162ea3890630cf18b8dd7e68b3c9480340a10918651ec25610789e6c3445f87579971e4dbcb73f8bc65dbbc1e853aee010f2a991abfeb45beab7c0ff52d9d162f143191e886ed8034a36ed97a73f42bde511cd615a8e24402a0f2c3da40f675ebf021b84872a9a77cdbce15e27cd2a87361e252c98bfc7b61b32cda296e2a3951d1ed540f23da6bbf3edd934443a36f217cd8f14b29ca28774b5cf58036bbc9a3189eddccdf205a3c1227c36dcd1a03c301bc25b51b76fb34ab0e87421d83da059f9fafec4f5f688948d8362540421695dd568cbb4d59b05f7787b7c18dd31ddbe878db920d6e4745017b7dc839fa1399429a526b9c8ae57a6ad8c64b2d1afa60f1ea98027f08292708b42055107a55b801be8b869d715010393f688583beade2bdd78ad6e31042193891a0ea49aa1c787b402a7602e40bc72f21272d34de74781d38d2a630413223175e64ccf8585fabdc68600eed2dae1cbc3559817571563658eacbe4e85b3ab14ecb4aa402929c1080e790e7dc20910e7399237a4154a2efc002b96e28968583d0a12eb6a1782f418e38b792423ec75d4040e4e1afd1dc3abea3b765928e1b3b36493c223b8190d04b8693ce21f22da30cbd4fca269ea5a410a4f07a408c6cd76d45d12dbfb07404dcb3af8e78c40e980da5778e3071ecc5acca1fb6e7a059c93a36028827dbcd53a37f529be0ee64d5ade645af13aad8a900bd9db59d7896ddd373733b3c7a7bb63e63a3321f6af22fd12e10ca55c8c50328f2a7d3e3f040c9780b0bae76f2573f63c63f56bcee966ef09051a2d2c19376dcf34397acd375e3e2750d889337603a00193c4b2034e01cc91dc8ade099c66b7369181c343bbab94678264fd6367deeb4a54d7f835ecfe74160d625928acd3f601e42550608418b77303349ba08cc77e7c6287658c8d998b223307f3543efc275e306d95593803f00638c6ef52373dc6e5dd6715e3db3271c663bd5e0941dac38e0c4a08b81f4cb8e41d65682feecc9bed899ddd881f6a2ce95c149dd9b8062a578aec0f496cb3857171c7428af810ef65c513457924903dcdd4f6350b99e99cd111dab5204c9000a024574391647e473952fd9d0a98ca767868c24a55f99490c538b521fccaf44dbbf15b6609ea5a727ec1797b1069fdd569801a6374894c36d625a0ce82d09c632b8e14b1bab856d8292d73031647b67c4b3d8d06c6c8580c8ddc2e30d4e4548a6cc01bc53b1bad0c124f3849b90501402e32ead06aa8a7ef409d73133639fea2ac32916f943bd4a851742112bf5650ccf381da1ffb2496dd5eaf8844203cd9899452447013254e2275340be6614a7555685c71412fddb8c61e33c0497705b265296d970e5b9339e45ea620f21c36907d33672643fb68700fb8b1029ae1777d59e4a234f7cde78a18c155ae123126136448e7d478304713dc31ab5ddc1aab9433ce4458ded9911b0b19f153ebdfd2a447edff472db941295c49d97930cb5127db5e22aac49a6e344f83034b235ffae0ee0702dff76df3f3a0f3214751d1f0fbed7a751069135e9512160e022b905f4b725b2b0abe3c360145e1eb1d770a49e0b3509a23be8a2a71bb994b2deefa5f23742b5b15d31522bf4b04ce4a517ef4a2f287991c8463984defc86df7f36dd9c432ffad4af6559b710a57cb9b440b68a33d4e6e8427055b41899e3cd477797667a44ecd7ea9ae9a9139add1359ea06f487f34c8f6c12a47b58251911c0aa1145ebbb656150d83af5993cb5ab3540d769c38f8464690a843f917d86f4f603d54faa68bdd34b6a4d124d5ee9e8c9b9565e003abf7523587d0f46515a077762f820e8d5d7170a51e2ef211413bb71be8ef3e843332167a4556d76690c98d5a51bce7af19b4a84141c6fb48305ab2f23eab20a51c8201005bbdd93cb3a1c1d66c9e22f3e45a205d4b0f9d453effc65629f51c0f26e3d5449efe22cdf4900a3612114d07352db7b170b31e6a9a46f1fb4041bc2fb174c2abc48df4c190de40d67fc6e1b238d914de7336166098398dc96596564ae7c39011d5c501ecd25964b5a5a98432abae801cfb08db03bdeb270536084ee96919692c8907e790a29ba7e6f3054750af3c6dd415010355f3ff7ca489b32132b54a8e5837d25c690d2f4047a4b039f103db98de9f2b5470117585e629df3ecc101eb20bf6b2899970f9f4048315aea148aeb62b568ce4c8ba77c1c7506e79359a43b82e5c5fef2f5036b4b537a0ddb28cfe3c22e07a966256ea2f2f28e37ad1d765905db49d6610c676323380b090da9e4a2de95b88a661d8f8e7650d9cf4e7d19083cec1547435eaf7f26909b0bdcdd19565e70432df944740d954fe16d75c5bccfcd8ae0c0552b3b5d7aa461f1021dd05830f5d60a829fb01b538f8535bcb06db1c3ff274811ded5d0fcfc1c30dfc1c253f341bc7a085c6510c961166dffed70b1f7edd247e05d8c195bb8287c5391a52a0f0c62c28c6e1a0ddfda3bc4167d3d50e3d950c35e79bf859463376eac5770a99f5a02c95c122c8f8a5cfddbf2cc7a7d0b30098b06bc4a78189b123aab2863b920c1cb6f5e03a955205079605b23785707a2f8f2cae3189badc9d7991a21335ed16ad88e86ab3fc02fba5557d373e3c667e7ca3c35fb001f574f7f08f51829e9a9606ee9bebe1626aa314e9c69fa7d771f1c232c1d10f1b50bdc600976dd906297ac005e4f0d8532cec6f1cbac96f861c0ed6fe799922f582c4baf396d455907ce1574193c7419bc536b9b741dea02937d9595e4e1d1bd335eea7b22b2e61f0f2c485ecf909f810efd3731472343d2a624c9140a073a62c48b51c09310cb1e9328a507072f4442f917dd8e1b2d51d282f3e21a0279a24d1a4425e82163c8aec177cad63f4b14913e3b67babaff56966e50a4892a24060ca015e2973e00415ff609f7416fd67ebf427a6e9637ceb0c0cb14f60dec1d19484d96f2b2505f9a220bc0d483da0f4cc0673556eb6514f70da1c448c41f800eb1f5a4ae7c20c6c1b96892c8680386b8c33f938164815a0cdaa2a48143608862472de63b4751b33c31168f6a2c5a63fb3d56937e412012bf1e1ca59dcad956123ce3559321e4c683c1ea0c3417a3fe1ac005c33b4329cda777242820ce71de2d84fce0881cd4108588ee29d9ca9b18b990de8e8ceb3124d62866c7f70874d67175ba66b84dbcf48a7fb648e17b60966cad953aacce33eea5b9b191e6225ade7a7cad51440e961f283feb71b9161e2222024d9365f0413059220bf9e0462b29ac49162de368ad307070f643d129829a0ebc0c6eb8973f988bc2e4f46502b42ad6a3b5d5bc8df430b4704302d21577b220d506499c67a350d473da4893c8235b446aa0b3a359ab46b249d02afb0d82b2486b533d481c17b1ee5d4b9513367ebf8a99c73ac708eced757d2f2f66e7968237bbfc7099a31667143aeef884d103802c6f72c9b00a21bf345acff82458e7b77f6198b34bf13cae210c820dbc360459e6bbb027c08a9f76cc968804f747f19ac6bafcead3c7d641b4241d081a47d7a1222f1b0b3824aa31b490cdd5b5021be7075485d9cb51cd66e51336de901ce1af602361e8d708358935d599ac313a3b6b40126b2c0d4d6308253336b898a5a47091c1e41407bcfda61931252f3104462e9cf2a31a9c44148d2b5b1c495823418b01b7b50a72bc62eac1a1079fc94ba40559fdacf5ad50c515573339ad48fdd9a4d4e5366a7da3d6510e5570132ae61b6f8f22623bcf57d54b1dd30cc4c9c242c01a0e223fc7db34145fb93556effed7068f0de880cc4bd6e006e95851a0ebba63cafc2872e86abc7cf79922a8b4e16b47b40da727fa261ad09f85fd6173709dbfda40985265ec82b2bb20cbf6eb52dc382fad744456df046d0783f5f873481f6d4950583bdf970e765956f3b88490641d104a66fa81fe86b76cfa4771aaf67505271f9fdbd923866dfe0d9e65f83d538c6cb3a8335fa39d12d216c0eb0bf8c9b07b3e6bca68201a7774a0385554144bba495045a3c58015fb94ccbd6d7903c35443c8333d69695e5cd525f3b2ea00a9d325819e1324fe2900dc9f89305869643904c591ae9023f5d6393c5076a8d2394b35b342493410881b4ca02e34180c2333b0537ea7c7a9f95f2bcb161b6599fafdcb690c84f8d623fb1991eea022d2a78b2ae8f80882c03a985e4dcf55e51af04035887f9dab221c8849cf631ce3818f81aebd9a54356ee2284bce6a614f8415867d312997337e54fcebe093e1a02ff6662347c1c6e63e1960570eb543cb97855930f37fadca0be24de4fb988b954f403e9aff24249d81d21463aaa86ec48dfcab564243c19e6b36b8722e094bb27a1484aa37efbf9114266d039daf5a98349e18664c4c99fc70337e7fb06220076431e67e4bc6dcaf6cd540468b745adf5ce2d9f96ba5cedcdf8868ab8aaa2eb202111545ad10bdb20855225614adbae80aa22aa4224c3511955370a56243d6d51a38fb7a194290964a582ed902290b255a26ddb2044b125a2865b1a465a42c957a166c89164abc5ab534caba65d5d9551ad910213ff5f1d95a0a8c9c89b1bfe366e6876c21ae201fa8fad2bd2d98224c07b50781080ffe29cbcacc6ff7e4614c72e01890ca7a873ab9aaf0ab89eaebaaf0ebad12dd959176f3f5e0df4dcaa620948b04bcb7c65b41730e83c394cca63ba3a7ac96c5b65107104039517eabc2cbf8c529c9a2cd176e82dc857c3ff4b8ac53141bb1a9fc1427ff4a60d6f0fa573f0867d74d4a75626abf691305248caa8b0790172d7683d8a315e8721357d1e3a03ffac10191f4cf7f99e8207cf46a8b8a0eaf27a48ef7e70388d5f86c0f62fa878fe885198699aa7ec628c20f98852ae669f3fe82ed1e5d93c06c70309fae5710d3826861095a20b5d518181e17b5e43b4bd2914337d3212faf90110539a405a3fab62da204b5cf1229d4b371194c51569029372e08503d15f4fc4a93c0159a4404316eb7a95d145b510137728f453e89d4ca54ff5f45902ff87c6167cde15149babea6cabf950ddc98205a01fe10cbe812edd177e48b34b5703ffe7221c735fcf5c1c136f9c2f6f3bd8dcbcd037bc952beb8dfa87226f852be40147ccc88e56a4a69f22bcf53878d9a75d197f20551f3237d4b8eaa209fd3e26fad57448deee4219049f922cdc8e0a7a560a5b17c71ffcfd2679b1a7f90b7dc6f8541d4f2c39be35ce7e44fb0e2ec3ebce1089d877e5e51fd18aedb0db297d7d74762f736822585c2c08b2960720bf7762248b6749f2ee4f95609ee2bb0c2df4a055d24b050c06c9186b713b4fc0cd802758e0e703feda4ff75d140171adc0f6a387b0f94377f0a4afbee6786deaf83de4443a3ddaa6d03ba1689c9041666b6f2a2320d9d0f1a789f34d8dd2d71fdddbe84eb74bba5bcaecb2ffd5a879b0cbd5eb38b2bf5c5d88dc685da05d6d1c3e2d817fd6a40ea08167122f160ff8946dd9cd27afd0e2c7da6a714bb6b6cd75ad289f1fdb18125d23b7169c650b6b4d21fe865445fc120c27e47e186e68d01a4d5f17f3fa1377b7357bc10314c7ccb927135dc015290d159bf73761c7b0ad28c5eba1975bc6085ddd7b9e2fc758ea1142f3a583c894830c627402f4e39a29759d6bc54d426cabf990dd44b7edd0a28a80ebab84f797904201dc5ac914580c1a09b6f1f11332d81911eefc07258e0ca0c83f784c0d3cd7ab1cc16e858298759bc7837cfa43120227ba7122f09188f65d4b76857624f7022c647a81dfc6d351b403e05b7aca3f7f646719a937bf11f6d985662e51bc22b7da00c5e985fb0291dd6dc39abd3be1adf47aa54f12147549a4c6e3068e1c0090e47a6d8ec41ec17f113bd976a24f2d647c076d09f68815c42e3484f68d2b5ab65a73e4ef6bee198e634176d9b28733c1272d4a740178ed0d232207af4e1d2f93a7ea4a9f12d3803c2fe062d79d83d5211475e28d85cfe3cda11fb4eaafb124e871b319eff69b12d5aaf88c4d9bb6315632ca78a4575f2b48bba79beb6b13e291e63fba482849c50b00544afae023313864e62fc4ea908d9583b7908f163e54bd19e0f4fa7a14cb3e9a2d18b7961c11c01f3a25ff929cfa7212ceb11364e3f0acabc063b58976e7562831e089e30427674fa9ccbc867b7e133d28e2f134424c85ed867ecf2c7f3ff2cf90dabeda65b55b76b07db752b6267e03eecd6462c33c4b8029fbf6215821a7abd4de2204f5a3eaa117a2ad7b1ea0e79831bc25778a5197f7942d5ff2671fca740f95013ceabe50b97f4538ab6cc3bcdd053c3f1f3e9993accb273a54ce6fc170d97b84573035e69cd12e4734a7a52b15675eac1508da21e041a8cd5bd24bed9ee9e15dc94d0817d6491e4fbc6fa5c903845ddfdddc2f011a3e52b15c67cbe464691d6af13bc28f9f8250300666e68098ad8eb15aa7d511750532cde422918b3512e172b019bcc0a43bfb2c9b33c051a3bddc21b09f0e5ea3fc9f4d2de8c9f6902c2b85001d13c48fbefcdb5e1a6b1143c11fe8e122e7a1a4aaa57af09fdb336157c6e2309e8133684df8d12349d6578d3dd2fc52ab190a0a1dac99939ed1134d2249d73993903f64d7310271893b2c226eecee57e3f62549464ed5aa5071089cc924d12dab0d69e85b4adcfc0a49ce2b592de8e15fc878adc01ca3d68687398e4423a1a38386cd6837dcbc019eaa8ce61e600487f5af55186b8c8fa00111500b400d24600a502429912e9f32cb402c35c40e5b5f2c5feea08602a70fce931ec6106cfe334349d62848bc87248016a98fedae2a2b0214c53ac16340a30da41b1caa385aacd499ece836ceb7debe8b00936f89a148edb2c31640e7c63d59098b88dadfc9203614eda59189451e31641016e5871c39b737d0c03b62ac2df2261e6f9e1c798f0e5904126b9b3c4924d54f483bd195c65a2255c5deb4bd741a6b7332fe1c3de73fb8ea8b94080a8d665a2a4b38814df9f1e2f456916adf7b0358463f778c06f3d658b0ddc2bbafe40a681766c0f2a7fbae695f30ef2dd3edcdcb9bc8271865ff5f38bede45aa47998279ca619a5010a09250ffa1b50a30fca8c4c1cb4bb60beb325c68a604839f847387d3b4a0099b129fc7c9b8d87291703cfa0c196c41f6be95cfc9278558d5542e80cded0c9912f236837061faf936ed9a98c7ca772e53a109697e68993bea9df3cab5c834120bff104713cfc40925eacca76d1a08ff0bdcc7e9f0997961a3e07f994252296df7d140db8ec92fdbb0d83e6cbea5c638d2558ffad0e246354c7477f208f72f5406d51f55e90f5a6cc8aa8e46dcb030a93b3036beddd7da38b3f4b95f0ab625a351057bbcaadd20af0e10d5804426cda732971ac7a27cacaef8863f9d45c50ff9c7eb3243677480954a8abb48f2b5754fdb8950276c3f866bb4b014844c389b55165146e34425e822b99fbfe22c7701db0a0b39efce81ef768c404614a2436eee8fe0a5c7e923e1bdfdfbfc058013325ac5ef226a29e90095ee3e5705a7dda75aba1152ecb0668588a848a03d60e83ede1edf660b2b9d5ae2415d5e1c038b76d41dfd670ba8bf82903f0d058894d0f22a7a6a49d090bb2f7e17b42fff0f63fccbd1423f14c454faaf3056a5cd1edc6747525285f8ffd6b79e008bbe0d3cea8d6e49fdd247e3fb62212fca51d34aabe15c3f2591adbe527b4b7c4f09763c5adc4513ae60bc1c81ad62c4945102b3516984356f0d9865713f20a6b40e4b95714d05fbcc8a7ff9c0ebe197503545fd13cb153d722682392d3c6adb898899b27b5b7fb48c486df23768d69f8f916b709b48045e0b667261def336e396e93fa79bd44e6c0360a7f688111d4ed98cc25d639dc68045da7f72e14fb81fbbe73b725e61e9304ee3b1b364f3c88c848ee29bb67cda3f46004cb32f2751d506290301e6495b33e6f2031f2c36625a6635f776304b99327b36c94db1219dd89c0103988582d14acdbb74419a83bc978e9c19e3aa27d734ae54371e3b2f10658a2cfdd85824a24bb45d36e8001faaabf68d3e684dc1d6d2f94f0b5172a6e5e639ebd508cc990f3c789ca848f8718a961479fea8c92dd6602014f76841ad81160180c3430f3430d62611c46a388de627a918c7e34beda7358b924fe8296b9d56c1417642b833ab167a6b64e7782ea0a27af91c5333be03fca0e0173948aa3bce213271388908aaa2f3d4cd75e189a89821f15d80be2c0d9d3cd78404980eea0ee43ea80785f405c71204bf131975a305c247e4edfe23301baadcbb18e032d525d9d6f83756052675d7f84e81facbd2dc09076811d2ba09d9c7b52c89e3076aa98d5e8ee57da1488eded107d2c4c79760875efb7a2bdf57400da9b40f5b04aa29c72f0f5dfe65fdfc9fdc0459b6e96271b0f4a7a9ba81f79ee655266b99205c75c9d5f08ab54128264bb0f82f638b6409095b1d51448f964c566928a350cd4fad14c5753020c567ca22aafc46f3d23934e3bb66a89b35fb83c7d6d0f8b7dd4755a05817560ed248657a6e65a46ed58ff99dbc54e689e5f6cc4a53f2da44973557628210f44c2197fa80ff472e1009573bcd7b117498c5daf3e6fe77fc21921038869d9619841f51cff8fbdd897b541d9824a11425a6b9182624403f5151ab5583821e763c9ed21896aed18e0133bef87ac8b5b81182d5b2ec51e19f0a7cf22283db6d3668e0005d5b62c77ca9a8205cb5be9160a391de6e71d79f94e3ec978522c9139eed23b164c4633980b40bade10479cf8676ff79ade2be3536a9466a6bf56a3a524af4f8a402bfb8dd7a677ecdd84643bdd8723c51de7a916f57ce25c59cddb91a61b36334060b8e513c619a03746801ce3433dbadb045ca64aab542300bcb727e0291c25f3031e80ee79ef74ce0bc1389f7b7bbbe7199e83281979eb2330c11d25fecc71d4c2a3235083a356952f9030f084bbe7c1fb19d19ac3517052c30378bc95a819b8e7d5852e3a7b4e10f02483acfa9dcc531d45f837c43defe8f77aa0b59f87063c87a313a1349389ed9f3f9dd772d1bf36952809a8055170b3597b189201cd1f6908b8067805e8d5d6baa7c02bd77e9721f2366f5e6f0e83b2a4c7fadba5a5f54ec811e7730ff47eac670837aff8a278eac0d3168223d246ef77150624730553665a32f04ab525082ca99b70b66fa7dc785b6864deeb1fbf1e1a6e24201d68748f65cf6f32896a3f38cf008c859e1ab880949804015511f1162128da001c077ceada219beaaf6d0731461bfa95f40759965b4be660eac37cc5c14c8c96cf8fd6ff9fe916561dc1f3615963003a769a99ba4d5a2f3c097d2014ad3a81cfc30299ec4ca20ee99a3468e23c1191d366549992163dc73b19df5ea61492d921352dc6cfd31952242c308d565c0377fc493fced90c81903c6c46a1987f4521243e88f9874e40b61b205630aa4cb6682e994eaa7bb126d0ff4ea57f6bdfff4ef5e804703b8bd895a119cf136c0f5f0da73215ec2c4868ff86c32bbc81c84c70429d5039eec403c08bd106b2bea84e6fa90a349052bfa3c05b7e52d5d0b305be2c601b0d48915c3656b6cccc8044635dfbbe5c2071a362416ba1193562202a8e68786bd5241b7ef1c48855f217b592d98c7d1309d09444c241b25012cd8e237feef71a9164a064544e3f01f964c814cb871ebb73214428b382542382b6f7dfb1747a3d2cd0589a49d8088d026ef4a2a2688ba12d3d1371a6d9ba5e20f27337c018f6c5478007b1993bafe1938d952c4f8fd16bb31fa2521773dcace24913f21947b810950d7f8f30aa7695642907c39ff65d7a57946622e3ca6085aaf4243eff56a6872b1f648793d6ab07f476fe8810473865134dce8f4272d401a524101a6e9bcd8a7633ac1a3cb7ae3cadba2c27555d125e5722f30d592bbd13ddae25f2215c0a726e78d91254489f035659bfe3f465be402645e90d1e1867a719686fb8f1529b93509f3d7f90f650067c6817bb13edd9a6483ac1ce7377d67b70cf6b4c8177f45056cf218caf7b5e0f12aef8c8a163af7c4064f028e6039d1fce910cbe9049a8fca557daac28e4ae974918cb29b2ab5ae8b8f26a2d42abe865126ca220b1dee7f3d12ea3342e413a8cb6153b8e183c3cbb24703aa0b946dd6349a3ad5e90ea1e04c4ae1f83268e2c3df54f902591001b3e77c5fd56e7bb881db68025a46017ceaf9dfa14f67067618b43c4fa0a71926a93cbcd7cbcf0d198837edad214e44fea1c622b512464e75ced8d5ea5f67512a6a7f1713c335522409c9532cd8e7e33134cb8a96430b0e8268e30af871087c40cfc5124f5fdeb89cdc66e0868868a2764e214ccee63a028c65710958527cd6ddeac22bb0c4eda46749a378f75c142964fb68fa158ec051acb4a22d67bbe4ffe8f8a96887cf2e32c17dd42d675ccb61dae399de15c7fb843c6a103e98d3070a69fdaf7f3fc8b5c215e3cded13b76e06b2f5d667fd484d630901d4018c7fdca61f3d77942fe00523023b8ba92c2a9c1343e5570c18abc46cd1edd35db4f06a06604b8987a3200d309bb059442ff86587204a8d07b8e3e2af2af8beae4a5f839550ffdd89a71864f1390d6894825af5d6aa4be52417ea4bf427a201a52b387e128d28119370bbb7f0fbb7b236c9bbb2a91c9961489ce673949ec252f6d05cee65ef4fbfa07e30a75b680896abd435f699365e094d62e910ec9a48eff198ea73f698fe49f1a65d71bcd9c90ccc7439800b3e06d58e1f3a7e0b415f39f050f22787af155dd25c49cb583007d6de8f13543ac99d8f1d71bd7c9a4b898c14b05c0931e932d75faf47ae0944489d162606e93e020a8c11f3709b59c955609af8230af3c6cc21d06e486f1708ecb1c244cc8dec33bdd8bbe25f415f94dd84e99581f0a74b6ab4d6a517960979dcd040f01ff6401f259c2e4931b7312fc2680774b1fb71d35b5e747cbc56e6ff16dcab4a618e74ebf7cbd697c68d2f52a4bf13ac0191258432005f3ba4b4aedd5f6c00bba58ddc386a2e524ceaed726d98d63ca587a68402631615052f16484357a3cb68106cf7758544e11eeb4e0eeca346587a3acada02e7c50e06e0569c2761c9095ac6a10f0e7cef03314082087454256a4b9eee28aafbdce9c730f8b0bd5076c49a45e6e0ec86c302085bd40e1d9e5a955ae9355fb7b72859195b56e98cad4ce2a82b23d432defe13a68191b0982e8a46b9ddb97893814503d8c6fb896be68df3d57fd6585e53e1de0c63ed85d0c48af89575d68fcf4360b617917bd72eadcde755db93f400702bab1cb715fbb90abfa9b51ed9ada586fb4fcef33d727479aaca437fb8a77e5a00c6d5396c817226c7151d25f70a0f6fb7fe98632eb33ec135769ac7a0fb594901fe72cea0ffa8b604812c554d3f0157b0ae4c01e40fe82354702f2cade9865ec6e5f9e8b9a08cfac6967a24931a194e82455781999cde1ff4e41884881c1682b67d117eadc41b155715be6da1800066f30fdb6da4a3bd85ad3b03d7d2c13a32ef19f540c893045fdba5a5bc44b55a1a38a156132bc1dc20751b7a0b2cd5dd94448690bab39d71c56b3a4bb492c8355f5e2a57c1e962b0e133d2ab29ecc0ccf3e9d760e8882ea2ce7981dec8b9d50b7ed0f3cf45699a01978ec18682004bd1b51e11a9ac2f34ec8a9de5a991c10d388bd023885d4259d969011db8a352a2766ea07fd272fdfc2e72e8001eb026eb8dbfc42971925e074e26e6385b7e1ce9dc2864cb7348da204e70da1e2c94b4141bb4a211a12f02b44fc4f0d0fb40e650a9ab38d133d71295a9996c33e03c20ba4c7372b19e8029f4b25f0af54c8b80162118e2db5140b79dee4f859d940d7e849dc5ad8e9bfb40a47faf567c318443ab999a096c879e5f594327f6f5b499300930e9d233f82bda2f89bddf3ea5a5d5203290a8abae3e2fc02bf94a60eccdfa803f8dcad4cf0eac8eca70740e7fe4c509245d22d87591cd23121c84405c6eecfb47455d93af4c02fc7757f86106e489b735124474fdb67beaebb685ec4126685337e9437a9fc99e6562783f067d40af4d6436fc3a9a566e1a997488c20adbbd284fe014f80c8968f732f479c94443ba0e9bc1f4e5cb142c3754a835d5e6ba3dd54c1337d83d88a0f9938c96b64b50d9fa5b7b86081aa8b04a66a166dfdc946ab6ffcdd00dffba5300263b19e6e4133b8428a4472da6ca4150f822e4a157ac79233e4ded599b286f3559234e4d0e22f7efadb09426c78ab8a175afe1afde9884ec6da58cd86d6e9db8ae52a9a131e6df63fbe51351a0f19034a2adaec30fcf2650503c4b4c521970d87198b9ef5a04d0f2cdc637d17d1123c4fad2239dc281cfd3f2a0ccdd94431a810d0f80ccd6dfa3e8555a9917badacb5a020071fbd4598101fc23bd0597ba4fe13fa13f708fe241fc387971207f1ed4d2a0ea88f68a5f452f5518eb124ea08f73a002f0e878e06052cb6d1450442de903c9b5f28480bd5a1893f29344667c2c315bd26a22100cea7b434f3dd779876e2a3fb68d8041afd7d690e2ffad8464e953b01fa0b0250b1fb177c472fb50319dc32cc2f0149727071b17de60c7e0af5d8851c9d879d8de83af0a247e5fcfdf2e00a7e33cfc573d21affa851c2cd7d5291d56c7a1aa91562fdf6dfb750932b7448cd5a777729797cc07670784789569a84cd861d387381cab660774543c2e97d546029142b7c6bc39ed6e8352fd8edeb8cf8bce91582f75fd6729ab5d841b44f029c5cf25ad71038299106942e87bf752d97caa8a194ae89b56b28ec4aa400a5dbe58f5dcbb5326b28a96b62ef1a2a5b6baf511f9da9fc8c20cdbb66c6eb63f0945d776037e5670ff82599bc5c8eaac8533d5eab5ea90fe4ae76ce7c2cbc089eb698adddb6f000065e29784d0c1d71d0a3e68d690f10f2d9f21a9dc6b655bbce8bdf84be6bebd593e4daaf596714ddfb27b030d3f7911f4694379f79b1dda7f6327e9f1e4bd6f3479afd8ba690ab23106e17a282daf556ee1e12dde2934d13146e4e29924e086bf32ef9c88a846d75e1562ab9fb71a9601222e0271b7fd3cd4e73e61c5f4e680493886bf873aee90f0acf2a0c3a6492ea0ddfeccffd0b76c4924b5bbbded6407d37a28f00901482e5d8181d9a128204ccbb2fab41be7168486d798ee6dc46d78039a6c192bf71e21670a6e4ccd3aaa979816245a8f3744f3938cd2bd6e0d7bbe6fd964e1ee737cce11169f46f726b6f1f04b8df62dbd956f464faf4fe5279526fdd6e8347c9f258f22d40677c56b00f9890b75fffb73605237bab824a64e851fd41731f33922d0efffda0b7c95e814df6e88aebe8cc264710b28236dd69c81429dac2846ca993938d69d64cc7f5499726237bcaa9b0d4e41b9e1d0d81139432e1851d046b4aa69699515bce6af2d177eb2fae80c6f0efd74a9205b2603ea0625eec6d653bd20cabb216786bd6bca5c14d85711d773cbfe3699778652b039528a2c59767b13f9f056bf4ef11581ab991d2f15e464587e49c142ea4a0ea569d5ca01789bfe98925cd79600c505f97662708ad5908b2150448f28215dfa299f688aaa0c56c01160b86eb66b7f82113dba8b234bac1c9fb2ba109f223701b139099375e199a6de0cc5e956905ff31498a0966661ba98c6636386b8fd62a2f08c56491b1b9f2fea09ab8f8358a29c2ed72e4bc039ccc323738dbc57502030437e6b7bd85a8d44d44fde3381b21a9720f02f00a0835c2d655e71c06b039fa487ff765eeef8885e8ee767f9a5b0bff2dbfca3ec05469e9adfcc5ece7b480da20ef6143600754a7fc19567c1f1de50d552d0d65497c7d8a6f6c939e0516a827b28c7e8cf21471cd64429355d8c72d2c14fadfd5a57d9bc5f1f4b7b1397f09cae4bb11527f77fb8e28abfede38f515331025659038f3224ca6b43a1c09a5ee9c87979db64866b329dbfedaa9413f3094f8d36a176d4e3028fdc1e23c99e961bfbfa83e1354cab4f2141a4ec230ca6873610132cc37e6a7bdc5cce4e7383a2d5b35412a7923e65f2df613b141f937b515b2a72baffc94e4123f67fa63b7711f3a877d267bd4c1381dc48334cd11247c1a77f4a19e7c30d4981b042d70944c5b0d85eb4da5fe1e761c910e26be1baf4541536b4be1f82b29245ffd776b405598983ece9c5d4b8a115ab53a41222b249c2a070d84ced79eaec9734bfb30c5698c848ebe9b33d7d1c2b21dc5692299a32900cbb8d9d42f2df399f5ce028914c22728338fee36e78d730da9be6b06db5bceecba52735a6d7ed160d00cef1cbeb6249ecae6bc7e59ab5b974d5e8fcbd04404104c20b41f2104121206017e141edc00dbfb855de1c82b9bcf0963e4833e2ce3fb434f4bde7d5b496b38d013d625bacbe94b326e7fd1bfd1528dcd5248ae32ae4979dd2b8c97f04c4738972d6bf046f3dfdb4f006a780e3b5c4e86b7de6ab807a62982616f2cfc8f0f2e4bb16dcb3989406a41c8cbbf39fff13e10812d294f3a936ee31004f1020e3ed0d5f46484295bd04335ac9e011b08ad9401c428bb45b1979d3d18adcb4678e20f561d6a3ba09301610eb0697bc44138dd4c8f9d9e0df91be4e3044e0040bf0a0643523d4524d5662ea894fe9ccc0f9a2a7e4d12cfdbaced5854cae14c47e9a9ab48aade4f3c711baf36e6408e336775f326da8e0002c37c0a3ea5d066c4370e2155797dcdebd5df5d9106deceb16ffbf555d40e9e081c1109b2bd2ed3767330442b3e9e3ab0e473da3b23c555a2839a0482e662f501c277be3b14333e3eb319e2aca36bc6e16cf4db9d894d30950dae4fcd5f06a555a1dedf54ac723595788c2941867c7fd7c05c209dc3b76769f0fbe4ebeb2355307269a5c5274d5071fdf116d8e38191ecba018df863cc127e4b93fc1d27170ea313518449a98ee9d0e239b7926f8921e25f74e2c560507c27db738d38d253d5ab91cef5c8362d351e4cbea6668cd4b0f941927c0e391d1b3139283d0e4a152be7264f7834283734bec585506ea0741df52a9746ba91fbf063059fd3fa75cc17005f94ae67458ebca61e9671fd741c0105ba3109e17a548e204c8178a62e6dea67de1678d892b100f874cfce132e457ca31e2eb95cd41377873d0828bc4f01c9717440aba7ba1d7b84a19648270395ce77aa6b8c3173ec8f15ff10ddd2912763b8691e5e9b3c39ba90f2434c1f8dcf3df4e06767a3eebb983e6619e54777a60b95d7a5cf2d8d1cd41b79d3678237d1f9c07649437b616cdd365fd62c1d1e1104a32feaab490f42ec234a16eb342af04d6b5ffe8d52b5a02922edd55423f79e31f0c136980e079a2dc8425c24c84e24e7f0f3281cb59f4d212a5be7338e7e1dc2b0e422e519c5f49ec46d82a62b22a413fe75abf48baea241a96e0c8890978e586c11bce85ae44db78c6b78a6290667a515a08285c5cc9c922f1b2bd1e4c836071fac897ff4ca6d55ca447f1c453fd9267214bf77f5a7583b9d38f6a3273818a8c2e492717035cd55292dfb70d139fb9f5c83b41cf4900f11d4171dd34a82a379d04d8d355adbd1523a50408b0a0cb580d8be01647ba3f1f64164b6d0a181ea5bbcb57361c3301de96b96397a2c2c30ac1e41109ee2dbcce7c0c03c09f82fcf44b57b44c439ced851acfa9598bfc1fa9abc5e5c74bab82730eb3e8f69c15399c88a8c541639f09c13910e5fba36a1ba8bcf089587066a9d3653e8859c85c9845162d7b3cf6876bd808027369111928dd22de4592e230da4b8ce8d4624eb6d043fa19d2c91da92c442c6f232352e490e423de5b379c2ce7cc22ac5cf93d6991ec9bd995a3900f78766ebd9301acf84296d15b278e41465b4174f79d3e96fc3315353715ae1924105a597c389664750f52e98ca9a62d3d94e0017ce36c233632fcb73a57ecab49176e9684568b0b4139d251676924228db7a4559605e7ad83cff495583c2dd360b7284d84644b0cd81bd1ddd8d9064a9fd70746e782e730d8c86adab04aa5ed6f6085c282f88640bc5b429f21000371fa336fff832112eba4f0d47206009e8ac51c626c6c6f518e137e4650ffea8e2ab29f32503f52f185c0e9887b6b7aedaeb68f0b1113bb5eb22fef30d7cf714d78ec601e94aa82498e2b1a6a0f0e22da6503c70896011e26e446619c05e3946bd4c16d14d57932dd105fe02f98d06c4cc4ae858acbf42350c69ce26229d58e3de0ee9ca69d22cd0a0e54fa6ca3fff1a3fb6484798e2f3458a12b78720fde346748b6e931d76e2320b1c83f5b85b61fd5b3a9bc2c97868f72b9e2945b2862aa95feaba75cf2f51857982e9ef5fbc86699a76583042f93d5d5d7a393eef5f458b06ab418f77760831cf8c9767eb8ce7b0648096e8c2c4eaed8e516714014a3581909be9133053ce0087860f87b2ff88686124002351fa2f4273b76d51ea990a58aceb3ca66f77bab7eab87c7ec85ebf54c561340a3532406fd91327c2854a8ed1048a94636c41c93c154c3a585f92a91ec2d4140bb61eda97a2663632e38547a372a79b8e0888c96e3e425998d9663b4db0d31807844d16c394a9e8a9daf1baa583a862400ff84c24861f41027a39075c6dbb90300523e9e3a1a237eee383db8b263adeea0e2ab0c1fcea39583d86f754c8a0476cf9899ebcb8086ec0c403e5cbc513427c52cfecb146effdb2836205d72893e1d52c0f254f000598a8f33b0a28e80892f80431ee239e2a3d296d55f4076511e838b01eca17e73bda47ea761b8e04d03466c609a5a4b1d23a9b07800aeaf4bb8b0d2c74e828423eb8a7d1a553047e5906eaa99e55e6efe89ec6007e899c711e3dd7a727c354d76225e4dd83abb9c76902cce71a26565874378fbe411300489b0b134b314df7c314885de89f71b9867c497e149f530a6e552d43d11f40acae6baa6cb04131c004ae3cd13c42822df48ad3a28c9e6100af49fc9ae715662eff6e11dc1e183da76bd9ec0190ec5818885ef42cff5dc02459a957541c558e96d4c0507c97a4ba121e7c4f980b41559bbc07a8bd89e7f62e89fce559ae03fab04a6864e3bba422c602cfeb479a90e359765d13c4c37a9e08f306cc128de9300279e589dbda1d0bfc5024db15d70ee399d23191e4dbf12e35e660a4577b009017b4f8a0ef18c883ebf500f4908c49aaf28241f17e79480f40df78a79b0720ac014d8b4b04d403002f38fc3c76d1b84fc7e209305e6e257e7a00d80b76cc3ce6b4ae2ea86510ebffc3171bf3b49556770ae3794b4dd15b7f550ccde5615eb5a588566360e4c81acb1ccb751645e06d30d8cbc35cfd8222001561576f996e442a1a88931584d462cc7ff6c0a2b334e6e221e32232dcc285781aa9cc403d6c89573d5f42d7d8a841ea00f49fb8b40c42e880dcbc0ec981f5d800f047d9a4056f21f8e005f05373e78ad424a8baf09cc2b7cfdc34c5138ea580f5fa0d628aba1e5c009b1a075762d8453b6031050edeab0e6828ec61329ae033b81bba36f208225206f31fc3e100c84668c54649a4c7628ca9f010692f3d6363b1ddd87088899b218072697ad7dbfb8408f058c3478c73b288005b509cbc2143d9dd802bba787e15d6e3567d9251ca25d457cd2f2ef5622fbfbc60764d3fd9271384e8d43646675ac633bed94d0c9fb77090d9b0d429fc905118d4b1e440938b102714905d476cb78cdbd23d8745e746749d4834acf218c16b42cab5129eef3734570d35f73760308c2bfdc5fa7ecd3b187614c57d751b583092ccef0737a5300393fcabd375bf9c6b040bca8f39d07ae260ab9a87394097ea9bfab342069b735f0016b6aa72d3717c934cea3ae03056730b0ffe7441572a599e2c2c0823df53876168539860fced00049e60bbb65128b71e541a8e30fddb06468bf46ef0be1a572ff9c4b4d8b5dc3afed3af4286fe92d2c18fe20605328e0f4fb7337395348ee30f62ce53ea0a33c9a037bef66e65ab80811e2a62119f8ba239cccd615af4799ad9562888b9bc9e942e4a5f187b268be660690e013677746c18049a3e13a35a309a554d07b941e8bd21df8c6377325e617346ddebd0473acf72e4469eabeb344a0bdc3a2ca445c09957b0f538f05100240ce1004c4390c3b0e2c11c86c219cf8a094c74143fdb8ba8bcde8f2e892baded2df7965b4a29934c01440ae809f509403f463cc76b9c26497cb978706e820892030e312f0dd30ff4632467d64c9a242f178fc461b2240848c7880ff11aa224485c0dd3df8a384204a1430e0dd36f237e3eb7fb9bad89d3848950d0111d6923872821ea4152c45bce6a3224b473241289363ef490001bc0963fd900c76fd22177b32165d7dc1b5d4ae076043de6a5472ae720c1197d34c3161eb1a56b74083818a510ae1b9193e53fc96628151e9fe5e4228dd4adc8f2db73d5400656c8a97d6a653fb39f2508cad94fcacd4c9bddd09823c10f511996a39083524788d658a9436f867c456b64ca7960d97ef4a646ae280ebda136d927773e7984c69b486fe4a4377276a1d459a275e3466f5c85e3aaf932ed239bd4ab459815ee290638bbd6b4f5aadb763cbda0bbbbbb4f36c0dd353e2b709d9ad066706a42a30115a24d5a482ad1109d208c098ecb26a93102942d6919cffea72a905edd137c64a024b71072fbc82027dfd30b707cbb040ee3d0500bc7a01c3f9c39ac4cb03c5d7c802b93daa43271150d4d398c4339ac4c8064ca7fa31f905cc5978c42d9bf850cf0eca1ec6fc150440888a0b92fefcb4b048e2fb1ed668f42b3c2bd7cfb2bdce7037cc71edb30ec62d9f760bb7daa3d86611ae51420ffae681fbf7b481f60d65efbc0062266ed7bc1c17e2d5d8a806b09e6b700825d991f7f9b367cc9f1c196a1374a72fc76cd163bc021aa68663ecb5bcf934edb8207f84f57c0e1ccc1c1188410b532676cdc68192031cb2f86c5734b3a3dd085ede3f69109446cf2f6b108eccd7d98e556711902a68f12021c7eae2ba38fef03ccf1fe4beefbd7be6fdbb13898fd7ca97daddf02b6ccfd9a6a1920b128be02e26f7785eb117ffb56eee703ccf7ef075e2062bedf0b0e0e7eb35d8a80e94fac1ef161c111fbf6552df6fb115b4ca2d001cbbb420a9612aaf88144a1dc7d73cfe420f5f77944a3e26fd8628bc29de95ba795da9a5afb0bdbd58d7b7a9bfd6a95544cacb11d723736e7fc2d7a262f08c56aa4af1bff46af87cca20ca110267872ffb5c01432d02403f103f7186374018c4221391992fe5142f6221465dfd15fc0425b8127fb4741892ac660851ff49091ec4ee8287ad04950423b010a5588a17b581fc841a4101f545180281440049462a3b0071196e8244451238aec5fc8fedf1460c800f4428b21a2e8520023060d05eb0339889bb27fe1058266cc28f421081d0a545564bf4ab295c2a5360a33008451a126c183ae60070195886d42f6778e872c32e59c53ca39a59473c6284661963cc88e0092ab874cf6ef85c888c5e0b250261d9ab3010437b8dd12ca56ae7fad033950bd1f516db7e844ab02d060b50d7483dcdfc3c40d25727f4c810e10f81d5c957df7fd3cc8d50c2fbe617cfff7479b96297d7f2c41e3387d7f3c41ab4ceff252034acaa3381e64aaaab8f8fefefe7fbfd7f33e7a9ee7cd78dbdf90ab206e729a0913263739dee679a79aeb9dbcca7b2ffe8567ffda7f138ae562d76ed7dbbe39cd73780edfb66dfbe672b8e566b6f7fe865cc51d21c9835c452299aa376e44212122a2ed4f45e08c6a99307a9ee71b37cff3fcc3f6590a0af6fd70379bcdf33c6a52cc176fd7f3e679be27dbd52e6733b2b1d9b6cea6b499b818bf79318fba185eca3b3783b2f257e5c5b7a71d7159b6eba55cde721b4fd5771751884261dcad9dfa396822f711cdc5d0627cdf1131bc3ec9ed930311e4185e6798ffbcce563b8223030d526e1f1c70216f334a47e09adb0707444062ea3f8e87672fe58313530e8ee4cd6b0ff4623671f73bed9880c40cfeb5db0bef4eedb483795170a0a3a160daa6e2dda0134f0a96b71d3705e56e27de75b94e4fa0badc3e39c041d9eef57c090de3ad18a81800f862005199b97d9af84009c68b3a5c3c1792a9fa2f5e1154c62d20ea80f9db621b6d9c776d64fdde060806d7d36cb0cd9bd7397bef3e8d6f59a1f197b4cdf062669101cb880312f38cbf7893e1c5ecc20577bf1311d8fe06246619f2030d535fd238c86a982d6017fa13200f0a6cdf6472d06b1ccc34cff30c7a4dc3eb3cc3eb2cc3ebdce28538b78e185e68f3e7fd303514cf2b799e814e53e0d06b6a868c36cffbebd97fefb672e42a327149148a49abd66fe9baa18179225e87cbbfb83c11afe3e56f9f743e0a3d90bdf7b47ceac17b59b6271ec0f05ca8b4bdb0f94653fb28047a71c485e72c9e0f79fe6ae17912d3a682e5e67894b0cf81543c0ffa012ac573a29a1be5737864c2caf54d289f9f782720b464fd93e74c8835ea9ba8e7d2275972e542a117a150f64b69941c18cf859c00f55fbc7602849e24d777f17cc85375e68bb29d781ee460fdc8f188b9c80c9e3391a9fa9de74b1cac24cf479e2771c9950779aa7ef5a19e5cffa26cf77a1a12b87d90d0c9ed83835796f9a2b6eb71ef1c0f2f72b0c2009b1cac8fc2840cb08a12036cdf6d1cacefb97233be8486a98f710ed430f54f3ac0a1dbe45adf6d9c882905d532f70b85e4eb9d6870fbd480480ea512b9eee831642ab2f6d8820ed6bfde8b8335cbacdf4fc9f7c3321b65abc501b0c4555312f1944f205729c9fe84ec3f837c157578fb908027fbcf1f57f273420287d226fb9c14932c4cd839ad15b6e89a4b8a42e9923644aea4f1260efa4b96a4d9c9e1ecb1e971d04980dddf8b3a4796acac2ed860c88cdc3e4d0c91df5571092b4b6e6af76ea6abfd46295e7d11388c45f78b7c85996c9b83b188c6a28691119372f8b55a70a28bf42042117de4aa81f0cb9367e5a083ab482fe507c9de564986a8d3322c1df26d90ab963ab6bb6d1f1033dfff414d736be2031309d28acd8aad0ab80a2c5681755af82f57a59727130a0a75c218bc31f7c6fde85fee352ffe9dde8917c60c44cd618ebc7d416a1e8d3e878fbef39af64b4713a347228af973227f4e8c3c91e7db0f65a273ca497aea85416ade9efbe666eee7f0edd35879b284980015f510b95e3d9f4e2a9427f7d423fd26441e8d3c20921484e6d19346dc6c574d1be4f976447532a519e461a4c8365bfc0faa791f0b774b9e10584749fefc1cfe82c34f12c6971f99c855e981f290b4268fa60927e49247d3c47ca17cbd20335fd3fd5866de5a667b3aef634fbfb087987cb5d9afee69d70d940f631a28d30663e677af4aa63f859fa9c92b79148bb95acac403313a9aa89f7590fad8d864faf64319c12cac19a240821b1f2796e4f619d224d7c8ed73c490cc6a1952f32c38070d3b744f187be28f83de6a7991233baeea57c52ffec4d8e3a047240de32fe394919e4480c3f88a929563be733b0dc1617c05754f60cff1389423764f8ef185638c31f125c65eb275e2adce5bd85b3c9dea4cfa4224236ffd70deda5a7fbff0c66b5f1883f2d9ef957bd8a048a73a635ffd7ad8e048a750d9450a7c73fb3881853ce32205e672fb383194e5dfd933ca5198816ca5e738e8ad22dc8cb7ac121cc6577c7964cdcececa12a3e4e6f2c1551d847c9d2ce1f692244e0629653683a0930864a4942d658b9311fef4fb4a795f5e2977224fa6199594daeeb7dd51c77e4b22447294a110e7f17f56b618197238e77497534a293777776f28b894d2871f262b0311e20359e0fe4e22c0f1e54b77f7b7c35919882c03cb9d95a9c8617bb7381981a7bbd7a0094996f41832a461543d86d434d8d93ffa2ea3aa52c1892c7041fa174e841a42c3d447f11c4904eb3b6bf42367853847c9aa4c9adc47796fc9557475aabeb539fcdaadb9ce8bd79abe257332c6468cc1b7035f4af5060dd7243d470d18d62e3ba594d262ae391e2a59fbc805b9763d2cb70890e06cc33c1c72c01e0b1b48e668ed57f24a6ff2623e9d7c7772521a039098453e5dba953c0cbb1a146416b32cc69651f6b2f439e4c9d3fec4b39d371dbca71ea5cfeb7c7a7b3307afc6cd9c3ace7ea70fe0fbb7a4613a40c0c12ad443fb9b6d18d723fb80c4dcfd8ffbeda037048cdfe42a9458e343628dccf65d96c05052529242292508219860dc8eaec2c98ad3174e37b399c783830e56ecb330e6d29fd8932f8c29dc0eed5bf181bdf6d86b6f4b299be6854232f61a2ab4dfc99b5c75ff621593986313ab59b5315a1ba38c910772e90bed87fe03fbced86772ebaaccb9192091c78e2c1c91bdc7411712fcb92bee4021553c9a264227421277228f0ca34df6cdcd38d12afb8ec4c11a9d6830eab88afba48d83b565249186a95fff85aa3639b9b32c4183f54bd0d1f582ab3371267245d3448d3aea3babbed37cdc892a174204eb5787a26b54ef89d2c6ebbf50a85a8d90eb879248f6798d7496d348815d898350348cbb1a46497d57e24575490ea51259f4b6928338ae53f37706fb228e4c47c471bf432f77376310a81716026a21a18e91cdc4865ee980615105ad8a51050df6f45c2d08b98a3911a76550a81b44f3d20805fc9d5947c2997829e12988ee46f808da916818ff98e339a1d7788d86840fa9892d078df09a588406e5d06f806113f621767323bcc66b74b8261de3fbca03467f3f07ee37eee397c368f4dd90a91f72b8cf7d42801f033a4e70266bd7dd3e2c5375fbfbf1d37143d454c0e70ccbbc98f170b9d5568b655eccd7a3e6a3ec318f0707b10fb19fdf03f63c44e0a3f6634e1bbc0cfbca5197ce8386e46904fa8e74808010761c72a03f658caaa684661284c4b408f6db700364dfdf1185125fe419b97f145758a63c3ee6c5530d963123d119f38470d0232b6671c88d1bd8413f5121a7c7810685c414002151c4a90938c6c10d7041348c9b488024875189ec2877494516c241a731d29f588dd8b46d1b0842074c5a46b81e71f8f7cf68230ecf7587ccf24317218aac8dd1930dae1f2de64ffdadbf94d2bf10fb691d94fefdf019fbf9a18d2cbd624f6db598e7b55d33d32f067410e3e0d0868d1b3404e1a254baf3c601c61afe31ee51f982c37ef1c0248806ea61071ca20a0011f4f798087a4cf9fb8311074cd7f01fd44bfb8733647f27e01d22d00e4a9897f0a528e68462f12683b55dadf6cbd85bff96b7265caf4ac6f9502183045f408c082e41f83404f69fae8ad1b1090a1cbffe9c3373f3e89b90e41046e676a864ec23a792b18621c1b766021c76d00b0ec1181b5aa88828e0c91e734bc451df7f46c461dfffae80266beff9ce2de2a8df3f230eecfb6b5c6d7f3f1ce5fe8e28b94317b9654a0ec19c9243bbd51d271b6c3dab913de6c9ae913d2857b453d93b4bce3e3c403ee5ecc31bf20bb38f3fea63af7d3ad45740cc9a6705aedf0f00c8403a8b32641b7e397bec07206ad63e88cd400e90b52f438010afd1068c03811de04be655093e28c8711f14dcf8a0e00814b07c9200834f12496aad984f123c3e49fcb413994f1239d9a8638da22da4ec80524aa594f5db935fabacf24a1f524a29a5dca9b5d65a7790ed5eb8834b291dab95d269857ff7596bcb7e611fb1aeb5f667a5c0f46dbbec8bac354a2a6a6c6d08170acdf190dff56bfb12bf42a1bd3b7ba955ca1a735b8c35f9c08fd7e2640466b9357ba9272870f6db73dce6b508b5ab65da67adbd7bb556f758eb7d2c5eccab632d6759966557d65aeb77b76debc40d6f637f83967ff427a476873e9a0ab97af5a5e7a3c6145064e1812c3ffaf7a3878ec226d7cf021d854dd63a0a9bac65acd65a6bf5b05a299d4ff8d945a31bf8dcece4fa5eb32c609f9b9e2cffddab1e4a0131d78fc5b302c7f74fa25018d70fd77665203c03894da2f55c3dcf3e3fe6eac54c3f209d4516d95b245037562ba5dd326fbabbbbe7f423248131868c06cf9794524a2ba573c625dc16b4fe984f23ffa03c30a17d4c0e1b0b2fc40342d8b7dac7ca3e1a226074645f53d261432119fb9826ca6129e34093bd8df91063a23f9c5fe881fee61cd054d0d13d862c3f763e2530417fac8f1f9232fd4269ca0fe8286c74c44f887e944c99f25b6b336b75902969adfd9892528259dec8d2c672e104056edbdd3d29a5b4523aa7f4a8051c44ea3c7bfbeccc130459b0696ef656af7653fff8f5a391c6cc06bad70027dfdf65a5efdbd762d7cbfe5a778c89eeafdd300cfbe672b8cdb6eb611f39fb1a378359cc467333531c71e7e466a84d4fc66f3d6d44fa288f688e01ada3bb8fdd25b0c8ed8819ebbca803d7bc8e932f793444bc8e93afe675745f8c8354603bfac87d31369488d1b4eb65536099fb270846b2ec72ff046105f9fedd6c6c7e9025c780a8a3fbc81d91effb4f1058f97e8881cc7ddc0ecf31275eeb2885ed6a1d365a87362333acf3689ab895c32650d62f793478aafe492389395181c19800c474de0d2740fd8b9580953b5b1b63c32a814107b7ac480e5b09d7f1108e4d4f9862ff11a6dd38ed47df5bc7fb397c26abb19ef69666d9478efb8be5f0226ef4b2e7b229b0e7fee9c192cc6d315f997133d85b4f3b82ab1b663ded88bb6dd9bbb671f6479d750ec7b97d9060426e92677f73ccdecb23013d8842839d6fb6c5fee901155a8bdc28142273f6defbf75adbe260f6230fd45adedc6fdb666d6a72e7cb65f6b69ca51bd120288735465eb0d85a1e9b595b84eb313131f7b32ccb32ac067b268cd97030cbb26c26cbde7a59e6f95acfc614dc1238fbf0676cf677fb5bafb7725fbafb57ce7e272270f6d76ed6d36cf028b70f09965cfbd7da2318d16494fb08466c21636f4779fb6ec4d8c8b2cf621aa6fe4bb418a59b963de56ec0b2ec031d0c40c3d418f025cb90e4f000edc2426ed607d65570b1c734cded6631ed270a9bacb5d6bee6ad606fbf531153e0ce3383d16b7190be0705c63edc326642d1c7288ac59405ea54833bfb7ec73c54cb681faa613a09fdceb2c730eced63f6ff6ada176a206716abb4fef874557c67c5efb4e399b5acdb2d175bb9f57fb57e9de3616df4c9d91a6caadc0c661db43fb9e666acbd72f35adcb919d93285c77dfcbec505d8625ef615a348b8f2fd7b3dcc084418c9db637f6fde3ef01d6cc9bafe14d2bee68148e46417609483dea372dd68725883cedb0293ad74b35098d65aac5a4abb56138f17eac58602a514e5d4ab7fa5b518157707f4a4839983db04c0ed93c44d96aeaa1ef61043df52399bccef87cbe803253e26189a64a0d5c6e8d3229297b8b973fb3669cf52f5e0c30dd7500e72a6c9f170d02307811d22d0f27235fad1c77ddda910471f82380801073dc61863cc334e07fda404cb8f8fb5ccfc18438186e1c183c00e0ebacb8f86ccad15eeb4d1222de0d1c19f9e9c229366b25e433c3bf24612595214a56f21d9f4e18a7d1b19e7589fde30713bbce37c9072f6d77aa67c676c2d24cf57c63683eb419ac1f918cde06e681aa9e81d2db891bcd1872f1cb7713f49313b49721843227d899b21c56001878e244b19f3d332f8a52741fe09a700d267df65df0ac64c3862085ec94a5c0fd2e36f25fb7c8039fbac3ffb6ef0b84afeb03b37c39f316148939cbdc54fc2a6962bae53f34fd64596915d5e600010d375f8334b2291be7bec7137644fca9e44f23a638f943de973b8052266fcc5a1ac1b715c0ffbc5a0280480ed923c996f0dae072993fec66c91f331caa40fc096dde039ec00c9f37ca57337c89c49f86fcb0178ec99b17723e36656487fa3bb27fdcd3cfa24aff31a7bfcf8c14cfaee5bc19f0f30936c6cef0d33df8508f86d947e9cbc7df9312d637af9016899ec81904a7f32e26eb09fd9cfb21320623ef9fe87fdec4b5e68bffb8df3813ffbcbf5207df6b138487a41516e2be4f679414dbe04e82173e8812c73cc73cb2197b779b56cdba8dbcc4761074e7ee613eba172e64d59e9cc7ee6ec0b3b90ad83a4bf127b6c49471de931e9b3a32f8c4936cd9bd9170ac913b3e1a09b228d18dcf85b6c6b3146a17e8565aa871d1c294e496b3146a170cd1de3df677b4e2e60f93bb75b220d4de9e6e09cf8fb861670c518857a30c67e61cc8d1a1cb4a10acc2272a9bc2e5dba943f657d19855e314914b2710bd10a32e4fe58855ec99c2f62921d7df972551257614f5f12b9dc71fad66399f4a5924c2b46b1afa88e4c75d5a16f2db55827d3a74fb54f0a39485f0ef5c8957c798a7ecfcbbfd86b23caf45b16653a5b7e9473ca1f09e4207d9923575228a6e8a35018cb1e07e9cb0f6da55228e2a0a255f6e9cb28f48a7beaa414ec431839944298271bc45e7a1bf6577ab2d6979302713a091032312d62053ab9456e9f1510c9b31bf539a24e2cc0d373728a6270ea9288937338911cdaba247b9e5f141a6ae170aba9a972d22844342df8a8dc0e6e357988afb8d756e32abad5845b4df6bf75625c9cbee25e42dc4baee25014e288e6cdb822c9019751becf9885c8186b70fd2fc9bda5c5c186997191027f9e7191024b2b797ccc810f4e900f0b887c5810a49541c9690a413a8d24cbfa24ce868e2dbb6a3ffbfad2651877f28e4f0b868628eac87a3183f7e2755ebc78f1e2c53ce2aa172fb67f51b7e9c2037c2b0deba74ecb78de84620be3cf8b4530de36195b2f7efe74a257ce44a6e6ec419e73fae4f91db798d3f28592855d5f6cbdf062912960ee336f99ceb1532d3f5b90e4d9f2e1fc39b2f9d479e1f3c76790cfa13c5f7c2afb172ddd470f77f8f1b6cd68d95ab6967f3175e61129e0fb5a4bcaeb2847292fe6c87295bf44d2b3b2a49d1ea1ee7e7e0441cb84a0552d33a05c5028d4b7742e33685ba749d46f353060d49a1419df526f48dd777fbb9312f8340ce0a9d49752a92e76a9208238383b1d9d233bd5c6c15987c45ab3d2b58ab0b46acd0c3fbf0ef19517792a882e16f1566cc59683f3278d5fcdf0f327cf744d24b367fe4ca019348574748eecf8e0601041825c05aa8436b7f8f6167f7d0bc25561f74138384ba9239d4e91ce8c4f7da12d4d1d4fcd6f9d930af0cb22793ede3ee6186999d639e2aa9dca535daefaef8a8270707e3fba0f12732cd27d2dd35671523f73ea0b3b903bd0731a9e2799c173224fb9f8d099c42231c74123b3f5e2c5cf98adee8b2d9dd8d2a935b7e5a2fca9ded49a141929df526bea4dbda937b5558b340b8be5c88ed6d59bcb62e9d41b9dba44cb6b4bd3b4266ab562abdedcfc80e530b2660eebcdfcd3f4c2396d6445d6cbe4deca1b34bcc4d8b0d6daa2199e2a8ac15cdddddcccf7b73d0437bcd5e4eda77515fe6d8bd95c8270bceda2031c4f424d266a65c0e194abc9f2d46c9d1ea57d8889b80ac66f2a1928f0b56f8b3f7f169939ae72d9018ebd05e93e7adb771e8ff8db8ef8db6f1ffeca25404816823f87f42188e46ce8e83ec41963dfdee2a3bc8b6f49e35dbcd8a9f83378292fd2f04e1f68d5e9e7cf217a1ad1f38856c9f8f9b304ad027ffe4ca255307efe5441af521f4d13b8376c42b17c0b886177c32614cbb780d7f6ecc2c96245b71b36a158be25cb38bb61138ae55bb809fe758f5ce3df66cb001fc6872fe00744cc32be707bfccdedc01fbd7130fe8fedbb8f53892c8aa7c77fa59c9cc72feca1658b11c669fbee65d1cfd7017f393828a50b87603744f7e570f046260384813d1c3a8706b532e0d071ec369aed73b8f7b80ad3f86e9c3c1a1a8c8ff272740d0dc697e1d9d0607cd04b4083f161783834183fe5e5d0a9edbbedcbc1254048debeb70fbf8de90205f651a22887b3a7c747892373b68f1244dd365993153dcacd6c31d2291dffccf80b3d80f2c29851189c343eb8c0e087bf1c0e72d67629df3e2d560ebd479b611701b92ab411e42a1f646a3eca67df32c43450393cc56322f59d1724e653671f2cca175aece20b318d2ff5d9702e7e1dbbbfb163871de4329b4ac4eb4dc57115b7c2a41ffdac3579e6a46027cb8ff2a37c1a704cdc627ce466bec721e2d07e3e035a26fefc06b4eafeb45905cbe00f5159a553dbabfcf56483db6b5e778dedb1b7fd0cdef6296ffbe83dfe8b71dcb0d6c9fff99409ea2ddebeffbfdf4206383ee56c686ec7e7b07bedefc90c4183f37d98454c2562cd4c41644d242608260bfc670112149d3163c68c3a830613a9a7f1391c04b56f6b10c458bb01bff6011133f885f1b7ffb161fa7270d2a14885585e2b5a228ba850eae7d3215fb9cb53f32fb66ddef636689e4f0b7eee0a11d93659726a93a53d8bc76750d37ec6644dd6a4993519af0021e5edfbc71f1031c7dfbe1a1cc48ab88ac6b7784ae42afc5b6c5f79cdf31dd0731e1b6cb82b3fda41f083c43c695c9ec0397cb2643cf8ad6cdbbb7c77b9378f6aa1c1f99325572e1fed42a7e6cfaf889b19b2b0497d58e4f9e1acc9330b0d33bd7150a25863124d4a3487d8b6a7c1dabb3c81c376fdb0c1c1f94162aec1c1f9daf743fb203107f181c55ffe5ce93133f833835fd881ac3d0dcf751c9c3fc3f3230ece22f9c57cec6d5e104214c180f132641196b5cfc50738fef6e1644d96abf05321999a7ffaf653caa3c478cf0b63f6f0478984503f5bbed066d45fa13cbf850c70fc1897fbec29d17c5ae4aa184b4c1f5a5476f1ed2e627893c6c19a6dc39a47245344f3adc5dbf77d93e5e07c4a44fa70b2bc106f207295125715b54ce719bbec4d185e885f78214b76e18598c50b5956bc706be1852815ef070ce58533c50b4d19c50b4df9e4b16cd8307da12d7d21fe3439b7efbed0e26f461247c1cc0b5142429369cece984b86e718c16d1a7054c2ea96f89265d569c12cab2aadb4e172f228c9377215ad921c5a8ca2c95e6f86726879c890436be9e735272ce01e420e72723875b27f9c3aae3ae2aa1d577df69f36b2e5074e9becb202616c6a7cb7ef972dc37dbf672e97ccb2ccf3222e9d3624a0c77788c04bfa10a4fea49145a3b12ee7a5fc167374c995b3582e96cb4341f13413305192eb4b96ab426993eb5795af2f69983409586081051658608105165860818515565861c515575c71c515575c71c515575c71851556586185155630810151c6d841295bf6bf8c899152ca6fc6b8bf0f52f6078ad18510dddd73099ab3a76571771babc8f343ec0758cee0488e1f5974be0cfdf8271ae0f00b8360d93a287facf4b09f23aa6528e2f03a46c3cc0f7dd2ef1ba6a8fe940d62cd32eb24e55a59f2744a37a79fe9bfa4b8dd12925899b2589725537455e3a4dbc172dfd56dc91425d1c67177620d8a71dc7e9a658abeb5f9e3959356cc66daddb81109772725d3092505a5d26285c5c50b18ef7d9b26c3faac1877235332b613ef12fdf4206918fa0e4484ae71795e3af91a21eff06caeba4cd0d8e2d7f06e92fbba2e4fd1673151e3e347001499017e388fccd0b97c27a3ebb4d7ebf5eabcefb4264dba18df692e97cbd57ddf6943435da7b55aad56e7e23b8d87a783f19dc6eabaae7bf19d86d3755df67abd5e9dca77599326ddca7799cbe572752dbecb8686ba2e6bb55aadeef45dc6c3d3a57c97b1baaeeb50becb70baaeb3afd7ebd59d7c679b34e94adf5997cbe5eaec773f146bd0a10e7f675bad56ab8bdf599ecef204f19565b13a56d7599ccee274d977ef83abb8efbe879619bd5eaf0e7b7558930e6be272b93accd5759df61d36d475adaed5613cdd3b36d4d2327285b53a8ca7eb1eabd1b9fc0c5f884a7de04763c687c9f8be1692f76ae2bd5eaf2699be1763f4692e6dc8d35c9de6720d65faff9c8b96c6e3426b755aabc593e9c380b1bdd0581a8e0b8dd5692c8da5e164fa2f58ae4af6ca9aa864af2e7bbd9a64fa2e56b416992b1b52c95c5de6720d65fa2ca8ec94b5329e53d6eab2568b27d35f49b128192bc33965ac2e6365ac0c27d36f61c24eeccb3639b1afcebe5e4d327d9552b5d665874eacabb32eebb243993e0a8301d3164fabd57a22d347f564dae379be230f7bceb22c8e65599665591764fa2918868dea935e4d5eaf5719327d944ae56bae21970b73615564fa27ce088dcebb4437498f83147bd7d530f7e70edda0d30c706801f0f46f6a730fcb7116f115c69a46e611ec67cb55df633f5bd038309ca944c67ee2b44ccb633f59beaa403540d30668de3471558c30348e5a543406262de30df9aaeae824d151a2b344c8552f9ad038eacfcf14412df33bbeaa3636ae6ad303c389c6518d18c941c65eeab48c8bc78a8a244e912c6224632d1eab432412197b39a465588a7c4581809800491690ac51e2aa152c340eaa448916885a46e5c7575447274867c893640c85088d83fefc182163ef485a06f5d87b8eafa8d5c9988def60298fbd2fd138a8112330c8d8e9b1771a5fcd221f42a40827631b191a071d9245939631bd7c35818088808ab092131ac754a2840aa196e9787c35757490e8fce80465ece34ed401fde141c63e1e6919fbd8c71b5f4d9b560e76f2464e90b1692488afa46d4293e7902e64ec2bd038e690f8d8fbd043cbc827c22f1c7c2581648a3ed648c8d8f7681c52890e121d1a5e7c257512e02a924c7dec41578dfe27d30f69640c658361d248a61fca9c65340ef9b3923633360e6924d6a08f3d86cd0f636138180b63612c0c27d337b59062d45af4d50a5494e997bcd10b9d9f5a6b3d790e46ad2f6aad364632fdcec5d6a2a80ea19456cc7257286d412990924c9fa4a2a1e8fcfc4fa63f426529d4861a41a136d486da5023993e77b25bd156848b8ae8904c7f33612520251b1006025292e9dfae723a3f3a3a3af4354b7358979ccc795f28ee9b36731a91397e01cf1cd62559d11c525454344990e96791e3c99447564f3e09480910101017327d2ba5e474bcf9239d1f1d1d9d28327d6c724566e07aa4f2e86738f1b077af66cde35a1e87c3922bcb15f114e554d035e8b38e6023adccb1a061e8c7dd9cbc80a7a471b91ca4df79dc0d87e320d7f2147d6e27d39fd63ff9491a59233dcfdac45a180fd6c25a580b7b22d35791b2058b6ce518d1a951df3dffea71452e1207e9edf1949188e342d135e8d3fbcaf4a58d4da6436818faa1b441a6af713b3cfb775d0d43ffe4053c3f1c1559392a1a15654b5c157237b949ae4c4641aedae28bbbe1707cf5f2f4b9225c8e73465c489e6cacc1f8b72557f7ee441cb7899b93710c781d303ff30b4792301b496a0f007af9e61ad03a5e3c265ebe86c7f178dc8e4baeb81beec6e562031cdaf6281b868e5666e6beb003597e8f1701e045204fd1d73c2660be9ad7f1c2f2caf45f3cec29fa94bee572e4aab91bb9428195bb415de98533cbcf7a33bbf80009765de1b6c2581bf6712cb9e2706ab89b4c7f9258347c024fa82febcbda5ccb60d77ad22b101fa8fc4ac1fac5d8701a4ff9fc94677faf71d0c1260eb25c88e0e10ffa445a067b7f4f424aea492c0138788e1a3ce5394c9733ce512824d3e0a0137d4d437e796b2dc628d20f0e5756ac741ac039df3ae195e9df585d1673ddebdeda19e5534c5f3a413945172c4972fa92c9f4a7fa31be15ca6d84dc3e30b0c95785655341b538fdc98482627a133763427d98f22653ca8ac9f46056f914930a0a25e551296f52417d8aca0d26d3974a5ffa1caee2754e41995250505052de6bb81b503ee503e2db62cbc496f1eac9843253bf30e6939e36bacd0ecf28d3637fc354fa52e9497f7acccd9cbed2973ead5b26e543943ffd2d79da9f3c14171d4c5a3991508ff2a1bc20339b6e344c347d2b40cc7c7a20a47cfa52e94f28ef35dc0da747f98088d9f42eb81da6cf87c0d8aa4baeaacb5617299c4199d2098598e9633faa3f1a7d29c85542ae1ac29c8ff9d83b8785276ffaf9e3aab0f4f7e98fd28f9e62b1fe68f425ac7ee94778e49972e42a12fda5d14432fd9c9c9cd1bb10019342944ff981f2a7a7efad96413d7d5fa2f4298fe2a1bc9849dc0da72f9dbef4d705f376fc7079e2c294fe85dbe13643368e87e9830cb13969a738543ae17a9cbe181485ea562afde47c9cbef4a814cf4f5ec903226694cf711ca4a5d04479fc709c1b07e99b3e972770e8446a88b82a3cfd38bd09e7c4f41dd7e36452cd5c7ac9f18859b808817aeb3e7d2f42ff3bce47ed81fd95bec596a69fd9f4851dc817fb8a7dd6c1d217961e8b3232e62263a78c3dd7ab48f46db796193d1693ef96e93d0951d89b43645a73788dab86f4a46918fa9148aee6109da2df8224e611d45bf4efe72d0729a55f91b80aec71d567faf32557adc3ced76b05fbecb515ecf301661b0e466c23c7bf1886d9585f315ee0d5ab7bf58eb9215315f3ae5dad5cd5507115f02907381492b1a7576828f43048cc3f7e607f271dadf4c86e6d66719098e5675f9d6998ea7dfbd218316eda10f38afd1fd2450abc927d3da40d0ed6c005bcd5c71885fa07c198fad580550d0524d2755224bd6792ccf772a4ccf34c82012b771272fb2c91e391649e73092619e7ecb327e127654f4292ed673838204aa5c58a0bed06c94fdc0e9aa7fcbc65a42ffb1516172f3eec21c60e018731ff884351e843fc2412c63e233d98ede38f643bfc71c6c7deca7cecb32f5c99590a3783e70d9721e01f4162fe81fdf53618de17c3fb5a66a8a052544e4a3d6dec1c7ef2ddf821fb6e18fb76c59ebc899b39f9ecdbd287276fedc98a35fd893595bc2033677f4d7ff2d7b472f2d8974e1ecc286f5a39f97c8019e53b99befd86ab6c7c93e957ec631fa487a8e4ecf595452e951a1a00000000a3140000281410884442c1602cd124a92a1f14800c8aa04c6e4a9b89c328c78190418618640c0102020002000023836d00a999ff8bf522fdbf9b9737be6e5ebcf977ebd2cddfed8b374ebc9171ef197b73d84bb628ef32bd3fb797377ddd5ebcf9efe6e58dafdb176ffeddbc7463f2c60c7b4fd85bdabd19f74ea97ac9e4473b2f397c39fada40c24a0229fcf5eaf6634a577f10a7c41e8aa669557166abcf799c8c09e16665236a4db317bcc4cb2e85051dac4012e4531178bf4e5b5d1fc6ad2e954ccb79eea51275ed83b8b6ee6d9df7f95babc5ad5d111a1c7af51b04b55f82bdaa3e1c7cd7fba8cf3f2e4810fa0d83e1b96381ed326afb07ce71e16dd254bcd1a5574dcc5a01381f0124af3d257efbaa864eb2706a349a7b6016af333a1b45b3318da4c8a7d9b67429b7ad7e87d1bec0f52f447669694ddc28653df798df545f2f86de56e6449aa2fccb331e20b8f53d7506c37fd6b8ef66adb30aca73e2c0d5bf398e0af08317b3fd0fd8e9490755ea0685a7daf261c015377440c19848a86b3e88400fd355c7baa92955340ec214f55b383564f940584b4045853f6a28826ea232768da09f7cb6310107adb42626583d1bf3e3b0bbd52d3aa01f9ed0372458d0f1ed4a3c58e3d72385fcd4f5f5dc9a2159d398b3d6dc8e60b41fe2a40c0f8f0d56b51289477449520e2aaa37a0fc3a3dd7b4a8acef06a9ec83eb508f6b702e56fb988df7bc0ab728c41df9d47f8348b3067c9e6e62faba61ea1045746f392ea2a6531a45c8ed515ab6dda280f3b1f7deb95ce8ee9ea973dacdd74644da5c1a13d548a675dca88156db70f636e755d003a989d9e37b5f03a63647b863a78031dc6f3a151754939e1bb62d722a651d035449fcae2bd1c90a47b82bae384e8316f9584079ddd551a05ef8dbbb6fa9ae354fe5f1e898f48890803cfb87a43df2662685c0f229f181f5919881f611d1c0f595d881f6959881f615d140f491f881fb92a881f715d1c0f4d189c82410d8d4f24ad5309552eeba7d28a58855e926b19f21397c478e108727c1c17d09da7c742aa5f2cd517e74348416b57c3f4efe885ba6ae9a9b4d035bdb9e031c6fee1b8d4454e3fecf4d2dbcc1c4e8db3938b23a515cc97877c098bacde567518810581a4702964a8d599d1af2b6e3ef956232f23963cd0b5fd20de9f6c94f2d7f7b6b1c933ad89d7dfcc80402bf668cdfc0eebf059fbd91f182ffa8eefc23b3f17f44ce7f272ffe46afa19109bb7e1d8fb391f1867f6de1fe6d2dfe39d37923b3edfedad2a749bcde43f44220139223541d88ab86abc3711d50a6951b193cf86d26fe850cfc4bc8f81c19eff247038f3132fbfab7f2e8afd2e22f6b9a3732c1eeb7a9988e8cb7f0cfd6e5cf76e60f4b9c3932dbfc8f08be6afc8763249fc46022de40948670f835d53530044c59ef91c1efdf64a25f6460bf4c83d7c878177f14e2a891d9177f238ffe2a2dff924686cefdfc7d2046656d73c6adcf91a901ecdac2dad35aec69dec3dee846e6706e7f094f2cee961999f41cee11bec3567c56af04194c178d0c6e692db3684d76cf5a18e42f7576ea3282e9528ae72aad73d0528977df3f98f29149f87471fb37ffade4d14057cb59473e4d9fb55a1c19c6e71cbdf2053a47f7dcca38b8afad2383918535ea8202cdc6840bd618cb24227b4ffe532d178387a92cfd2a258ed19fd4f6c4d976706037978a54c1f3e12362fe101ea5f530e614f5287b1c7d5fc5a180ea1b788583ebe072ba01fdca4acf89b763329cff54b9580ed2221b5f0cd1b28e5f6052af39cf07af5bab3c27fd1aca482ec74ac22afa160a073400ec062e4fb9e2de6b64b99de878b4a7df69c299e1d15bd1f3350ca988c1532e3ec6724a72a9a176ac4de1698d40231ffefaeb6326462c7f5f5aab72f8c356526294d313c2257e3c90ec202c162b2d44e09b25de21ab5ee8bbceabdb8b481d9df191133c8101e6d413c54d7c0ecc30c4484732f79f8eaa140dec4d5e78f98da1660b9c896c156ea9aa7af760058eea4208780233274fb38a133e48e350eff5acdd81f9324d09d2ceb137e070b07e714e9a25683b8c56ba0f4a4ec902a8f5d01115a66061a201f01c8d804f7b04776cea6ecb79ed65062b1e2db153b6306dc08135fb891c195b75a271254e6669f6aee58d08b776d2b862de483c99dccffd6f3904f6bf75e68b2905e86af0979bb27e38b57872bd82225aeed71a409fb0c347b9b08a8e2ac019818070b9006cbc9f7db0ba9d52f9206c21e2626cbd2fe7df4c6c320db7de5813e69f4565f03ee183cec5ad5190b442dfde33078d7ab599cf08ccad9f8f586329749ec102b48103f4fffe148ec6b24b0b70143fb40bfd737c93479754baedd7fd820e139bd9c7a4830a8b7200518feb65cce56f9bb0379e8e04d545141ecc332796960c6af6f5b4f85365ff7de21c2055d5b2f748bb9c2006fc863351adf478b651ba9f2bdc26a327c720589854a75db711680cee120617af14254dd52b2840196e60a746cc4c356f1a7403c1011448129aa2b6040bc3b75c621ed89cb96da3dd80d5c1463b375f633951f4a92c1316722e2b41e81339f3598e8c6b92ee9697fde44c06277568ec3bf3394a5c65e0e9be70ecd054d7aa187244d7233c6af307b8fefc2a236050659adb3e5d79b91babe85c3855eb87b2e863b96c552a8ab42bfb23ffa46de0cdea278882a97f10752712f74b87f8559d3cce8517f95bba567a6861e902faf0c744f42d2daeafc52ad280528e00ca4014495d75c41b90c36d2377e712738a8481bc1f9d4a8d07a5417dfdd09c9778d43cbf61229f269105cd6d5fcac4901ce7a827c25a7da556789006e4030cec83157c184e93f05caf8d7a50b3413b1239dbd0984b3a7bf8a7fd6d9f7b332c1aa1893a8b66c36c0c1aa3c167c7e6e343e7e779f5c390c089c57d5c28d55c092225d3f68286701fea79c171e2718d170103b3d0401604125816b1c169e07f30d79f0dc54b4c04ae3835681026b6c37598a812285282dab4d640dca4c8a1a4c8030b9c4d9b9ace29922df44a4df694bf54981a515be6d7c26b19515319e5ff1581506c0e9ce2699bbb1d16b71c0973dc5e6f0db3323b40407b481e0d4eb4fa9513da19eec8d6526d3bf9509364fed3744bd6e6f25692671e04c15825efa6831324b2607f4bf83d31bf48a87c1a00ead7bb42ac24f96fe784153745c9bf6b73d1a27e17d3a658498be76ba358a7aed15b2413e6c69be4a83122fd1a034672b215a00d1a43d3dbde608bf6abbd6ada7d908581a260341f54c681f62d893e9bc9420727e4772e959a7830715e6e02f504bac24ad7cf551d8bc4719f603c67e79592c05a51e639d95a752b6cd66dcd646632848a869a1d7e41bdc7676720d67c513477295be8d249fb86eb066bc85651a7947b2dead818019e106f915ec2c51c68f89b49580aff66688a0ac986fe92d1283dd61ac5a4de8820c2c02189a0bf7870e4c089a4f74ce024753762fbe8730cbfb51b49578e4d636964c061eba5033a5408f0154a9827cf671d4eedeef0d7d5310c66e7ea1c474ffdacb5464b8a47d6be855e532da19dbde0d15f3b68d268b33f1817edf7fa2d65ebf330038f8bbbf3d09566057abe2dbd638444298e69094c41156285872e55ce8e254cda4e9ccf22ab6da26fa24adff73e70d87a4916d63e2a5760c57bb98781af027d9997dce2b050f383c9fde4655177693fff043a293fd94ba273045e315142cb55f5812a18abb04fa6f32c516434344d57d852485e7cbff466cfe20997b7d81f8d619469e5977027cae3e9f528a00446f7772f887c38b2119511a6335b0365b6d1d3171c3ef9973ad75c24f991d81006285816e014795cc2c42ec05e2e163b6224148e1146ae371bc9ae4e72a3fe8ce4e2fae3e878cda735ed6e5754f359cf7fceee49158a6abcfb55dd4e155a5bb762a978012d9a9f32133e38a87a1b6918fe7a5e0e56caed0814025a57493b5b9c91f64cfa51bfe3b14e873b82aed7c98ea323d08bc12235c5c1cdb9b7d328e7e3610b08b5c12c0276687b8115d0df1827e1dc47a3036394e534c731e444cef77a76ebcfb99153ed386693ac79dd8ea706695159ac0c868f6c4a4d12654402c59270cef14856f65e5b60141b59e06b5e96de4a4b3c1f547b27d59b80e00db643d9965f1c987ca2beef5fd9b2e6ca57854a0717a327791774c9b22f7a4e04e94c5c47525f215fdba4cef720383c7b250c4c1d32babd430b1adb5e51a4bac756b72f0f4b907f5bba5cc99e83c008df248ae9b3f2f4b1f7fbd420c86271a2b3265b0c54c395b075866aefd826f779c4a8a11a115105b3f05da07465044a0444f5df89ba17c0013ec5fc8fd2923992a695c62a93c782c4498615eded1b17e692e3c1ed69efeb6b135c18d7f97aaa0503f7058b0c360b34ac8d5176d3ddd6a2c91503317796c67909e738542ce28ef1125314abc398842dddf339882dbaca04fd6ad1f7847594c7a8eda6c368b1ff80d5591303456149b032f33ddcdc0189398130edb891f85b0c77b0c75f57c963983148ec4ed947dc3799f8b5c7203a46b3b5dcfadc2435e627548bf769bf2d4d69e85f28db82bffd53daabb81eb27cee5310c45c32bba71cac412002d4535f37bbea9747c237a70872383936739691a618fdac03c61892ec625638cc594a7c76ae814d0c04dc89ee546485987d73ce13251ef30bb37d9d7f4ef85c9cbc76f9146a8fa321395f6b1724144e2df72d4b10c71d3a82028bcb72bb8b17a97084342ab94e8e2478601927ba1adcfd33ce3b8a40ef69fe070c64b2baf6cd68910c249f3fd219c4d378c092c1a85c2bd7a471ee5ae60f9c42aecd1c9e39c59e66c2abb3dca83ef1cc1b19e33be3e2d8f4078de1877e533c3e6e11963daea28abf4d02a8b042c00dca89f7e6298407e5b5299e6b4c466f2cf040012a1a2bd3d065b63902b9f748bac47dfc9c9f14eafe3255c6e7e8b20837f9c2744fb083f58d249b3497e3f64e7571d6e0539a52f51088ab66e195c8dfce8f27a2f00632e793194f8eea312ca4867c81f69665f370cf5c7c32876bb4f0bedc3ec54db6286167544556c8e75f1c01280f76c495f712173c11d4be4b97794870a8a0c0aab1cfc64ab06c7962f140c8d985aab93c4ad677f09a4bd282b024e47ea2f5ae17926e172541d08aab9b8fac385890a52cba6a65ded0a2cef812530d1308fd1bcea80b0c116f3bdbc8b1446ad759e91efcd78160db465622223b6b398e2e97afe4506461882294828c4f564a380570a9487f1a6247ce51b94bc48164408f96fc2a38f8bd0d7a856098a409aa27b5e228efee66de1ac3f6a5fdf79c9602991b6762f14e9b332df7658114dbc540784f4ace22086f2e098bb9af9b7af253ebe9fd25505afc5ea9069c9fbf187a2959c0899e498d1b16a014563f69946e217ae2419830814f3972238b9be859b1f50b7e7f3c9183c17405bf54b4dc0c632ca58db7fca42254081898427431c3d44ff78c3596f4903b169db4b83defbb7ad234f6cc864151c238166dda01464553a0d1e674f1b75ca993d4bab3f24dd698c1a8f8a5be965aec71cfb9f0a84ac111d454bb00558fada5c6321551d99c2c2fc3262592c1f8d11682b872469198f13133b865fc13701a272771c336d5b4de320d3323beb5cf44c7b485b633a1316a1a1e5919b884462c6b75b50ba21a7b75905d83509a3dbee8ea3a4273a1d719617ddca55395b6b5b1bce658a876b106d3a254c80a1775bdf8dbbf448241c62c158b7760ff4dfc620cb446d7bafd0d5b9bb2d28f4b288e36d3812348bcfc17d1dc7bd510ad874308c0b041c14bc2f4316a4cf0794efb49973bb9635c711295b2957ff527c928fd36c7ad2b3c622eb047159d614d7a377077707407466ef07bcf6d988f0d1bbc9a3399f3a63267c821bcb3041bc125d843d7d4c7e50a4d35210edc6cde4c984ae8e6d7d290c3f6782fa1c5093ebe667923227e553ddc31c14e798ea88a8b07dfe16ff8bf253d58f5fa460cfc9b37a14b3cd3e197abd388ffb2c3caf451873c8ae940ff16ffcb5305ae0e3e02813d20da7779cd1c5536cd11f41cdabf7257b6ed61f46e744ff5faccae7644d977424983244d6bba10372d805e2e98001dc5efe9146d224f0971d8353887062a682ecfbad4014ab8dfaa2b9631353670ab19f9af3deed8f145d2b6aeaac56281e9b7d241c2458240e95685ff7843e30ed6edbbf59ace1ed3219f843ba5db02b13d8ae8f897e0485509f0bb75de22809676e91739bf4d79484730eab98cbbf1fc38623d7246fb19bcbb479edc0a868162c862aa1b121d2f487a4323a2146c8177030de1e13f310c7ce3f9754480942e51601e8aa0d034745ba03e7dad1d2b815b61a27d1ae8416e3a49b9d1a35121e9647c6387985ab68eb52a9a9a604f6a9b101d56093d6f0658c7b7051a0e121f66788d45f79881e508c6113422a2c2dbbe980011b1b78ed9685e91599559209ecadd63238d88cd98c07a3c2f8a1e90f34d65fa54d6ea8352e90be7bd9c022435759eb8dc31de30d5e35344bf1b792bda2037a222bb2f46200a8752639606eef0f426f8ed62b41624f0c33cb7e025548b064f23f0b3888f396a181f98214e5f8e08f2b5e5999c54bedb5c842c1a0d27fa6bf12d2e41fa40326d34a6e9ba45965705cd24ad1bd1d50c17c4245933144a0ab005a09a986b0397ebacc355c68ebe2b4f2bd6724a42860acc077c97d2cae5afa811a6ab1dac79bc494e438360377d353c38ae61ca87fe9701b7ca72711fe498615133367bf4fbf5d779a12644a414d3e9f631fa5aad5b0566dbd2a9ac715bbdd930a83bee6088483b224e659a04761e3e8615b846cbc4182e2053d8f6045d6681d665b10149d41cd566a98b791443695eac26115ddc015da61ad74c2dae38c9082db9c48ce2072c08068d315ca61a710ae59c94b4e40067ee4cd59f52ecbf3d4828e712e16208faaf4506f01a1c0872f2049a38353ee6c35dd62c9057caf52bc0c8ff8eb9ae85cb05785dc09c9be027337ffec8961498568c04c1c1ede96279c220bba95d9b6117a464e784084ed7c1cc1e1cec30a60683636c2419d9012c2a379bc76324a27d347a66fc0bfcb4587d12840124addb2756b00e224a601c03fc0070bf9da85bc4a218693369428525d4f9819227acdf093e38f77c1f19daf6bf74a24015c948830cb262c48a333d242a710955ee6693cac2caf037e659e62af08290be4d5e4194e64a2dbb57557fb513da645ee70985931dc8068ad018d05bcda1f522889d45537214edac8a619d453a9520b665afc96235f2430fd404059a6bfccfa38d646c32af94e5a67077860c05dde1e3c46f34dc98596e5754477e6afe4aa66807a24d40557d8f97a27438a17cdbf7260678e201bbc7e8b1edfb7ae193815d2f021c41bf0ddaacba133c111725a1a4cf4f73cd40fbdb3a59efdfb0c232c65da5b4365c451e6955e27856986ef46d83255ff79c79c88d8895c60a2e7670374e14de86ce1df192697df04027f35ba41aeb5ce1e043d50b1d09eaeb91f1744ec7fb4e098c000a78d5ff8f185a47805b5812053a49c465c3f1cccdc1ccd52af21d0dca8661ef4cce1553ff742005613adae01baffb59321b91b5242eaf9e139d69e8ac899238677549f23c7540c7eab131ab7d3d0ce9edf2d16e74ec0c3d4db12a2f3169d15f81f607875f51a46b22a2a8a4a7f3856979fc62dd1fabb8287a16249eaee8cc8e488d152d709fc1e9a6b4d49c662efd19489d29ed418097ef6f85bb429eb38bf052df43cb5d2f818ce3729d30f7d6b195772c7c017805df566d9435fc5f8166d0138d6235b011a849d7b1ff2383346d178aa2c83cd6f7a109fd9e8a00c807b6798560d6a2d87803e07cf88aac440be5afa7a41e8c4243aa597fb0d43e217b116bb8212f3160b6b51bc25394c02121f7cda2a09f98f331b3134bb4df52f64560bc73a754c7a15137c9a6f5c7d1b14a430ae942e8a99f79d53097416fbfe8a1cee44f42aa18e0bcd7deaa5af8170ea85953995eaf74c260a5ab038dde792e11765a1fe7f9bef3cc4700d024f5b1b4d535d5d1417f9f1c76487f7f81229a05044ca74dfaedfc13da038a4a3ec06c745eb22bc69cfc3d81cf2e51266a9d7ea4c98b3064c627c027e2116bae77dbcd61632de0ec4f8bfa7c0870663450181c18b1bfd2d4e1547189138bf3c930f07a0d344625905dc4d7ae5a4ae6da9332953f3e2d93db6902edfa3a107787d6997b973105a5407d1f4625eaa1fcd73bd21196da573a92e939e2f537a12ac9fdb6536b6bc6f427bf7ef475e2f86e87ffa7e99a58c503868a9bb92c51118e88a6c349fcf2416c6a173c320f1d3d4151d86f333d3fc4937f44828f4d7c12423f6ed43259ed3522df9a207a933f6789d984b55b81d7730bb99a213f2de99237045853577c0b60466507e5aa05c083d78da4f724758b919ce8832c6195985c7ba58545d916562e2c40962ad5a6ca7f758b2cdbc3ba184cf55adb94496c1e957c8d63e01e705f64607ac03ed52c3e0e4d6380169cd9a51cb8adffb5d91fbacdc842dae6424af56ed5c9aa386dbb71946c44d50396ac6b6382b3a676db150bfebc739ee5c7aac764cd4c795cc1147b104c05d3ba7375178e403b22a08905e72f4513bea66f5f073f3ebec22d10edc148356cd020fe4f7af8cefadfa113e5e8d83e8503be634650ad7edd604eb250ed544fad1b5b64c7fbf03703ff4f99118dfc0ec780a53ca5a15c1a38c9a1b4fbb3223bba4db153b6c3afc023f836a56095b59d1b13da6399beaa03bb5a8412fb8ab9708f5eb2e60a0f71658010ada4d7b9428a5512947feab79965c40670935960f48c6731dbd848e35b2e50f005b5ff11d5727b858cdc6031ee7fbcd1de231895f7e789fd809fa818d27e149e3d1c368aef817122fa5185c3456d434d29ce0b3a09a9b13439f63bb0c5d1f173ea3ae151c6ff2eb675c3f20085de82318a96100dfa50fb3bc79ec8e955a3dcd00ad6e464197bbda1079c455389bc1473ddff853bd7c28725abe2be117aa39fb8a115dd66befa8b89d6c306f0f4c26a7efef7127f4dbadd74807cd21211c477ddc60b530cc9bc6c952eff97b1efdde1fab25ecd86abc96edf7ca94a61a80ee623d1e15c02591ccfda79268ae025c46dfc3e39e1513c4036f386df6ce6097548c266de0a25b055bf7187a18fefbb3354a824abb7c5673f78e8a4a7bb325ecdd7ca964a5d0d288e38e893de21586bf37448bed366924f7049346ab276c73a08541612e95f88aea2edb74d7a1ca845a12251011539d3643e13fa263aafbcf71c08555209c73495a003aacebfef08bf73f3264d3269994cd1a6db06a1f2015137ddc776fc38cb92f6226429a9076f3b6bd12596c1c1d8ff4928e865611bfa99fecc815f7ba5aaf7c42452a2789afc9f380af755cacc2f439ecc43281cea7a37ce67002b19011252518526a592ef67509fe25552fd30027f9737ccc11b65c8c2a4f798087b2bb2e81f30f5bfda52540939d48b1afef0a90a322ff6a85e42937169a3be55eb9545f2a617b23e6fb179be6fec695cbda988efb2956a8e12c5c95791c9d1046242c9d5677f24a741838b220bac5adebf3ce05ef9a45c1e3d9a9fe9db1b0bc7f2c248fde581b135b9bde224e3b23ec8a4eb898aafb8997050885e2eb0c2ac27122181c7d34be69dd4bc87a75a31aa0dd813ae5af8d989f2272ba66abc3312904e58a1e76bad810bd0628c30eb64a439a1a5399503b3b03d1364da3e70683091029ac8baeaf0a1835801b2bcb8db2c85209c97a1c700901de3e708484ae40373127c28371825b31f28e99f26e83ee16d576392527c9fd34e444e0fe4306a1d25940a9eb6e00de0d60b7d4db1b95ab79b0aeec6e6cbe29b61f1868deb35d3a9b44283ca3d30aed9a2b01d39e1ebbb399257b438870adba3700d515c2ae007bcb07309c6a2fafb293a6a8538d8d7bc3077e68998c655239d4e82f6c0def13b1cc2fc617e42419544212c207a2905feae7e4a0f176458c714caae01ef9f642122a58af2ec551634e435afec41a4276c08f952954888a11b68fcda6b57fa668d9d03b03e82bee64df753061155659a53a583b98a064db74a606ae514d658601e8129caa7d3723e458c38917e7b00848045cd53e0d83fb0384ed6886350d41187cc02b5d9c7cefdd736ca9d079a3a8e13be1c7fca024b7df9ff5285cc46963f77296505f1fab371ef5f50b37222eef89e4291f181b6ed9fd929dd7765a45e2c5480f7e86fa13d65a77cc9d43c703ea0c738b971406a4072748462fb4a717b0318dd8f5260781f20643c3d8d712438a69b3603be3b13dba2145fec252fe520a85e380e03c520623fe0634fc4be85e0e3761d1e42273f851104af5a7f6e1e7f20ce796e867ffa53dec6755b770a6a6c19b389e541b4687ff087f3f8e4e6a7ff3e101fbcfedfebef99f893699b542e121c05ab2387eaf39c0424c8c0efa1fb194baefea18154e5891dfc2e819d38819bbddf4da42351f3f9c14bb6945b8db93d187a81e23f5ffb1c0ec5d72d7eac5d7e6a34a6c63d6b560c15d05930f141ba25d648f46ffe05c8abfcf3a16c56b906994da29db55ee33ba13c0cade3324da6dd4623fc52290040a7bc98be2fb66d75c2bb55cea2b35c2fdb8d412d31aa357cca97651d2839f22153089490314f0b414912bcfa98c461b9062a542a99f24e217708530ee4504a65e7906a98498aebcdecec91343223fa030aa21661cbac967f13a81d04304710cc44c25a5e2e83a4000488a7b54d7411dcf55f9bcade2ccff6b43405c909fcfad72d9b0e5bfd819255146042c47e80372df6550e929c091b89dbe609d60379339330731227620ee809055986e692ddf479a0a01f50ba54f33dc17c19993cc009b8c66d516d4637e01202b2d5a086125e5d0c909b0744ca4fb5aa88d0bf9798147358257c0b0cddb3daf7338e5d4d61c20784eb29d8cd8091ba32468d3ba45329735036ed9421968904997a2b80831b8040b1c950aea2cdd8b8aa11765ecd5250c983b8ca73ea3e5bb6ca364083f4337d0dbc4dd7cab0019bb9ce06d16614363c4d9a1c31007843083037f35474d10aa08cfb2de63298533b1d76d5d79fb7b97afc85a62fd4710ed0b1653b3c15380dd0aa51312d905cbf2bc3fd1d52b6273daf7733fad26940dd98b81dcb0da2c6a9e8500e92f7b3cb59b49ab0a60d243db20ab5220aa7976cba5a265688edbb5383f94628fd7e5f0802c5c14327d5ab6a516522cb18739a2c19d4cb26b66253994f55f09c06f61ff6abb1f10c4ba64e60c73b324a5a9972ec87fc1b516f127bc744db5ae5e25d73169fac5e59897fa28c2892c82fd9b4097be6daad002be5f49a62076fc2df951d9b850ed8193ec580da9499605ef453a453fcc631f97325393a3d7349519bb1d87c88145d7bf1655aa2dcb012db04c62104caa1e59482644e6a0e2ecd5fad931e6b09dba3c63aaf5cc95e8babdfe8affadd3194f2ba8b20f704bc9d1bb50efd998d00dba40628b13dae419997de81df6d89d7f7e7b51a41977755eb6dcb44556390ce6b13d4d1d841e8b6ec4d5105075065456213fd8c20dddd6028fa68d427d2a44d6a7b4b99d3651ab253590465e3a70209968af27f14cadda3a653af911f7887f04beb2a2af8095ab92b5bf884d266ee4bf74198bd02ff549180fee24e2b4c7461ac4fb8cbe79179d07ea8a6691fe2110ef2457555b3607c00be9ab2d12d20fa024ac338510f91e34bef8f60855a4a86bd7fd69e4818a4bec1c50a349451ebcf6415aa618a9a5a62bca5f2954a5a43238cb586566f12329e8c41cacade1fc9af415528455c10cca1cf1b8272280e10d2b1abf76de7778bfa2b34c4d678fc16b7a420fd92fd5219d1e49dfea81630fcab4ba5e74fcfe7b9a65a0a7480e87aa18f02e2dca6e2ff7df4140b88db56ee2cfaf1584f4ccd425af6264b9fb08969377a3d4d18f5e2bcae3f596c92cd82802ef71929c8fe94c122b8e823633866dd55135047a45e7e312ae1380fc8149aff3bd20d3a7f21915dacf2bf361f4cbefa6fb6de3e2764015f0a3244ddc30b1945fc22ace282183f5c2e71a98cdabf7cef1b8a244b1571c01c416546cbf4e051c99b27959be5324588e671784a1b37f41d39c130f441c05f1babd3e491b8800830d20848ab28453dc824f49c1d3a3011d4b91638b001f1ac147fc109a876d008df12047548971a479abc44195d53e264a555341eb487d7131fbde54ab55e6d9b9a8023c12932fa0998dd8301d4e34dc9d036a849d93b09a05457f45d18f5cf49cb3618a871503a8d4038d3da653156492183e69b427993fad15db5decc2e8a5b317ef391cf73500d4d2c2fc549f84b199b381d7a823400cbd2adc814031be22924e63999fb4b349391664440697a083395078834790b61db22dc1d8e9dca76b4b1a0531e4161172bd42cf4a212f282b4cc9db60d1e14e8aa30f9052aeb08a562cdc9191de9a79016be00e03843a290dd31037fe964efb67de6b97183de4690037dc58a7f52d45967d3d3ec6abbcbc1d8b96c090e6b4bb4f9410dc49afafc88a59d58a3da224e7d9f528ddd3662179043180aa14e395b2c95c3908ed359ad6b3a5ebbe8b62f07b64a94e88a68a34776d522ef3ed7672be284290bce4b205d87fb128d79e514b2ada3a37e50479e08ea1a4d18bb76d5e55c1db24328abba8601a189ad862d63842008aaaf883d6225c52c25423a41345e20d540d7f01528fad5cfc0f4c0f14392814ac0c783fef1d3b4b53c7d9103f50af22661d805408c61cb23329915c036a940131d74c946e0c9fdd1d7f10b29bec56b603edde07fa945d54469ca5b5c987696024f0ae25dec46de754dc20daa70de94a8b54df242cede6242783a2097ba2d4e88a67aaa800c534dc11745900d63a611e2e9e05ba1d360a9d07db3ed8f48f72d857dc42d11832e683a39e3f4d0256693ed256e20e3136f97b70155403ae4d622ce25e40f7b933ca0006a1a61d822d7cc793d48ee4bea378c8e8398465dee5f781a6e2f41479b99df38c33306b0c4a75176d4ae9bd48296606959d80df32cba98ea005515beaee594595fe4e7979c3496a5f1a3e6dfe741c725c9c7b18e7a8492354e7208e0b211879efe630f12c10fa7a03ddf191aadee745349a320a520b06c6acf5c899428288bffb0e4418b9936224a9593aa3eeb247cc32c62e30f7dd74e9ac46e31dc64d41f53aae263b0e208d9184d61fd6f9e5033baa441cea3d58de526355061139c3e705259207ea368c696d2f236747ca00cb52c6e706bb8a98faa39b5464029544071f4402cf155a4cbde7ebcc4dfa86a1f78695b345dfe21f1be74f2a68e06506c94623804fa86394a0e0b44337a3839103bd6934040debc80ba9dbb747f5a3cee0581986d02af8681ad31861700abbb9a9ffa4188e92bf68e8fd02e95aa9829fba53240d57ea4b28f8fc711d9673adee762997fac690a3f8a14048d647980650e73058018494b15e0cfe414e8d2a4820c48d6954e3dfb6a48a9367de86a736d2c1ccf406a085ff0c86284456f507fe05a40071a590270768dee8c325feeacae1ab454313f1cee1200d87772f5b4fe0dd03bf974437cd3da6c7750a043a03ab415cbc393358ab9329b2c5f78e770ed8a949792b3b4ff9bd4f6313fbe25f7e366a8e828da0203509121bb70305ab2ba3d807c626806a6324f8e6d407c27aad3b307980b0035aaa1a78a706961fe4f7fdfea8c206bb07997d3c4c810d5edcc5dc958f903ae8defbe998fb8456a33bf812896e02957328d843e51771b81b868d3fb8b53457bc4fddf3134e9bebb296b37153381f198cfd03ca88131ee1993296b0a8f25bcad8f44747bcef4065b6c91ca29b48004531d4708f05cc14524de3130c562601a135daea6a9a8f85545e72437d9b43197ad78887f9a0c19fcd74613564e6034c72ff15fd335351fb2960183b2a00840c60c277c8f002b9800f3911c28354699572984b42e966c69cdb1de53e97341482bdb54fc17adde30657a7a3261f2ef0367a06451a3cb046fcf04a582fb946060afe5d9caa84451fc5b1677ecc0363f27b4ecee7ce2adc57c910e9e1939e433408171f09b038b70569d3b32444ea5d152cbf26a1babf464c483f9702b7cd7d69954d9b26a3b54cd15924caeb5775cab817a8d2204a6da5d451ec7d649bb756b6b7e0cd472f96f4f854da2c3dac25d8fe8b3221c60cfa9ca03dc482e7c5630e9fc8ed5b52329acfd3d0db92ca0eb22f9cd653d019bf6f4f9cc426e27071b2ef0ca0d2ed0f4e82a69b61eb9ce05006d05108d1b516263f1f712551273cee562af6da0ebdd54ae600d4f5a0fded2505acf91008eca7f28261ba3ea93e13ba3c883f3f3fce5f07c8b78a57e8c9060d1055a583af8dd8ccb2209bfe156c3bf8c8429ec3ec251b005b6ed216711380d912612bd92756970dae1c4e4d94f13bc1984448710360e0ce1041c04369231dee1f3edf24267ed4c7fd1f832c1ab196603d531445943ff1f36c508665281994933eda8e7cd2813cc9c4033ba0ac4bb31a20618e14cee7bca876e56029a1100974ea5176425d6d8d852200e15bec4947777a57aa153a2605c94df500717309719d8f5591eaab2208ed58f1f30232518f2f83ce42302e6819779515eece150f5a26ffa95c8bc52eafb0be222c06bcf025c6e72f84367a7bd57feba1658c95aee46d61672ed0b9cb4852bb57c4718e177fe370efb2bf40db44ac8c570acf02de315b8e67357435662ec99848e6b4c89e13a4edd4381efaaee0d31d5174efe7d7019190fe71bc9c7c366aa8ffe33807cb07894824f10113437cab833c13d74741cb37b9394b8fc8adf59bfba3d4bd36c52e3f40f511ac6f14b82d2d42ca53940139fb1273af1c2418987a7ac737be9f3caad791b386cc655fe1e64e43e225fbb1fdc94966d1b228cf000d76a7fea215631a0893bb0278039f3fc8ea8c1f04497790a09586aada429517bfbf7cdd4d88407a08799c2b0915e3d9c053ed0b6164f17bcbd0ced7a42a0c9befcc7de90ac69bd6511038ad5be73ea6ce5f5be9ba57fb4655db823c88b4f57231e1269769c172c089758e512db065781a62565a6e1daca3450d7436536d6c1c0cbd9e84bfc3619ca2294e41431a9cabe2cdcf5c690d6bac652abfaf07c47b53a567a0e8be5ef98e35c8a76bb52edf1d628aab7321745ccb6bd7943f103fa2d610288cef1f40bda302586d4709155376cd5eb6a8003b88b2c26d3b7258f00c7a76bce4ed54cedb5a6ba53bd090fa6d0d3dffd605c7ee87223f81321bad3013ea89036690e1f95a391ff69fc29fe56176cf10369ff1a87c216c2df5d0bdf2a9b88f6c2087f831d9d635968e56365c7a0dd2621a4ad9ea4a5265d0fba4305e852f272a119355d17789ad09c176bfea77eac75eca5a8d0656436bdd9c2161be4f0b6e70f857769ba35a7259f9033219e2e536f4893668fa3877d21535911deb9bd012f0dd6d2dff8b5a50868f8b5a7f37686284e36201f458da2803d00cda3bce269e42145cabd5445abcad5147b3c55237e004cb09673d9156d9759ee4b89f49d250e47ca1555f14ed056c89610f325906237c926f07ee445e64d8d614264304fe95ee088a7406a63616fd017413d320432996a08ba899c356110c5d17c31df2241efad7ab19fc24bb789c4e6b59565b62d15ec1e5a8a294236785cd59cd926945657c0b7b17ca12151203808725d871a831510fc0da6aded401667d0a84a0fca4b97ced8da07dfdb210fc30eb4d95d936d1bdf1ed7e47164f4e03c314e528dc515c6eadbe5c72e2e4b3b00e0e7c22ee182b8b338d9030eaca18a2427819342bb1ae1861907cd29b4e42fa0a78e0a11ecb330d0fe275544caeb57e4e56d4265c426fad4e240e54de53119f284a892b660fdce0160ec3407798f26980c956f14d793ad2ced8c3d908f5917dc8db717d46279b180165c68f7bb516f357a958e0221ff53331104bcb56ccbdb92329791397c7c2513a679f867688c3b1f73da7918d8050b356ea9687a5c465aefcfd07a5946896756a6337c7728cfc96dfa87461adad2bd9c4cb1ee4db8f2f358d5b59039f9944bd67692435d3fffefee2c124064ded7e09757a8dbbf36c059d869b7467cfc837c72a1ee6e08ea5850cad45da044005ef57e98e4102e756947987323e61e25dee8ac986db33b83b5d672467c308511682094761aeab81b919c8e4881e3690f06a638e40c337b2ec07e35db5bdbff3a4e3b36b23aa4140f88149ff9ea5798c12d5a1a6592902f0a76b377a924946479cbb9262878476985e8aefddfd1ee4c0c5aec8fcff2ec7aa2eb2d28d84f7c807c8812b736d2c01d31cc687f39cfb625b69ac8ddc2b3a02f28baef83335b6b0af64ae6360a6c6d891f86f848a39c8c1c659f0d3b155f129b13900927705228b4b983f448692308edc836fffb0025e0cab41bd24e0870f2f2bb116c2107988a6eb2519a77fed1d506026fc34d520043a24d33379d35a69a2b95e8f03f674aab27b82c53fd41af35fb7b0ed930109136f84cbe22692f9b59bb25bc477b4592ed4102bff9f218508909661022d8e4dcc682be54b631c56c62ef79d3d6f7406d0ebb7c283d0a1ff379f6f474045021a66c2b547aabb0d8a8c8209edfa92fc45bc8fb915ffc4b625c1a7a8c0d26899599c9470aa6cfc262440a0ecd5d016d2b928d914ee71f9e2f6c19868dd6976651b76300e65dd6e9c573767d8de20b95866a8c902da19cb3013bf9490c4008f9431af7a520f202bce4c66525cf1bbdc42c3564758ec39bc9d95bcf147264aaba10535851152e61a684c3c1701384678c07a02a88b3daa3a23d3f8b0f3732380c8b6cc4ef7f9ee5ac7eead59a04422a504528026a8b0ca0441ef45f80bcdc459cc3c0d99a0246d0eb131963152d7c4ce13ccb5085584177e432c0099831d0f54be504e318d80f7fcb07cc9abb45457301480d1f5c4c4ae05b673ffc536b197de4a9971e5553f97f6d44464bb274b9f1ce2e27205514e61f1e9024f92757337bd686ad2088e17915d75079f86fb20fb2730dbb3b5dee87ed593146b1320eec85335a3a0aaeee5ae9096cd00cc80b6704772ce20e38b609d154efbd68d6560332d5ce9789f80d950cba39e2259cfa06ffba7003f11c6ab83ff1e3c73715b59c42bae8d712b521b0de0254d13ad9aec16a169b1feb2c6f56f4a914196fb215341e3e8d3334d5fb6d8d6cff60dbbad7f679d0d5233ae899c3ea97973574a0dbba1d0f83b83556410c13bf58c82822054ab4eb02beca8cab12bbed76d1a5c3e33f9e4dd39ca05da66c6af36a3b579b78091ab7807985d8a67842f4ad36ef689844c32b467fb4158f399b1119d3cb688cdca665b9b9a27356e24eeae61a4f8c4e23cb02f2f7cf9ad487dd017db9263b27fcaa2d3c8f75c6ac0f458ac5c96dfcf637b74bb22c21b79f3f92c96440f70e1f7eb6aa00c530ae079157c8977f8ae26b72325e49c0d93713083a0e3862a10b8bee10415f7a8d8aeebb8526d5214fd9920024f094a0de47b90bcb2aa751299a7615875d292b35759adbeb8ba5f3b54208bc20c0969f3d1f35051d2ab388c13bb8a477831314c8154777f644a1cfd0124a875163bfe57972861787f34b789f0ac09316f7d55d44890b36f7c6ae94ab3a9cdd26eddd1302164f7f2bb61786e44d4986b10b80786420ccd8824fa3324e9c3d74f6147f5e12b252a5f036d79f55549aa953b94e08365d6a8de2cf61b90d77d69ad6523267b0267f7cdbce692fa955dc9df8b6c2377cc42996a62615d8957ed5ab64676a47bdf1adb6406451e56d8612a14b5154844780133d81e18dbd52e471deb29400564c2e7fb6196aa74ed4f200d3a0eb151072d3797055dbc9d302e71f96920a8c834dc8e79a565e765187183987162b77202b406f6d7731b5d159bbd53668d3c197a3c7a4311725b6bfcaff00f49ca171dd1e74ac15373700d21738a437ca2da9ac4cff28a5493c1e1ddd8b27c6be41ebb83587c12ddb5158ed4f5ee787e31010383e3a994aedf3013e13517ba03506bdcb949e27783f72ff682b0595ed1e5ee67d570005a9f519b2e8d775edc8b77ceee207ef83aa61974557d5dcc8b6f9bbfa83d0ad07b2f7b6a01ed728684617842eaeb4fd78f2482bcc69ceeb67718cdeb5beb353a58b1f7360a92b8fc594b40a398d4367b6387ab80d53e6197b01bafc648819c414e4da8240315196c12e4a34d32d1719934d702aa72703eec75a7c647eba77c5cb0768a53686b628565dfdbe2769e9f9f12874809e05805011003c2dd40a8fdeeaa9128e0c0c56f321bd18d9518f8505261088b3c9acd6067236d0516136e30d1b511e0db2a319cb9e3460d145378997e9a6e450fb7d49cb2e0229e36575ad6de72de5505500e409c03f03b8f3457337e545ad867d74b8336d71293f8d9c267d1fbf924a73c60239eb4e822385678e30758a8d6705429d4c14423f2e3b28fe76acbcf2c073d008af375a5752a5ccf4a6a4f6cfb46f8eaf41630665c6a44e75d3e800e900110b6e2279e9e31a11f95dfb714281a12df5db481f7680be413de8ad28fbcb95a3d6180f7173560183820bacb8f0e8e9e6bf3d565f79e1b0ac9174ddaa83d8674987f04fa238eece8dbdff789bf9618b88631adca8e1c3c7fff2f6b7e221ecc56425de222e4a3f7c40fb8395ca4982452d1b3a681411276ec42675aff13a045d0754cb4992487e8f021092d513923db3537fcacfa2315c5a0affa2aa197229f0504065440bf54732c86a3bdb24ff9c84b9a9fa33aa6a2afe7154e633768c41e4a7a267188b3751da031ef821f29fe0052ed1fe2c7d5a6409f4876b904a1acefdfcc5c4fafe6f8a59dd32421c5945815a1a5067ffc5137257227dfbb299c5beebdf9ca502e43f22d704a554ba0192120e6a6f4b877cd23b2830d932260eb32ae5d3647929c9ac2c131451cc4f8f8e9903b12098a8efe27424a38cf9739b4d5b53b0ac4c67b19104c0c75ff070e0bc8ac19ce408b6b840af8ad0cb7bea913d24c7b77e6563853b72f189562dfb5897a29168fd7c98339a4079747b5640793a15a65fe2071f4fd82a9bd0cbc929c478c3ff29d3b8ee21508f474d95b796f4989938d4a79980d47a349fc1aae193a5479267af5ff03b2be3f08ee835cafc0ef15663912bcf9bcf98347b314500ac52abd8e25ba59d75c481092db84c30c6bccb973b314a209d77ac3dc74d1ee2f74a544cb2b015127cfd5839308178415a62a8a191403da26f165656c09930a7ce8484305e97e86e3037f0bf7753872bc63c07ef7803a17ee2fbc18be8d33298d572cf3e5319ac5785bc81a40241ed6daff2e6f796862662d8db1a022beeff70393695649efed5af5e8c5d96473382da8cf8747f986021ccd83ebc16962a0ac389b3fefbd5608d213891b58b4890b6a28be35c493c2fcb962355d5728f86e55a0f8bf7c39a49d288eac25a190920f264cb8067e88ce53c5a231264a0fa7cc311aa45eabafffd11ec36a7e4273c6ea21f83c4402b3aacf4527e6fbbd016864e3834a248a34abe22ade1f689cb08eb70e7e34c41419f2f51292809bc5910e4437a076424872c3c55fddbf32abbc1b99974ae0a1be11c990035ceb50e0ce480219a3a82750fa13c8e00a74b4ac8f18caeb4e99bb67a2f13c298a8fe9873105831b476535095c5843213f32b2ca01d6d362d025516f6540741f0d109b86f5c59034e4b4ea15d0ebeaf398b45c557ca60a094df2b723e5c7539f2d096173973c216e820b2b046e6020e75aa92afa29bc289cd067a17dee3725c191d4f109031c17b7d939c3aa174a339d0fc9ebe49dbeac18bd4c50521beeb208da03d711ea9126de9e611175c84df4840cf7007228f512daec563447fa1816807dc360f7d0735309e601bc0d6d2575efc331bff5f46e4360275b943e7cb69dbc2a04ebf4ab8bcb523922cb2a8c6e089779739faf8a40eca7cfa4cf7e26b1c073166edf713ca06f4f2110cb161bd38d077578382bc68292829fa52b3b2aafac9c5e14a7778cc9b256442d6015275ef4d7bf378d2b244c3d7d0c3e3c05723f87729cea6620f5c56645cdccba6b108cf976fbebc2e1af4d2d6b9d2df59f1e6348ab9565c98c36b346535a25797ccf00b8187b6168eda3a8f0104e812157bf2cedbe740e5ab357b4b7cafb29632bb6274a922266a784d2a5e35a8fb2488568efb669e46397e305454a5224b4772c2329c8242641629c8e249a1f9f0d90f862a3eb0767c8d87dfa0fa6fa06df7787132ec42fd44497eb25f9e14cc633a4b5e33931609ff1018661004bed2a3850a62114de4fd0affd5cfd2b7e4f5173da80b9de4db86e643e81d97af2b15c892daf2a32f8b8a1ac644a4fc2cf51e93fea74d056f4dabcd9dfbc7e5c212c9d1a064c29ba16a4d06fe618624dda9db00f2cdd1a0fd39674b6ae871a9b1fb6efb5cd927665517f8f7a0507a83ee1aae5b15bad43460317c7a8f047588a341a3e2f4803f8da804759f0edbabf1cc8885feaba1d84d57b24a6039ec62755a07092e58df33fa7c9fbc27d53ff3f246ede2712c79640d74de8e843dbc7ee3add868e8b24b436704f386aadae8ebf2e1baed7ab3c6642e9c5f73c261d189a9097c811870cc90e4752dcc69b1e8541e55d68e0794236445dba1e24eb06de6d1e74b453de1d73664887b5fd40e95b6b7f1e2b04e38105bb0afb23877a420bf4e363335f20adaa4eeabd4b65f7e7fe8da717c98b842b9d72cfae4339d1842f3d06edc2260a53dcb769f548d5157ac6c1f5d9709bd4a8805681be8e20cb485c41c2eda510d1ce616fe53c49d6a182119ada3cbdf64efb4cb17226bf95751878cb2e8e019731bf72fe5b28e25e2a8c2f918fc15999e3793936d4c94921d3e8cc04e28250cbc228a18a2a8fa40bf627b895cd31d1a03202aa09efdbe6448c5cbd83b67dc1e522d0672e1097db519c2a0d86f16cf2933c43944c51fdedb350a8ff522e36c1cfc10761e9b431c56656304c3c723da330364b49aba93badb0293adea114af14e343f2804ad637f464c73a5a9d12c04c9d137dd48a702af05cc718933d6b8f4f8ed3fc328b63e711704b0144a20f407b6f3bd60ad4be3d513b04f57f00bb52613fdf8ec11171c7d82ea0345aee7eea6de894b55203615b8134b8a17432bc84448afbf30eb3826ece53d3b74d7c3dd778b2341941fe735b75e2bdd1a0a3d21a1f23858d52e5b733baefa8979be0c2f1215bcbd8542f8983ec51106feb9147ce281368c9caadd0ec8da1e9d95236144d29fd3b5c4351206370fe29759948fcdc1e51ff363c93b5068029e729184f77304f61dcd487bc82ac26ee49e7093dd49b74d326ff743a1e8c1dc410101c53c4f9ee0cf0ae473c2df4e34485502bdcc731cf496ce60ec40cee1282ade8cd376daee40eb9fae1c5242a4c143b6e65dadbff6b9b015642da56f1fe7b33f32787e8f1027e1661de4a7004e22391e9d3c8e9cfcc1359eebecffeb4d604cfc439c6403e9ef79fc7b1e44655c31e691ad67094659c077094a001d716cc06d28358b50611923d50810b14d468611869e05a52a3d63c61c175b6002276db03be7d73eb95e723b4e594a6367be1d01dcf187fa38aa74457e3dab59f64013e5b61459b5569a839b59a65e51468076afe4925b62e16517fc9265c9bbbec80316f42854016778ac6333733943db2029add8deaf8300568fedb0ce15ed71b1fa5da381a2c0c1cd57f82e01c7b563359e90107ba00148a038563c6232a9315b87759d8e4e14095ab677e1fe5ab0b8b512f1a5fdf38744d1c58225c3c8c0300a5aa452851447bd0f6484cefe753cbbf198339326de0617366c65afc134e7e4b53932edfbfb157a4be06e4e1b96af15ef08cd4a9e767f60a1806d77c5794d80e6975263ca5c934d7753fe8c8df5f46078cc19b6c44e5117f6cf5080a4a46ed5642a416516cdd221d6504a563ee8f0aabbdc2a5a5d526d2de508091036d6b0d0f24799c08bf57f309573848f2a1202a6c2e9354b8b8654e42e3b4780d409e99f7d1984d367b14430f8d49075e1fa928095452412166b6baebb8d314060208aaa26202d2655ea2efa521e84fd2afb3034d89eb6b6c9b091cb3f17ab81f0b150157f6e0c3b383ca5bf1b9871b908b528e6db0271c9cddeb41e28f4f4797351eaebdf80d21584a77ebad47922ec3fcf4bfd40900350239ca144c44ccb3ca7105af63a8716a27c244200ab2849b5fec13cb8d385c24b3629cfa54008afcd46406e292ea6d42bdf9452fc6fa8026b38fd2849a07d3f0501a4b1916a9b83866890dbec2bb89dae4618ac2d0c1f7045a6839e12f78d8e5c4ae302d0f1833c3d0ecfa10a686e8cd5a8a7fa53f2c5121991f3c054ee5423b1a4620010e03f2db5ecc1fb9c2be13fb8088160e5333f19fdeaf100f805318740647b8cc1c851af9936160e941822cf71dbe6d0b5784258776bf6d05c381ee07901a1d8eb1597cf7f5802b39dcaf529a2cfe0fb9266e6d41dc405d12667a7c2356043e233f90a081d337de5e2b0072c079c7afd7cf318a3b614e286e49e6d726f330912763511ffac1e24fc5201bc61b2b7e8ce323996442b9f85a01eb0b0128117245d6b75186cbefcca30f2b8ce4461fe607af21fd80a89ba078b3e52fcd55fbe4c50b36d50e732068428638f889d593cce90e227b6655c881aeeb4be25c3b756431b1f91e1a7c13e9ae8284ba87af904fe80e9938bbaa9afa4e32bb6decae2129a6338c30683a9f5608a6c58afd38b136e70d84d98b22c6792a1c66b2b924beb8a2d1f4d32d9c3b4a86cb9903f24f30035b3ba1af3a3d2a2dd282b762049fb515f5dfe34bde9765c138c13959d835ebefc60553918682e6fbd3b99d33d31582da78ee9db65618da9b275ac71696e4927d8d73e977ddd11fbb1ba24a66d68314c34c14c241ca7db38e41e05c11be2a5e99733b9cef477eb97446504043290410480ef53316e6e2ce15049dea57e7ffcd587ec5dfc36da53c6f90fa43e905fe93f64b538667406a79feffea85bcc278de10cf163e98cbef517a63ae0d7441a2fe2959ba4f4a44daed445bc4343f78ad75a295b0ed6d7d6b8c843094d9a8f061155da103c1b605bc4dd35d5a44ac951558e2d56e5e0fbe9bcdaad40a8d4c135dd8f491ea03f2136b9199d7d33dc3ca537c9e303fba774f463a519286c837b85a9835b45fe4c5237fea4e0251245742a4a0a625327407d67ff187f3e3a4c926dcb2315e877474810e6ee7febb129660881924076f928a85a7701781a09b08d64a8213d55f73630148fcb8a7fa9181a3b9933b1f585ea0ad8c8988ac6cc9b61a2da692c1d726f4de4a7f8c01de136255e2c71d464d4c3b340971cd3fdf28a3ab438802ce7a306a82f6aa7f9fe3d3b142f410075326822fc9d3ea8b4f59f101625c734d1fb6b3687ee48c4569c5aedbef01d2b421545dba0a25db066d41469ecc74798315c29653594e0c292b18846529b80decc59600feb9d7aa881e917e9ac26e6ae2cd8c2ee46784e58ad6d4ac141dc4abeec205474469a57f741c9696d55bb3401564929f844524ad1c6bc4ebc47d5f5833f1e208b0b790656776caa3be57cd85a5a51584825971ab3d9ac33b1ec48f976ef9bb60dc5bdce9d4b41fd54592c62c70aa1e3128641b301897481b8c083d2c021c3cac72251c0765ffb2c09a2e8b6d1871ea6173b478559cbc237b30af36aa1c646a7d3c3f0958c261aca1b5d5398e2e0a390e2910db47c5b01cc77b94370e766e10bd469c09e2a48ba435ad33bb12245421a640c81878c452f736ad8a8d5152fa5ea596f0199d39e0cfac2944c8ddd03ee8c52f36c6fd70a9894d99c1f15ce25d45bceeaf0a18f9c9eb7425a4e4a15b4ecfd1597d00f9569952d51d0b6c4038e38f5ea90eac4f8d2d3499a2609a9ffe52379e64f5e431f77e4279ced7dc5a754509739b1f1ab8adb567a232a8c50e2fb253e18309c2848bbc43b8b5b46350e3a6b635b55ffcb037e1cf6231cb449d408aca51a3755af8bfde8d6cfd38837bde47c9c68252f12e4b56fae7d2e80683e0e68d3507677b688139d0e80527088f3dc5d98066611caa8e3b09662994952f0d42408aa0319713acefbd60ffb4e679bfc6978c568070bfced125fbe31535542cc67ecad20d0e225f3664889f6446fa1e44241b085508d16937b528d26a482c8a1071791287fab30a21423429f9cf5e1221e98453d8f363b03cc7c9475f0d9395a043c865b5ce2bf8ffed6b30d9d6cff35856f2dfe83af9541e6a0878b9a90bfa81cb19411494f63cd48ec3958b4c78bea703112e7af15235615f320e245b777b1fc23faf7e8c7d666afbc44d17b93399c636e7a1ff0aa8fe9fb5e01c38cff981df817598a57b4ea88658afe03ff7c305d6417fcbc36ced6feb9da0ba5d39daffdc9da3b732ad78698736b3fa6acd55ee710413b0da6d310d589028ed5afa29b6b7a939740140b68bfe41560b26b731c7251099b73ce50d5f363168d97a9ef0198ba2f2b119a1bcee339cdf81dc18ce988abbede70c3c6cfd825a28831c3c2fa63ee136315de759f25edb76692287448c619a13e01ef1b34a3b32db5eec77fe71ffcc99d11636146a8825fa6175f0a306b0100eaa88c4dd53381d24197f28004246a66efe0e7ca860b39b942b58d030c220300602ce699d4f3076a9261423d0600286165bb7020490090ebc5861d5f82cee24438937f638f13b83851e88dd4d0f6adad22053e28558a0c0bc370930fcb53ea8155c29ac589d0f9b9ebd0f991781f166989ff4df6d20994e22a1ce31efb5705fd27550b7bd73796fd242174c6ce05c4fd1f6349a76f11e9f1d7a353e9b96890a4370517a01804b4c894dda9a450d48bfb66d521b7bb9d0ff552a4f9f0228e22d60f85e2bdcae52e4dbd3b80c52c187daafc064410f34555cf32ce7ff95f8957e414b76b968687d96739aa4febca6e0f986d2c7adcd7bcdab5498b933bcb46c74107842c6345a3d3243942d6e2e20892cb1a3dd85018b36353e6a0d0db818dd2975e63dd7b8609122f90750e24f2d6f409b902804c66b30bdb1e4a8dbdd20bcf65076fe946bb83ec22e3eacb06b42afcd9794420bcee13b50eccfdee018c1575f1efd5f7892fe92ad1aaee3e31ea19733d9eceb47a62ccb77bf9e4e7167db3452d9f04b975ddce83b333cf4ad14c03da0021b000db27babb9767ffa685a79105425a8e49535a75b71d17edcb56d817ef83a6a00f223f21b1e158da1188ec4d3c549c952bb422a95a150d8510f0e747c5da206e49103b5d7fcc8e9262217fd7b941ee07f38e101b3db086dc12f52db7c076cbc5a3c95bd0829983416c21acbeb34bfa53984377da312e29ff9aeaef2f6939e191c86004695fd3d6f721f784e0f48097cbabfbbdc0e0e6e5e28b1f2851b8e9a77a0de3862ec9a7dbe8454e5d8980c478fd72312c0e5b423dc1269098f0bd102299ef7a3b42ecf392dc4b8aa4f074388ec04c9620fbc224fcd2f5a1a68594a220ab0de148f6e16cd2bc9accb64a1867c0608e0033d1d0f234a08106c7b4bd5e4a3f4506d03f1171a8e87f3a7da948b892afb03f8271c5625dd29a5c4932fa916b9f8747136b8928af3ea14e56466a856bec83e0e1e9a282c2871dffd7c06cc9e6876b0fda9146f7bbefc66c8209894b655d41c8c47a8f5254adbfd92bba5066d021551d65c5f2e357799d845acbd4b4b8a1269054a1ad8ef460f945ef4cc0ffc0d210cceb9fd472dc498005dc5f6eb49dab85c7406ebdcab1e3ef233a221f4c8c189f2e5edc103794e0a6c02f6f152770941e939cf09961db0e79472dde9f3f034fbd43378590c8cc763802d4ee5b063c054c82101ab3146c3c0eed846c7f1a8a3f8a523a809e57c52d69f0560ba7054ec32bea88a0272647bcb8f90585551395370c9adc5f105873d7f208ffc9a43e6ee188c7bd988a856407499c080e40795e0b07d9c27ec155302f9c13e894f6c53f059c727fdffbdfe80987068d405fd0b762cfa19f02dea7b718cd9e84495efce6460da18508cedd084b019ec45ddb1a0b00120a28365001916e91b527db63f082d80fec9f7c09f26a8e54a2c98cfc187e7b17cdcf0339375b9257b8d641011b185df25885deeb68fdb3a4e5c018929a88af31f4186cbee7e514eda4e14e5c07556a4fc0b3ee92ca59e5b7d0515cde57d091db5abbdb33c747cd0b50fadb7dfa029339290adbeea85468447c4ab98ca789302ea0032d73e81d719850c166179bacd82a48c4dff8a9d6c783a84c0bc831dc1397fbb1385605a8a014bcb3fddc20fefc051d4fac88daaf03ee6d5aa7d91512f95a0620df84afe89f2187d1baebc56719e91cfb8e231eaf5a03455dc2f8e3803763ee1f2684340407972f2b1a2b037f667852776bc82ecfe7e63fd95a24b170bea4913d2d9c57436adff5abaa92ca01afd104478ba1c70d5d588878490044ba4f7e73b8e507c79c9f293b9f5f5f246aa06c06c2191273493d47e0601f511b62f7bbbe847395886f8e982afaf2979ef189857c334353ef3996f9182274e469787b6bada4d5ee32e21e4ed30d55c39879aec4acb5e05aeb192330ce3747f42302b61477120c0123f24151e8f43e280055a2d1c32bc0acec773c2d819981fcdb9964c051e66e64f332d310238ab2b1c19adc4ce4ba7edf09e80ec28528df251b00dbc716d559e563bed81fed6f53f3bb11ab9f27faec3f82b50f01c1fe967fcd6d8cf82c3c31840eac89f10824df8f546c75c487e388e28bb2f55c7688a9bfbc974be7c08c8c8631274ed4ccf52205667158d48e8daec5df2f8b7320e1b13905cf8fb5d2258c0724acdc1e90c47b5d4570f0cbdda50b2ebb1518042ef522bcb0de3a4ec96a2d1bade345b93650930434d93c83bf0f43fef1bdcb9e1de39e07252c5cc523fe6fa6e46202479f939359f5693beadb30cde7dd1984e1f3ed382de74cd14844d038b7be6423986cdc1525c8b38cc8199b21f2e9615ad39c27b9032f6c8b66565bc7016f44361e8620d0930096b3704bf7b4c9372d0db1cfe6e0c7ee5a85fd3db6f9cb7a82bfb5f5369c88f86ddc7b5f098446898a55bb5aa95e0edc48e3a8e0836be815e7eb189b62662689a369a73f6a7f84ae83434188fc1f12a8276deb187c817a8910a6fdb31fb206f560fc42c61cbe0280d000a9c65ffc315fbc21aebc355533afad958915d41eee5fdc100d20bf69d69f363f2a6cfc5d06ad0bbd3ba54513fec60e3df6740db1a15954d5f00643523758f26b375cb1869ae2dd18b848f9c7e0713d7986abaed628df37806d4e8c3a416af30d3afaa25011d783a2ae59851a44a1c28f37443c0514c7d0c88203d100ee75cc9e0eef85928d09185109b5e46baf75e52b2f0e101867df99fe0096520369a676e98b91c8b5e1c94d1f77282c14b38cd6623c305799d4a0fc9713f83bf0980539967d87254d39bd2be5cb4d15f3ce216700ed1d06a1aee3cb410e2539c4f1bf3ab592f60076e73fd5732a41214ad309b68274a2ab3876a2c5f1e507cc7520e50d9dfdc4f0070d742f0b16a51913f26de880c4ca539c50e19dfc9e89e2bb8ed98802aecec8da1714f00fb42fd7f3b7301bcae10855e3122e5c3539d5bf8906bbddfaf503e8257d3926b004e5e556227ee30e02ad85aaeb78ade49e3591a5229907bd8328c9d96fa6f365d6f32edf965d673b17c5f0257cf43de5609547a490e91fa55c00f33e6d820969d29c080af7207a7f94ed757d5f38a8311ac1728e90b04682d0fc86c490ac3c049797efb1f610f0383c7486397ba94c5c0dd4bac94906f720ad1f3dc5586ddbb73a2c04b1cabecd7d846959d49ab6d8ce60d8c666b44adeba5978700fb56f76bf8fcd071886f59197cc773789bd0a6cf49306711efcd4837a02ffbc140fbf31505dff2d9f1f89903759fb73780ad7f11b4656a1648b06daf18f1d0913094743a2fae057e2fa0200371a9c972757b13745f0b6c84ee0a1d529134346ee221a7820a4b3ab1220cbc02377464e54e2b2d037d6d0264174dfe7b8a598bbeb270897273dca967e39fa40ed8d24b5ced6d729a4a55424f8665f0b19eedaa0b3b54514f05b7080a61e7986f76c07083617bb4dc420baeb5d1c6e24dfef9e4277ba0e4b4c1eb7665334785c3bfe1271a335ccb044045daf47f6a65da994fb27224e35ca9fe0b4a9c4f44ea5a8437867f80ff77ba929fd95e1ce1786e598ce86913a2754f673200ca5d26f9b341cb5800d966255b47942ac36f6af25828b870ffd9e8fdb0c7c313e12636486c0c45276cecf5c3ceeb8007fce1eb316735b4113ca95859f074a222dbc34a3cc8c0e367bc2454b90df4ff2f94733c8aa044ef35f9156ff8c84d6d09ce81be72e86828e3ff241fb7a26cbbcbe75d8446804a07c0298192209d0653371ba97cadf234fba9c0db58ce0611ab328f5a0a50aba16f5e0e799cbb681f3c5144d112a98ec2901c4300d14b13f6fb9f1fc49aba5ab9138e8bcef7a404519b70bb6da20047a417264fd8be11ec2bfc8368a88d8a1cd9ed97fb1756e9ea1ce81bd6a8ea25833072b743afc0ad7964535659a18cd3363ca5a8c92d8f25450d6c21ed99ff6fe62aa298112bcbe48e428aa08d1acc6ca68cf8104a8cd27c340cd0e10522e9a05d109b108f31f432cc814edf6439991d195233d8534ef5d036d09076eb7fcbd01ad39ca704c740c10be012d7548e254ae553e1973443584def1b6d6c564f05d4fdc15317b1525eee1631315338893478d6e60c2d3c985cea73960ae98e0a1b6a35597aa3b673049d5ae8fadb4b42f4437bab9693727aff7d90be42fafc7c0750f1520a94e0d578c854712dec1640256270f3ee5cf201fd74e7e28d08e6d3f4a37d8620b486260f3569a78b36e3867c9e97bede8c730a19e6b94209e9e1cea3045ad1b03851c29e75204129827c73e222c415efbb069a391b1151f6dbf2d909ef5e8a5d435293ddae93d01ff35a15b029048ed62a305ee5b40f855a0553079daaaef813872d651237be3948618149620a3713f1001c355f0e3a52f3bc4ac1ed07345cee71d2fd01f2e477b6c44196b7bd6ac4232a4afaf8ab11cb1e5806281e79ce721ee04ad2567ae6f57330f51845ae0bd43981a2e91b7e1768150fd584e6bc4b130177780a6c0cb3381394b2ffac919ebed4aa67f1c2310d58c09c33419ff518b4018cdb4501abe6d5017119c4fe0f987e6128cbe221fbc37459af10c0122274c4cd9f14b456f3b9205dbe8b7c12e6867c388074dfd02b818c478ae371e94efc2c823c6b3033ca4ac7274aad3c0fabb7c6e189f133d5ded7907d4698347207984ff661ef64644213c8f235ca68e4eddf8af0a3d857a10aa99ea1cdf8cab75ca8bb24c19a7ff9feea8b72d9e6a949c316213889485bbb3aa428f819e98adea40461d4075506e1227e4db2ddc0f901225b28ce871b135c86f21526ef612a0f8593c09a0884245a0cc881fdbc519e9d00f9ffcc0607908a8ddf7f9ceb929158885e5517e6973fcd28931df4587005b0528c626e0193fc76b95a94c65d44404728bdfad67b878dd3f05c76ec5f515257c5f119c4c8980b176ace38061d86e16fb1135422049a0822387518349a988a5dcba32388181a0f75908467b7058686cd1632b7e26e7623b0eab81db27cc374d5e222e2d3f66e0dcb36f4990f08e4c209465100beb5565ef7259dda40101400d4435bb1f6ffb36bded5e1090f1584ea93ce3cc7743014b9272271f412d814bac7d9e4b48d8a05bed2929de66b53342047f5be526e1b01a5200f3582dcf2d64d9fc879fadd1ab8bed6f8c486e58d808084b520d076203543a27c386259408987fe38e867c2976a2359d1462891a3c024894c13163f148e044f9554f1a640e34d0a8c0eeba6694a8cb06834a9fb5e8b2610d928fa4cb86fa1bd481e29bc8e9600f7177347ef98151075c1dca113d45a2a6dc56b24869afd4ca058d64f3bce421eafc6779e25bf742696f136ba0f54a1e0f08ab3ab93c81576a2c3057b232539341193319711cf46033b1831b43426ba624c016793ac57e9c90bda51a0d45ecef5b087ab32947b6fc4001a6ce58299fd219bfb137897191f487febd43df673deeab8326d5aa640338652bd6a1d05f3f099849ce547e8d9d26cb48a0e11f74dc0915359a1e3c68e9c14b39690df85d883a0c7a1ad9728cb8515fc3c677aeba77ef91827410ffc062479926111b62bf210199c03f53f87df98cb17aa84d606a779e8ebfb7f0ad218e172b072f6b565a2de33b262a13de0b9a2d85416135352969a26da75d7eb640a387e4e8ea2decaed0cc9c525a2d3a1e254c68e6a7c30c25831445197fce55441f61b7a85e8950fe9b2695423adaece64f7eccc7993d9cabf457a76c1b420e3111e7d552025362b271a1bd8b8f4521a9c4c018804860dd4d0fa2f796edb970c314a24651270ede7b98c66936b193a145497699f5d895ca9e28255a698027c12b98aee8225e0920a9bdac1d9a77867d6bb31a6fd61483ed4b5563f52a890f3557c39ea2ad795736e56b7fd0a23d3618150e2fb4db338115a231700a28b5dfda939b54967516a108380ff47229cfba6a993cda3540e537bf9516707984731282b42d54c26cf6f31602faf35007b7a8eeb3ae79bcba3732669c58448e53f0e9b54173fdef6542f126219747b2b1860a2a6b8ea01fb1deb8079c4e41962d3c002dabcf22c0014ca2c6f51f29eef2a8139fa21f8fefaf5d0d9e1afa09413de4d538a6fe08ff0c9ce4719728f9b2ce40fe55a2f5c2828611f296c8ceffc0a48d13aa730f7566ec51342a8957d7983346ea38fe59fb9b9ac057e448a87e642ebae0d1fbdc992159ddc69552b30b85f98629797b577808a9adf17e60e1e774f837f44972c62dd00122e0209e651ad3cd22c8bde29d4646210ec98030987186d3f03cab93d9860fdd11f87132f90bb18cc46fa7a513d346230ca0129fc090887cb3e13a7587d6ae1cbd7588f24796861eed3435f0a87264c73826795c62cd911053330503e804e0d345c8f108f6c9cc5a4a6a79d5aaf8575128a1ce89a663d315728a656b189a8518e9838de8536375d3e0ddc06628538ca69d806c601bbd0b6c04e23da7b50af2e0c3eb044bc090dad314f40cb586e6f10e834532a710fe1f6af59004603091f9be08e2b91a3c494795b35e6e768155ec96fad156c93675f264b3a0e0868076df0a703120a20bb4bd2ad14b85ca2213265286f0171f9cd6f6eebd23addcc1dcc031fdad106c49e44c4c47a6dd9d245073ad13a2e17d61a30ccefa9c5ace7bfed7ef937605086e4a54cc6ca3aac8aa15c43a1be754ef1b526d456ad6599f0892602be7e37a827d6c6afd6d1d906bdb7b9ab556a28656aea09c1c03c39cc13a4b676c24147cd7575128b7a8e6aae36594c1bf441add21f72694ae98e7eb0400470656cd23455ed5f7dc7ec57221319f373d145ba80650142f065a22b9b8cbc6e2103e6d72bdf9f52f7a048c2ac74fe503f12973645f23debccd0e77c376b04a50bfdb9f9549847e37b10406c2084482595c36ce11f1726a383d9e9433fd0e9203a171bbd59ae0c56d18a4ec06bc88d5dd182c38e85f4bf502a5e36d0bf81cbb3a0eb96c1ba48bff12d39bbd0214974a8b844701283b13bd6818a8fb22254ceb00e477dec8b9f3e656d7bec82ddb79639948a71006e2e0a0b78177149a3202106f507f59e2b58443b7f4cde8fc900e4b978cdbd1a61e4d1d6e5d22379f1921e3caaa48057345202c672236f5c7c1f06ad27651ee000bb7c032427d30c6db0f4e5968bdcf5c3e8073fbb0ef8907aa6dfd11b6f9fb7007b6da07fc845d41eba528c5575774efb48266ee556caaa4ad5a4c51f9b2acdf88a563be7118eefc0079356d28849cf081ec24355e6845d1fa139352adb8abddbbdef467d946829f702bf4b3a1ce0f8b64406418c176a6b91b40af1dc876207cb757fd5b6536e500f141a57a4a666c0b1a32d49da040c73c34b46d27f4ffd9f10ecc2f08e6dee44190cef2851e690c7627f2bf5b556bc121d91327acfc9cf14d5ff4bd1244dede5402b14a82f7f5227099ebad60698db2353a9bbc0d458260979404b739d5caa31e6442f440e28685483e83420c1474de03c27b1713759d6f23866995bd8eae4ce0a098a2e3657df3140a9ece24c13f20e77a4948550a23994d6ce89154546229798b9d4af8128d50152b240dfa7b0873ca076ce27de551dee95fab33cf846e985a31a64b66a764897ddd76356bd03795cbf05c82a918ef2cefe73ff87517768d3f34a4ab8405da410cfc046ecb54d66a1c11d2e59104a9fb41ff268ff08db382ceb7829e7485ac9b2836ef9ca26cbb962b454e0a8d616c12814d963e6d1787099aaa7411c2ff7c4b5c2a31d6347ed045a452b91b05c21e0b707ea7d76e5b475298051e608625fa09298adbafc815fae12953807afc1811a9cf8dfb8ff3cb4c1d0c4538ff0a9540cd788f69d77ab09720d6c6b1e2c659124db32b0332cea53747288e89672a040d86fad76dfcf3f4ee0d35f3c035757344698341d2530b4430ea4963c24df47d4793bd7df02de104ccb9026a6e46795b4096914d3a19c560db4ff943acf61de9b01f8a011ddb562fd05eb09e4fe45af439b258efb0f88fe9c197ea54d5a29ac0760402884000d0d4efd824d4f7936bc50d09f76fe61a08a327cb7a5b79adc33e41b611228decbdf7de72ef97075e073d07f152999d28e361978f32997af98b3240901c663374c065ada51ae57bc950652992e54f6aa87496fdd30e688a03bff207f9964414811dd5ff2e3189619738e68b6a20daa32a94d2bea53946fc591e72c45f8d1a327685b5cacf2c256b622d9bb8d4899ae85338704078434c3f9e50c91f118df2693ada8b407bf0dc8e16b5d70a5c4027a5a794524ae929a5944e39e7a454523a29a5301ca5a794524aa38a948210048a014cae41c423062f36689c74e748ef7c96f8458ed1271a11a911b30702cd77f74121911670f3307a34882802b6608670152f7d8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a8a463b99e40859224f57e4cec86505f6cc60097af14748160bb8125d1766019563fc1799c8f219bcf3521b9eb471084436209a48941264015d3420ba341228041214342020bd323ef9c3841ae5c358b294e9c94c7c0035c08630a0a046c1ea8c28b86f06dd7b6fc530927befc5f776f7defb7b63dc7bafea5e18d65a9bba1765adb523d6ce60adb5276b5d586bad88b52f6aadd5646d8b5a6b0da955865a6be56a65516bad5bad94525a2b49cb28a594524a29c54a97524aa90ce8a296d23e25a92424b592bc56925a659ce432486aad3a3a4092357756a26bfe8026f140988a0f518f50260213599e444637736aadb5d6eef55d9d99b93992357bdc9fe89a319838d767dadc9ee9e3ee4c286e1535663865e02a7626c19debf1ebcaca9d91acc97271a26b7620e6debc6e8dcba5f1c09d4245fa489fcb2259f24726bae413a0497c9098a1fb0a72c9f23e2181c055ec1c0377ce5036361648b2e4cd5d892ed903d97355762c518e158ae23281aa79bd6c8e644918fb135d12053eac4f0fdb2363775260ab7841e1ce998b1eea213b23594d6471a2abad70b1372cb646c5d2f415760a172df46267c7b24856f35899e8ea2204c5fcbcb2b42e47b04fbcd081abd8d9458f1e1548b29ac6ae4457cb20c7aadc54a29a2a4403cbc40c0b4bcd91ac6ea93fd1d51f90a93e30b5e7a5ee80a056b12243fc893f38d115a950b921ca51a8d2c429d429a2cfcd4dc5a95200e1a92f9deaf283fa840d5cc58681a140921563ea4a744515d454151a4a344385585099c85e1a86613c78e448fa135d1578a13e2db46785ee402fd02a4a3b325b441133926504c5892e0440217a0381680df4a1344aa0535822e02a524a29a5f4524a4f5824ab864c74ada27cf1e092257d6244633481ba65e3375d59c9b2bbf7cce9eebfe7cf4f96dd73a65bb6ea3d71264e960de33d59ba274b969d7a4f99299365b704ea964059f6c84a96fde22d73ba659fdef247fe64d92d67669a47ce64d9226f892371b2ec166fc9d2dda6b794913259763750770365d9216fb92257b26c19de9dd32d9b7bf74fff64d9dd33ddad03e86a9c26bd9b25c6c8d6de2d9365b7cc8e6645a06ed9bd92655f02d0d52ba5775f076c8d80389f9c7e10d0157fa2893cc4e178684943de67ef7bdddd5126cb7e8d3824b0555931ca4413f9ee70d761dc1de30e63927727e930c63b730748b2260f5d89ae598420aaf2430444e8089409926eeac438c63ffe31c6c7c77f8ce3c7c0ff678fe3d92347b226cd4f744d19e4f8cc9b9e59b333695005fe8d8e81bb39130377ee60a87e95ea57fdff5557a9f07f7c954a35595478b2cc19c99a2d38d1353f30656e26ccac992f936682608aff46c37837576648a954a994ea29954a75554a954afdaa5f954aa57e5258fe4c16c9924032d125a98026f12a31442f213985f984ea377a0655277de02a7686813b672f4652a99191d44752a9d45323a99111d55357a54646466e46b0bc01922c89d3252bd125a58026f140328fd49142f2079389d46ff48b54276d50a79191d369e4a79191918f9c464ea7d4479e1a399d4e12e614637ea24baa40d6f8489a1e39b3235950c5c86f346aa4932f14eefca285c8e9242272bac8e974fa49e4242232f2d3474e222222444dd45eec2038d1d55c902f37b245d6c81549e385295a9cba1e82ab6812113199446e121111b98849c4643a5de4271193c9c4638a3d32d1d548108a01f2912e4a7842e437da8548d73b2e70e7162126534888e9212693e9a610534888c84d1731858484d0344d7bb17dc895e8ea1ab48e6c9c6e9bee1b4853d73de02a7221211c17722e2424e4215c08c7991e725308c771ddc2c576f989ae6ec22746be9ca8224b16215db3b0c09d65206d1cb76ddc378ee3366edb42ce3d84dbb60d688b4138d115a97013a46b869aa60a53647912d7c59f92b66d9ab65ddbb6ed9bb6691af7eddca6691a0e4eb34856cc9189ae08049f989ed74e109ed862de62e711a66918a61dd334ed1aa661d876ed9b8661588c890192ac28d3252bd1155b004de26d7c10f5c8f1cdc448eb224c7631ec5eec17c3b08bddab1dbb86dd7b33707106da8b51e527ba2cf0f2893b190c5564f90ceb78c055fc68de3be7fdbc77de39ef9cd38806e044d702866e826a6464c21459d6db15015796ce49e93c9d73d249e99d94d21ad446cb44574c0e4f6479d259d3b4666140b2441ec87472ef0dc6d294c6a69f42ee7ec7cf1b7b9e76a653c4b090e54588b87e04922cad3196e8a2d0247ea492254694a5b421c8d2cb9b76f2b8632c59622cb2448eecb5c1dd9c72be73a3c949b330a02e912e280016c922c08d2e1bd004eea0204b22b864d992da9c81e5398a11a309ace0c2104ad7609e32c85481798999b32751cad92b561a8d5c462c231522200c68fb68343a696403eedb3eb21fb98c460fd972c867f3234c5f9a43301f15ead9c9a1416648c1f53f182474bbaf3feaa49ca32751caa3571f89ddebe3e3e3e3d325f63505def1692404b2a8102cb1a4ec127fa77c4bbf2f5d4caf80ac78234bec7328186e3c70e344b63e2740b1ff2a0bb23d24014247c79e18a47160ab5b687860b22c072d872d88923c8188dc80832171bbc095fd86bb046d8268621f71bff4ab61da4709774da700aeec1b05d0c4fee224669a6666ce4e073781d8ed68efbede7b311f580f4c0683c15ab0967aefada37ab1966c8ff9e0b6947a47f75e5e765f7f7bbc91f7725cbcb9f9e447f6184bc896722f3fed5bb3da4596d8bfb418d34ccdc90c9b1a1906c52cc420d8ba41312806c5a07b4727fd7eb7d3ba2f43826bcf22b1753b6e37011d304847a3a0faa806823269e0e54ef7489806cda4c970d0c4107db467274fb6efc9d39e85b093386812db1cf1a4993e66cddc993cb3a73d3b730057f61307d064da4c1d9c6c6b95af407c787a747670b2bd8d665d1f5d622f658699c6490d79596595554a39baeca08f6c7f81685bcaa89bd9fb19d65a8480235d7b26a990316f39b6774fa340fb6d4bd9ba19f3d65d6a05a457609129709306aeeca95074c16c4f871a85a8515eea6b84bf59a351aeed4146863dc01e600ff014b27a8025f6f037206bd2489be1ec01bacfa9074a38859a388d40568425fd7f642424a44718c2d51233f79328c9df2d47f6ee96d87c18759ca599373367c7fe524c85863005626ea21a79a2979576fd32fb154393b8e64885e8507b44ed591a04a6e76507cb59b9c9f6a351579ed168464f0aee1e084fb6a7c15217d8aad99ebeb4f571eac1c9640a93eda94db3a85097d877f75d1c4e275b6be94f3ffbb73d3becbefa6a972da5bf754bc44cea3e12ede22a836b4c85a91153a22055052bb183a360c8f6b4089ad86f7889bb0497e5b11ac9aa337146b2ea0ae693f39b6c6b6ab01a9ada5283507b432cdfa4b1d97efa4c1fb025b3bdf63d69a289d541b29d1a258a3e4db6873ba71c8e857559e60cc949c589e4fe6613d9fedb729f42d66c8246f5ba3b9d84f4eca42e9579b305de976c0fe184c9766447f6336cc07d7dcefed26c295a2644d3b72c2ad622b1bd4402840e171f3d31480c4e03b5d0f048a2ced83d675fb71cda6fb744ccdb69d87cd84add8e98358947ef8e0ec195fd0853a126b8fad1e50f4864b6eb97f65c5c5ea008b97dbf3a0032dc09572d43e7752740524812ed785a0d9b0fdd2141b2ef9b6fb86d6cb2cd8dbad73a25a6043257dab3b73ded22b56be252a7b74bb6973d9275d2257d1bb96fb89cd3ce7bb27d5643cb172711f36d6b8ff96c29b2d3ba2562be1dd79e7ddf8e6ebe30b45089220c615841187070b27c7f76f70cb88f8344984a9e136888858888818bb9f7761f976937fa9c36fb6c2021ad256cd1cf1ffd4d4369fd4e23a2bbed65a3c797f620ab6f64c994ddf5abbdbe995c8e5dc364f0933da48e9c812b1f702adb3ff94322922d8df2f59c37999efe68408d82c40d1282ad9215a35bbad747f600912aedcd1ea91259dce70c963dbaa46fb69370e7965a07a451b6db5263c512c092f97f642404bbddd741ff3901691ec9bd7f801a85725d94c973f6bca8e190d0be23feccf801f7c9211883848080833f6458328c8e76149a13449232599c204a72078921f6f848a44e7b53cec0d57c71c321d1df21555ef29c48d0b989807274c3724812c9205fe0e6e7e550a3a0bebed13a54cc9141a48edc6914aa5d97c6e9a0939c5226ad5ffa051367bef21127cf4f0b126fa24d0dce6c03e1be696f364eff1cc88987d3c9f3738610b8eed1285f9f467e5ecec0d6fdbc94016cc5244a345ff9081b251f7f51b2a331634d9eb1697481ab19d428584743ce74c9fcbd1c773a7df7e6e8f2773483759f372fb1d769f88b3779c2084c6ee6ee3c0f095410f2f9147b2918ee4be598f2a6ca0c5164302b69ddc1b902854b35e59acd39e79cf4325379528411a95c39f0f62ac5f318fe817ed27f94fe86a4f0060877801008b91e42f85c391053cfe0313c6137db9bdfc581e14c6ab3ab71a3ec0b2fd6c1fae38920d9abf4c4f48a61bf9fb937ec62d75a9a98972c6a3eda8f9072c485088bf8842cff99bcf82703f54f2592e14f6aaca0cb01d044b26ca0a85487d7764077c04108011209ff004fe1e9e91733148203193e5e1e0101d86d243cf10c1e4e7514fc77616ccf6060d53718aac350fd466ff8aa6c4854f771b0fbe0b5bfe8b44ce586436a98874cf157236b9f1b8e1aed69a790e21938dc47af05e52c6a5246095b76df06f2d6cd5c925e8d1aed49fa6feb50107627ff36ec105f3c838643c15f14fc08de835d8ae7e5b963c2256e2ebd371c351a0576347ee548f7dd53f75d179d48f78f4887df48211df626e460493bea258ca21dbc129d6197c40654b2129d93d8804a2ed197b01271c3240ce14a256ff5db804ade7173bd9d0e928c51295caee76047499af73069e1499d1de19c1c50456d0bd9a4d1de84f5da6517217622244be324497e6b3c6f760e9730097f10e883423a301c011d36b27ca68d81fbe04e061a450822242b3da88f917fd42653d89ee91fc551fd131141d57a138b8b5416aa9a42bd18e9be67169d49b2a892be868288492041fa8e9851d76e5f9de88ad0c49e5a9bed7532c7953e7ac669ff0e0d81de69c4468610c34e6aa9542a954aa552a9542a954aa593d682041ccc34d3ab2ceb0ef50d984ce9d04f4ba6742553fb6f95a9fda743a6a4cd87b6b6fb46f98344df1dcaf43c60ab9ed219361c8fa8e202a5dd1af2a519e6435b3c473f797637646631972b2ee5090357a39772c5242252ae78e3d972c51a4d265b2a1e018d72c5180e962bbe1d6383d85c71eda9b962ea83e68ae7a8ea80ab111070357a8f60b6204ab2c4096a8fca00c4a1361cb785083894d3e933d0282d4e5d9c3e7600b6424e3f5f00593247b200a270a79fafe8923fd1849efaf02053d973831c2832a5af4cedb9abb614ee96b39fb79fd6ce1346dd056e81e765b80c42cd6ebe08e14f0655175942311e31c645b2a64b779add776f7eb3a69485e02426800d315f9a2f4d146a76aff6a28ccc1213bb0cb38b1968eff2c8407b14126519d42c059cc63c5f12f06fb620e0df5c21e29f0c92e39f1ccaf4d545b214d0cd9a0490fe1d011d115d579a35d3c608dc376ba0c801ef65254a4f620219fbac91ac1c1d8f2ea1bf9763d17ddce93b91baef5e49e742b89add6765c0dfcc2178c7cca54bcc0385c2eee5eca50eb6f7655d8c91812bfa8bbd6e38e65f40fa91cd4d8cc930ec62cbd102c38644b6947babc4f4a87c61df81c3da0e95e2499c98f6285773244ba3a71447efc9d7cd89eebc3285b9d238a9d15e861bd0f245a94eeee3c4541fba3b812b9afb59a791b2ad98013a36a10522a11829a55185521a7dba8184a65086c22767521329aa91a5b92a69b5b803d0647e7a00aee6a3cac71d217de6ecf9a822292c997185a5429882f0139ada8b34e4d49e8e08b4177fa970c28911444cbba46d54b31b23a5f4bdc551cde8864d3abb0fd30e6146c29da915b0f579d948bbd97502d3b4d1b669244dd3489aa691b29336baa568cf46dbbcda7562344924396a98353c9f69a974394ed3347b374dd3346d9b983bc5f2b1f44bda4635e3301a638eb4f491a66918a6699b76d2865deb6ed237ec924422c553d2b69948a41cd89b84914899c602b6ae6c026c6917cb8cd14a226118866118866118866118a68db40eb6976931c61873fc85ad1863d4300dd33ed2300c2b69dab5ee6e29d8b7edda49dd1231cf574ccf617a4cc32e09c37cb55a2fb17befbd17cb461876efbdf7de7befbd17cb2e76b17bef8804081d2e3e7a6290189c066aa1e1914413e6a40ca569d80e254dc3fabe4aac625a0a56314c1b612791b0cb6e89adfbe22cc5a092b66025ecbe911861a4d2a4b9d8e651cda27677c024065bf5c64b72afddd6ea2dc9d06e16b2e520bd492452b66924a3ae757bc02c95b4e5de7bb1ee380cd36ea47714e9cc23acde5aebad554aad86eb0436d2300cc3b68ff4bb5d92f6fb4c8686c551cd48f7dbf5ae13a49196652312462291301289f411092361188661db46d2b46cd35ec3e683b65d5c6b0ba65d4dc348a312cd1b69d849d8d6c3d2b4f90cd3d33cc23b624e79a6c7e2b17ff25847a9238af818e5a5eca0a90737e18588ae1b4d8ae892f9eb712779ce9e873c797e368c3d49b403ca20c9275397a9cb3b5387cf4e32464a29a594524a29a594524a29a59452ca1f91651302cd8a2f5912146982c4f81723a7bb6871919b58c8f01014aef488b25d7bf67821888837a259f8f14734cac89bf3aaa9c40863a758f58b9fe17a0d67dfb63786f152e92198bb0c38e42c585c049b5ce0163f61171fc1a7bfc02347e1174f6d002711c7903bd670352f1486f1148e19e3951aa8cec40780ffc2d40302b1d86daa35c385b89ae8d3365d628f92f8668eb341d9a0fecfcba8ee8b43a87f6df3eef3f2083f4be19867409d6e395229a9cbd45329a9c35061f9f2ea12fb09811b6487721f5a2562466198ba398571c8a3f00bdc39b875dab33fe1dec1cd83bb073790f6c12d036ea00e6aa1a1201a962a7245b2b4d72231962f5d02d3367dc3c2d33e1a85a66b78c87646217f3b64fbdb4334c4eec52697ed675f4d04dc1779e213ee8d30f2c49e4601025b30e5de2bef9d6412fba259fcc046dbe7ec648bf5648bf9c01958c364678d2eed1c7475c49ebde79cd80d3681344a7ff4e97367f7e920216559b6e2f39e13906ba359164897d8df16bafde3f68fdb3f6effb8a790d53feecd6e76b167c7b27b6feb407b08edb5f77a43d91e0392edef8ab6a564c7ba25622e755fcca4df2d47766d74d24ea579190db1c81ecdb2345d62656678ae73c2e16c2c8d8f6cdf44d2fbbb89ba3bfae8189c066aa1e1914413c606dc977dfbd7dfec6d4fa3c0948f68a6b8be5e5cdaa34218bd825a515be42d4a76dae587d5c89ef65a8480bbb30735f34dd32872d6ccf737a242d9b641b1936dc8f0071432392349205b102539cb5868763b69a6645946da4428ae27e1f90cce0ab77b39cec330d339b54c8bd9bdf7ad6df5f75e8e5e877eb637fdd4debff0021c4c820b4e96226d53851073dc77db34ca28e54ad97d42b2bdd1cbe54e16127da3976c472f37377a0618b861a4ec19d8b24ac49cc250856f7b2d25695e856f4e75468de0930b1c81b4e7137f22500c8a42712812e118a4557a05b74bbfe07ee186e99e1127e69c8093382c327f2533f688f620d0dd76886a6ded99c681b511db72d837ed539862ed6d1759687c8d74d76a6d952ea96e31548211946004a5793a4193365f9041920f8bc9fd2cce80e3c0ac812b0a5b307f810734a1872a272c2edecb5a1b93e9edcc03a0cbd2449a2964fb23608bbbbd03a0cbfaf091a97d0360ab757b064097e5010f9c90ed8d580074591ff88009d9be08d8c26e8f00e8b25248a1846c4fc410d0656f6e8e90ed8580add26d10a0890d0210b0a5dd1e0774d929ec0b90a1cbfeb0bf015bdbed7b802eab630590ed79d801baec113e57b6b7a10374d9247cac6c5fe306e8b24bf872c8f627b085ea31c9f62be8b23ddf8c6c5f025dd609d0845a28c8802e0b056842a9b0c7d065a9a0e1c1966a86db1fb6ae822efb530597ad820874d92b40139a05fb10e8b25948c1168e717b136cbd60b1419715bac21e832e7b85ed823d852edb0568426f8b8aa009cd5ab0e5ba3d84ad03dc5a6badb53ceee5b8d3e9f73ce89aa7af43420e618b1687d0858b43d8758790071e0e610f3d1cc20004e0100a400087f0c68d4398f3211cc0000e21010870080b50001c8710870f87d0871f0ee10f871008208230408a10431cc2200ea1010e61ca2114e2100ef16c845bc7f0e815632f954ec2da374cba096f2358e4283cf214465d85539f01ab7e3cc331fe63607c00ecfa10f8b345995e8814030401c40f3ee028000106906f0820003df0d0b96811729ad6c5d25817eb625d689a045c24ca39b2240626bedc186728fd8c1fd505a5518ad2ba142f6bd73a8a233bf972a1a55a5db2ea426b89525a698eac34e7c4d11cfa92f407f4455fb08452164056bd0942a6348a4c690e32a534c894c280077dd1170aaa44631aa5dabcda932cf992443276384280ad105615a218802d780b40976d8926f4304ee9ab4be82f37d3f475fa475f5548b2ee8e6d89ae2b34853adb526fec8dbdb99dbc19d59bcc9de368753900be7908fcd92e647a21f067afc8f429f8b34299de00f8b359c8f441e0cf5e21d303813f5b854cff03feec4fa6f7017f968a4c8f0317007fd609999e00f8b33d997e00f8b34bc8f4197f360999fe06feec1132bd00f06775327d00f0677f64fa1ef067a7c8f43ce0cf0621d377f8b39f95e2b33ef82c0f32fd097fd6c767697eb8799e042b1165e06f4a91e969c035e06f0a21d37bf89b3f327d09fe661132bd0df89b48c8f433f03797f0cd2664fa15fee613323d00f037a9c8f426f89b54c8f427f89b56c8f437e06f6621d3e380bf6945a6cf017f930b99be06fe66d137c390e951f0473b90e959f8a31fc8f436f0479bc8f43be08f8ae0a325c8f4167f140599f60e9f7907d73f8a02e8b24152f0025b5c09a0ebaaa89c20d3d60a095a606bd404745d1616ea44a6a72caedbd202824c4f5760ab03d0755d3c9069290cd0755f5ec61004b6b422e8baaf171888608bc405e8ba30305e1882adcd0ae8ba31315708c196290bd0756564b490e967106c899c7e5a01baee4c34a13358c8f41308b6464e3fa9005db70715d075699e005dd74713a0ebd64413fa035b281fd84aa9606b86f7a842a699828f28d43821d3cf2540d7b5410274dd9b2240d7c5f9015d37279af0c0d6610bc3568cd3cf1cd87a711b26dc2801e70839671261462104e8ba3ad184e2c0160b177d45133aa580aeea124d286cf500ba78e80c21d35710f20f327d1603777f81639c057ef10cb3f8c5d95df89ec330dec21c09890c1934d050430d9e575262830d3366d0a0b15a0100002626272737dc80430e357440c121871a3aa0b06cecd062753fc69f01ff2a3cc3535875144e7d04a32e82476ec222dfb049c3a497b0f68a4b238cdd85e75b78f4bb2359108025f6d4de9d4c2d05122221092243860da242030d2a2b35d4b0c2e2792c2d25252d2e36d8e0f23263c6cb8b068d17cc6a0513030000c4c89898c8cc9c9cccf4b8e137f4c8f4970687e3f0afaf8f1c6a6ad8e8708372fa8bc37a0e3e6ad4e870941bd6e96f8e8d1d4e4f5fadd35717d7e979d8c8d9a1f5af5d77812efcd16cdfc21f96ed77c036300ba3601d700dfce16c9f03c6017f25d9fe06fcadb2fd09fe6ec8f626f8d321db0300af300dfc412064fb19f8b3c1be047fb008d9dec31f4442b6af017f7009d99e06fcc126647b19f8834fc8f624f88354647bfb8b275cc1953d0bacc195fd0bccc1957d0c6c822bfb0e9fe0ca1ee3145cd91f1faeecca5e853db8b24f611a70658fc22770653f826bc0955dd99b300f370a00045cd997b0107065ed315c8411b80170650f031f0157968333372bd924c31f332e399b1aa4d15af08e4f23374256e7bcb447ab4d7b9304def1698402492c4056130196d0c7888142b160913f0994e5af73f249c359336145d92b31abbdedaacd8c1fdccdc939b05542f991a4ed27201c0fd7f54b96d0dfcb71a7d33d998690a32bf403b0c5e254b2aa4b97d0cb1aee640ac9ea4294a94abdbdfd575d447c28bd94b1002ca1f7bcbf9ba803b7891264fa9c9c0cc015a5b18706748e73b2e1a88c165a70149c44c0c50f64fa8e470b174e062f33439924c31f333ba5cfd2e7909d51c94c9ac81644961d86e2b447e9ebe2e04cb386b315b6b0d34f20c43180011245d7d5e91434091a044479ce39c4fdbcdc27c7cd1486291033f68a51f316c5e2f53486c58bbe1a05a65939ba4965689969a8846a9a0b9b1e55686600000002005316000038140a050422913409c364f3f814800e84ac4454469d0a44710e23292509418000000000001000001080192a1000189a0ecb60416974b175a606993472cd82a9f3868eebf31c60f4cb7df57bb82dbac94ee230b79a85013a096280dba21b036836bcdf65ce3aac53db984359e72e412448c170d17afb209bba08878749bab7f5c1eaf9f4e8a26d6e4edcaef6aa34b85050a06a1be7460cb4d5612eae47d397eae42593aec9c4a3ad36eb03ec9bdc42b85c61a42f5d490649922b510905ea9bedc06eb8658321b131d8e90592bb4280f9eeeeeb984f23d98a0cef0f967fae60c38b26beddfe06591fbe0eae4270b271aef280b0e209f0d03f1bdcba180c2377edc99b4acc29911762c27db9191a0dad91df7d08f641f6223c2d10b6a66f9f006b5426b2bee1de217368eb27ae7050705fcad87d3fe7cd756cacfb72109d2612ba2f0724f42dad4b4a5cad4b8500ff1d82d0d760ac25e64376d9e1ac679f51a574a8a081f7deb1e619f63d82f5aeadfd10687b7963591c86e159188d251d40dc5ce77a0b3dec9744ecafb008e52fafdae893f3b5ffee06d1ecc4119e126ff342dcaecf95ce023fdd6072db01d0b696d3059a28283c80ff5f0d9f733afe6d54642ac216d675168a82e21a5ac16b688ddb439f590ee8f335be266bf7156d92648f059a5be7d08410ffc681b68ed2f0c3630524949024ccd0ed583d071f39e163fc8107ef40e1931483ff4cbc9384bf8c0afee9e13b21bce123f87f0bdfeee00de3c0ff0fe3c1bb8ef0755258e739005bd2c5861ad84d8a5d68b0ef11db3f61a33cc431178d174893423cb2a51af00bb5a22415f4885abf12208c9102e070b860e236667539f7dd10218bf4c1a7dbc7137ce749ea1c010134494c449dcb0340681562160030baf20f6f9014f44d01e129dcacc804ebd583bbef5dfea0605d490933d90fc4d2fdac81af8ae70f92d3853d80df4eef077cfaa121fb1493bcf61301b01f2ff00e69f9bf8778c2d71524bde1cbb7c555ecfd6fea8284bf6f156a4962105ed8000b1eb848ab08873565a4b38482fb00cc0898159d16c0b558f43f4a5c459c34b24eab2b110ce2c82100ac8810e145a1b7aae12efdf7fd5c37fd29a1f54723ec16a1de18f652e54f0eabbaa1ad6099bcbe22e2c29ac164bd3e731044bb23f1bc95d8bff8fe515a25115c9159214c4de35e9ea2e3bb4dd3159cd7e6865e492b5d53f80f8e385b25a867893c7bc1472f3c286b2488d7393a0bcace8f3794fdb68336359c2d88e3255b48cd53b6afd95576f0caaf2c19144fb2a524266547486d5c3cc42387d73f35e81e03d5052ef8db2a6c49b60485f607447a06c602054d3e1fc742dc21022920ad3de0b91468750a383e00500d62ffe4ffb790f3ff75c1a9bccf7877e7bac6d1a45ed62e576edf7aef13174f352fa10e8ac82092ec9ca7e8508876d211b336d325a22eaee437d34a3f309a5ce67ce2f59b44639269d8280bf6f101702902d1fb4070393eec633257536ed46f6078377044c6ea58f2f52844cad20fbe810d85c815f60936eac79cf681d55e30644a89e823598e77b7c780349ed6506270a1c3c3eb03db065e0cc56d8f6e1ba846ea0d30f4dea291becce1e201e3c1e25e0ac290c4543b85b5ea6dfc072602e0f0f4d15271335d2b58192b01ff604f04c1db21663524bb55c402eb5179b1fa40c8a39a2bbf5756a1671214192c04e1297e12f60407950c9277eb04d012204955282c800e8c17caa990b2576439a9318bf6145567562c91faeadef28aba4a766b6246fcd79d38920c3365b5562de91b2376a0cd50ecb08401cf6090a1a8d050b7136470bd2e861d13b9a2b6b05267468499d6fa061872b5d64e5407e611f42da6574ffb44b04eaf7bccf3f41c9afa948331da56b53e5dbd3a866815fc071a1158da10c19605179b08949e7d9900353ab663125c42dbc7c7900d38c71ab031692a735de98c5761730c1dc4008aea682199cb69223262c7ff688649c6e2c28351e87450280d0d4a18476b1066abcc937ab1dd12e28add933476b389d6a5efea2da90e7a04ef659fdda22413e4f4fd590b5bf7ee9734961bb01a5527695e45d95196bc14af29b52622bfb4270887254af54f70deaac48653d1225e2cf339433ca36dee9450fe9946b6799b821185aa34baa6f420c2e9e60bb3a7b87348155da0a6827e65047f621241e90f3f2605344ab07690473355edd1606a653e337dde9e6bf450dfc3adae8349a657a93c950140a86e70ab1b1dd282d6fe300d80317ff5f512b15ff6be18bf324b1e38a96cda1d7474c5d3150a6c93bb0ffe336b576a96d5848f92a472b1f2dbe8a85ace91a00ee47428f3a3c01a0e2b2d48929e0a31e1623eecd3fe2d667cc7f93c55c1c6edfe2202fb69f16c08e1945505a5018f3ae9bdb24e17555058a8832a60c1f9b0086761da6bca262591264946dff7cf1126d439806904c9978ee9a705223e18b9c5513321b7127ae9a8f029ca41ebb417a543be4ee4e6945860015624927be07e43146d3eae7d44aa44363f94528eac49b47026cf4929de88bf89bf08bc17bc137f13bc2f7a117e257a2ff026fc22f25af422cd0da20129c61f6bccf89d4717123ae671aaca971cf14bc0467820984371c551d3db73cb4dbd0a3d9a68daaa740dadbdf04dbabea7cb4b0426c092a2cadf9edef35fd5f76a9589bf7e9e5e368f677f3995d8be11168f6d3215b27e659d607f212c8cbe2e24e97e85dbc39cbc3deb76e005f95e8125b10cfb549e406f1fbcbea20d42b7d25121448cb14fe3f933859e1124ec59b8e1240c01aac77b325b85bec6b1c030941ae59ea44135e00d4a8e4af594838284f45b8b6ab95ab051cd0a0be8b8d1b2fdae408e2db582fdd6e429b2f4e66bbdbbc2549a0942c119633bfd1f6a62e34f697dfbd03877629b64f180731a30f50693f9fb660473e67d5f6f24ffec3d7a178bbd89930b0b592ae36cfc2d12dd02a9d7d5484f054ac8fce99d686007ad433f9be33bd25f85e26239363b2172752748b1e450e37f098513e27bde2ccf85b6c8932fd2b973fcd0392a7a44867a9527bde185b57c6a9099d5adddb4a033a406c14a084bdc0c5f7de1233690f8dd26c57d70370c34e36b0dba161cfd79f941c05c4669568f080e66a115ab4f1d31f4530c36d9c08019969c1011d19ccab18d7f662a20af83d81820e804903f0db0b0ba340801ca9e5569b108df70a5dfae411bacaa7cae42fb714c55b2f65f3289edc26911aa5423a9ebd01fd977f8a12859a6c73b23c08d462dbe3ba2b0d44d5b9215f4aa34560978fb000934955068898be632dd1e8d3235bdfcee2ccc562c9053ae2879064295594e3c9a14233f4939f8f367b5f9037cbb8471f1932c19fc557b4562ac7ca7d1acdec87309235e43e867078e7779d13d2377a8dd1fcb5233f48bda6bb83f0605878d41979e51ddfd8af88ee1fda8d20aa8be4b72814f3229789784bf02b0b89a1042050c21a730bd097bdef660c0ff74f93c2391ece6f7c1ba24be3111c775d3bf9c59b3e717a922b6f8e96f616755d247414b5cc6ec020f1b2b618c3d58aaa6c335a6cd9b49bd35ec3775c48b15538b386cde6a2567141a0ed28872853cd0108aed3327d6da29e1e16edc12613abfbbbb5a123449999b0617896bd6c1879867e48f5b85d8b2de1020aff1170afb6153b1d05e26a7f9e0d7a605e47aa2370cf006946b39b03c175e8295fb1c3e95cba5a78973ac6b0fd9d90c49f72c907a2ea76641221b3652c87a6e38fecb1534c2905f8e7beb4b0bb2dbba2f05898960ecace12be76ccde964224e096e3d921c99b5a6f6f5dc7f96ed2897d63145bdc56007ce1c5a4863e096d751a25e3d0be684ba68d43c1b44bd05bc65e93d3cd56889c1249c84938ba9234222cee5e770eb08584513911121a5d0df5004a128ee812421ec15a34e2e81a788ce85276d4e3e67b16573992e2053e4e509999f4c4c88286e2a26040f24883a3799cd1cd1c7cadf4af33234d60ce6b3de46806f2f9f2de6e3626dfd6d1067b821ac0fba1d33d7be48dadaa5c07fbf2751acbe85d50d09c65b585ecfde58669ca3c3a0f60a9bfaf79a7e069b903863aaf64d3fe0d049f4925f08a096a8059cc97be0b5bc9746ef4870f7e1a09b2af1ae269f0ae4dcae6f423b081607e36cc205657f85736ae619369db76ad1d88321d4c491c118d41f100592329ae1d8022072678d46c003ceab303360cee43f8e1b3d52a91d8ec13bc31b1bcbfabf759a86322959fdd646996c9f1b1f9eb881d036866683d03708fdc6d06be564ae2bac4eb45577253846ead0a04dad210d30937c2a21c00a9771e5c104fc623150c424a44080cf9334afde14575865f21b052f78a01fda0c2f2ccf2b87e109a9d91be91b081fd60543b828880d8dc20b57ddc592e7e791b6c6fd70ce476cbc8bac0ce51ad643dfc512b87ec13325db79692ea3f37a1f1c93fa5b2141818fed4c707103f735e4f16b28119e79c169a07b9ee9c833acee7aa68d9521d7dae41a47994e375bad6188eb91e96a94aba4ea01165e86552c6915708dd6499d664f8fff1825fbfc5853dfb27b225b271d66113351de1f6e07b27aaed6cda3f239287f01dfad4f0ea4d1990c514d20bd02bb2ee9f458e6e70327bcf46e14db3fd3304c84c00453d6be396548abbf683034436a1529c8e2f1e87c32fcf72c1cf504e39132f1f6c34c848c8005ab0688f510b77b32bb98ce24aef975b947addee08701fdc0a5b36ac87865e122c7ad085fb922f212921a2fb15b36200d9ee9e02b1e803adcdcd6c64ca31b11214cfa0dfa783dba3978cea5884638907dae9ff10f5b4f0e41e17f7992667d880747ad73dc22dd875259fb89d0a5027ba0d03c7e5dfb9974be82c07b3abde30fc76350a6024adf04074b40a9b55cbdaba7b57b63971e747aaa8b5a651da753ad86b0c600ad22ee67b57e086877a062025f1e54c92d5517776ad101d5e5e876aa5789998d6093086be4b80b6632e7128661b40c8a84ad6a746909f4171f4b19b129ca5aed6ca96451ab2d1cd8fc2cd0c93a5d6905a9dc734e70f8f36d053d58b06922d21920fead1a3fa8456101887f2aa2a4e543c08ae69a383d09c5afa3a5e7ed7ae602c4d5bf54705206801f24a161893c16c94aa6617f5a2210bc0b5161a2732dc34acf1529f1b60396d94bbb6dfd8f01cd11ce96dd5b84eeef4a8470d122fbfa64d12178e400fbadb0aa75256d143b979946a414151b01e388ba9c3db4f2c5fcfdcfd0ad6efd093374b50ff43e5c5749ae9fa3f096de89b36afde1d9e67fdca7de762a25f475d4aee26d0c933ff089fd32b8d02675d323166226b92975101280b0aafe792cf002dc621861e9aa2ad5efa4aaa20fa4e4998c4e5cfdddc2b417f2d0c122f1ac8ad55f0ec0f9332c499338aa69e3a09826a7e12fbb3d3fa98f24163897107fd691cdaae0318653ece65f0c17f8209c92e82f1f3cf39072c68b782342d62eb4608ec33b01dfd5e332d6b1000deee7fe7fe94e0327b773838517e44202a1c72b3e5b16584c7bcc2fd9f8db0eeeefd84324eda55a07ee8785921ac091f8d194b29d60d4190d461968943a59dc57417efc6b0e6e03399cae76aa49d296ae4b803c9b861491451f6743945305ac82e31641c03fe9585486229347632664f06841dc0d0d9867d8492f77a7b375571064213878a08b2960d13e40de37ea189fcce163e55e6c01fe5f40e43255a7f1dc93543c6f19b2351a120f92dd461241d475ef600e442d8cf4963200ad93453e02914b7b65b6e8f6b949c9f41ff3a39ca8d44301f4bfcd6037518d4649baa0dcb6bd9b16db82312ec0ee93cb1c5bc32c633f850ff2a88cce7df63ceaa04ea8f9212d232a8d94be47b7412ae154b1b8f2482644a9319d03e686ba5e60b770ae97a3544407aa7c223044b1249c51788d1f222061ecdbfde2c5ea6993e345576f38eca1184a801998d0c6f55341276c14da344293a9f0f11246f175cd51b0ce3fc2b8c90a6c65bb332702fdc2ae684ce20e7e27332d6ce8fa161dc8e1d610113c474567999d694baabd54e174b7cc4b6b0b78bc98e2e826a69200139e05f85fc4a784bbdb655b8b017b99b359897d8198adcb4021a95d297030758e888cb9b7465a04c1075a46c2351e7596260d0fd95fa13fc65869b15540a068403ff6242bf57c33db3b1ea0ec4401b6ff2112392f1b9a2cb216bd974455b32b38f11535b41be8950e88af328244b5b2104c77843277848a8979274c37a829c1d30657cf4a3ab9fbd9428a6259efae07fea8afebd1b8ffde5e2d2e6d7dd3d6f18d32cf1e473cd27d2840fff26eb1c0507f77152c1aacc21345274f477e7694098cb247e61b75f576d832af403550468fa43caec028e6e5a74b9f6590cd2d7d55bf9b35e119262e6ec5820b56c9c9461d2f179f03a8a98f7683aa6e8e7f5396f0d85faf9a4c023e9fb6ea8d82c5344d4b2c01ce12524033ed0a6db1fa280461d2884e0a5825c6e2689fa9a5647e783ea52c38bb2c3e15bdbf0f4e328c524065c3c1e93a88c019462e394bd003151a7087bb9d1e9163e6ccd897b168175b461ae053ffde95ebebc152e2c9fac850f58c12a416cb9318e5fc92d37060d8a0003530e333d692d3c27d4c349098ae7234b419b442669abfe70983e6f09ec993cff383a945db93b179ac02e10a50c55b0f8d98cae82f47391c6988043759673fd130b1b08e4d33fa0903b826a9815be5855f2481d9b88af3ba824c339ed8359166017b3f4f26783c060ea49b491bb2004c7d9ef1118d19678503caec7369a98d016abe9d449710b3c201d892e9c905ed66dc587a238160c0538403c43a6adc9bb2e3e9c2811d385508598a0b8c1a0df8bac8337eb1bb5ed7d035c64e58207ce2c345461b292ebd97d85bce50371b138b77358076c9881846f8bdc58597442a03e4f6c79daad995618f3e1945c1e07f7a3fbbd30c0e68e29694ba654eca3d814c73180e032181dada27e28ef98518e9bd48a7bbb5a206260eb7c81e0396f9c3654a1303f8744f4965373b7051cdadf8d4dccec795f7794c172990bf4708f1ff98821ebd47e47f5d408305a496d81078018320d40596c8258db4920ef85fccfc6f8ada8362dc8b8ec53a8b1ae76ee96802ef4765fef39c02e05017106a0aa4dc150cb0ac427b5cb718341f302b8eea1d48c697adabe4dae0099591b92a84ab56bdc8cf1321f36bc1732e9b6ee25f387486f16baa9ff6a8c00f26f2fcf34bdcecec7be3b0d4646206ec0b0cb29b42b93522350bd5a2af30d15bdff17439d2865658e682099083caddb4d3e975330944ca59cefc187250b878ff3387dee70218f94596cfd8efd108f691d8ed5be005e9bae42460a128157940a52752ffc03ecf4bbd79adb5436f1c3190189706c7bad90b70ff337a89ff9b2b5a60356458b27a64ee69822f917c5cfbaa9a214d3b014ee40bb190cc5a18670111da3e66a004243ad5891e3fe3a06df3ddf926a5f375c024aad80e53083157dc70b3fe593fba022ff71bb3d54d40ba88a3f49dbc99c3ee2c7a4e668ab26330c0b229806b7c3072f3c02dc0db06bb36a3cf999774185447017e241eb80e35e889822646d424811399d2affafec9bfa098c02753e49d440e840e98f81f4af6a69915f0e78f3adb9f9c3ef939e4ada7643ae69eb545b68404944e033a0b0a2018c5ea3c61ee05a9b983fda55eb89d8a6350f0932a1cae6725f86f629914dbeb29a8357e6e2f2bea78949fd95be4225924e1c8e835dc94ce652473516949be4fe5f77afa4006df5bdc404f7355fc3e81a0800691f0fd67c6d5ac76e0eba2fc890186e64ca09c2adb59df0ae782979600fd816f0619ca8e8e174442ac5dd3ec6f055dc6ba99fc0d1ed65ee52d2a5c38b6cd3fadc97466fa944930f5456a47215ce09c692005e87c77bc337376a3eddb6e5f0a0c3c4b4e43e48bb736529793ff383c5116b9aa8ab2d3884675b3c7dbbbadc1d452a3d951c14ec0f38f192df7c11aae8ff5d23eaa7512cd627887fa91a115cc5d7cab699329a324ad68fcf3a4845a597eb752da84a2571d86be6893ad7880c9aa1cc2ff5432778cb08521079c97c181944f9e7395a793b65dc280e48d225004e58d7943e4d8c9c0f934d275ee12fb057d739f485b89987b45539b3aa9f89d235f00800471ecb5bc4304d3730bc5110a3da1b4e82332494e545b0accb493750d5017ad688b5b33ccd2408b4fb2118b5435042beedf66cce5e76b3f0eac3c28f93334b2f1f8c6ec4ef0010b97dfc89b5764f3fae4fe40c193428d694ae5a5f06773cc4362f588fd4979e904085caa890afaa2438ade2e4850f868d61db78ff04ea0f15d2d5d1a98f3429ade0efffab6fa1a028ac23c40ea8b1bf57c9d2392c2ae3d2fb88f9f519a15237d1faf41f498fa3b36c2f5ae61ae5349231bd617058e0f4e472567b447d9f716295bc0a8f4bd9b16ac7c7441950906f9e0b49e1b555a3c93c3372a493ec1b22143210f573f1136045b41430e73f56792a59a39073955e44519ef110b62cc0cc1d10358c1ec10d8f62624e92e44171d63b8b27fb14cf474f4c8b52856e69f00d6657eb0accd7513b349f770a65e84a96522a916b7301461258a8fa0f4809ce5b46183a864e79cd253a59f4a8da35f0307558c80a9b63db18a30bb74180276854952b355db819bdd5c7eb15a83b12508a51d93cbd6483d412749418a26511659aa758e63639e1e78c55238438d165a226ad916b08b6defbdc992b4657861df2137f843df3d3d6f5390cc2c64a3a3018ea92000f24b0c844dbdfde58a46086ba7cb5804aec4e9200d614422a434190b380125d6fb8003840e68795a7480ab91c703f7e8dc5666623292ccb7864bd0cce2040d2f538716a64499eda379532f5e4ce0adb625099d0a4c9ad83fbf73c2200a8cd122c7c68dab19939cec0a6a8ca7bb3adc46060ca38d3662020c030a1ade7077ea56880fc81434a62ee1687c22097abc21378b6978cc186abbc5e761b2beb3f5b89e4340922c74da8b9c48f66169abfaa7f545eb274579afec0d95b238eb0816996e5367b26af3b6740ad50c882106b94dc73e1be4deaa1563120416b83fa3656b4ad252182a9a02852ef9d5a7d6c6ba6291b0e415c42a7d0adde6479e6aa4e384ac341f6f2e572cca421737ea7a49de79e4de07f6a821b2498d156acc548728b14009f62244b15e83732025e0da58a1cba964e7b002fa5d4b65666d2283044957ac1976f00e0312a7795eb04c6d6f849aa596660a089e458c5f00de8005f7875e2e780a2a837e48bce15412ec0adef0b2240920981809c64791e03ca8ed0d772d86eb14e00ad09f9e2aefe7caee1e6b7ad8539146bc4d2cfd4e542d35664402928386474880c784ac3b0030b405b97c9442731b9d5e3e613a7c343a91a1dd3b8a85757e44c84836efb0d7b777b9b3132743c53693e42bd6be89e4f2405b646db9f13586739738b9ede1761f0e34d070d53813cd8f5298b61b78b10de64a3cd6a01863a225b99181955bf70908373d4fc1e33504f94648a46177cff48ca4bf1b5846ba4ccc7e10bf501fbe69c34713e38dd86f0a783ac86cb32f6b7e0bd69a7bed4cd6934997c2a3fc3dad274a434076238aad2dd2a88129794699f481ce2a14ce953dbc1af1c30a46eef7821acbf478beb8a00be9f1043249c7559282bf04d05068c38ccbb405ee4c70f3966ab161f42e23396737afb37832e53eee44745ae72620a5f431a1221ee815f746e7a1fdafcfb279f70940858ce9e271a9a0a5ef663d85380bc842b7308ecbd96c8b15b5e3330da2f740a55563da00e711c379478923576cc852a1858a0b12f70034e312d47e6fa0c2e61d6d77d2dea7cd58884179a2aefcd46beb5bda4194a5b5758d00447e98b637bc3956ea2be83f4856de70f2e3166785accb2128e736507621eb4faba67c60f50320300daddacf18b2cf2db9c177dd93a8276d25687ba6b7c44342b8cd995b742d17bbd6a5cceb10ca3a7a0209f9b74beaedcf4168f78a4f90bb603bead01f771ad6c88c6601e487b47964041d98b7881083124e08cd08fae7a24b1286373d60623c05b936479bf9bce147ae59b499aeda2933052b472c496fccb96a08b828dd4ec257522cbf5a60086033046bd3ce079d54a369f52cccca20e0caa47f6b0d4fb25539cfad821b5130b07143d567b240e58bec9cea9925a3019d389d5c6327171405f4339d6af94aafa168184f4a26d87b0d5b4f4ae67e5a322798e3599f7170a2a5132f49e3fd3f0043dc8d92603d1013fc68ac96eb6c35601b809709864ddf9d165ea86d0b380cb0ffbd23ff79e35a1d4855b0f679b2de35abdc139628a120e433be73f0bcd9e16d26b7878db2b4f02b039dce61912d162f6d6516f10b9d572c2d235608d25ce6bc284e618c54166a059afe61704da5eb501b3e0f0a0fcd99a212f5553d3927df3239a419d20123fa56d9cd30af4e96d31271303e51a6d7c6cad9503372f4b37a9c4442bcfadd219787cbebacf0f4a62cc53347ab312a805cc26758e8907724dbc429943bc838c42b43d6d92e1b7257c7e1c5001c93214151d6d803ea994a82d73ce83cb4ac36bc69cb6dcb7d538336816266f931021bcca6766faface43ff3717f711994a6149d2b945fd98db59e63542a745a7b5108dd11426af231df0f1057c7f887dfcc33ce18454da6a94f63246434afb929162136a0f883bf934126a28394d971ef94fc1cd8e8330e2e7c4d35b42d570589ac099ab87782af1ca0fe11dd16492b6efce54dad0c62a320298c11ae39dab1d77aad6e5eddeea6da902836dcba5e62a9bd0d9e859bbcb3533f5bece7100289d9b3b43d17666508443f37ffaacb9fe4aab9e4558d4bee87c757d9996746bdcb9cf65d334ff83dd8749a44451aca5bc96e39f2d6c3926dc7766e6b1d5663a32e4b8e02015c64bb276404f52b13deb4acf9cbba2b46aba2091cdf85fba020f99cbfb20e4d4aad2e65ccb1d5facb4a1d8b053f36d2e661a1672871591f223b8fdb5ef53b29eaf79f7e5744a1869da57f1488fe5104fde44df97980eab8566c776e40fe601552ce2e321f54865c1e8f255e996944b912bccba010b8aeaf3b998cb8a6f6eaa8c9d9da6b6dfbcd356f24f3428f58f1d02c3534cb64a156778c55175c4f98b0acad31c5a42933b82ef1de46169074e0415c58256adb237259579253693c830b0f2c5304000cc856aece42d0208b22b02501092dd8cb475eebde8eb61831fd5c79ec438f5ac8510512436a5c9464b6987353574a4f2e552d464b298725b470f9490ec7b33d4fbbf5b31c7dcf15e49335669c2cd9914664ead4ced91f3edc52621d236ed5da232ec7e927024e709c3cdb031d293782680cef89350c9a412bed672805648832398533e77986bcc6a9cc1059494e52a1ff3538e737eb8fe85a7aa77113cc0e17312b6a8613a03f0179ca12528b5a524063689c32f2cdb62a2af99a62aab8ddceebda1a4732747835a6d2cf25c8a31c7af858aa4293b9b920950ea6b843db64bdec8715fb01907574ab2f3d11bd497a6a6e662eeace165751773a04abd7eb3c9b7008c0c8c14ed5b744d45c02498352409497d2b2c494c95d64301504b0882147da68a95da2f07ce022d72b51d1ab4350d718398d221d69b008bd3465e3c04d7926789a10b08402e2ee9c2cf7d8f80bad8e5204ad0c2b4630f49f5c23aab09466235b5964e3975e942802221f6e0fc3fc691dc5f87d396ce2802d3bffa7141bd7a445be5f821b22452267054da0bae9f9509bca31e8666c188d845d23558cd9650c408997a68162e9cc9b36e37298c0f7e96572d56c90f7cc04986e3eb8fb390cf1df2aadc4e08fa283ed15d9d99747b6252c681b09fcdb2ede096e37724da314d759f1ccb0991e2b4bc88091011cc45808d0174d25a4644be38e19c22486bb5203d6015ab40867a45d02fdce1f1a6d3674362cb6aff0dd897319286a883a3aca759e9a9fc5901fb53d88d12385fc3ee02e994a8d5b7b28893479715c90a63a1343c0268f397066f02ae3108829c95394696b01c9421179cab5212cb8181e5ab0684abe44d089b95088a0211f9bee1e990da3061f4525fbc1674b749491869cfcd5ea50819c6dec4de4a65006fccf490d3db99689982f13141f2717f9070725a6df8ff4c29725bb075ddb13b37899fab0302233a905e009a9d05bfc10e88e619ae64930e524fb27921538bd88f4c0a924c3742a665ff21fae4988f28a7a465cc18d15c3695888ff33b30d2b94227bac16042d7fd90ea0ecd5865d102000836e8dc0bba65429d866476b2615939f10c4d9b8784ffc2097d7f8b51e4e30d021130b93800d0d8bfaf48e050b21d1604befc4ea8e1e6af8a017768d80e735c0a110c4c3385298bab33fe519262215026a7200fd55d0ca29f58f393007ef8cb5ff819510500f7c00da0764b4b350139f9fccec033c83506a96b0846fe85d26806df4d5f1b51537f51197d0051da7e64f15eea487102c61371ba823fd91ea0804f5648ad4735cba68cbe7fca63e8e7874b5785e3a7546cbfbc8143858a77a2ebe1d7e0c444a43e2b374e67e1931ae5dd34632002203648de11e9fa5d4e2ebc175fc63078da918f19629294e289c37185016de53ccf3e3bb26ed8a85676e7b145d7e91ec592d130452d3eb9ab29842b8c8fb9ddb103b2493cc1101e6a1b0c8880503cfebf3ffbd1d77d964d806a696775cdb49cfd5c25a9bd374bb832bb63d4b7fab0bbb1f21842e34ecc7a0bfb164b5a51cab14e54d56d95d61627ee75b9d307cd56e96ad42067c05f925b420eb3bcce48f2e30b03dc8b15e129372213b5f0fa838d685d56aa0ad26a72941018dc822a82ea4035f8cdf7ea9cdcae84d92336d6e8f2eb6700cd38fcf27e2532aba0a17dcb7fa3e21fe40d4901a3f88c57e8dda65a92d6c2a76299c4b1f7628206943e2b0576b87ab0d6cc6e6a5681cce12831364b9387ca3f5cff53f60fcf71d2642928c1f4163bd2434fd68eb9c74ed154edc22e8fddfd4d12b23edbe4dc06f7bc0f040fa90b7f96169e16ce62b35e2cf1eb287588fe353dcb209d9632171c2e32b0b8ecbc008de7f142d8662d680ae3e81191ef9dd33ee857d6f70a7ad9b4c8ddaddbe822aa208b7b98a16f5ba28f36ff64326d4cd53aaea0af088424ebb381471a443a4591e89ca070292f51d74f5568b80723397263f519d21908b722355a30a744d99b1fc20e3138479897106c01d047e0ed696146f8258982653e9b4a16af056a44a13358082b85530c059ba53ff21b45699fbd24a93eef3cdf397bbc51390f48264a1a47498fc48c8ea30a57394a25b62df037d1af3f140a569a5c37f8aae39f4711aa8169aedb420a883de4ce943c189000eee18a9b55aaa54dba182928e54e8437e80ae76378a36aba5d3acb24ae8a0511a5e603a06ccc756b0d7116f7d6e619346d268185fc4cb48b8560a54cda14a1c009a7ccfb9c9d75727d77f239d806dcf4cf7bdddd54aef26bc822df344228bed33fc4185cd95c6fde673cf830bfa0d27bd77ff9c6029a0c144a8c480486717285928fbf124f417616e1af65affaff10e87fbef0afa133c6a9e4aa5ab3e1e099841c3bad5819a0f60360ab05d1bb00948d62d03a9aff6853f58eabfd8562c59069d41ca1cb848cebfd3e06bd4203935d83430209f82f913de592acb0cb217837672047be62369546f4503bdd66f480c73548a05fcc3cec76d6a64331ab4316e51d764aaeb907869359217b22223db508b41b11f562d6510473ccb8f46037af5a9c5e32fb88dbdba92c641e9a71d30eb38cf10b24480c718279b2bf31867f664ef1749ff25e960e8b2b81120e5fe24ba76737f471e3d4aa023ba10d2467ad4237931908c4903fedda6afe4629be543b6ebb48591ec77de89a090fd1a706cad24021319a0b369e194e089c02370a85810e43d2a4b89e111181413fd868663eba0bfbc84b8c19de8dbc9e2e50ced04ba3600f41d1fbc80c6774db2c592d13c370c69aaecc6282872859b7a569636aa565d284b535533a430a7716a595326f945cc223f31c6e3ea6f30206379031999feaa343195d586363b1516089ec274b8dccba3ad5e2ae8f0d0457fe384aac128b45623dc1f2293c2e53f0e4c9f92d0581e6e119aa97780da70664b70ef30af53a2480fab70acd110a64935d1cfa17aabaf957a45cc95dee8273a11174c9094222e519dc2748d0f19b3616e0d64e472807a8bcf60e8250c7ff44e6315ea96335eabfe2c29217bcb3e01d64fa508ec58c1d28c3086bc50a8c713fa13b286177ee5c5d51b256bc795d6b46266d043a96aadcae45a14cb18454816acce306d1ab958221b5104c63ca6c5325a0359f7c55339ab19008d47193f2b428859b57e585d51a8e3d49c41fa181c3b5f1e4eba6ab459b712d19809e1a8a2ea00c7425b98797c50c269a2aa8e7733284104ba26f7b44570d985b7a056726a1b8e9a631529da3e2076a0fec5ccb600044645f933a94d9b0ed2b00c5d9494cfedece09b8eadb73df68036dab0e339da22dfbc2b9b69587475d28399b5ae1d97fc9ce0fa526ce323d2f870822bdd9f5d89bdd08a2c0c942f3328fa56a31a2287ffe39d1233448207665c73ffd5ce505cae9337e0599bc5df638218d3af6c47258ebe103c1f0b5f6dd755376e4e4a68128376763c84d1e778be3b99daa0f5ccf5de0e68329825acbc41b6054cca8a974bbd26cfd73d584c11f9714f8f09dbe44c10dc881dbb3f5e89144ef34fb31d874e081a9030eea26678402f501ce64c27793a27c46e1e8918804b1567ddd49df5d9885daf0ec608bb1e5b630c8fca66e32dc41c3b78badb0c1458d47b2c8bdb77e5930145e8be4102c75d11472a75047e476664f923557e7c1ae41d9bd1532e23f859a9331d01a6c426287f40007d9828100abf64baa37e8cee3234992695736d988a826490f7fc3dbb3b354877b63238f0b01c14ec1235dcc1f712c42b5bb70829222a95f28ed4c2f2b2509baf0bc7ee1352a4d9cb5a44a140af35e597bccbf22368d215607970b7d7b93a4af7fa26c721205211f6c5c821563bdcd518c74aa021f96324177b53c705a01224b09c262792f6f4b6d8059ed391fb81a2d7e16a3b10c923aa8ac3e07d5495174c81b6aa4adf0d472b7d34bbbd65d513125a622264b467971017eab5bf57ad3d071971a75c59007834c0bd2d7b54e73c7936d2128cc401369805b556f4192c5e6187cc60a43497a92a75cc60350b59606e689fb5b5fdec8dd87d50a05e27b177a230ab5c6840357dfdb3f0871b6beaef464868707a8c490e4392bc3371c3b5282f1d3333ffba79695712e9344cc0a42cd737960380d78370aaa9de979485fccab159a44677582bac9e23b1973ee430e1dd29b2ea59fae0dc0ce4cc7baf9bf3414588a4444c23da785d3815023fd61b2d05f938ad6ed3bb0939041045734d39347a9569f07170ba881dc224a285996911296dd0e249001c843b8f31a7e03afbc72496c363cfc8701b9f588ab90355237c3859e0e78ff8dde7cb5d5e9157715809ff766ed040d39a7942cc848f04b0fc5e91c59acb3691d3cdd36cee613310b0132d72b86b8fed069f30c0496058660cd082ddcde651555c4fa27f0122e9992329a11575d5ee0429dd503d51811004eafb2c65965f95f2cc8bdbe198f288239b3918721f1637f968f3a8d20b224166b88b03bd2d5fdf093f9f4c8db5319e14e388a182631d303574d2775bd09962041be8b0412246e8f051bc0553707523dd1e03758cf12912084193cf7158e3608846b830831e29908feef76c66aeb2ae6ebb55d9851debd7c9a893ed3caa34896e44e633099db7096205135e60d53dc22fc3469da578948a992672fadea43467d62d1145a2a48fe3719d5dda4028f5b930fdb458985be80a4dc6787f6852ed07925ae70888117b46cc1367f4c65fa3b7e2c870a583c495f1e2baa4c647748a690e5145a4dbd586b557e050aebb99f073179e4421f7817c8981b47bc5113833ee045d48656013eb010c36234ad195b9243d832d34641de7a6269a432635f281da583800c62a1a799579eb18e00ebd9e5f7d0d6e494e56f9b95f16e5771cce0e2a69ca657b5fc0574b8c19096be87e0419032d2857be18299d14a7a9432ab14265e2f6fc71dbdd99cf54c4c1c067b09afdff233147cbc149b29cd71bdfa2b0fb099fc48ef4b3b54267c84ccfed6835d692dc1998c56e04d600a5307ce03a307c5ea9e293f338ba6a6e971519e7eb1a59c89b3c62623df58abbc7fc13368dd16db3252eb2158dd682b151494a800446ed402ef329501752bad679f0dc6e03a6da0c9c63952940860a9ba91771b47da99214a05ba695da4a369f5650e39b7a03a80d90d30d58e902f6c7096d34d540822d88ed35a25db8a74b370b74d0c672526423603b96249e5a22f1c1067e70e3f8b1ff61d971423af7ae0a6ce2fd859be542c705985010ed1752e18a9df3181aa5caa642904377e338649efa3a00bb931805e4f4dd7851760d9c093acd81be6c90626625a26c05350be8ae805407768d59f1c0aabc1719211ca774f264659629e9c24b07bedad1141b163ab98232a22c7a3b1c8162946349d323c881bf4d3c2eb0401f4a85d1dddf6212549d5f8b33a892dd585872c4400af6dc6636412755ce14f265a1a1008da7fe60187f9d0153645aca847ef6b677bf37d2da25777bb5c5558d9bbbc03e851539932403459e93c10dfe0ab83f3ce7115f8fdfa433fc7b23d67343f9429c6b3a103f77882c77e53e90de5b2e69821e229d24b8ac593d84462a71297153f7e12270a8b5c1cf510dc605099a0d03ef1f062a10034d2706ca3847b89f6788fee053f386bb29c3b25ebc3d643ee014114c6812dfe562464165c846c4c93d8a1060b06b93171adf91bd33c5778888b9c110be03dcdc4c5705be03e71b471380c310a6d40849c880b719233a93bc33e7adf7b7d2666781e034391a9cb1c5ba774ecf699384baa4ea616bacbf32fa463d957b1ae959a9b7516fe53d1af756ee69b4a772afc63d90f622eee52bd935aa5f99ae71af4a7b1af754ee6db467e59ec6bd95f66edc5bb9b7d19ec8bd10f702c7bb7f3577893b4c7d95002638cc6f53dc372d87f8082a46d60ae9f4fc8e784394bead928544cd3c4e16251416390f1c770556ca52302b518ff258b2e6e142780b90a5a503e4ba1ae2feca227c2a0ff552448141c0e502e271e546c857343f7fa3ce55320052517307b21b0c32e3ef3cf12558fec9016df315d26b07afe619087863f0ee05260b41cd1f3c7c86dece8014520a982d34838ba82e632cef43cfc8972f115867230bd1dbd0ce6b142ca038072bd01e408070c0ed2b376d28048ef02b124172e6aaf149c9b1c123200c70ad3733023764cf186e274611824ea2ec99c49945d980182b40eeac3a7505612284c1c810da877c3c885e1571f4e3a34ae108b5162124dd3c47158a3af8f1ab24f0035a1609489c4f11aa450efc7a14d25c01ed6544c8c713915511c73e3e4a298e50cb0262c2c5734445a1831f6f450a7fa4659108c1fd144959e480bf47c7ac5046700f11c20d6167960406a1232cc6a35ec386a71fd34d30c52498790863e63a42f0ec17f2f626dbd1e27e654a3a113a6a27de7a7c30df6ce473a0b7481aa57b509b2d47593f952a9b539056706bf612dc876d0ddd02808f943229b257f22feb11822868b1964a1b0fe0049f3e8f701b9f1f685bf49323fe4f85c980212d99c9dabc3d3c04bb32f54ee923bc84a5806149ef960f43f4febb94eddc6fec05bfdda8a139c52c77f14a45ea0704b38a3d1aced07c6e20825fd4df5e6afd6e2092631936ad285c7c0f3d2abed1fb4f6fbdab27c1099510eec05685fead88308fe02f57d2fb8ce6af82ecdc480ea81032df88886c9b207abf48cb9fe8c34df0412e81298df1d0122c7c512c34df04ca8a8782ff4345eccdea5b35717a152479223494f7ae468279f53edf882f96b6af790d4809cc9ad129ec0d11fc57567aaff5be62a4f75e4a3b56625216d2de936fcf7d5ad5fafe54190c0b409ee9fde0355f63047f7d2e62c09e08c6a918259cae0b2781fbaba6825ff7f6321d0ff0a4df1dfc812c7e09b52987700ccaf48fde574c6ff17826f8f63ef7214b4602bb83efcea5e8a968c3be31996c403a0f0adef7d9f0cb746f29d79c56e43de6ef91ffe34a9d205f20f407b6660d1e2600fcd0af875ccfe0e1067ee2296986f85b493080b5cd4246b988248f920459d5044c4bc612e7211e35d941eab238a2e1536225ab13a07a54ce597d8a1f89bf606fe1a238205fc487895cffc67f2e9f0302ac3e0b8bf9efc13fd76f69ffab2412349cb13cacdfbf91d904152e5a893aab889b8f3cac3fe09f2fb17958df3f38b327621cb40279543999c7c352fa229eea3cecc99f97f31e250eb1362e4d78d86d7f2d3b2d0f1b52aebfbddfdcc2370ed2a63081eb576b2a79f2bf494224386ec07858027f60cb7f32985a46fca6c8d8070f0be7f8174a1e36847fa2b303a109d80ef2ca244d5cff3e480c1ed68087dda9e4614ffc894d8ba870d2cba6f9c8f5f49187f5fbd3f489e461bde6fa95ff5f1e7c80202a2c6690e3fa21f92e5fe73cacc59f35bf7c6c440d54f25087ace06109fdfdd3a71179581fe4b586d27ed4d57e4fab4d01e161d16bcf6e821ffb60be23416a79d8fa54de6cb36710abab2481277d1020a0e161ade7167a611fab576bfc7a79eed3e389a1c5f52b1ff07e29d73f4fdaee3659dccaceda1a272e1b34dc6bb2f80b3451811a12715cffc9d1ca8099805c2f6822e775eb5827916f877b15bed047bf5aec9f90033021c3aa20782f3e9da887b7bafd8f11f10d7a1e16423e41f1b589152e68aead119b0a2e338732aedf36f3b143a3e0e1d74977d912e5a8297fcdf18b33b3277f8f3a9e0d1485870062eb4d9e91dfd39a919ae28ce1fc5e7db973142d4e66d72765db6054e276f51cf1917aac35a601b9f1efcebdad56cee9edcb3bb628c33c777d2b5a9aa392d50ebf15c8abf14a7ec123fe5ef11ae7dc12683250bbb2167542b8d746bedaa6a5257ea75912f9bc079c0214b9e008ac5a5015c522ae331d16428eb1312cae876228b03e5e4f9fdb3d4597a7b1f776a169cc2a29678952e0ef48f387718fcacec9b381ae2f6c47ebcb66f58abe93651904e6b525589d5900052fa4e923aeb6938a3db8b3c8ce89bf2c2fa0f827745453642dcfa4d14c7acf36ae97181fcffaed4cc58fa9ddfaaadc340c951072cbbb139f82f6e787b9c301e443ecefd9f09ade0ade13999677d2f627c9395ab9cfd45461bf15d9ea4cd6b6f0ce4296d3b17e9e4b3739cdc99c039ca20af82ea3b5fd9e50331ba7f4775e1faaa0167b873a11ce6f005f6d89d282e99d284bc6d73bd1b03d67c97d7413e315f04b11ca6aeafab6859b0ee195424de4201908b0de43a9a8485c43f395cfd6ade09dc9364e593d817838fa32b9c1b91fa52214a23e710d1f718ff78b8d7764660e8a47c19921be2fdcf57028776125ea9440b44080cdd1e31a6acb142673a4a5cef6b2c443d935b2fbbae4f683875b4c46ec4fa1db96a6c10eb844db52db0c9eadee4b6a52a4dfa47cf5136b2bf60e532cdc0321e01cf0e454a394a29662f4de2be5630ae76a56a2629b8ffb29c7000e3f4b2eb8d57ea04e44f31bc2d750a2b4607aa729632bca18ec9421af2362b94d07c7201fcda126cedac0d75f3498bea991626431a1ccb20b24b2482183dbe0d599a550f01235ced31f0ca02b839c3a39eeed0d937ed9487c2b23fb545d90226bb624ff83f4c0c78fff7509571b0a5b9339e12ff9e4df25c58222e121e6244121eb3d908a0ac0673fdb6ca909caecf07c3243081068fb47f91d4b49e4986f708747354b563b786d11099c2d7138c82ac8d315e439a2a262c21884d535eb50d02541a0a4cf1822a9a81fd6ebda06bd03d8efa4511b45a6d9bd925e2931d1cff83a7380f5d8c44455dedd572b4dfd00321b63b2bb380bf0a4ad171d300d7d4b012186e50b6f4772d3f326d7aa8a66c213a33b47d2a9b565bcc0a6f980fe9a12a079a6de33123f9aa6c06b8f6e5ced7bbaa319997d5220260ddf26d5c592f8384a9fc723a33f9de467f66d8b9d646540180f1fb81ccebf78a005f1602de91ceb3e452ed810c4800c4e5e8796140e31ec3b93cfe0d8097b97611ef02fde6760315d5fbc971fd334474598478b1ae2a30d844a397a555bcd5ffeb1bf6221c30318d1887cc8ba270a5b587ba66826726845d87d87b95bfc3e92173d61428c0c93b91f364380794ccef9fa05170a64652147c376ca94059d06878d715dedcf0e7dbc4eb1519ad069e432f8a919c25150d8db490a55692d8dedec457605da20178411671611c01fc5c72f47395b7266255dce04558dafaed9e32a7fd1f1cffc41e4562e7d871b4d4927d171c2da41329b9cdd688d89e303c7835f90760e2190ce9d7c5ee327586e7f1a9dd10e5cd7a301adb7d4eeef887d98f4f45503ba605e785a401c554d07c95ac031bc6245a101d61a05ce81d39973fc1de804477b1175806b394a39dbad60e3b70563d987120dd787c6f203c0d839a984bc466db04a0703248f1985eda08bd0d99b7382370e086b56ffdeddb69472cb94920c550778078007dc5b90db5050b089aedc310275456ef0892dd21b6db7f7127d0f4479d10b3eeec76fcffe06caba89e86f4fad8cd832ba2e7cd125fa237816d932c61854f40250a6685ad01d0f607fca16454cf03c198c67db76f4a4e4e58b2428a7f712e5400b8a5cb84e24128944ef2715950e4542f25c09c8315ee2716363cffbcd03452fbd057022a277f92211d10f92b7af620bc1ddfe47ead6b725504801b20cbbb8f7720b87f040981a7cf65bb8975db824a0cc1123df7325a0cc112a52fc8b9f5cba449f725b27d2de0ef2b5edf96a9b96aab9d2bbb1fd0868ff037b84305c7b9d95220ed8010766902579b9aeb3cf79d2f3788a8c42dc1af668917a37fac2f01049590d145226e2b5c040c106951c271279a21a4d02f6681922df75214c8b94470cbe1a2d7a200f8fbd0ac814fad2839129f46bd840c1e92076474e418aee7b153de0248a7da9e2d65a503bb95d1b40f4f2e35aacd4be81601aa26829b81ccbcb75674b64b888d8edcbd58e82138c81525da54512247ac55fa432852a4727a0090d3efff6547cf08da26fa3fe48d2a069f6d3340b925cca55a0dcce97c3121949354df33be70f0d04877c728919a440207c72c704b13bc2b8ade9f8ea73b459d22932fff352df99864f4eeeed039cc2b923a7e0a7fe6ccdfaf3016e341af9b8b5d6963a7bae80c2c7f323f96ca7e283134591e68e5209736a13e5c4769aedfe0445fb47e21b4f4e644a03d17714459f0f856434e79c9372edc168b24ad7d781cc65eda7775e4badef9ef65ce70b51fc1f8dbeafd670e4a172b51773be11e5a268e004573c07348b7de93580596ca8e225297c2a5325e6c5c9f79c33666a4dbb06e148b2a40b5f8b92060d37575656e6ca8ea6d1a2080d9ff730b945f87b45a6cc1da365298bd0e158809b224f3c64693ef33321039a2b6164ca3451c137aef0fc207a6040b480d441641e7206fd3933812490df29ce3971b81a15c10c659516692753e84fda759776a3eea834bdf4605282cfd2f76114cf4ca04f2b3b242075d0c130e8d7a7ff710c1d9452f9844b27b3b5122661d5565b3b39c35363308909c2d0900c865cce56abfaa708059071fb5fa44811f85282866fe4a0cba3b39cc5f4251cbfdbce9225fe0e5f5a9c61c7c286b5381180840a0148ac6c0e3967fa6b74872e932939dfaca3a32ecb97d387aa4d3f6813489b56b307ecd47d7a8abf26b5bd0c74a02ef13babce1acd46d366169ec5c816fb9f51cfc7a3c33fb6f71ff95bc8cccc293a7d94d87cfcf2cea05a1c27cee51c94f8c68993a343650ce584a47639b1161988c90ed422cbe64c8b2c9329fcc37cf6a769d30ffe353672460ce40cf9fc9c94afc94e4a294bccf08d1dbf0437c0570b49d2591d92e4772b27e532fb317b0eab3d7619e584a47f623cb2ce650639a7450ee2723882bfe85ec819f2ba94b23b1f3825f3efb64b9752bee8eb421fc217d14cd6ceed0d8e2e59854c837c9e52cae75c4a29aa747f928ea0b4585936728ae492c6bf206730102898a345fa9ee2548e9ce1cf335459fb7d237e4fb10e3c347f0df319070ff9ba5cf340e05410bfb3dae4392d1d178fbfbcc77de4f5a145b963478bb287d99a44d87e2b184163841146d01861040d0b5850c4bcb91acfc0c8148d19a645ad19d562773b4f7bdbea16bfe5c4c85deeb5dfaa0fec54d43c77a057bada5465b3fe7ad4dfe246afa6c380d2ed1f51af1aa77bb8daf9ad2f99524adfe93b7da7943e47c2a55031e2d5556b58430d225ed9774a652868a52bedad1ebdd5f2e5337a2bd6a246c22cd43af5aabb1b9605fa0e6b538d4905d07729b2df37fa14259395c04890307864cacb860ec74b40e972253bf85678df98449e5b6cb584be9811ea5373858b45c74a408284a1f574898138f6e3e21d0943fb6f3462263894ee07e6e3313cd5256d07bfdd73549bd3856ec8202467d491dabe79162c4646e88f9b4b99422d03ea536afd079d1683f0f97f21c95d3c7a51c55d2f1f8ff15d91190d05f5aa577eaa72865fed4d4cf08ddebaee3bf4ad65e931c03ef5569be4bb8ebb364f0196d2092353b4af1bb077fb4f7b1b9c9cab6d9acf380aa87d601d5a6b180cd64fc814ed47e9c40d984c91dd9233eab5a75e693ceded2d6fb94947af8b121e7c3e42a2071286f61a8d9abd45460f5c1aba8eb754f0b9588877e4e9ebab0059967c3e0b77177df7cf008aeb21f7f6a9c780fa1e6e60e51d8bc4351fee158bde4e433921f97994d189e8c60ff683085d261a92ecd3ffa18264c3fe69516b1c11509330fcabbf08f4ef95b85aad5624ce751c08ec6b62024de3fa07ab367dab6e1c969cf14415a40ef435ae611d6b536d18ccdad035be51eb7bada5fd603f084a1fc53bc83c6d1a0949297ee47fb8da34123a5008c4749d165f6db2e10f92d71e05580109437b1190532d6a3c60c02d5c8d245459b1dfe8bd45b5295913f1c22edc2153b4ffa1e245e00f3a72c616deb06110acbd8a70de88348b0f3889d2eef5bb7e837eb9061d3c796e34ab68a3b6bbb559451bb5ddfe2d1c88f92d9e3b91d7c1be75d24a4117221beab7b0aa8e04dae0a2550da4833a0c72c6eb7c398d73359d2e696fbf6f24ba4ebe8525817cffe43b8f01f6fd394f01d6926c8b1601a21f11895e05f8a265887e636d2d9dcdf5ea142058575595a2a9a94275c8ca5814855d5a836e2e7d1bc3c4ead2b733b6765c9daf6a3bae76b51d07c4aeac8a899a4bdfb2aaed38db7175656b55d50ac4da25625514be045989de6b1589ea4b90d58aa5b52e0542eb71b548491018e98026e425fa232f5934900481141da0295eb2b0d8f9a497bc447f5bc137f3123561e21b674b76552a4ed449af7fc5d4282258483a540ca122f418278285a64fb27a89decc30d3cc9b9b1a7770d6d8b4d83dd3b469d2b448e79c01e78c8a65b644a25697e88b6abc44df32b8b55aa4ef31ab1847f989a4431b62637989be163aca4bf48960a15b8dbb4db5684cb60db430ebd325faee21c9ad8ffff8f071777ff6578b27d757cbc59e6fd6dddbacb7d9e96d2d9f944eca4f2b9e7e09893b387326ce8fdb9c23f8f82c0a91589bf89e268bdc3982cd95d77e2844e4090a1045f45aac872f417c4c2f2439fd2d2439ce9c4618721ffe2f417cb4c8cceeec03c812f467cb4f2bbe629d03c7a97329904b7f45cb04943962b4a94b5f0b2b38fa8daf5a6ab44847607e4af1f43d68c638cbbf2075982d7697f7a8e40c7965fb8d65a13f6b3c66ce94aefdd1c1a0aaf1d8ac5b46ce80f18f8f74f5cbfba74f92454465d0c843978e3d143476cc7359803752bb149e8bbcdb6f1c497d6d28920db5cdd46c2812129faa9291c9e66c0a6d32118c87eeec8d97d8ae56d5488ada5355f59562847dd86ca86d664bb5693cd9642d0b24b3c184c64d1664849f4bbf63802efd2aaa221e0ff3f66f3058d04c68688b41b1c9b4695cf181c5da24fb2c904e9b5ac4d3a6fa1ae9b1346d6aafb169533de1be729f820b5f82d49458b6b9f4bb1b9b921223a86a6a6a2ee775de26c23f5bac4303240cfab409e31c420e9942e977e17c2e54a1029c6048ca00df1e32457ee1d2e9222f416e2acc4fd63680b2589597e837e1abd1227dd5a55f0f3e1551e0170f133e91a16f9c3c3875bbafa914496bb69ac1eebba513551a22ed87d68db3b562095f0f394372b5cbc105df687d2eb5b3dad506d959ad2fa4d822b3f5699085f20f8c5bb3357526cf7c4d9ff93363b2d9336113881355e74455f378684e542727aa5bab4f2a9ebef569d3686737a84da36d5dead278fa24a33d25e598cfd7a74f322378faf6c7b6ac8fd00a18a365f093802a2d835f035fb40cfe09eb936c02b54932e103b24b7fcea6900a507689bb44dfceda347290156ad37862536d1ac5b1b278da346e35a3558df5056bd35863406d1a256cd6a6d1a65ea99f213732d4a5cf413597be0f3b6078f468935ffa735ca931980c68d6a6e6a16f7f7d59206d6abbb23896d52666d34d9f260bfdada64d72c7083197fea6aa3995555b6dd26993e8e957579be40988028a2dd576fdb24ac91e528737fabeac664e245dd261bd1db4fb3284e5bd0cc99129b2083f37bc722789215c0e5f8268239d0121ee48c4b52f436ec097213e5a1ca26a91092010ba0d4a268440e7be0c69b528ef4b90991c7cd227c8cc7d09422353e47d1902a445795de84a5bd14ff3b5a7db8c6b0a748193289c09cec7cf897e8808e0caf742f0bbf9c0cd04802b628284bfb5f61fe5450f02f351bcf420a0bd88cc11a2dfc02947e0c97bc9b68cf6c8f0f58f9f8a17c1ad48c28a24ac4802c74b7c97eb9063a2bb5bd5dd46d4a4aa96aa3141aa39126cb5040e929aeb9108e98d50f0f9b34fabc48d73229da3f05ae609be98cf5dc46b9923f8bcf35a7c84c23c590a38580a9ff9fcb9c57140c2792d73da7cfc2521e732e91c244defbc96e99389159b8887d3db816fc62027b8491ff972f6b9b37b05123efefe9033c2c7bfddbe2c349d672c64837669f376ebb2eb63f0d5a4aa96aa41a55ce6304b1de6b294c3266baeb63a579365c45ca1ae8db996e4bf5d7b6b98aea14645685672fbd468dd369119da20b0805432564bc7f5eaf981c566aa954aca182c69bb6f748222be5059614de9278dc5bafd2cd6b4330db26b177662286d76fb35d5665ffba9a19a8fa6ea139f60a5adda84c3d25a1a8ff6d27a866ebf06db2cadf193c84f5ecb8e0f66467bbd1b7fad4ce9977664d4e2ff40edd7a2add569b4a9dfbd04ad93094bffcf6e3f0ace106e9bdcde414276fb576a54ea9aca4fa2aff547a7a9baa4eafe47f7a3a6baeddd775dc51adaee462b73c4a879610c5704ca1cc13d84abcd6cdb107012a5abd127bef192ff4d0c895bd17bf4e0ebd1a23ffff8cb4fa2f0a54bfe5b6823766380ad47a9f3ea5007ce37cad9e8271292999f5896a8afccb9cd67797a1f09f94692ebfc92257ffbd5d05f2aacf091c825a0b0c4f5c7d1275e79c97f745fc5954b08b9820d475bc315e59577e3c5a83d8f6dfb06bd4bf3ca16672de0a63cf94b18f2e4618ed36d968ca30624bed15ae720ee236197cbb58a627cab042cac340105ca3cbd6d5ecbf61c33cae542b95080bc2361d017019909947bcf3cec72c2b7518e739125fa52ba54d52f0f6a6ef7b57ec82f76b548d955c303475602bb64ab860d3add3b87e11d9942d92553e8cb6078701c109a3bb2176c3743e163c42d677328dbdb069690a03a0adc06d7862d7c2b2a3154c401c814fa6edd3dfb9527478827870b355c5189a10285172e495a3e951776db018e280544a607e4fbff9cd7711cc771288de3388ef302ddcd36dccddccdcdcdccdcdddddd43c5a3eb54dccdae7d6bdc9ad6dcdccccc3dbbbd9b9999b9bbbdbbbb6937a529e66e06010a35846608cdd0502c369badc85277b705e293292ef6f022f66974a31263a5860d1c3974dc5c7f1f767878befafc38288a7d4acab13ddf3ec9f09033f832f38bc09596e132fc2da8d232fc29f8a265d0e7af61234753507e1dbe24e123bd97213923f71e892f49f8b428e54c6b4f4277b7b04bf1dae95181857dfef27e32250d2f7ce8a104166385860d971c26abebbf2386733b856f144d703ed14f3cc892bf13aebf15ae7fe31885263f900d92e6e8bbd1770ed1a6d66e74bc3ce1faf7d0a700b0f8efc0b9fe305160f11d57ebfa07d12693255073f466b8fe769a406bb56a70ebd5af57bffce6e6e6e6c64b6eedf7f911a6cdb4e9396de6cd9c28142a2553e485f938772646f8c68e51a980b40cca729d39b8e0f3f15109c99d22a04c7c755c4ded66abcfcf109ae9d3ad031b4233846608cd101b99226f1164b1d8c8b2d93314930dc58686862eb775d66b99cd66b3d9751f22e3b98f6de21b39463aca51337336833c35a4f3822b8ba03369683836696a623473c66231209922afa33c4584ce799ca7679df3f8ab9bb598430bbefe972466b3cb49e676910e5f92109229f2fa8ddff88ddff8cd1086e085ebafe5b48977602284a9a3c33c53a75d3c3c3c3dcdf2d30c1a32697d63d7748dadd3d699830bbe1eea2196ad622a201367b25633876a1bcb308a633845b5adbbbb3d66862f49f8f4908f8f0fac5f7e9ab3d76cd6af39ebd79c29c12a21c0aea7c071dc670e0ee34c1c160e0e4e0eab56adce561ee2a016070905b55a2d17b7989983200ac1bafe43b4c96ddc278d18dd5ab1cdb475c526c69c2d191b9b246c92f0e1b5bc0c01c23233dc9ca9384e8b99f9899b676db9b335081edf314d13749d4e6df3a904d0a4da46c1939984aae3da43c5a3eb94c851a954ab1afe1ed302c257658aff386773e6273ba4e566b8fe946577c66887a48edd9651eaa9e618671a8d359bb3193487b4180d35c3403c6b4d464bd9eaf1b0b2754e5b270a3d71efe38c693e84da44ca217abe437d9211bdbf26d326520eeff9a244de7b67f94926b4d23264b48c96d1afa5fa247a938a03c193928ff5fafbe8dea61a7fefd5f577d978e2cf34fe7cb3babec9b48951336daa3cf4e5174267b6a66bf2f00dbeaba9425dffc9e29bf6d1a6fafe2728e20c5f924855aa8d3aac358958872f49a46633771249a492a8f94cfd9255cee877ada501d6ce132f20ec3c11c47dd6baf304cdce133e769e8871020c569882134a70c2084ee4ec3811c409d58e1331d871a2043b551083164a7e4c7848484a56aca8026ba70aae510784850c6aa84211a49d2ac49c74412d445a70d19d9c9cb470e162ab820d264c7c491010e62384b1e092b41886e10d37dcb0d3c40c1683d2c4134df434c1c44e1341769ad0c14e134650810c3950018877a8204bdf07388932b66b9ac635a53149f444b0686ffd44d221f2dc734f048bd71e48594837c40bc3a2b1703ab232b07260fc2467b7be5c72700c096a8653ac19e9f2a10c3dd4b77ec3b8bc72f878a97e831cc3280d86478f2084c0b9f5555efc2473441502e4d67f11e32751c82d2e2425c03b1c236082c4378a2a2b34da648fe0afcfc1f0b8cc305ecbf6b6d69f40befaf28ea2f842e5d65f59dd5a1fa67b51f84140148e58ea730ca3646438354be7d67e197949f35e7a3ab81709ada7a37b2f1c42f4ddfba959be1fa2afd1cc1da516e7245b54433d8be839cbadfad6825fcba855148a3d72866fe41ad14bf53b741fe92769fc0ca46974d5d2e939892cd5073d7d92af98989829b0d420ad5b496e7d8eb549eefca03ecffac42cf5356e189f5bab78a2846f1459a64d4d89f04e11d3b415ebb1ddbe91a67c922c7d4717262ca3c8f51fe70c13e0031b29cacb61027c702361b03cd197b2c4e2ca912b59e44b69a24f9480096030f9f3edb66b357afde329a5cf39e7ecc94e04ce850b3e6b65ad4c696b9acf39ddb566172ef8f88eb67a377c13e197df24902d53fa47ee4e96a00d172bf8361739834ff545a9ff013201b23f4596fa515adc51ba46e9fa15b75bb86b946aeed23311f2bd087d7acec3bd1d72b4d8efec01d140f40e09084199d2de8d1799d2ef1e0e97f0a5f08dd2e5d22e57bb70b4a88375788084d17e5d644a47e16b590ddc5e03b7672f87277cfd1efee0fe07ea59b897927993f42be80efe107d83e1945d8b8c92c1666db34b9f93d275034063a545fa346a080951200a4479a88bead016cda12c974e8b264553535155a6a2ea4c8b38df385f970ef5bcaa8ad627fb1a5e616385dd66b940be9bcd8da939d474586bb5485bfafb585ea215c62189495cb97265aeb3a65a323e9c8be806e35cb4c9702ee25c8452372b03da60b25a6b6506abcfab4ba254cbf6f8c8c8c884987320ee38f7b1e270c779338c53353637ecb5700ed717f7bc9868710ed7ca2f4172727458386dd26e5aa4ef5c5997c35153f5cfd2d5542dd26f611d736aafe25584437c2b4cf0f58f5b4da54fbab15dd177387eb4c6e7ab45a116e9a76caa86a46a6952555467157c19d26216d1cfad66b3d97c6caa6db5e16c39ad0dc8c6da743ace6955759c6bb28ef3d9710ea2889eb35bcd56d31b6ae3d96e546c3e808c6cab11398337542d12eee9f1e790447d663db269d3a62714f62838301f3c3436ce755950cf68936dabb4c9f5a54da6da64ad717a685432a0202156ab1a47f43425f28f9ccdf08d0fe769f1e4509df9a97c00c1f1b195a0d32608217af0b076c0f0d8e88c9e5cff13e6410999717733f82264266426448824c6e9458f580059f8a838459161210c46494860fe5f6bc40b28244a0e2ef8461a3c3cfc6a9e16d9cc3cd260173f3193706c86c341356c300c48c86a3cb4d5260d428821acc8ecc33e3cd79d630da46f5ac5427d12bdb70d11098f04629beb23e3ec609d574f8e1e607aae6f967a3c745b1510ad97e0e11184104368a0d862c7b86990ba062f512324c6dd1c8bdd92784b0290c1d79a8bbc0801d23c05cc910058f0b18f0b2006dfc831d2e513fab08f00d2f0f58fa2c8fcd66be111499bfa7bf5c598e07c02e8c237cad9c89091d8837c940ea70d9736758726ed7150e574edbad591644797fc397c1c7280430cbe1e52fb1a92e8cb5bdf0712fd8f52aacd0d06df5f1b50f0511058129202a6d6dd36597b22cd6262623e7073fb4f50fa4595226e7f0c54ce6d5be90e096e7ed05e0b3f143be746899d586a27c6da89adb470b38385d59561107da58af3093eb9041ba12b9700831801ae5c020c823ac64bfdd67edf68f42f8a1da3229ba58c0785e9a694b66b488b59f8815c5ee9ac53265d989999575d82e1e11d4a04a28841849cae4894718456ee4988119a4c2907110a222424068722be8e89a9a9d961bb3818f1f11da54c6803a267625ae46fcea4e77bc964403cab747a9d53ba665c46d92ca18b23078c487b4ea4d5c933244ecdb44c24f04c8f023933a50c047439518743113052ca0ac3a3d65a6badb5c2f418a23249c7101f112c1c248801da1d1a19f2a7d37bd470ae428043e4b4495ed691978368b12b0f6f20e600b46442e6fa7e75ff88e1a6b84c6061e65e967ea7ccb233dc963942c6302e33b71f479b0a70fb454af089defa28597e625937ebab01871a7cfddd6a6f479afa03b2a7888c14fbc7e6e16ec538cc224c2fff4c760cd8a86635e16316f70dc32105dfd8ac91632ed3ab7d7f770ba89df55cc249bf81b4b89229fd1dd83d9030fab946e2f6cb1639c1270abd17f91a8e5ce3e5901109bd3087d2d6e49c5a299d27dd753c71b172745cb0574fec07d6e2f18971228deee0449ae60327d2268d1669cd6a569f507c7fceedef96a7f33d8f487fbf44de7572bb7f44e4f3daa74fb0986c86828a39dc629d8e71bbfb7b94dd34370da49f657416d42651f7bcd8a79b7e0f385c72e878691ebd830499db26faddf7d3a861a3034f341a044645127d017bb1796014c6514a6ba51af812040693c914e9bafcd6c5fafc448280f7222f1276805f5ee2f7426e79891fa5b986c1c34914927f172f5f3c719da6b578c2d737fab7d7c00b70eafed0bfc3f64cdf0528591e942c13e497df6c3b7c28a9f5a507667676e9dda3e7264f394d9ef396151a35b48f11aacc4ed3bc1bdb75a15ded4c70489eb33cacd702a3e24d703e51278aa1e22f9da722228202c5ca37329222460aaf45e5c604e71b798ea433c1f99e3361136942f25c49d7830f3b5af49792121a26262968ac7059e1b5d870c161c25eab113454463a465e4b0e91e78e058be7588028babedf0aa668b1e152431a2638df8ae7489d09ce67b2850fc59f78373c771c2dbc1697156f82f369ef2cc20aa230e2136f8d16dd468bde99e07c2ade06efc676619cf8b4e7fe41300cbd169516bd562362dce0b5a8d4bac2dd3063423b74c39c415328e8861bfc35a7c3dc63404da3d929b6a83d0aca0d28ff72063b8aa6fd0d9a3627d8332dc38af1930d27669142aa669edcb48905a9863f0149204a0da07883d7c282854299321385821234b5f0858562a1346d4e8d85ba9c562a95401004bf54b2c1458b9312a90616a55269545a61522a954a2502b4787a7fb40887f0008b089274fc3f112c2e40920e17dfe25b844338cc4bfe2e9e0816e9f9cb13fa88b8ce4abd70f06e94bc05093ee9e383d91d99f59a3298f89adf42c42857034c2c2d42098efd357c048edf5d019a80252009384ad908f8a1005f40cc6b032873c4c8afeb202873448b0f4199235a84dd4fb074a5a769a19d414f5ff4d726c95735ba1204be0c69d16813f5d7a4ef63dbf408fd38cc650ee441b1990f6d534419689b220db54dd116facb5f7d72f1fec9b469ecd4759f163f367c8b97f94ecd20f0c1182d83be0da04acba0df027cd132688bf777211f8a41b50b5076c97f24763156da346a31d74d23bf460d856364a0eb3e2a51885d7f1a2e3a589dd32d47b97a5e3e3f30d75e8be11c960ebb4c230b5d6f13e9c67645db3c113264356d4a6ba3d0a3d1f045c890f69ca651aa09191232c492d15296881a5a06117c6a1a0e38dfc881fbb5e8b3869be07cfe9e07bee4f092773834649fdbb8ed2dc7322e2f301cf8d2a2e3c8a1a3072eccf12250478b7eb9071f5c5af45fc1854f52f04a0f07253e7ee92940f4a3fb2efcbce46ffdc54f8e5c33707733337737333733373333373337333333773333737733337737333733373333773733737733733373333373773333773733373337333373377377333377373337337337cfeeeeee661cee66eee6e666e6aebbbbbb99bb79767707a066a8144df83539856a0400002000a315000028100a0784c2c15090c579aad90e14000c86a6565e429909b324885114455108196308210610000841608486666a00e45d20c0c96080d524b7b1a431c4adf65d4ea3af19b856ed98efa4f66fdd80a38081edd3a7a9905cd56fd3e103e0f34692b80a5a5d02ca1fcc2acd65c00821ccc0342028c0d0fd47be54c8579f8bfc8273e9cb6db4258c10a956a5d2db982ff05a84ce6cc34a3bd5c29e07347e75e7f15b787bd05c47c59e9d93d62815f9b212139434e5aecbe811e3cc57372b64b4dfc95772fc32b62b7a61a24150181ae325768c17d0d53699ce6121b0f470a1be99e30438411d133dfc47806a5f59dff5cd1c9edf8262c45aa8e3472c4761f0a79adac926b09e6197ffd644eb6410c98f28ffe382a64facc4490675ea66f8327ba9f1809567e0c1688f1bf9e130eb5af30ce1c74b35f1b58f40f12f9bdde8ef4338616bfe49c420977903fd12cdd9756f60c6697ae2581f9950fc38487337c57a571bce91869b8f3d0526e674917e94ec27f9cb9cbceb4b0b1cefd1a072eb82fa6fa1ce4f1f888bb920284a7db0e87fd23037fc6ee6c2bb91ff724cdfa2ae48d33b0c47f8333d32ba52ec61243f56ba6f62830f0dda09a54987d9c0be530d40a09d58739d03c23549431e5d7c90864168c09560f07acc6b588d6ba0e99791f361997ec0801de88f8cc39a3cc8e533f57c8704f6208aeb48e709d011067528fa291ed2a98a963d2da4a9e1d2eb573c54eca234895f1c9b709599253d25a8025b0ceb7ba890d39b1384024ca342f835bb12a81d2cf2986930e3d367860651498fdb95d089264c6958dfbfc94f92cbe494dcf4880bc1477c92ab50234be7990a5282749fc3392d4d4397327c98d15a7069d7d2592184eb52b6b0825c3dbf96ed0c23028844e1d2e436507533a97b41ea911b16fece0c2e3c66944720c72c8d7d2826f2d21470b4f7d9db98d17ad4aa26e6aec720515b2313a43c379e961014e08a84e6beb6ac816ed72faf8790dcc4df0342f126ccb36520fe3b5724d51857963c28c66decc547eb9cbf12836f1299427ce75cf8d6af4977f0b86a9828b3112e447322fa32ee3c57a45cb5b06181ec7a23b8d02d32d05c0bab18926f56d69f6fca4efb72aa8472b7a761aceaed51f0e4fb6e30f19633b4f10a2ab93ec974af88f2ff3c3f6939a4664dbca8e9c633340fa101b28d1e7fa809fc148d563924e4fb0a59b0e7ffca5768e1bba051559ef98b48a0c7b19c26d0c2369abc8045ae394cfc78594d08195148caa2e6d804a5cee3d713c87d2fc6c80eeda87a68a26d266ea9bbd6ceffc2edce5dee3d7fceca71b5bd1a098259f7006d0613cc8bee26615befc8eb51ef7e3b89d8f8337473b0ecbefc7bd1fc403b051b388474a59c150cbf81adfbb8c9619082cf2e78055d9e99bc979ae78a6fa6e387280987bd4de789367fb933be27fab2a5922d698a18dd7aa2ff5bf554c4bc4b347e55bac44ebafc26105b221a968b6b90354f3f50306ca4a59d7dcd3c0d9986ffe63bcf1e3dd8f6bb81490b0e2deae9f5fb586c24128120a12728f303dda07422d055afaf1b6358d825453bdb769d13a5eb786e495daad2e9fa79fa5a5d0ef717d9e15cb519c11a0dc44c38f20dbb8357b8b9739d80d24dffe8b3f9f43167b1222456b96882cecf716dcd12763145495c45b3a81c90477b7c5989723865396905dad03c09f2e97071a63f03a73f3ef9e8d12c1dc7ad1ee28f7bddab3d11c794faa43b4a27587b27e596d483942742bf5eb2bc49ef77a1802c3efdd92acabd1ec5cff9a1aa856cc1b38613198ce0a4001433f080cc9e32d25610e259d0a8371f5892c3eda1f877c6e061ff4baf1cd4a430ad9d6f1e9f4b5551a1f1fe30d4ac146f738cadb1868dc0cc21f96a528410c19b9e9fb67576452d3b3c7ea386575784966ebf7be43a9e04cdc3db989373bc7efbb979039f7760ac0ec671523224eda6b668755ebafe269c2acc56703a4879da70e6f7c0f1b48c1c6fc9f20b62bbe19acb9f94328833042d5a0bff678bb43ffa33d7fea1a5ba10fd9250d9757a24eb1524d1a68c290b36ed55b84f7d07f35bde60bb898cbe866e902b4ad0ba2f4275c7da23ca59227774b4b1f1b1546764ee3ab55199078825f0141030071bd8d9ab3d996c4e4180627a646d96ba5aa5c3ac236c325843b1d014de2f4464f9467b32b09248d602498920df05c59eecbd42dadffd3bb7610c50ec9e24366bd82153061809a1f8d83ab0ce4986cae123bd962261e39b52e90b89d207674345fc9d89fcdf64894a2ef6c705da0ea25ed111865d6c1c2207e12d5a78b68818cdec4188c889ce8268e3dc27ea10fe5884c76eff57cd1c3e16efc6cf8f7929f8669ddcc9a3553ce482ac2b0dbb0509e0362da428397a63e5a058b44175d3b16682db24a899da3f19e183fc131cfb9b0c3cb53f3ff1e16aeb3ec8e8726941d488e9c9c7c0a5c150964d3d0d1c5b038d1bc9a6122f1933fe8a9fe0706890379c2d1bf987bf5fd1b1e0a92376d3b17d93384a951b49bdb998a526874d79c953493de8e67cb450a1385c513112bf4fa6574157689b069681f77110ce804b1d05216904b036c66bf1cacc0a945b8fcb617e81151dda578a06b6eed4d57bc4ab0b2d610ecf317d3e334f6a0e8e66184a44bedd5f5c66a75b835157e7100e34ff90be38195c05eda4b57b7a8d9264aa6741d5e5185a69de8afc035666527989eb8a4e31287354619f7f84040c6e5d21ce825991c07f52c0ab2bca7cbc023a46240fbd631a8d89ce52230aa104cdae8a04c393751d4d192f36a4604661428bcea9852f2a4c862cfcf3694e887332e7368ab55ba7a4f8aa68c21e2335e89bd46e45c0c783b7429993a290bc827f2a0359db3e3cc8da66ae4e265f4299cddb3f7ae2b6c535e30a25b1ed633ad42eb8be60980b9e1e2713d7588a552e24f5330a567e61028f7540f71bb95c4de53a5f84967e10fb8d8b831ae524995b2e842e29d215de6d833d16cee252867cb33c8026f5ec118c6a756a9771ebc6b4601bacdc9638ea737b6acf21b8a1dca9e549bc491bd479a4b164d3c1c8bff70be28df77e1f81b1f2886ad1c4677812a9b2adcce103f53089e3a8f2894026f7b8bcb6e9e684e79773fd91ee4e9c70853ce4aa39e4730a9acdd138fb996bb54ba8bcf39978df5193c03c1cd426b64bf7d5f4c61ef79d6be6696d9231398788eb2e09cf44b672ab7e51ab467afb7329ef456dfa5555d0d56773213869302a532dcf6b25594340efbd87ce67a9d3ce8dabe042bfc07165e848aaedf1d0928880c31f22756450ebe7071489a0b7f7f1db04c26f9026b92beb96b20cc8e5d97d9e9cfa4236fa45bf89976135ce2fb81fcbd0239296c6c4a3cd57dff5cef36d4a9ed40aa1fd24b865c5505bd679634369b972d07e615f78d38cfaa5642b9eea82b2fb1357bea121d78b2713cbd7c82550b89daccaded3ef619d0f631e1f12598c47236110d37f549a3baf9e952412c91d5dba7cb92e7d032c4fc1caf59c8c920d07d18254d45f33891d4cccb8e503b15c985622cc939f4c161791de8644895160ccc153535d9e94c225d97a6963a35edfabdd6c1dedbc4d2e8a5aa4f4049229fbf52aaa462745d9aa876f9f42979d80053688042ccde9b5939d4ce180cd886e44c3e312e53992b863a1ccda9011844456b540b5b3588fa86936184eea7128ebda003d12eb5a8a8b1de1d7f5a4301497d29e75ef515b645b6aba4cdda7d534b12151aa98dc5bdfeb3d54993e886a1e6b8e9e181d1245901c53fc4a417582da0568122358b09190656c6a9fc3e38177dac5459a17a50e498c4db526bc3c2ecdaf414d255047dfcc6a2a663af84aca99aea0901782434e07c3bb393845aec7392f66fb89f98aa41ec3b4c3040673cba96f9cc1c0a26ca55fb4a1204755e9f901e4b1f7f5a1a6511196e15923f9955826f970b8ad228e4e0ea089202b14c267dd8e85471b07fe17e301fc2448999c7301e462785b7f3e87d3a930ce02d0be8784fb44059d2cd0cf613bdaca62cbf0e55c5661b120b45c9907451545493f45f5b29bd0ab61b17e918588f779ab74c5f85152d21fd846cec994f9a963764c1f8de1b475faae0bb295d913e9dceed8b9662bf6adf5bc38c8013c92d4ae49e4edc81941cd9da44768499869efb3e9e4ecf10e295d1475b931aab85c261a19e16846ff6d3307466c1831888ecbd75ad7ee62065c4d6d52870432aa2e6927108e5518f484490f2885d8d2b56dc0e9a2b4a18ea1bdb1e102e4c9fb3ee674ec1a9bfc0388e5b7832b356984d221ae1490a3110347c57249e2858bf04f852c4c1aedaa87c74ea489eed5237d00b8c8cfcaf2894a674975ed142cc8c3a5695f7adcd859018635e30610e38efabb82141c288e676c35f7d6ce30910ddb735594f985c3d0054e93bb5c33c72035b545014dc394d4a1b9be8f1314a33da9b9252554d09052fd7b02dec465548bb2ba10dd0243facb812466ff1213ff05024564d300d0febc051ace36b64e9f5602412bcfdd2754ae0e265db6ca3ac966bbec48a401f48b5eb21a603ac86796ba2e28ebec84adbd9c0e6a819c728d33028d6050ebdb11358512d7196f52bfc37aa452050b95e241749f633b4893d7cdeec61cd9d57fc844c67649ab9e923b3220d64ff3eec093afe62943de7e9907bf82e6f11db16a48dbbdf026ff9ffd4b257dbfe3e16f8ff2a9dbe3d13f6309cb1fa4c63863f214f11ae2269bc60f35d68756bda6f02f8c4298e27768cf045f60ac3ecacf252c9ea118cf0c9a62f641ac64b1f1d08364ba3463b58ae164b79e0d8c413b0d624cb62e969dc9240b02a308985714581aa019a29e8155e21b82ce0efad51b83e01318734da4d19004f3aba94bd9a8449d8801260fcd0934399d9204da31fdc531aefcddd1f66aabb8c0bb00b1e998d9b05ec3c659dbaf06c415d14f91674b1e3fc61028e842fda788273e2b76e204e059f869cf446a31e437efd9404f591c1aa2710d4f69727a1a15baee741f3ebfa03d65cc597c518b61aa5adf87524a4b3ef08b22d304632fba84a771a517dc4c6e1ac9d18bffb176bca6e4ade58883cf22c892089ce382998195ed77a043d4cf36ffcea8ed0e1e31576353bb61fc7fc878068be228006113e05622d7d34a45129eb5ebac79eff5dd3f6ad9e37e86627e9a5141fc7d8efa02859dda5158da39742eb7c9fbda449cc4b8801182fb0a21c0a688a1668c77e36e4d92c64547cc77b1f3e7afae4037a904eee0afbebf4b6f36e0c909cd8c3b460024c8466b7b0dd3eaf62e310aa3cbf3a5fa34955ae249fa941f27e8d1ef56344b2c892d0e1d111b4a7670bef23c65b2284bb3dcbb6ae55fc8ceebaa1c75819107d79a1abe17d0c5098bfdd3e28a2047e3c0987a19ba3af28889c69c675ffe214e69520cf977fd7b62079fae93c464deb82050544b043dd288efb372a6c7b690a3d165596594d61279d3f586d316b7c576fad0e5f1d2644cf07d087305ce4b34afe7f527664d2ae2749e1633479122d104e9a7afe2b8202d89fef3f8a5f0541435c4a61839d33655d0a8c6278844a4827aadb48de3c5e3a0ce1442223becf400d2dca72e95375696ab126a555fb76f0744fa70dee047d10f49dc8ea944e22eeded038fc2f353807fbe549cf82d7a4ac693a3b5a6181ff656b77dbe860b756323f3a918e9b760e38d2c343b3a70f8c35edc8b08b76bfe33590cf83172cc1cbb428ab88ffe0ec1e56cf50e03e98e0aaa5b2e48e116f495f515e34d0234a2faceb709748eeb2bc65994a936fc613a40be18bb78bb5d778ebb78c7db5ca6eb6a7343376c19adb1f7ac2b503be6c08e0e3a7043b04f7746636cacdf7ed29315f245950f0b278378c8ccf03e12acfaade3e24ec061029facd74fec9452b7cc9b05d53561bc94189f632f26b6579e3916190469c61725fe741b84a0be45c933721facb03ad8cae5d2467aecbaeb9b6039b6307f65d226e0afb636cc28272a15090b860d5bef6150ce6b27434ebdc0c06aa3429ec2668695430e27f822bcd71023b0ce222c88881ae6f5bbfc98bf6cdd2f4e6969f93d79a7daec49b7e4474bb36005f809e7fd2edb1ef4e41586707dfa222832efbc841a919f5824e7035c69d69cb27806daa91aa89230022ab4e85a74d5b4a42030ff928e11625ebddf95e90dc88397563d30990edd93ba99dbb00b9d227653c24716e1ef97a64d41d9d6dbe377a9c0a02753fd5532e5d27c8750e56c4ede4e4b50e85376387b1c5d1149fe27973ed56baffcc69780cb6690b2138ca74c1732fc08a0e6681875797e3bc3df191a7ae110a102827d1f9a18e43ad49838607fee2f918a3a9bf659ff9a47e8e89c497c26e51fd93bc61de54197c4be786240caaccc980ec5669d8d45e53d0285420785ba18140a59f9be1b2584312a2e5d33c8c6e7c0203d24429c01cb7558e70b6a211eb63495a725d832304ba88768f202357176136ad3de6fee47757837be2d6923426ca883f7f9ce28368fedd4f8c5889c4d70a656841b5d703dd82dc3ac848168c8380d9f580f9c1755074e6162833abc8baf96b2112136eac4bb7c6685adc7566afc32624e669c28d08ba397d4c9fb7c66041b11b1a3cedec55743ec79b6a0eeb7217066ca09352537a24eefc7a7256c44881d75f03e9f59cdeeb3853abf18819319ced417d05bc00d6e78284866727870436638144aa2b3532032c4b8428021ecf8fb8a4517827a471ddfc7c743de8c10bb75e4dd3e32cbfe635b357ef16fee3cb3e3fbe7edf105cf5e7372dd6bc57f12d4eb1d96b279a654b4628d682a654b8a4bcb02680a89831645097a0148d7382cfa92e5f9d8327a7c16b8b48f441719dfff37726db7352daac0acd40d178551a6f4c6b10fd02b723e81632b024d2b8e2f7a5e8cf74ffbf7c51c7be6d4ba6f45ff23d4cb3b5c4acb8c52cec406a155847c0ace1666992c89f3b6cbc2c84cd89d69a0af787094322b46b4d2b4c27321f3c5eac9444b19f117fa53d6ca710b73a5499ce5cdf27a7f5f433fdca6b05a6e00572b68dd14f827244ea76952a15da9e0edb83236cc12a822bc39ca999577b14de2f88143e615a71ae57bb115448c1682b7c5d9b39a71f2c49b0502494f1e6372374e3615027fd43572d8d25e491cdc90182fa461b37fa47c6000cc819099f5d711ff72f1193b86b7e76c290fd37d26ad708d60c394934c965b9c89afc861445a961ec06aa00bd369f4f984cb4c71778959f3949b16072bc84aacba3cb87e2c3a6853239f36d9ceac6f6268399964d40bc3ad2ff6fcf2dda65f9ea12786dc7d7e59865e98dcc2ec8d416ee21693b771f321d8eafd436b982da1953392d0fa1022d99dbd14eb3cf9c2b611753215c4c0647332d09f9270533733f662881bd3be77f7d3d1e29dc6801a52edbd42fbc2af640075d3b1e438c5eef4871d056bf3749d18670c14082f9586a1bb4e6f93a2bd7e9da2d779c4d9d31de47ba9538cbd2506208463add34bd15aeaa5ba7780d84854a41a9d6a14bfadad9c09ae40c24296f153acbbb62651a856d522a7fab21dea2dd903f9f2b7761081081aeb6b5d7fdcd57d1c1c8d6a77f426ed4a7fffbb2e75dc8c9c9bd3f349c870ea6cf889f0d5159c45d8f311d7a086141fc4c285280ca7698ef2a54a62752955061007c5453f1cb4263921aae5653bb7af4706d53e080645e7cb22da6fd0ac0cca77551560ee5ef5323858e06b6baf593e48f4b37ecb79574c0221ad39f41e9e3efa480d89e1230dccde9087f5a33b647c4c6eb05873bd5a0e06d9118f630a8ba7271ed095be8546028242cc0a321956d00675e2ca1d956eb029db1d551b2b9ab03b3c77b8ef930a7984a96101c2e018c4936b4c87f7d3b851f678a647793040f52def86ec94e43055b7c7abadd40813aaabfaeaf20fd16d19b55b4c45d222105fe0c36767ef88016902fb703ce86d8df880735f81d0a7f476978ad9bbba0f08af82020b5d2c7e334c12edc58d05ded42d43253b5e261d39be30e2b23184a114dd2ac58d122391fc8533a0d0f03ecc004fe4c258b3b11e69cb69d5eb02d6aac9e283d63684ac311182a414e5b21f20d1919dca617f2c09bb365066d8f09d25ceea16d2281dc86b4b09f1b8316b852b2a1da64fa693c5e079f10f9716e3887aa6bb3a49c0d80cc6211e9edf97143083c2805095bc349bd634fed0a57d1a5bfaa2404af8a633bd92d00d336384ad725db67552af8fc048c33840028fa9e72c13bc28859f1d65a867d1b2f7ed38c05e01df0bceb9cddb21437c280f96426ec3d846557565c91bcd9b1578f94b873c4caacbd3868703f6fba3978a1a36c0a7247aa0c4bebb38ded021a45bff8c12e3f1f733e6a84a0a40f2387c91d6db88fd1f2896c4ae72ebf7df0095738e0d681976d67d119ed85bf21f2d69af1e34a3b17d8f3fa011d7a4ccb17a4600477696005dc407b34684167909e6ca15cd8cf91125522c7a06b1f9075669a7a1a56ef6b1898402f009303006f68ec8b62bd30a96098b264563c7709ba1046ff588deac492ab1036ee1e9b9f517d8ad060419ef4445dfbbe2284b0e3d7ff26b7e00d446978cbd93f8a91e3e43048d37241bd0f4f0e2186f298c44e8a530e247b4a33fb12210de0d7ff0373e4ac7dc49d43b5b626ae8a8ecb845fde1191a5d049e205a03204e54c57ff86d09846575a56fc82e769d84bb7f4db6ad8b04a59d544240a3a90b487e1748ff615364e2c01ecfbe02b7116a941c37ffc9cffc00e88d3983e1a455408bf2c0317450cac43edfc324be606dd4287a155c93c7835073681f0250c1ba2468b94edb0065b3d2e710fd84bf75479280ee4901b229fb27c9cc36f727262dcc20ddad60db4108d49d157187d3a4b751741c84f3bd5c742582cf7c6e21afb8cc737a55efba97805ffcf332d20b86fb57632b748528b63d820f44775e48cd26badd760e5de7c86d3d25c44b5967411499ac31b2329892a3f6c222f4d6ed09db961f23be0c25a9bdc1962557418da6e39e9c45cc565b7b8d4c8eaf17245af47915e163af67c343277d1348cda8432968fa144d069550d8034710aff079bd7a72190a7475d18c370cd6065880a047a3b3eba10e7a9df9bc90c341d8028e8145cf4bba1e3641afd8f67a49afe1aafcfd79239c57b75823c2d7548cfee89be79343f3c0199dd8a65945604a3f846aeaf28ba121d1b5e9219617f14c2d0f511694a7684bccf34df326dc01bee2879923425da1892cff9099af52f98d461a233da941cda53099a7266f99dcd858559e336d00051a42d19a6b9c188ab9591f029a6668bebc81a8dfa325757dc70c4e9abe79fa816ee1dcb9e69a244431839c9e2fdc7584d977a0f3abcb58030cbc824b188b1a0b01d75c18446ee640f9b7c1414edb4c350375149455915042e59fd7a048a9c2c388358fa48e9f29f3ae9bdfad3744ef2dbbd3883c324b4dc75a5369a663add5669646734bd2d0f789bb5e567593dddf31dd6468f5ed92d94d3b6a9cbd25dcd62ac07d0cfcddbe0b477235703717550111a7317763783c0d2c1c1855e74ba098c93604026d0b1de64c10d646fb78743d5b97460e0faa3bb2831790f10d333b0809aebad9dc1f3b505a003c87112a6bb279a06e5b7dc828bcb0c97fc2b62e3624f7d5ce7043fc57c8fd214c6a0b6d6f7095102d45adea7778388edb00b53c343693a9ecd88c71321c7be9b3f139d63612f00de068327514247d03b253c1d6d399753921545d24d32f25871c658cfb243bdf5cd7a4a08fd206ba6e05dd806f286934f96f6ecb048eea3302a0db0dc9c230404571fbb443e4f62ba21b5c753840bd82b456f8cb42b6c9324f58465464ce77f050d8be20618b201caf4a9685ac95047f89f6437147022a7a43987663d14cf931f1f721157d31b0c0854813b75154c175f2fbf1ea495b00fbc86a9973ec2d024a8258a5c8efab83a40f041d65bd5a4290460342ff6bc2d9a92ec5f74d0ebe5898644d3aea43a30fe945b576496afefd78e5d3d9be8d750861a68a32fcee2fe9925b75c5c2a693ca3ddbacc20c6219d907a2a781ee1b6ef83ed7efaf3094e3050344d2df9a22de646621a72a9b2bf4be342fbddacac9c699d2139b374b2c9608c13e98e0288f1174e22489ee400dfb81e9140c98d95235d9b01ae34c3e1099b2f77b294e4469237abde611353a8902c9f53015d03f63aade3c21f22900a43b6c509e3c5d91ac1245df0f8e89c43871fa0a27c4fba0a7890e8b587fba10947cf785d60eae1da2490200005e9c91db812e8402d8b2fab5e867c579586fb76b9a01b2e564ddffe3bfb873cf3862ca9d605f866466abce357a1d6badc754c8b38519af3924b3a55aa6318e997bc44b81fcfa02a6e98f69da826fc533035c4dd3e6337a9ee479b026fb83d946f6a96be7c65fd4621abfffcfbeec4a4f6c7e93c668877ca7bf0fa627ba895ec43e7ebed25b466cdd5906f5d43c73ed3a0e7fb7ed8a1090d01dbc86adb7aa6222e957cdbc4ad0b3066c77b6cec078e59cb9224fbfb7ffc0118626dddc315a0ad54b24c77c45263c618f222c1b1dbe701d5ba353c33409209a26ff945f02c673d52bb105d2d0014db83dde8825289b5623063f584fa7d23bf9f58a09393d3706e612588b3ff285f45fc903d3ac3a0c1c7560c38e546cb944a9194d711913e78d6c1e4b1055577b505f8b33c39870dadd337e0391550259b8957b5ec837b06a7d7a067ee2a0ed23debec5025c547fa7bbdefb0e5d3944b0bb6db9717cdbc9302e12d6cab8306c251972bee073e316a177883b723e024f3dc74d2cf9cbf4dc5e60ff55824b7a87ef79ac570fd4d4e537515c75c3c32f59b2d9082ded7008756abcb3ce05c4a1571f9ba2f5009621924cf0b80f7a6138ba81fecfe6e8339fa599021bdd4b4d53fcddd7a7cb6b5208aa310247e05563f9435317e4c6743125691c4092138a9c251e67fe9eb33661135d256fa3eff5e3918be9fca9dc30d48003c93c183f359c85ecdeff7a93cb0e6c9276a19413172d727a169b2e050b55dd817a86053d2f8954f57e35276e8d32660fd6ba8a975191c8aa6f35c7abf5ab005c9f26576c734e8b4b74473c888f138f43ae32aa8b75f1eb3f17a1eb8a9eb5f7857952a4c15ad22836a971f8000bfbdf74047bdcc780fdfcf08884972d46efa0ad1c5d929179a1b76b042f2c2446a6e43d6e90f6c50fc24954daed04d31aa40a5a6783380aba7020ea02f5e6eac21978666df24a5c6175b3f52829b6b489a47ed03a98ce2b272f5a6c262545d246cd56310ddf2ad614c41f8c8dd085b2c4e27692a654087296844dabc3dcbea7db4ca4824cfe3503f6efb65a4e34b4046ec1a009961ec5253591d4ab14d11dfc5b0c5d7822924c76f0459451e9f0977aba9b11e8f1170eadd8cb972b302606bea196b79cd09adb788e816a35f216ced50f01ed5face098584633ee220ca78228e179bf5174df893fcee3753af9250213689c2447a5054db9b44b5a364440cc2c2d6bab1076cb259a9328321d609f6b663468a297ce6d3aeaa85f873226740aedb9b51c0ea5021ffb420802dd7579c124fd15c52008745ab5107f0323ef65c8599cc03236ea8344153342818bdeffcb4c81fa7b9386fbe89a87b9bd3debf6f9acfadf6989d6a91bbc4c5437fc3584ddbd4e89573cfd0a1271a7c7b21663cd965a244c1580f420508aa46cdc5e8605eb1acfebdcc70bfa907ce8b572bab947af5db6356125a96a7e75ec34d8560468841965b4d043fc7ab1657a008ee1a7b3ded6c60d860619baa35d02eab44dcdc33a48687f1ad7ceed7afecdd8e93823cc68a2d2ce464eadce702ab0ad7beeff62f7aa3b0f02a4e5448348807b456249b732b6079191e1dadca6de298d44e57f0c7b01f7f299b12341c823bcabbdb3fab1c3d5a14f57af8ecfd2547478b432eca192a177623ddbf439b887b92485f7163aa89075a155e57c54c891ba112261201c4d743d9ae5b4956ed4082d523861feaef2ed3899dbabb5a9baf2513e72f643730478650a8987ff69d2798efdb917957d188a6ca2409ff1939b77c2d0f28c7f0903cf2e20eeac12e1c609bd306c982852d2fbe12a68789d2e9f6ed0f5163031982746e66ad3eeb89689fd62cbf73994fcba8d02bd2e4d6f729b573919f8bcea224e03d80bdb30787b82910ae6018ec1b81e5e587d2557c9847d555333f95117a3f78fbea5bf4ea27da13eea2d2bae2b5af49e0003eb831d18038b36c26f0d0c4bc688650602b8416e37de8844fca81c2c736e60ae640bb844ac090db2529e0d94bf2cee01a62333c4652507ba8b84b912288925ce0e926fcaf0ab0400a2c91aad2223f08e22b60e6fcef336eaf4e6c1cdb496aeb7413635b5423537b691334039b530d9e1fa26f6eac7ddd21e9171a3f010eeb4c56a1d6640a440560c4412fecdcf08c3fa9c1c84a14b25e6e91884bc81dfa0bac346394e32ad6623a15e8f6bb1c043e1e1008ec55a07a4d9d4e0093deb0a577d942fa4b64113cb69987403a2d663c913bb231cd72c25e94574fafbf570c37148571e9a9cffdd6f93c718fa8430ee3662acc84e4d9c13316598f43d39fb63d246c647075300e5f206d00d0b50fe2073cba67a1b76708074594a615216239db4e47d873870fcbf1a7c3908cbcf669f15e86306c35e0ed9cdb20c3d8f1059c9e643a40e48194f1cf180da8377120e7813f33e8de0fbd1d704372f220ff4fe4bb9ffdeaf55f409622dc151f865da38c4ab4338be2043782a47dfb4979b51da8480bad281a8efb51698205ec5652d800d76a3565309ba3661a2317601721f893cd66825c3eb37e8e34fe12d1f315c692b31853d2f369e04d866e79b2342aa9013de7cde23af466991f612754b86f27319cd32ef9a2611941480780467581d7836f8daa43952b12467de54b88b2be5f8165e0a3a6698a16790be998079fb1e622bdc99bbb8972a0505b760210d5ea89ca1ac972f59d46c3407a94053a33c482351baa92895a12a334210bf4c55603ac87a0c9830f08cf6a53ebb567464a8a30c5f7adf014bef6320689a2e0ea5226a6fa92477f0b4d5da51dfcfa75318036104135b22d6143c11e02603fa2ce7e846e91924fae8a7a6fd72ea1349bde3cef59cce3564ae61ad528c22b881ea800499cc34022bf9c852d870bda5a8ff42b8e00270bfa0d459a220a849cdb549cf5ab7de8bd77af877c224c9171a569f6387b7cd750a1b93c736ff95c2b533821055d50f26b1011465edf24aed7c63afe97854d94fd9a7edef5082f368f19d8deb6da83a3739d9f9f7d00102fb2850b4e90288b211a6a3c83e6080954038a282dc46aa9480b88b8a70a8c28ccd11999f97929045f838f82dc6680299385215b2cdb628d1069826751a8eaf7925456b93a1f016a269458c91fd1865f07ba5440eb787feac823fa5e3b73590f456d961492aa63effc9af49bfcc6796e0d2499e30a5f48b9e47be920e4c3f54ebed8d205d026763452ca9be78df6d5b6ee937c84f4616ddafff159ae442cdd911f473b8a192794b5d370ae30e9333051956cd1b8e18ba0fea662154df7c0b456e91f4a66b07ad647d7ffbcc6361cac1ebfbcfde3e7b69bb2c4205cb2a7ae100a5c2aa9ad37cf3f1eae4d853da523febc8a6698a0997ca4fd7ae9f584ab08fa23b54b8adc1569e3668639e2b5022b163e33386bbd594b81ed5b5b7bed9cf1641adeccdcf3e1a531aa6c3c3fddedf73d7584b2578c94f49b147b979ffd44870fe13724029be0a393be481621a2f5f092ae5e9c8f14b08191a0d265bd857b81d5dd95f56e6814eeeed9698be3194ed7cb5dc1cb9a5029a9dd62c195fb369030d8673fda36041952f79fec821a5ad023e5525cc7a0d805014cfc9fdd0d2a666af47a89c6fe01b3029df99898609afb06ec20607a7f427f1125599a5f5dbb40c0254ca4abc657e4e83db32be24e24c4c1682efba2d0abed7f0bc30f37c1cd8a38994154a82fd8b566c654080dadeb14b4a3d7c39a2dbf9061461640f18149a126a4cbb7c74508f5ea02aec41e9fc4bf036ea294ce06212bee139052175550efde64e449dfda8aff9a93c5a1849a8b13e36f61402bd8b5848d5fb0743bdbdd90c2987694bc779d5ebbede3ef1bea29976a443e138769d6c449067ece4fdfd404417e74ab8b55963f672fbc78a076ca2ae8869944283bb7b21a32effb6596a6991ab248825aa37b32536d67a018a77349c5345622b82aa61eddb0a0b25cedb7b73fea904943cad1fa2ad20926329eaa686df4d20a5eaeabdafc7b6b6c899dbc5e78ea19d87ff73379ae20f67423f987b3834246ba3989dbd1e614a5718aa72b79bdaae609c488011143285bddb0342cafc19c2e1c857d2103e5a01ea0b1e09d803628682238a7e57e9845398de23511b0c5668bde6cdaf374cb83790f8b5f1d42cab7bc133048d5aa22a2c08a50f6a341cd28055774236c46b59eb16512672ada4e0d864ceb9ef805b0a6db3a8fd19fb91492cc11ca549e83bb74e001ad7423ef0f3d3a5cc46dc6bdd87dbca03cb8988f34918b824a6bef9e25dbc2fbde1bddbbbc156b9b123994a8ef60464ab75753eeda740fa2519f3217c746053a1bea66360e275bb3e6e7c507160bff8a10691d0af1c5e6577a9f27aa8211ea37095f9f92debb423befc3fb15f718350daccba0c1267b3fda6b73c5e5b0826e3ac3f585b6d6f62365ea5b80f06ce90a3ff31af69b95b850ae88946f0f819d1e819c570100d76d22daa764b3bbb3fca3ff334a4a0f6e60b05d51621230e85194b11ddf10b494bb2baf494e3e8cbccb9da1e8f621c01dcd4625f4e78e5b08d8191aacb316a06e51c43d6677bce4905f006ea88bc3d4bc9137893d2276955f7050e81ec418dfc4b6a16f8b5d79e041603ab16aaa75ce3a81fc67709e302b9881cbb235bf3f80004e654f586952a5fb468c5a632046880a39dd74e841fbf68ed5ca91bc34f8b701f32a43ef2fd22fff35e5596f9515cb010c6a31fb2a81e3327edd83b3ba6a747a192f02756ff9c64484e1b1614a55dd666c354c8def0a6448f47e70cb3d951ce131d0c52d50d70e53f25073b444ab077934f7b98a88cfa94c624076f34c80dd4bf2c6279aeee5da27f65fa098a1c0d20b07e6a82e43462e4280339751de6ea4621a08521ea9028d1f73868ef1d2f192384d4f8b980971b2864e0d136921e1b0c18147337b917868c17ccad22a6c48bdb43114986b09eacdaa1929f5e1d49805f97d3698ad405a02b82be25e401b209f1eb1a3ff0a91c8f1ed29642dedd8f59ff5db51f50df5803d371a4f23e6e5f37907d4a0d1e178493c3f540d9430cfedb5f44682d89aeccb82b170ceb5d858599da2620ed7dee6426af134b68eaff779c0a1cf9c4cd0b7d5e32d75294fcd2bedfffb006764910ffbfe05073277b34a179c5d9c52504638c35456ea3b2e38ce5c429003f7c34fd0a105ff4e94ff320b5d8dd3b9dad28d706162385372cacceca627108a628c7a39a0df215a403af6224a045fb299b4ad9984048a9fd9159b75e4f654dba56ef5aa94ce751b5af0a500933c49623da225ec3162cd104ba725fde52b15597afa6a5810ad151ad204225930d7f39399d8239a0535925353fa84d399804793a2d71f597090b5fa9ba05961d414e1f83d86396eed54f96aacb9c66882909c2870e5381f98d9cf61286c4f55a47a749297cb4c8ac8a69ba8cea4b293ec884aaff9c50613e8c77df74af467d9d71d489dba0ec5dd7b6ad9aae0d793138f1d548b1dcf40117bdf1e639dd772c411e1fe05817644a1450e89d912e779c8274157773903b4735bd55716a7e2fdd2e1d3eadc0cbefb964bb4336ac1f7d2fdbe5590104e391da3eabf77400b6ec6b6b8bba47c574bebb9d1dca673a61e782e071b763d85b6a1dd14ebd3171b381c9ea6a1538053ef45be8cd14f69c74976e7583549a9a9f0369750a9cdbdbdb6100dadfd3365adda73fe6190f6f401b0c096633d941abdee25142f8ca95d2516c4bb879659b101400eaaceb7cbeabe9f5b9285f994ab5d4e7edc3a7477a8aa7578875af0c01dbf49a62269fe3d7feaec96d161cbe333d8ea04308eee6672fb471bde8fae676cec620b3b35464f77adac6cda4e1f0ea07e13abc0f797fc5c79313e0241ff3f0317f4c16132dde39c78dd943acadb0c797cc0016878016c54242e0e240100d54857a2c0867c197adcc2048d03d41ba11db53f1d2bb17da63a2188f070f5b6a1ae8e95fbfe4e6907d7d863062c1523213b2d4c223352fa72c63ea00cd240853e1593a1e3a39c6bd0655b911badfd502ea416ff427af127ef2550e6c8111f1fea807a8ab3acf30d4f6d391cc539e207ee6091caad4560e66f8bc329aad800d3c8dd48a2797d898f0e90ef8113e9a37520998b0eff84454c2ceef1db58c19a8dd6d471cd7831e01a3bc3c408cd9c6c122334b6dcf79318edd1943ef76a8394518a37a8bdec8d9e62e735a8e44b78eae25d190493585c0684838ee7a03203280675c7c9a32793d17d9ae1ef68936c27ff142d862ff5a3a74c47d1a850ff12ea3ad5a65424024fcb9850c96e3ef58f45a79a0e4c8c2970193541885dee3ec0f7bc5b14ecf20a35607ac714a57e9e1a018069d546dcaaf601874f880df7d8b9810dd3fdb4df901128d99ad80c9b6faddf3723d67a6b43b05a3665018f5d13503f074706465361436a4d799ad49f824cb098f13e74dae95992a5b991d5d2d6c9ed62892170adf77e3e05d747a2fe6d26340b841be4a6dd507b1220108106eb0a225ac48ecf59c8584ad1c8e44ace0bfc650a208e32749e78b88c1ccf3411466ce8bf06d9584288e25c4ab0edc926b3bf618f34a4494a0131b8974d1c24f7cd29226a7e582cc590aeb5d8f8dbd508f979fcac28accec14cd68c3a02d3be5a7eaaf9aeb96a2eb9739f5565008db5cd044a37afb82e3f5e27ea67fb89338ff15949e1e0335cbc85a8f8357d7e23dac70c1944dd9fe963a390acd736291981ffc32b3a7c1032553a06c4103fe137376d376686bbc05fb70a7e7f38afaaa82ebab8d0b8256a5310c17080a06cf0218a61fb0a653b8947d96d822503a4a38272db5518a49e2cc2b05569227d41225d3eda852a1eb4156bf312c865a1713d507a9fa0e191755b6c88b2eb97afb688d4815095e84f944e3d4ee5fe795aeb2e0029433a1a06ac2f68fa92f2180ae85bc33a38304c8bc008889d56f4bc2757323058d4a5d79635f0a9f419f1ce306145254fc3b7564181348be56900792f1c424a00d1a3614a110e892e80426cf54243b9105cc6e30445bb415fcc66c92a06efb059f3f5b3e835753fddf81dd938f034c1ee383615497cd67b4b027e616c1d43c1a1d95af95a57ce521aa740b206d59a7df8d9c9daf47bef6e14bc482e657495a19a2e115fa2055e99c3e8d65b3013d2e1a94ef04e533c26a5a9da71a2f1cace5a2983b45830a833a183376ff0e3004a27ee8a943e0c2cec81c37552d661f786e0fe9208ef5c722961abc106f1643bc4663fb1c2c9fb19ede11cee791423e9e469bbdaa4b7b5ffba2a11d3cd2405890601c9fd600cbb8a7a0debf4460c0bbc7af9d45ef73dd96f605649c1236505db677db1e6f5e293813d3d5bf7fede24e0145673aa88b951f75cc2ade31ff47c2fbd7982dff8518a8c5172015d3b5a7a51c1cc3297b6cbd387340ce65be156b44a9e3f021391eeb95c775323dd23b68985f9d6233513fb06f363909e734e16c30f9813a55c04c98f11032f1e7a4696bdbd98102776953159ab3c14bda2e39716fd2f22e1141fe28d8f1accc3768ead65dc14ba5276afc698b142e9119e02e85945b78a71a11c8d0ab42e0aba41223d77e90172c8aaf0a8dd75d07b659cefdd18778aa2ee8c3b2d757cd917d0e05822701446194b9fe895a04fbab0ce4d5758936a14dcc3953985fa30014469dc3e16d38acca2137f498a16a74078c0013cd3fbddaa1c8c1b4758a05039d5effead6770b81100aa1fdb9586342e3eee177bed011474632998db6b2a4f9581002a86c66b838551fa63069544e98d00e5733a67636d55d0703fa020257c02030e356f574dbf13861faeba7cd6de20522b574ce66a6d974b758aba33ad18e54a5065245f25185980750f289ba91248efde03cfd81d42eaa62b9cbead6dc58e61ad0261bf72302a14df7f238f91e40a98b566398022a3c42d2583f3945094160df1a1b8ca43265d40b69259be3d5d00430b7a3c664f893e67e3d2723fe83dfd3b69008c96890a35744255f295b318a5c23364d70f1b1379c2c54e6188327384c9914ed3661673d0e8593d5b4b123169966233548c03930da74191a9d81aeb494cfd32a115ae2a0bc4b9dc29ca8651396d313eaae3993c50929921715fce0c1f791ef40e7029f98b3b661a5602a7f58408125bc38576997145e99ee0b0c3629957918d96ad2b1114fd54482404c9951cf93cc723ee11cd3a52cbf08e72070d27e4e96aca224a974bb34f4655b610258a736c8d9f9b11e8ec7cc835b743278ae3a0dd8527a0e6a9499ae8320fb04945e450db9234c07f400cdebd90ffb9ec4d4cddc61d2894da22ef359b876fd08d7173b64fae1366451bdf7f286713bad63b1272d4654629aa7c4c6e75f84437e84e2190c4c303d904d3c7070d459f7fc7336613f98e6fa0c68c3cfa7bb41fad7ed3bda6f1aac28d96a643621eaec07867f4e20ad5d404bd9eb3467eb25b63cee6e20a76ef6582daca3efb7e6230cd8485bc0786d063f7da246d502943406fa78d550b601d8babc9319660c5abb0a170ab062aecac5445835cbd942f116130914dd2b24f3e3524c1163ed2fc2052a95685b94c2064de869d3c20b2230ce3704ad4bd3da7d7be42537c63a8409107c6fbdbaf1c7b98cfd1726fd71e1dbcf0170fcacc9d0a91a6ce9138a402a618311687caa06a4bc8fc144ccc69dbca8539519204e8850ac5cdf122e73530dce78a9067765c65f24d5a08af3e4a093283413409325214a2deecac642e909b43bf6aa348772f21fe99c36a0eaf5f8749d67a6eaa89cffdd8cddbee3117dea1b8145eaa8503f18841fb3237dc544498cad3206544db58db75ca853330182d54d031fb86bb259c0eea6184f1f24948215763cad7a431c6df7783aa5869ca25a19c4976d9adf07e0176302f147d344851863cf43daa2e61e40e2379bae3d4042847656298738a88d46952ddc8f6e7ee40d2093be454c367ef4c3b46ef1dd385b35cb239abaf22fc94f3b0875a311d055daf88efb73301f94dc08e6839f108677a8f906804844921a7fd1925561dca694e31dfd9b0387890e0cb3c5f22b0c006a0129941782998053d68e96026b733b00d4bd0c1219ee3b5dc6be9111f3ab629ab0d067fce6915517b5371d55ec5e663fcd2c4104ea0868fc4e921c482e1241132cd3e122d0f6fdf4fcad3ff8a68c6647e00d6eef21f09ad50797523275f3b768a32320fd88efaac8cbecf01e57cd9493464da73f2b7ba410b46d53313b3c7831c4499707490c231a39922f5add911ac4602f4e3d4f95cf6e325160586d5ea25b9800cfaef370aef3008406c8865610005b3a87dcc0b5d12b5b0c810198456834042f36a7043683c38b4d7195c4334c839674c8387408c988433302b02f6b2b7640ed05c506c8eb8bd8d354e37ffeedeb59c29d23b2161b579894777d46fa2ebba5d216f49c80bdfd58cd65123869c2373948be61aa0ff500ad00051f34b8d8c16413a3b86a0bd5aa9319058c9c795019afb79a8c4e23991f99c0087f21649e2e4d8d384a93f1892efaf26b5eb67dda1415f910c680273b0c433a555f9e427be47e68f2aae8b1328eb48e4296711c99ba720e5ccf27da0fa7d06ce044a6dda7d188fd4775e355239d203b38d4adc05f23d1f88ba2e6a51092c5c09ec107e062fc9dcb0136ca684ed15371be1e524fd24f74ca8240f0ea219a3a7119cec767492b77b6d7fd21adc8c69345ede3e4ef50f24d0f1d35d93e8302d084b3f4b78a2d1fb12d96b8ce0e50b899d72e5b25a872fee638c66a371806ece6259692eae0b947272b3654d78db7ba90d844c1fc8b216eea63dc2a1928cd56f12b645b68ebaee0976e2c58dd9f57fca02cff320a9c13d3e50a88e9e95b8620437fc0b9de42175d2c2afe4cb28ee887cd53a68ff926cbd3acd53b1a8b81fe9808d225068b8c169b192a8329457ef545c4a2b29b1c4cd3460bfe2ad553d19806586f0f00a7d8236290cce79220c65623503738b562b93be1fe64403a841787e9cb0fcf59da0245b00091efb01597bfe68cb3c56b39d763e3310f4030696a6c27987d4227ccc4e679f65f307e05f69c5f807b5551795ba9fd2ffcbcc7f40a7483b096322de169dc6754ab4a486df5c434c0be699cf66584d4e8e1475eea500ef3db1bc3e7ad86cf5f8a9ddc306fa68334145a12bf91dcbc3a6eba1ae0e55d44fa608c2164744293df300b10e7cb7711e2d3d1037a008459db5a5dd5d8dce3d90e00eb4bde28acb6dfb1b7b697109f823fad942dc56fa39a1349c1e87cc77e331c71d8827a3ad0b1a5fd4b7f2deed58156ea571870444d184a3bd055e23ed7affd275f30f7aa22ed3c7ae34258749151f4408b2675e3c9af1fe8e67ed21b8078c5c5962d82af6bb4f500f2f58e18d9d858cac09547356312a65399553781e5c1047c44133be27dee663f1e1c451501820df85e1d9b332d96960e51a252a0ea6e8e1ddc77c462cc1ad3345f910389eb0487e78d5018e03edef4af0858e0bbe7aa5e4d63c2a7f84d2485f9c63be794d476eef1fd28a41b16458648555c0fc50dd5728cd73b1c921fb422b58b35b22cd618cdacdb15734efef43e0bf8013b0cd0b04f6d1fe4d4f9fd0f7ca2ba0c57e6e48db67f7acc58c116cb8f1d2ee8d09b64efbfa42ee89b645c032d4d234f8a01a19ce4a4561217160f263ccd06097193fee5f4b7eafaf006ebf5fb14eed95aa28bbcf9e68145e4da37d0a805b55e7d0aaede6f6de32ecf448e28a79ff7fc90456229312c6576f4c50c0b918c7569ac5831243383f43ff4a82173ed05eeb1cc4e5f58c021b8e0fb02855e64e7ccb53d2162b810e8fa142cd09cdbaed827124ce848d673c58ccd2e5f3c680eea36db80c21415fcfb9351f403705e74dee113294f182aae83226b335a1c422b81538eaa6b0899b2c38759f0889b785401df54c4a732266d9a7a2909e59ceebd3b37255b4b576b80ea385ff01815f9ca5a8a7adc74b44f3683708302ace09a0864c7a05a17b161cf1eae7d34e69e1b500396cac0fb6250103f4e4313447479962faba79a9f8d1e9eed2da4191c1b8f4f4fe0cd64fb9454e0152ffbfa0ba3943aa938c27d6adbce6e36f7cf4ea5813b2570bb56910d76f4387eba8646d98e16463ae3a2268e286a0e4901a457e41d8b4d64dac1b9ca20b0f25b90c53433279049ed2b8ac671696246a91f343d4b722036e66bfd80502744737216a43480d860d44307186da01881d134d5d5ce5533d964ad1520172c5327aaca8c0d7b3daf8740f732b8de6237390a72a59ebabdf828cc5ab654a114d5ae93f36c48aba1cd8cae16a57b9f85c1d7df461fb5b35df34821e05acf6499351d30e18266c740e16c1b5b5a2ffe1af720b525ebcf6f405c3b4b6a3429744d1481cff1771509bcab2c6438c16d5bde45b7a8ad15d32fbe5c36a4d30a4aeda9da35246365ce4fa5ffc5d274cc7fcf2bb6c46b5469173ec7a94e6ff26b7922952c48f39b8df55e50fc3ae71b5d88093e860fb445a8a7dd76266d944b98a2b625f7c32811a2ce6a78bbf66dcbc98de35c0006c4f0e811bea8ad73149bcff0b6d9dded8d2d390533c272e672ea5d5e7675c442fc9999965d9c2f9b3dd6b833a3dcf7ffc2cc940ff9c28febbc4d338383504f9b97e02e7b5729cc995eccc8551ea804b333565fadeb82c3e29503f27e2833aa4361e3713162d4148b3921731cd17ac75a276113a90ec819fc94060e9b3534ba652482c0e9fd862ec0036a22a214e97dc1180fb9ac9b379b604e71e5ce03fccf884d4cb43692630ae6a4e646437b7be50d21a977a2b4af3e871d87a53cd23c25df60c878ff62186ccacf88a581e5f62577c83b4e4c934eb963d3a924d2264c9adde41c03d261b9b1632c5fe971be7757ef6d5b352eaa6e0acfc0759149503912b44b0f917c15f94d3fd469ae0746616af556b78efda313bc7ccdcc43cdfa59070afa00a50e582e654258e96e632e25d94471e5a77a04aa65734622f12e60b9c61d04d56e62568a6410e937c4326d1cd8e22570a118cd56bc6a5b766c2eed54db61faedab4a8fcdf07e940bc6c565eb9e32748d5519cf6fbf01c2d5796d24bd61953d9740b542813465a5370f44518c0f09dc76b1abdf366605e0713ebde28d8f58bbe9654a463542dea5c4e2a16a05b224b6e635716ee429fefdf0d044ddfa2971eccba9b9b3df0a860bac73d948a63d98943863eb0d62c621027b35466a64ece9db1329b98615d749696ef57ec554f002aa34dd54420fef1f04f4f0bdc9f9cd6a522c11af141c2bde948b9a75f4c257f7c6f1d6c2ef21aa7ecec857dadcde237601ed486b0b1d63a0685ebd1f72d79330344e7d3b56a8a2d3f202d51eb5b2a0ea6082d4ed514a9b730a88e3c0dfc62795fb24ed5dbc3819516eb29e6b938b42cc6872b3227e1338ace6229de93957ef66d68152078a87cba05be72d662df38ab6e9a014d43316b5f304b1d5010a351c14bfd358f106aa58f9bf71ac2d24fd0329ff575e0ad170af274d8d8f17b02014e23b5c2cbd82c0d90911be4d377dd919bd18d62518f8cfff6b2da1fc6bd7802184f6d74e99c2d72aea52c3316c93f8ffc1774d5ed63b074d0706168bedb17e5efa69e9737ba993fb71821ad8b988910944402b8723487c1547c94b146ed4b50841c937f504a2cb5767b4f0a978b4708a8a7ba524b0ce05da00c3673f103836b62f359876c1b8cdfdafb582439cc476a0e90f82d477751db527dbe7dc1ed2d7854940cbbbe8a2d7adb311f386d8b0384a18078eda09c8a3388913bf701d974577cc7a81e675eb806087b1c55978be076650a1677add5ed29b3575621eac7a1c3d60cec60a269983905643522a6b433b16ef24a9b3a9e48a6dd92747b7fd384a8e24903c811b4b9746e10851a4a6bf0275d31125bdde35900ccf99783d3919955d861be55ca3ea7ca530d81942ccfd265b43b360aef45dfd4de6cc35535830a35687df6e914bc6dbb0b085c2fe8b742b554bb091203b66d853e06d3d16ad2e2ce1d1b1413a709c76866bcb899731b6d69cb004d91dae68c3a1bb80418cafb205072751e1dfbb994a9e598284f32b9aeae184e80bd59543be68dc7bf025c62c80719d9488355d5468ac422d33b99bc6e5d99e22ef086104410c148fb4a151083dfa72b81d504efcc3cf5939972007df983c0a710473aecbf41224338e63d02548bac00a4c7f888a8ea566baa6a769f6f1eb7ba1e54aa2f3168e50c9e9e3a258506303bd619d1024a408f24a1ea27a67b5aec744a488ebf939787efa92ed68ac4f28fc5a5e65bda3332034024e560a6120024e1b1316385e475e073b5be3029360c9cea3964deca25c3c12b540d8522ba229824ca7c606363762bfcee2c881398b4d5a9f6f980d2f04a22efccaae9fa74dc358cc2d0d6ef378d60f1c0cd7ec8fb2a6dc7c19538072a0842fed6d90383ac2870136938773e25d91ebce43676d0faefb0f25d55c692d4a4d7a4b37274bfe0b3087f7b11ac6ec024ba2784bd45709afdda1e4521ba4df9c295d85dedd211b6f4e55ae6a53991de593bcdc410519713cb549f1b1a3108671cd297a202a48d17549b94bb3fa02b51ca21fff321f9984232cb2ae6c3a0f3611ff2645d8e6e6aad47e8cacb2a73424a1438bc0fe10591482c147d39339ba6df8b1731b777c8a6caa32aaa2c7c8792e1cecd597ec3220c18312695e5663ac8dc733d2a57940e5f13212467196607254c2e0341c7d0c7d789882e0a999135c1fa9f1f597dc17101057acf2c716732e1c7ef67f68d9c69edda4e67dcbea77f0d991918f6e960c5207262aa6222015ab67950c41aa2a791478b3ad9f0405bcd03f7d57143673fcd7f4ffdaf0653a1c3e157de8aa151a03165254e30220c5eeaffd41c97e5371b81abbee462b93664d838d57567d0cff5988dbde46f0125b250424e3f3e8a7743fc000f569e071d18aceb9cf07208570870890544ae035af1e4292cbd7aa4f8fa5126c5f9cb95332f5dbb0d8d2fa04ea63742a389d2168a9249232b135fbf915d551dd4fcda49a4bac3496fc47f67394109812396e549c806d7cb46330b76594a2b336a0e3d8cf1e239c2f2c7ccd1bcb31d6618cc105cea82a35a108c88b1dffcceae12aa1a29636c8190c4a92ab40a8c4adb854aa26c90c18f506ab03cc4da731cb837a31e3785e2df14721d5be8c4ee0bd1036d5df8eebc2e14c8d3027774e6b798c797130009e02ed6b4a2970a7aa7aec742374706ae3996ad2b917465dd2e05fd75e98493d1c0b3f3aef7457c27e2b1a7eb2f0619fc134467d8abb86c6c47b7bf6795718d6bd324400900532c1d6881ad99556e58334a3d5fe62af0caa1d612de601007675bf79f753a2774ef75b03fdc5be5f66f69370ff64f432f47c5ad04bf3f4ee212c1b9902580431754aaa6690f83379291150e73c11a90e11e8412d64e2508bc202f067dde6f00059563a4aa9218e54a0355d5904c8b666ae497097efcf59abe46b102b59e92b58a25dbbd21a761463fe657722918fc9aecbee53445e63bc2ef4681ade234683224b58a1cf755ee7e1dbe45cc3dcfcf2ba444431da1b2cbf5118ef9255e86d8ab01fa474312e2e69233f20739e7b15622ffd00789091d3e9f1412854ba0fce6d8b7f8f7e17aae5a6fb0d92cae3b74998b823428568fa73a57929a6ea043c8663237766efa481a3828ad535d7fe75343500629ab03556f1981b227088f2b8057d2e6af39f5859191303677365c9992f7599aa7bd7e2080e2685c17ee2a9031a81bf13ba6a0e1abd279e961a41b49a4d94c007c6d0a76fe76f09bd2b6991ea70f8a516c93be143e2e44a98c00e2021ee449ce37f2f097b61d68bbe9da7b178a9a24edfa8c7e3f1bc8af95b9d58d2096a819c6b94a0b7c851b57c8fb014ac2bf8f0500096b406cc0b5db8ebab82b3c16c4526b36a2d0e15c215a37b24643247bdd2b9c2b151288f31469c1e8e77cca4e2d6eb326381b78017c4ff6f8eb2a761da222f64575e8cebd61e34c0b977538e3ebcd9e4f6580da0969fefc675d22135bf07d9c73168fff3387f40099950204c1ee650548a81a705eca36e68fb812874a38268774e2b87b347bca54b9c40bdb1255cab14811a89b153722db6fad667dc614406b68a24a2309241a077a41fd3cb4590102a4f2552c38863398d05cc7920a1361ce67d6177f70467f8ebd9b2d8029d771578881ba20ca66350cff1545a61b725c8fd03ca495b9b4fc9586924202460949b7d88879e5bf23f8c990efd7637e3a59821e976bcd74c96e85fe6624d45e3251b920d0ab18c8c65002bb8046f954578f12321308a3a4146b11a8a08606c65df9b7c70b83046ca5391fe4868bd89fa23711c7c1b4921b14cb82a07c4a9433fa8e4d15ada2ae2f9700d6e7ac9c17d1c66969a273e7143c0d2bf88563c201638c63ac311832f1b23adaa2886faf44c3cbad9dec156c2ca4399456fe9f10da853d2a70e4a67421be34be3a5cf40a1f1156ec7e99c44873187a4319e156c099261820fe4df3f1ea6a5e778c65d014027a8bc6e95a8a7b9effb4629db97e900b32d452ccb34130693ae2040c7ad3f92c0e0c24bf44dfcac609b2cd90bb5ef6c7e38980ebd427c1ec6c2b92b6f15c78fb0b0e8e7516354fd21ae5be504d97019213138d88be914868f27e087439f9f8e193fd7974a0dfb8ab2be5b36e72482cfa3d6acfc265af817ce8fdc54112b5155a25710f7b7b22cffbba488bbdea3520c2f5699811cc447d5690465641003e63763e39a3814f92c302a70e2de1c3a281bfe38243f4305c2ba0ba93b0b0a52548b7d03005bbda041e4fa27b2825409c4a3e118a5f084c30a8522431d926bd9fd13d60f0594e9931ffc1fa5681eba0328828fc0e660a0caa7077f2525e40958845530a218ca997994fcaeca06365a1a908895619ae3285204a83c16d55425c44c1f52270c75821de1ddbabd541c5dcde9bcfb4a31a9fb6787beddfb66923e109400da2b90d2909c2208651c65cae4cf9fff35850c0710fa3c634842016497387fea1cef76991edb11c789c161dcf114f2c85bdbda81b042b97197783876916d876cd2ff61a218741f798591c39ad5b694c8ad6620d10e67c0ce1a0c86255c0eb02c77c9c2939785da3414bd19780c22b685c88217d5801fee2744cd52c080d600deeab3cd8115211108d68dadf3dde395cb4be44b2181fc9a6436b35c542c1e0de48e30dad06f516e103e88169c5150224cdf668d8b359db890017e230488a5c06b9964864058893494fec90f9a68168cb039fad7319bcb3f2229177b481fd867745d819f9053323eac3d0cfab7a4f9791aa59fd2d7628bf53ad4680ee713b0eb0edfe49212ca42179278eda8af245273ad3c0741fb2a35d0e599289b3ceb27a703cf70b2f2d1df1405c333a565ec754d4b7742246dfc45d418b03d7a62a45c6d1885ffe2cb97d847c28af61d967844be2be34a3e018c3d65467b0485bb1f28b5ace46fa0b09d5ca40a0941b6ded7947a343c62171d009a7beaf3c66cd0a9118155c344ddec9be5ffb44a6689e2b9afe10e5e0daeea9c3ec1e527c54b2454e94c9f2a7f4435bce370fbc6d7eeef5bd96189e688e18f5fab21c17f49b8d92492741a0332e10d0a811001825922589de899a767d7145f1ac5aeb59b352d2aefd989a22ad6e9439ad25ddc364b7f3c177110d788d0070c03a3a5e05cd275498408b8fe7123bc2165e3b54c3a9e83cef298b98f6820d82b529fdfbfd8099ed82f46b56bbc07801d8f0c11d2a0a0460dcdbb706ec28d8c5f92e396605cac29246bd43e5da26cca2461bf9ccc5bbb9d3dd22349f9f6e2f1384daa3c0d3e9e028153952391aacac57155d2647a4eb78d9bd5cb9bfaa4a7b5400c21824c2d4c5aff745edb98799806ec80021d8c2be9b6e286283fead10593f0e980d076414bae733abf7328ed92873fb750fcf8565c5eb1ea5de5d5f8c45331d7a87195d38f41222bf815ef48c7fc8fdeeb8de4f37afd686f257d3f14bbda7ebbbd2dc83bc3bf220ab25cab591a07ed43dd140025912aea03bd2fd284bdd5221684b06ad6a72f6e7417b83f8375079e5054ff1adc126ef40253151705648ab2e6c4de63a0c80b10ec73aaf9f796e8009b74f8802d098fc86607a62b68917258d7f12e68d9780ae517dd9a255f341eb754b71d9854c7f360f09c9dbde5bd83106d386149898beca2fdd925b1d80713a14850f3e00449d095720feb484d367cf8a3213e443157aad8dbf13187563cdcce9b6c85af8af483600f60aa0facf1c5dc08fdac5725169ca30f46350eb74e8aa06b4c9d4b2087ef8828df80c5025e545f49f40f04fe6a3319ec11928c5f3c4722da7fef68314676426598e61d9f9a1c0afc0bd7ceb7b3c8948f088053ebcba6b49b3ac8af5b3dff66cc87f36dc307298f860560624a90018649e27bb85615df06d563d35e6c4c048a2a47a25430e050510709e6a196e1925cf40d383ee289df0383abb925d3a27ef946d3186b0bdf639a1e001faa825d1b003008372cf8e2721d77bc2e7e51be998bd139e3f8bfda9be9852f1533b409215bcabde5de52ca24652a0a060af60973ce49929d265beebf176416102061e0141946c90fa14d4c466e7cf039c43cc92f9ee471ab6dba526d9af221a7b81497da6a984b5194d394df40cb78224b2ddc6a388735d92243aaf8b3f8dff0476bff7753c90715345ae6a7d051a36d04563759d0b5e7ce0e99dd54845aa11645798cc65a9b3e5eb1e2739173dad9a63e67aea35dafc82b3e1710fc5c3a6be78651464f7a12e9492ff2a497428c467ef4a3f00893098c3ee443c21298781884901f3d8a1fbd146204054845601e44c8cfcf21e0cf94890d899827d81ee6d59ebb9be991d6e040f35975b9683e9bb5ea0a5273d51a73d56a351845ddab75a9f42f8a6fd03939a19c108cab1b57b79cf37a5154ada935af182b08a613f241b3a9776d8eb5b6f5663b7ebabe936bcd4eadc9396867678727eb0bcb570b7accaa7b814aa4db841e3d26e61137e81e3dd65aadc787abdb16abb55aa3281a2448e8150bbd64b39eca63bdd04c8845635b90572cc8b60589c5621bd73cf2841e3df654145291b441d3a7b29a6b9681640b2bdf41a2484fbbd106a2353751524899d854355ced11c986e9b905a9e23017451d20549bba20d1b4f72427e86336007d00320784e262312e4639a0d45e718459f75945612a202a93a7fa84e4823c5d2ec871387dc685fa843cb9cc7dbe94c75656f0484d8ff9456114866bc779064209ee6b0fd703bbbfa54438f4bd28f481b8e37a36e57c7064b89e39633e3832dbc3e0c86c325b0883335373736b38afd9d3831c8885a6a40a7d2ec6c5b81d1d809ce322fd007c2ef9e5221577cec9b0957ca327b7bd548c8d1a2eae418f5e0abfc8419cf27dd1d7653989a6f3939cd06edaf32f8c74639b8a5b7e335aecb922075ac6da73362b8d8114464d249ae69ee484bed8ebeecb1632d0723b8b385c2f8c9d1c685335e831ab54af57ce84d5b9d9bad97965645e2a95cc2cd6859839575dbd5cfde15466e5ce059b89f303e707ce0f9c9a8eca90abb5b7371f462f67f825bf7cba8cbe137a9c31a7301741d31eb9821e678c73970bc80bf85cee5b9b5559b5cdcd0bbafbedb7e99a41aa4b6eb9e4a2138149798447ab64f2caeb6e48e5751745cc40f7b38aa2ee8ddf1b55ec35655f8a092eb4421f0e85fec3f20445fc5c5078a189a5df8526f6ba6e088363736f50a0e0c20ac7c63e0c8e8dc5b1b1210c8eebb2286ac662ac4d9f44069dc371caecf963d327ed680f2be8ac550c0509c6801c1bb9a13098aba8897ee966956c71598c55675285521869a40bb265fbda536badd4965ff9c58d5033c84df447e12cbd0dc70be3c58b1850170201c5c209c4053d56a751d4a84651211535c9e42934052972419e422f1765cbf6f43d45caabdca2a6979f720be414e429cb48917e0ead326bd3ac922a9366d6b8986f6c268d4baad0af3d37d3c6c6ab31584cdf92fe92f8626640de366e40967e5ae1803a2ff51a0af9fb4784b7c7126c0fa910b4694ec904f969aa54e0dd34f2c88d5ea552a91508d180cc841a7a360f6f91a3478f8d38bf4ee28fa362668c07e14363b8c9df0b3bfda20d5956527c6ec31b232a78a9221cd0cd04b0e98fa441bfd080cd3a5a37eb66ddcc010ec023372368d063b7dab64aeca21016811c81cf25d4e98868a7e3a798ac5be9d5a6399baea889bec8873c09d539419a5ed286a246617ed1298b8dc4740c1765b8486dc7f2530036fdce47f7c34f21a093e81ebdfc5c8230fa18aecfa0fd6514b63f10dd7e346954d629a3afe2047abc419d8c9fc6d08ed2a6b1a08eea50588a3ce891c2708d1a9fcbf6353e17fb80cf65fb077c2e567e2334bdd50764f09b619adf8819b4fdf09b117e439874b8387fce300420802390476ef43825f0fec54680e8299b4915fa7802263f8dec208c4621ca4819f4eb5eada7386343749bfab848bfc54a8ff9456136328912da25e0537309641296f61f3de94326906977e63f5a60899afc49334a342113a040cd47269bc56a3e14c814f85ce6941886f473f4f3ce4d5aeb30d77171ce189dae99cbc446c8a4cd17099c336aa27df30e314aa9fb5420063e53c26b3c182183f6d86b722c6a298c02b1515c0e9723dbf443a28b2e42e21dd982b63fce1897b3e9b798a19763712c960d3916b64096a49115242a24a4b1306f418261d3c7178049951d3dbb4d7150d3fcdaf5018a39f83223334d1abf245566b76d8aa2f42d699bb22999651c35428dc20c444df443b40f5228a96966d31f1983c603c82362d0b5d08aab1b57374e044209cd855414456d629e65359b7a6fbbcb2ad92dfcd8f4b77def8bf950c4cf8500d4c6e90d0108b08518eb72b95c2e97eb2555e496392abfa8c96327a31f49aa4d698de6d76c168bc16030169695150a8b65d8a6f9b56179b6a987149663a0c71973d4e8e96314df0cd3b62185815487c6a889fe4818f44861a598130f82fe0a66259f3d96b6205b267ddc92e567dad1f759b67f7d9c81dc2209dd02067aa4300aab9c5fd0c459be19a6bd19e0f3709cb1048433d684b6a1cf607cd763a0d824211420c365089190d18c174d8468010ce82e8d0614c16d0eb0b5c6032010011b540213a0004c05dc0217b88181295f8c7edb41188547984088902a0365a00c647310a573db6648356d4855ab8556f66e5cddb6cb5531167354c8d30fa9fc3466a0d90835e221d5484f3f24235b6648858224321a4d0a03e7cb4df4735006f2d3e8b1aca2b01d3f8df945bfd436e3f979f909e7f8a9c274623a310a9bc9f84995577926b3b0d7b966ea2ba7e6ccd86db3ae19d78ccb472816f279061996b026d0ec636bf214d264df27907922512b52cbf4c8cd548d9a6023078f18176d784438532efac43e277efb3053a562d104d1e38a5fceefe5eecbbd79e05c4d550b21e87165db5da3850e60ecc7c026f8e5ee7ab8c8dfcf17ed9c2b60a0835c82b6cbddedaee6ca4a0cfb8205860c6bbb1814357afb303770c896fcf6853c212107204f47acc896efad8aa2ec23214fa1b77fc4ca6a243558a2262a8ea4cd755efebeeffbbeff3c94341c77b0d45a7d03577dee5390e3feefb7edaf08c70eda9db92fc4d1cded94b5eb42f36683dbcea0942ad335022535cd70e451dd41774d01ccdfa6cd04bd1f91c04fddc5c3a14d4819b04461d55a65f52953a94f1a169d35620d856e6ea7d7af61e30445acb826a3d3fa615369b57ee8cb9ef735a7fe84c56aadaa3aaeacd4afb5aae64cadf579f43822a6e2c8a18520bbfe0e1a2f7eeabe7e0d1b30dde5706015c54f734f2dac706094521c180e0c2756aa5904d3bbeae993773097d0a383250a0378cc6dda255bbea6b19366d658ebd6ad6bd73447070888540a02ebee8fee566a03e64677b79b1b47e59f41f0eb7b0c0be9d027c996a945a10f4fd9cc16ebd06456ad1a1b30cc6caf9b323d3a550e1d4c804166d337c27a575c826cb376dbbe40b34b90b95beb32d98e8ba9eb190f58a2a8542a954aa5aa8e927abe4659993b3b2b3b9bbed3e6ceca9ca711655b9121bad0359e9f991a1b999c95cb27483563abdbea7766ab733d543a72eca85eabb9767cd8f8fc0405b171b96a357312a9898e2b75658666d6bc726066326adce8369dcacdd7d6ddd0f8692c6d5dfdd143a523c70e2378d8ea28e244f139a7d7286a6565afccda5603d2242d6b6e85013548a4bf9f0ba96416c225e04cc97d496f49a41791483fbe0ad28357aa905e05585d2495fcecb1498f02850a14289e44228d2620898072a34001ce17312181f34b486f62f21e8944fa923701e5c6380695222492c8c7f0292277268128de04247d09288282cbf762d0e44bf0eba028f0edc3ccd4896cf1e1ede3a0a87ffb189794e42f24d2a390d2c99f944a3e9c94944a253fdf049b987c8a1427a51429dec4a464f231fca464527a1250ee142529c0f924252fbf52c9a700e797a4f812d8a54891e24b4aa0dc29c052a9446262f2a592090909c97fe0dc252520c99b80727fa0fb9ea992ef4ba0f724e0485841b94920f7226048a847ba7538ce166cfb2250dca39ccd90334c3c13134f31059949d273cac8cc48999518352c8cb04a2aad9d3232aa998ac9b99391f151335341b5d63ae3a2cc5cc9e42e77f7888cbdcf39bf7f2e197bb7aeb8687d747d7f8bc49d9e0bb0c4227cbf0bc792c7332c795c73fd5c464eb2a0af0758f6f8b23930bfe42f38beec928fe172c74dd50be7ac8aeeee3c357ecd221695f7538439bcbfd910bf178a8c2e707847c0ba83654e910cf4284a7ab5a6545689a854571d38f41762fe05d894555a0e1911b5ca64321c19ce8e17bce0051f22bc67d7f9a3afc9a5fd687de7953dd76776f0b8767add9cd6eb4e401471e4853fce9f9baa7a99fffa3e03825fdf08d932650f0a0880f796a3fee70e67fd077bb8a9d6fccc181e562d68d27a72764db10d317737a74d905d7fbe528027b31b59ef085a8fd1c80b2c1c1abef7ce79617068b48db99c255dd9531c7fc5142f36821eebaed945931f09c73bb2221c4b2ac2f17d0847f144dca64df28651a728a97f4dc2f18e84a32e5194cd18a4581fc5ec710a90e44bc0d27fa0f7730c2848f5af162995706adce76f46b7a7ee3e86e30e741a17ebdbdcafb78a5c1b6cf2bd7c4578f681661536ff96412e87296658025ea9723f055877b06c29b6edefbd1fc35380a309b637aa3f23efd69e2980fb1e28aa3517efad6f9802b81e28f7a57274c1eae3e21d8d3e8677737b0fbcdf81a31cc21d387d4551e0d75ddf6948be9628eabb6e82739f70db876dab98a0dd2bea7eba412e4fd077f8bd80724f9227c99fc3d27c92097ef6426b47fce58d26d8f94340b9edfc10ebae29001bb2b1df7dce71a809c71e7bd2900cfacbc5ec851fe07648c8cfcf25e44532c4b7fcbef7ed347eea3ad14b14e04837291c7d895d5f041cf50e0147a0065333e4ce1f023fd0249b5cd3f63a0fe470d7bdcbfd0ebcdb03e5beff313c081f9a8045882270e1b8853776e2028043adb6b333f284963200ae982b8649624862566e62748944a202921892148cdc8c3c4172517a5844e282911b4d3720202020a0fad664fa6455ebd3e74613b3b909927ad55be39a39d8ab73067b96da3fb13f6a6c5c41eab66da82f36657367fb0992266b847112ab89412b2f68cb054b8ef11377c40e1d46f0e86103a6c64d0c18325e6870391c9793eb6f5b13403939393a5245eeea62b1582c56176a2c16ab852333c3caf8e32156e87cdfea46450f60a1a6f92cd492f6c8f2b990b0407f437c33ee10b3468c0a4c2ab897fb668052653e2855485650bf1924ef9b3192e2fc9114e58f486cff19da432df23e0868dd79ce53da50fd665ca972e5f4ae17fac0dcc33621c2db1f987ba8f36d281f093b6d6abe26c2717edc3d61dc56371d8e5ba9304d78bdf01327cb7e92cd192dc5337ba60f10cb59abf9e329ecd92d077bd6d660cfd61b3872d429dbf56fe8eb5f55ddf9685f4df7e8af9f650bab562d9a3f8efa823c25e3a113929bead75d4fde456a65868505a356f1850c68d78f41c34f92092fa876fd69e3aad307abf58386d2999a2a6f6584cc67c3d8b881234775fdd4fbb9c882b87e5c3fae1f5790b74252c0b1c1b161830c2660ab94e148024e45dedf0e6d6caf9faa8a8de717f25965e542f3c645fba2ede0741d713f9724688904ed5f0ff97862e9b386ee8f24a7f5a55b692b47392e44ff82a2cdcda4758144bd507900574d01d8692355ec97c4408a2f90220ba46869204df66d8e1f6c6b73b0ad5db1c2c3b154a2e1a875b5339cb53a686bb3e52e14b2934387c85b3b4e1b548ab7f8a5a3481e45024a3f7a11d008176d8ab0879bec8784e34a29946e1a85e36c8923e18b3d4a1e14e15c6d4b124a377da19b70c873431e2edacf01eac02759d0343d2eea25f410f4acd19adbd56ab55aad56d77dd82d34e15aeec3de3b5f36143585b8397418c1e388144db5a347cc2ae36dc391f1666f64bcd58cb70c9ea05ccf7ef7391c651db68364c4c893de7e0f12fb47949ee42dccb27810f749c0171ec4fd1170c583b84f025d7810f7678ca3486f57333e508024fbc35afb76e5950383e9c85cab9c9b6d7fc6766c7697bd41e3a5860d3fe16d4f74c54fdf673b7ba6cfacd5fc098a9ff2db175d7c1973b0cb9970360cab1bc22c01767fe3eee56096005b026c093117790a17dcec00ec8f1d7c80a6a6f99a9ae4cb0f020fb8d434ff52937c17d1eab5d62a7d088d24d8f4e79e0276ba7d89a226cbb2ac8f6d7e2eb654da36d14f25ea02469057ad66ba668ed7cd785da5325e6878ddc67d4f5fd6649bec1205a9538b4239c7515967ee7c995592b5a0172b1fad77d1daf4599aa8e1cda347e83082470f6a03c6515508c94413db0b0dafc309b2e1ccad091b9c2076db2c4e109c2038393e9909188fdcc8c057c07dade148822daffc0e84a1a6ed0c7a9430f6f6f3e5bfdcab75a9f42f8a3062c8a0affaa276af224ddbd70a76e073a88ed32c7bdb6ef8e2e2465134642331cd85fea384a5aa1946ae1a1aada6c655535373e372b95c1308257050948d4961aa8d3969a5384efe6694ed05cb14ad3f0e47e11f4fe68c0e6f47e641b3e74479aa2933a78b6e9a5266639ee6cb8061b3e7c7a0f128f36fcc17575eb0ccad5549dabd0b32ae96535a2b75b55a34d3a69391286348ba571b1b9b4de205ed3134e891c2624ef202ed1ff2a4b77b1496408fb1acc044ea73ce2ee8534c24515f51830f6d25f902894c4bf7112fe8dc611a1b83bde6ebf5a2a1a179d9174ecc2d0d8da521797696b240d8fad899f5f1d9829dd9999d3dc69fcbf67ddff77ddff77df68b51d49cdffc6613f4f8f17cb5afe7fb5a3c9bfee7fa5c9feb6b7dad2fab6c685a5fabd552a954b7d56a612188d3565471aadba9482414d14d7f37d746db6633b6c55c2e17b7c5624ed0e38cfdf8b8aa8bbb2e919e907cb32358d0a2acc34f26ad632337da35890d5e234de80c7391924eee989dd033d0198b887c2edd732452033e30f7b047a0b77ed1a7d01ffaeff1dbef677eeff3fbcd1a24cd28ed6ddc31739182333653e4017c2f974e5044175174ab4d65541254b1f3c69e27f86d4cb10a1a1a9a555dd55575ae3eeefc310db6a1b011bb367dbcd9add2cd372ee43f41d116f7fc66b458f105df1eaf286ac6285e711d5e552aa33e80417b5ecc8bbd288e1c412e8a1e63438ef540081bead881023de21891c638aa07356119d962adca8b5194e779b1910dbf700dd3486678865f2ffcb27846515467f6033dce174551989b2885e197dd429fd933334431dbf743199c2e00e70ba4cafd8d15dbf7b5cdbd5a6b9b949a6c09f7fd141f8af2bf9f723f2588454ab6ccbf8f45be9789223b25c9d5a6c85b09c6397bdf8cfb2c8ea047dcda30ddca3904621a173f5d73ffde1fb5117208b451c3c5fb62121ad3fc90315c2355ee639fd269885b52e5fe6c8154b956b547dcd2e1e2a5e10d308754b95f411c9fcbf44210cc987b4e9554b93f43650761f43a4aa5d14da975373ac5274ce9b9ff9d41fb8f29b57d3f876cf1fefe0d1cd47657aaa0dc90030348753e8029608945413482b40c39cba12123879da51ee83df70e3ff95740a264c0c8162076fd1eb2092d73ceb0ebcf90a89b9a2a189224b730bf22ecc6dd6edb3697e162b53db9cb81f690c60c5f3e3250148a34d5af234a1d514472d0a39c55d2ae2e735a28418f72067303470e23786ca918d516ce907b65e29b06c11692aef5e9f4806b6858c34b43e05e3aa50dd10f819cf70e81ab0de100cfd978b794d20a739460c05ba5a0fcc06fbd69784265334ea460b6250f1ef678378c0e3cb5927f0b463326d4d0843ba5540d4c54353cc1aa01c8a606236cd2467370391f35734ebf570d2a16a5b4fea821c65abbd17c388ebb18ebec745de7e5ec827d19639cbfefc7cdf78542212756be25134eb49c68818b32f40226d2c09386a034fcd0cdbe4cb9bb76ffff79adb4a32bcc91166e76f1daa841e3055aa79cc403ed3490831ea5ceccf64983edef4fa3860d1ac8161b2e4a9dd729e9e898f840878b82b7799cc771dde675c1dbeee083bdbb6dde7d1c1d28eb115bcf814b9178a07127311e7dcbc7937b7b6df56c774b9286afc034cb0a907e0103cf41a3487145bb08b3ed4fec1f03e8e67ea5ebfe5be93eafe0957b635b29c5db1db16d585fb8e8bf72023df3dcd200d24c5124eaba89ae185db8987600b0476ef448fa4680642d5b58f0408fa269676596e1f502e203888f6aad8b5e06d6c637e34e622c6fecdce6d6da5b2403cda908e26e6c365a0352fa63a32d9a8f8f9cdcfcd1993e40e440d3786adde5bcee72dde5683af4242734104a686ed268341f9e1e1f9f5936eb1ea5943ab9abaa767dfaaa2432e8ef43e15867767dd28eff64ecd5cfa59b349e31c86c3a3a3a32fc9743390c76e3d91f58bb52aad6d6ec6a4b4e538d57aad8dff6f639145532d3c6c50a73a9b079430a839e3fa6aabeadb6ce619b7313c955d0dcbd55a56af1053d4e17a29d2a9213ba854c7d6f5114e9abeb255b2efebe1751765a2d69db36d2e8de6ddb7e4e8c84bf462436c6b01890c7788c4fdee6dc99afd70b0663b628aae43e5b3eba813c51cc922db3556b3d19cd9f2eff5ca68b929b64932967e87b11e53975f6394799ce1992eb9c22d9ceb9cd89227373e2bb8dd8418f4e2b9dd43e6ff8665c5b24b08ec0baaa32141908254a37481059abaaa61882445f3f7fe8ab73e6517d8dc4d033fa361f3e7cfc902a7207056d78dbdec55a72b156958a95abcc4ad62dac2b17ebcf946844a1d0470655a6a191d1d0d0d88852dd489e30473d36c975d651e894ca49376aa70422077abafbb4d95a6cede528a579dfb94c4663b2568f8e0305c5667ea23bd67fead3d4e4364c75e6e5368feee8ecfa74aa5674a68a2e13c8cdc42e9b01b991cd9d95057203e406c80d90aaba57eb52e95f54e55d698bb6269d8314b7ed45177ebad869d4244f2ddf6fbf396df91ce489fe408a351492705555408a3f90a71b52ac5f31f594229c56bb71db089cb1ed2f84912af5318bef45ccd394bd45a640e4ea22db4d256fdb1680cc6d5b06e59e33ac32d54755f155951b34f72adc755d288733355552a5fef59c2655e6571545398de6b48d6756d5bd95b55515454d21b61f52275f2c7ac6b0960ef581ddea63ceb889467f1585e4890844113f970fc8ca73687271687259ab39e32e069d15deb60d8401b202b202c2a2831eeb8fe4c9d320c5ea3417ab6cf16e477a1a3c023d0db6d6ee7b994e6b285b91b62b76faec8daa3aaab232d6eeae569f6d275055c9d49991d69aeaa2d547a5a937f575691cdd6276db3c5555392aa47e9df1d1fa993e284822a34ae3a8d1d7af3637358404661595a12b4c5d33ea4375266d519953daae5febb3d4971164d7af51df6935efa90da8db3a8dfe68d1d4d8542a934d9d099bb129dbf6c70728a8a66ee080b9d9f57504a1ae979fba1c3fc1ba0b24c6b33934b1319e2706568cdd360b242646a60514b455f9c9be48489529957e65e3ed7b719c6dce1bf715f131bcdeaa4b5fdaa068639b2d18da78cb16fc36e6b205f3c6bbaafc84777ddc650b7adb8408bcb7e7f6168e24a83112a4b0c422910c3415453925b79a32f4a5e426c7b16a6a282e384a374aefdde6153da53f28a594fb5e747e94d699daf479f4382226c70da04d233f4cc69e9da1cc590cc86cce3981cc80cc80d0be1552a42fba28d150cb3db1dc0f5c71e24f25c5f77b29e20b592e8bbe17b9ad75c1cdaf7f6b0ce76abdb576b57ab5e25a73ad5fada1faf6af54b12f5d9457aa98d8977688ce44ee5a378edb7edb66d00472717a8e42868932c4684c94e10ab276afd6a5d28ba2cf0a8bc45d370a0909bdb56197523acf6c4746f3dc3382a25cc7bfb779a280e2e762a7e71e63428cebcc397b3121c6b97b3926c43021860932adc972717357f6207b72f76a5d2afd8b1cf7d28563d92374d0a3ebdf9ef6c8d37c428a6c90a759cbbf59efb791cfcf278ca0a86d4a91fb0d686f348773c67d2f4570d7862b5c38672e725ed7dd172e6e2b2e8ac0b0b3aed5b2f787edbaae9b05e961446a87f6f23abf409edfee05d6425530c8f6f62e83bc6878f4b0e2e7e2398d2e84c1e979d97e743ddddfaeeb60707a7a36c6db3b15df0e6d3cd2d95b6dfb91bb82b86b34729d1a0deae1b31d6f1d61848cc968b3767d441be233efef7bab36ba4b7a8d1ef6f6d367d660a35c88ed7d66b37768fe12fdf63cb6d06f22f00405145d32c785848061e7e20079dcbd1c0e100e101352335b2d753b2d17e2de41d1c6a47cb7eef19604cd21417fdc6359bd9f317bbbdcb4992e509e78f438c24ffe33531e940303c68b172e5ca0a09c9c6c2f74af794fcbc56ddbb66dfbd1fd66e37b9923d949324d916d49deb8af88db712a807063c7fd71078c8b37a0f0dc73365cdcf0df1c383012dcdf273d418fdc731d889fc3f77a9e87ffc686b1e1e2f631fcc6083ec0ed610f409b07ddf76fea04280348d32665db7b1b3037b8cec68d0e687741d05e38fac6e195281712c76f388a80c51b46177bfb5113b8920c476bfc64c2895da8298b0b4f5ca4f153176e72af688b461b2183dc13afd51c88aa5ae880ae66fc347aabe63dfee38533a407f92946e5fd56eae1d9ddc6711e78b7cd6b5e732d06ad5d3c41194fc2a0eb56731ffaf23c082260b971215cc8763f06bd3d48e0dc242f343fd38e56b1e2edc3cce80d8214ed8f7e3c5e01faf02ac093c7a0c9cf208cdefefca1b5a8645fd4b927a9d697df0c2943a26066b1fbe2449a3e444b22d1b858429a2524d224bddc256f6f499433132ec484e342b8977b2b01358c8e1e72669f34f2a470867784934ae6933ea2dcf7433293e9dbf9763edac7635292c207abf583a685acd5a2a86fe7db69edfb21d96c27e62758ea27c64f63484726b4f2d3188aedfb058554a119bbd19a22c40afd84824429514c09b6856aa19e900f49e8c64fae90cd6bdf0fbd7cb05a3f6846662dbe9d8f36fb765ab460036b369b6dbce5184be83c73f7b4d99e05735eb9785d665ffd313c868c8d1f835995635cbcbef18f39b52ffefc313cabfc84537eca32abea4e6974aba18e27eeb34654d09f8ca3f08d9b3e156e51d3fd5cb1f6b92ff69829563d56b92803e215886740cc02b10f17ef671645793bbeb359fb7e9659f9c99bb1c2be53a26248d37def152051d8c7070bdb66a7724c5621c4c6b3cdd6e873d95a9be4072fb4560bf4d528eabb5fadb6ef67e383d1fb6c8276b0e09a8b17f7b8781fe6a74eb6c88d9242ecec6b79f6b53dfb3e46a1793f3f283534d95050bc0fd1786a197bf8870c84125a8b541415a28954bb7af2059bfdb001c86eb47aa2969f466f67dfcdd2da8da223ecbb595aaf8cfb31fc24997883cfbe5fc34f726f96564b2bf7b9e8d064a36d3c3cb41f3e971fde90b3f12cc1b304cf123d2c7cf48877f6fdd1db89e15aa647cce3b3af85f1eceb01514ce3d9b9a026e540df1530d014c4361ef3ceca9610cff67dacba57975edcb06adff780ae07b4ef7bb5eb1e8f6cd17fdfdbf1682c445ef6eb7d2f609e0e804ceb0fd9a6e48d4587a94fe93dddde88637f19082534fe181415fa71d3fdeb75a1891702c2a19fef23a27ed8c335fc348668fbf2d47288953f077c2ffaecc29fcb270a4d445e4d246addbb733b10051443a1ef63388af4f743b41f1e7e1a43ac17111a227fdfc6c87d18921ff9fb219efb215688b6ef7d92fc23f951e4fc381c25f2f775ecb86f440f474d21ee9340e9a6fc9e08f8c24df7433f7e1a2d2c04e4276edf0f0589607e1a452a1d3f8d9946e6a711e7ccfc347ead3164c3b3f3d9f8f8690cc980fc347e351be4a751d48af1d388552a3f8d5e8db6efdf31bbf6fdfbf9be8dd57edc10dbf7b7941b68fbfe26e3069f7d7f63ddcfb4cc936bb927fb709f03bc1f855ecd4f9b8c6a35c3f2d3e8434222bc1f85262351cb4fb6a7e6f303c400d9f77ddff7bade7f3ba19b904dc8150a127a5defbffb188673b08e9f627e92f937048de8be48e527fdf7452b3fcd8858f7b5e83bd16391270a6196588542a18977ff0b4dbc17f7432137d87839845962e561ec2db15ab144362180c112319588ba444cf6d9dce399fd1e2e7277469284fee6fc76a06f1c34dd320e1ac526d18196cfb5280ac6879ab8cf318a9a60904cc804889efb9c9361b225b6b926a4c8e59ccd89420e065c0d36c7f99866d8dc574ec5c94815ee497ce8ed5d2a4eb5b94ce33df75e73693c469e3214a4c89d721017398ad2cf899ec3b2e53717fa50396eb8c83d8c5b108754e13ed3e6cf9d40a20c051a8a2ae5209ccde6e2a0b72d71e8819a44e686e3f7367c71f165776fc19165ffbe27902dde0a767efc1ec8f50000fb86dcc81df42867996b816007cb9e46f07091a3c1ed19f6705b71ce7af42449e8b1cecf659e7d797ea1cf453eae9524073ad3324faedde8f0d47a7c7c443834c13db8f6f1641d7c8345b8c79f6914754450a66d8edb36f713c86ba97ef8a869d9dcb85c41747262e3e4e154b21d3fcd9e1e8ee6e6c5869a0e6b46b3b9e7dae0dadc7b4ae5322107d80f8526a1afdbee598371329c8a5b71331ccb4fd5251432a0f2f8c862b31daac313c4f5ca6980dfcc7eb468b821a60cabbb73fb5c443e19b4b9140e619688d99c481b54b5397821cc1273ceb9c4124bc84815d9e2312f0279721548917b2ec522886b719e63031dd8213d05872736f73a744e4a28a549e97bff2ea828b64edd08ae06e4013c3505c03df73864cbf4c251a6a1c43d9e370edae338706ec9d1b8e8dc8fd43cc02742c1e66670cfe2087a64c9325ce4b81793d01ccd0f17b91aa9c2591b722da9c2bd733fdcc43dc72d4173d9674b008440b0c4224c92849eb5d68f41eb8d830ed9bf29f8b225082ae2f799d0a3d6b22c5bec538ee3388ee3388ee3388ee3b8ad5a9bcac272fb896fbef9a6e08286b1e1e2f6ffdb977aa06bc81602ec4db674ffedc014c53253a1edb1f7bde0fc85445a6bfd3cdcb43dcbf6dbf6a2d0880cd6b071f2841ef3de7ebb5ff5df7f8aaa7f5f5cf193cabebf7d2ef7ca2acadbd5f77a1d4c68c3c54dc62c6d4b0098602281fd86218bbea0e7db3d561b783e96d8e78c544b2ea4d289961b77d2946a3bbf2268bedf4be77d2ff87bc9dfcbcf9ef942c3c5199a7c604f5b2d9ee970b1befb0e1773b8587f0e39fce45f1fe6467d6cbad1f64d4ad0f667b51bb7815553940c7ffb0d41b769075a873ab4af549932ed5f676806e33963a0c7bc93d063a6d3ce6c39a711f478b75301cb1c5e17498ea0c7baabad2673d35d438bc44662630b82a082a08ebe4dec23b1ad49098dc4ceb752a7db10bf373cb7690a7ab4ab6d575245bec6241c9d84962113348e2e9182e0c480840628da503149129a6500a97da7d33943e74cf5b9922a77dc7c8c9b8f8d2555eee752496aa0bbc712d3cd2bada1a9922a5288d156197da5c38f2976d8f74565d0f9edc65f8f1e5350cc5cbc286828765c4ca9cd03f80964cb8a1f3fcd10aedf8b97371c7a1da3a851185384795f8741cf644bfdfb52b668238c615fc71406f200ba660ae04e1632b2a51a2106fb7a9ee7799ee7799e57e7a9fb5e749e5f11a3ec2199da8dc38fbf8f04069a3efed08b421abaf7be0cf4a86d48623031090db4fc61df4f09a128aba2a88d058bc50d482449e851eecc408f28662839a0c9fc9027fd0834996110b61fbd7d4c0245528470500a814964a0290b4cb305457e03eda3ec943b90c0941635dd2d4c5151d37d0ba6ac44c0149616f4f8032da546dba84b4df7537e64cb7cfb4d60fb90b7df04ec8fc21030c5879aee8ada5707ed3fa46afbfe9072f1ea2d52d3234a6cdf4789a1cc644b18640bfefb2834d7be1fd33efba200ed27b47f4a2d4588fb294014a56dee6adfc760c91a348b1545392a250ad204807d5f86230b5589c509f41db68c421cf6fd149844a5d4a8e9fe8da166fbce941a6ddf2759e951db881e4a8ea3e88c90e4494b94a6a0b48452134a4f28f56182a689577c2f4eeb57044ab63fe48dd32391c8470203fd3d7d5198034507250b2839303f7d285bd8f3a6f8a4f4fc26b9a85dbcf76f4aad04444daa5c30c527e58786293d9a0cda0c2932490c4a3249121a041553af34a5864992d0638a8afae03a5602844cd79d3daea8f9d8f7537a9ad817b358b19871d4e8efa7b0419e506252acc99601ecfb2c621cf5438a9aeedf1f54fbfec84266dfc723fdb800dfcb8b3c83c87eca94255b03e42de74c0b30e78b398398f334276a4e96390d3067cb9cd8a31f090cb4e8bfd72bde8bef25883c4fd95199b2e46a806c5bf276005abdf006f6112885f8214551292a37dd14d5be3fa4f6ad4f22a371b878ff86373ffa2932900758519b29aa149994956c99630a0df67d2c025db828ba78ef7f3f574a682b4a6a2e7a09cf8ada8a36ec0bc3c5fb94a5a484c7c5fb132ce9094b6852e53e6ddf97286652e57ea977a8046d376639ebd40c000000007315002028100c068462f1701a6782dedb0314800e85b25a5a441709a324c76118c68c32c82042660000000046468206001471589726ea9ddac67b5fb72fdcb47f35aac75cd0dc410606982aa139c81f9a76dca1d9712cee78cbf541ea9d3595e98e26ea52e4646a4163857ce3a2c489abd6e6a6d2b8863c344be12735fadedf50f67d47a1e9ebaa4199c2ab11f1138b5468a818edad8a0ddaf9758dd0282351f09fa9dcc3711319083ba8f03a01bc913cdd4d2d381d3b8eee3aa3913f19800fe506fab03d13933f78054e3ef24ed527d1940f99306fe3688de838ce99543adc5f493511caf86cc9597ebfacf2fc3cbdc83c3575358507d52a66b8bfa6814da0e163bbd01bb2ffe89f86a28a45ee8b689f15e728474a836bba2341623c35f543dc1e0420c8a818ec4ca9a2c81402d603fd3372833d7b30f209bebcd957e6dbb4453c1380dcb22b3e41505379f31573543ac30bececfd28c6a568595474927acb897f264342665d01c0d6fa70d1244971014028c5a8e76756ca40a08dc4b7ce09d0255bfb3fd06c054901bc01771f43685ea542e6c47ad8fe852ecd9cf071a6e059c93edfd00b2a29d51bd1dcda67c0f9bf3907f98e878105e0068655e0df0b877daf6a7597008ff2fa382876d84cbbe854173d19c0f2fb116a139910615eab7eae3cf76d42ff1021a77fed157142c3631959c6e2ac53ecdb1f6082f944000a71e35005748f62ab61b2394c71bf1161593d941e833bd077ef59161591a29c1076098e0c9095ce276a3a4996c5c6971b476f65a6b3d4162807a6e446f8b7992de37afc8a672ba7bfd7f704f21b7100c0f97fecda27ce8dda698384caf5b89432e9fb405f580df863ea9e74fcf191f733e0f01025a8eaae2f57466565b2522f3aa2b28fa02c0fb5cd3b7d62be90d6936c57da49bf3e54be28003c2c994362afb4283c4b2c25996c3bf4a1114b28edaec49bc2328d01e399e8b3d5f06f77ee6d4431fc87cef5d9086d91147d3e8d4ca56c4645a0ee42904152ca7e42a2825b9612008bcd6f89dcdc8d91c5fdadb68502289166416c8cbf7288221a287e391fcbb7f79e67e696153bd6f7515313f1c2b8e58067c20c8391ad7924ecab0f8685da069c97130d31cdcec5339eea775b03f557490a775fae5c3f9561c6f019dbf7ffba1a763c6046cb0e4585d7c6f23b557c5e61c5f77418798ebf592ff05e0ecd74aa588f63e55738bdb059bfa17dd619976fc85de74eee6a1618dbfdc8f6cdc6503872d3e8ee802c8dcb2312b70df3959e8acd11ab0216bc58d40a689f732f4b9adf0a6d320365dbd586b22f09a431afc0b96fc0f3be7b661a1383a47873ff7ced08cb4d8c63e47496d053f1c38c9d949866db305e0d315a99d41cb7d436d050e858ac5e01b43b0c77669de8b92966eab4a74756288708021130cba39d393c11fa196ad809f9e6f3981069998ef8dbf0cecc07b9ee6597cb4bdd4baa08fa304f46b6ccff2e77b958252ed1cc4f2ee5836c856c52525f8c3c2f5931455a51f82d9d33b2fcb063dcb4720a8d1c0a345842d934950ae4061c021e4529396e416fe5cf365a85bbec206cc5cba3410fde36113143f8b3bf7183739d7038d18103449f7e3647c97e711efe0e27b17d56de7aeeacca56f2cb4662300d72cb0cda5a02bbc0b08a4ada3ee8b1de2e100625038d2c4ffd6d232dae3212082234812ea0bef7d2a30f6e246558f95368f6b8e4ecee146db2990793eaf4dd8429cbe0203da6960a1361db173dd119bfc1b11cc3a2313c8b8127cac5632bd7707c3160ca0857bd4ebc268b8426c600fe0df4ef6b29e01dd544aa7a630856eaebfdd22cbcdd70169b946793c0346257e82a9bfabac41600586d4f729d47bef2db8d0cc5458e25d53b0ebc518b8efc610cf9df64bf581ce20641b5f20ca6fdf552b8854ff83f46c88f181b5dad33b85ee76a6688c2da608f007520671c3342022beee68b70207ab2636f624291fca3b5bd87b1c0aa11029e3c1880e890fadc9f0414832a2d3cab8c83f5aeb5faf6ba0983fe69db1dfdaa29930d5bf4e1b75c3d00fcdf9af644569f02ed471e6ca47a8e537489eca1c92d8c2375ab1e958b6e50b2527ad38f82591d06c64a7351792da4a91a7abd4eada29c8acfc86aa3b233d4368aaeb994efd0f4effa6ec8b0126426c19c1aed80ee18dac36c7138dd8c2255f5b5a0c4dfbf0f5ac6a7416438cf3a9bd4b35828169f46efb7eb2db59f034a55de23e442f0e6cee395f83d6afed13fa618271c39eda408d7602269e8548fc10f04a2b0c876fa87b156ec5881536670be37003c39c0012fd55c04bee3ba1e02d7a889cd894f7fb5d07208ba4587a562110a5a9e1527df212f193a0e6d73ead87319174ca2ff7833652ab19715982440efafd6d3a0fe8cc6ad9d41f94d743733f960de32d18ac5d426f634eadaef7df7c1855f75dba452f9167c638bf1c835f88a62a1906e3734e76d3a36543230508961e5d5626ae223fc905790fa021aebb24451a9c76eca1dfdb899a17134b6be0658dc22251e2622512b3e4c547aa8dd911fe8429ce7ea2c2dd6615a5846b24cada2a1a24b8d720f61ad9514db349ee91833016d5ae9154751ba76ba1605a9068c46b48f986474a81ad00c183656ec0d1286d6d3db16123b248e0d9dcc642273196a513a7e1be7a7f7c5a301bb414b853dbab6c3d67668d1162a650480cd7b2c1e69ed401a7e832c8798e27597d23701df4f2bc96eddee49d15c7f6a1821668897e055259709f11981a1d895d7cb6e749dedf4b8d7fc24d362f773706c2f07903518d5032e16424f69d168e6e51bdbf11d4f1539c814b25f1ed52c3adc2cc5f7bf0253391226702d16b551004f38d7fc75e525d0b4c2a01d90a7fcf100a9fce941e2248e2a8e8f3e7b63f41676cc363de67aecd50b64307039f87d7b656762141bde97007d98598121a9a71893fdd26e6f3cda21cd808698fa4b8f136a5847a4326238c44209bc0035bc2ef433d43d0ece4002956741fb3f405b7a10cedc9e878ee1e0c0415d3ed1552571d4e87e02469588f2c3e24505469885e400f3ef35d838c54efcb0e8d40e195bf5f680bf6b2653a74862c78fae1a14c33ae6add816b620323cb67bb0cc22b57a34b0abb6de44f58d7724e8a9b9441531750f348c17589f5e1dbc66a9a86845362fa7ac2e0fa247c07f7ee58910c8f121695c31d5c4e62f1d88764b84cd9bc3686e63e3c056f2f26a5ee3c4605de7817c30651d1bbe1a966de0753035769000b261121edf060dce5620c51cb24b28791aae2d04d9a4ddd7c70dd6c3d97b9382fb1d3a24904e5441377b5117a804228ff535dbc213b0ca1d553cd4dd0e6b28ed808d16237f443ce6e018f4a5e05898538f1a882c99f058413320d230dcc27dea60ce9408ff26a76901e07f5385c86ff93919e844334e8b1c7be96a94c0b5343326fd15c8bdc5cf047028c189715c1005ca172b0e46342b545deb040312c242e99dfd7f0ce76c24bcef0ab4439798d1d65763974258c5ef260a0b3e1b8e0d9e2d8e5d142c313de7682aa489a14ca593c884bdc1776e8012ebbc12b16f8a49852dd6ff85b00c02cf148ab0260ddf4ed60c38b4ee53820de0c2342efd7f6d1aaea5c94af3a9454282a0cc3c2d4954bae51a44d9f061b0cc00569317fec88f8bda61850b11f8da078410c241974cd83f280cd8fe4c1a22d97166938f869521d6b554863815ae0c0532a532a4d698cad075c620a690d1e5aaf58cc3da17d8919c288d9772c379db46755212416834424f7d3f3697b5c02963658c102fc518613d5756c6735da7577dac4604703aad460fc6b5e4641575451c5a9de526377688fc23886e4b44e238286a0edfa40266f5f794c5d111aa2c50e97c60a19f0cfd6e037bb6339f2a3a9bacb7a0be9fb6ac3971c8fde57eec50034922812cdee8ba4adf3ae4cb69a20c09e8ac140db3dcab814192e8f92152e452234b7a389e8ab6ae8634b1d9fa269625460a5d890b20a14f8d3304729897824001c9d19aa12c92c184935fe408973b6040a9b12d1e0a1d61a5bcffae7491718cc5311d5071787f608bdfd96cfa68c1a58756c1fe63d68a0b59ad9ed3f5b36b4a7e5599e5c2f0ec43804fec3a44ff9192fc83bfaf0dd70481dd1738ea4d56ef33ce326a2fc74c7b0765672c431b2f1c8dcc0575acf7083fd5a496caa541a97921b7df535991350937c3223ef050569064f9037023c26bed9d45b2ebc3622696049b589fe3eea232ea8f76cbab2fa2e7d474b729c52b5af3c309d57ebbaa52eb71534f86b630a14adc5b39f32aefe356823a14f510a44ad403ed72040533fd1314ea223e8d025ac58ff82a6601d39513ce8756a7b26677d8ada52772179a144cf9a6869c3c119f1659ca114b12833e8595df5795d154db4863b934ce08e121383c779b7c946a9039ce89ffb297cb4a3bcc05275cf7a1cafac9f7df3997506bc3996cef296a034b82ee23561c5957695c4813e07c3019574053c88908a175584d6b3320a776c736e32e24cb8985eac8880ee1adf6088a66bcf8a0408c6a304b45046ec8e630571ac4ac0d2758fcd64871a1ef75f32badf0f018a3ac1a50970f2fe9226a75d67966176d8c883ac8967c9dd475a167e20c112262c118a39c5649e291a2484a17ac7087e082a8b821eb4c304f9490f68722bf1c82e513e8761c1d8a70c5673391fa44f6a82446548daa69e58134ee05078c3b5db1cf131bafb73eec6ac05197d674e2b5ec24e892b1c97889039925279526e6d0134ae9b2c3e9491c46fcc7e2556e58ac1cc10fbcdd427852b36285ffe69dc8d27b65f838a522407fea83c4091a52690ef49b270a410f7320bafc438773e5aa7b7dba38936ee3cf4ccc0b7d310339f00ce7cb4e2fd41b3f5f86b986290c544200943ed6dff5d23e9688655f133a79fb3fe98562fb0c4632a97d07f0b6018e0bc4bbfb13808a9c8727018c93a8eff2624d24a28193e7a20b50018f811d4d8a891bb0eb52fb78d1df0bc02b65cd88d42a8a3fd1a3255b8c630471ffb4cf2c84bfece734e5edd92f0a59f1daa93d06311d43b1fda14c8c3eaff84e05031a9f178a3591a7570468239ea9b927a9f99e6d97414b1236c25041e94805593701e534b704867473e39f1b0b63e157a3c4b257d737bbb776de75fa57aab33e64f4b44415247d9f3323ea62a9f6d470e371ff8e0f834ac14dc037f26b0cf3b47a8d95909bb21f3fc61eba14e6fce006189a808e9ec5f5bfa1f72a85667254aa10352c06a47434c51b78684eb3b5a6fffb2311718a99a5b47444a794c2e2373106398de9bf33fafaef02f3fefb4863720f2f7cab33fdda8fee40b4121fe02921aa9d88254ef02539f53992cf26979e0ad3c0a0a1b78ac90813e00306f8db58196dcffdaee7c9f609f12949dcb4ae2daecc01d914d6584b227b64ee5432b3971229c7249a1ca2442e08d22a1707884a3b002870b6a4e4183779b1697733517e6f2c1cd146031ee707c7be05dc85f4e03644f46606a01082bfb68bdfb83641fda547152f2cc1a82272d32052ef5d714491dd145909d919f7a32bb9f18182afc909dc5485606320419dd6265741d241e6c03e95461ea01d11382829007a865da7fca1d8f7db59687e51a0e4e1b10e12e361cab4a541a92126748a6e09ae44c11a9ac1f0af4bb1c4c532d73d1e32706e2f502423f94cb521e69930c79bef67c70a53cf7b06705a9490600276b64daee04821c0c72a916212a3c3f10ac3b0659426712a728c890b5aa1e8ee4078142a4604ef863af6de0f23bb40062ccdd22b28b8b0cd3c02fd612f01e4a34483d303632f0ccbbcafb286849c0fe7270462e0ed2cc9032a6179c9f1ef9bb6a70f2eb63d6d576f7ba8196700b93de430cd4a5bb9e0636ca202bcd8e6132d6a434448f23008207cea5a0c4ad60b1f054ce17888483e753083f5621331716df849197f231b4be8929856264ca2c00e42e13e9a0677f8f1a2302957ee83d6c5eeefe12a0b27bfa6c25f436ed8958924cdea82806bb483d4140292ba91a0e7a43a42365e629ac0837162c565ccc59f1e35d0459464e9ba41c626b91879d06bc4d8cd0f015cfc85e39e2fbca5b4a941d2b33489cca5146458e5017bec583bfcec957737e2b35346f1d839432c70282d00d25d314afb73da87d65f5cfda1f417273d1994e34b781d41cccd5668cdbc3fe18766cfd1d0fef4313454090e61beb0d757334bbbb4385dd3304be753bdea31a0279847a093341157dcfe04f51f92b2658081f914d4e9cc77fda4854f2ab1fb6d130f57fdaf0305480c58e6ef56f1a878ead24596f164efeef5ea29ac103ba7f0cd4949c1a4d330834244b5adb68c609fe16a4415970281c4d05179bb8a184a5962ec4ff1f45ccf54ee35e64b5b546ce0fd11e1dd7d172189a67db89456104a5aa4486cc5163f53a23f0f0478fd6225ff29a082e24e7b6bf73ba610a643211a67edb1907c3e12a08efdd2a34578c70c61a7f9604ed872737bb8c0cc304b5e84edf2ccf9cddb0ced78939cd00a85ee17217898ea86f16cf8158147f9754254fbf67cbdb4042da3a0ad2c15a4a6ab33cc4f9beeb765941135ef83e6f4e056f7b76761631eb4b6cf2824875a6bb73fb7e9252c2bc3a6f637aabf1014db4d56e1047690adc9626ae9ec8e052da45220bd84515f6b22a2e95dbce283a354da0818857d238551bf86a30e77cdcce9e60b7dfb77542032c166639cf2d7be83f067e1c14b0e9b84d7ca7fc6ba3665327203b8035320475331fa7722523bb957629325ef23f1a7e904b43dd452f95e1edb567ca41028666eb5530b792525b6a8bf3a8736c4266b65f1c9ea5da44bdf33865e9188244cb1dcfa32bbb4c6f792e97c86982af29bf4b0887b16c9a3643829894143fb6765e2a3e178b6c5976a5184643fe011c2cb6bfb8919e04603b4b1bf6b14d60f55a01cb82d52de9311e46a310ce4622106c5711f14d44ee44ea0760cd104b5bbbb2750bb17cb41edf8e0f7f9930e4b337b0d3526d87d8b38f14fe3170ee8e6fa235094f638c1fcafd35081a3c4bcab59bd32ef17145231c6ee70282ccf115a927b3396b9a9bb797960e6b8d90eec91b9eedb27bab180f54c2cb56d0ff41dec6acd512eb405033ec6097242e643e110c8bb427095bf1fd46e9cb6918a4e52d8e212ce8ebb1e39a06a0cf0c77080602161f2524f90e91f4701a36558389bb62f1b9816bbc1e58ef5557979c60e88abd2de578e8c90120f2139bd484ec888a07139217679028ff7e21e39637410d106a1e7711067f196e2d7fa42f59bda9334598a8fd988406c5644152ac710ee79ec36d3ce376704d69390b3ceae72d500663794f3d7a28e20b33abffc0ee65ef7c62cf3e74e06030110ec980d2d854d2f0fb5e90eca8758293be9c84624dd66e0ef7079f81985f2772f01725d4d324ff6046812260ab2af4059aea92772cb83ef8eca8b3e66685ca8daed37dcb1e33a7f4838e5b99a2dbe95ca19ca7d282449546cc86c4432653b6eb4a3f802ded12262dacd40a7875ee4a16f366c2c6c320d5e6239b3c4fad07d75d6f37796bb6e757c258e77d51b208791aa10f085cff332424e1cd9ad502efc17fe75742903fabdacb3ce2e025858ec16cc97bd9e4b0ff313afe32fb85058abcba7f83edbf84d8f506aa6dab1d0eb344cd07f858e5be6c258212586dd861b854e7bc8a43d992636fedfeca20fe8f9bd98446cff35fafc79ffa46c03a84483dbfb3fe8ffd717c21c2a71e0f6ff0bfa5b961d7a62a45bff1f8eb64b9b97130d367409b25bc1ad80255bb24c6bace0072b57600ccca97e0eecf8effe6e6971ef86852a5f6093ce9cc415186cc1df66950e23ad5149c81b9e975c40fa10b3209409f5ab1530ca7b3181d175f063cb3b9b3fb60bbe66815bbb4ca3b1a30018616a59639686f25b1f4d18160b24e30cc59e2d9d0aa84650f443aea7b8daef0d8d775885f02f684371f2e23a4929543061f7fbec3b330cc3c47a5ded18dffac06163942397a98e6bfd75f23874cee8c7816b969e73ba5fe24ad20d49e962f17e7c9c8dd7ca116e8ad92ca7518b5fd805208d469ca4e00a4cf3598a13282da56704ba873cba45fdafcb9ab7a6785b1bae381de7eb992b2fc3fd75e7ced3449d6d6e9a2bd1347db31e734029a7d06e40214d5666f69742bf11d0d446dd854854f30543f43ed04bdc270709e9c33c1ddc554fd0719c4f270affc821337080b9bcef5ba387deaa21a990a369ac8fa94dbb473aa2e706508a994e2350d619d7a695947a8d24bd6eb452d6f65fddec4821887db4fc490e23f2443154c0c9f9ad482de2712d68caa8071a9e49eb3f5f121c986be540549495207b41716ce517730ef7ebbd6f189b8a39895a9a80e8919e71facfce0868e3e564d9d31c0c71575379a4c7563d58fcd8e5fc4ac6ae432765a5ab286c0a218b1a4017161a3fd4ecf7cb45c10c83e2a7c17625f3501f0d12e50982fb2f29c440b9f5b63eaf3cfc092982af4e48d522edb16804eaadd56acc997238468b9b04ca050f9a02699ad484fee68470d611e08ea393da4fc5ac1be9a99ec6b9e1144b01b2a50b13a41434b31511b13647a569dd30c1888b65a1a19fb1ac29237ef89d6b5cac7387dc6c88b975489f87c24cc5ccecef7b2884f37f829add33f0ca788d6b434eabd8e9ec2af58a8e44f1b74d7b00c4edb496ea1fbbadba1f9f5b00991ba511763bd9c405528ca27f67b738de5098ccc73b6bf237ab5238381744b0ab2c1fd58b3f8d12803134fa33ee7d39136630b1743218597877420b0d6c0d8550eb101ded227d33a098c13e66d57b9a4c61600f97ea2d6b28ac3a3861fd1cff60547b92f649bcf0f54f90b3074480120ac46110c5b6ee50edc0be59459ff75c00ce67afcee0648c8b5c29dc9c6917066008c9075a4155b93a39e2407abee77c0054282d6bf40812ab76a0fe44fa2318ba9b06c4c8dbd758ab35492b9b3a17ff3f7cafb6a6ef06fd80133a82cf34a46dfe71e19b1810c62b0a698fd10fb775a230e0a9a89c2048c844864bae0663826c1878639896abcc6b430d3856fa136004abc37cf588db0f997b769e0af49e11ebccffc0f6f456875d4c67ae168016bb5ef7732f272ab303d2235d9e01da84b2f7a70e76a43165a41a11cc58e6842fe7f6bfcecbf1f40f6cb8edc1907001e3199cd33006d301ca116c376751c05ae6b424bda5c04e1de85612a3459724a8f9bc903620bae29c864ee352315bcfc32970de887f4d9cdeef6234c8d1775fe4db191ac8854e574e3336a457246a39d4195df40ec86f839183f661e17d464a179972184d8f567a871f62dff44d04a7761aa5c4556683dc956c8f648cb7226b97576c27123c06104a0c686acca5e21def32c3827b164ba172af9957624b2c5c157cfec5377c155cbe4e16580cee87ada5b1732d9255c5005a8b2e998b1f9a84095979b5d2c2e724cfb35afed2d41108de9c1d8c75f8b1b7f6413f437788a495c71034cb5d84935b8b28055777e96d83c76db9b6585c1a19bb96640ae0464b65d60a3a9ca430ee5bf8f8d76e695ee63c2111674535a28ffa670d9359d831afa7e18bdb746c3a8b74498f8a8a1bfc59f4da9ea7c4e332136adc8228cbb73e8fbbb9b4a06310c67ed00f26a7195a3ec9dc6f8d512ee37c2ca920ff4fc5fb3540438e5d35677648ca8bd286947f2cc4133970851c726f8dd90c767970002c6075a96cad5374217c6d0d5fb4c85bb726d99b60667591661ef4d2ae9537aac5ed8770fb5abb137925be425f8b0d8514002e30c4f8a04fe0d2d5e3a606c9e1e0b819e6261e4e932a8e100594c8ff4a9686c6654529de58cede78a3d726e40d726c4cedfbfebc580a2e0bfdda5ecec253747980ff10e5dbc7c30013ec46beacd5cb9dce5b822efc25751364c8cec46ea4765d966bab0020b6fb3a93b70e0b870748da09fb97c459c02be90c473bd9b681ceb9aad9e97e71a2e15b6ecd3870bf129a2f4135a893c266dd3de9c655a4710e8cb938b839f2e8b976d6a4afcaffc4ae177f5c4bcb918b2ae0e286d40332ee9bd6bfc8915c5553f8018a1afa472e22fdcfc6d7f1e6452e01c01942ba13e10902202b1a82cc1baa98fd7d9710253daf683213f903129fa06aadff7adbd2aaf912a895919b301e86517d0f6f44cfb5a1ee003edf1b0afd8b9edd89d767d5caa006fea1682f96d46e683dcdfbdb5a0b93e13bb45e00968c5c5edec76a040135146e9b9768f68e551cf46ff3bd4c27b8299b132f79dc4c438b60af9a4c717c1f51cec7af1774c4c820f870fb66725848ad3d1c69fd77c7b09ada06154f14d263c6712e63162fdbb52f6eed7a6c70d03b496d29908f788bffe6f867c664e61467d6a44745881a441a231bd6230a42fce6334c0a6872a7123bc5381b70004a7434cbcdb91537391dc3ae84df8e186f67cc21f1b358287a16d92ec2a08b08770d953097b9c332bb6f2321057379f3e356e5671f21ec6ed7d562ad5f0d5d44211c23431ddae6ccfb14f8c82abfcbb0b8c384f2a15f583468d7250326c7f55e19ba66252654a326f6d825483e75552ff0b64d802ec194f1da18c2bb7315c1b696f8fd512af11abf969040052528923e9cc63a328d09de4774b9f28ac983a316bb9c72381edd6a376500eef20e1d559d3da7d162ce70e32c5cf475369f7a97efededb9764eec1eedffca60e24219d9430fe15b1e7797992cafd8cd0d0449eb5d1a779d28142d65511d337c0216e12a354871043f043f6e75023d8f0897c3c07d42e6de7aa74f1b755755615d77a6da173228d69ad09f8a9a4320943d112cde05fe0b0e190038a28c34e2e931abcb3d1505d7a986827e709843ce168c653e9dd2667de9b533e73c9022461da727e542763e3b2263c6e5d7535419d5253a3029e3f9404c24599e3e818e10889d0f399b2c4c303aa584418574cadec7cec0297880d0fc88a9cb65ddd6e8007f65c5f264d1244365f19f6842c6384a2d55a842e0eec50d704270d43d48fa867c8e7669e5bd4bc2482e45e3eedc179c83264e242e9c6e7be8395d0470f29e0ba4da86a6c68afdc951b0bc1ecd46e0e28237d4d28865ead0c4160e72b524772a69cb55c465336c2f01c956a192ef35621be940e00324e7d7a0d87b990b3c43940c71d9ac97d8d48285efb4aebf6176af9aa6cb3aced18148ecda6b655c1398024cc5403c220b4dd55d55ea4f625941c44a88dcb18c63588cd4dda4f85afee603e80623f4a3b099ec2019eeff18bf15eb5691222eecc2dc0af7ff1a77627418a3a02518106a1b23a0d76c87866ebdafc761896b3eee0fb80382d1724a8136772553bd80c35c0a55cb1a22b405cc46be845da34eb7742e4d72b3c4f270a7312d7839e5cdeef1a413dbd98cd4a49de9acc15db363fcbba2cbf002834ba17ed0262389b677ad24f420cf4a3bce49606f86eafab673f5091be09efe6c99d6010d419b5e0eca4dc058d9345cd5f2310ada5316e00503dea3cc047820c65f2959d7a4f07c0062a71a6a964d70784c950c59b864eced104da685be171c096a789ec8c44b1777889140ae53895d06dab295577dcb2a7e0c931712c61ad7da9f1f213cfb974b3c092e7bd24a8fe8fa901edfb57b432a47b0d344f419a9984cf6c0f7e48fdae2c5c9b984e17e05073fcef8b0788524bb7ccf9238a4ce03ccfadf7cf50bb231040536b8c18ae133385bb1f1f0db4dbba4fc5ff52f83a89669870f7740b9c5d6252d44902d93be02cd62cf8e0e928a116d550a3a37126074f586af2058c8ac47b883922499ff9f0f7a532e457f2adc4ed3bd1c93a8de02b3c7275843e6aa1cf327c04e0c97b7dcef994814904797896883ac1244385a8ea3726e9e5c44400829b82dcab078073f945f48de8edf0d2594fd41c94b66a1649466503222d414671efd16df08dfe2e6bbbbbcee2c3c0b6cbee65edcbe059d1d06fbfbf8b158330cc0dbe160b9af1368f8ede470c8d849fdeb282a243c207a43a45e5465c69523af3d1bb840b078d3ec8007a56104d926040d24613e5929470a653a89123236e022c985dcc80540bcdecfa8e85b9182610add30d8a0068b71d1828194163694b936dc75deb63c626d257fbdfbb883f2af3b0c8079ba08b78a22fe8406187f8f4f884b74f8b5de3eeba0effff239c4d0b51d6659bf500874eddf67b1175f1421a30e6cf6a5474af91e51c7cb8383ebdaf0c13516e4ac673150e23ce417144c505310041663c32e25dc33494f0434c5a656fd4e8fa601b8944ce371996d0738c040145df5dbc134a0793b6fc4411bc94332b9cc9d1067351b10f96b569fae77772f27d0099428aff0db6811ad48b39f3f3a9bf0aac6f85f49a0f93dc14371dc500e002869279a21bab036e0e9bedf92eaa68f457b880d2584467db075ca04cacf13fbf4893fc6b9fd2c16e87fbece2000c1d47a2a70a106fb53e5172a945ac8d1a065c695aba069150a5f8d6c5b23f9f94637414619048ff6b55b358dcdcca20ddc62c7ab75f405f941c93a94a715138d04bef8772dc8f30e839a5a6d97d8c74fcb483a11e7a5f138e4b4c0af0f7bcdacc41a9f8a8f1051b3c4405095e2f9b8947ee073d25c171555c5f29acdf5af041e83421049f722603904e5c87c73a7aa22729aa2f8c42428a5d7fc47272fd82844dd9287460bb14af7c353b06f4ece7ac23c5eaf682e77dafa6c005b6f88bfb31fe534e1eb5ef3b7b5a9608f4912117539782e58bfac64f37557bee56ad3a98c828b841f7cc2a68e087c0711eaa24174f62f74126b076a33921550bfb8150b3586c5a111583154618a4afa778477fa409051f7798e310243dfc87f514522feb8fad713bfa201d5e8ee841b0025751f8e6c2f1cccb26806ed8f68f2a62d2c1a1fc6a858f28fd09cb7d1a43ecc4348998eacad704df9443bf1bbe4bbc6c7e3e25f137253dc3ead317e3a657010bb778d504227411abca59b4dfb2f426e18b5fc1c7d05a830fead2b7c9d768d44f6b60460a89c7010085474808234565986e7d305f05d9e1e9ce9fdb27b392c6c712ae38b1991aa71517c5ed29958ac1d28db356270483280bd0e7776e1c5471fa4ef6ded1aa74dc395453d6fd750028214326bd70893c30bccd251962b4b554d459b6eb66b54c5687cc2d7cb812be6b65d03be962a1e654578c34aa00c9230e43392ffca3ecccc7ddf7d6e3032c6e3b0898cd7470cfaad7ee0cbbf730a508cc9dad314ce18b633adc8cfa86905578dacd875a1d7f5e1d48c5a2ab231e2694579500e2a7f165435613f6bb4a13ebd9058907998230552a3d505887e2552a30b75810c678fe3a6e1c4de01905b51ecc7a73edfe2ff313ab56f4f143ac644cdf1430f545ddf412e61845ad6d5552a11e0364342cccdc27ddcb60a43dba05b2fa1e2d0f063147608a6b2075604961b5051f919264621c7abe97dec30d2ca9c1de20c1b9c0be2d47e08aa78d3f0be06faafb7cff6b48370ecc52295700573655d6f24749906acb971cf6d06fb5831bbc9766d8e33e62e83ff4fdbdcd667d4f8663fd1136ba01537f6a5e6fa44b291f7d78a5635f27cfc9eefd1ca1c7600c3c5ae3b5bc6568206d1b124cc0d07431484c1bdca5337e4a7f088d447d1758b690ca27b139a38fce32df8104d86ec6650764773d500a26611f58e3f6343779625d3268b995e82dc09dd070962cb54a1b7da1fba2922e8df2f9f0f9f90b92642584fec3a49ecf14223eb03782d43d0943bee88ac8bce6f33317b202cc679f0287d198be0980c93778fe304d6ae9b2a524e5299f862a557e843ddc64274755d0cf8d5c004c2d68ac6c3f9561050be54d1d62f5ef45ce8c261f28d3ff9e347814ce6df7c6e9f35390e6516b4301bf5b24dbae16d3427f8d984bed3e1267dca9508e61d1c531f050aa7f60c0fcbe09cbb1f9f54fcb492669fc83ae6042b1ae9952f33c4d420ab36126863b557289a3776cf18d51d2fda0cdc112345eebc0b2e1c28fefb1d1de2f8af7c66ac2b2f38122158462b172bb6af79473d2a9e80d243373e54e6985c22904a0386d75cfa42d29cba8f7fa9f741ac6a6b6d3d1949ad003b7689bd0e23d2578673756809d6fd8042af315045cd5271491ee739ffa364fd54786442080ecee765eec679a65bc84b5fbec721574619c33374596f03a081d87812f777f04d73913acc976642008359f5f0eac062d98bf52328fade9303020a6813040c67c9da0d387125200e96416a0b56a12fff2202459b4f0e38bd19457f67a2c1733c05f161def03293aa2f58ba1fc9f13c588caa944099ec47f9aca02eac1d1aa3602d0472d07af0c7ad71c90895b8b8944faa7408301c5879515297db364b98d172119e2444ae4e868a398fc67a40c31861045008d37c85b2d800e23918b9341ffe3b162af69cdf79ef5c1078dc375ee63cda4024bf80ec91758fbc9e8cb5ae4671a93b1f88503265ceffe18446924c0417a8938a7eff0141caf7a543793def68d897e0e7c2ed82fd814a4b2ceb0aaac8e8206dbcac654e1d2b7cf9b4f0757ed0333d7584a9413ef4268bb3987396fbbb8bde57cf298a9554ceb7365e7e98d1115bada0bae08f2b9016fa575734e1c6ed8d624b3e350757027009afa558357e6062daeac4865587c5d017c0df0221066d122053ccc27deed7c091fea0327a2e6f194c04b2e8a1fe3fbb272257e51e34e5fef0121ac6cad4d47fd94122d061875e3d359a8bf2356cce99fe707558ed3a7b47b086626d42f5361faa1d800eed9438ab072bfc7e5ee9c17e3d7e5f38b5d1e004a808f44d7793b67fffa881fddd4094fc4381d5dc9660c1325824c28b505e9f1f067fd8ad3ad67dbd2daa0bede41b447bb038cb48d75ad261c7d7370b58813091a5cf900ddff965f83187ff74795ead8baccc81353563db9cef065668b2b2df6b9a8206c57364556bc12b0b4d6b7408f4e52b93086b33fc4146eebe6cde00ff39aa224dd3c553d7313e085d910f1e726e8e86be6d8eb3032f7ad638b541eb90c38e73730557caa849dfa2b8750a04a0d237322ac02b1104f2d4de8701fbcffdd583012e1a85e3265c3bafd63cac409b8866054bac974f5c91a1113c663198dd4f7f339895e0fa564078240c154fcc0955c47bdae6f244a02f4ea12b38f93673cda8632c7fe2c94343eda619510bba9254ce269281fb47e10f5e91a3bdabaf25b0cf9578bf5ed09de831473a6dc19d0c4a76ef81f2becf20160d2e738da2a6ab48d71b9a4e693126549512a154c3b1b95af5487f1d766b3afa16f2a558c45478051fe82f1172bbd59749733c08d8839a5ab3d48e70623dfdfc74ae1b5d02810ba695e540992ac2d39f7a620f84170bd0c4d33604594d51db80859e6f52cd83e7e37a30265514a4bf8b8ec39ce2dcebc9da22afbe480de74af83eed5abf845c1128821f7cb293a0ccc5f9e27a10c5c5562187ef280594bc88dc2ac2957cd3c0722ec437b517f9dff874980346e261f5f6504e97b9f39913c1986dacdfdbbd2ec30de8c9cefa2f5984eda552a6f8dda79c7000324f5e45f3d75592559251b88a5a381b31885c36417d9ac194df2393d89a2a79c43dc8b37fb3a3051696d15ef175b3d86869f5f9ab692c35b62c0cba268c13b87d190511a7a28e9a3d90ac14f1b2843ff9742cd77c07a5fdd4453c54274cddf174a312bc5d2bbd5eeb2959764be160e3bc8954cd2ab7d3aee105c3625baee8ec7b5a9d2a3575ac9a0ea2d74a40289619b4f4da47c48e81b66e2377c72f035bd9d25761178db93f6d34a40d441f1302eec02378327ac22a5f54c0e209b6e9972b1720fa815bec789140abaf81c18844d8925fc96000c1028491118dcdad8fdb13fdf65520f23b9fbcbb9de5b246e63adac88d0251243ac28a4788e8e1ecd1b0082f206f8b066756e06c2c3a3e9abd7ed31d9fbece4594662e5f7fcc9738aeff16d03422a1d3c040a4f8b04ab3abb92a12867b2b56e9e10e5d5994e83486a0a222e240c021e80a00017a0d089e1473a27b2a56e704c66df43b66b8dedff41a1a33509ba5df9174ee4987cf6623cd279be3c337943edef21133afcf21f6da5b9bb3e6661bc6a3cc32b5b9862975552dc9af5c4cbc3878e895bfad788fc2f302677b00005df16eb033ae0b26c2750de6ace97e947047272d725a66c0f1427681c68c34f4af6cb936872dd3649404268b9cfa228aaaabf325af9facd6ad7f57c66374f5ec534c2f49a4695645e499a3625fe46f87689ed05fee32483db1797ee5a7eb2a083a0bb73e2782f0d60a2c5715ddeb1d33ccf497cd23b9ae0833c74c1b8196c35cebe4b64c8ffe95c569123f82e3c5489569bd0bead5781f7a1e91899ae4211aeba307b2d454515457eecfc8c136fafd6a97c03a9f3675e0b349bab4647127e2c233a66b803e5582ee8e20c8b4e8390f83b53f934c8fd85ca4552c89b6ce15c0c6f28fe9bb09fe9435c7f42dd76ba908e95f5af5d7bf080f0674d99130487f0d173c7ce8511aba42aaa1bfdbda8a5226942415e7199f729bc0612230212c4721ff6e06c5f4c9fa51cea7c78b4848eef9a92123318d15b6b3c9b8be7ab5d32ff167c3e585b67bbe978e50422d81935ebd023b4b363f5454738224791bf79bb9ac3a470295e30b933dffec75cb80ace1331e406c59a9a368fc8df4710fedeef77414a276d335cd878ff638879b7ccf4b7c764e79d64be7cf64375cee064d69dddc22b66fca6bbc79b2221a23a3f6f660df35951c2eb2fe8ffe697e908a9976794da4d043a4e60ae39b74a5165eed3c6e342e9ea9b026879c1c585b8d8ceb630824d025d65802ddd6d8c95bd7d8095d6bfc045a6becd4b735fe9e907b53c9d0a252ea25bf902e9a1758167e8daba1c9fd0cc73a962a40b4b8884389f75e2ec8d98b6b8de51db9b96c26d84f3605aefb124473ab1d0f9dbec6e0cf33648b73d1397e77ca43a3e80d94a4f34abe306023de8e3586e73a76e0be44efdeb2f56a6b87fd2139033af5a236518480e482342e4d5cf9137592813038aa3af8b21bc7ea059a57a9a20b5ebdac03fbbaf255c7884e7c519ae54a62b91112e2766aa3428756cb27e8f9864af67a450c033eb7d4176a4c4ce7bcb62781f761ba4b78146baecdd625a84f6cd7682049ec94d7305828e1339bdfe06de7768b8b8b851dd2d959d865226644ea8eecaa087c6e6243dc821bff05dd35602a3fdc87e7370ca2ea843362952f07e9e7ee4df5c2a5df9470adef17255bfadc35be70894207b22464e472129dea135ad52189577ceea6638f5c923ac67edf75c7a777d5f147f76d7b9bd77c1ee73898b017bd9b63430d7dbe9e88638f70208e618c90ae4b918f9bfb2840ed5e9cb0da78b0582ebe42b0347a12e19e4da41f8347a094c9a6ec1be170c6f9abb12510eb3d407f22ce850dd51bf92bf84b2cb05d7eeb8e029e6c03b7bd331104dfb3fb2f8d59ca0e0f5ba51888be1963580855b4349c840480c8b35ba3c584aa6ef234b6e2a80e77fd2a464520b3cf2c068d5f9dec32a6ae3edd59a6500252e77921f09b52cd8eb21d53833617a20072f2198da6411c47cfc912c58bfdfa83cd030b3368af620db9d6c78c55d239218f7735449e439265d7ddd20405cac61cc670a63db67b84a337e4b9cc9251428b06ffcaa569cf9c337d4c035eea45d365553e135093279619fa51cf76f1ab0b758fc48e896a1a16c9a0f9fcb3c8d0c1936c3e730f216e220ea2cfde2a6c4869730a7f75c5a7fdbddce85bedd7683578e73f7555f52e313e2d2ba1d8e173d3a319c5598b0c5fe09ccf617439d7b32043682e0e29598da33fe79327366060660d71855ab43d50a9fdefc721bf596404d2815391211eea036917bc8b22a6616f1c6b163946931db2f7a0b5a14d2d8baf13cb6f34be8064c258a81b7c6d8f47848c58f3b65e98ed3c3bbb7674bb2c534820e1be7dc1ca6bf85074e6a582e55dea1c9a8b485ba7edbf089000f2f94ef681156545b3fce06438be0224de37e228e1b9c9857582210f1c5797a5a1bd646fbcff35cbb4fbce987f39365acb40f12e988d95ee18ec49536eb69d30700dc2cbebb367d51183dfaf1e699f60d44aa826eb389f90a218bc27294f26dcaacd575fb57d784c5bb2dc1bb12015acda2440f0ebeb369045d9b7cccf198733292fa3649ba03ace165d94b5f3462186d27b21eccd059358a32e1105ca1f6a5cda9886c4752b462b6e38431473265dcbb04327ed6301cc11ca1b718e03fd4491c58749cc140cb3aadda4f956ff9f83dfc4b0ec373bd7d279c6721698038aeb4d6c085662b932aa6ada3b58a1383010421803f3f8b0dd013f4b9ac19faa5d032b6272d07b9618a3f2a2305c03c088fa5977fb35f5fa3a43dafb8a09e3f8d6063009f52d3aff8220a70d08b2d59cdadefab79687008bf45cc09d2d02ac953bc9a4657b576c829f9b5fa47cfef3ccf3e522afe7efeb02fa53302e0d8945d55ac3950f61ac2e836accc36ff1eb3795d645c3dcc86e3dbed370fc2f57f9692ec3da37c8682dc899cf02357e77353d22de75c5d874e3e9cc9ebae6cf895d495d65f8c77b95cf7e0df857bde1be47e3ef66df481777fcf4b8ce3afff3f48ca489f105ea356eac6c142ef473ad9d9741a70d01a3cb8c82ea94426bd31910aa7188cee9ab56d9230638c73fa892555c81bf70a9895ab4bec2eb8585afa729ad9d57f2671662a257c6b5440a72237a4e67483d065f782f32367d2ee4c6ea16b5bb1411d10123d6afd1fd261930406c7f1da6c6c2d76153c500230beb601ae29be60bf7656f7e09d5d37ab24e41ce73d989daef6af6a2160da9ca52a5523f9668f7066863f3bd11dfd5af4b8b672c85645f4f183e5d45e7410beef90734f628304cb2bae75fe9a575d3c54b4b0959fec05b65660cfad7ca5a67f73f017cc40d684741b4e0fa073f23ea8be59317a7e76df75e82d5b80a9c53105c85a6775e1a444a7ffc881d0bb1fa4dbd2e337fac1842b2d522eaabb411bc01aeefa5a73f769916761e2efb6ceb4766ded71bdf3f4a2a90cbaaca4b38919345eed3e32aa49de8f9811c008e0992c46de86b0c142b33837255e44a0065f3d24731168fee17c15217c7f9c48263ee3598b7b67b7a08ee7a7a2d847fa1f0dd4276b001226ca100346d598657345b5b520346058095f0c3dd606d0521ecfe255058692128437b3142cfb43265b40733f5a0804f0cdb2172f654b5ea076f218cf6bc28bdaa93fb56d0b8eeb9bf36518986d8e983c920fb21feb73fe407bac966092574f9b19e197f97f4f1fd3c58ad2753362090aff4d432ea91c93d4ac54cdff447d67439a803cce8374f3c041de6e0d005c8c7ba0efd1f4acfa4dff83498e8b7f0e7ae5c63b73b2880bc858db11562a4e7022e36c6fa601e670e1a1b23a241f6acfdf303de8b42225c415d0f1b502f6d3ccead7cd6a345541d974dde22503eebd0d39f8030b5114ce3db13b97d166c17571c0e0185d1f5d8a83adc12cfa7d23431b5bf1b863db1c8703cabfb2a0b122f408ece00783b195724e41ff673b938ed06fd14ca93e071bc7c183cb420a42fec8602f032fd3f6c98d08a70995d8c07f1af5f38b0e890a3240aba92c08e0a57ca61937d66cfcc0c7091aa801f27c1cd6f3c484fcd67edc7cf709578964183c60b4d72dc615dce2d9392445b49010a088d2755dbdb29736914adc3d44bd3ff9454220c686278836df0e79cbf859275e225c1c14657fb05f417a45bb815499e01e40304d9f062f49dcc467816e806f9081ea0f3eb5aaa3375b6b44297d279dc71a0d32fb39be3a983ce50c2b3c0b7850a149d4bbb972feb2bed0b4cb5c2e84d3ab8e72015271b5bf08f7a14506429d9103f21315f02dd0658af26d23cb8a67da350f1f59d6bb337eef4567ac9bccb42dd701c2a185070138cb2a66219cb3a989ea96241ad885cfc59f512ff50c5492951e77f543db0c913e9187f027cea78175e51dcc074d0c262b20b9b8bdac883cfd616effda86f6e09d0ea2c0abc584a58f6dea82c580cc4b042822b41cf6eea43fd80a5b9466534db79d0dab225bf2392761673b25261db9bf92e512d0aec4607f8baa3a987e9c26d8d964302d4320c413024383837374de3bb16a432cbeac95d54f0dda3a24f9ffe98d6612162f6f82ddaa3564362b0421376c083997e2493968397d4eecc17ba97bacef915952a9812b57a077d1f13cad158cabbedd6080ca39709927ed37742ffac1f392908020b54b6c24c2e01f5d267c2e4a8ca55c062c0a91c9f3fcb18ba1d3e2daa78665874f71b28d2312cc74bbb78006cc650e064a48b04140ee83f96b5201b55a97eb6d78310d75d52e580b64211da74e28a20b2fc87a84b0f84844f934551011daaa23a80aa1b27fa4744cbc7785186530b15b26d4ddf0e825aedbba80b3235fc360f3a1900a0dff887afe9a9aa296fe634145f9c634161533f9c62566b8e7d708abfda0e5876c44672648834200ddf45db784674bc87707b59b0c5e64d6c0318b51bcbbc4cd5ac5ee28b806509c4a51f479c504f97e8ab2dc6a34af800cb9186f77cee5b02014c322516dee678c14934736b2989559745e5b543e74e4fff191a833f3fadfe65d84918f3fd14576d6ce8266cbbc4562a54b10638bb501e8fa66d9d09d3ebcce35ba8f11c486d84667bc54e871a91d6a458e5415364a1017e7a3b301705c42c8765651833d13ad568e877d2a46a920ad2e91d8d224f34217f5bf2f72df551c6f9b03c6e8d32ce1c18b5bd08268564f4ac3c89656f1a39629f37957a793e903c361d0f46f67541bd129f32a4ad85831a23e7830380cca0b7767a493738c8487e91f8ee23a439ba109391a86800d7bd41c7e3451a18e0ea8e1ed0ff3843267d8b99a0e5fa7ded7c272007686f064f02d4212fb3e55f10219344fc19161d62729a1a7ad501b42d6e9008678538847811b838c060b72f696d152e2dfd890ae4eb672b157b4ef250392971c9ca69a0b301200406082eeb86ee9c255654aae7aab63703226812e1615a2a5716d5055bb679b0167208fc00a8312701cb0662c72372de6842e62ed6cba105de297802d09fb505a469b4a9b872e3ab260e97522494f87029ded8a4946ba5fad5dfd24e59ec62ddbc5f8986d9e990cfe95fda617ca00dfdb35f4f74369819d294bbec0e941f37840ec1ef92bb93b858ac51e375b7e196043f05cb213b2dfbbeb66ce5bf9c7a572dba994e8b953a5aa807d0220d428d5e68a4e6e1ed6d8dd24028c5db7654dd8c992870bbd2f8222dd21f8f79d2fdc0b7cb1228a8dabbe97a123ab18ca5d1d4f157c871982974365ddda9d1ab2b3a0429c2cdce2862cee7750ed7dc591aa18f16370533e15a45014b625538ead970cc854df4aff8cf5962226ad472f12ad6878abd9c670a0da7794e2dbb48effc3cd3e7ce7c3bbe27498a8fb016ab74a89fe4d670adc3d5890247f961da75255382e8a3994b1c5899eb2789bdc82e0ac0f46c3d78ebb14d793081cb8e6d389457ceadf80e15e1384f0783c42ae9fbbeb38aae6f1036a2cf595ddfdd0cf58061070d654557e57f2c3c83168abcd18aaed188ec466305af1a0cc244c28f613d3ddd5a308ad7ee3cf77634c58ee8ef08894784919ca3f89f1e8b46931980a2578d1c9a27533d0a67bd679a89362b4e1cad0cfc5e761ef486fdf700bf91863e496b5694793f177c832c10b7a4a1235b89786eeac069d4c403fd1d6794c347f8c70259f82a1b03bb2d2ecb298e473bf460761ae4dc347d9e5af29e5c562adf9f4d6ee8ef596d44a1f8ed9f819a4bc085186264f5792f6be505c6a68fa08aac2423d32ed5b4b40188aaa960d578202b34a149e71815763c4e7ead42c965fa728946b8bb97f4b2aa453d8b5c15cd083ff528b39937d835544521d4290f48035f634de2b27f0a13d1ad9c3c1dfa8d8482b323d1aed93017a92095f03add1bc9da8ec4903f315e98c28e20a81935f9849d950c1c6e1918e6aa55e141bcc884e946ada992043d628ef2559f0595b470b62b0fb8dc6f497a5a513142111dd85ea94c4da1e5c25891a4bf61cc141ce789dd4ec6ef08ad87c9fa308850787c66720ea736939c41d179f1531c86d063c8eb76ed2779f88b1576ee9e8b85bf298665da6f7ed720257e56a6e180884515a2f58d894f5f66d9da10c1d0c16c81682b74d922aab51e8f29438755874080ad839924a12480fd01044dc0c40081155745645c11b54c524c003c7302a86563ae347260a306dadb43c704081e9ff343c19bb15c9e721d01ed2e942842dcc92580bd79d0537a4146db3004ec4c78f570b7bf370dbc47e6432004e083dcb1f4e0f8e5d424be212457eb16e79c1d729210138bd084a0d1809cffa0f0a641384c9503427a3ecf012806c94507a4e22f5f556ac241c7cc3fe45973ec7d2d274eff5b0835f3756a0da2df39c8ffb76fff8d1d1cd5f0a3395ae1b982a2e5ba337643398faf1494de5439f498a9a5e509c001a94212c7b0a0fb5edab5dc55cb9aa1c6cc428c1ad2a771c2515b376ff3678066ebcd12bf6c9fabbb08dcb46a846c36a2774aac6d6cdba4d8e1eb71f083ab68f8fa23b319f6b7dae41a58e625f73324e027d29209493aa243750c3eedffa79177deffcbf69d32bb1850fd697e9d2ae54de1f6e18395ee618febfd476e34b9d5239b5e5ddb174d348991ca426d444382bb29366a78d21ad94944bb950ecbb4f3684aef6aa638e6941469d905a690f67cf85e2fc4209274c5059dbe04ea9b42bb982b9042130b93f66fb35d2a0ccb73f8d2589eb83f5d6597281578daf6c4f0b70c6667407ae788f15dbd903b20d49336887bfd4cf9acc99517170e7fe71c0d528078889335cdb9eb36e7c1b78c445f971ac6537612b9db955e5fa98e86a06bf745db98990c095cece0b87b94ea376c6daea35f8879c0107d2a3245277a5779f16ef081d7b57a9f3e5d374dcbfaf6c1866105a05807cb3c662329d4602f26bda0b17ffb8642cfe15b16fae661565998941a067bbba81e3215f7a19d0f7e51dbeac49319a884563fab56da08883ff41b60181aeda8fd1995bca600328da8ebff683f45e7a34b3872f3f99a28363545a01acc2260af71070210c4ebb0dce2a702703612d9a645e6c6ad238ffec92bf8c520f85b6c374d755e29409e10d1ce8580134dc7071405641839741dd3d9f12a14fea25f44d7dc915d29ca3cb0d86c3109b208b82c3d03a0cbcc794efa9447baa2a095699f8e0006b8875a50a871621f51626601b8e557fb5183f1a1e4c83b1e3ae0ebe3d552051eec2349b88ab3774893b57c01ab0c201368c1141694c5538496bf96d6cb64055e0232704b8fedee6dfdc758e0161d191689a0bcaaa3a97009876617f29cf59369854d17f41c50ddb8a8c939c0f3e23a4fefde230eed8808c482d4f1c128680e9af6ab687ae2dba504972cdd97d6fa185034558e268b118ad1cc0cc73d93340b78b6add3a88e4a659cbbf90bdee6fafac8de83bce92c388b211a0a573a0731bc027d53b2d1be18a8b5d62250ce110976917850da2cf8b9867c33a12d330072bf1a04123a49fba8a012d7c88341e0980ae2402d5d7457816a44435da4231a29894d1de5ab341651051b63e3b11e249b5f76e2a6b073a7bd7df2333fb60e990172d02fe0e49457c0ee80dadb81aec7bc10d24eec72c0e78d61152754141b13c6f27fd88c128434ae69c56cf96618899155655cdde230215334a7143ed49aff93f2555db0a94223194c3d1c4691489e41d23878eea574072d63ee081b0404c414aca9ebb4095d5a98b234d5cd9a2f63d09be10d4a5491574e76e4f637593193f85e88b053c8104e0579a73c5a329d00e1efae9257286218512bea06786e21fc00e5d71e4c1edad92e12e52b54db596f947c4c6604c70eb4a0d2cedbf732feafec957731be7f5358f7bc45ed3c841763cf563d69ba2c641267bebc38763b174e376b9bf6e210c98cda6014795b63ef2189ad4b954428f51505e300beb5bda029b69f9027a4ebb1e6c3bc7ca6c093cd764f69c09814b718aade2ad93b7a42fc3f9b69ef621eb84e6415843a5efa028a6db0ae3de2152860e254b3ccf3f4051d00a64e7f9eb770660e9c64775d3f386d6bb563b8b4ff016a4f70c08e1b4b1fa0bb01fe4b1a02bee0d4283faf04ff864318bafdffbad21d2f07f52e18a15d423abf9540856ffdc9917824f2d2c745e051a97259c4f4f945330a84eedb067ba54e1be6758f9835717c73f85256ffe2d03ddc68a6eef28525519e0a23fca3ef68629345526f2bc2806bc526d9b9e248ba8404e1d497959a01d126e039a0e226ebce518ea18e752dd02731b519d3ff87964fc4415aaa8142e5845d5624d9b5d5e4caf743e1c659b4b3c732a3a27019589188158d817cad95e9cdea0ac3d0b404837385f205a01d78037c768dd2ada60b5a9b01902b05fc22091ce96410f6441ea15ca114b0ec4d50d430d39867962365e14754396eaf4b0cb0a740a3cc8d1b04be76c63f74158105bd39f2279ad7c5445daa371d9aa1108cd37796453ab8a753e2de00be4c435568101a9640009c5c1c1336dbc4567d779664ac7b5a578164f62d788788a97602b6f2acf1bda9b7ef6057c6854f2e475cb702bc897694f20c006ca3d0e847e48ae78b12fc7eac1bca8b611df5a9d78482d24d9a34d9daf3b05fc5541b0fc654372b3c1a8af82b03f661f73a719e5e6f21df169ee8e3a7ba8332c5b45de550ce88a45ce962f82f3852b24256e133da3b29e30b9ac3b5531c665be5b632bb5758bfed22a32c504b6f7af0b19cc904234e8c5511523a1664a03e67408b48b065a51bb50716048031151b6f76e1ffdd7d9cf6166752d3034a4e52c5346d8aed9e740b70cc44144a11f60f45fca192a1c64e118701635f92ccd6c8e45c1aad46d70b0090104188a4bb5b60142edd2ac17d4503712c7b9ef9e85de9136546173a9addd32a69732da09a26dc5a244594fadfe66c452c02199c3b8e2c475d50f3e445c70b2de9576765578ef106381e953e6b4888d2ac4a82374f813df221cd0ee0c16b9fa6ef136446a601bf5236c2cf7ccca1c1ced96f3494b13fe4c00af4c493268f8974987dd9fe8c0b6ce3da3008e04aa228b2670b1a105a397926c02cdf9fed984b58aa529e96b45a2b3a688b5087451b75803c263a72f59ec1645115522cb443258b704c990c107c2040f0607c3644dc3ea9369662725287e622617a01f16c9a4ca3e0ebe55831c50f02d57490a62f0f6e94169c9ed68fa1e7dbd028080213d763a8b99f7ecee8a13f7a5fe16724712d4e2e372248903d39341f24362e4524f2654d9897b5091c51fd2bd3d5a89ae2d5b9b24f39f6a2d89996b36f7101bf90c912ff96510637ddb288c78b49e5a8db12d269e686409373fad7607bb5c92550cafa4f611e679d47357f9463de0dc36d5e2c91f5d289e6920266ad9a253663a3fc9ef1d81cd5e4f74b317e57f05867730ed9663ff1a5a6da9ad6afb36ef6dd07b7acd5284f5d47821607827ab13b115e540419593e298188b2d27ae74c682ac3351a0b611262ef33a6ca4d57d7f97121249b5826c06abeb9b4e15278fc298bc308f52e16f91e927b423bde1dd4e68bac12e55990e84230f2068489cd81c7beb995521a9639bc310cd39a55fcc9840fc119c5cf52113dd61f7b16fd36196fbd3cd330d0f21bcddb57c978a64a31ca5c90956321e494104e7733c287bd3c737281f0773c1a17d5421b82dcba5c6bdfe578b6619b16a747a8234c1f6a6abed6498e160a787d395edc982846b9656c8a96c1936892e63b51e8e3933d57c54bb588a1ddb361c569bd69cffbf321b8bb4a650f96415036593109dfb464975454806eeb622698e77da663a8d9e8a2ad15329e708e870865510a4c9c5c09a4579bbf469cbdf8c0efa00ff9fadd905d75a245511ed4dcb6adea4d01440c740074f0a00ab478ab66addc8f9296407ba47ad450ed26138552c75a88475e11ed55b6bb4d37eb0877da8666c7e70757939da91d1735799dda3f7e2991db35927a10404a90eca191bd35100d942a6cf73712274ecdff061d0136b1d245cb08375ec66439a3de42b5f0fa7a98f10c81fd8bc9ec9c795b682f79a89d87c477a512616ddf84eafa6e8701c54928d09bf6d0a125ccf7a1a1510f82b4b60d7c8778acac85de81698d7f80b0dad12648165fa97983530d6b1f447d0b675869d3067443796d0ab5fda88c75db399d3bac688d25adcec26074ff3fac2b20ab41e0d9ed0e3d59235879d943e7ff95eed48f7f7a2ff23a63c3638c6d59177a7341061aaa7f5e9a9f49a240b622d142d3a24548b3d576fcaf7bccce2eaf49f3e71ac0bc26603fba894bb1b24d0f28a963ddc4a55a51d145490af4bea35846d5033ba3f751fc597e610d63b6b49e0b60a974c48824a043e61a74a0025cdcf551558611bf75d734f995905d946c53ac015c5df223a56108251b7b2dcffb6094fe8c3c67c98a616623ebd34ca5008587b9c672c79ec066085c52e36366ef9d3d5916a11c59dffba6d9b9c85deafe69e6d060e4538521ebf1c8d3628d5b74e653117127dc48d0a260ce8302c8b11c2b201fcac1ff98ba24643fa036a68a4f227efb5382632bb42e57642dc1a7590de3bcec966223dcd6e57a00b804c9de8629eb7f398de6b36950cfdec6fd2a3307dc8cf3398981e71e1e13cec5e5d0ae131ec44da0027e7fb0e9173b445b16bd902ffe8b71cd9f8bbbc233475efb1a97807a4a99d58ed79a2c4514fb04c707a4a1c55fd6f163da1d289206ab68d5a5799c88ff2e36b37e40fe94e12b82da62d9994410f3e2b2406deb24853a33183a12e3b9c58291132b900c5a359b25ca82ef0730e8f946a434759b390b3da7c5caa8cee1d93289dadab54f60c505b2dac39ebe4de97a63c7d730ef0e154fca092872698aebc171c986812aa34c4f486c101745168071c7f302de3a37f8a9fef970e6380af648f810d6cd0cbf042ab62452a6de29e8d9c4130083373876e46361af343dea886dd3efdfbe11d767fe2e3ba23934802b77b438b0cbe336e2fff8e1883f7c528896e99b1c625f5f235fbf349e411e99796ea95d6f53dc0b6abc10a0c94cf59c4106173c5b002b8a91de316eae10d274ef1592db22f4142caa0539e118775708cba6dc6f22e208f3cfb04ab521680de90a8491fd0a47f3cfd9080c7796a0a877bd34bd0b344012e8562a002e01eaca4f2ea5a137a6c1b2ac4d7999994637efbc03ed4dddfcbe9a07e9b622d310ee5581e726c65ee32a7624e01be378b55a6a2f7c1b2fd860ec36e71ae2f802fe12fa9cbd92563da89caee4d43c2f794bea14174c34e554375155d1026013a7b3b47affdceeab715f487e0692ca6c333f5cdd31f419b472f1c0502261c397d9e8e908b03e7d80f8fb892045217e07830206c1a91f0c421eb9d7dcf5d86873052e2d9861691225c1ffede004047c2dfacde3d612362841d5c60436ea03f579aa6819e43322d1693f8e382595a5facde601164bedf698495a8748d35b9fa91c723056acb447f92006212e9eeee6a0365eb300c256df688c52d591a62001bde7e858d55ba9db0a44e58941100e4db66fea9e4340a92ff4416b3230fba319ed02c4c30a2476c2a476364269faa75f1760a0be1aa88bd63907ec75e94b50bcd1e8910d0b1c56936b769d53fb96e19fb587408121fdc733d72e4a246046c1474e5e4337f13f2a7d5eb2e9610bbf5c47a52c7e110af032f46e388e3efe1251a6b97946760c7d7d12e6f366bdb338e989dc70ca9f47f4e32282a9a141f70c490d0d0dcbe521fb088b5a87405d3414ad4509d09ce0548ca94e8d2a5d5ca377e35574bd25a07687ac3a558392892d5b839c290ef956f26a9d62363d419b66e5652f3da6ecd70f38a7a664a9690cbeb12f8fec4f74dc931ae57cab945e9ea6acc7209085e89ca705db8cf1e7cb39be3058ce08219f02b80c74da06a7317e04024fae61280009853655622856dc48df5249d384e16ab28ed40ac9b5293a7020dc852d72daea4c19b7fae9f9236ef173e89a3b6c1f42bb86248a6c1e1bccd57d2dc2b8eced351f58f3de162f62906f77468507d3040273f558b57ace6d2994d385579252387217d8009153361f4bceef5a28fd7c6d007380cdaff0c6de82b239c304a39edde85648f27a8e74a72718878d54ce9890ddde6d03f0776b8502b389076a86063cbf2da3d3ef57c7cb12314c33fa1a0d27136ad8f4abe4e8d5722d36d3d73f1cadcec0502829e1bf4f98ce9af07e42382cd92e2e5c6394f71a15219aaf6747b180c450c87a19e0ef77a1192aa2f920cc95c361ac732ff61cf736efa3d3b7c1e2bf37684727ef1a7e8e2858a889fa2fde6ba233b49a755264d99f8cba2e8b8a7dd2fe6655ec873259b0732ffbbb0f0981e12c40a9cf79bd94795564e2ab3aa7a8cae0b0d87e4584651494d1862ece19de96530d445cb029429af6adf5017ab3a844d284f742b7b3314b2288f8f2f925eaedb3cb22d38b8b7236a00907e0a26aa3778007c27a91e90ca802756401b87ae54144656b41df241a8732f78c60cb047972a619210dc7f5c06e89e9436ab9a04ca8bff0308f5bc5b01c7bda4417ab67e1f12305549661deac2ad65bc4d21df7430cc3c6e8aed6c24892a5f0a9759048f770f106dbc5135826c10d479710eebb7fcd7ecb63e7cacb906c95f52a9540f70945b1a8576c672d8dccfa34d06c73923ccc60363ca539258d38a0cc6c924892201f9062f1454231fea51ec37bf1b90499ef2d5109be01d70f0b4383f7dbc6b51b393fb28505163ad6131dede18eab8e6fd8fc3c5c4042b1d1f4257abad1c9648760647b090c81a24c764ceeb623d70cad6323ed69c1ec810539513716697fa131e3119918cb9d1fe37cbaa7649f0061538243616c67dfd4d7d2ea972bbe59de790287997a9faaae96bb3d7e936e70344b587ea514788f52dade74b03493677f9e4e50d458b1152700ac4048a49be33b3455c7587dc329cab54528b9c941d8bc7be6354f859ca8707c34d9522b512052752080d7ac477d9b4ee065977be7a1d8110d6556e9142e10a50460ac88124b08fb6f382ec3ced8535ad45989241fe513da6134e44c2ce48c4997b398344692e2977a4d2a470bd96f5e53b60c64b53bbe2bd726ad195aa17b7b677b2c373081eecfecb3aa21801d6e44d01290b59d2ba72d816266278155750c5859f7fea6bc2e59fd7aa308811a57509b0f02e4ae280ec0e53140cbf36ebab79ead08b520e6e941792668517479404659bb8bb5f63bf8d79e3f370dbafe496007e719c93e60822d3ef93d598e8c10d8ac0f671085fef838df030dc58b5851b011d99f6329d6aa848c237e4a8c36c39a57341a700f3ee45db1f02fe7f1dfcf3e32c36c3eb2dc17babfb4e89ed2c59302489bc7332d613b6150c75038a6413258d9591f42af30d833600e3b8bbf58eb8bb9afa7322e5d6bad1d792b0cdde8e772b0bfb5d2792900762f69bdaa7bd5ce7350b7424f78357482f1ddaef00045bf95f586cf2cff7a5ada2f28ec83d72adca290ffee4cb74644a792276b7c9eb6d280e49a3b0404049cd215f68fccce835ceddb9b10c76ddd7007ddd86664fb051adff6f7185eff09b6ada2eaa115c2aef53381e57c38905c02ce78d95ffd8c0aa7557e05265eab9fd12fd710c4583e7fa05c7632dc52a4bf056bd6cbaa09ab258e10147eb9f72e8c49429d59f857e0f44fb026f9e18b363772cb74b57345e668ba363250dd97ffe1f6c6b824e633f33eb6c5830fe4867d9ecce2517b3e947b933c9f1a9a33689c54790c499cf071caa48416aa71b141f253e121b66bc535a819ace9e7455c85ff3e81c713cd15f639f9e7bc9f3b21eb8fc0c707b7bd1dadee037969890f84dc77a1b9893589b32299dfaf1c257fc4b8b37c1cdeeb7b0368a558a8dab41b02515fcb1611c095a138aee518eb99aff70ad9ce82da83773a77643b77bf4c522a8f7d4f219787955dbaf372dfa57ffbc3b6ddb0e252158631a4f64a708083e90d53dcb4382c8861b5bb2b0acb89616900edf603de99155cc0f5c774eaf64ba38cd18aa7bddb9791a164f29389bddfe47b5e272a18a1fad6c816f77ba3ac196f2388c7e7645170fba21515567d2446038b4101e8abe4793e7c42d7f8dfea0c3d372aa4db180b8c61d0a8728028908dc4a7a8f27f3f8207ad48c46d797f7ee1c8fd1a8161f8bf83bc9b700146721e0c1428fad2c8a1a06498ca8726809edb0424c6ff074f7a6842eaa11aa11c3932b9b80c394c5dbe4290ed5f149eccbb43b883953ebc9bcc15797147b8c69e38693756fd721a8a54911fc0f2b147ac341eceb0f380b3d142cb0923c27c978ad57780c78ea9315aac5f9284b045b35ed634c6bb71198e927eecff09750f74dcdf9fc79842e4d069884ea2985192ac471edbbc3812afa520a8929dac58d7f2f5441ba20a64791ee15a3444a41f7ac44dc9cb85b2edcaed18c51922c0a2d8f7449dfd04128e731339d316bb5f938b471c773856d2867dcd9254b14d0cb92dfbec4c0f04e0c447934f8fc7c6bbcd369d00a78ff4330a600daf46ce0789619d948d76c187b9f5ca18f2f4421508211ad467f657149cf10208bc42ef0d8d958a3961d15a32db1a81a1bfa8b13c607c5685ec01a022e62fa190dd36b3b59853071771374865c88ed5fe889ff4aeae0667c0426a8c9890b440857d099222cbb89116eb088e7d780307390a2257c1d4b53aaf54ba9df17c73afdf20d1dd4751ff0e6470947254460762604626a6700b166e1746e5eaae611533e8aa8d9c62112d6ebf6f79c2591639cfe812307c39654b666f1ce6857e183d0575689de1e91f31a68920172476a8d8331b49b7a98e8b96838211ce00201c441d7de97bbcd304012d9ac5822133a0d44884545b5a9cfd31d7e01dd87123b0843a343b1aa836458eba3b3f288d33e8c0ef75246d88e5a0e8df56f30a46c29db6414ea263010c3b8622ed8604da2bb8b903fb55c6d602420991491983e5f193ed64a6b14b474057e314b3a2ae6083abc14a3781a3a0660015b1ab740eed952bedc4f3fd7a615b75ceadf27020f6ac947496a8bc0d32885ec978174497e5a46caf8707ca264867fb12d81851ebe36670c9cef223444c19149fb5737f3402760e37fb881867ce0c9032635816910452d772f23d6e8528b76917618a6dfea6a889fc59dc1b55bea886e19e924725e3c0283224a5c413917ea909f12c6c305760c28dae7272e77bca5ff943ac103c1bbd59a2b1d4a49ad1034f10613756aefe0c1ebf7648203e778bb619ea24269b5bb3924b12470cceea1be93992ddb32305d9a27837116a9d5eb911d2deacc1df88ce2e1e890be7dc9888a1b3afecaf738782ab6bbb35c2c65772f8384446a4689f343f3240ddb1db1c00a4c8278e626d96c39e1e955a3f8e8bf36209a105e01ec3f33e98a53f4347e30f1c3ed78ac1f8dbd27fa8d62a264a5947e8416c23222c6a5e5011cb27cd61161da1f0707578e138dc8fd0df5d9d4780f122f5135ff4e6dafecd34ac000c01359a0e5053564e6c16fc0446179d3160b67e69366c0783d40fa9dfa63378316c4ba76bf9924a4a3c123398731d4a8eea0b6ce50309a328121a3d0c6d11748f3227f0b5a580eb140387f240ef82db451d753bf2a7276a1f2e54ce07f6365584980179396094c105ba2c40a451f889f228ba031552c1b67a16f003981557625dcdae002851987a3d73e07fab3a0b1890d242e6b63a6484c7dd20a21932cbfd53101693b8af17a3811d4f80db23dde395a6470c1fec5b021c9db540755476569d6302b9a083c3ae7364c42333bf2de1099c24aa8eddf20334b439af0bac6687e092a5f6447f34b5897acb94bdb45de5b45be16e127c2302cc39fc36720daf721b99acccaeb5cd52f8d204b4164fe8785efcac65f69169bcc4b99bd38194fe216f61a9f35b860522254b05bcdc22c3c794ddc3f2b0b1539ce50643aeac4ec5bc1cf7ae27310ec349595c5eccb1938893489c1b1c9dc5092e84fbe24bd1ebe7550f8b3f247e77aa50d1e72fb7a3986cc1a4fa3dba6bf893e66f2603483a62b30a46f20aabd13f0383309ca6d84cac7259a5cf99cffe0c8785273dcac18a2f7bb91524612aa10cb39cc6e728c8aaf2446ca32630634cf2aa618938e4465333073c0cb649e9716751b93605c07f468060a85610db33553dfd9bb6bd787f9d9b8d3d3ffb6c8fa04fd438437564098d13b875bd0ac5aa280c76b9fbe7d73ac050b8dd758b1c64cb6bdc7ba5684617e97a602e10e4e41956586fb3483a6c08b40d886bc92f77e1762a02f944a213c4024f17a53412f7958618fdd51f8fa9e05ea5bda10d0695583effde3ce4a1f5eee32f4f3680a2d0d527ca95a0997bc1625629e6a1583797b90e703ea8cc9e9b225b43b287b7c886cff8f10f5d5ca1fc041680d0bf16f4db9503fc5b0bc8a65ada55d10496061bd61e15aa4af9108b038b00d1ef14356c81afe63b91bb5dce5b4858c9418640c79d749f0c1fe417a12bab32855711ba8385479920248cc8c5084474ceef049a247e72d7dcac900df396b5a3962faca691e54b61a2e36652f97b0120a12c2c2d8a04827c1c6f78026f79ee961bd30535588b347fb04296f6e58df67307466a4c367b6f723094bf28137ab28ad65e71e27be30483f8017bd80b5f9a6025a92cdcd52f5e16b49a2598147e46f7be6f863dca1574f0e6c6d1dea1da358c158c10e049d56bb7a17faa75e232d388e385c913b9e8e4be06efebcb3da429b700a643c49b84976bdb77d3c6f9bf3cf9da193c3fc33d494535aa0ca1431770cbc7c749ece4ef33806eafe58eff780b261dfe9b19e688df4309045a3df0e48e39e50f2b9420b5e7c7858b83131bdd4684fc14bdcaa2bb74f4ca9bcca425477cb6156dcb5e6b580c0a1db4eb91519a81a722aa0201654450dc430376406e1d8402bbb381fd24ad57b3fddc5c768c1f28ed2885c8360ba6ccbfc1af9a45555b28c32259693c89ec95c5da2cd7689e051f99d5a31b3aa603858437ff7e6feed452158da33c97fc88ce470afcb2292937180e794cb54a78e702175743460fbfb0206ba6a5316e8337e48f8feeec63af503743f61aad110348877c9115ae5bd2da5d079ebbb6f2e090185efd3f7da47cad0469d05234ec531f3e88d74e44ab5c961c9c0f113fc6309975061cbd2d38ab9349ae03e2a2c01e11bac61d52613b380b5b6476dee0c30f64190ce90d4a02fe3cd15353cc33212e5c43c3776f2fffa04bac6df384311f746070b07b442106c7d152a1a4354b44afe18446f97fbfa747569ec7d93051e3e36c85bebf89cd0ab1c0ab57691c4f3814b5d1bed0a1e7797893ce9b9581760704aefa11005af8c47f7d0724b09c7237064d63ee2d6a9aaf6f40d315c39af646d5bc503998c03161b919afdf8aa4fd4d04ba46516fcdbe1703d5ebdc0a7b4741f4781751e749221ba203b6592c1384ab91553011dd5f500d528205c105dd171e7720abf9b54a984720970d46ba132f1d015951b36b9d0440cbebc65d523685958352903b48b0e6ce90e89011694c0e27df69b484b02e9a60c015a7c3b153adac4767925f4d08074ce8dd57bd905481d8f3ebf8fe6dcef4795097c5a01806209f037591eae20b56f6d192ea01f6d43ee33148324279d754d4e5aa942d530728122ff3d6cbf883e1922211eaf8cdc6eb50432824806f5883ecf3524a8a90a9a1aa72927b4901c5da7c252d40343beec58b527309e5c6d9b5b2de93aa8f03ccd1d8629ab9333074b1e38bfe51b05b4546baf8fe52738c2a18c4ff591ddf6b4620c5a58bbc37fc99ca35219703820c8ce3c881b8008bcada26bb1ae9fe15e6daf8230e0698487d13fd5e7e25d0ddc40256071acc81ba4d083dd1572d47f43e2e31dc4d09bc181aa2b3d5a19c1243c69e54100e425dfb52fd9a92f6f9c800dd9aab4827d543d479781d1680a434924dc724a740cc26065eb8de719a399086d3a40aba65adaa49432d40bb4307b34ca2fde9710f2a14f96302f47d7b4bfb872ee6cbda81d5d7ed7556bd189b2b2c785dbb17a71e1ff828854d5941b00d78cda6dcfb9cc85217686b78b1c9981e3ff29cdf9788c0d8a76ff62d2e04d34339c6630b08496f57c447d575a35aa42adc26a580b9f57044be466d73a42c3e7af2267d53cd08a8d064d6d1411096ceacb440f25c7d6aa2e9ea039c5f788cc535472f40c15292c1848af7e033252eebb0427f2479e574aa596f353fd399b56de310a88fd0d7344c637c309e47529ff0b6fe7e21c07b4855c4d2a2de88f78ee0ec0ea103f32aacae67d80263a9010827cc792ca327af69fa6c0edb76bb02556066042e22278942c96fc34e81fdf526338f6ad85c2c1515f44b23f3cf6e06f18c024a712214aaa560ca6e099dfdff0948008d4b83ff48713ff2fc7b2cbaa66800de8efb5c2075478822280928b0142d9bf557c3d7e57f1190ba62a12ad181638b65cc48ec26816f7f78db43b7f10aaac7623d76122b81f9ad4ce7105da3b35c7929b2d7ef32436ad6e46099812a42d06f37fd6f061bb14cd9f83faa55d844d5dcd309148ec79552197a0eb7e38a50706309c42ff0b7aa8e964b567d1d62acd28cc496c4477d1cfc016b17e6543f0e929f67c02394cbb02eb20004ab0c981ccdff616441f105f8ff82a0cfeb1878874645f4c18cf44b93ef93151e21337e280a59ca70574135e9d9541cb7572d1fc4ba7a0ea561a70cf5b7a13709f3797f798fc27c6bf238e3febd70ef1203b6b8c01e2964fb08de57f6fd4f1e7f33f9f66cc27fb2d362422a58dad0bd099cecdc9ddaffbf0c61fd3a344fb0a2dc3794d64bc619e03d7e77ab873e48445e969f450991a8f7c2fc7784007806d822b0baa01b98762086f40b01eae5081f1ce42b9a8a437798dd93b6d335e9b01f8c38b7ccfdd23089ea90b7f14c7a7129ee4292c965c0650ac788e728800b5b6a678175c067e74437e3848e156653016f284280a16f7a89151dcb4269080306c44c498781cc44f1d09277c0e7eeb18203ad107ed0308d1e4ca8d8ee2a023c4a03da783a805b3014964d07968f1d24dd7626f7a9fca705991d2a587f4323c9a04ddacd6bfe82285d458bd2e3d2bcd15e0b10e405c0b83d1a6f0c983e83a0fee1b1940e627bb18ba57baf746e9e1d7b310c739929f15b48db72ef2da59452262903d8073b08130841ba2ec8af10a16357514b15c5847a72a4c355885ada363675e993565baba49f92fbf97e3170b62ab80ab8c818631d108174297d622e295c4876b8da31e6fa91524a8f2db1b4431a73e9c45c385bb5804da7a03de7f6233765751bf413bf06adce341b345b28fb442400ca6b6f7f2c2cd2d8d73eca7011d4fe07e5b339882ced35eb83adbd6691b6f6f30b55b6f6fe5922cf164518ed557c34fef0656b5fb7883417d0558bd8437b8bc45b392bd85efbca345bb667b28c106952b08b107bd897acb348a35ffb9a146950b32ecd387bb6a605d166341e2f313295f2546aa6523495aaa9944da56e2a8553a953ceaffdbbd4944da552a9aeeb6ee2135a65083dadddec8737afd66dbbd6da2f46181e3a364102d1e65486d0f95158dbb8dc9d2e4a3b9dbe08c3a13c1a61ec773db3b59aac977deda6606b29567f914b754150b2ec1090a2a239860c9b556e5e75a8544a9ed9daab0ca1b33d7250eb3a2b73d02239a859a2adbd3d9259246b45ecf1125bd05e3bbdf6b6e8ad110b5bfbd0f640938121821a8ae6506f7fa505b18fb5b7cfe1202ec30018b4d7b4e72a7defbbe18223878ef7be1b2e3872e878efbbe18223870e3abdef860b8e1c3a40efbbe18223870ed0fb6eb8e0c8a10344d1525f0d118615b586d29ed33ea5bbb1753659da63acb5566761ccae8934dc6b9ac6b29cfdba2037b274c98e23cf1c99eac815cc96956f77c21d4a688123db3ef7e1cceebefb3a9b3131e0ffecea6c6bbf7532e02fb48c6e064ec3d7563a374e3b711f8a171377d8df3c4b3b192ccb47d7bfdc0b2b42e6ee7eeeeefbc2227bfb56b8efbef6dd60679ac7f480d287c14601b8a8fdbdf76be69dd3fe29eb2734fdd3a9bbcfa528a54691267f9d484cd72bd27833c92e329b41ab69456ca57cddb1a716bb4ea55d533e67badc5397c95a87dcdd8b7c08e35797b994abcb9cee32873a329221cdbc68c8dd8d50ae75f9d47511746424439ae5a2229da2a2a2cdd97c2bae5a955b74494f5c95308c25d08783387cb9b8040bf9b834d9654ebbbacca1349f2e7327a32e73f2b4692f97f6e3d25e5808070d29e5e026cd872809ae9e245a974f3d2ea375193719695d26924249e831d2badc65aebbb94f0805e12542414e9e08090911e9278e224cdc74b6ae0341b6f4377f5ccadc0f8808bb3eee6ee64b0a651c9c55bf08f952d9e14cf7abb5d6156abb0a129ac9876ab4d8e8827c17c4eb827c5d901b5d10972e880a08f4fcd95446be5f680a6258a48938441ae9440a4d1f3b8c4b4b71c965877189655720b6241422ab7e75244b7c28f1984929739146928929c2e02ff4ca7db95780d87d3f1cb4517ce83ae7b8e2218cf1a9cb4346db6b7868081b1115cd5e3f409a4b7b11752174d485d1cddacb65fc2fd7c91074351d0d89b6b3e9b0030e3c1b77f80966c2f85e4cf404d05017332020a025583205ed7a3fd7894b38cc9ff99aaff99aaf9d5f436da7af18e70e7b9ac665aef32490398ed35eba203059b290bd853c6332dd91ab0bd976080040be17752a3223fe42af1e6b38f1725a0ed6e27ccda0fb9a4bb01397711cf092ccc199f31cc98424cbae54b98b959c55ebfb508ea64374c29b6627ec071bcdec5a57305f48bbbe3739d3a6c98b95562e76226f9cf83cf1baf73ef17ac1ee90becfa578a9d75eca733ae5adb0c21ec2d5ff9af2864c56fd142fc8645526f47c459adf95b567d06ce9af295f90a9bd9ac9aaf817b0eb43a1f5a7bcfe940f57fbf5dab5a90b02939d853c5bc83426d71dd9ba906f969872a153bc099bacfada9b41f69b2f07eb4f973131d5afb7890aa1b7caa40d9e2fa4d96afecccc20233a974ca27994396b9532673367a9afde059caf59430d675798065a82a4e1c85429287a12f9349a4732a5ca4c4c4d1387a97ec54343bb7eadd868d757daf52b0e9223f42831edfa38e8b0c306240e3672993924248d7cccd4fc0852875856ef023ee193b5108a04d9133e1863fc848f4f12cd06146ce3571942fb7334d2d0dfa2e47838249c0e8784dbe1601c8c4b5a9a4cdc9399b7250737270e626aefce3859a7bb892a43681b63b460b6767bedd2ba1736a36ea973b26d1fbb4e69eb94b89e70666f8f2a426f5f334f3067619d3c9b2cfc186bbd5afdc7f0703e1b7f17146926a7699aa671b333da7cb03dfe0d8bd883d3912dc8b80f64b1f1f6e1f6838d7f3bea74e886b1bb365ec92a43e8fa34862042e7406b68a491b179d5c8c15aa4237bc8b0830f6cfc82b6b7ef7f2362c9db8a568d8ac07a1461f0b67d9528c2e0af4491867b4d6badb5d65a6badb5d63acff22ccff22ccf405b5d5a6cbcf7dd70c1d162e3bdef860b0e9a936c9ed93c931dd5a38ddfbe76d5a26ae420fea5a521373170431c541942fb4a54892a5125aa44941e713b9146e77afdde792fbdb7de6befbd95daa8f56bf56afd6abd51ab4bad386acd516b8ddb8f7a5f3e6d0ee58a28172a498c4747493325274b12e53af59c7a502e5412d4ab43aaf911c3901a6c9000059c246dfc4580367e2393865cd3c6b6f2f4e49e9c9495f2cc8b9f8d3f2f25cd949c2c698d93d20b9ca5a5a5cdbde42c229823fef82b0c6dcc2155a24ae4207e1ca2d9ca489c9545c691b94cfe8168e36f41810ef3d0f6781b893230f36c3f67d8fe86f9651e07c1edf39220219799dee6645bda9e38887fdb7603d1f66ce5d70be740bfae472ecded6efa4329db9a48267b934ef6f6dbcb2962ab834d098b34297b7b19146950bfbd4cf256b77d79e7051ae5d5b866cb88b3f06cedc8c25fb7032c764764c5c6cf7d4d601b6f8ed5219d8e4e47ac23591d9165a2b190147ab563cc032f1af380114060b8f469a936210b22e8d0e0065ab5634c870575476704b60a1d63c7988e0f9549774db047ba53b232d02a5608810910826881123a65c758103e4d4120a943d078c758103945e86ec718104fa826d0283bc68028c22542d31d6340687193d0da8e312064401845ac8148c10e57423709ac311542d13062a57d465cb63b153d3380e8004a4506b255115a64c480490507346208c164d8a0a648b114838a8c02854c05db522e90a590204503c1507e2822a362d093fa2188ed34c592fe4246b704868ac999a572c658cf40e91483737870e278c4c4cc082975313937d832c63a0aa2288c740cb61f5428c17eb8c004dd8f1988e0f423082796b3537f00c998563fa4d8e1e2c70b5e42c03f96ccbe07dc1448a6e0d1787bac03449bdbfe6fe4acf803063267c51de21bac3b20b4792eaf338e58afc21772e90047f7b722c42b12a9b3ab4e84894f251357358ea87d439cac5933a3177d7b3918b7245ae8ecf82c5accb9ed4c567cbbf56c6741cd0f078f302144100a8a60023352b271392ada220828847812051baf5080403b820728a3d0ca83b0a92f3432b331fe42b9b134c2875a4511a2908ad92a8c6044358f47ccb3acf04aa8060894efd9fe2eab076938d9618c0db81521f25b1122a5bbfb1fd9be2224be7c19a317a394734e9752ca3fb2e55401c7b2853fa594cad0a7921e69162d28a594fe8e2c5a68f933ee28e50ebd82e3e29c32f739e5e4409da5e72c2b156aa5d20e16417d5049775a330b28add635ebce6c6975e70bb52b66a360b663e2459bcd355ba8d764f963acf5ea76405ad828d88c1cd42be4c09611a6bef340b5cd85f310fe476c9f14f5ba598508accdd73245bde29cd63e87bdc901ecc908435dde2f46184aadb61df5dafe289f9f8dd24fb4d2ba5377228c3f4b10b4fcb0ee4c152c17a1da81961f3f74777719a9bf6f0f43090e8c2db6944c40c210404f3a8004a3261b17028c5962b36cf933f26ba490fb8e5eecf934ce369e01466cfbcbd9ae71179257c79438afc43e96e8ba6393308cc0634993306456a6ef8e4dc2b0426b12860d3817f4eab91d9b8401831d82467408313333586fba39948bcb2f997841c1cd6c54f1400ab14d3f6b290c61d357c56ce8b3bc0bf81205a64d63c0d8ee6f8304bc1597e845b9820940ec1d4c7841ec490f9b3ecb93a14dafd8f4639a90840b9bc26ee80ca54ebc20869652c3804182ed8faaf4573bb1094048f240172f248ef861ce7c20c44f6c0540e8e20929a06a75c2e909b399eddf75378e956872226329e30fb29892238410f401206c200062a7490d624de400f61a42a72461091ed0b1fdb910684eb9c305112260c1911220f0004c0f9844e1451394f801c286d6166c9a1363ce1a44de92384d28dafe5838e1043ddcd8fe5b77e338ee4d45c04c706cfa9aeee10ba24d996cfa186b1fa47c42121f9bfec5f4b5bbe083938d9cad771a1965b149149cd8be032858b175133acc1b90cb046d4b7a364dc2a60913149bbeaa09143eb0e90de82fd971d3b7c15b1b90b3e4533a9ffe6a3e1147700981c809324872d9d08f992d032c71c1e3430f47457cc086fe8ccb54166c4a84c3834daf0dadf5093adc80f6945c6c7fea3231542f4849185102156c71841348285e4d32d6d121d2c84d3f2d031de639bfed4da62085ed79139ac1856d691fa563a16fec18f3610950e8cc854d8146fd80045adfe0eef800bb4a681b3bc67c280289fe1d633d7ca144b7ec18eba107d5073d63c7580f54dc20746ac7580f4eece8bb63ac87268ab4ca8eb11e84d8f26b09346ac7184ed3ae39d04c07c0d13c160f65450ce7b5b7a436283b365132da74c7184e921dae8496b8e812ce806d39e727b34fc97df540a491cf7d75e703b5082037f654bd228dfcfa2a2772f0ad4598fa218a89ba1369e6e720514cecfad36325a143fcfab6b7b9e932ce1d3b2037f68ded534a29650f154cb0e3cfeee6c89e9cf41cb30a111a63cbd1287bb06082fc9cb7f54498fad963f9e895ee0b8b6cee5784cc223bab5ef5721cf7e1baf5ececfadebd7063e7fa5bcf6f48644fe54484a95f3b203736f7a95e11a6be0c2868faea86e4b0a4ea9583e3ad67d7bf4666b6cb1ed9043b7edd893437f68d19300d0b18138ce9eeb8bb4b9fb12655a5eae452c0c12bab4c02deaa49cee2e1645f1eb2ea64cbf80bbd6d1514e88b7373ae4e052a4a6aaa5a134eba459787b5d65aae365d9cbae4f76b93c57199baefdb1cdb74ff5aebb3ef5f6b81f6fd6b83f6fd6b6d68ad52689bb6911dac92cb684e5ca62e3d6172994e069be432614db2d65a5b6d5191b5d6da1a46a124aed70fcc6524101f970979586badf5ee86ab4bf5098c890aa19bf38209c624a59430261813ce4f52558a34d64984394294b14988e07dab94b4ef47abe4e0fdd02aedfb35c44083552262957ec04388c6981d9418aba6d6353756298845020e58562eab6a8355b248f828fb2a7b018b3878df06073d09d4c063c65b36c4dc9d193f709143f9a4b388fd30cee20c0797a91bc879406c81b148a4e1b1bd85edfe2bc4d62a04400ccef2973afe433208f81213e3d196d2062273f52c380b7f828b2edc9c534a39e5872cf187484ae58c6134e79c73ce5982d99e4f24ca39e78c2f83c04517e9b1b61074c8d23284971897cdb9471da42b436a6da508d177018b68e1b0a1cf23c9a63f23b3a1319fa64d636c1a2381934de957e94d6cfa3aba931838db1f6fa7bea2abed9556efb4bb9d77cbe668a4d2e9a4f7341fb569e744a398be4e0b7d5f267bc8edfe12efb0babeba66eba29ea09898d0383ac7351297d13b9ae78bd8aaae885a8a3400d8aea49a20b6f0647955411d7296bfee99adfae32c7f07726dd7afedef55a8ba1c4c525f5de8b0166d7fd412ea098ac965e4761a1a5bde97f288beed822060eb82705d90dc054a2cd9f627ca75280c4561140885d2e17490f80e154a6ae2f94112b2dc8f0c546bc24938399cce9b0e122aa4c3711ce7511805a241da4c9a4d94c7da9f259ed9349366114e8ea669da57431445793be28cb4e6969a388ef394d49ff5396edab8a784bea41f33836262ba17ea8ec1f40748bdf4c7723bf20a23d0db0c9a2d39342497182151a11e1da4d993a4a963776aa532e85cd775a2b4f484c92525429a49bc63d32411278776ec8842888bb3453fdc61db21a7e764d780fa710725f30b71d8e980c4ec3967984f43006c58d8f28b9860da37f2674743006cea4baf6508fabe0edb3ee791fa29bcc0965ffde2648514d83fdf7aa17c6d7f61620743ed3dcea8757e2b42eab65f31176d38ebc927d2a5c44b3c4dd271ac74ed7b847dfd0b8dd8aa237176f070989fecb19f0e09b036f4f3fb2d41d0a1ec41d2838383452e63af953c91c6ed8e9438c258230ecac051c2271ac16187d9aab375024f9575dfc600847d91d8f7579149bee46b3557ab1d2e85f1b892bc54ba192cf7cec3dd689f10eb3a5c92ca286508052767c60e1b8834323205a979c91f09731e7fe2421234446464748434537222e453f4235b923484ce12edb128ae93ea6eba4f884cd2a825414243442724495caf1f5837048e37e1e4e4a219423f8a6a66cc0001525151d1e65af20a23d03fa7abc5fa4c32a7aba5654e99cb5c6973bd09c7ee40611d4f761dcea70d4a4489dc5d4d2e13cad7be46f408a932c9d7937defeb8aa254c95b74e9c97dcae43238272f7a3e7838ebfa4c325ff7c59544e727692a2db97f29cebe1f3a0fed813992cf809008f914fdc8928ab664caf6f3b79229cc6542d0a7c795e4953f18e8b62b9a4371a80e454277b413a5a527791e19f94fbb130341cebe3f7b5c66c90c9a4273c8a7b561b5191e366cc49028d92884ec9c368a28843657afc5f354431447ddd26c4d9bfb9269b6e8ce64dd28883840ffc481fa2822f59ba80f4f96fdd3477ba6ce4cdd5ff1195222f75675f9cb7fa28079ab86cd7d0f92edfbbec4c8e6c6785efb76fbc658088c5ce69312519c268ce49214b2a913c5be4f673dfb56a07de913faf7e70eed8911a18216f6a57a473ae1e22a20b77c1943c14e0c05ae23702e1523942646588a3551a22226c44eec0339d5052e0e063530c2d5841d222cb1450d585c21050e149ed00029941fce774ae94b2a25a594522ae9a7ec139df6e6e05e9859b4f8359ea5a723890ef1dec06c6937b357769fb2f4b48391baca4154d6d20bb7a3ad836f9654762f6fed1e47a5b72224945bdb7245e5607c906e8e66233334567b929ff472d8f6eff8b9e440b78c2c3d1d27d02a2a54c5bf6df3208f4cdfa498d441153965d09ff91863aa684a6541b1b4becb9ca9ab598e80634e5bd40ee68e728faa4285c94a45e76471306bdb7c9608137fd6fa54a334ce981dffcec9e1eda4a51069f936c61823cb8e586b7c531a6f4f68f9f67d075eed185353521146e357e5941bcc39e704276bc6d8e230be78b2685db99691a58c2fff6d506a24ca36a52eefa0a57ac72c290b1256a7156acf2f2cb25d98829b6103280e4eac4aec7c71304eea39adb4ce3fb2679d72e7307398d33b202ddf76a794b2ac329eb5e2ab699ec706acb6593beafe4dcf5d9e6207630e36f49f2f37ddb26b809eac9843ddf202732bc1c07d6dc78e08c5c121229d4814b2b91f9e2cb9a7911c53a2b375f0afc93d8772d71d1a89a18068ebe03bff912da58c99db3afbc9bd92c3b17cc1f205cb17338c780181a0a50d275afeb3741967e7e69c1166a35acd338c78015ddede9badca8a1863d4e89cf4c374cb2c3fd0f257734eea59c5828596afe59c2c322d3fc739e3e9141ed971b2e2eb9310a594524a29a5944e4a299d94523a29a574ce39294551fd4a0d1b20c8020f1778cc08a0471e40cd0d8f17e82c02003d5abe0bddcddda144cb8f19410d2a60ba9b4a5978e96ee80b39c8a9ded497ae06152af410d2a9c002b3c841a98e2c6e280ca08e1a1838971bdfd32c62a0751661a3a5c60a4b0c326808a0341090a9f7e25bd5849b210f917d7eb4f65b6ea83c7a08a58132c1c4aac61434644800a531230b154a575950054c5a831cf4a742d31dd6a0a00f81965f2b902c2a059205550011fa024d53dd0da528591009e9db4f691c3e4d7280c4122d266859a28589162428a594524a29a5b4524a69a594d24a6bad75454f3a860a4b8b0e8dc50200b2532a83638656225c5c5afe0d23b4fc2f8996ef19a102fdba1b3ae3a94ca1e7bf0d4e0041365e68ba1a2c2dd4a061a1f131e50e1fdc0a0d1e2b3e68046000b412b19a594da93200193162a80a50536504a9062cbd359b5259e97619505aa90c9b266c6e6ac040467733096000aaaa896100d5ae3fa6ee6eeaf74e684a0d9087f003e5470fe8e46e8670435f7c78214509454c34d1d2440b095a5c2d4ac826746442cb39a554125dc26dce396bad95deadd65ae79c1e81a93285ae4f29e5acb510b0d2a9c52a34348aea67acd4c8f1b9e478d99137dd1c007600a03543937d14c026efc82a4b34fe1f794583704c7783bf178196df42777359e86eecf727d0f26192d0f25feacb57a1bba973055677337f6495296e729cad934d05bb9bcaea6ab840c70c904e470e1c375c3e2038881c4010eec6e7d998dfb285e4385b9bcd7ca941356847cbb7b6a54665b9a92b420ea0c110e30c18720c39ced6b5b11e41baaffd7888214f1972c691a6bed08001586774373353a1e7eb6aa36dd1353ffaf6392b6607abee661e6006ba528921432543569942d31f92552e3355dd0dfd5e092dbfa6d489a287e448439e35a4d013d5ddccf9311d90df31a7ee66561d1ab8d32694a3286584965aa80531acd0f143bc658f4ce744b25ef8e09e40079c7346b88f020ed6b86350908e1f69e28e1f5bf2776a487ba1cc456c70b0765df71971b052207fa4f12dadb5359c748eeb3eb9e460954a0ed69ece23e2a0f46f888312c791f84e17838a2c2b71abd387baebbe107fb2c9c11aafde30537d9741b576dda7443f11aa3f39733973b022d9408752a9be7c329d784b7bda062597b999c9416e6983b7d140d3fcf3c399ddb92b897ce5e774d65eeafddb6ca07d895da7e3cc449ab8ab3f97ea3847c95cd77dd77d21f7feb98b9e9e9d6bdbcdf9b7cd431dd91cca738ceee6d4458f739e5684ecee0b79d8dd77d67efeee67ec679bbbaeebe8eeba9bce717e7c44b3f6bbb747b63ba5f453f1f09a49b4cac12a1f0718daaf75d78a87731d47123f9524beeb788ee744ad42e1406bbf525f3b48f1fb87bfec20a55f68644a29e46eacfd50a71e1ed9f27aa1f4aff41dbb287d8ed24be9bd975afa0105edf8281c68f9403bbe0472b06e7fff4209dbf188266d10e8e36082e6fef5124df5d3dc3da59f75be397dadb5d6bb7d67535dead36c3e79d2c7c198bd50f6ec882fbe1feddfeb4defc8d638cba1a0607cdff7bdb7d6effe3efd48eb77b5bbf7e2bbd5f0c8df7bef7dbd51f7f5be8f9233fca87bfad8e1231b9fb6b7db775bde3e99a4eaf0bd584aef37e4e9cada7a72ae049c8defc32d8e2d74b8daf637cbbbb80cc6f75b7921eefbad9cfef4ad70859451e29718cb9eb86326125474d9b0d0f86740f0c8b618a3260a7f617efb9eedf48dbf90878ddf3eeede76bf3db6dd6f9db5d8dac7187f8d676cef758c31fe564e7f037ebd4ff8f5c67fb2569e3c6aefdb7bf1b5f50ace7dc8731c89138de009518489bf63c02a07238d94b11ea21d63470ced10b5e547263bc67a7276ec6e861889b38de7fc7bb59f39a7f5e2be30fc55fba9bd640b13bb1c9cf3e7e3393deda76af5bee6cdc79ead80bcd2e785b8637c975981a14a58d0cb27f289ac27c041b9f40de85fe92fccef3fbba8e5e97d9fbe900779c37cbfbbdde9f4d1c1d317d2ddbd91977da29b76372794ea3eea31c6dbf6f4b79f5db71dd9d9a2de51df79210f2ebcfd6ccbcd15d4df70fafba7bf8f0ae36c6fbbfbec853aecfc288f7a973befc8ce5a0a640b38c9b6475cdbfa448b0557b71f1cd9d593d54eb733ba944be060423cb283b361ae1d23481db433d0d56c6da0fb55e7610f80fd4223263b1b77371ae3da4507a390bd298e2ef44ffadb57fb11d9e14a7dfb746f6fe4655bbabdbbb1983e7ecdc3dd8df6d6da7f216efbade4bfc1bedef95be10abd22446ffb3ac67a64fbc8ae5e98779dededa917caec51ee63778f6cee53a540b6909264f3e0da58be1cb4de911dbb58bdb85d1661e2ef99d9dac00a563eee99c98a310ec607676b03d2067cdb51fbf67b7170d6393f74d9f3231107e3e76f88833f6bfd6288350ec677428d83aa1b96693f6c9171dafeb6077e7f8f32b76ecd05da000a10c1f93f658de1039d7d0c6056b1e7c7ce4784993ef67c95b7b49e5d399d5891cfda333ab82283a2684719144f84c8307a40d6a6b287b6e34f28e87853354051745335b800bb4c08830463cf8f02a15376ac8289297c905e3f2271f0ca1c97380ede40dbafaf7d3b4cd69ddd8fe131e343076ff59375eb87ac6dbdad7d38a3b5bd7dbd691e66d1c0824d9c2cfcc9393d1593943b78abc68ed4913bd227268225547a4c9ed135415e5ea4907b3d022668062c100289165e3045271029018923946cb1440de2e3a8c5174a3fb8c0484289255828725085d10e0c063fd8c48f353448a9e7b5f1c4db46cb4d0f67b79faf9e1e643f5bcfc619ac67bb92fd2212461dc78d9c0867ba11936cdbb736c99c4bafe9f2e4bef5a346dfa9ad910a6923b4f4b494a0c5a72589121c718314162f54622ab118a30e547642584b5df7deabdd59ebbd358c42d74ae9811c2ee76ef55a77272a6724b5965626955a97a595c99c73566aa9a595894ea5505050eabca1cfa16c41bee311c64e0e4c5aedc5f71a1109392082dad780352f060467666666348c671c802311d6b41122105bdb3b2c76019bc1b40da5031b9773b77aadbbd329664b226410613c21a2544654f8564b5133b3a53dc89acd6276913881b87d928820b6c730b6e3e87faba573a788ffea255d71e653ce96c47a656172b6f396b008e3afd281961f4a9d4f3a954aa1a0a0681494f51d55137f8ed2bff7a6a8b88d834a13197ab67098ac6de31061fc517ed02a2b1931eecf2be4fefc94bb9ae171fb919146954263e512f90fdcc889600e9bf19ad2c1306f50a91ce6412ee4446ee43fb829bdc2e23a3bdee34ae2632d7a2bad717cc77bdce54a28d52819f7a37cc276b9e4ad6644238f91d12baafea9fe144064f93391359959e1b327008930fe33dbb92e6f3e2d3e4bb98228b6041741b12584105b42c6719e394ec671db0df7c140573a6722b097ed6678d595ce9948ce32996c3669d048a24163c64a45460cd50a058aa8525052daa24eddcd0a2eb2b282b19deeb90d179362443a75994bda8a34e93ecea3fd200115f1fcf0d49b648b2a109d49d279bc27c979a44c4a4a72c2398b2563b190787e7854484a42429a618c55d8ee6b4a2aa82093c966ce79d780faab4f4f96f5d8d1b0c3264e96fde493b95711c6beec5e486d1c61ec47a30d673d8ae3600e9c23745ab4ced62948c226eb255dd207a967cb106cebf98fc31c286640c7589fdba874ccd8cb6a142aa2010000410093160000200c0a074442b13449d244cfb50314000c719c54544c32954623390ea3408ac2200c52c600020821c818c0901aa2aa00cd69e9338a5aa6d79fd4f16dd6b0f552cfa21c49367b0edbf7e5d7a205ed0d8690ce98b1137e686f216a6fed0641da55a363dadb947e674325ea9d26e80e45e8390514c0d5adeb09a43a6e4a121976c196ee59f6043ad2e8085b8281d1e83321399a06932d7c187044e327189f045cf11a9b8cdb1a903ac0748330f42df03514a91be4b781d27eb0f07520ba653fcfc6b0f56408402957da40c8b703f2cac7e55c951cde72bffe37ae996294aeff3a7dd76a80b5f17fb9d29ee9dca6082807c403369fa2d6ab63c8a1850a10cdfdd09c3328acee62a5d97bb95848d89a05776cd5807b52008763e93e522eea0dad6ea81ed89b6d9980509b075f46a864255b6a782dc89217826bff178486da7e853613cbe40ceb75f33cd39ae3537f3f395b2b216b2ee006cdfb7d1822c282dc350f45b9faa140e46b5b18d64170b7983e53d92e35c4196c5712bafd8acb72508d3c6d66312da383b6e1b6ce858efcf3f811ee2677c56754df2926d076a97b2ce50161336af98216b829a04256e7ab1c1d3bb9aff223678297c0948b9db4a7541aa57d8a43204b1b599c4810171ec5179ec8d7f9c55ffea7d99d776e729adfc827728239cfccc8535439eca3bde3c0052419fbcb005ee04452c4e104c43ef7eb7b3d7782076e7035a4424a63ef346d0ea07f3cf99e81730a119c340faf15287623a36c83aa174e313269a4973e0d08b04d32e35943831a560a3a8d6e3d93d0a96f969c7035bab06c81d5929a03e86d4dd5b4003b977962b65abcaac3e3f51310541ef1c8b66c675161c507f50a4094a110a19be312570dfc585a8858961616ce8dfae95e766793650923259eeb8439747531c6a04e9a1a94b55400f8a94f2b7465d8eb9033cb132c3e0417ef7ec5c3eae7105ce8ad39a705d7578fea6559aa1ce598ce60a10be742f59f5c64069b50a982105bb28ec5579b110d3715200724042d3e7e0ca876eed994865d195d006870579d9be61d483fec06d255120eab0c18618ed6592c8b00af1b7da8981b0bf1b05e7141b6a22ce10240ea8b491e48c3694b05c49a7cb79c7964d4c68a1812da6e0a97ada6a082ace20d77b1d620b05a27884918c166abd2e9026975f5c94722045f4ca44067c95b022d977622bc3c62f2b3ff3b50fa3ff893d9dc100d4350c1cf12368ea2af17837ba7546de7161864af7f9aa8ecee5fb16f0e77b1bc86c2b199110252bbe42112e46681d211bd8531fa581d1304d85350d17c9a3c510e7ee14bad9b5781c99fc95ee53438fbccfcb58ac6022bb99954f409bb2209b6da25ab4b36d0db6081d102621f0e468a3e38232d15de398c70e4b169ba3276dfb114e416ade057e9f8b55e8fdb6bae0afde5052b2957d3dd0e726457132a19acdb027686fd8869ddbd8f467b18264431de943df1f38707b25408e0906e31811bd84b0ebdcf648381c9010e68919e9ff819ddca0d34f0fa59eefdfc792f342485369e833099613f82c1309331442f5a34bf73dca4d3b90d8df6f4b16b4330106959b75f7d1492f1bac454081ac4cda21ad2860c294e5b45009d4e660caac8b111d7ad7d0650ae99b5f984b41837147feaa0c288814e5df0f459f70d3d29c4ebb142a804dc751216895019f1002fe9860e0d3bc2bcf7ea092014b8c5d73b5e3951c87a4ee7131fcb70f02a33fb799f84ba6c5149ac300f0ccd358c476e01ba7cfc0ab9115a171b6ea9179c49218180de6c0d7a7a3f04fa426047a60442ad22f403fa8c268f83219f820e239740bc99b92ce8e558e5f1b32c0f155d1f829d40925ee4721335f3bca262d54205dc7c1a3415286807da756a0910c88e60ae1f61d455cf36e58adad33676dcc4220ecd2b71418cae861c1d751650f751849af044abd858d6c52e0df872b022af74941198ee2e0e613460eb4e43574d434cb5ccb2d79cd12e04b5de7e4892fd0c46dbb8380969899a32e497c1c1de610cf33ad68fc369dd424d708f5dec6841ed316a470a1b0c3b532f9211244f1984e081359cffd0ec78c602f241711619eb5ddafecee74eac116e2e764b95cead12547ec3619fa12adabce80e812241d161b8362288867a0f78893b6f0e7158f223001d36585204a77b5a4f12b2d843b423dd96ec3581c5928703e9fb67e20ed7cbcba304a92039cc0bc3043729dfa042fb8192f8ee66152305d26dd43d96cf077c6cc668b38fe96a600b9c7230763698c18ab688002af4e18917adf78b7d8747b940e32fd8e7eb6b3bdce0fefa2dd703ad1b0a9a9b003ca783118f34710656fc3747b07978d46d90a15cab1bf24c3e4fe019da162fbc0f34fe1e5009d2995e0787a65466ca92ed25ad582bb052691aaceb2e03704d50ab04c406e536894209df2a7387e2f705d4acefb9906625d8ae392add8fb9cda6549cd839848393874fd4cf56a829e4124a8307c1381cac580478574179c75830a662117106ca9232fa6e9ed743235062fb40a5245ad7ffdbe12c58befd80a0c130e7818b7e828b731692d0a03c1648fd29eb0c006509808c78a1703455d4ebe4ba3baf393cc2bc9d9eb0e6d5c75e1b6d751c846f7026f2312551869d5bb302a5708c333458335be3b2a77b9129ca2a03b52efdff05c135defa3336a22f1c25049a2cd78c0e87ed2d9bac43c79615abc0d97b493645db7852cfb9501e4f3c2a3e56651d1ca21a8af016c6a4543223d446f4d7b46432681a2f433a4a04b95040c79886c329479f6ca064c4a26c3d5c5885624b56567df0ce1110dc1f5a88ac461f0440f7ea8bd6b80f68668984a0c46dad9fa1cd5828f6c3684dcce1e62fe402230b1a46538b4be53bd44307cdff8c51e3f7aeab088b4dbbb74b0a830b7258a784a680a0768faa1e178b7801d99fcd786b7efad645f4f8f3dba63a9afa978f534e012d3af5f16ab3161ba6883992f8d90ca1ef8a7336a8eaa8ee34e5e1025e11886a34e57cc9808e2678cfb922e27200f9ac981171ef5bb4e0176dcb74677ab6fbb0ed9645cb3d9d1ecaa4915dda345f920f505a621f023bc7b43513cd75ef71eed5ddcc356386e44a85cd24f0eff173ae07b31d07d11664a77abc821c9cf74de711fb43862d6f9147403d6b331cef9620d050b25e2ed8ff4c9a54d77b352c183d2b680835b7e711488c32615763ea45c90c440851a8d96726b51e5f46f8d9829ae5438d63c11969060c328c1f7f8e4da7e7cac67c3d1558ef02e13dc25aa62654a1f06a9a46418b81c5535864d3b40d413fee6028ff39f755e84821ef573a0e8e115d4172097bfb38757291e8567a21e41126b96d64043247db9587864e55535eccce92eb95145774efe018bc303134d1d9458d49838d6c5acb5617d5522566ace2591c5d412e05c538924a83b551722bcfa5dfe87ebfb0e046e7a4f55ad338545afdde3714be82d508ebc889b6033c5e01f886e094153b925ee80197cae6dce8cd0481d5447a5a5ef51f3d90aca88be3c8ccf9a43565c45a217367e8261f63512869dbcf8b20cc664851b714e4117f02209462ae2865e228c42e40c651c4510f63231042494750c04b6b6fa57c262e823063318c1ec0213a2e3a4bfc43f02ddb419041183589b91d15e1a5f63b0aff46d9e1c042bc254055241fc7472b71bde7f57de8ec9f481d5846b2ad2fd71584c4af125a92236b6f3e30108a63c6675df3505ce59c8b2adefc4e19bf67171487cc448d12bde53153f54a1c3f56dae769616cb3b06cb107adf0663a9b885a6b2ad1e8442701b5bac8ad7dea7840cce6b03b62d066cfee2a4087db4cb03f72ab3c553c2f5854e1b3be89358b6ddbdd4f8d972aab73eb6f06c74103e2eadcadad896b438c5c02ed78a38ae21af4aa72d9d82ea82456ea788314fe58709931430c2fda313bb7fca61a00f6d9c7ca1c844657c6231c9f270e70b1a755e600605b7ee6f8610a3ccd5183798b195b7300a799369b0cb4d9bb3ab621186bf6f350d83721dad31767276842ab9a91088f940dca6e0c73c90df758c2681f92e04069e4f6738b36da4180b72cf1a161f7d7b9c04b4d66662f41c5f98bbfe8d51d2edb0fd8f7501b67f6469211c7774acc9542a5830af7a027ee1d2814a6859d744e18cdbe744d2bb3a6ceadf099d1f674ef40155c841db89624d20dd4b5f6c17ff61466c58acc5b31b5a18238de8a345110cd866ab2bed9fbc43255a34d754173e101454d4957ee141e121cd53ddbeea801197ed5437a5b6ecb985c7c775968078ed9a7cabdf0ddfdcce4bcdf76e26b8aa8a74f5bd6544fd3668fca72fd782ecf31e2997301168d22fa3ccf733a268f3d30934bcbc8ae9629942a0b7e90c9241b0cf9801c019864434da3130b8a748fdc14a433c74c8567ebbb646fae312bd4fe46cfab813da5468384fcf0f80ed5fde580041b3335ac3804bef65706a2dbaea756a2bf163505c81814d0eca79829db2c180cf9935d4db4407d8c7817db7d1a3d3637d29de04ec15e8a92bd832ffd2cc407afded31b2e052e19ac442b61628f649d6066e5ad0f050ddea4e825de08b0a2a22721d8e3c7755723cc3f398b7849321536d91b16e70ee12c5464b9917dbed3b9f1bf5b64ef1cabb9f6f528f31034588bab2c108678e513c70df5b021cdb72a248e652eaa8521d19c1607ecc0d7a3c20c456331c08e94d0ff1e42a65a7acadb599612f8f5e89e3166e01d1de20a32f6188c83351c0bc869e54ab03f9acb0ef65982a381895c25bbab5b10bbb0d775ba1c843fe93f6a26234f9d0c76e2f68ed093330610526cada863aa7be9a132a6ef90baa7e2db6954a53419f6028c12a926039cfa2d7ccfd1822d4533e804233eaa7f7a928af16f069ca44f9421eafa2dd8ae10bad0395201f2e1d8e80242a73eb60dc9c761a8a3038e1727ed89e449de7ac3e85bf09f737255aaa20f9562fda9bdf9110d326bec453c1daf45c05164e2d6efaa5b9e7b92da66e2c8e46da240e1472bb0d0c66869f6a2d1688f773191ac40fd1d4dd74f36fc54e1648ce0b2443646ae2e01e0514dc9c46666a9391255f380c2c62cb188c701e721bbca3233b7c06786df15c7552ce2ad0d14399ef63d9dd2d00fb02926333204948ac4dac5f4dff9edadb6dca323951bc55b4554c39fdbf7404d6906f02e16f405ac3e7c0e8f38f06e857946722c3bac4fdd0f292735c7cd7e3478e922bfb5aece292d262da5d364408d4c4b875d8f827dd596f181fce5e1783e24c0dc7658c6be8f0db914cbf87d9230fe1210ca65df3e4e549873a66c8750b73f094a2829793ea7726d40a40bbc02e137837b98e2aab9d1287a53c3bf6845edd3b555a3b3698fb1df797c4cc1d50d7636cb6a04e17b74d38818219fdab9395b106700ac20f281f8eb03c75f8ee7649558ec4e2be50222e66ff4a62a96cb3277f68872cf426da1435324561d137e0d7c2131c2e85af211d0efef46e3fca26110131f82be61543da8ee01f4aac8a4b17b152381d1b3325a61f30c825ddfb0139a27a48240ae3df4be609d497785dd5acc3a78face49006ca6a9b18a10d5ac9bb0fb91bbef1f806617a6224689c2122f358039aae4b48fe8f0aadeff97890e2e72c4c1bc1e5a1e9774aaf6f0aaca61becd5411e3f256aee9c4b25658bb9fd90fb1f1ba3e2d61f9d210d890789b825435c66b44af23f9593a0f6512ef8fc5e01e933ec09789c1e0e5d72bf353ea354323136acbd32d1c630699b0b6231e937552d4c4438e0c644a7b150be128f7e0b9bf6de142d1646d6c1f0a8bee0ac41cd3d66d5e4a089d07b021e46802d4634bc36c6f54905fb00bce023eea933e56ef879c1c51734415af25446bb60920faed93ebb5d2aa2eeeb7bf7dfa36f42f0443b044c86238696996f1e518107f3c73d6988fafa11bd70c6001a4e85af40c90e04cc0f8512414142d670478d7f05f0bbe89e176f91ff6ba82e8f801ef568b14eaead536b7f29b60e9a3ca2231c120dabd0907033c9b5c5c3fbcb1919983b5c113f0c19f45d3cde6965fa86abf89e2f630c03603e7612609ab214888d5eccf9a51623bac8bc59ba13bd6da111e4fae43b3304856dacd554198099f6cb63b9e9dcc993dbc36e273296745a55b564ae47b593ba523dbfb2ca2626fb19bbb29a3c4079bb26fb8ddcab429a9361c9942f8a35520d558fe515a760414bcceed3b28a67e095a1d4a025893a3461f90f6c8632820ad183c9b5ddbb65d4d26a1a41cca55ef0d7384cdaa378625877e89660e4be64609337f8c0aa26e6bb2bae16ee6fda462a7ac0b3b7b396856de1c92b68bc0da87e16071a6778cd07c26271badb86d32a2fd7e52d88243b2bf133e8412c2ee327201df9e65af06ade8b744844f7d7a4f0d9d36238a945284acbd0479bf780653bdb09e9a9777541fd1b8d62b8d6daa81574a5a8b31f1137443cc76b0240fea8fbda8319039a03d900590d14685a908e816d2a418e187bdb901cc940cf9b904b072293c9cfa25d659c7632ef2ba790af144cc25cc814ca52f074c62b64ffd722826d3f23c92dbb66e495d95b589da069656c5491691868df491bddcefe0efae208cb7eabca97bbe24f74ecd4a7d2396800713f73cc263a583c01b3a9b5a83b3b082ea6f9fc11b4540a8c6947868cdbaf7758dadf33e234fc1a3395f4cf68ac2e51ba58828ad9dac00e44860e021ad9f1be3028b5684c9be401926f7bdbbd2b8f09277c62b5feae5777caae6d4077eaa3d0875ac61caa15e41a656e89883600899fc58ae720447fe0caa982e748b422fe3d088ac0e020e1c0539fb0bd0036c9a7c2010dcb21d43eed1a4b49e40d0b5d9852054b0c83772ba5c5be0c739b0f065f0302fc92501f857219324bf58032c10bf7e404b24751178332b236807fef16070ff148275281cf9ffcf601968090fa9f24a57c433a4d93140d5adc0edd39d41c3e5743657990ec29209e5c9175427b5f7536cacfca3e26fd3eb413a009c53899ccc4b88ed3e8833e86cc3f21355ceb36a034989f5bdfb84cffcbb14067d82d443a67ba4bf198a18ef07417bc6d6f77b1838331508affe56d4d688fce1207e0b5e23c68425cf7b154bbda9aad03e54d3165b05c09dca9b44609ee1120e41f961453f55818668666c5797a988f06ebd0ca2452310ef4544e00166d8383e4205cdfb5366b6fc871d39e53947cd03ab69ea508a83609eb7ed1e51eb36baa1e686ed504e540af1daa0bf7107f156104e6e598c035b12755031008121eea2e541696270c501555068e3f03f36494dcacc269cade7a023f2f092e6248280b924048c305e68c427d4539f0b3a210f8f0216098d412b994e4eb7f4a4975d337960b034062594f0e17289c6bcd3f33ac5b80af61307941ac5137ae1cd7ed253e9d6a07c902ae40d866e4d19d42e970776bb05a441ed0879d437e5ffdac3e3566f71d5538b009a0e4a65c32feaf8770c4129585c3a3b90d88b442c8b5b865be4ed2e15263e14d8456c6caceb5b822e03e94567db0091127859887d44257536abac44555f2daa336f7d6aca120715c1fa5234b2e490a92ed73efb122647f0375d436cda0ad23983a6d87271aae12f1d2fa34a358f058f444e42263eecc5c0b3fe6852aecb7bc80ec3e481415dde847e916747f242eebdc7c2c4d6e5ccf03e05a1d3269ac214168044c82590312840a7db7370120c944d0d1056401d46fabac1076bc30e0198a74741a2f286a9d116b394c89767a70d6e23049fa058cbe43433a400cca9ba575b404919d508c7938de5f0fae290d850c441d1a8f623d9d5f0ceaf2ed6e5b493d1f815de28fd699d1425c87771f7ef1e2938275c85d37ee0429647fa78e7b7ed76204ccc20a29454527c81e441e3bc317a5f3fea70c44c639acbb99610181e1335d2beb87f8a5198594315dd9de35eb4a2b6766c60b8ba0988b7986ca178c5a0eee99b61c35aa2c9322ef8951c98249568f644d430c7ce8985e37ae8f9e8a6b0e8fdd3f1584c45fbf7ec8404a2a42eec073d475184a77fa91079cd1cff53eb736ad137453a15c4894e672acea0d4fd922e96a6ff62add64ca6a42be299e1dac2583303cdd713e9d3f521bc2722c505bac721d9e094490211abd9f101af2a681b49d3fbb6a6fb0502956a41173b60f8ee701645008eff501ce0ec3ed5f5b5e86d98513df66bae7ad8101493f32136705a8a78aa82be5c2ba50f3f25d63208e616b81986d8fd22b79be0182cc331796b84a1500f2c343d4843ea709196fe30083a8592212ecc20e768c4ceef4488c63fb80cb6d7677d5f1a3d1a12e50e589e5229c75f1f0624d31e183da7a6877107444f1c3b032f72bb8109f058010583c27f5306c13b5ec2d088eec3c83f5b52601994578a66f59b91eb3782f1325e7d29cc60fc09bfd48a5d9df2eb887c047285f261094844ee5021a732c38c2e45701b77ec9624f98b4053b8c48c57aa7b1e67e9d922c6226f5f149188fe4aebd6a6507405e98b1602457c8d915a205196f15f7240fb6fa983788e60249e014e9254d47f0322f54f9f01decc0b5649e5a544a5f893b643d749659eda44cf264d55ddec094cb49200e27d25d22c5220f093e1d61e95d863542410388a4aaefa4038ebef70e264916018a3f08d445cbc712ed212855e493302ee1e10e50cd65ee14c2e4972d3a07abd9fb7fd7a405c24b8e72a2a32457ccb45b4b792bb6d0f4b0f4358c245daf42cfbba70b563205e46a50049fa5d8abe07e95634cd02bd25616cd6610428181c29781e1e85985ea1984898f1fff0e974101bd2727f4d9715ceb3e950f7138a56d01cad3e7eecddc1eb5e5f89bf3227803bb645b91fd35872f8a510f7584d2229fa858cf4d3ef47ebd06eb267dde3b42db0cbfbde2f96d75728d6d31e7b40647ef23d76522a0bf3fb4e61483bb679b6e7ace0a03b1e807031f5c00c172d0f80fa05e8c4fc013417fa2dcef85cd085507fe0e2fc0caae40662647a18f9ae44c939fbfd7a1cf9e240727b1a715f63087a080ed047d75470ec09c7e2e8fedc92a271c99cf40325e151a167fa73675983ee543cc9064e0fa3025cd51b7430c01c2c6e1200aaea6439e8dacc895a9603cdd3d115f7ec21d4da5348ad83d9e0eaf2e9dc09f8d1a2900a7a72cae0b90464250fbadcf0ff8a5f2925b0df2d3e2a0f3272992bcd010b68f0508100985d6e1f2a782f0c7384e1ab837198ab6dbaa06c33d55e68027d99242b4738c3990a8787b2ec3222c33aac03209c128c1d87cc3fa0f7fd9d59762fc0961d79bd22754b5887b4ff1cc374dce596288d19ffc66cfb78d8815d6cf3a098eeacdaed5a104624ef2e1848851b1593eca8214970895dbdcda8fe64cbd261dc2404f02f098504f242805e4b502cb43c5a9da64f4e9805c1608af039e6300e360e3e784e6917afe6b5250f93f6e487507838e32bc5012e6709d1a26224177678eeb65e3f72b3b0e512ec434d1aee745276460f6cb59a31c52400bae5fa9221b70539cedb6f3486b95ebcd2b4e02015da525334a2b590640f51749fe5dd344bb351342de0109705e350ab9ea63a8d72a6540db74e828de1fbc615d848b6a7bdc5f73720f47d0780d73ace3fafe62c4e1a2e21135c41b424a71e640c8f6627741bcacc24d155cb8fe395ba370be0c2bd2977f89cefb6fbdab2117eb0282a4092f37918cfbc7befb69fdca4107e45ce23e98be721e54a1b82b843aaef0523d3b5111c1a3ed6206551c6a2319c28ec1fe47e80999c1ab4c311009780945a7e26485a410b093b844d3c4c99e9d4bd6c6aca9f5e3a76f1db9c500cb552b0bd06134e245f71d77779edc44710d75fd2e767a87e4122a75a3702bffc98044affd72d2b9c95264806a2c6e1212a45c82e0db1aa6a4b8fae8265e2c0acac7e817b892d3bf6b04e30336037e0c5bb5db1144c1364e561ad21e46a62dda0cfd9cfeac2996adb09782a15dd58331f1a9d94ad3510b2f6e7b08c3ae680a18a0c4491598b0cc96f612748468732a939218545461443a2fe90a0afc9619c740e88bd01a735c9309344eb26435fb66ebe3cc786734c55b98436b0dc57d769ea0bf3b456b2b9692ea5c03b4a13ac97a0fa8b26763eaf0fe90b41db9e600cb62e6e372c91ab2251c5448dfc1412487a1307a585d90b440c03e71e420c29c9b7d2221b3de2f7dcd24e40557d4168a164656fda2154b07847f1812e611b8ee22937759ab224d1600dd4e3920d7422a27f517b62882d1e126b86e95fdd73edb17765406c49d1516f4c41490da54db501889297f803ec4a1ce0a3d42b64e4f9462ea735156f901d368392e38ab65175bf48c7d24a533875196cc44694f5c6f65bb24104f99e72a955fc65079eaa444e2dbcce5a5f4e988524055506d1c9a280ebef687ccf0b5caa168103daada913d234c8b42dd922400663e5c5ab9f58e6a302d204b5a2734c108d0334e78c2737cb5ee1e31caa35d1ddd5718ee6c6b3b81f91a280ac874da092d61fc4d7c3529ab5fefba6e47dcdbff421d5612bc08386b1a2c59271df5988723c89563d274f99241e26f53b65e48bcd32dc98a5591f4770dbb2dc3d2a5c70b47914f8d442ca5595dbc157b4fd7c7531d130e36d809c112ab75f899c83034a2d9c44401a7ec9599e17bcf93cb799370c4763e979a00290c3d85687792e8d61a6eb7d95d10eed9a41c01c3068ae99b352040f2eb6cc905aa645a84f8cf15461b0f25f886fb38a0ba10317478a84405d05dd19eb802361e1991e67a6d579558fbe08a54ae4e8ce8277e5fa867dd7caabb5b9eb97f079bd2892940f417e571279a7d465153b0bc8edc0259c8a99b021dbcced6b844d15e5026ccd561ea065b02949e512f39a4621b420a0a771dfeb83a272741a9a155a32dab9b3c20dfe4a6b7cf902ad296500406f538c0803ac6e8b5aad26a367cf983d402a4cd6576ed5b21f222c525a2cb855a0016e4a5471e84fca686ff2d532a37d34993cf62f2a2a3fe1445649f78ed2b04514abc404a11633653ddf91ef73e1a02815b119b0d962c6ce2ab8a50efbb8be8282a2a5e036556193354071105eb636680db33d0907d8cd0f7839c17fadde5e48fe9067b7782316fa79e70531607b16713b0fd29de6758227b19a32b308080bfe996f8973b4e688231e84a214c4aa61e10125852e65d642e78f9c5505b66d448514520b5dbd9c0f2d55aa947a07ae92e661510455c35d28bcf1f052036602e4f37afe56aa8dc2d29127f664726363ce688d11cb21f1f6f52224b668a95d95a9432dcf667e801af2e936a15b7197596131e5dffd9ca571834f7dbbfbd9732a9f19efb1460c2b20b43d5e14c3eac2dfc1723c1f605a44739477084611b66d509ac3792f6fb14b0579bdce3b5851aad9e4d8fc3b7570adcbe737c30e55560806e8ac2d30ee14507a1e4a269259202828d40597b6879b3a87adff7ac61a95883cecac614f31f2a1521a385db92fe9840cd881c5edb11112b72732231df7820500c2a2619e9e2bd9791588acab390b032e59004d2d578b8802b389ff654b4748f753b80349a6dcebb86d5610d996c3579592d32a2d664318ae0e9c1dbb016b13aaaeb6ed4c044561167788b919028344c1ca6bd690d0cfd9050c168b60e0fdc3640ef66352b91d057f2654a6b656ab752eac400a75b7dd7efc4df88e4727b6f05bd3985005d45b2985f6608edd33df3934e7d163383c0a9122f1ea02026c90ddd35a73485f26a6ea44a95876121473d73e2778a73c5395a61a55bf0482b1eaaf9f0e288ff9090ea9f330f5deeb06299e4c69dab26bee1cd2338ec1dbeea93e733d184d9a6973e04661a2a2f289865b7265709af74625ea50e9838103018719b1ae06694318339ef0fbd1dace029dd7d99f218b7b2126d3d320cd60be2546798f4778c39f76b3086c9096245026e8656727886c91716d851e8c08f0580a42cf5180b3ba1a684614f77608eed3abdcb3d7b5ba56dd38b2448c6fb23769c597f354eea11ec6e772c8f3570af366a021b7e74f80c317b166a8b562ecd9ce055d76059d6bbae159c1b934d1ec4d0ff2b7d9599868b4a75a51dfaecdea0c752107fbdaaaf6b9de2cfe62c7dd5f37365d01f3ba83a0effc2a2878c7fce8980c9d0a42e9c163bc1cc763a878af28b84effd5527de65310461c9a6bc23a9645dc8574b11c4b6c892a7bcb60a92e3372fe347ea5eaf42201025d14837fbaaa6d631f0ac75b3e712e626777a7916360b9a1de7233ed4273ce9c042edc990e62cb64f9226412532448620a7eb3ff5748e15aeaf54a92e1889bed796fe6d696e036939940fdcc6986a86db42cdbea733079e8a1dc8bd575088c413b4250d1845776d94eb523c9947744d99697e915a2cf90de3dce424c82f4a6942fad3addb0d7b31a0f7bafe6547e0e3cf8e8034e569385012c9b0984b05b0eaf995e1d8eb587ec9ed6241d87d0086d6d61602ff892b52f48dbf8b7f51c707ea16e243afb05357b624904b912136d605a597ba783f3748450e15a8528d10913d10cb6cbeb3ceeba477beedec26e941272ae4cf5245abdcd68ffe97cc1a66cbc2f1c4c06b863940a2110e46d50e9e1d0ade8c382cb7f12f4ff90b432ec95e761a3c6179204d3cade8e456131eda208e43d4494a929e1276cd2900d4f844fd7cf4d27ccc4413ee73e8bd8dafc1778ab70d3ca920fbdaa0a9bd31ca91a5fde9a28282d9e1ff9ce05d88fc863364efd66c84969a149878ebeb5401f710d928acdffe4156e87fb7437cfdc3473f3d9df6a8247f0c6e42b7ce49c07f1afd9211f6a666bd839d777d333da646511c6c7644acc6fc2ee9608df2fb79b8d19b50e5830f589fafc83885df07c78fa20af9fa6d077f53e0c3e3991447799371e0275eaa1c9e149dfade3ecfa837d58fa084fd02ff84518e2a195ab53af22dbc0f8bbe9d36d95305eb560ea6b28cf714d369542a33921887642dd61afd4da2d768d3b153084a9d4f3a64c8876ce2b3ca38db0fd42448204af5b7b4f09a1a42ff5dbf1ff477ff181f7db441a2648c76e81533f65a5da971c06c49de182d6407988901d092bbf862d46551ea1050d12a061e381d15fb712d4cf6f04fda31fecc35b9f256c7c8c51b64beda1842bd8bce183148083b2917b5e183a7b20d70787ca5b356911626c4b944034effe5a362a6a67b2e9605672aa43a7141710cbc57a1e40b87d79e0d191fc6529325dac2787e59553db1e762fe7a8fca484f6c9a2ad2e1436ddf985a0084269336d41aa17072d6002daf0755a1ec45de225cc8d11b933ea2373e1a98a5ca854cb3f982f2bd3d1b4772602853079219a0675ffbd56359d9fdc0047218b99e9a614f75756307da837f4ffc9f5b36d64d77a7ca4e360cd43f51e2c47603ae2232ffe0bf3876793d1d5e3109107b3804b748ecd0323a4236f82c6f4e7c60df46af1d07185ed44b17a632b38aca4dde872856fb47e327031af4f5aceedabd23e79652b122940cb9b5f196b5e840ccc06f03b75cfc3ab34604bdc1196beded9159b8cd6b065de9a58a8e6d6d21c011fd812c8e3e356d7f5a59bd31dd37d066e32bc9da16e01cd11fc2d8ea9adade1c2750ca554b7115e08bc047018e7a220afaf7d52b79337e7c79617d33eff1c7388364376ce1dd31bbb97ee88bca47c525e5ed389b92d735b0481b4af2d44c15450307de9407c13616ee071064d824e93e6941e9882e6672c96f41e7487437c0cb7f55429924c63d424254a5ce7c4c1cf242b0dfb80d8390683e0efb830bc2750011c89a1bcc3246897e99d2e5329c9fa65b3ebef7e77c71dfdcb2c37fc8f77701df5bd09ef128c2ada451ab0ad4788d8f8e1392abc0bb114ff8ce216b760ac4f81b13f753bbe45a146e4b389e97259c405fda022e830e2addd972024817e01058f9b1cbfc18643c275e021ae3aa178601df30120048e1042ae4421c3ffbcbf6e824001d9e703b95c8c6c441047023526d12c4911963b1feed84c6e0a7f140fb5a53d04b00ed7cc4c3a51de465b423a04bfe100d37d76ae4b6ccf1af252f35bedd8125dd03f8c006a5c4663583bb1f4b564a06cf310842eaa2f6a9be896e7ab9a11f0d9fa65744786034897f36974e725fff825043af939123be066efedf62f78beb553230b582cf32f988df4e3465551dddff1c7920bafa185638c7c529480758b9d22df3fa26d2369d5c1aedf18109770f6f1d622115a8640cc6cf4befc3b6875772844f80ca1e3fc2eef97a391413eaaa948a1b3e398bfe0960c9279d89ef5b91c0c7c5ae21e9be2be005dc902247ea3f2dc22befb134c5c629d6fefa9fa6be17280288cf88ae3aabd5e0729de336200090d8b7e0b424ae1aca74105d449328bafd598882b377715308cca5937891852d1312d2a111bd2c49c2c100ee599358aefd631a7e14a5357f2f11759eed4bcb8ff5d03070720fa359700804428b7b9a982bfa19d1b04ec343197d93fa5ea9e319556c078a78c73976f708c8d9ad531b8e4d4e9ba19b724a14a4ee1d43a35f8a2763b03f7500a851cbbe47cb1b2808b286d7323558e376db39d9b159e6180f209797642596c4f87da561220d691a373ce1279dfb41df028a2334d42dca6648c951656d9d39d00988d541e42ca470fd3e9ae63d55266d4a22f693811fd3bb89e4b257b9a6a14ab761254157ea34fdfe0856968318ceaaffc6a83b2562fc449b074810268a2e7571ba820b43d3295ad918660ca55420999366071311a2e04a4a6564e90ffdb38420c5b36f8cb2e1402e04ec48b622f51da5ff3805f324d18572ef71276c4d3fff32d4384c5af9d65cf2401da3907540c500ae2127cac1f820376b4880bef42dac7c49c7676cba9e15138a934f4277fbca0794065c3ca8efd8ba1e051607205dbb8fabd9b5f9137a3ff3790bf83c96ffdb0e3843f5c76401001ee5925dcf1b1a40ae50914eef9be2f191c74a49cd16f31be1bc88dc673840dde814c6f7fd2c275abb9c0e584e0a5a28b12a88ff285a87bb12d1d42a50caf125cb5427fcf2144af83bdb4201555f8b7e66292dccfb98496bdcd4eea908a783c520357458a264c71353bc45eb97ec0c0db46f952c825918edcd9722615b0e6f336257921147177b42a76437652c25bc46899e198019302701caa812755ae2d0eeac049352e396efa3b68c777ef3049700bc7bd1a3869d93625689f7442a0f35d0eb294a9d491f217ce3bb99ef9e829862f0d326b4bf005f9e1207f770bf8fe2e17e38cecb6610461e08f5d401c6cb52fcf0707502e08874ecef44c9410f9510a3ac63d4c6a3688d28fb40c79fa16e26cc9fe706d34793cbdce3e970a765b875ec6c1eb4151fbdd4b905e3901e766a4ca451b9ae25134386031746532b60fd195c119c5f70d2883aa2356362a44d64dcdd30f18d73ffc54eec14e7ceebb23e008bbc1d452aa0be0c17a4ad5022d7cdafdec3f199409b6126722515169c5a5904d77cb33a396f923061ab465f118a07767adbc8a2facd7e2ee3d26c23f6f9fc584a137e31409a4a8107bd13c2d088871ade4bd43ebe57739063dc5d6da9c0ee8125110b74534c3e9b41d747350628b60204b838866f5e8c437ca5726ca2be63742a7e9537ea03b2574a883c2e292a9df95fc9711b0e7ea1aeee6e1a7df08dd7693e5e1bb56399bdabfbd8d2cf057754e729728545fb6394265d57c1e28c6eb14894187bc73e3bfe2dcec1c64936a0606fce9569e51a4d26fc4054ce8ad6c6a7addf0d0395d3bb69be5545b2711e4fd4cbe004531529975071230a193e49cfc2650dea2373c78afdb10df78958feddc1cdae41fe0365c1044b509dea3d3bf448ce8e87aa619f40a7e83721590dfb72847fd5618111a150a19e371db2fc7cc2ca38a2023d32a818d42468d1bb9266e78baf9660ee4c463992c3735fcb506387851c8c2327918e06fdf658cd9bec82f0e5c02c679b68e41d392ef2f964ddfd3980f792ab8e2bc2898737ee02d2243df3f312d008cdce2c1f894e4f5ece93ce375be7b7a197849bc21982e62534d8651a94f7057bab00be5b2e4c8e22217b062b8573c18a89a2ce01537ec4fd9619e96ce04089961dc381c294a6e71d700328655ea282ce183d55bda3e54fb2a9a9095fb02d8acae8404e93d3e13d67007ac5379bf4ee96448848831516aed7bc385051dd7b7810af0e451f03e4b5aa079d8bd9a79b3f4d7d728b3a7ff6e2779eafaf20acdbd5fd47afeab1b40501bf8be0818a338f22dc5d07ca44526225564fd53da70341edf3a956c4651986fb67acd7445a9c054b1f1857955b9d424f37f1f7afad66d7bc9926d384bb4b4f905b5175be811467a5dcbb6d622ff78fd40a06c1e64651fcda7eb33b4723a9e097da2ae1acac23cf07409f52644aa4ff73d41f5a5264239de8d7f8b4d9ab94ae901ce181b974c314f4d9c5b628f3907c66398828e102f91e7c1ba34ecf990d03b77a8f2ff845be7296b13858dfc4283e7e297c8d71615c0a52342867d5e2bbb848d918c8d9dcac7a5a044b5a6d88e95d04dc3c7851f4d814e5d7d8b590ff1bf8a667428b972281625e984722f51b46cc599133eed28ebb270d738c4b25aed6a6721dab1d8949bac4872691cb0567b3f24a7577a8aff4652e36645c3324fd18370971b319b5b52e5e438b5416d7d60f3686c6b4681ff0fd046f99ad40d8ebe67e8865df58813aa4f31e921d6f176d2e12ca35ce8274e3987e85bbc47a32d81739e65cc21a8012cd15a60566fd346595502e61d3a5a314328de94a23da99c77555503090ef69983ac22377aa06aae0eb8362ab314d08688354c2717528c65fb7821154596f60334eff25f9ae53f5712a5c532df9eb332b74e793ea8bb5901d9935217a13d985156a1858e482c3500270702a427f24a0e938798a65b71fe42475a20add0ea89582b2ffc774c65347f2b48c61eaf139e9dcad6b2050bfdd3b3575921d39d2ea284e79eaa1fd9fd4ce16b615cb2a89c337270c3789c206ec33be23265a943273c7d29d0d47cfdbe7d68f284478bcd6df7f56d193f703294b7551a2779f97dae46289f03591619abbf89dcba2e9d9dfdf44eef18ea16b177859932168e0561173e5ba0745c84d484eca94bbbf45c35059d26578c24a06996096e20198fa3bb11d0f9807a5534fe9d2e29aad9dcea8f3710f41edf827095ab78330a6da67b91e42290bd39709c2e98d42af58253ace424fbb0859b9477a8a3e553f1eac99dbc4fe85595eb04ebce10b123cfb5ee7180707b19235bd362a3503cb1823fa2909d54f7ef261939b77a1ba1528a3c2b65b9c212b73a396ce8a13d5c25c244a2558836140123bf69512ade38439a77b8690759fab032d78c823ce428a28f0f896e0baaa706dc8f4f88c9e5ea9dc4f7a0732851104129de860100111f46cf2322bd03f11f0e351062c8f9e2ace6fedda79ef682a2c6def336852e8d5b4546a87aa9041896f71ee866ebeb6bf49ad87026d0f1e833ac45ee7f17e5a43539d85c5ad6f0630a21ae7cfa0abd42821f54b35fc890a2ae8fc6cc88b68bf169895aa344a2ab0ed0bff7bd56fb00ba637698449bc7bc91cd047285ab531f25abdf223eb79cdbd6647aa2d087de6654e805df9b1322a3a8d23c3f033250e83f45e1bbffe75b10b89b1286fd41e020ea883a75a2901fec9a70a2adea9c043d3019906877c44a1182c9406ce071cada5961400bc1d12b8db941d723e44de3ba54718d37074016d3403b1f9c344faf8c061790057895602f6a80310a84c9cebf6af548a404ef1fa29f6a2d5175ee0aef45811dc5223edf5c2336efc031ad5d502bc9d027e2745a3d26a1eb38f57d7c9e912a9b327369336d21acdd7920fcc9c5565015f4173caa0ab465a2fc59983e01a5a4336c21255571bb96aaa031b0882bf7d052884a6f8a1f5b8b3bb52b7b8b7475d0ef669beb1f6185ce8fe9ef6188429d1b59dfd7d6162710275d3f90fc37be76c0a454a775a1051e0825d6754f5370caef43889eac33266456db911b71fa58f3451361aa9775e83cbb0cc3ea087199f242a69de57d46ee4af88480930abe1c19efe1751e61df31af850ed582d5ac0efa88ba40969bb5196e5d02cd6746248db2304f64d2f44503d8ac95235da6682f70f2645a48cb30eeb86f2c7c5780cae80d2dd5ee548c921012717b035ea8bf48cf63068523ba8b5bf461045d1950e7166b45b4ff377a75ea60537983996d81aedcb2c14e739a771330e4266bec98268c5a0ad6277bd5841367a85b5dc87980f9d66b0f6d5941bb9cb50e4e53f140e40e715fafc3ebc96b72752c174b8843ffe74dd7ef31d3b5b4475c7ec7caa7ca6c9a703005a9312d9e9e0c7e56485b7deb62c4d5b95ebdc2aa9180377f6e250f6cbf44e14b36e93884e0e656a72244fe62d956150ce40d5bd55733f7b56fa6a7985e82dd772fa35b6eb906854cb7f8a2c0e0bacfa26cb34bc62ce9a7fd30e2d3025e18e91356e44f7bcaeb445b03171451d20fe7b0f5947cefe330e3a7ce5a4e1e1206a8805380a1c70bfa24be270e1eaa1f6d87b0873cb444114e3fc93f4454e9246d8fba564e4fafd7f15df1e11aeac17a48de07d09bfbb37be0faaad1aa04199f7afe6d805d20912d66cdc72d6b3a55d644585fc5e1cf60438d7aed2e375a3c30d71de41bf6b4f0622f14df58e31d7deb9f2304e74f2daa7ffecc268955cb09248e3cf4481e547727883acf60c837e086571db306f400b3801757b70cc6beafe8ccbaf3513f1bb2a47f1cd8fbc70bd544d0b8233e56068a616d01393a30148bd255586b0ac81e8900a0a864a08b2737ff7d9f45e88280ccfb4c4e27c467b003eca5c8b4c8d39979b802e9cc010c547805ab28865491b441ff438061254441aa72fe6c95597f5b2d530641eab5f540a43ec8a69f8f3b69701cba050f9bdd513400311e41a95302910f7a9e3902eebd07d0479225554d4bb553394c4ac6f3c50ed8ea7da2060df87ed5c64afa8d6a52c7bff93a572640a5d81c4b12287b21e9b1f954663f96130901dfab3f489917d23cf56856de2cc0632a0c4a58f3b488042ad981ef071704dcf59c035485e2fac7a9896981ec5c5011f544137362065c2834d381ffc461903876fcfff7e18c029ef82d7fc3296025834e35791f58446d4eca28a3c393b605ff302379ca86fc81985b9ff90aed7fcda03ad8f64dfcdb78062906b6e95cb7774a67d740836816e52a07a84180d4b3507fd520d4dd81037253026b508867e2903fad087aff838af256a18bca2794412ac072a83d8f017dce713452d53d29f354da99ae5732045cf2b92a4834caa3a98f582f9e464389d6beb022ae5f07af6b2cc811685a5eda914b5e88e9c56c4419ddcf2f75467cfaf7002bcd2eca9d1fe40b12be924b570aad3af3c92abb795a42534b1d500c4bdad763d883728b425f22b622dccd03181ef5465af547dd6ed8712a52ae47700f24e028f897727f88a289322b41e608c4e979ef57f6b6eb95eb0f20ba372df785c1127dbe76c072275acb74d2c6bc2fd7fc24c8bb7988c198b6d05111374c6dae0e13ca21376ac272cac7bb0853909b5ca05210ecf69103f4aab791c43a8e5a9e839c81c5c9d120efb8f55b2f481a84c676714e1c0e5483419da10bda0f00ad3c1ca851407e3b2b1b1221196a2c957635ace2e4e2c7a14ba2d1ca2dbc6ebd9414867e081bcac7c293de267885addd91ac7bda382760958d80864059777628943ea376d2013717542932d4c52fc42ed4a94e642209586804adf523e8273d6d1f0868e00f8bfcbda98079cfeae4e32b02bd2b88513db639a9c5c0e3b62ac5f4b4cd6b4388ea2388ce3c823f96e89c1cb733896a0117d5437dfad2dfa671225388820dccf15a3447aca2b5a10990b8796d5dff429dac809a6a7b3db8ca9b9c833855e657b9819628a1bfac0538414af45a31ecdaa637c2e2741e4ef33b2931dc6fc852ab54e2c851cec6d43cb031d5c9d68031725e098120dd2b5f207be1f6570f2c5c55189e7a47be2aa488c65574fc6a4534b587d10c7f76456441b28ab48883da36d13758f1569404dbe2a5133dc292cc7cd27f0aeac16c1e5b72a5b4862ce274a72ef47b474cf4b50a7ac12eafdea3c793e9c54d9ec09b097cc002f38596715b514ebfb38b83eb436bfd046417ce8ca62fc6ac83d47d86922f1515a451b30b73a8ac4bae0165ac6734159ce85dad3156c36d33563d4b1b54ed8f046395cbe68cd50dd57a451ab0a9c77e133919a9571d5177ea6076d13f232290cd4603e08c832bc8925e8f470192bd20b2e0292e5f59a8be8b0e7378b0294f4fd2d03e1741487b6ba9f597051750f5f6623e974f7dd4aaebb6fe4ed5abf99c7a243d526d771ffd8809c6371487e2ddef0aa79fd648ece53c018cc90b92aa3c9941ec55fadf79f244bc63c0da2f0c63a0256cada37fe5b6d6a8d9ee901a998f958c11fa65eac72b60e79d9746bd07f866661221083e58829e125df4316224c831a7c3157c4aa2b79e9785061113b4bb267f303b2570d10c6403f1d7e5601cc9283a3de08cc84d5898fcc43f5360d0f8f92250673ee2f01477f28ad4046301b0abb40c203027b39a92cc2c93a5858c652968bc6c7743d15af6279d8e2801609e87deace0b48b572c219e97ddab140869474e77f0af00cd3ba4b34fe080bf83ecc26f0b34bf40c0e11051c94e30f27c077b0574e826b604380a35f7ab514f4259897752bf08d81e078758bfc33d7fdc3c940338b0bad80e0a3ab4cc01822b54012ce9980f7a899001ba3a30f97fa2f02b447bb60b46aa9213377f1a128b5f8dc194ed37e40638010e00b01d8c84b70483fe369c1e62c2ab0757ae09093fc8e0a90e5f9aaffbcc7895de1440c6ff9eb9cc7844320ee0563a1f55e0e0908b69a1ea233c4c7857c35b9d5ce43b10cf146d9bf46e0b3fa885f7aae425ee50a357720d268331bd133164258279d575293be81a56299117e9418d97a7a0ca0e87eda85edf6fdc61bcf6fa7ef529c06476eb0f622bd6fc25d729f54aa7aadb7339df8f324ee09568fea1bc3f8cef3b2df2af236253a0fc833d5d035a3a1a44f6d8d3bece4d8858691049dd9186765d66c9b970b58527e98911229a15441423300bbe07f73f6fab624185c001e03dff55c760559b607a448034656e13060e4cc25be84d92797fa1674c5e43da9c8cb790d95223a13647e27588cd3c53cae00049bc086d1359ef2ff4cec85bc88d92791332b3323ac4e6e4bc847c1b921de44ef6da5eb5908eeaeee0b7e3dd6e751ae048e5a27bd8f2029c3d2d071181abdb7ac3b800ac1cd0e99ec7f828106b3e429ef1d260c3e1b2c42bbb6186a6d211bfdc369ead797622053cf6babcb79d9c9e7cfa032c0881e0f6824c197008bbd1359170b9038a5668ba1a60957d4b05e3449adf5947a5569f211e84d003250d3a9331d2c4a90792371377f756ff2764398e44a3f9cd05ed9fed55439bf759009670c54395b66f9e6cda2fef7effad037dd1eb0b81a42457f1bf0ef399026a655b15a4a9a221d05a39258034079f76411c52d17f761399567d5df88df577d8faba1da5a1cf19f7d8fc8a3faca8019eb754c05781922bdee0db3f929c8d5bf28e9233de09441d651fd6699f04a74d648411bff43a5efffb5a4a8bc139461150d890e9f8439bc690e25062477c5d0552f320483ba62f54e18c04f734184baf3061fb6644689cc722391dc6f3214bbc30885731aaf6c1286d8c57f0ff0e0c1af9ae9a6dc0a329204a1d554a51ce279b4399834ef4c6b33948aca269967c9cd3d0c4d0e6d5a17722b3f6d6fc4c3b778ee1429d193510e42a722aa9bb77430fa35cbecf1c292f8dd1c714746b80985b912611b17daef08a0cc7f6455cfd8806d0ef14b51ab7876de3d10d75fb8f003b481306e5fccc5819388ab7a140e8b4f57a5d62647e4452ea455bc2829e655257b8130aa2440709b7087a4d8804ae28ebf65c3d8e6f26d735e8131e355650da6a8e62a8f83f4e3c0e6986bfe36eaa0d5e57d2a053b7efd808678f2774feb2a9ee10a51eab9bf8e6a0ee52abfd32a4395161aa419875c580faf24175acf6e65c2f57d50dc1572ba8089d8704ebdbb63fc161d9378de98887fdda991c20c97a49fc39829a01786cc89890d4e4f68c69ef8013fed5bab2296d3ca8dffe56b50bcb9456ac88e0ff5f05f4bb41f38a1695c2b2dfe02a445e2d15355263628b4f9ba4db23556dc895ffb5c8c9a4ef31b5ce939ae528663d9571bb18095738840ad17f171509fcb37d25e9e37b702d3e5902ddc8b6ece33bf031adc01db4c870e45cc0590e30c14a1803795c7327db5f21dd56b240aa9abc495b0dd5dabdfbeaa894358f4d89639c74453c07a2ab048da70c545266bba7adbe985c704d83d4ee837c1754f511eb4152f89daa32f24191876df881f4b8083f1b7dd241a9c510e88a22c23f15142b0589efeb60f911da823b6222afd291b0c5da51549dc14b3d75bfd89a89f93d5fca5cb540d3e443b66bd9b10df5caf20f25f859df323f9f5788ff6a28fdf5c77fb468f80fec5b0104683d48b4386009baa2d874400bf3bb0a68213c469fc0e0a16a2a9d8df2d06143991c71ee9c0a260a45bba57da9cb6116bae577c2d3dcaa5a88bbadea902cd6aa7215b056d54a1c6b5587b4d80f83b80b957074272873e411555fce5a10c16f58e401729f58feadfbcc24d214be42124edc1cdbf653ce78d90dcf26c8c9e08efa7c7b1223408145decb897ddf42c626f911a7ee1f4c73c9d06f5410cf8e47bed32404d611b36f21d1080329af20c8c28d51c7d1cb4bf57feac89ada5b699d1eda308e6e0bf3c05371422115849dc4043b928efd4c4b2410e3efff62f58d3a48826a9d4f6136259066a574e20ee1f34f01e75df845415eae05ddc7c2d26c75a7f043bf6183623e33747f91ce822cea094f97c7d951b885d31ab45275a2eb1115cf4fc5c7f58fd281d24fefa7e050a15bc24a50ddaf26c409ab0c9410d0d9ac5a7b7d74465fdeccd72460ec5203c9ac3ba166645e82aed775eb15e089f455d9cbfcf4ade7bc763b63270afb251e49553e28bd4bf78d689430ed6502eb9284243b0502f70ecfd69861462bfb1cc2ed6ef9c7272fd20e3004505e98164b5755fa90d43611698af1207bb20cceab5802804757a0fc0605dad7c0a33104ba5a14f0be8dc96f9eba448d37ac0524c14e369943eae25bcfefcf688e952817b67f7fcd470290efb2be09212c2fdd801ef01aa08995fb4008af9193e33799e1eb077018261cd2246720f1ef47891888eb210de0b0e01803bca6283e8030cbe8eb84ca069ac75ebdbdc1dee178255e605c6b02d9a945402e3b25c8324e180abeb2c8242d0b242fe22659c54463ce3cc1de06e957e999ec5b8a7549418faf68de82d9ce810c52f95a4d8eda5de1e0dd15a865890c3dcddc3df1a0b87ed0122d80cbeb1f1c6af063d5a0bcf183b35bfee72d752a8c1994f94dd4caab958e50082cd7e8d7c0dd98bd4dc9fd1956f90942676a24a628a02bfc4edfc0d87e11ec73d8c00d03e40845940c3492f991d60e95370d048ca34ad90c5c9653a88be73da3c5624031736cb13acbd19cdee4be963962f1358d74d847e09427b38d0f07dba1f1c51e1fa861778677a6e5810f4733a7dc603f1d7e1e30705de617ae418d9a67d10ebe40d25d7d80c7a17b49ec559a0940c8e8a1a1de19d0502f4d0d7f1da2a91eaf54586221a1f11ca734f287eebc6d847910dad715e05271e8dbd9d003fa7de6b35642334dcdac51e1f70c32f3296077d18cfbf6ab16d309e0f6a249712a3068a726d2fe4f6e7f61c2b9ce503a17ff0811fa0c01c64041815b0c4f4594aa5d4d2f45634c6d4c056ee032410a7f6e70ec57696fdc03eeef23b87026d335563e151728bb4701e0ca28501b53313a63c2d90c7f50a000c1cf2c51052baa9abcbac289fc932a49088cf85ceaa30c56aeadfa18e46871e4ae494915872a00240f78998d3cf11f489069664481b83065a987af4f70610d11f516582a0a05ba0e4ff56481ffd5548b6a2a0ab2a0fd230f3a73e8be518d901e4fe656905f699a4458cac2a3be3a66cdf187fe77ef6b46940d163035df27ab3f2e32cb59e0e0590766f67a084be104eec2b7d8521e9cf0b2d52841b6342e5f9d1433f7f7a602c825a8a151b8cefa1d6f5e5d03e6046a1c1a0490ec5f781b26a47c96405ec8c3552c0e5422c4f5d8275136b6631f57067a6d1b466fe29d0c80c001348d1267c3075c9dbc1a86989a93a0b0f98f59099414eb8ca0cb2ed8731c5b841caa808428b92855489bf79681d3267831d71ba0ec064942430e019808224058152f82609de0ef08401d0ad61d2356033c65dcb5601da3b02128c9c8d415ac0bb82c86a0fd62cc64cf869c947f82e5a0780748eeae33900713238c0c724c22ecc57e635d2a91af697d8f8d89699eed86a7dbdb82319e9fc6605db332d6bcbbb0ce79d18c0e6b38fceb56ffa63b302dd9bfba1610da64b38a906b7595b85197240f134951528eb0f49dec81867fa12aa18db7dd412afbf55b918833eb045c440f179fea187ea99a3230128dd4b2ae2dc91c82730acd0bfcc958eb92fc1077417cf93fbfcbf21553fe1ed602eb0a198fcc7c0ace1f369820ee2e181ad2af7782d7db99460526326baf8ebbc2fdab3d1262aa3b9be38f8db7700765f36999bf467d365cea677f9ea072490a1fe06808a6f7a2f19929cddcd11fe995fb30b83f15390b1645f9845b01ba1dd4f78ae99f9effeb31593d6681117431d27c10504dfcfb124eeca742ea9f80cb9a42c87564d61f5907d1574826b8068aea49c43252abe6b008e87115b035f646ecace671862b7203739c3d0977764b03e3eabcca4bfb01b68b8d19a8f0468e3538b3b6cc025080a8b01c344fdf25788c5c827a8ccaf7f8a11e9eef6f6f8675b0fb89be1e8b3f3bb4a7617d7ea1786cbd8f2a68a5527a2f1e9c193b09fc99d08415f4b329e3c9536600f3475a76b381e0b7a67c0645fdb7383852685b22eb7c05f4009f340ac5d119f265c82bbb2dcc3f65202149bd76c677991504e6d70678db18bca96bbb100bacbc7b85359b77af902f384d63349f17ce699ef52185d988111190e03780e058ae76ad0425a1813fa264fb6300c1711a10733240573da52628ce4f602fb08d1368fde0305333858cda043fa11d8a10af27343383acaa8ff2de7223f7b2a3624c0485c24450e007a77ebcc89060bc1d8ee4a0caf69acaf0f5b90e0a6af392d7dc7e2abb5514cef6e92d41d25745d5381598c3e274be49521804e2080af9467d9e3ce737456c46258d9ea7a539bbcedc8ca2894150251180953f2128b841b9f7b5800110e42a43630dfc5e73cbd5421e695f3d9ffeabdea3dba7f7d3ffa29ec38bcd9e3de83226382401c33e72d039a190bd74b5e052882d421c72962056be729e7b6a7f7fc037811b48780f7513f234d940e45e42be89cc78370db6a8d90326a632ab320b9c20959cd389eec888f957fcdb616ecfb9f792533d39f9c80c272ba563c8d8cee8bda9c2c088568e7b2e9aa3093b9641e88901ae86355417914492af30ebcc65349db9da08c71c05fb04ffdfb86445002907065309084e908c7917f27f9a7f431512d0cf7001c22982f696b265dc06af2da375f6d5631256fe963e0a6a8fe4c42735515e9fea50956616c4402deff87d67c87096c26034a9606c9ebaa9d1eebfffed140672ccc8f94a4e3139f43b53be086e6e8f829c8258090a9599649da0a4bf2509ad37f0ce6663cf35aa6da8522309e48ac1b2a5725958235697239160c5364eac465ceb44cf86353d3c7071ac9806858b09d8301dbbc60a298f28ed208fe390a916edcd3d550489a215ef3511fdd728a3207c473c70cb06895e9aa0155f9b24f09f3b3c88d62dbe8804fc54626c121f3e11612ac1da37d71fcefdcbba4fac410f446e363071a43453e6c126a8d0f796a249d386109c657f1b0eef03e0c19c4f08f1b155129270cc22db4766ff82029e8c84e028c37af184748062c2b3a08d9a2792bb9db9d98210226f9f488cd8f74194e90103da8cbc9272e1ce3ac3e31be5141c9567cdfaedd67b08839f82702bd097b42e129a0400ed83365de83404fa5b5b0df3827823a69a511a50647da3609cd5b189ac5e878f63a788ef0a2828f2d15de8e23c18aa1f2cdeda87eb04ee7a5ba55894083a9f57d75066e4e958625c799a96e1145b706b3843357dbf281424e801ac2b7a3fb702751c470ea1f6b6d3448971d38bb6aec4ac50235a49d066c4ec62e1cb123a87c529a3fb24c3ce7200707419785d4a7772feb43182c9a20cc65c9433427bdb02bc79cde4fedbf5c0e3c376c1214e768aa1a88b8ac6d8ac2b001ed2b3ea9ae87ff5fa8512be34118d271712896620ea5586ecc89f56566ca23ebe17a1771de836fdb3b75b6bf179c2313080afa8ccc4ca544854ca070909f20b2b6a6672332a16787753c27c3297f0838f140c4ca9024ae261645f408eaaa20e122daa8a9bd225dbf65c76f5d92a9f97a93ba02b2f4cd18877fabada3ad465c6676b6436861dd6ea4fe83c6a0e59bb42f325cd098c8b589eb3997b554514cee77b55b983c142cac9522ea8993a39043142f6de7b6f29a54c5206d9051f067106988414aa0da5f1c75f71ec6bc458f4ac3f90ade23050497b81faf8e88e5ed29b0848b0453bd6d1a4c38e28930e930e14938e14930e19261db9aec60cfcd0be67660c8067665224a5d1c0afd0d709b4857f65d71528181be30c04a147f186d9051abf7d1452e071e3382a2dd06f430a7dd29d0d1568fc749bae14284ddd74741357dacbb3e1815930fc15077fd551e56c6cf7cbc2f07f5e9ec138b5f18b2b8c717654182275b98f3def1b534a58778cb1b51497a3bdeffbde8f6e9cb1d78fb2e0822822d16ea23edaa9fba9529a3384053c46fbfc361d72344487c597dbf7c56bab75e5b59db2b269caa6d5e6f4f4c99d6dafa0af6a63b5d8d77eb1ef45a234a7bf6f8ba0afaa03ad3d94a6acbd6abc655f3136270da02f0ea8adfb77c586947d52dca96db84f8a1bdd6b3517b328de10fc64e1836e6474da6b9d141dddb74942f8fbaac4d23c145ca6d6d785d15b10a4ed49277cf2b0e903535853322aa9352535253525b520fa4277cdbe76e88044a02ff76714a1b8fb9ed6e4bf69ba5c3f58e8b3ea6472cdc88d6a6ee4473e386e54fb013a79f8e4e1938771cd6b4846b6d3da04394ee6399d0be519d8132464cbc22867c2014da14f3ddd1f6cc407c707c707c727465fe87619126abb8cbedc5701a24f6b7ba1f0dfd3eae294d7c65bd71679eb7e4b8b8b0b0e1c315567db22ecf097b509edfb2b9b73f3be95c974543783077d56dd28c4eed01c55a8c2dcdb907dbfeaec0b858bb3b518478c8fa61fd48fdaeaa72cf3244772a36a6d68b536379784234b462e73dada762732479a511ad1fbc0501c73cea7ece193a9f2438bd6c6d6f25b99ad599bfdb1403ecb42c8be6e7324209b7d81d8d7ca56326d74df779446f4a4d369d49d401378f2bcfb387764c9f3b2c039b2546bcef5c8d291259f1bfa42c2104678b8ccd5a5c0050a3cdcbc5fdddef1347adeaafeb8792b90ca0b1ae847a8e6d0008509a2349f16f5fb7119201452e051dfab7ffac7260fdcbc1ec69508cab4d2e1e68de980bedc0fcb19170ea3ffa0561d8a185577630c407370e00f4073545d07270236077254bacfbbe948bffbfb82fbbc5688d294d50ab9696d90eed6146c6b6d36fa72f1cafca1ad909bf7fe495a1c7db9d6465fae4b0331f4696d1b638c31c618638c31c6d86485280dcea2e78d9e67f2bc93e7a13c4f7b1e8ae7a5784450efe2266a656d8e57b6bf5f0e0158dc9c4f4f8619d7f17d8fabd303a31d5f14c7f1effede041c7bfc1a0f3f18b1f8a6f7ffc610c49ff17fb47b9f3069c2b64ff799cb50264d00edfb4ef39acdddff9c24515d4fee856caacdf827a9f5fd150e774149a233dd1e8ffb283efafc5082c871f3d6cafa4226d7efa0c683ed4a4a6e633dc885ea4cb45f0e3a7f8d25334b7ef3bef879e54a2b5f72f3b2f8cadeac6c4ea519a93b2e5c690731b20bb0e90d8817b22a04c8be52f0968dbdd456a0efd39a24ffcdaa54dde6399790697b1de9d2e6f7d9b45014dafe5997be2e798e0ba9ba6f758d78383ab2ef7aab9a64e3311ab4abcde92091a585767171196fa7c896c7f5efae5bf49195a4ef0dc86e53bf774729955900902de8f6aad2f61fb9230fb2b5100a5db7a844c9c9b7b3462ccd09100ffaf4a0b33aa96f8d88d7be971e18e3388ea30c1a18d6ae6e6a8e89f5025d5daa97b6c7c8b6abd371a7ded983dcacef41dfb80ae1cb2a445665b35be25a636b929bd5899bd5839c04158923e45c08e73a23775b53b941bca14e87ff813ffa9bde7f749911f5fee068adb5f631057f3cefbe7fbd11e44134892830e38cbfc62feeb1bff0869fbeab33678bdf37c6f7def1f1fbd3d1de8bef7dfc26e0c8e383f6ec213ec618e3d7fb845f6ffca7f1647a6acaa90bfe088a214877cefea7cb76fdf8fab57e04ca5a8a32811edd2d8aeeeef9f4c0ce20f81ef8dfdf12fcef0310fc32088220f8ddff4a0f7bb90c816ebaeb8cf5024df759693709317f2ec3267afc5044319d4413ea846242a1505aeb174f277d2ac1136832a14c2862ddd57bec701cc3d3e9743a892693496b7d3a69144a14ff249a4691ee9089485df0487e642549933f4962fa356ed2fea617fd840f4637e90742683a3b2586e10f9a8f7ddedb10313e7088920ec35014c5db8ed06d4816e2c96b61e9b6430e925291135bce8812598f0e373a37daeea683cd8df64489222ba436bddd800bb20b835042071bcaa6b71a7a6eec36bdc2033778d66d5131d85506ff9a1440abd87645bd0852858d9b42686d566e47bfc8324b513dc36649cfb8a12f2c34961e4a13deec7e3f1a4af4c58990e4ddd63eca826051e5c9d2b3fd04df041cdb583f6a75e2d846fdbd2f629c13e7ec6ca94901198cedfc278eed9ce3260af500eae699c2467db8c2d9a87b9a8063a8f2c43196143cf8d4a400d5c63997f1074b56116b83e5b769e420f2b1c1544260e58258a911ed20840a46826e15900d89c289db911f2380f98b34c2d0e7bf4a49a544695edb5fb5f4478e7a24272a3ff4484118c79c4d13b03f7466e5583a56d1f7b072d534828ca7739993cb7cd9060bb52f96cdb6fcc5177399f25f29430c4b0eb6782a6d9ccad19452b274324a561107fb549e509b65b3af17f296b3726e962ff4b8cf95387618e23ca1cf1752c9ec8b064eccbe6abcbf6a66a36471e1ac3fb2fe2c9b55a1d8366bf74547487fe432dfe7d3e9743aa14e277d3aa19c4e29a7938cd32965d241f7e9f4426efa7fee7145af7ba31a4e84e585deff7394267cfd94e6f8a30ae3af5ffc4a96ce4d1308f7ded0d9178d0f01dc79f52dd9ff6fe03043a7397f8f7db5ac68686d5bdfc3b2fa9efd7d5a53a1517faa9450274a797e5b559e2c272ca50c6e4eb8ac284e709f2fb4dd4807822c33fae258a53272537555486eba2ac94ddfa21d9d3ead717247b3729446c6cbc6fbb38c8e9c382b89b5b32f1aefcf52cac086d2a4b0a2a039f47b062ad03f126d39e351a5ca1eb9cde6507e46ea59ca1a9f52a25e55a65e46c9c13eb251ded49d8dd72507bead7a915e6a9d56ea9df2eb1b49ab1b486eaa704a558e9bfeb654c5dc7494b751d67819258e9dcb13f2ebbfe1c44d5f5942df4872d35fc6ea06920a68fba39ae893953b6f38d9fe2c3315100ae3df52aa68942a1c554aa992d1979793bf0ac8be5ade5f65b32f96f757e55442f645e353f5b8f9449fa9a55385b3fd593a568e558482f22939db4f2da96c54379e338dcf2d9f593ee7accb77e2a67f8df251e523957f0585f14729297d19557e68fb472e432d4be7a63fabc84d96117dd1940615e3b2acdc8d1c7db125911aff47f65563e547db6b107db2cc5a584a965cb2c8dc54dd70b25490010bdb9f9c704196d9a912726670b3dd077daa74a24a49612adda9735ce6fe8c1b97b179350367c6cd4d1effc865fcdfc92355b75468bc4f95a7525298e89942f09db32dab5b715429c92749b284696284cd67baa3153daca815681a7fa276a85d8844a364b1b1ad10c959a0a977b3c57eebae1971d359686efacc4d074d13205f85c6d358f1806962840d4ce57bc044d491b678b37247ac5c0b88c69b9563b171d3554a0a73d308216ce5554af4c57f460f9a65665f2a256ff97f9fd62c3374284d159aee53a554a99fb27d52665bfe646913c2c8d8127daa94769423b8f90118e8a37f9f2a259592ff0c1bff1938f4d53a028484112ab6f80107f39f11a3af0cd88c80071d827c52e0c58d9dca215083485de89b686a53982646d898cafae305c06fcb6ac45b2dfcde09b7561e9d5ff41ded7d6e7a35ee5d4ae3eeeef9845bbdc66ccb052ab3a9d941cda9a12fb8039430ce0e3c4fecc1dfd244d3eafbcaf348a0ba18096ee23feb0cd78a6b9dd911c76256c7ab316b3dcfc567f6c7a5088783de973d0f7488f07da6c7b5e71ab9b602d9c76f562417943ddd2b84cbc1ca1937710b7fd519c16570071628a2b71c6c367e13c610efc01863cff36ab5eb62f1626a3804bc2f0e3baf5673cff35aad56ab013ddea12cb1b9353f7d9d677c46064d1a8066895bcb887daf9765be999a9919135476351ee8d83102054ab0806cdfcf80cd4541ad82e5e805b85f65340315a0323a768c50c205ecebfb5b3dd3fba2200366ae0da4589b74e0fc79a3985def0063d074d34d4f72939406022bf41501daba7f856b8a7dff6ced9b827dc1bdb283bedc4fd1dc97bb24dc5a5970bda94e234602054ab8800928a4c003c7abbeba16cec8b2dad814680733bb19a75e0633e8652ac3a66b66f08b28a4c0a3deb80cddf8f3a718ac9e7f745b708325cdac23fa84bb45075262b33778340e34f946c8a68f755ce6caf08f1936c53915c69fd21a7ba937fbc442643a3935078e81ce405ffc4ffcc3ae706c9485339d0db734cbeccbab1ea9cda7b55acd81787eafb55ead18636b31c6d6628c2dc6d8da9c2b7dc1ee9e6d765f51202d16676c57d6ab526cbb5fecd1647c65db712ce666913ef18d2e090ddfb8cc8959d82cc46e5ee1580ce7548c836ff08db7fc6f70ec06df84d6c8d538a651b4ceb5879771cb8d79917caf1d717931ae388f268d7bec0bf594e2a7d7be4e4f1fcf4e01fc18bb66638b2b5c3b1a4bf06decd5d903e583cfd315d7b0126c0bf2b7261060b65d6120166adbdfc4f3e1e5a2046e3980010707c85e17c69e8b54a2ebd321747d52085d9f06a1eb9340ba8e2cda64464ace683a058004822481fe6d6a176f611b0aa501c0a64f9e2b4f5f20b8c2b6d7f72700ccf0fbc095ede85b518b6dad8d85dc442245860d1870700090324246aa464ad5820a010bf9a3625fdfc7239223896465a4944685f46119c923ba3e256bba3ef9033902d2075d9f3442f640f2e0c21a89cc66455819ac6c0f8fb08dbeb41c65a0c148f698ae96b5396892c88d91dc618391d401c748d25e467288e600c65dfb5ba1343cb2af6f856d2e361b2a04021829a571b94e36328408577cd03f6ed6dcb4bfe283c65f82e90a5bd007f56988a14f6cdb61d2b61f26f5d879c5a281ba297803d54df14513435e7451f34173427a50ea828523230002661fd730b681607de30d8ab43f2dab7bee6d14f0aeef9f41219f4db9a96dd8868570ce3ed6d9dfe58aa1a82f923bbad26cff5a9fe5057d6357bea2b685631310a98b87efa56fadf7d67a18af581480f1dfd597f1c50ca0638cb12fbeaefbfad7480d7b9b4441763e47208901110380c1c20a32ec404b0113b05a89489ae1c7878615709ed0501849a1a3830960c003ab4fe6a07f936fd27881d69ffe34123c4bf414f140830f2460f7ba690a4df7a96110bfcf003b3b3c3c30eab6acb070f6d52df0da1601db5a0a435b96ea8eb6dd81da3b7a401734789e5094c6455fec4b00b4657f65252525dc67b8cfd3065dd074df150c7db12280d9f6779050027d7d4a680882628c254cfc00b37f01fa6a80123e2ce49458228117301ffbed94ddd6fff3d7fee49bae9901fce7912d96861758304600bc1622e03bb8aa29b2a404142a6c81029f2d60467451dca488893103cc9be0a9815ecd8bc44c04715af28389c98b805093264224d940c405b01eb5a52b821411f2240b2d625cdf427e2e22d4e8188a0d71026c7f4abe49804d8760d8ed6fd3211890f6e9f28424c9407ce131331db8593f2f2559c13ea9ed263d714b82bb25090a2207b92531829fb825c12113b92599c1e896c4c7d1ed270c2c82db8f0b6e3f506420b71f2643e05d4d080d3f3108f1f381fc012d82817dd0a0162ab82151e2866428e7dc901401441ee286c48897734322821b9298092edb23c2f38020b9b9546893175c68cd82fb44abe4a6380233b9f9d472d2cd8796a5b8f900b948379f9c9b8f0ab72359dc8e18dd8e1c713b32848e4e6d7a3b42e46a114485232fe417e8199bde6a5ed4509b62632b6a4e6ced2f6a6be192d4d5571e8850a3e3565b7235f9b71a6da336bdd580d8e2a6b7da6d9f664eeb20b248400c1f49e903bfcffa20b2488047c5a206d3c046a16e12c017bf6eeaf289a1dfb5785243104b37d800829d072ee47e98757145154f60fe4f5f0fb0422745113d3a44e400f337e9abc71062d83023028249113730ff10f380b3cd4d6f457478d06d7ae341b65f36bdf1d0b351a8cc028ae454159a831eedb62fa048acc2d07daab6b7a97f8f4d29bd15c9a1d7658f882b1ebefae86bab51bfa9d5ee2b1e1e8079c06b7681888888888888c8075193a1a1a1a1a12122222222222222221c0e87c3e170b85b1b1a1a1a1a1ab225a0e170381c0e872322222222a2e170381c0ee74d44fa4736b6abb34ae9d76a7d542702644706bce363364617b316789ef781e00c0904c3309cd9bc9c381b02e32aa53fb71c6635239f55272b881a8cd53db231b7edeacc9d381aef35410924d8a700451a5b70785f82b752a4792f2ea99b186f4b4d2cf8f14ad3a21d0c50f45fd571ca1134ec36d9f64f706dbbd2006a13b9b645cb0aa4ebd75d4dee5ee466eade72a0dd860481ef1d226448927dde9db3b130726dbc9c7996f6796f3c5ddc78926cb91bcfecc6530b41d0e6c6238427168a61980306e3fc6e3b49a328ee60b1cfbb8136dda16247e71245711cc7996ee70714362a8adb0e44ec30020d85e7ec8d86c44e5d7ceffd402f41921f8adc683c375a4f56705756d09ea82265490c60a0b2848ba1255d0c590283222f3e6f36a40312ac211a174b0c0df131c4a3e4c918bec31509b281eb4132c2e53084c36129c794c2045944090e0858c3c6a4053f1a30a9028726c0606285101e94df1d2e530360536b0f26d83505ab447476b5d9d8d824d1d3c36cd7176104bf5ffd25494776ddb57e10bfb5a4dade7b2fa594d222aee7ed64fba2187bf5d3b5150b8c6777a644a42ee76bfbca198ff4de22287df1802a1df183182d3051c452124ef49061e705171041c50b4464b831e0490f49e4c480451039b868860b39b41064c3131e24305f693345ed0ab5848ee9c03533a65aeca6b7dacf3e5dae100840f02d2b38bd94521ff18a0fc75f8e987242cf64350653e9639c6f037c23b73cf3d61082e397b282ae8f33c0319df2c3e5bf914c596b6d4fd6e367adefef075d51ae9b9fca0100c5da9091522325a325c542294943af8cdf075294b68c42b64a31909b35e8fa630cbafee91a83e09c718f0d9407807efa327e63105d8ed65a6b4f5ab6b1b563106ced4c86632d53e8fa1787beb44cf1d1b75f1f03f475a52f79830dd842dbb6bf0202fa374c1fd0a753e0197db97883b1658afbb18b6be3e704b9d282ae9fbd777b7e1cbc380c07d55a570772b8b6ed8f34e0da485d395840f27d302ffafb7c3e184b546bcc171393bd8c931061aa59bfcfb4afcffdf3ef6bb95dfc7ddfa791f8b09dc95e4ccc8e8989018ac134e78d5e2ff991f6ae3ee3af855c814c690d861987224992e49362cb68f2570b8944b660f267f2b2528d2217e78c6757d7a41515566cc6682972bd3c1a6abae82d78b0ae5a84b11403ef03c359399bd9b0b05bb586d9190a6eb44c296610aa5faef5ffff1350e3328ff86ef6b0b5b5626b6bc5b5e22aaa67ef03431ccec0d937abd58050545801928a84d6d96c46b6e4b45f9c617986296c06f7e1f6e2ecd9e0d159a6334c674328da86167e6cc0d52822b3a1856a4313b3d94c0a1d972bbbdb9cdd3de72bc3c5787667b66e91bd1a45623716c339f5874896e28736a2f4c92486a11495be800f56f06decfada5bdd196a7632dd8cb3d06f165f0461bfdaabe4451730e02204556cf102cff33c2dbceff33e10fc3ca2259e576b8ee7d59ab3f3bc59162e6841d2132cae406281155548e1a456115031c50a8e54e079b5e6785ead39b556cfab3507bb8c2437dc606ff63c9ae990288ca0286180cc1a50cd6a7ded894a72a365de0be27bad4e171a1c5332a7d588d4415f5254d0f5b6a03ff732aed76ff67e180cc52cee843be04ead06e4e58c513e508321675762ad925bc3d8d9d92171c041dfec7db0cf236116df6b7580ecbd367b1f90cf773cdfc9bef3058a0ebfc776a722f8df575e53032a085f8975dc0c692ed3e32face3f9f3ea52203e6ef6f2ad81834ce63503b93fdf67adbd5eccfa4aafbe197ec480b070f1cddef7d11daf24b535fd8edb15aed58cb01ec4f39b3f9c533db3590d1cf489754e3c039e21855778867baeadb4998ef517a679cb7f360b2d129e617bbffc6ff4f86300f672c6a914e92f0f49dba7a3906fe604dbbc500467b6cf883b2139e3810e1176d4acace032774c1b16b1edef230a2e6ed9400981b3cbf34097aec913a413ba3e59643ab576aedc2ee7237742e900204136a1eb934ca4b864e09c0c570ae766bedccecbed726ea763924ba95a3b576e97a32fa92354336a6e97f3919ba15273bb9c8f9c4ace9549ad040b79029248d72771e490ae4fdec82448219209b924030d5a3b576e974322a781d9dab972bb5cb869906b83ef08238a206dba3e49844b0035b7cbf9c809600031b9018ce1cebef20ae7626a6e97f3912380cb5a020c40c7aecb68a2c6e859c2ccfceb2cdbd830312c49ad29ecce5c05375aa60635901e111d6daf964449d1572894c1a62d3e03a46b0f7e02a8a92353e3a68742f6a543484768448564ce108a100a2a24a4e3a3ffff9f801a97191e097da34e912defe21abffb8d576f71bd5d993f1c821fadd580f08fdea2e65638f55befbdf6853f8d2f0f08c822b41a3a34db116dc3403621fbf21e03b1cf9618abb93aec5e5bdb2716634732681862b21918ebd914d7e88bac088f27d3b0881c8aaea1f22763a3d8ef6bf8853d212da485b49056c390b6fd653dbe6a9710a9cb89b26dbfdf77e90bd553c322349ea60999d57003109a03ebc8503df6856532144a891297395143a086908545b63f95c9687a2644a7e6c0406ea8412643d96e0844eaf2940699d0a854ac1a8b52cad08c00000004016316000020100a860342b15896457130d61e14000f6e964a5c502e120763812087411c04410cc3408c318418808c21882954643500d3d9f42ed897290622390ee4e82591532075a0697941c8cb29a97a82158babc86411a26d4663ba3c84862c496301ac395c23dc1c814c11251019111c4cc64b806993ca4de5b39b6022ebe621f19a986de43bca6ebce4f5911d89cfacc4026845ffa0d2743430deb9f1ce00ed094c9c54551ec696f244ba9ffe6331b44012bf9241d5ca9583d2a73b0d4833703dc7541882fa0ea1023a21c5e5fb3431801f9c831a5389220bd88f4d88730cec22171ead89c22460159c1a4fdb69340a6a7e1c836de6217e6490988f557d1fc15386e5da67d330b47b41f1829dda6032932aee482c37d3a53792e069efd73852dfd9382d4cb4b982d463b6f2fff83146d5cf91e329f3788ed53c53321489b55b2df61be21062f6c066e1b66cdb40dca431889bcdd488ec384d2382701907aedb365e83056343823d6555efda6cfd141f4a9ae3524c8ce380ae29c6a9af4adc132a97cd1b9e18423b0b1ce2d5fa1475caaaa8a0270164fdf6013ddadf7200814560084a4b7abf5190ce6eb7013ebd9aa003bfc5ff8b637e851e03fe09946622e504386468d27b48782afcb2cad0f44ecdd6a420d28cfeb76eaefce47312e208af32abd9fea1403067709c4c2cc083d083c240830b0834a6066136f4275036c1201aaa02398819f14d525950ad3df2cd9fe0b153a532e055db9c5906d322106c9652824275d21a50ca4baa9b2d26ddeadf275830d56c3d15254f695a4fbf7d5a48b0df9a18fa898f8aae26a7d9af2aa7681d97eed653b93166553bba36d5f74756db53981ebf66f635fe74fd7f7b303450e46204853318a7383f517e4e5dda3596e64a69933aece66ce2e62d5808d920df24028d7253eae82a5370a9b5fc338bc3c755023d6f2141ac84dcc107ac968ac0fa01e92a9fc9b22fdebfe9b272b7e99ab1ee96d3000827f680931be6eeafccf523807ef79f26e643dc812231115e54e853d5a34349260cfdbe6c1bd9c335049339aad415b33f236b70d734d25836fff2eb610b7d8ada43663a1f021f156891659c63322187c363da757b0d21f597624fcd8c8bfb6098538db827af263213bc01b55b80fd041d43e8b896ee59e2a5aacfc0783a8a1ecf1d8194a56cea4f4d13b56c48d2403bfce003c716c003128384581c1a9dc84d1423cf270910a571ac569fa47169105bbed1a334240149097d49d4628fe3a74e108b4edb2b9a287240fa5ee6c77e9d8002c2532d764b41ec2e6cf22c24925dddb72cd0613096c330d7faff20d8b1fd58ec3835a59014242b3fd51da4f253354e511bf4b675f25d511f34592ee07cc97b865a86691f2183d6f312f07d4ee671db4ff9f122a9f534280675c6204b90449a0ddb14c2eba24efa3ec33f570f24b9e71825f66a150a14b0ecef0643fbd549e47750a66c7892dab3ec9891ec582e11115292ef51e49bf240c7e7658e349804de9af65354a7648e6d24bcba8c2446c3d03c5f56a38e1beec099bb44915720055646f1dbc2356a97fd02d214f01c96391c24526259a6723c4222b21b35d8cae85982f0f495442115bb73e77de21074a540db109e6c83f0553b80496a169c8d0e52666142a0c75988a55d7ad62c73a8c6133a89cb591ab4555c17fbfea7229de668b42d58ea67e9a58449db53a8ce9ad707746e2129f73c25c4c582e7cef9abf571d66a83b45fb47d36f64234c406e3921a8dae1956cbb139a6a1eecc0c54a76ac7efcacd0e135e4cdb5264f51330ce4ed1ccc864682587c8ba2bdf0a55f71b3b7b1edde61d747149ce04c1081444fd1f449f4107b6a36e2f19aac4dbba15f18835383bf4819d75bad0760433668038a37480aa6ea84bb614bc835fee546a2f64be0c37dd9ad2c000a4b8b7c83b1b61dcee4209f10c04c23c4d6c71e64b77adef75302ee9a176641195cfce15616796944e80f9b37888c0a492e0805b11550c20ab03c1b9faa3ff5647da6cd10478c556d50da410aa8012a07d4360beda7b4e4454dab19e28a2b314ee8e11c568871d7354f31d1b871d05579ef481d53bba53fafe735429b002c3b59e4b4fbf5071464ac8f32beedb917772b6d4da3f05956ebde2c70d5345a95781f1cf9fac47d6f423f1c05cd3b177253f8df2cdf540fd8a1cbd6f9051747a83aca3078c4725d4c64b1328be47610e4d3884a4a774442299e8f8fe1a9003500eae6a6fa1360e5b6c8c3d9a37ba107f63a07c6c14dc067beecffb9452a74184f64debe1d92778fad7620cfd65020f3327dd9b3cd842df2536997cb0391016bff6e7c3d63970e0bf161ab4bcc86b545d39273d41b8469d1133357ab5abed65aac93fd8accc65e8cbf46b7dca7a5c8d3b25da6e4abd321fda73e2006c54aea5745eb45e0021fbfdbca3eb1dc18b356b05bc79a3e1f82b296221e83fc9fe481151d56e83a801bd4e7208f1d7fb23538c54eb7b831c444b884ff24a2e017b09c52cf4770381a3246646dbe9c47bc7feaf4382d6d76fccaa05ee502400fc0849c86c0539395cd8f9b96f44e0e242fbc338c6a8c7969a6308b6ce5a87baff5edd9cc717ce4ad30972327756e06babebd2d3deccd6c2e31b925d3310e9806d94b2e501888a7b8ed4131d2d8adcb8d6ba15ee279db3fad124c9a5a6be7dd7aaa6cdc5f2c169084c9767ecd0b19d8821120104f2058bc457d6efac88a6e326c5d7629ae603a094eaa112c5d3e6b6dfca5f8049c3856ee72742e1b422a33f52fc0391523a81c0d69f5e62c979c62c496fa55218042e46ec4acc49e03c9a23499206baa643c6740fae32f0ff4b677a0fb6abbb18fd9c90d5b13f1479cef9d88c5c26193a2db7d8e93e5471eaf244de125856957b720614648b2bdf323c10ac70830bbdc9e8998f9669a86f817048551007b8c9ed466e2979627367379510acc964ba40bdd658a5c9bec7cc8c06e79fedee9f2b65c2e02aa00791b6cfc7175c3432ac321192da4ab39a23892e20718e96f6764ba3b088a06021b49f813c08065d5bc275916561de3f920f2f7b0a11fd272056647dc574220240a34f68a3098ff3e42ae138d73b549d04f4a4befe0fea9b0b1a4ff98688a0543e6d1d935c6ca84d1685e05651b56aa9369677621a8930272890fb26178c266cdc7e09908b138127d3081536791a35200a9f271225b0e2325105ebb8dc2a6b8682a066c4a4f4290d0f8439ad242509000bdd9ef0de97f0d274bd5ffc42d1e06c36343c0397d206f46deb86479413aed85497530f71e08603dd32cc7df44de780420eab432bbe9278243880d6e2e3f496e6ea16b83e8b2e48a773337fbad92811ca82a0f219998684e79565f04b1d89db6023a4222a5a761907579440eaca618a2248b9668083169f18124d120db6a19c1a8ab5e3662cc44c63e5104285a92c1caf4279c51ac76b1430e4549835cfbd5cdd36c9579e5a910d2d5f0a98772568b3ce10aaddfe6cc55e49374d89fa8d23288ebb8ca19ffc85db9db2608a9b5730cf0a936860e84ce4797653876b7c3a42aba9e892a3d4c0d5a60dd246f5e6c9b7b537deca498477191b6dcfe849ebbc02c4a13c897a1633cac3165361c88607289ee9d4e50394ac4ef422ae38abb13bd9be6f8f61aab563fef70daf9571c48074b1742a36b787a9ad3d4d34e2168126a65a143b80982768dc01d1624c6a604db0712241244e53725ce1b1a1c81c7297fd0d4857a2d6264d6092671e1a2cf820ee4a4d461a82d03750b26104a880e8ca0368ff144d3bbe69e7bb3332ab6865942b69949a199b098f2f13ee4edf608a929f81baf5116b1325ada2698f6c0314cf7a706e38096455d425491f19da773af13620161a1fa36da12e02c90c23602bf73c9d4054ff7208d7d90642b736ea7256f836b16054726888d5080965c5a29f8c01ff4b424711c281643e732f480c71f03066580e42743a1fc39eafa693b8426448cd304b018fe282b46f6d7b9313e4e67167d08c21de3edca1491e2cb7cd97af1a97dfe1c0d74a482cc8633ef41613b5de56f2226ee980bc7a760fd4112a8ed300943c08e530c8a02269e14bad24ed054ea3cb35bf72b134c3dd354fdc3fe11b35d27e5bf44f97866037bbd36a4fde5c4424b8115f3504d06cbcaafda437c19bb22e3f8b51ebb902b1ba39e8a9bab46e11b85fff56664d71a1f7288e5e1becf929deeb3add83e81f15f44e2707cd78d557e78f8ac64c3f79d57356cb751e1fe044920406204860ae824d19b2f364be1eb98512f3a52ea7c7b0dbd6640e1184f5781abb15b6e8183e316e51c796d7913e8f169de6adc93d18e83d2fdaa8650ceb1da4791f62321c54804d983c3b0621592e89bf327e55ad9a4b8ad5c53330b98aeb6a2524bcf469e85df8e78f2cb3efccaf5979fc9f76775df03b5420f988c2f0ee08868449363064ff578bcbee40edad5d51f089e74d7fe8144bbbde136cc8aeb6fc2e3bc0130b49c433edb591734773a7b4576a2b0924ceb7c7390282e1cb5406a81f76912b1301bf75f55614a72a8144a794e2f64b3d54e2a7d3313d9a3adfcc966e923a6babd6216982e08cf0e58ab23d207efdd9a62a20a1dbadf6690deb3676cdd01a10a0005d692c4ccf69ccbacbcb1f7543fd22c3bd20f44339293d1d28bde216606fd994b4b1ec54f728f0e9f064ff09aa33a2a9bae5b0b72921b17e68729bf887e0be2ec4ce019bdaef8608ff5fdd99e7e1d0ebed427ec600df399b145949f9fee96346d80b84f2e613b9e1d39a7a69bbf97e8b1c02f29ec1df16edf6b2ae0348f2d8f20d9ea29c26686c5eea79f3f631684c174b1d4fbaed5bce6f238aed18c1f778beb22c3d7fa7a7feeba4bbe183b8f56c76e7cd45b5bf3ff68cd9248ba7dab063dea17622191c343135e66c2826532034ef14c2f522a424722fa27a4a117e3e4fe41eefa27614e213a77078b93a94cec004dfcef3a2aab3cf2035968a9809e25368af49c4d7b1c5a9a85af944630300605f9b86f9535e840497dc5028a9b904d34ca2d582c207910c22b3584a712400486d9e1c3bb6ff7d101b5848a52d3d2b7fffe143b11bb545f3b59be689f56aa0f68130aabecc336df77c4567f486811cb0eb0b9f337738d7b44157b4000a910fdc7c1cbcbe72bdb439946646a4658757db91606b9e727876874e033662f814e112a83075ea861a778c80cf89e36671c27b563c38366d68801ab57c78d177e559f1005167a2e8f29abf65eeb98f9c9c40ae992511cb515888babd16e9f07687af02dfc25f991620c2b47c5647a8f2041083d227cf4a98a11f3575579ba38f369cec771e3698364764ac3969da172a037c93bf401adc576f2634c660003e7fe118623c3e8b1ac6afd92a1680cf58f4905dcba306a374a8c43527af5a3a6b292c0a87562f4844ecbe9202392fde40c94fe9f85bf5782bec097782d250aa78fa6749cc92c486495b9c9cfe41caba45e7e54df030d59b0641a49ca45398e87c6da34d7f6d7e542920a595f9bef46d49f8028c219e551ec5a3d589ddfb91a34a0e30c2f19ebe5ba9c212a479b697d555ab417949782354a7df36b1d89455a5ea7eecc4c5ed104acc354aa357bf25100964aa322b91151b1c2de2c7fe71b6940f54facbbd850864cfaef56c2c0f982e39ecaa965f5d7cfac2998b394f802fac68f556d8c60c9a40dc3a059d34b5b910ac7301ddf569920ba0f64e37b8c5f9ade9cc0b435b5d36c911f42c5d8ebfeee98615a4705264461769ea6e537c2690f4b37c74b136c26be1b21565bdf62dd0098b60a27258efeac1839295b07f6422b1afdb8c677cbd8087ebefc02915d75f19a3c852e9a02bfd8636af8bce433c93fe86e7e032354348b8238aa9ec9c07f8d50180d7032f28d44055f3515edf0624dc1b6019669ea45ca8fcae12b8a00f7e53ab832776850318ce5223db78638f08cde389e37e83a02c7bae9958d89076a7ebc063da26c2cef10829d8224d223292dcb5b80be7a0c2e4714f5a184f7c54ad6d5081061ca9ee3f96a95d10c05b7fca91dbce1d46e89dc9400ca3af41718e57f88a79fe4d6a53f1ffa92b7a41ac14f929b6aa9690442cfea2aab8d0381d421ed275145420353f6f97992716ba33d0968ab63350b34fd7ac4c500ecac93377622ff2e6998d59fc32eab8a61e6c274e9d8ec6a2dfc1891ac4ffd8ca69853d9956e1ab7701ab60c7eb5ed6bfb177049c6e2d0dd67a35783f1db3255305e33fb3f32f107c0ba7a1cbef259dcbb6fb1da55b1c69bf74720285ea29d78c4a6214bc7bea63f7b7dd0bca51123b4c6e42713fb4adb1d65f4019e1698adb49e9da62b3116ad99d0bc16d37d0692cb2841a1c80a4061133cef0dada9e69825cf7af43b63c415b2284f51457230e9031995d0c50af753ed9d316f69608224db1594b11c76705a3b3423ab5f8c537e244ab2761cd67adc84f42a0b16d1f70e7330434054c9ad98642cc302f1f1286a27107c601310c908d7877714078c152372da8565eb98486d41ba239b1a72cf90f05a8495a6c072af27347521196525b71f0a45381ea5b005f27dfc1c3d2e1e212155f78f89150fe73828acb15e7aee238f3036e0bf6bcdba174b463554329fa287322711c63aba32701f766577113913d19d620d5afe7feef1b08fb97db65a8f396600ea6810847202b2aa0dbd1453a7476065a58cc9236a83c80a4df917abd188f30bc86f930073ff83bb259b34ce05dd6c5d28804372eaa9ec58381572f1ae7cd8dbf118a1070d8c5fbdf8d04baa04119f0d865df92584141010d1980da131833fbaef26760bf7624c9ee0d48d8f28b43f58723f3404b064237a7d7854b07296e0b9c5c9d22fd7bf3d5e953e510f430596eab74faba0d6a95d6842787fb84d60c70c0327911606138b755b1b1b995c3f3d8f020f0c38359ba0039779ca011aa6e8cd5509c9e6aa36b4f6838363798604bc7f835df9f7db1e987beee6c3f84ebf847e9182045442a38c25196fe40a1dc8db96e4a1e96e59f1e3fbf29d32c2283bdc8d62a407856502dd8d9e915d0291b48c60ced705747ce25c5637290d5a5ec2c326479d446da7046d8bcac99db458cb747b84c9a0af721cc89ebce33a79a9a207c5f9e052c87a6b20001a1500fc8ce5b6fd059591f383e1d0601552640820e1b2f822d5d0db8ff85bab277c33a869bfc66ee8cb5e807dda6dae39ec0877f258c7f61238ebb9687608bb1409896785b0de16878c2efe189ae834b5d7ff52a8c7fa998d113a8e6b78d991c328cca9b957efc3b2986734fa2dc59333cd5e3d2e3a59945882fd9b51c272fa883a40c48d6582b02fc4dc5928e7f119929ce19db73368fbcde45ac59c21d9f6cb6e251e582ec9157737b1ae916c95fe9cff35e2343a10bc75b9dd13d8504a23928d9b548d173fbcf6931597be9f9d8fb22553ae2154092ec3fb7a21e6d4513c68affeaede992ef16bb36dfa70839291674e1bfe7073d34941cea90a68f01d791d459f1d64d829d083491838ade358c0f14f0804eacd7f6cb5f7d777d917e3498e29559a45b15668883a403cdf09b1819478c713ec8a3332ecf6db9b3a15c76f8265d19152670041b685584a9de3b0b7dbb57a728eb702cfb2b192cde2163b746e19dc36bb20026348434679adade686b73184048da63523fd1b18e5f386f0056f189cbeed8e87f09d2c22a35971cd7765b7644aaeeb7d4ba01d019ae779a37033a0f523ae74d0415989f6fcee1e44919f7efaf2fcc9c924342295bef7aa4e8064d4a2d01b9c2c8ab1def16a4e936a1e985c1420c3380838bcd9eb8dce503154b364c1d887742ead22c7fc65a9d91170fc710f7d4b9c126deffe0694e422626dde5cc73d9b71fdc890d07a6dd10d534ecd780d1145cdee5ee18b67335d150b89d07584c3219589beb7abdf804a4692108033e01406002deb4bfe27f586f48c388378aceb27029b82138d423d28b74ee0966ebb5b005b3eb0699a1bd463fa6e6ff73437507c9232cae02b6e939b3fb55431cba67ae7e72c269052322f27dec2aa3feaba785cc3f4d361ba693f97dad08a70d2673cd5346477bf10fd1231d075b8fd07dd0c8c30ac424836ce08c24fe4dcd15b11f8233c6ad25d4b1f626523981c375cb8c07beefff032993d9046334c723f27c356fe5aadb302777e02927418ab80c9ed031820e0a82f6f1af7f67db0a8aa06affccdbbee2b0d645e59a96d70f5d48cfb4a2b53a2bc07af8be09ac3d095a1ff3501b8aa5c0eb058a5e16fc57eeb14f3f79a505d9cb97857c03b6dca99cc433bd8fca1685c51b46c2544c8b1dd6f17605475035b88c871b9c6fff67ca3073baac5bef0cc2cb118190c5ab4fa2f9c5351a000f2abb66b9b02422869ba85b621f869b580404635f65d2ae5ec7c0bb0defabd00cd74ef3d4deb69951312e6d49da785945439d8deb2d46e9b69c54bcd24b60261569ea56a28eb736fe4e32d07130f65154e62ab67662d292f37bc31a43a6d9379e975d90c742b41961750420c2dd200bb4e5ce28d926b85a6466a1c0b15ae937cc02326215eedb2b17996a6a59368acfe63a676e149e7581305491ce621236eeb9c7cf73b6fc831f53658ced4a8b1da2a4b11151010c94ef663b3083e0c44fd3af38683282f531b139225c0698b69337b8d0267ac40be73c9d2dd0084383ddc828f50283268bf34cebdddbdc916d06c02fe6361ab5f3b7fb5bdf949682f2e550d4b1b8188abec48c6cf2b46ded516dc2fa2d5c2110651963a6ad1417984cb41aa20b89c5febffea75ca0fbb1b3b74805910597cae53497a0b6204eb7169fecddb21cca24f20c5d93d8d44cd8b426c6b0a23a542a3177c3086a28c8974e3b997a860013248d804e4a40a10aff1a2bc7a3651383d29495ad725c49c62c8928faa64cada22ffacd615554c70ea7c1a73859d55625751bf7031f795fd426dea1369827153cb73e67420a405cd0e1feac5a66941a636ba0b4293e03e3cc84c94f829de4d203bedef6db4c868adfe50960915e0946b236cc0137cbdf50f9e7a673142705a1c1b6ca403098e0f3557aacb08ca24a3631e566f87062cacd15570bac926061619dcc9604698a923bc957c7c8c91535416b2541d5db1a435c65134187ace6833b19f14b8c928b54e62cae29f41812d8d3fd89be2458b1ed2f08fb20900f0d1348b72ea0cdb8d80379594684155e8f151616d1744cfbab4157b6b739dc0099c68553e5ae2dea987bcb48352e123ec8d418a92db2dd187ec61d90148d6d5c60beda02fbcaeee62e6cbc5b0f8afcdd9854e115db55b778fd64f75c282bb460eda5199f9ed70556036a9aa56a23370007e82ad805cc7061977e7d92e0909caad1edf6d31113b38edd676736c927aacadb41f9b744f68ba9e3a957a30a606fd28ac8b42b368921ff38a6733a5312583049b1d399885bdd44503a0390fc958c56961a5efb206ba874e57494d0dea84675ac3c42c3dd862fb75f0a9b2fa1ecd86b800536769a7fd9553ec4d383b6ad5e3b0f5058191466c46743ab91242040221a4cee12d08833ae817eacf06514d9550e9885a08ed9e73ebc1571af020ac368fc077cd6c4fbbb16bf89c530e1a99b2541c2e3620286433972a0702b2243e0a8131771f011b6ad1438d9bac627f9a0c60a4ca8bbc4a404e2b2e1b850edba8655bb155163dfdad6499d431770219812b5536c183f5f30781042c0bdf2f037cd84f7d54bf26fa8d0936616f0a507d18fb4a8aa68f22c2ea90d5e085b2aab7fde754f6a3fc55bb3c2281935dacafc888d863b56d870f8b5d954f96bb1642b77591ccf9fc0e396489b43a3d1056bb4327859cbfc2e1f4daab72d7ad982287d634bc86e62b9a2bf9bed134e0fb9bff9a34442366b1733c367bbef2cb6a9338ebf4b205e6103268f947a099c99cc293e61b43e4deb08e5f379d78ce742b2a980a17427078b1b1bc3e0f302eb018b36cad0eb15fecc83cae5e5ecd10156b2c06899a028861c2355c67843e113943ca6de82505bd72a0d473c951d0c0f96db0fdf387b9f58fca226b2e71d27f8ab1fb940084709ddb1b79719cb4d2e0df6806533eee1ef5ec41b5cd81326cef24c4f3b0b6ecde5a2844a6775f3a58f65e693067be503e8c98c654c973e9631011f18c7737774344a61034a15d2b004c09a106fe8f1993ffd58b1eecd1fb4a0579c3896999666586602e0efc0164d69dcbafe769963813a208b0be3eaecddca8e65a6c1fbec719d4484ea4a4b70ee0aa56bd4aacc7a5d1a845e9a2c58b5fed7cb5a510869a7efdcdd45056f839beced8ac73d85c0a3c558d2b3f8118d447106288ca3694b631573407ecd7ec4f0d050dfdc11d73048a700b7a1a81e6a83733f570eee12c595c7484582e530db78207c747ef844281243de323dac0ac47f2a34fced8f93874677e1f959ac8e3ed420a7bbf73b733f8d5ee6dcaf93855c71ecdd7d5518eb14f106f3e483e621e05cfe4bdf1b6d0c02c771e665f9db73c91358868d63abdb25451ab6b4fd7db9f4a735d50bdc3f4069730e71a6228e38326c60bd8d53a401de9ddc7731e9eaa45e4bf3d402fa2a3e9fa2f94ae4c8967d7344673a6dfc150fcfaf70720d86f6a7a110c54c68fd8adbf2c91ae91eb45cbf2fff258ff15f3c737b644faa80e9b11fe1fe24811f58331f603af4528096fcf88b26c90a464cb88e4947f83df7d729164b04153477eba2be067a902a2c6c6894ec1be00f2cb35349ba4bae3b50c2801cd05be0c9802b165052dc34cb604b86cc4b7ebb0487b2a32383fe8a5ee1e418118bf15ce4612548e190bcfcd8c276a38698164816a0e58de5ad77a5319e033514064923ab189589a13755ccea034f1735c9d7175f627c51d5625b502d602e8c96125f677b918fe11e570e83e8a0965abce26992eec2b2ebf686e4309c1acbbd6cf7e7dc62b382af4c28ae2fbc4fdeb5b95e8bad130215c4e2aef0c61962b54c3ac66041688ca789a471a6e9e46fbe6187401f88cc5fe11930c1a982769a0384c056da9933e07704ee006e741e8941c0f292f36401698c2799c80c51ff90fa07cedb18ac777410e93ef80335c7e827c68ce3895d0443a22784734833aa07652e18527a59732a36dc583ab198812ac1c2d8863833ec78f3a3c4154858c59d52fded663294210643b75f38f12663adace65650a1e9deb0820523bf92dae845b59fb0a79a53038a7bd304911d5bcf60330a8638e911050cef979d2c2f7614397392213335ffa7f4649b9a2a842b10e22b1425dc4067b98e949ccb0b4ef2874e62b60c6d90e0854a08f175b9ba0871718110bc23e40203f143343f358125716d24d1ba38e45cc61bc4071d404479d3669d45dadd401d4feff51473e01d44f4646ebb59931fec39edb2263e7073dbc9427ce0e6b69b85fcf09edb2e2bf181ee6c3b4d23e0463fdedac1e6309c0d4fc242f5fa89729401fbe6c514554c2c44815df6c559e0d8543a9f0623e38d9ff090607540d4e6eeedc11c98333476b3e5a22a8f486709ad099f0dbd261bf46e8e13e329f79827823fa456d03d475545d0b3ca3006eaa4ac007714546e1372e83ef84d3a395e9f2305c139c52d3de245f86d1954892a555dc12e134b5f1184442cb34f26b552583679297e09a3407860e714b72c2bf2b6fe8e16455dfc6a28661bad6482b8318ba3ba8affd354f5505bb44aa8665b4fa55037f99c1ff925e9708d0f7e898c010b86c807d50df8392c06fce36a64ba0feaa1c1ce9d8e36cad8fcf90474e1ba3858ce6b36ff9758338efa53d8641af9bb1d3ce964fcc1d922300e6406330736cf6012ab16c4a476c7debc541143c3cc81fc470139d8b85e8c228e7654c841071bfbad99fb72eb277131c3711789c22edfa5719cc848fc3bbd3089ae03ad1d57295f5d8530a6bcf633ef864a35f9bbec7b9dab2483a4ddbbe601e2c18b3e110b25b035ddb77be31a24fd0e6f12f8ea27e79005c27482d40a12203d769a264fe0f306977bbf1bce9b5f700c37a624e258795f540685c2c8cf71a0782c07c86a1c28f952d9696e014e8c723b0887810c859ac198d707f81910d219fcf5a37e239d50c4385970f9bc60df2a822e39518ec9adeb7138b400b1ba35a575ef70a0f187c5d6e099ffda9b4bcaefc419076caeee25969e745a25eb143da3e91b049c09779882770d0ef98131043f0c029d4c5e20e052bc5bbe1cbbe2ca9d3e947e2a454329437d6de7e46864f0378864f588d6551166f112c7cdc0a02f8f24017901fafecb82d8689468102226830071399e880c34e23eeb51e8cab0ef0e2396463176314bbaa9eb34c183e8920828d84325a13a98b10ac7a567004a22f28170398e58c70d03625b27bfb28604f4a58e88ee828bd7269c3a5f676c38e4544334b49f7e91adad368d420ea6a36230ce4be4aa389f1c537743b36f20a5fa91c2f21c687f559294219b57fea01870d1d97cc68279ba19a0921a54a4bdd81a9f46fbadd79471fd67096259c8d12434dee7f863ec6006970696fa70548208e2fab3a77d50aea107ec6562654f94c919259ab39c4ea4387d7f8fb3ee5510555b375c5f1ea6ced63a186f672aebdccbd8453420059f3ef95f6150922630d214e094699c04ba7e956efa6d302a3a6a14fae31eefec1329cd3241489bebcb87443f6ea5ef884ce33d98179c5235b5396260ed973f46e7d22cb17608f9c96a124c6a9da8f33259bd598dd4585c68b95410d3a957a293aaa787bd60731b2924710fafd0675cf1ceed8ce942bbc0093f5c304166565e2b0fe0330676fccf678752e06fd03caac16b0f0354c6859750c4bf8f299b8141ba1f4b531450c6058b10a7990385058c557af41d7e5868f2bf903c66f40eee06b573e112617182fb9fa3fdd14c3c8b190ba05d784f82d8aefa8346ffd57a6fa1d9c83a669f466b98c72d8e0cc9262addba7922fee1f5b61e8503f8a224205749be8422342a3ca96826dc99b615512020da1c8b722d1fce45fda1664a0e204d69aa0e57794e11399c3cdd032be63f73bcff2a44f2042bad0ef88895d8cab5c8ffdd76e8b4df4384fb73b4db52bef351bf52f7474929eaa9eb26f940f5b4ad27190b57bc578d97fbf08bc960ebc541f88a76f298c0101a448f15316fe121b6368942bdad52ba1c5449da6790a8122ad10dc9d414b96bede1bc8e54df3288dc3b3c9bb3fa858e5712c27cfe45c309d97db1f5780df85fb12f403549878e38d7348efd49087f1b7d98131c312e3a99ed2286493edbcbe6ae5e330299eb765240509054b8941a2462a84297a82ec8a7ed497fa57973e6a1ba133e730f181c68ccc94d2e06216395131e54ae9558bc706bb93a804b28ecd82d3483855837b06fe467c435b224d11f4158a81c76ead12d0a82bf0b18566ed9afe61260b5df300b587ad7d558f4ed4aeb0b1d49c47a5d9858f3c977f1dda79e5ba7a0417ccd328905b5be104315775fbc99def7b9e9e68935793a6ff503e296bdd996a3e675ab19e5bbf4a60aa8d27b3f37dd7cb1e674de7f685aa15b2d2edbcb4bfc25a5a07ae9ee866cb084c312905bd23c9d7c7346536e8b390bad894f071f8f37bfbc956ab967d5d9fbb9d6f4d6f0e39a588cb0e124e0ff50bc3e731eb445d8871e74e50af6f6195e8cfa2a5ad8fc2c53941fba61c4b73ea70e73fbe55627ddcf8c09337d200b73f0977d3807931e373f475b7525c4c31b9c0638f0d728e4befd1a0ec6f648391ea30a900f6ce7d0566a5de5178ae0a8091e5dc1a42f359fe0feceb015b412e6d771b1b03cfb5a113ee016850c747ab7476879d60ac2600adab23b1921fb39223c59bd6497180a2fec996d08797fd281199ca4205684b1c76f1be7ca070a960fe71cce74420c06f890b5390f8f0e10c981cf335519aec86fc55786f44bacc1c779c65912f135d96bb54414d817859428dbac0e618e6a45e8139c482c1d6cfe9fc6928b513c5256c59f2603b784994a06c00db5436374e266dd62851fc50ad5669fe30e3109d26bf8538e209ae87a00ed6358e780a224f9f51670f944ca7ea1c92df1e37faa915e5a002d58d44cb4c92bfa90d825b00029211e58093cf6cff5c743bd46e11e34dd451d22ad04b2b4c2d2fb26089bff4bc2674f8b4322d1e01d1971a73f660f1d8fec2b0493cbff906b54b6f2908d791cf873acd918a439a51aa4c00a9bfaacbd69f3984ab6e558aa37ace805cae8c86dc9288d5d6744ddc309ad95cb25a0a22b02e110ccfd50a9b6e78e836bb71c14b002056c6007c22004ef9b1b7c4b3f2cc3976a5bdf352a6e2caac1ee6d5eaeddf8a20339bcc00ddc9a0244a2be711d2ee5b7032b979d0cf68eb17be10bf060162311422683edc465e119670e5fa72b69dcdb6c41202ab829a2e203573098b4f4c486992467af5a0da63667095974b7d6afe860cf9a7b05de0384ef742d1ca4dd691c9edb8a459ba9aef8c0279941430e0d0debdb768406af9a3f3aaa18f2b51b029d49d418f67a807ba4105eace668c323bef5ff6a7882dd668038e865c395b6c2a0f69eb9459d1398bd6347d59bf106588e87cea79cdcb14a32e87acab83287f8a2781c8b1c81cdac044dca5d1f7e92321b9617a2ef6f58f9660f4e150339a26a7a70ad948a83454f16b8ff34529b3c35d0d22f115a90a5a0998f2b179c42e76942c60136edba2e7a99ca36a8c9303296fd188133f1403a1a981587544b915ed523e5474d73635f3d5011121528151f2429c54c491b29398089f9c3ab5f1864f451841dafa7d760d72e9f4209e8a50512cd7aeb4b50521229fbd515ccbdb345983079092ecbd93652b9310001d2f761f04e4f2bf37cea7a60010bf3d26e9fe3202297bb40b8c71863afc6dc32f3d6872d4c7fddcf79916177fcef87a9a41ca3a081bad856f57cdf002dc70637dc3a80dcf702d1458740376d1ac9318180d792c33f637e60544a8a55c85d077654c820ca28a12b2b795b0b06e0fd713ff7a8d7b3f0c57516f83137a43412aeb36633dba8a6a424b7c3c71b57e01d0dc151da88df04efa502daf09f722a44f00548936f34614883845ed176cf2fb79963a55223785f658eaa2a300055adf50a2205d9a22e8a3dac686f5e8b7f00c325527fe692b3679451534836440ec4b70acccd7e3c4a0c7b68509fc4455c62011ff2ccd67c907ccc9baa1069df44a8b40a91782016d6f2ac60df3f1ff21aeeea5e2d2fbb2507d16e3980dd3a2690b94168ef37ba1d4bddd15a3780189add69fb7f011116876fc20a6f61343d5dd464e7450d7de34e315d6705654645aa78e899ad5c1391ede1d92e0989eaac904cb988aa14d3bc0aa2f6a8b714dec1205123ad797f45b0594ad47da36948918a8cc66d7671910b117806847adc1fd1b0452547167d1f60441fa687a6961e6a00a25239b0fb20dd10444f4635b99d14ca3983312b6accc892be753118d2efcbaf211fdb5c11a0bd9576e8062d09e7010b77a185975618a1aefd29be3b4152a6142dcca27f7cbeae83775c3eb23888126c04305e09f55688361620f686b2630b8152ca91d3079cd517fec581e9f886b7807a01ccf87a9ec8d90acd07a900de72a71c71210a87898dde651be1ae6e4fa9da90e89939f6a21c52ac9a7d044509f330ccf9a17d1122a8efc901909a2928ec681b4a04d8d076b40382ccbfae59a8051edfb89057a8144ae07ba00e9584c1a7868937e2e4e5acad50c9aaffa2d071f11ba6d98ce60f8864e8862392631e162dccfe265c9682a3bdda3b72b4d78a7f1cede08dbdbb9823998460bb079fbc332007c01795932c7fe0b7e4317af2053b538671e5e64bd50ab7207d760e273e19951dcf48ca8204d768d970d39b65e953082a33b65c0e8d5ee780ab641ac65e01efddea31a9add5f5df2d9392c315afc4b17de247e7d063db81ebdc2c7b82d2e6e3618636152662a854ebebcfac3d6e043185501260c45b7d1a9deaa3c139650f7e3656e9f42a227328b14c0612ce2c3f405359af9ea510a2179457b6193dd9ce12b3ace1a059e6bd5ce1fcced2386b01b16f81433602394ce685900514b301e60554d94bf67b9758a8b3eefeda7eb589cdb893519a7e7419b7c6a5bb9b0d0a74cad4eeb77059dbe416886a117281f41852e20253d2505f4fe75585f0e62bf7bce8f9bea49bc0b7d4610c8ca7ca49874a2b26b0c9272c7c8cb9de491472efe9894676ef7f6590024322db7934f38283214d615551ba8710872825a49e8f2724be08e50d6de4f52fc28687ceab7cad213abc6e2b30d54acb795202eb7f6470405cb92c5c9dce3329483df9ca1a1b65b1da2c6c5863c04d42d0740b39e6fd6650690c2ed783d13aadb6dc113303a031805aad544598f562db2b1f7cd43670d89a56b952857002e05fb8748f87d68316cf1d814e47a8161ba5bcee1d1d39a73c1eadce58a3314f679884911fd07202181d9616f644a0f75a468b6131c17b77dea681fbb99ac75ecf25b427cb0a8563abaaabb670f89917c269f8c0cd5242cec7089b0048ec97f9d82ac77898f291b8d33f5ae6d527056008e14f64971c7bde44fc4c8d14a5bf343b93bd8b86d3ed63b4c60ac8a758696d29697b12d2458ee5a38b14a4b80e4b6cd1414d09a6212ce02f2a3062884e3d91a99061e42abddd1c0e150ca8477518962a16dba7b3d3dbe37c847c9795309d113417396721c36b7147c2f331ee75b48aaebd1eb755ae360db9b32d57824537b4650cab6fa824dc4c5d355238fe90b90b77039f7a09fade05749cfee1946fbc81977ba1e93b061e9af8e38d6ecc87295fcc5f041007f967f2a659799c337ec6ace74d9899442433f83c261409ee1786e6e2f6f3c7894d19c3be363a80d89226d2f78d41ba08437dba73f2ed2c69440ab47a87ce92b2fb4f21ddadb65255f0ac120e509a69fe348cce3ad6ce99993cfe04857d6c3834bc0b2c6f243351f1a8f770d8e94577594365913d329e37604ee7315bdf81fc997bf28d41bd4c9acdc2b17b8f335357f45a9f8370058e4ddd801a81a94df24f8ea96350bcb541a921d121af3ad0f3edf255fc36d819794538ea81eeb0d1011c31381e10574fa094bc78ba7abdd20fc453253d8dd86cd6c6c33b5aabce731b197dcdf419a5b0a16b60a2ad508d39c60f87756b01455e5a2fdb1596845a7d7033248ca0537af59dc878ffad6149697971b20e3dae5b2adae92ab53181ebf1a922f479bec8deaf5d9267d36ca1ef75aaddbb6d0ef651c20b7d4a2c1c29395dc6fec161c13295b619f95e6fa8840147f9168fe19a6119e38b27b20b1a543b58c523515c40a6c740557080c685957cde05ffaac403a4becf8cb3264736882a8155aa932f856c6aa0c1210485389e0c3c9d659012749dcd098d42ad7e22f02e97368c5f0b0d6edf2a9c3b4e92454d1141139c9104a06077084257365d8de477e605a92a684e1dd3640a52dc21066901b97fd34890cdc4b14d1f44ddde3a9bfccf2eeec8fa8c826d1bb1847b96c1a818fdcd67b2ab6b9fc877b5084796047263b82f09f8dc82575fd6d02ac6485bedb3764fff0ac3048c47001170e58565a0768f200119ae527511488358f56026fd0717f6a7953bae52a407c8497c6e32cff9954b97d42f00ef537b918b4de2bb2e7eb22ccce9a1ee0f3aed7508905857c8b8750527feec2e229152c450dd7f53181a236dce46752bb377e0e9c5f9bd13bb11e1649062bbfb479b32968a1a389965cf40c572a8f78c040039c2581f1ca52cdacb491b59c1020adce6aa7106750dc5a977611c5a3a6f20d50fd344b7ab58f34f2e6a869d936334803cb2ce9dd9ac6d3a8e961ac3cb7c452bb9201f89bb32ef2ef0d0610e76b7a53232aba80d02dd4f7a57079807741136c736abbaf1e80750f4249ba2082d86466a6d3349831d3571a645030201a6f56008a73b3c089a84601d5742046b38f010acf56b87606dbf4204eb14b9439f7e56267f37e07f7cd5ccf657ce2dc3f5712f1442d8ddba1ebea9fa093307ed63f851883a72ddc91ae9b60803d2d06e7366d5c11d4877057e0a4a5dcd61e887cc763d50bfcf3af3b431456c6c9b489a97e21ed8236c165ac7919d96036062c0577c62817ac42d7d75e61b74b2813bc88042a9298306d875cf6254c2416c7fda0171fea6d2e788714eb7912a2240cb44d318910ba135a85c6d51c176c7049ebed36766c6be2c90f59926774462770d72fc4c1298c191178ed17faccb414ec4458b39e299d3ad4b6c53c7b92ffa22a31dbe658055c967e0e64cf23c3356a9b832214e5650f5c9f48d2295c3819c8bfd83070060828ae61f31c90664b08baa4c22493d4780f9be90207dbee03af26a33c2ed140d99cd61a7817e5c1f83a9991e397414a1730e81ab45ad659a2fdca0607ecc77fd0e488035f1cfc0cb8a4e51447ee3b8b7a67753067d2fa0dac6d8d6d6624c3b64d629077363da4654418468332cc255f977534cbaa49c0b61504dc84c9d8d6a3e2a333535977ec6c14dc4680675ac4bdf5f5117858e8849598fba8dcad3891605d1a47db45be32cd61d73e3fc67d7ec3bf2194dde1c0d171b82e2e9fb6f837bfa8a5a8927da535481442c38449086bb377f16036cb51b53675027b9f212c6746539f21a75fbc8181b4b7963b3b2315d187fe44b9f1ae8c0dfa34694ae51092fef5c2be21546c4647282bae4a14ae312a9e6a4881a78d95ad6f8f1a8f81b8511688dd837e0b6c68f6a3af030d7dc2b551bd3de0031af145eb358a35691cb71b8b4f58223ba3b24247c7c90fd9d2b0291e74e081871e0368f5fd78ea0f2010dbd78ce382697aa17616019db51f5cba9f2c55c31f37d39421c6aa183982b470f951db041cf2c820983683fbf679189d67c2168281001ec6ba816664bbb296658ecc06cafd41c2cc44e6e3b2aada5d261c84fe8d6e19649634a67d278131496be01dd65e1cc2081b7ef2ccfaa885bcd06a8b5122216530308418540b0bf2d9cf0d2e695014dfebcfbe1dec55d683f2cec7b3c844b5c2d94485220718ca790372d55064f09029fad542505ed32be23d801015b8775bf4201b20713b9579c0ee76a34ab9a5e80d22c1271bbb1d95cfdb659d4b426ed05009db319ceb7dc6cadf48c1d65b80a89ec13cad4111532100c5d2692f601ae1f32e915e39d4781c6c0b50a3e5734f2db46c6a2cc62faba54832a8cdc45b94da0451e3bb6b7a1c69ae56827c73f58c01aaed62faf98f2cb6de25e9062b824b733c01d5b7700aca39a538a3efe3e464adb3c900888de57181fd850b6936e3beec8403c857bb5bebe40e09df1893bd4a3349fd159eaf9fb10b830a5001c337cd10947297096d25aaea02c9aa5e20f4b41c4ed4a07558c0f6819fdf80022a2501079aa4da0ab1406265739cab5aff1fccbc30845ff537071a4edf6434302efac95071fe431ef20ad7405c8e8445a9b53fe900f56a000684733e0437dd06a3ea1417274a461eaaa49f326ea0d2775c7a793a63975f258bdbc0b90ed9bf48a24c914accfb81eea474112cf0f8fff028b3721751537121e2928363875e3ab46b9c922979e0d909074bf7db2df61d5a6cdcc6d65bcb44f3832bcbe9563b6c2de5dd538df673595317b0f88ed8de39b1076256f615ef6c8a4226c71dfe32b45f02fa3d47f829b8531400e1dcc34e1161a5320d1af9fdb990b52c326a9f239205221df8d411455c66b73f6bbc6e746855d874d9b2f13b32ae316cc17e7198eb0d6f087696c153f330ea53501ef37b61ccc1aa671bdd6072c71b40cf872023544723a5fd7e7e5463ffdee3876f76e8040d24ecd401839459ab210c2130ea9c66e7a749bc1b4577e7041750218acab8cdc658c2d77cb0b34b2af1ad2852c6182c31b0bd701ce86c44fabf7ede992d8b11c5f1aa7c7535c36118afa8812baba7ee7bc17b66a971533f9dc3ce202efc7f56d1b2d458bf951552e7daa8914959feb0de1cb25b836b9b930ccd8cdbc5a8214a3484083d107a70f73311811399f0b58f67de52f1d67f38ee779f25c507b28baddd8595eedc7a2f74cf292d092254ba7a66ea8bc9218c9921f59cfc3986a4caaeb783261c8556940b3058e36197ab4b8e06c0249ba64346e30f3eb24e3018f08f79602cbaa8ad18efe0f37db1547bb238a14f83595637f7639eac2ea6f28e2140074d19ef9c84c87508c7a87504677ac7645edfe51cc7a1da999e87f64bcb41f16605d08803be2ec416b619c633fd5acc13f26390026e9aead9e4384ffc123e27c6b747727331428ca280f5c262297aef1767c9924a5305ee5762ede5fdb8b0005bb3edd7393175720ff72474f965160c1284f629230ff3dc71dcc23ec3e29f1816b45b0a6ba0d316b25954a9208b2ad0ef608d946bd1233950f1598ae511b091cf1739b8ae51cfa42af46db0b2f85b41ecd02fc5549295228cd2b59e17a8b143bda2768f56cacf90436cdf1ebadbc532f0037ac616ad3db725b9334aa9393a659df6c52746cd6bb098cd571b44f94116ff17cd94497e6975c2a8234804608df0b03bc68f45f406063a43b4ad68943274ca845d61449bca2189bb87c1e0d91ad8b1c5b37ee82cfd1ce82b3645672dc136cf516f533b861fce0bedf493d91e9b4656915c9934efc14a283fdc8925e792feb62606e4e756d91bfd95217d4cba91a46218549df2e068d771a479af71e7603b46edd868c3416d94d6a46593f38729b805c108df7ffc72bb4296fbad212e54b1ba8010926e59c13dfe04bdec4090dbc1c0fa1b2365b26cddda88afa52ae308790e7ad8b92dac06c37353aaad83eb2e5c511f3ed7a9f0f36c5e8fc47f5fdb689308b0db340cb5114df71be45c1d7ea25ea7fd01e15fe380bafec92ee556d19e02e02f57b19704e2a104da73901d98d7da0350355231af80e11480721b5f8504798c9279903374e600a222938edcc98e6b4ec4c25a52f050091c5d3a3703322105215517cffe88d22bfed41c13479123bccc69a7b39c5fd48969ff5f63a1a3d160d01cb0e58fb48d2692ea28a08905cd1d00cca1c8823f226dae1d45de777780b24eba85f2e42c6a12115247780d3fca07d717b89d013a23c5aac9b93eef2df64a5e1f1a3151470eb430d2c3776a8e305f7056da8cb19a943434da8fdc1324f1a0e1f2dc9c26c53cf92e51d72bba30b29ed36163a409fbcb6692235dedee2a069f42edf569875e2eb5a5d1e977501b43d442b52cdbadc21ce71a097f7686f313e09d447478fc3d3977e54d60fdb5577a9759ad35b9d5ed67bd7aa7650ed0551d6230dd946f98e5c9eee80a4459553c13ce84a9f8b0306d3a4459f553483fb4c5ad422cc3dc6f25ab456a200958b4c4b82a930beba51f96b2e12a4137730d682a329587d0a03a742757697ffa9a013155fa6fcbf5ae45b090a54b2931587fc314ca31870d16a119ade2870b78e731220cf1cd0cef12a4959288b9d9fea9687463fea0a8c44c01faeded694a2dd2d341cfcd2323438f05bc75306085ce0405a87f6e18d4dc0cdefe989b1cf29b6821504742f1d9bf5433e453d8ea60b5584dad05f9ffb1713f45d82882228998d59090e5d3e3724126323a1edfb32859f2d32087cfd777c8e7154349447630318c128d478ef40c2f2f3e60d1e8a8b928412e89627bac430c3c7142e5ca11b4d412c0d9dc682d2324b17b3d15b882504ce249a202ff0959b543d1ea065e133ca6b5750be299bca63d62cfd8b5201cc37722cf40012b9311dacd047da09247103bac502945c300a52d31c278be9026604fc5a5e2c69461d9289895795142fbe629f50bec27d529a579e11d0588501eb7bb09640c80680a161b00c864b0dc218a7b16e3a77f27ecc5585f4ee743e32519b88b4436e501a14a597363512da44ca2465e0081309f9089f5adcb6b81be3ee168e7e67f53ca7cec925c2b05a9759bfb8abafbf0cc242710c8d6832c73209d6645a872c04238ee351aed807086d571a391ec9c8c8acd6383816a7234b0d3c17fbc723cd44a7341f203ac5b3d8b61fc6b498918ab03b637f0bfbfc21cc1433ec530c7bd829e6fa761bf91219df0b63a26f3dd3ee31eebcaef384ee757f12fa4682dffdcb275dc7a5ce05f85fe902bff7ded9043e3e4b17df83ff9d4db02f953e0fc4df7d78962ef2779fcfa6fce03ba1dd59de9ad9e8faf6d35cff336b67169935db1df20751d046fe48fe49fe4bf5e69404052c25b4b00031830ed4fd02f95aabadf5adfd9c71969a386dbb7fa7da5687eae76cf5b5d933d5b65d1fa9d65adfa8deea1916a6a470e6ab8d0870687da47a8380193154a090d4b01105ad5f852a956a41c036b405c19e1478d13fbb6af140c4032c577df3e6cd1b367bac0780fa585d0165433502f4dd350cdd8661276a132aa34f4a3aef3f5303dfe287b427ff7eb1f14c99f6f94c3bace3039c3e6015c2103fae28e93206ad7588fccf4cc5f4fbf08d6ecd037157e035985ea3539ad097c6104d5c6b9f8c2ffc87fd7d1a0d76bed72e78deb3262494d2f6bdf7aac7e819880d556cef53fc5f3ec2dbd6edddaf5ed27b5cabbda47776ddae42d785fc6cdbfb48f791eec3aac3cc143f4268fb30323a9f0801161180b001920411e87da454cc0feb601e0c3c8bce145ebb33ab312e72a2d99e6dfc5707ed2533c0090d75a86e6cdbd7e643a57f171921717d6b4832e8dfc40c0c0a02327f7a76784a1f99bb7f92eb77c7aca86992cf638e0ffe07855634cd7f1e33e8eb7864d1d26c02faf26966931225a02fbfc9c4d39e0cf282fe9241200c06c260e01814f464d0e88190bffb33e93fe831e0b4efbbd879dabbe0f9f2c320b3fcde7c27f4cdf20b7a25f283fefba09349c9772a8d6f9e4c403ffebf13fa81e0ad2c73c0fcd9f09b41ff650bf2cd5722df3c9994e4ff93c9c4597ebff3b4f1834e26a0b36cb1f3b457e2f9f279bed45f9a311f13e77b4cf16539afefccac28cdac686956b4ee9ea3241e73c7ac630c4787d439228f53761c2b1c1e83827680806a45484b30eedb8c925edc5bcfdb9aad821ad3f7c9bea0077a5ad08f2610d0931f04f434d9ff7c4140563bb92f6c5f9a0f9dd66ab97e43450220b260dfaf9fd66a35f4be91023648525a7a21abc5a0cda8646fcd22d98fe378cace5a0d9f15e31084f23b938280de7b7af279d93fcdfe27f4d162708ac6ff639a786cf705ca1641fff32e809ef6f8bf4afb2141e7efc49e24334dfc3f90d954fef841669392fc4db427dfcafee79564ff733229f9fe4f26dacbfe3b957edec4c954fecf1b39f940e6f8d8bc2d684fbe124de9cb3b945554a6ffc78cbd8f99f33313e7794cf17b3c74a7c7aca86cc7aca8cc94d98c925e54af1a2dad6dd98e13e8b111e85cb56c4535dbd7aee73c81ce0c074b9d0730bc66664a8ce47932168bc5cc8455289364796bd1a6c9ca92fcfbf6beadbab7d9effc7d19f706f477fc7b6f3d7fdf5add1bcfdfcbe4b52cb8abd5685f3e905951da8f66f9763c22c9f2c9a791e5cffbec08f19cfb06edfbe1242ec11454a925c70ac693929b746f2bf28a7def8a7ae27eb27ae29eb77cbc817a028a0376e87e696bec6b45d8f9044b100c5fc6ed89ea71df0eb938b766593918860fcab060a61aff8e5f964f96501a1d4f1977e8be8c7ae2fe7846e72f67b3fe032a0af4df7f67f59a97de9944a3958f012720f3e969f63fffd4f33e1fd6aa8a18f9a5393e3845df9dd6768ba007faa5a0b35ea0b3f41ee82bba54efd07766ef2c5b900ff42ec8073a9b9428953f7e13ed24dfc5f8b4a79d4de589bfa2b21f53bf8f19fb9999f33de2f3983adf95492439a232d3a29d59370df1759ec7ace88e99f338fa635fc70754f489fcb1a278bc1f336dd494b5ba9f63de17b1f6ada8288304bda4c4665f1d27d0715208ab506af3bd3dc1fea94656e25f43a33d4f5036b4e76b6894e767a2be379ee7f9fa455f7b7a4620745ac1c0b8b79cc72fe3de688fcbc73b8f7fe9de801eff8b9fc73e8f711225df5f2083ba49e7f99ead1b9e76cd61d7ad30543b7431c7e4791cb3e7814c8bba59770b2754ff039c507d3239a14c4a947a5e3fcf2b3115e9a12604549f4c4c457aa8a9e31108de97204f8f59517006e3c929425f1cf75aa825bf4930556ac9c97919d9d691926c1b3fd9f82d8d46b3b4eca5fdfd7e0946a09ec03da604ec107e1ef3a9c6a3d55e90561e36fe6a0b90d6321b7686b0323c17e03b147fc96ff6e9ab8689daf861f8ad07c5ffc1d54de3677ab331cec66f9fc024a9362a146119d40d7bf143db92d7f0c3ccd0a9626f4d185450198d3d8f09a5519eef319f6ad8509e134aa3b173e90ee1f10c9822f4cf288476f04ce2f9ba95ae98343d70688f59d15cfecf879df9808a3ee97cce87be638eefa3f33f66ced34c9c9f99fabd16157dc279fd46de9549b118599a15fda96897f4f444637cd93f3de9fc13cec7fe29e79f6666457b78766ca436736cd41dc21fc331a59c704ba318ed011c27d0c9242c584f389577561fb259cffee2aec3175b10c7c7b4e12ea2ccbdc62a3cc88053d86c6ebb37f1023020992f8b5b48a6c58a5f94d166bb6e397161afa9405ca1b9816505ebcc9406a019030497a6851953ba2f543c2dcf3d3b8f28536cceb9f34243b7a5cb55063561562872e40359696c04a1c183060f378c01e3e42afb6be7d182bd40041f0e609e218587847966e44c42a39909191c21e79c2da0eaacac49d2657712a47b27286c7f219f21eebae5a404272280693488f1f9f7826777548d6eed86acd136f4aeebba0e77dddfb33bb10d2c68ef14abbdf7deeed608ab90b5b67a0ef8736e87d921bf6e2f584ff8dbd3626bc19a9da8b3d6ad5bb79f9a9beafb12829041052103df19dcc71500d1f743eb544faaefebdb33cd5acf665f4feceaf5d65a6ff60a79ad82200e4ecda9b9d3bcad0dd7909519b3b0305164df0cb887afe7796f41f83acfc35784b00a65ae15865861c8171fdc902aa29ed0a68c70dd106f5791a99f14ac5cf90193018dd754d8c65cb264863448402f6b8909269458c95d7de097112fe81421060b143c00ab2918788810b125e513bf922431a7b874b98283b352e8e29302d40c5f60395944c8e81079c2820355282c67e8f4b7adef7f6f653dcb16f8bb77719b9428f9dfb3ac5fd1a66ac112f4eff4bf662bb26e75e8daf5ab4e68efbdf5eb6ec5e0fdee25aa8fefc59d16bd1838c518e39a660fc4ef3e18b1af59fd7af177f37530670bbbf7de7b53a73d4407c264b01ac27608133f6bed674f1838b2a880f92399f1c7448c6fa8c5cf9d862ca6bd9c354e976b689c1c134236211a42393a35dff72a8bfbf8472c2beb0d044f2113423621a11d911cc726d77a9e673d0f04b7ed2c115ff77617df7bef158dd8eae14e316ce3fa29086e8bbd2c3bea7077f197bd3619ecf41b1086613594a560aa817dab68435cbf7afbfe3b65b1edef32ff70044391ac9d8742c2875d1cbebc80e60b93205f8c7456be08a9b053db2f2684b8661a607ca87a44bee09478f9f2e2159ab459c6d5bd58f16cccc22c7ac112b39f1a0be6850ae77b23057ac1517a4733b8b2175c771402d4d72588188ef274d0b938adce66bb5da600b998b35ec2cb87ea970fd59de625d8f8ac0bd58fd791085f5da4626fd81ce170d96f35ab4bd4672e5fba041ef46cd7ad2a22b6fd54483f974e4ae3547941e334f190a0f252f5816f870e77ddaa8a4241f7205103551065a876f0c8686fd72daa1cb8786d2181c1eaca93d4bebe43d5bbf7fe1daa7f3ff476bd61275af34dbcdd6769cda1a0a69ea87877f7ded3ddf3d5e1d8c4377f1ec6d9896aadb5e23335777d3b9be1ae3befc5f75ec718e38b31ae666a31c65eeb50edb31018638cf76c638c31f6a927ea678c319ed513f631c6b89ed0230961758cbd0aa579db7a432f123a8dedfbf962b36e70cf4c2c43589de8d3613f45917d230b7a6cfb1cc0b0ff817d194e74010e4345756dfb6d9b43438648971b2104e9422d0839ac2b23a869b3860c6abb33561d5656906db77dab656d97e7445f4ab6b50e80dae1c991114c0901671d480f979ab2ef46bccabe5bd9772cfb9ee5764b939d3f73b9b1f3ceceb5f3d639890bb4a4a02dd81e9aed7959cb06a98c81d838730db9b902b1ddb3e5da4ed9661529ea097b7adf99bbc7a7784dcfabc0b5d7649d28d4bd977a9ed77d075eea7dfef4fbbcffbe834ffcf2d789fb3bf377e6df4efb7b21f476fd9bc5dfddd817adbf77b9d7f6bf5166b6c3b61fd5d86103982f2e3e4280fadfa95b75a358f15b87fabb1a222ab0a548ca6264fb2b2ddd9b4de109571a2057905841fd5fdc5bcf112c1692e072632609b48b210307ea4f534fdbc9edeeee96cb89b8d82f2efbc6902d361c71a10aeaefb87b9be008ee0835546fde2c417d87ed7afb3be8594ab89673b9909d6f0e087147c02a4bae8625daacc0e4deaa579637472c2183c385a832dbff5a61d1f0b4451550f145bd648b346c9106375bccb2c51ab4b6f8424e44dbe2bb5e216e0b1bc5da16c051e85cf73613b3cd0d7b703c82f960e9aae585b5d3d90c3b36f8e07fe31198bfd65b58c457169abf1b8fb2feb2ac70f455a2c76d0f0b6077491c75b91279160e57c3e170217ce170a8e85c3e64734f52ecfbae03e78a778936b4caf7de6b31c69b48d645397731f1beefded77e7f76452066dfebe382942452b868650dd1ca32b3fd2bb04dc9dafe2968e3911755a7276788eca0d1058d0c6aa266d0a1a3aacd0e34319059a10a2708ed3becfb65e7858a09a96dfd3961f0daf77db20a51b3f7594661e750c1b2eff768aaae1dcbb305ca4e450155a48724668c00b7c4459b2323806aa10b0942ba9638c9d161b37566df2e30fc2f6cdfabefcf2ed81410214a880e24a020d5027af10835904802499b1c48a077ccbe37446fd7217927cc4aa7b36d2750bb9cf1e85a2b3eb2151db6bf78048d61c6762e317cd9366cffda95aaed5fc10ba87f8aba7585ccf65fe144d5cb161627dbb76c7fa41b35cb55a002c34f9648632d1ef6fd5809e4fbb6a0a4d95e85fa8b9ac7762c516eb8cab173756b04617602b63f59349b195902851c608888c0061b50ff0ae2871ea0f820820f263a24d1f22478a26755c2ec7b7f2c85686dd1b6bf98c2100f3f59a210539992dbf7613f64e8b1fd3149644bca04db4590453be68241ea3a923b0a49723aa4f490c64a0f4c43465041052242c2a4e9725082c4997aa061104fd91a9dce6cd696941bfbdebce48db678a88ad5beeeee48866c77c7efb6baddd291a7742a6ea4242a25a8d8de25a424b41c68ffdafebfa7113747b9b6b86c31a040edbaf524cb4ec331db7e05bb6e3d1113766dfb15977ed69997eeca326d93ea0dc6a60ed90bd3aa556e6caeca46ca680d7cfb59b2b82f70fb7edd2c88d9294c0d9b6d1f67055d7e6f3ffcce8ab3ba281d9614fd58f6abd6bd6510d421fb22e0620266db17b6fd14d6b5add6bd5514c6050303ebaa272e607716bd96ed87a15498c5892cc6a194dfec19ab702a3452155a85577eab59f6c328f6c3acf00533db7e683fe4f29b88dac7d7a7fc695bfbb60acaca7160e9c8dab1ed835a3cb8bc0718afa1cbcd7eebd539d9f6c1cfccb69fc510c161dbcf44f4eb07bdc0af3ca5f59971a2cfebfbfabc3eafcfebf3fabe3e3619f779e5288bd539b119d9b2bc2acfaac3c2c26e3a5c87eb705051525d550da115dda402bf8e12701c0a9e4977c87e165d51f05fdc21fb14d4a02b5acda015cd16cd5fc724f02cdd0bf5af3b64ff8a4e9d6b57993d5ceade72954fcdf4cfa63e736deb5252f756d1a92a2bcfca535eb31dd6b6df6175599d96fd8e8bc70731be765415fe16f02c169e55ca60aa6c74541516f0a09ab15fa5c53d99d96e56331b87030a0794b5513da2ac941d92a7b6b59fa77295fd6c653f63855d268c086f35b17aadce6ede59417796dbdfcbba43b59aadc8dfc8bf6645a739db5c9b05d1d9b9ee8eb00af950e9fab59953082af030c20e348e086104684ed51b1b5d3fe4e07a82d60fddda2e60777dfb55ab3dc77aa287d54e8bd83537c4879de6dc102bb921667243b8ec27e772aeb3cc5e73ae1c38af52cb928ac2681faa1b6aa830830f1caaea1a2b4582b8e006c7103eeab5b596309565bbbdb672ddb0fdc3249f692ef78abab3492169e9853f8c190834aeaa98eafee97bf03de90ef9dff7f7b75256558565626d540c085051f87bfd6bb32e20c1cc9d89a9f2509dc184c3a1f94173c65d0287e6f27a9e6f7712b8fc6d94dfc45be5f2b7462c96d4f6b7585e7737986d5a1766fb1ba5d80e66e32c948df2b752fe299ca89ab3b1968f3a0efdcc8aa2a0e938b49a7557b39e50023fe7873dec644aba4e6878cdd4ad520bc6bf9eb00145b219762194d8fe78082edbb91051e5858825bc14c185c8082a36a95a0547a850e5881fd8c870031245b6bf500c28125e354c1253703c6b5184d03f83bbfdefadf7de5b31e8fe3aae15068245617d80d8af62746a896cfb56c6b544aa0afc5158d6ca56d977af5eaf8c7bf3de563b54abb5958dad6cfc6be56a11c36b36a99eb051b46ffba0b59f3d2082a5eb6b081e43f840c19717a22c71258dd40ba8fdac4e092b3922602a88753b147a2ab3ba7db6e8a214b5629081bc65335ad9755b3b11b618386e77672a2ad1b7bef93eac5edb31766774d3a6f7210f6dbeb7fa2095adc808e98424361f9f3551b67fd27b8d3c95d618d9fe1bd09068f1531d56d1730a5d1473aee305abf6dae7b56738440161c55a5b77c5b923ec8ee3bd81ebcd580d4afcbfbbfff1d2f74766a547d83886f9f2d9fa416a847d9aedef5f555cc0bed93e64b4dd238bef655eb39fc27b1004c7b364917ffc0cf28fefb42dd3be3f865fc77bcd18bec3d3028bc2f36462893fef4b45bebe37f24ce143be62662be2b444842a294061f981c70810f0048a47171ba40009025d21c4ff858b2e6e21cf54b6ed8766beba0b7ed9894a16dfe7eebb0fbf2f67fcb3fc754cc2574c9a1e543f5f4709e89fb37687baeefe1dea3eadedaea2e3974f9a3f1ffac5c9e09741309b9902bfac45d2fcf93a86fe85b02f0c3fae10f6c9be10c6f585e1a765ca676f7d19d9dddb10f6253d1e37f05af7bd6f2aa847692c4ad8db76f82595fede84f14288feddbd7deadee2a8b70ac4b0f084c7961480a8a1de90a2b8e1010464ae80e040c993a91c01fa339e4c16871e84704005fdf93abaf080911f67a4a02315ed27706170e071e071e03d15f99966561ede4879f3e6cd1b943c2dce87c06826cbe5abcb0ffb1066daed2398c137721808dd064f0f3cf05af7b929a91dc337157932f950f71dd3169d56ae24a59ff264da79b295c6d0821474fc1f93fcd08a7ee6cb6fd754f7173c372843c8a1d3ea66e71d66df7d1e4dd26412a3a0244e2ec1ecb75a26ca07eddef6e8de4ee5ecee6d55f7e0975fdc9bcf770fe3de7abe7bf0babbc05f9e4c6294fb3f27d301a658c942c7afa30b0c5441c9afa30b14062852d0f1fc79232fdfe89626f93fe6f8783c02f145dac089c053fccc3b9a15257d66597bfc1e367b7c9e34517bfc1df349495ac5ec4ef6f5b5c7d799dae3e7984f4a7cd8384154edf1b50f5d7bfc989aaa3d5ad17e9676cafe53c6694054f225419244f2db0459a5961c1a1c24786dd6841e6a3d486dff0ac222ba030fc40b3e78a61d78bfed97b703f2bd1c63936f3fb51a7818243bb84f5ed2ac5b7440b528520ea0486534a54cdb8a1d786fb71822d934ff3dd30ff6cd5fc73bb3597c247ff243f2c1d04c731a039366aa77eed2a96d7f2698df9841f8e0998a185427c2fb88ae5b3d74edd07d8c818f2d06fac1f72c06380f7eae2ac6071fac2ac62f7d9f45cee7cf669a5f7614d3a2ed5f9d63e27c91d770321904d7fbf410b5fd65e49079d4c0f712142c3ddac816f4e7af5b9be5d639383a27477f71e5e0e899508e7eadf35a9f690cbc739208c5ce06c41ee7174092e7065eaba306fa714a52c72cc9d779bb7374cc1466498a39a2cedb7c7396f1c394170e5cbed6e7470df493af63963a9ff3768b66a9f3e2d72dfbb46af1ecd8643c3cb247f25b556385c3e142d83a53e6e683fabff0f7204b4edd4273b5fd6538d1e53197a05c99e6925554cffb17195512e72c75c427bfeea21c5b149d746ee0353b7e373620661679ed7b21af79d2063b68ab01f949e7065ebba303c833bfbdf5922ee83b9ab99e005f34c17a027c6b62d3b32840d8f7f040448963f7fc0f9aaaddf33e4fbbe767e69392bae59565f734d9a1f9305ad97d7ebc436b7effd78e20683fb3b01f03dbf7de82544cde48a11ae2053166daa4a9c1054b93206ef4b095012268ba6c5922489a310ed831038f1b6460f264046aa376dc2785afd9ae3ef1878a1054c660a9004411e87d52e46a4b17234ac019d17929d11ad1171c5c2a657a8429f3c38d8c96ffae13b23b18d9fe477690418c9923db9fe666dc6caf22caba1c4e518260216744152f3264d0c490b543f8812a391ba84c504148093ec1ae5b6492ecd8ae5b644e10a18a0d1f34a66e6c3132a3e301005b2534d9e18b1043d2f87583d3f156d88a5a701ff34594d124d8756b4c934deeba35c6c84e854208b313d5fa63cb977336714d65db1660bc5b6ef7d6fd6b67babb7f3d6141dbfdcfded1e972ba73052bed1d06cfea35bff7e27b1d6071b87def3d9f4d98d65a6b2d403d21dba2ede370c9b5b37e06c9a78bae45db6a1e3c0f63cffbfba1b5f89dc89ea9ddf6bb139f628abdb741a718878bfebc863b317b2dfb5e806fefa4d513d56b169fa50629de1e887be6b5bb43872b51bd786793bb8e1218771d2570479069d1ee7d9fe7bfbf9b5d7f5cb1916731d70c7d77dd1a53c24c0b976d1f67fbdafeac7659fb29fce6a1794bedfb45d07bc540d9f765b31cfb3e2d87ae7d5fe8ea8045dbf76de80c612d7ab1bec63e64554002d62c9c31165db8a10b0e44b6dfd0e34515aa6ec6351cbe30570882e376f85528edb8ccbac3cfef149e658bf06cca3f3e7896e157f4ef10ec99c66f02cb70e604330291ee2dffe8e27bf06c02ff2b2bec9bbecf6759cf0b5814067b23d823c13e09f64bb02febe79a5f09fc7c3229119f293f7836295102fffba67c96f5bd3f959ac0d37bfc4add67368d9f1f9b4d4a94c6cfdf443ef8762c5b804fbe04f28fe0934f23ff18926645c3d1ace8b6fbc585bd5155a162c31ea9aaf836ec93ee6d7cd82fdd1bf9b0af1706fb7a613f926696117843db5d8aa578962dc01fdf05f8e3d9a444e97efe26fce0bbc83ffe7836a1954c225198d11d827d8e89642edd21d86bb35ed8c7cc7a874012f48a22afc1609fa6d830fce02f09c1ce0e3aaeef4858df6e77bf7edd7d834a95b59ecddcdeaa3d2dd1696bd5ce7e6cde9e4e507716a3d3dab66f7fa8de6acd1a605bf102d6eb30c667c53f7cedfad76c45595b6c39032909636b6d917d6cd3424a5a7a3143a7366a97f7cb7b962d6c3d9beae3fab809ada83bd13001cd0b58acb466a0826249922557b4acd045aadeaad69412482c51e44bd417d4df56393ecf4f9af548ebd707f7a641984a86076dbfbed50fcfe8debe2fc2ee50ba77f257c27f3229a9a7d2fdee646272ca210c753c0adfc8ed958b76cc407f1f8eff99faeb59bd463ef99f19fb4a9ed56bdf7ff97bb2504e449ef6ca0ad156b415c502f0fe4e6b554fe4e791d223f6dad7bdf894daa734676b15cb0f8a61f97db7e63d36afeeb0493e8e997d48fc3a32c06997f83b3829f0623f86f8de097ed7c910a3536bd581a9de69ded98e31994c8b9ba2ad55ce39e79a5506b202d4fc2938f0e0831833cff96bb6a5fc13c8ffe2003be72e528730fca1808b8e61ff87821b741ac3ed89c706dcb383ae037ffb0de8e0fad944d7b776c78e211da45b4fb2ecba23c73e7237f3bd624e879a9c0e37581c0cce321104442b7f7c663d3c3bb21ca59383a363e4288630307f5ee7b6bbbace256b02e118ede4d67f849576656bb5cacaf538b265cec3c79cadf5d1c35a179f6eae4712774d68755ab33dea8fb4415571eda661cad54ec0b62768303dbe6a0faf1c5ed9ae917203640aa7796bedb483dad587955d733eb838093e8c5cfdf04347ae078e5c8f0f649d8a33af94f6423cc06cdfa1e6de90e351e526c703879aad1994c8ed1093db6125b7630904ac5fdc795f0661a138923151e3e4e0e00c11b15a2093335aeb39395172e845a7852cb211e34e26135265777876768404095fe0e9e1e1f1788c497a663d3d394814663eb39907d5b5f9f1f11182ebdab470e3a7fcf9f1f27126889920448c4a94a2288a635906e11203e20a87582ca68180b00499080aaab92055c4205899c643891c0f36188ace05a9caf508015be578485d0dc972a563482e4b9a9010068360614c002698406747d63504403461c2c407200019e76a43b55a101c1a4f61c10900000000210108204c228104124c400105586659883a31801327a4baa4beb0a4b288c903403180018c30e42350d850a0d0686c04b0d99c6c35e1228005042080d49494951d2225a5ab5870810516e02ffa8214175c90a5a0d804c939205eb9098e90a84908b7a2db0df4228ec959536480a222d08b8e1803a83080017240b672409e643540ae7caaa8c040850a21568058cd7876cd011921ff5013bab1190a062b30c040cc4e452b22f8cbcba8561c60c58a1f51c25d733fb2fc60010b1992fb91c4079b1f4f3f7a80c9f9f8cab91d573ac2aa5db1acb5d65a6b2b0a5863722868c9a1a0b5655e13624c54ecc71064fa1e9f1e45882c346352842961eff1c7cc6a9649b4dd56c6fdc06b58745abfc49e2f6dfd7ef9cbf0b750a109336b63de5624c2671a21cd3097aeb4e8e48e6fe44c30824d18b2ed2bc5521839100c4947547e1ad98c405cd2d20ba01a65c29c60c6073722a036a9ea8025cb114abcf1d11543cd0ad3038e366468dcd0040263c4e4ba5419a34211d43ed2bdf9df21133ee8b28247f408461f2dc0773d8de8a4a517f5a6812621603264aa481128a87d18f556cf58497dad908394244640ed934d74ed52a85ecb0d31921b72b5655ee321001200c0340154faf4ece8e0c4c610fcee2c954ea6cf09ad4d20747e10ed67c623cbd1a4087bef2c953cef9d02500b40e632bf9095885c99291294b810648d0770585206880f66cca480da9fc0ac1298198cb62f040073e6459fa6598b41bf8937d18148c4af36e60c4e7048c030082808c86e77eb43bcac252698c8b9f055b75a30627bdda0a71d3bd6b0c084ca136a9f66daee90fdd22c3242ff98463e2652127a66f6984b24681ef3c58e09a38d4e6bd70777c8be8e1954844eebd7b69f631fc7b4505c3ab5381b33add41db20f42e99434ed94697fc2d8174d6b159a16cb840d9d5a2b180803c120395a665982805977c87ad1568d1a8b81bfb56aea90fd9ceb5573cf5497b128ec5b35a95b6dfb564db56efcc9a1fc66f3289e6ddfa5926c7bf175b732b3ed3b962df365bdeeb6652c06755bfcfed8a4c08bd65ab6dd96886bbd496ab55835dbbed5626f1072c26ea2aae233c518934ebc291c0e1704e786c885a370385c0f13db5fff80a931b3233615aa31e24b4622017141c6ab2fc8c5e170382022142b0fa57c3f40f12e1c0e9703760547062e1c0e1704fc022be359381c4e47268387f8c2e170247c67727e58c20a87c309f18ec852dba770389c09dd48b5fdc513708c5672dc20a0962fb7bffb35bd4f710ab12b40942162fd7a67eac16c77a778662976d79d5e5913c2bea7df44d46946c22b3eb8116f54d80f1b4e752012fb5d6128f593e23857605f30999a73c6e623d2bc1971543088fb5b0caa77a6f94cf53d7776cd8520ea3f8686564f54fb5acc659c68572c133daff3bc6c7a1de8bc4ee8df762694d9a0655585cb0a5074a202791577eaedeff5fb9f9ad61315e043fe5eb318d5a0718731193003a0a9c90e166058b2c209646a304243931158108313c21ae192a3cc83e4aeb928231f70bcf1aff09bf9857f03fc4af897f0bf68636e9c3301ccc61f03ffe775b57be2afdd1b1e2206c54e56e93a2ae12162d0fb6ee22162d03a2a7997167ee0507f7f8cf5ac96f56664730567b9f0f3a815c2d4400312477880c971c6c80f22980102117e7801070c630e56ccb8b1c2c48d07bed7f6ed5fbbfeb69b83ceaeb91c5d50d0f9807c1f93fcd52c056c608434fb9a0c53b92281a3c7f6a77d6b48f061bc42c211404e2df0b011252b872a1f4c501f4208115b4e7a38e1041bf8becde5a0a291d8fe359703041bb66b2e07108f84c738e7cfbba2c35d7339700ca1c55d733970b612ba7ca87a7d95c066f63684ddfd0edfebf7fa9bd056cb55ededac579df46dab25a3dd3de79cbf8ecb0d2b37ae58dc88e23a8b88d61163ee38059998f50540798936c0805a5c800d29516643eb636183eb8309792cdc2f771dfeac0dae2b36c4e064af1365b4d8aeb91b5b6cb0331fdc90188ad69113b2e460b812829ed0830b2ae080c4106b3a209604b1a9b8996b7b10db73234cd94e667b8d2b51861a0c775aba67d75c8d13ba1ff4ceaeb91a50de087ab66b8ec697c565bf55ae9c5f4643ccceb29d730a9bad688c111faa49f2958ee243751f8db1e243d56bf5d2c0b223e54375eaa84c15eca31276b87aadb5abeac2ba01d0c17cf3e7a1d73979f61699d2b15d7334b08458d0b00273feb288c48d873d8c974704d0d5ea78201d4c17f6a2adad284c940fd56cb5487d04c6ca876a66f1e4e6ae5b4bdac08edcab84083a16775f3e1697734f3bac7db25cfcd6a1d6c6fe7e09fa7d39119cecef653313f6f7b4dc0c33fb7b21271ac0fede7eedec8d1fc6e1b6d7bde84440ecd9125576f7b417b26b6f84d8dd57d0e57032ecee5374b9104ed8dd16257c1c7516b731d6d2c6c897366d6c70938528092db5cf6be3afed2591c58a04cca45410451060fb832b08b162ce3a5b2e236ed857cfd072830619b4acdc0872a5841121ac8cd8617544f703122442118798b3f670381c6e0ac59f2b9118431056fb7e774208626fac1034a0d8fe57e3cef36af785237654e99203122cac41ef165417161a284bb6ac805e35fb8620cbbe57cc59cb566c5b149e5ba8146c584b6b582a543302000000f315002020100c870322915012e6892cb90f14000d6eac446846158ac491288751104431108310868c210000620c614619232a00960d47cbb70fd031099484f8576724ce80e1b4eb95df2b6b6e7c8662f7a74f6ecf135900fd1fed7d7d74cc992426a9032c8848a9f260fb4661729c083fc44fb27dd42480303178fe937d5fef79ebde5e0406296a58a386b9b84e5964327a618994efb6ea8f045a2197ef7249b52a370dafb1373b80903bd228f85abadf8aab2801c22bf049e64052a984ffcb672ff39ed1c74e8080e1d81386106594a413bc1fa4bee425903e74ce02803a7d11c5e98c6a5d5149a28dfb690c22687c12b172057b4fc33a1204c57c7cbdd979bbbe5a166cd6f4d33fa96a72d3a444a825ece7ef1649a1278317067a94677abeb60d5dc31c30bc812e447d3b931b0e105e5bbaa868fc2bc8b9d20fa68303e80f09d96ba494def75c6ad85cfa74f925550695799a3df84e87ecfceeaa42c65a3157551370bdca4d6ae4c320029a5d1127755293289d6da287937fc4c4ec7748b2e0cf8a453c0b072280ce738929d71b90945901c2583107df76927d52e8e7df4727f4afb423a3fff4f9244ca171c5db3be0825a04f31fc1337d0e4d6e05ca17dc8f0ddf825824ace16271347c7f7bafb57585eedbe859238277b45fb350f5983dda6ac3be400d916e8a14d79bb5a295b010ddeca7c71e6eccee27cfbd0199b892a320bf56a210463d9d254b3db31090c93c67da1287d8fce33673521820cbd79d3d6227a7a64b87373c748a7b14c72341a486e050dc40c425bf47992464aaf5d0f13fc250d69008ff2e15cfeeceeccf377702c74052fd200a95ba567a10c54f45043e02b55f1514281902294a20c5045cbc408b11a0680f187cc63ee52270b2045cac408a09b8680117299062023ad1a0ce9b2e02fa957cea454e1f95b3cb4e8684cca86f72873fa9757768f11e5a542f392d0446ab8aaa39ec87361a48200d3191d1a1512ace26d4ae5f20ec107448139d8d5e3a0bc1371e96cfc78c49ebe9bfb67f3ae58e52fb16a75732db2d799fa7bae01d0dca835a8453184ff4174194fd27a57ac0c2cfae767451ae8bee767a9aaf2da505dc0a0f29e5ada013c09d6541ebd627724c3d2a04e8d8c6caecbe82092312309848a3360ec68a4b44646dd60c8a53000e36cea552554a4e764418c5b16fc75f9f8462095fb08f8d0511284b3c527c922ddc76e9eaebb3c862d8d419f2d215a417312b5af6886791461f8f56cdc8c3c0a97473bba5fa81e5bb8cb4e81910f4d4b3f8ba737096b56b635f8e30dc79eb74da3772062e61b5e9f1e32c15a617d786f30f13cda1be5009845d9f524e396d6d2a179aca59dd16dd40fd106b094b9be577612a18e84a480c9a0d61632cc382eb55914302e25e2813fe4c52c37ae177f0e70a82aeaa72eee750b337aca46cd87fa103f34206a08bc069f122f682ee11a8f62f096795c56ac146fd6acf9347006ecc8381b9d13a2c0373232ca65eff9cb3c7e85717ba2e98b5dd18478a15aaa37c7bb2c13b9d35e963e1146cef1d762701e87d5c4bbb977b401bebf2b1aa001d7e9dd299ed4401ec8e26c06a10de8c79ed916b16fff6733983c7ceb9f5cc363e12deb1e033f3f06517e71f38e04c999b88a6bb797a90b12376f9cd20b2aa04dda22ab2b399928a2cde971d041bb50338d2aa4fcee09bb3e422f6f4833f10ccf0eebba0eb00edc981aea15c2002dc2f702d15e0b3d953f7d27972f958a57610ccb8d7425ca5ef3c698dfe3f1c8e603c215481cfb3ec0e95bfa889d7fa2e2f47694101fd2793800e14c68d8f27d90807d50f3a95a3eff820fa142b2f78a60f413714ca0c94b125cbea7afb0ea720f8f47906d544ca10f09b18bb877edd62ffc942e9c0b946b86c1548f3b6076dcd7d2c359245fca4be7c99380fd1a6d074e8c09a1f2064b6a17cead95c2eb103a211e1a398586c8201f3ddcf65ba5170edd4652bafe91e47bcbad0a99be244666debb5884dd7659582d3b6a1a150a9388e924bd6a6082895724eefebc8aaeac2e632a658d6b09a03d27dd212fa012df87cb363c6ec846ab424e006bdaf42fe6d015966efc7315b7dfdff502821a6b5ac56c8c75f6cad2eae14a38528093762e7d6ecc4213fae99c7f012430577cef1819fd85f8f305047b85c302a6b93b49050371f1f37ea82672361936034e0f562dfae7d47aef3b2e95a6631eca09911f0ac865072b63122ea4ec412c37bcefb6fed85b5336c9922327874014080e2cd117c413598323e44e5003961c24313d9278df35aa39c4c05eed8705586ed7fda9655df53d6cc22a7425d414ecc48f078c1c9087bf5ec74db003220faa41290cf63d9f1d7d4c8d73d782ef07573b553b2fe5019551a1a5333d1537dc740fbbddc495d9766f268d284b8141771d3346b9872259562525e0324fd229557bf9d4b21588b53766f61a0edacade3d12037e812e0af24955c1d350f321d2a660ade026a7efec84e8709122e3622d672c09c00bfc28e0a981293587aef2e9124cd78156799038480f22fd711167a336a828a6f0f0d7a5bcd31f2e0013bc03fa2663e39b232f2ba6a5f03620671a9b73dd46a960fc75ffb779f915c652c8f29634a5229d415d556fadce583b169f61a29b118059603aa4c5b325960318ab5dacfc60816b5a062ff2b4b13a7d2711dc51ba62c41854ae138922c3819024271971f92cc138c7ad74e0b6d3c9d588bc65a0daaf7d337dc796c902a40ff3cc98f951eabd07cbc426094ee20556b2da70f72fa0481f902831e18bd0177d4a4d6b6ef3b03f6440704950d30589ae4539ac87f0147c8ee69c060d059099999803586122a5c08f053f0b974f59a095cf080c24e19cbb76df8ffed88875976cca26b53f178a5094878f02faa69a86e463ed1a7186ec572e6af111cf540c517ef0a228ff2d661dd9d1133b5b64d82a405d489a2f0ddc172331fcad6872d476f937dcbf6e0b2767fa9c9dea7092b700121df9016309a1215c24cbd8e8c0ccabd48ebb53e6c390337c505fc308fd29b35cb6753b7c94c05a37603201b7da6f4fc3b1d80f1eb80bbb63b1a498ae8519fd4e56f06bb7c6f35e9a9331a29b115da216201fd0d05fb127754843866cc2085c46eb7d2d484071c31e26b7be5aed97dad56eb7e9bdecb7503586e5b3f02412e76c05a6c813cc24ae262d1503c82a63c3bfbd4425146b4e43168a5fad75f167fdec699529b979934298f7c99e4cdb24e8832d1bcc3679661d2e2557abe7ec69af9066867972e29d0fababafb477174ac147f181f8806626c5e72a075c4a9cde10d9c99a609737be0c6bfe15a1bd2ca5b97390305e05ff193efe495aee13d7cc00527aa0b375835feef3c00abb878404b0683d30efca2906d84965ec3c3037e30b15a60c3aafdfc01e033a98202797f3b7e18e97a8ed87afab6aead0f3c1ebdf5aed0d1fb4e52b335ea7eeb2c6c2fa311ae62d3d34874d38681f70662596b9a2e6e6b91201ff5a236ee05f9f8b0217f739701a6558b5c684c5c94ed94c8c0141cbf0c4cbfad7a8d0346bd39d09e7e48bfcac0d0dedd5b71a87efff3a4e641919c18a8f27965e803d3b0f9f288c685def5226ef34cf33c13d3391c8c732756be38f7bb21eb3a57bc76f733ad6a62a86c01f6479d0ca3b98b50bccc1c18464529bbd9a5c25c6d59fe772e1371181e233ee90b5aec7d6ce72fa8cc86aec03d82afe854a1596b7d72ccc1e2492cde14587155d99f872f37e30f3f9666a94fa34e4821de52e714a6c35be397f58616dd5ed2069d1ede87eae23926edb8cdafd3afe96b6da635646cd14ff13094eb608c5ebc3dd821294a6ff0b3b7e993d3c1a08079f6b5a2f7240a9ad3b2530ad38782cce067566c9458929f796b6155f5c86f2b23bf2532a60f4899fe37447e59e204b6fb6eee228ee8cc15f611eadaa3bd59b85f0f813d8426d62c283bfa57cdab7d50fc2e9ff895d2aacd04e4f20f63d4b4e0bb21c585bd1cd062e1e23029cc3d6eb3b6e2029fc35e1f0d681b591c59991e9579f08012aa01432cc6c43ccf265ee2d3367951bec58bc879c1855c3c69f809c01c355a6b5a4a96264e6321445ad579be6d99a6b3371386f57d88bc7d218966909f0580ea13bcdb673548665fdb2fc443d77621e84c84f46cc1b0cb1a33049340d0bb33cd815250b78748d3f8e7d1e6d34c4216606a597a6d1d44178084ffcf0a394a48a1672ab90bb20b40c25f17b20617421602c47f363fc91c74f54d9c772fa4f6dd505b980ff209e59f3e55390d9042cb3a12cf28be870ae493cca714db23573aa9e4875e03d003ab836dad4d3772fa64c0932f10696110ee29da02f2c348dfc6b70877fa5f4555af3eaadc1d4b0679e87ef4e55c4b6b5222a656a74d9f453c1faf15ee160603e817d332e18d6c090df15b6e09356ffc8ef3edde1bdc365f8ba6b337da06fd52816b40aa56489d75d35ca56a0c6a0926e81f48e2b9e48800f56b9845b48a1f7fe5beb42d110b5eac99249fa1a3aaa500d1c5b8e0e8d2545094da2c40f633207a310a1eb55a0b243c06642f83a3aa4941d18abd805037e20a4014f5dbd348819f7243966f2dab3ff6c5a0b08f20620f64eea56ed3df0f21bbd349d2d8332a9a9fa22aa33e325e25200084ff81f7e07d68508a2fa0a8c7b62edc8222a45acbad87171f6d1966f0b126a2d59c3c6903ffcfc7c8c9944947ae430660b07b371887af4f422767b5957bc42db8eec6f30f737da8cf89f8c49dcb42c98d65a6fcefc1ac049c04df0c2006708c488a51e1a131998888ca9012d65b191bdc0bf4176edb3c4c94bf07d91e4adf9288f3f340a5b22507b0043ce2056a2ec00b08ffbf237573b5dd8625f4a0169528ced6a198a64eb99d5f626a2e0e276711f3d21ffa8a78d08206169e9e39a7d64c7a51fdb36ab61b41133b0126e9b9b50cfccbc52b836ccdabaa3f112dfded2e6698a0bd25cab397ddc9a0251877bdd82387a6608646558a0aec6e471ad124bc521574069a9604db1d0a0f021ba8a01f28a4efc2984042fe722be76d57cd3c6088eb8727edb31c7739a8a0ecf88342cac334b17e71ff034c255d48f237ed6663725fb9229e0c1ae32649bcaa085673e275835c2695cbd42a8344972aa2acdaab5106613df29058e28b6c78f0a95ee0339aa78b52135ea482159f002d2152a37da540f68d9abfa6c917c5d427a96dcccb8d9aa23572c2284b26fc63820bc12b05832f20881f1736286ee07e836698593406920004700ffa81e52077e84dd061fd221efe770572a49308d27f7b06344e62850aaf90ef7b73c75804d6c201062fe4e28c6289926db9bbb91390531bf9eed98d31e20d14ebd4eda001584f959ab8f3d718189aa25949b1da167e3cd0566d4c60ac0bd0b342e7a13c347b8183e0893fdba7190195aec0aa368b6c44b039bd7703248b9521d959666c14e30b8f01b298cd0876156ead1012c247e58e89d3e8ab48b7266b8e10fce140a429a20f4398616cbe0ecb34294bf471c42a37293a149e28142444e9b02481fb8220f62c5ef5ac90c3f2565c1286def0849fc5613180c797d68cfebbb32e17ac3580611c9cd7a3945dc30cd97e0d81d7afc5ccad08c6682615466b6ddc0ca9db459480dcc9c3089421808f110ae6a98c2ab4c40820175856e31ebaae0d60f52ea458e80f80b33282a004512bf11bb5ce31e05f1bd234d1c827e8c909f0a36d15a7d07362aec295a32bd759253c65e7f22ae4024013bb551f3a69342905c6f51a940b9ce8d673dd8bb6b2fffa80700ccdc025287e9afa6ea5b4880f9a549af45cd3753bd29bd2c3f69dca17403d45f8f462c89c6ca0ebe41b9c0edc830cf4db57bc97b5419402c57b9344ce44c735c6f4c5c78760f2988263108e9549c0617f96a47fc279d1f9121571036d2790654a01a12c25337d89148e1a3236ed6bae70210c11ac140234812d2f9bd73a7bc44d0e55e3aabe69a2691e0f19f0de224ec02345d520fe9b38fd552794574a93077231bffeb85157c06acfb3107180ce3470e2993c4b04691fd2c231848b2576a4011d0d5d1335755ec1a270ff3800a672c69e1c8ca774eeaf56d4c88b73924bf807d1ac1396cb40cad4ad9c820f5e4c377df8b9aa477773c5c1e1f092ee176cf3ebc7a482d03b583c010e6f34197c5a6ae8d0cfaecb91d6096735a0ba17d4c050ed1e141715cb5b0b05404cd3a3273a033dc2ff00726c5824d85f88527f5cb70cc3343ed727b8e250e868267bc09fe32a68445fcb4b2bcd9063973e70ed1fdce0b511cccb4102a8f9b2a5f6f448d1bebb158a6eeeda2408b1232aa6be0ef2217b7dd4b20756812dd8d33122f226a3c76788fe4c8bb012882c4c9adf38207b93c2174be7921e7ad1c111ad96d024b942b30d859a7ade0e727202a5cb1d772abf504e25dacf92e78db174581cf46de70a1a137f5ba3caf4901cb2e3fb50b57f5872d3a4c19094af95e56e82a53ab63aa3df6e016718c4f93f2a7c4d02797d6aa16833a85859eae7e33f9f3063dc2f16207a834b069a11b30cb6932ccc900b8d182b9f9c9fd9b16e332b8edeb890e4e156f50df3bd5b95fa189b98bd47225e2240f70f0369ce055b3f84d97bbc7f20f5c1ed47a551eebd8c0d03b5d7b89e620eba557da267f870a542688725c8156bb51cd27c8ba654e8bd93a6e417be1b0971149659f1d8c4b7f0d16d5f954dfedd3496643022494f5bf52fe0d08e7767c05f5b5241708f94cd2c883f15c91dfc9aeafe73c32bb0d680854dceb192b0b405159617510c167bca3277831bc03f4dc9025bf040caebcbe76e7dace24ed5e8473d32b01a31e07382e34615054e1a70d53228a5cf3972487cadd41ce2a202e7bd5841fa1ad74117928e10e7540e693c04100880964d96ca5e3efa4b7b2c6fa35f52c141dbae8cdfd1c99ce0bb5e1a171b011d2903b74e12aa1b6bd02d82b3f5ad83103dae1ac14d93f80c51ef04177e2babd28e9a72e920c7b6a7c1da6c9543cfe5a62d8a9191d350e48b121791b55848ca2739f2f066ffde3e44149841f513353004ea438c74aec134d2fb370d33baa87b5fc3bc2538ee8d643f059ae2f833f62321d107a93920f238e42c88737e42083d9f2c316c30fe52e221bd0ee5c1ad03432e772e0ec8c012357624153c67c84dc19abe453ba6881f817df13b93a63d443cc5e29d3ea91db0553a446814dbeb7f9d3e474a455a0125446da08adab8e39cd0f48ba2c19b4226bb1ee3a7b5506fb6a604f5de8846f6a80fdf7c79c8a7135f811cfa3dfec6340a9789ffd8acd60c9138cdfab1fe464c05fdafabbb13e9491db63fbb943abd233cbe93da19319437e27902119bb8703a10167f4b95f737a5e416e4b2602cf0da661fe4160389ca20886e9b7004c193d4e5bca3392d0dca99b4e6816b1a7fac828c8e6f3da8f5dcb92881110e2350b8b6847e5049065b67440f41edb76152ff5d1e80f0f59d5092d3a871a70842c3600c80c57c251c5f9bb9b3503a92d24ec061a7ad123212f310b17d776714da544099ac95901d6e5d2cc17e19b46158b3206420b353e0c5176c2159093a7dc1fa88a4419056f2f2319c43be586c80d411881cd490a50174cc0d9a80fa58556d690da3128763dc9880c7a334177a2056ac31ef81e0b600a068a03f5314226765d8ab5183a70be8b011c18818fa9481ed5f34d1543ad86690b8d00142f1c6a959e5264da894ded4b412900892f8515aea49a9469c3513024f7086a5d142b03602ab17ce4d55f61012568b54d25be47f0865791cb9ed45b37caefc04e4ddc53ad92f5493a8719151e47a51cf7ea44343704746ac124eb0fcb5907315ac5404ac83d1157920a2dcfb441b0598b110a2e05862e2f082c5c3c8262cc823d17f36c715030f35bccb054751b8130f9a514bd9348da8b636562b4835647c65b4c52c53a27fd42d7d380fb9247887ccc8ca84d2f268990bb598b9503a178df6c83ec1141a6d96c818e5937a5ac6ad44db0fc19a1bcbb84cbdc45f208ebcd5a608b484d4e26a7d603a03097b350ac1d72892accce5820c93f995291ae592d3ecf8ff14460f5009d290e7c6ac5a6be24c90d424bd7932ad15ec2b4604f21c917ce8b2b051e17a1509fe5735affbb59d138d07f98d8f17b906bbe1c791d0b2205b0dee2f6a72ca828023bab21be9681869c959e9c261ccf2da9a78d76af9d1095d45576322faec600cf1727dd0e1c255d296949d54cf3a475a6676249b0bb56e8bd33d5c5219f3a90b3212cfecb9598b751b74f49b5626d0c7c25cb81013c3aa49027cf89bcd645d5978b1df9a77e235e15245c605401e4d966f0ddf0fe92741bcba862b5ebd192cf5f3498e0c3d0b564c3f1324042cf11af561c864cbcc5fbcaba26164ee117538241d7e74afc1e1e75a23e58fcce0000442456ee30ca77f55feab4dfa16683d9ff475caba68f7d9a77fa7bc4f8d810f364542f386bbc0132f205b4f410b0af3aca9f6f4a00564ee7f8cf76d0ee52f9664ead5e41d0970375cde3e18743e3dc24567b6d8af44ed0426901578de2c3cecf133bf58eee0c05e1ab4cd62fa20d00837103ccbe01f358b965f1c9400ac25c1863bea8d94719e05d1a8df25136e0189d92052f44f261ce6584594a9b4d8c5530653b2f527fcf8ab48f82cc4e5ef9df20e060cee0383ebade175a6f77970fb3cf9b52504a73dbc5a813ee35a4a0bef710ebd04f56bd0e745aec26c8566c6117560bafe731d5e4582e49a8cffaa5e370077eb428821920973a5985de97c3e0f912ca87c37391ea1374d213102932ce600f5a3e148e629adc7604066a20c4aa710f849d0fe171ebdc3e453a699f7087b73a41d195ad0fc0aece911cf5826475a88d9720560363e3e54a200cc20a728e18f14917152dbf69e8e894139a2829c021b02db04d81b2a326b90ec832c8c2b190c316a7c9fe1274d5b1b47c2cb1fbabfca628daea5c40bc0b25205c5cb0a1fff6de046e02eb0ce4fb8c6a864ec21e3f270caa08064dd509357c49564ee5a11690f0202a307138e0cc116140a5a902fa600140ffd7f53edd5eea129c669d02bda39f59683d51a1ac947122bd0b0d1beb0c9839cbb2e22f93fa14ed0567a1330419e7cc7360e8887f2ee3e3de6aa81206e88962d92da60b8004ad70b0f833a3b17be9700e6cd50e7efb08035932b7597b0d34c663393cf8eaeb652e4b4ae2628fa6e3b01448dd14fae377c572284a9284aeb0cfa51ac74847dc52f9d0c48280dadc13484332e76a91e34860aac007b4341d818648927acdcdb42c769826d875f809ea40e56ceb21cfefe242ee04eddd57ad0d5f3b194a7f2a3df50864804aac12bb2aa89913bd83a2fb2bed0c68e4b33e299c2efad18d594e6388ff9e296d44cc816e737cee7205ab08cc2380772cb096abab460ca10ccd7030a28688b9238e005ca2682bd50b684b743946d0194ea8357f6c1c04f168a5b0a4bfa569b05f8cff63ad0720bb28068ba71f3dfd727c24d89a2aba38e8e05fdd09cc8ed03e788ee3896e6190611331db61e857b0142da5a3ecc295b9b7bc84ea7c1125058cfac174d25844c6da3adb115037a3de3969987932b9676eda2a98a7534ea36f62e6bd51b95adc65edec716b0b1badfeb219eb31d38af5cc3a1e9958c10708ad5cfea18bd8b41c2ce10a8e009a3cf5897f6bcbf92916645d5141c5424c05e7988fe0f884f34dc126e28fc07d4adb844f45eb925f4f7c58585eec3b367f136884b2342b07ee69e7d40b8ec14c745cfd145c457954617652084c2428ad1fb7e384ec6eed53c61b5a2fa41a7e28f8cc80a5aa9e1bd7da0f19c3513a68ff7d781535e0a11fc3455a3ac44c62ff859a22549f327ead7a75bd84e287d70416eac1173dbb8aeb2004d56e0360314e63905000d00cf67b9621e9b72e0271750a5140e55d960a0821ae3a3593605d96dafb2b005441a2d00c6748d669c114530872ce5ec39db47a0ef475753f12b1df4b71f5ec60f2228f20a3654c343e79f7b1f18930cd5a9e28d0411dacb601be43700616bb87b167e4d8bf02c5dfbf317fbd26a244a5c34c544a4b8a08eb8085144b16013af5b929a306738d94fb35f07c25809b25840c33ee2ac14cd599dff576cc9ccd46d35f3787204d5f129fcbaac83997d5724063e60c19decb3433e7bf572ddb387559acfff5f9813a5cf879292b0e5361d49c151dd2dc947978592fead9b440d03ab65450e0d9d4f151451224a36ac8e9873a7484f6d0e6556db7eb5ab74871381a0fcc78c15b6d005d3bc3729905ccedfc981b101640edca76745521bd2352ee69e4d21e418e99627ec983ede119420850e2413150689837d93f43789dbb95d5005f45245df888bf4adb22a7c402560347a20f8260a1b819627982c2c05eda01871d08f3038292b821a26839a0bbbed07e111f1c11880bca0f1199a78e5fd75767d58ef0bfe150a949c6aaa3dfb59c92ad82a353eb24e2a17dff246d79e954ed489d4561f549ebf0253e33c8c8b886eaaf51d590cdbb92a9b0742b8e2e5e846bfc21cfe59859f57efab612f0aacc1aa2302940dac450ad29a5bea4acb2585525a439164a877cf0fc57dd999fad5a025c1a76526b08436edc6e5ce9243496893a4df023757fecf8ae79f4f4e8410fd73e303f1fa227c185291962347dafe7ec979923f6571034e49b2af52587c5ff239c75d2341a03c250deaacdd083e5be5a7ae3daecb235b759ea1cc284cc9c4c9e8ad1b678a1718581587f2f2886b77cf0112e89770292143f6f0ee36a53979c3ad741fb13dd64244b68ff3207c1993102104122aa40e37b11fcfe32ed486dc1d7e2b74ac0f28c9b048992504b5c7c106d6e259abfe39b14487914210c74f6f44b0d33adc87a86cb59db25057566dd4f2f656fd3ee1d09c688487ac76ebbb9d1f3d5bdef0fe2c5396d741af530b0b3aee4d232f4c01170268a07ab8f2ae86870078fa505eb3247d186328e9615e482636327d1244798f60a648c9efd7f97665cf220ac8cf8a4f1e4997143a64ed8ab320d3745e762a5660a430a06edcef2a8a70aaab8fcceb9268a112abefc1534ebd399d491dbb6e8a4378658dc03587e2e29d7ee62ce4ae32b27facd07eb09c94b0d91a978c1993d4f43f335ba2322b63d467e5d29cba507878c9c5dc9babfb9f29dd7e1be06c8eb5141afe2e14c736fa1d3472b767f25d92161cbf5f980059625b3c8791ef5233d1da460dc3522c41e22cc2b42dde32e84196fb81f7342e24e4564218cfc4dc74f34d62cf72e81016a343e08d980dbf37203543e5277dcbec88afac931517042595dfb742d5933786fa7eab717014f400a8eb08506e2ed6f76cb5c96ae9391bdaf3bb331b59c0741719bd5a674f9a9b1ceff6279612560b417c3148b0d8dbe2d7dd1eb1bac7b0c819d04b0d651fe124a3bdb044c94dad92e201708518a5aab28a5a5a16cff7630db8bc07bfc875a82eda42c9ed0c91940dd94d3669f0a44327dc0c8317947b71794f46f75162902b73d998e88d736f085588efa7e31a87a282f40f9eace27ae58ee0cf186c812cf3199deb12847c95b78bd241c39b70aacd4d7fe852301bd53aaf3fba4c50d99a203180011e8eafa2591c4e3539b7617befa74ecb52fa3738dca4ab18d0da19dff310fc77560ee01397693a175b2b3c901ba2950a81e0522dcf1965f0c8ab74a1399b9b401acf5c47f483b6f13840c0a56f3aa241652a709a7343acabbb414a51ba295bcf931b51e215ac7afba8cd915b1f93eb3c8479da6ba88134eaa59cec57d158d664b196869c46d045d18e87d6e5e63fa168dfc6c955cb28eac18a0e6e9cad624e5f4ca587b250e3f865a9c9fe0706ad549d39298297344d6a52939c4a0e7fa93509463ed6a6a647cd57cd761d09f09a57dd49be3ab434e6479aea044aa3995b469db442ac5aad00f3d79441499031ea270ad8d7445610241c9df9051512c21fe968eb60a758f3ffd634c3cb1f216687f2097f097a59c382d6dea3be051aaecc5d04e9de6f15514b91682522946d5527db4c1a3eab8700bf54858e4318a53a825a206b517d23368c172ddaac59e7b357a5a7e6fc91372ec209464c598bf7a7a64349a3be47611ed49abba68116dd949fbefb0aa69838ad682d2a789aa2c68df31bf9d541fc7df9b94079fd637cf53856e769e2fb8430030c086b0192a008a3379ca104f807886cac25481301056d8553c65d1c45aa2a21b7891560f624b604b5c5921320580cfd6c47434eb330dccc6298484bea09890e5d70fd896aef8186a2c4299ea150824836bf5b8409573c9dc4aabf64a64edffde85cdd73d738638b78e215fbfa3e6783c56cfbf312bee9b9f796d2932d3a430ffed1010d09926382feea24a941ed12069a582c7ba13627cd5a387154d664d75b60840c065f0b842b0149029b7c3cee4bf4194f80d9a661e2606b631f793a0524c4ad2ecea191a05c206ebb23d7eb4f9e78b4f654faec285ab81519985131ab61c5b92f117e50df62ddbc89259704b3071a38a3a2a4c7d80e8d64a0ba820fed87468163b9f1d478166fb9ffacdfe31081e9fa5f29911db2d5dc908e83c0da4ab50c1eea0ee3a371b76dc6f6defc6716e18b6c8488caba71d8357f01b370b36cba39abffd96ded470b9bdba4481dba3184e247b5893cddfa57711ad197ebd22763eceab4e48e1356e73ab9025d89bd683760f3a7774724b1ae1be90511fa740b8fb8a2c8a2e55e27ed1d7c11488662810cea39e2bc49cf95e5d2a75b1663fb10e995b331a19eb455edc4868ec6ecef7dd57a62d6675b86fb0a290304d681b0bce8a55db49a3ed8dbc7041c09a22129ac8023557b57596a92f033ef37f528064f5105c493c8939992d678e86be32699922176b3b6e1d22f4e98d8f796a3c1985d7f46e1f904e91520e054255452961e6a07b38b83d5453226bd42a3ceb6ecf8969e2ee53e3e0d1462431203134e3ad6e717887c089daf2c4807d9d77a632cbf226f6c7e4d3cb655fc0dd2d978b0528f5df21e53196b1da2b810592ebaffd46740ee189ae9021cc9e17f2b9bf442610b849b1f71445d2e6aa44f5aba272e509bf1388a7472a1cdec5f3d00b830fe6c1c59b5de60655b46414a7832d62e00ca51cfe067dc5c99f436b7b754ab5f22fea3175eb6e9beace56be20c7d0a7dde8b7cd4967ae390ebd9991549b6e6a51505e5d895b57d415b7ed7d7cc4cfc895089294e0af2b4c8978785f52431c33188a76a01cdba34325fd391b6d644862f885fa6963233197999db8f390ca7a7131a91cc1d62a671d0cf507c7679690a974a6a3975dc46c1e77a9146cf8bcdffcb59d0e6edbf117d027b189256580174b5b5dd86ffd2350a658aec68bf5cf21a4e4068c63ad299a7b0cd3bdbd066cbba9fd847ae5761f55521c00de1ebe4e07abed501b2b31cf0eea7c35f07482f94151c73790c012584f37b8dec581a20457fd48c3d17fb2a2a83734dafad2fcc18d51228bafa5d8bd40c54aba16a4c8e848b9752a3e4fb03dc10a3666ce1ad8a552688f47c0d3bf5cf5e587c8323bb3c740b0acf312437112b0a5c8df0b632c8732424070f1059683185cf02b40c58ee1ebc120834507cb631b9da2a7f857d240ac8527dfe95263de9de11ef366b04b4d608047d75d09e1340368158b7e7ef7feee1c12b4a8812bb11e281d680783c5438d2b0f08de7a242b73834426d4542830899864c2d320a283d358fa920c3a677b5f6d802fc80eb7572408f0b6baabf68fcb9405cff55be9f142c68805bab8af69fd58e8c0b54e5055310c9a394f705f8f34b5a0b5740d156a6fcbee781df0b83aa17f916e0906342d34ae6aa70b135524e208962863666c49d6fb8f74f652fbc26c797865555b9d2e0a5506474a20f1e4af4137599f7d3a14cdd87500dbc238340a9548e420667794ef9de41a979dcf9d95eab2c44ca214ba6a5de1657b90445a1d087fb0aa4216cc90114a238a17042b5c6302119f024d6cbb45b3d04b9bdb5b55463b689a2196496927b18b05b3c94b17082ab950e08ceb6da21d5054d869a6493659b35bd4784938656aa1001dc9e4cb695b48997e3e2351cef82376f2f4f122ee73c7027ebeb3944945d2febac6344e59a877fddb27b44e5492d85e4620a1e77c33b321b3a289f35ac755070e062afd4ce1b16366d0291b679b75c8dd2252da65175015a06c095ccf889d91f069876875c43a148e139f019dadc0b30b535d274b40f41d2aa5eed6c93b38463690b6638e067dd77afe0c97fdc1cb75e034e83279a58bc8cc8a30952396752bc963efe5a2075fd4a624e1746d30b59176c9ae3e4a028b14eb449245c5b653ac1d89af2ee8987560543c5e2411949d24de545306f1c78d02f4bb7c026c8df5b1319374db5472fc438a47607c3355225f25c10a4e0cb5710f0369db67b5872529115c055e086761960b05e97d44748e41487bcac99917168370927ae8f2f5d90125671869f6fc1859a853a5c247276d0553ab17f63d1444fbdb84f182a8d44f08a3146cd7099a17d93c2d90109a808b72a68284fd46c885618c49a103b8809e80c5700e6c0f1578f841a58a094d3c7ac5aba39648765d9f603cfc44f0c3b22a6db4106d4c63cea99277222297ec9f96d631ef1b533696ba8cf7734928bf5f3abd40a28308624d1575ec3152cd7ed0aa6864b07b64240ae55a74c68b01bfd7a426a5a6ed63d3d92b6cd150b932f7e979b0e159ec034b9d7afff47a20aa062786a767ec7fd2540c9e9b4a6249f07e0072995efd229ea9cf1fd3e0fbf5783a330f39c0509c55e0cdcac8c92b7026f72469d1b2fec26887fd1eb0964e006b914b059632b997bee47c078576ba4a95cd7996f40f6b7812530e33140514ea884f8e8ad3235bbf6a49f085fdd0648d901346f1ed1a3881e82c83bd45a16e1d5d6ec0022b5f023858d8e379e317a8f3de968e3cec95b07690cf12f3e6bc87d00ab58fe5bb1df7f736a1c86c834b04ccaae98f440dc66fc235bcd7cbfb0441dde4c7cbd5402e24408af5fbde4be78b149f59981f9f29d1763262cfa443b2933ec80d80ab30ad02efe547e38487d654ba9bbfa166a05c60667002c778dacfc27748216b1e44026aba08ddb87586e5e2d79dc2b5a8cdaa534130ff634d0df548aba05bd91db82686648f7c7e8d5553b58307f19e5d95abee1c250b016c97fd958d0007d2d0a98ecfb92aa92b2099006e8f27a1fd40a74bea632be7197a1478c412fd7b29263ab6edb5f96f48d05388f79d3b2643a266bf18aa5f4966fda0976bded15542812ebfb34241153bf7b2fb76783558d045902b09324c9ee41657462224475714e82a943f87e026f94b2bcf4f7241686f389d7e205bf4092d54ce48ad364d708196ddd92bbf9186140def5128ce47f4533fb483d021f837fb16620b8b45b08f6b67bcf8685ee2b82dfc9260cb32355b6c45be0dfe2edfe18225f43813af4e56af63883356bee20cb3dc87d6692df6dfdc3c0d74b9cf11b80b43054c26f978f9db179b37beb12e31a57135cfd9d4b75a04550d9009b1d5d98710257fcd47e7f0dbb6712ffbbdcaade988b6ced8a947f73819fb90402e81983ff77874a9eabbc309bf70d96cabb4284b1f0959ab07d8a61a82d09477c0a8fa6cf3814d5a24f56591c27841365c841d51654fa2c205abbed2ae9f8f02b11ca76ac5456e4a496b4533bc07a9724557dd3844c9544cb2c0193049f38a5646de4060ebb8181ae8955b404deb71bbda7a7870723fd9369a42a6b602e23066462afb080adbb292d108e1f217aca6cade32e2ff4f8d0b92e661bc1100a7b39253a0a82913660870005c10c1366631841080fdafc9b06090c4ace82d0ac001d6455e9f6677cd09c3e1fcc47718e41c98f4a9731dd44eabd3782801711cdf21da02a51296c9e8888108c52b8f5fcae3c271f655474f2ccc5dc9ca7de474418e70d333700d50e38190287fa794087f4990045bf7f2449057f085a3a818ca8b7caba69097b501db9515f01c9553053501bc1686d17165c9a662e51c4220b68fb0970f66672f5fc9a218489801c8d388b55592834d3c641b558f004e481f064cd324b45b894aa20348753506f1b83d5e04178787c25164968a62c5be7294f60064c4dcc7e517ac2709d2e17c39056bcf3b4297b8390041d478098456c38d30ad5c00d502db09da613ed2b8257a8fcedaab1ba8609e892e33ff59f96946b5373ea5c12829030666093406a2c4e5bf3544043ce37b45bd0192163e098a21298b6ca06b36a88f228f062a8287b8ed89a0ea626a354985a4b6e657081f231b1b3649c17329eaa8b029ca88ce919db5578d27c922ab861080686353686fcd7b0f9f36b34f990f9678f246f73b5fe9650f1d6d5af0b50a37d481a80931510720ed720ade6cb491ea8ec68b7265aa92b2840efd06c7c04cc7598442645a694173064e34b0bebda83079a83c9b204ae811a6ba018c4c438f59d29a44b2268002ea0d6a9888e9a807128329bf9ba316180ab1df61fc2ef5876da132d0fa5c39e16983564b9926c60af4e2e519187fafc498e488cfd7b468c061027a2561ccf3906965f19cb15939a2c95e55453d61d235f83d4acf62008575a64d5a45adb7627d76d8160f10f5fc69243d783c4f64bd30185695de027e3661c2b37218f96c845154c0bbb0bfe8ebe93ef355888be6d2dee2d930594cbc2768e6a1bcc1b8033833b0bdb73e3ae671dd0013d84a35a3319efa6438144699283ef1db6e06a0cfd51eb86fcae1f3739d8801fe7e7c0ddf336a885ecfef1177fd18ae5488b69a28ec56441d83873ba0811d9a996eafd474d6958a672256d5688dcb305886df3b143436ce131a626c5ab44eb94d23b46bbf28c2b7f7fa788190e5a87aaac58916246c8671d59ccb7b3dbd171c34d53fbdc613820f6108525e07d6f939886673771888113a6e48e79691a5d9bf813749168310c790d9ec58c7e6014affb59b5b7cfe9b572a3159e64e90e33e02961f1c21b2c2db4844818250afdf8b27e5ea8b30097acecd0264b830378ee37681d5c1003bf35ca5de1519afec742f8a17ca7108b28869a7f2173b69bc6e3664282b7921bbd5befd0d04a4ea79542fcafd849149664c5e4dd88dad3b84d53dd72f74656656aca27fe0bd0a62917460d76fe123741aeac1671b04d53972a0c8bde0fe0d7a8639afb8da9a501216bd1784c2610816c14a41d59d4bae9b501549df79071e10dc0d33d62694b8e468f7bc716f9294fb143cd4e5cd50fefab613afa6586f1f560ce1c8f7cfdeaf6c81eca981b9df6aa786d9d4727e0fda0cbdcfdd1826a061f721b64155eaeda4835ed865d91fa868fde66923ffe5ab9baff50a3125140923c468797e2bf87df2173998a001a5e42eb1c5e7c9fe389af75640502c65ed64a1a5a8fd508020ca638cc23eb1e7e6246b6ba3dcbff21de52a276bf37117366093682eda3f87aa016b027995c6ec8632127170a68a6b061ea6017ec3c08f193703e0e095063786be6647306be7a7839e43219c7dba84af0b14d10d98a5fbf9fef7554a3f1ee605a05bd148e4c81def116b3ad8568c62c0b90e3d68091854e59c36b2d8ad334ffcaf118d3d5cd7afa38992b9f200008754ef1636a0df182ae6b7cf9dc0a4fc91ca2da5b0d3e0ec26e065f66236f5caf2ecc8f9c9c6fb29be6c1bdb75002358a7f06abd0275210736f192243c920d749e3cd9980b6a05b7408139f465db3bfdd251a065423ee2f1877b4d0c1f4d4421be8fae41c7b2778a48d6e5ca7769e1f751294ba8d770201dbcf7d686c8058ce3592aeefe7c4cfd162845affd7ba06db37b80fe1d7b39389089fbc6e8ff3d6ea028e339ad06eadc881fe7344d2d84792c471e5b3a4dcc7dec30c6f2e2d69ffee629ab46ef881dc8122b37b25065a8506f955eb441ae22f3aca8c35a50c7deefbf68dd99143f1d3e9a65c3c6ed4ff0eb7b26336525547bd37930ebe04b9c3fd8851705f46db55c6b51701467ad090c51542c1257367eaea6f7ce06e06f751b565a3509d77c914d902ee6765cf19494549308c3026e90480d815e5e3b73568fbe354b2beded7d7bc415da58b7450283809f35897cd1aafb9570c545549f4d2eaf82cc676642b16442b828bc2f89c02025a073f452aa1c8dbb0132aaaa88edc9ea622bf7cbe1b9202b854d7a03b32bc1825fc5826c3ba9facdf430389241d1e634962863b41d1ada7e88f4e01ea23feae863d0548cedbad5245869b7600d89eb54408ab723e49bbab213732b5d263f0988f7622eb7a704c92153ee15c458659f49f85718a5c2c8265eb786ea21f4ed4077bcc20179c61b3a4998031baed5c900a4e2e76b63bfb46a3dbd951c5008f26746476e868cd44448d0ffe0252b46c4a753fbcc9026d3c4386e486d19bcbcb46c34ecce1658b6d435bb063838716d4a076f544a0a5bb8787457044bc07571071a930912cd50a3cb1bd5fc564c920e08dfa4e5879b332607545e04a409bfc366748962a5b7c046e5c43c0e40f0563473db91168a311e08ba1fc959d544f1781f40617437160dd28a2641fef99d6b714a9530f361146cd40d390f341b7663b144888f70ab73f31c0c3f26633953d3cbe92fec25650a44f8fd3115a8388de3d3126edbef06a153946e5096189a0a89718f764c91e870284e053edfa35113536135214f7f6562c7035966219436aa3b1f0cdf0f67a6ac878fb0c32d4bdd2e32254103890750a224ae12a778826e8df1d1e6c9d3e764f18500e1914d4f751d0c90419301f7291b9f065cc05894db309ae84315044d879cdf7f213c4af67366b1f8341f4b98f3c43a9e1128bd858392f6542a9a3bddbc0c983b1d16eed019ecc99774ccc1373c56a20a8876ba6b77aa02aeb09e226aa5c8b5a71c015ae2d5e406b6f23c3e9983da227e8755c41e5688db4c5017ebb817d5717f108e2e9b7b34959b99981fa6023dedd0acf01b1f8f75e815cea0974e0860762743a14203a12198aa8c09ab638d9148426cc001b96424cbd619a280418d15a5ffc06bfabf3720f0b8313fc599b1b470df8fd4a57a7e3fd0745566b1f49ed8d4cfe9c0cce1d2a4099f5391d204a6e60c256d525f7dd5c6b5fc20d13a98a0ea31581027155683d1d2d7008f23051249413a8c6aaf33a07b8edc89d609ecd83208633fdb5aeca995d4bbcd89ee5d13ccff5929d6c09ddc8d2b9a9fec48b170ff6b91518b4a9f8fac38209e3d0ccf660e94ec9c50ba8040e3732b8155857dfdc8f7d4263309446e205a713adb486aeb00ee095ca815a104c00b8f594ebeb310b8e6201fcca9a8e1ba4ea7dd21da3c5a1e5cb42fe544810cb14616e0ba6b6c39443e75f569e8db0e21ba64e3b478bc1c5a8cf77124049d9a869085b752797dcf0ed29681a52582dbd64827b5d50a7f16bd9b9188a10d54b8637c84d6a21c2c6c78292ea6b9437db26b122ab599b50bd8407c22ea75e287f5c65a1d8309904526fa566f34e89bb0c2f3108c433d835782d6886fb51c106fe2e782b0aa233541f0d38a0132eec06d82b98993a6e5f13672e87cab729886bf2e3db3881862f924ec266eed0226b56edc54355851367a1bbc75f966cf167780f821e26851343758187ae748cf6ef576376f9f7dd886808accf6689ca705b272d6b6f535573c78f9e41525209a1888a9e91353fd5ae2e43ca28e9e00a2398951ec15601fcc1f44f768804f887aedf087acb1b51b6a63ea5394d76b07a4ec0b5eec27386ba91fd4542fc0010be03cee44119e04ab13f1276d5954dd042d1d30d62309aa09bac3faf831aeab222c79d98513d5091d2b926172b4e5815cf9c44b5de0847a078c067554684e99126802db1e09092d05807f6096348cf4782e4962d128fa6407548e51d0e38ab6435c7bcc4656174499dba15ed87c201243657210650d40c295857025bd894aeb050d814f1ece9563251456b7c453fe89c3950d8b76cd88813363b355b920c5b549cfa1ec3507acb4104c136956e6c7b7013afc5343585c3d1bea3c55416160720b42a591a1ab23a39b00340605151941a54776c6488a2ade0a208aeea3142aee80d5283332f8a535382c2f13b2d6b4648dd6caaefae6ffda861e733fe5740a1a52532af9927d496b741292f388c6f19617bdeb70976dea5c5332bf5a0b27933a716d452de062ae7c1dc9162a8b429428f5404be18a70e82865257b2187364071f764f4f213a2d1dd8de743aaee9aba2a0be5fb8a7948078b2e6fd2e201e5a607ee72dff0a8454b33b6834d34cb534f7af9e08e0d287f32f12595bd9f481b6d5a43c00683101abe5f92822149be465a864507f614663691c8da5f1340a6880ccdc007d0d15cd27810140d78b50fc944273d7dbebff4f1c52682ad0913e3733850be2fdc6e0e69b72da1ffb33d2e83501d5c3251f1532f0890c8cf7323e058fe9ec7b6bab733b4f549adb73522f3eaae612ae5420554d95f72c64a4a9e3c25727a627f1bca289b7e7179c85f338da2d48b38ef7c252adda771b907f8fc3b71f798cabc317769312d0a5cb8c7e5032a69d7ddaf2ff1867a787359961428b4787f64f2923ebe98bec2bd9a86ff132bc478bc72d5f4867b40b88951d0e3faeda1e353e0db7089d3a00c80bf61d5bf89d71c4b171ac26ed3a977a0736a6c29225ef31759d2a8ee467412aaeec9e9826640418aa642d2424dd5b9d2da8a2acc0aba2a008aca25200204a3e49850ead4a4e74dc698a0aca8c76bede58bfc18a6981764851d6e2e289aa2f9aac70af399b407b7fda53c2a783c2a322ea0cbd2ae507343c8ce6c56e9ace97b0009966680114db0f3986d2cf101f681650e54dd0a840e76e820aee10f582f8036b0bc2d89137227180b6789022c1183343217dee0c4b153be9192ef0c167c19e2f008b1dd4f247decfdd0263e9407e1297e8077d5e90beff1195c9ead26860be2d24bb40aab00110ad99fbeb7a74d5d57d3f4e0f0ecf12bd571abf69410e48f9a70aec248f220280eb1202510bd66038658ac6bda6a4ea3b43bec26e562656570a215c5a86bf8f384852aa87c6061f05be79f2285d9007264e2c4b6b98925ef126545fa9cab32d5c386ee15b8c66a36046353144b9c84e9bfa96a2755f42dfaa750919aa434e069e30ed3547828aa5c72fc04972acf613b418ea643bcfb226004a339301778558fbd8eea2c415805deb3da2e767923e3d6ac33aa9c7b0a67a8c9f12fdb68dee2ab17127c096c2dcefabc6b41c993205e36dabefa1dcad71933c11c237daf355c7cd04f4710315c5be6d78c37f3d69d6d3b251d3836f46eae66fbe59bb4c3c0f88547f7bfc48914ccecdde1e1d9062fcc0c252157dd8268c88175d10506bd26f9362c2491b521f64385e049e702d9e4c2ae479ba2e7798ba71e58074348a1c024390eac9282697869dd1a3cb76ddeaa91a6c279deedaf702eb118afb85bca06ab3d3c443f24aaafe4b2a23c30e490e575495b00a40655fe3196a97d5da7195fe916001cb8d833beef90b4f4ff119705fbec778b860d5e0ebf94b2e57111ca0928f6650e9d88c638075b20a89b885eb054b34d04ec13644dd283ea1ee4ac6522f05392ec11146d4cfcb1d4367c7a06e919bee0a901d63ab6d17bd64f6723f9958b786a66b22f0c6c5bb22c9ff882456c19aac21a2e603c790312d4a7ab32ee55f203abda9b1cea3c57924602d99f47965dbcb07c9c6e5e6377a9af2821552730259bbeb75969e37df73eab0df73ea4e48a5437151e6ffc9c9b8c32612f23cbf3607d5c1aed1dd93cc28fee028d8ef64f566262f61cf563c0805b7f84def4707942d0c482d830a6bd0e64b91cf887f9c99ea08430a8c1ca737f0c6acee101e3080f519c1233b4e3fdf5b1ef6bda1699a395c7493f723ffa2a81f8eb16ed7b58add5e223680cbc8dfead3a7791b8efb29a1b2d9e244014170a0bca76ed8162ab55edaa25ca8a8ab4ea9ccaa5b570e7b0ccadf6f28385e03d63e5368d0994b8950ba3d306d040473bf9427c0e315c24ccd86e044d861a8119e2fa19e3fb98ece5ec3b000874278baddc03d89c2b6add94e6dc6f6d4562ca8b6aa8eff122eadc5cc13ab011a4f0638ebcb1ed6684c737843de96bb4e8dd50c12ef5ca3926a266a811116279f2a719149962f2d65d01683907ae45167c09afe035ce3a251a5579cff9b888b7ad6a89ae9802ed5efd529f40f4c91a6efae21a6fb79a43825a41c1d4459a835d1d666d73578370e994074dd2945067ced350e26fb522180404581bf3f6d0ea0b257ca6edd56c20d77d2f89e68174ddbe83a6821e153e16cbc471997b5f96fc0788c4bbfd8ab4c97fd588e41bbebc2750b8571390cebf8c7ae0ca3c5675d19ee288b9241970ebeef1c2059f2001b3a940b10ba589db310450de9af3a2e82081ca9218f290f269bea22634ed999bc0f433f9295346496d6114fbb971a52531253ff618463e6470353be40bd5e87a64060782b7d690b355c5944ae8b508711a334dc48cf091ea1e8eb2efce408e8f6909bee41eb182d39d705122b03727e65d5a1ded9c6259a773c766ec40870d141d7a80735f7e5fa26b625ac8d86b1bfb20555cc879901cdfd5d853b751679ca546572998f46b611ea0a38e10e79023b5c5eb8e411b7d32de013710ac0f8f17d8b142ad30094660a940f5985c99369c30c4a3adcac9b5a286a3794f91e0a17a23495285f57143ee8d5589447604681e9b40ce95ddf01dce8145b7994cf84df69980c52007209d99551ab9688942333e320c9ca1cd8d2db13560acfca127a4bc84f7e8809e2d97c36a6958d800e6637a3c5e0e162c13bc402a47eeac3f08320a073bab76029109f2e1983f2499c4797845ab04a239b76470071b702e5d3735236edb0c46ef492ae52b319f300746257411d301af6333d7074d49bea3932a21cd9413e0425efb559dafc006a8e891bcd4490e4e0c99ba39527c70f6d0e282a808e9c1a81b96c729ca01c50cb911373286b8ea9d4ff85ea221a315214421192183ac739bfcbb9803e44e8e80c139e21e5c5a41f3eb2a543d36b991a9a5da3eab71593e30a167e8ed9fff78af5900160cf93a9e08456d86762aa393705e8858c34f966b15fc30d13e6b5c01583c10d3127302dfafd7b108843318909a54e28e828d3ed6433db0efe0d1e9c204305b0d22f55eaa27e7d4d65269efa2334c029150a4073bc6b8df706a44b00bbb81887b414395f905523c0c2599a2ab19379b753f8d793b0933af23029fcafc5ed2faf8c14b0420e834be793eb7b0fb6c721503ca0e3cb985886c0dfcd63cd1f37c6999e2544f9278e205f1fbcf948c7e820c6f3828092130e4bb59ee158f9866821eaa9cec2ceca2c0c79da3bd4584a339df62246c5356f6514046afea13c00dddd2897f938778d050c2540e520124fbde6fe90f7d72a853d1bd861564fb52fb3c690e80c1e5588ec2d91dcf2928fc6bd7257b3d6fd5f42db7f085810c8ca52e3b1e4b2b844e670e357b57a78022d3fc823ec5ce52a79403a2cabae14de03c7a2e388cb7d020c3c888ffd231f1eb404a8fd6b0761dc0926d3da067845eee39fbbd1811784c8f008806a5aa8ead6a0e0863d9394fff9c169d4641835f8c6e00ee3de8c67418c277169f0d120c00dd64a2183f035a020d06e1accd2125eb0a50bb6becb135200d5d305645097e3d098ec32e874e83d990b80dde96488b340736bae2201df75959b9bd904fd1c8beecea3b7a19005c44f589cb3b61111b3739042a69e04014f10346c9c15b4b211ecb1c683a01990fc386a4db383cc2c01ddbfbff63c02ffe7cfd8889d0df887ae86657ebd1ea4f0b7767a26b5d4b5d6b75c4053e382b8f8e32d0e8ae2806cff5549ec427015196cdc0b35d39c3f386e3c41bfe19a46bd8f4fcd6d81e33bdb4ecc0caafe5fc6e4e38f4531be29a7ab02722b51f43b0fefb7a040f9a21dcb0f1b194a4a621f61704ff00e60da29c2193ce09455bad3fb510d5b56d1f6480490f3ef4ae5f7cc4b5e5cd695bda1b0583f5d414951264a0faf1b09df94d52959df006512a147daf04b017708b9c01fc3d63c02ce59121629eb4cd1486d5f070d7d7e6e6a50303775bc9bf08c85a00caa01366799af41da7be820f59bd18dd792c5e066ebd4736004f28778346128fe6baedda8517e5be8807e9a4aa5f4f8ef798c0f919785e0d85b733ef60e5252189a0f85516d6034e4b81981ca7dd2a47df26540019852e57050ce08d5395905b0727e1525d99ca7a3c70673b8771805f00a9b2126f34e59902069bc619e2c769b4903378c6e497a4ef1790e69e93e3b59628538907ded79ac07ca0f9987dc86f082bda3e5eae23aab0a0e904e9adf77698e7509a1db10b43ffdb4b80574cb898b1b5687b77918a4c528477147fccd1e2016040665dd6d654b9621820b27cb7617444aac33f5a3c0d7548d753774e711bc9a84f53c60389175c95ef5db96c5d5c38fb1fb16295d583c71360a0cf0481a2afa98e50ae28319e065f634ae2e49d957d06f3beb9f8917681f456484ebcff165c085493e1833c4344192936c20b70a4426af5aee209c8e888ae01684861143c027947b1a5933753033b312f1dc773700efa9565ffd6e3cd6a29c993429db8d54d02084633bfce27efcb1293e099951d42c0895d16c9eb0779744c2a3e604e7903bca2cde543ce12b49899a503bb18537e492d5b25c419199e090dfb24e6d2620dbebfca6a5b756f2196c4f09e96d4ea51264614732eb3fa00e4cd5ab3209e710cfe7fe7278eb94084a001fd67386d8045b65b9031e4fb2982378faa695cad48e09816ad70ac62c1ae4dc0e4eab4f9be65aeab42dd857ebf62ea423d39f4ccc59e2092ccc1321bc8bf8753f4f508cb987422c7b9d46c977f70a0012abfb43ab0ff8f6918a7cbbc58741a664b0213f286ffaff98949d593912423cbc0764e52a12e4e0b51de1efcdd1942e09db4929b8bc92a4e5a064856622dc7e5ea97236a8a3411561dc85da4544af14cd505b1d5198e678cd6b41dba7e0a7a3f950cdb90d47d0195955ff8c0b3fc8987c68c4cd3620533fbdee1d2ca13f028097039beecad2bf5840f116ad8b131586b2c7396a934be83d23b9be0e4e4da975f806bdc71a69c2447744119b3ba21936f1dc1f14fc560fd8f5c8c49706e10631b1e13fa839a2fc9d617b32020f1f15c79dac89b5d04de5504a21b1c4e2a11c72e14145f269b4429672c8bf8ce3da58538e43d2fba3fe11d26627e06727eefc0342c57151e1054f398d9c95f943a53aeac43da00b8af453e06ac88e67fa0b3ced0f0a455d8a4bfa5be887bc8bc28b5088d1134565ccb80b9fb8dca9942eb525d71ac14602354daba86a2462a425f671d400898b46e623a1b39552b77324741211d5254a659b56177a9921a9d72914c6e467473df10dbeeb5cad80c60bf9ef368f84f37944fed5bd3a4796bef1a34315081e612a564384ba4fa2db5c5c81c62abc0c8fa91a03dbcb2872905a7c067f063d001b68f1cc1cf201bf783a3e314eced5f42f87b6c82c88256f3ee45bb026d59e65be9e13e95be31ef8216dd29f35d30f2f1651c91d565a9e16c16952bf4016973389bb1f4266adeeae211f47aba778acd05474ff10d55baac87dc332e05b7f3b330a2896f920b3c0a0d6ab2efb7297626ed0eba575fd4a14dbc57a236b4c9dc3027dd736caed4b5f2eee853210f48ca0ef7b385e90963350aa9db4d8c3790fc443de35a6ecb5d84e96acb60b24745c7a49dd44c2c77460c9ccae4baee2a61add1c7398e416a3a6eab04c4e129e310735734dc0b7c5205047fc2fc06a5fdc63479a63bf98e1211c5599fbd2af49d32e3687c808bff5d7b5abbaf2fa1d582907fa2e78a76f09006079e2d26898fb5c2184a807ab7db2e04e1b140588ba202445110a8c2fbd00d87dd7ae92e70f036cdd7ee844cd85736b9d9ae6127e7041e6bca56f992742516b1ca2a1fdc43cfcab2f4d392c9737fcb69027ec509ece3d915d3adcc5f5a5f625f2e867de2bace77cebd3da2947f4016da313a181aadded0665c96ef3b28339b4a73155f86184e4421a2de040901b6910fc511e43e53010242e997919d6d01e0ccdace499eee61015b273544c0b32c0891d9a1949bc289fb6f19b6d55bb2647f73c63c467eb98922ccd3549822a4c40b20700e541c0a3d08e0709e72f192bce57e76adaa1887a26f8b50695c04527a6b819957094da711c1fa20b5d1cea97e4f6b16f42e797517cef5248bf5d5f10fb764bd602eaceaf94441bfe5099aa4eef3a41e88e551a8139f8c06237fab1f60e64683291afb849cacc7285e11bb10a0048090e89835fca35f05f6d0a8baa4153582dd18a0c6aecb19fb29f848398b34760c3261322c74b32331cfc0a36043d6175740967abfa4b246110132a054965f61ae1f4271100953b34c72fc2dac8a7e1d0aa07f0455e2bfac1218c0a1c3ec6539e3146f415045a1c23a05b30d0324a3aaafdc1e7977797dd2dbd8bf97c6a8eca319836b653a34b59f2c27bbe2ad74014df0724db1cfce022b1bb16a002820607e15067b48b07dd6bcbbce09575c203a1aa95ad04ad68cdb6b6dfba1f114208d96493bde5de01ab090b0a1e0ab20a8c46c12cb51c45d94829ad74d2c965eca35bb69f13ed991633ab0499a794ad8369b805c565c7c0d56cae6e8e320c059a9d9a97e317370473af56d9f7534ab9ec6d59fb9c6cb7dbb10cf3ec1273c33c5d79745978b48c18d5f2c6edf038b92108e6f40e0f0f1e9ce60149aa343881cd17aa266cbe5045a173a34747473d13a78ff4a3a31ee7f6b16032ba3df5a827679fd8ff5bc97d71079e40a697dab98c6a00c8f55f0ca1bea58217847e11ac0f800432fdc4343a353c4f2930637f48a69f4b190fdc07e6fc8051b6a3adbedc2e5b5648d1c56351b775bf2243d90b2e05f333e9330f050c0805f23cfdb279ecaeb95a610d0b92cdb6f35e19ff4552574d37ed32cf9c1f0f1cb4000192132c41e28626afe9050728c094c0c90c33bc261326db1232d89c5837a162c5c4e6edac746237aa066e0841183136083302395c402208159cf143951464d14dc2e47e0becbb9a87d56d724c6ab2258b91c3568e2e103ae34a2154c6b02d5dbefcf42ab394521ecbb9224ef6e6de1587dce939ee5654c491614e96b3bb69f599afaff316cb51cda5893b3c62ac3c5852827179e47b29fdaa066232a5cfa11875a5d10a87d2247ab84942428d265ce4109c30e02216232a479a1c1469c4e4c4300cc322760c0b638c3162188661af52642a28d34f8a7113a3dd61f65289c58a55ea846a5850ca079583b8bc6998d71d66ed451d85f2a44ce4b6c8cd74f11cb669ae32a41ca171e4a7c4ae7c30a37457afa73c3e7a981c659e21ae26450de3ce29981517cb31a94913398c57321e6ee798d4044a0e51a8eca214d52489d6a449eeb740d7d1939a18e52ec7242660b2fc02802ce9ac9f975fad301794d18527cf39e59899b56735af6c5d51143570f065cb0f469ce1c3ab470e6abcc1a44a0e4260f49a3cc8a0ae91677dcd596b5db991e76fccf822cfee3567ad461841593926192143ae3926357123872e9b066793451b3a4089e3c98e952c92704d909cf18aa1f3a2776802e915830f228008c1ab89a40daf18e216afc65058f245ab5b83165d5e3184f0860bb61cd192e41583ab862448ecaad1d8a106548e5e3ab0e0157f0b306509913422e5c92b8649c3ab6b04c8c773928a71e2047bcf39e951d81ed515c36a50df897d4fef588c42658abd62d8111274dd39cbbd9bdd9b6bddb8d4dd1abdac809d888c67da1e7e5093ed4cb69f51a7efc316c147667a67faae095ffb9ee9438a404486501fae24be38ec1cfac87585b943c4cad4e7c644ea8c8cf794924b1b9cf53482b6894811640c61feabd59d75e6302ee1996f95efed6e77db11e9e970d899bd1cf7ce72f84ad9137bcc6ce70e91246e1c81c890d765c9fc0a9e57c31073cb302cc61e75dbcec9960b4332dbf7c378347960c7827c397bcfc41ea75de570954d0f3fc8d3f4b066469dec61e7793f9f993e71a851c1b4676c62ed953033f6141197c751d8651e2c5c20f6e8b3683ef39c06657e3a761fad83fdf4d906659e7db441996759f8419d729abed0de2e6332b86b705613bab0deda500ceb6315ab0fea28177b0f96bda76bad1b867152f698d9d66a7b34cc54821bc6a3ce662ef2dc6a6bb559462b8683e2120eb8d801798e044932778d044ff263c4ed0191e72e3d203064cde616e61c46193bf6b980c9ec36ecdb7eb8b27d1ba41f646b902f379eaf5bace764675bca53a9b2a79f67366d768b659cf482640fe2de1fe7933da83e46b9f55e0cbbed2c7bd54e1bace7b62bb74ab93239b9f2a6125c2942cb906bfdeab56ad6e21764eec7236d0e1218a1945222ae4c22ace4790570b1251fd2df2c5b07e37404115b2dfa81b95f332a77740471c396cd0f3744a1beceabd69116d3c6e94e3ab197d4da0f4a8ed276d847f39c947673cad83228f0660b0ac330ec0d4ed48d0c6ebee912b07c8d3e58ea1d7b1c0dcbb175b42c33ca1d712c628989913cf150e70dacf2d02ab3b0c72ca238624639a288d1d13bb4175b726f4a4c9e60746e317283524aa3944bb10703725fb6117786c42f1ac5615c32c530fdc49d6dd4a00b7449927ed2469873dfb7828963412042f20820b88519b3cd0de49339d3821b4a2a98158b82dc975544112a7672047c71ef57af84c99dc33c12b6cfafed392cb774b1af5daabd944c9a4b9720a4142188ca10a80f9e99328a82c8dd6f19027d86ab0c81bea318f644ad4e5c12a2943b9f97b670e9a223f7e597304a57a498de91af666329b7cc575a07498a80059c120cc595837243f924f793065b82c9f40b8772385fe31776f342dd0b720bcdf2c934614b5f86e923d50b2299749647b40ec52c9fd3300dca2c97a451c572071944e5309d6124982e7269cb0db3d43a60e8fca4584885069bfbcfdce170639f9fb6c319817243ee3eb9243b2666c8dd1795bab341e6262623db883bfa5cecc2046ae4ee93483aef324c0f993b1e6ea34692fb1c3ee2c92519296e188f7a62665473452d21de34385b71c4a6e1865d7751d4ba9a8d191b2ea58f51ab185da233375c4aa9666ba0ddbeced47065685fedb9577b4d7bcc55ab5ad5428b6dc5dce0622b7461b467abd5922b1a6e7717456d83e96fd5602421c638697737a5b6e95c237b95a690beedc37a8a29a599fd51b1a6338e8b456a0aa9ede447356c3b866198d53a2adf50d2424bb6cf66945252541c1705c218623afbc42068b9d935105470ed639e9f93e230c3f633485ab22487362b09139fe598b4e487a425476630cf75de6326b51ce5ce849b63c2b3f67eb52f70ae3c5d3e7e000d112a6204c99227538e5a074beb749ecd79ddf103372611e1256f3593b97188bb0e080ae75c8f84163a770c21c42eb7470f080c19cb699d4d7a2874c6348ce6285114c831206083372b12dcb0253188c317640e654f8399494468c18c2a9d9d1955cfe7e620fdec55662c9439e3eaec88c964df29323232324262646474c32bca0cbb0a1077cc631f0f236e0bccd9b873dd12085aae7627dd35adb5d9bda73b7cd338dcb9ee1ae41eb9b095b911b8736fb58e09cf691deddc79b48e09dc4157eb6ce7b89ed6b1e7fec34be67e42ebd0735c47a586a38b27800022c910483290b29d5b4d9cedd7c0bc6d7152dadfccb7fe66b1f442a9158f048ae514305396da684983dbbd7c59a375b06f61c424f101dc1e3d1280b6cdbb2a881bf2e46dca502f51889bbdb18a55ac62556ab2049a1bcb2e71c77695926bdfb70d5a12e6b5cf0549eb94bc5d7699d9ce711ab6d867373d918cd19ed8677f35ec41f4f598f6aa699719f779ed934f584adc27c7bda7b7b07bc8db3719a5c1eda627ee66ef8aa7754c883dad53bfddc7b76d5581af107bc8bc5dfab06ddab7ffd8fed33bf1b56d1fb225297992b74883bcc51be44d8ebc6ddf8e6a9dfef6d5b497c3db1b8a20825022c4972e3b51d3912d17bb9e13cb1da411303794518c4439a29f90cc720a152bad435b0709b31057005bdcaac12e77bb0a881b591c40444540444531c98b27b9478e4958d6585153161d5aeeb38d724357687964a741d9e7339e5c4f422a678bc37a7a219e56abc544ff47d3304a39e98ba3fc734283ddd3a03ca241d9f2613c3a829346e40ed207b96466c6da7b57ab1f045d2e1e1f9d0f201d64310fc769b5d68a55960f77ed1ca60dfa6ce7be618b43d4d0f491fbcd7138a83bf7b6f72ef382cc93fbb2e662476977cdf5764ddbb64f1ee916b27d55e650bbdf82e4baabfdc91d68cd30aa4189eaaf6e13b7e7c78f90289e0ef445afec3f4628f6211f918983f589a000d1d7134101c24e4f0405c81e3b50760d134101aa95622290c8ceeca17d21d18720865913b322803d3b10bdc54450e6e92706c22a66c9ee2e43fa2cf489f48b74d32d485bb8e44a3fb1b842dd8bea18b5a8c9232243bd2d69576e77999b666e310e57328f47a66bedccbdde6a2583e3c4716230871b1672e520fa9a65291f651e81ee32384e9c0878b7388c9fd195ebea52d1f3e34788d731d9da9e80b357cab2881126b261e30a19c202117bef6af553895f91698a67cd301ee99d1bf9a024cb0e762e991093e50759265dd192b14985200d993b46a0b0a024ab1492bd5a7bfbf8e201278e7c563194f88a8b5ef223684a6c9c45af0cdb22978b87e720f855cc4a0186ec155f560af6d5e215f69e06ca321cebc702aa2b5cf4ca321c81ec338b8b5ea7187edc11e5ebc7a258c86b0809ee1124f2dc9d3b777557f2574a30cbebc9230dca0b7ef4b352a91343c292886592be0d1b7788c888dc8167f6cc1d7b2d2b050a430a180cf4180e57ddb3e2c9cdf305eceeb6d6ded5b124dce579fa53ea1db8eeec55e62a911cb952302199f841ca33e9c8446acf84ce3b3277583f333367a5302f4f9f9089337f8cfc983853860b20a0c821e50823a3d7e9a64301ba9f613960e6a703cdfc8489a0f48980666ec24433f86210c0b8f135f3398359dd9367e2cc23e112c0172270c11233b02125a9e8c81057b8e4208d1d8ee8e10564bbacb8bd0b7539dbbe1764c67048fb0bc330942ab090fbfd385b200a73b297a1409483b2db16a67db66d32abdcddbdd9cb7c2dc86cb55ca12e53cb751f7d12185a72764b737bb2a32d9dcc501c649f6551cc0fb15fdf0ec92fec7c38ccf2e9c7066577e9f97817ea72b6f934dede7998f558818418cd2fe61f0d661f4bbe3ee6ed63c967a759fb581297a035719fe51199645e32392277f8249206e7fc8ff99f9617235cb06443155b7278cd0f99c7a2747de1e03c40729fc39b9b3c9483e2336a6bf7174cb6e032e74bded64672351c6dce6296c508c6d1166074684125cbf33801e6e484972c0f94758c4e3cc936266da1254bae3e9e460c9334c7d8cae1c1858b49315812002b3774b9b299eb977d218f6e99e769c703e3a11deaa66db0244994b2fb46caee3929c530572bd755d659cdbaf2cdeaa6e3b6741e09b741d445ad6cc6d88cb1196333e63737bfa1f4addfa4903b9b3136636c9e531a8c3c7428b9984e26b40637c94b187b57f2f768e07c68ee78593383d5e541291f6be81f7272503771a7c88a293c50414282ca163078f55b7167841040518507269492e0e1e50537fb36eac8cfcf6e76b657d0658a272bc8620237925efd55dce1b2a0b1060d6ee4c08d284544b0856114a374455154a79ea3b376ed818b3c3727cb186de0c8c99d237fe3c262ca727584d1a1829894769e5f28e9fc646e7b5759fc1de852860f2b887265082e454bc0a0428aa534b21c51e232e18651952a96968811e370c3892a4aaa44818206167be5571b90323cdcd8a16e5c57b494d708952eb61c91a28505af32a808a3c3183d2491244a132cc06c994203276dcc2004d7cff2ddddb70bd05edeca5ff995fc89447b5707579d3db40fb187f59d651968ad7d866158ad57d3344dd334ed8e8052ece211cfa3bb1be76415bb9347eb50ec6a90479893731a94b85d3cc29c2c73725a2766da7476a89b9612cf9d65ec115fabbd2b89142d14524a792645e040a893ef8c6829020824bea8f2040d91065760d90208245f1ce10595fbb3e72b9518a534cbe1cb0f61ae4c5165ca5360c6161aaa94f184cb4bbea50f5c6cc5af3b38bacff6caafa4cc72c68d3d733078831b5b60f7ec9987e2698792bf917164f95925f16007b8f88ef1b7025ed450328233d658c2060c8471250e2f9498438b345e1ce02c8db7910671251769a0c184d1972274f8a28809146e3431470d37f03266005708a104172488638a23734a982a6ca0f1858a1a243131cc463185002dfd2809c12a56310cff687029874e0c9cc77eb35a35389f7d35410f85e8c5daa5d54f96ac08d8733802159c3b4496c02522585c18a0006dd70e03777b18b66bbf726180d287c19e3b0ca61c82799ee5532f4a53725760238d33bc0c110317a4a0051a2ce14618696841c192d76cc1bdd853b0e79e82f68d856107d87307b2e7de1848fb96e19f49f34f6e1cfed42face14fd6eccfcf2452441ac92348b0f684c0970e71bbe7a9856c16d4da026396c30e8743190ed2ea2d7e41560cc3a80e4b2273c80006c41e030861e71a973b638f99ee0ff207030861878c992c7f1a75a80e762941174fe47265a60f32316bfed9493de6aaf8364e5f1be2a08bc7cabdd1831e72729c688f3d6672dfae86b01c544f8f3d3c0af5f489db8f9e09757633b98b3bb010fb0b1f64547777c541ac06c40cc2187708cbf6f3f605899d36d845e93236b8d80a67f6638406e77b7ef48c20b13957717e080b448a98e044bb6bee68731577cc735a0bee167bcce47937ccca106acfba4192c31b24b9aec0421cc20291223dd60e895d8668585ceddb65b8ca208c91bd3fe31472657a8eda7ce787b040a488112daabd0971af6ca00667d42265bf6b0ebdf7c61df35a0bee8d3d66b89e5e6e9c7155c60d7f72505f48bb76edca8d53bbfc2ca171e8caddc72ee48a3b7a6573f44cb854b8e679e67be67f6447b878801b91b6ac91bb7b4f4232cab33d1f904c71bdcb7be73c4fceb8f20c2ed260c718634ceae2881c93b8f802428e495c8449bd69de262473278551d69e706389248aa4228f245277d8c93d91b973b19d382dbd9dd3dfffca5e2ca389e644264e90f7ee5276a1902b7b563a1f0fb3b677670191b9bcc46151963990e86549e6def414ee4d3885d369709c38b673cd1cfc993b71ce297128e4ca33e71eae3c146666b20b3467ffc954b2bc779f79f6b1bccb9cc97cac0db31c60fa7d044cf8e238712220f36edb0ec2185a0b56dd17b3fc38dc7d310bb97294c6e94b232aeef3aac80808a0009364859630218838e8010c2a4bec00851428af2e438a16c06006286881155d749199c21b13802c633c081c41011761aa68f1e2065c7c71821bacc08ba3226ce872b851caa12b5202042f403285106fcc804a4c430829b8ac6087263830e38624318c244159c2fe042942ff04104bc412462c1e442c21780290101556d87111192ac225cb13cd065d1e64294496ffe6810c50833f0dca1364b2bc4cdc310097249060238e2b6fbce45571a748071c20c9c086265d182902095643472926bb4cf3e577e38e7895149b2c2a29d1767906b51281d14a044769adde0d1846652196fbdb8bf28ca0bc87c30fe4ce74e69e293feddc47b547cfc7c7e323f6903ec41dd9b32b20eec81f224ef6ece626950a259290276752042ac30c19779ee62c9b3b32b377f5105c81d385a4c16c4883d9db33e36659c619c1c5969c382c0cff88481d20b1258a0f39e401c3010c80e3993b441f407a7283d24b3b7dcfdc21f2c01c55bc329e69c2ceaa9da516463f40f442e887d0af402f444f64a84e8ca7c7073abd143019b078f5b3afaf7df25102613264f1b2971e1095620561a2bcb647efc7c88f06b19089434d2990cf48a0e0a6c6822b5dd3c53302977d2c20d9c6ea38ec68ebbaed2e1e1f3d3f4e0012a2c210163a6ec38e82b467f8ad06bd6f0546ebcae8875dc1901abc50b27bf8cadcbb8761f02e835713679ea210c4f2d1b2bdcd198847993e668b59406c100b4810bde6c3fb7a7834d8391ec33416507ceca8c1b9e37a510c09bbb2b59d435e2cc7394f82a43348e710862c47587d375a14f704fcc333e35e69ad4a7fd57f1f6c22569557f68b89a21750f490e45557d0c21352e444174b68d029b8edb3b3761586ac90827d56f3f6c9ac5d85217347e6da8bcc1defda1310e315918b98256b31c62ae364466a9466edaede91561869f7a1bdb4ffd07e827620ed425ae794b5aba09d05ed14ab3f188517edd123c195b5ac7bf6f8d22c77eb8a3d78620f99b52720f66841662732d7ae5d7b0f69b1b85d64ed51eec41846d66e3f3b71264e7dd630ec80fa9ac1ae89a33d6e71024c8e5b9cc092653e9e89a3ddfb7a268e765595ab5ddb3e9a5dad136e11c38ebaad0ef51c5d3dc756831269eed0d72d924bad790d0eaa49ad54a9d52ac55a62852157aa54ada901274e3df6715fcf8705492e61c2fda0b4759227902813b73e669984092ad7a42948840c9972244b242cbdc1e03eff344ef54ce04ce8d73c4aa47ab9a5de03736beeb1716b7018957209dc817e1aaca806eb8f136a1776b9bfb71aac24c899a7e703d6c62b4e7e240069ccd3607b28c8bc5dfb583edae9da8bb20e0b4851eddebe5ee1f49d3e13c795d9050314ee37d895c2cd3b780798a8e87583c1578de3c6dad59aba4422e5e684845622ad50f3ed93994bd5a452dc1146a91aee83d7cba692cec6b6ed336f388c21d7fcf732ef6acdd7821c936b6a785a27a5faeaac9aaf264ebdbc8d95d427bfacf149d6278bb4fd62567d31d77c33a7b2ac065fb1c1f2c80a4b898bfda90ba14eb3f2ccb8f5ab1596585eb345f549a306b1fd3acfc071c3b8653571a613506481e475f34d480c5e7461858d13cd771bac2b34582f64eec8248d536fc2a1b533b8c3358c1cd73b528825a924b5d4cb2df5b24bbd5ca35e2ed54b3046dcd645e6ce5f3d78bd4cb2293558bf6189a5c119326e1f49522553bc3ab86440132b48af9b4b2f850f78d9427a29f4b8200b292412fdf7c167946feec1b725df440f85c63c0dd6fb68b07a3a60704354ae8fbd9a3b12c9de55ad204fad5532a9f5e65adf410a1d60a2d885d2ab83f91b4c24c324a571f4ba79f4522882a2895707374c010205af9b56f591b845b180b47c9fb2b213b28cce39e79c73cefff8c92ab541f2744e1c1f120b57338ad6b678169018341fbfa0f9381fbbb56dc68e5f785948dc194f27d618a6d33b12044a667c8024c60e62f880a46404eb59a5109327dec050d23e2350229218467a3a082eb6c2d85d2bb3a942f665914bc6ca5e94b31931b73fe59ca02b2762dde7e59642dd66b5b9dcd0e61c57838f0fc119396e5f82f67a209591a1711cc97814743de9384dacc6d28d14df6012939eb00135efbcb4727445a9b31f3f507099a7126cb0882b99c82533645c2f5e1ec1366e87ede704ec9c0f0d1aa1b9ea4c8e9051e68be6a38188ea341f0d332a2c934c1cf9847bf76d98db3e2ccba8836ddf867924601b66019139734df3cdd79c324914f7e7046984fe98c15d8373a68d7bc24f8356e491099c387249eb9c4eaf73fa3cf5ece9934b66ae8949923c43af87bb308a21f23e3aabdce750269149e6e593b853d40397198840430829906823ee1441d9b2450e64d0408b259c78d967477d2c20d4694e8389a0f4512f7aa53ed6cf8be6452fb9e409ea93513e49c5ca5183f3da27af345827365d399e19b7cb6dd5163aba5c90056406f5e7092b7a90de45cf831e01c129d38ff0e3c766d576f30beafefc074e1ceaa3a741daf28b7915c5bdb8f3ccb8f42c24ae7c9cf30551279436d26c628f9666b4528a6161605b563b576fd7c05fcc0382f96caf386ecf70985d03c3ba5d7a41362014c8d9b7af33aa61aff559adb4048a0307e600e5d9d5fede637c7fad08ceb754f0be9b0fe9bed5cd0a79a2562cc418639127a70db88b635b8c52d96d70ad5333bb7db523001dc4d983e3380e01407287517107c661391f410c25946747efec8672046995b30d2979643c66845a126cf0cbc974b837c7a4286ce4906246dc538e49515a90b31aae97635214a51c52a4ecfb4d52142639bc995fb85a7462e76694ae3d8a9264e2c44cb1efa6719ae698d4c417395c6533b81b35ae8c15abe0c4e6c4e4a4747663ddd2a78132e5b2d50fc51e31d75ae94c21890c1e94e062c4134863e4c004225001192910838b4a82b9841a4534318339b038e355c5e0e0890f4d80c8c11855bc2a11b94e916ba571e386b475e83bf6e84ce77664837fc328941f36549ef4a89b2e1edb1841153b1c7102ca1546de444a0d3e5089d2c6d1122b509d45e2861dcdab5577bbab61b71873a588243288c194212216738ca1c50b6e580ac30d254ba05067dc70955b376881ad371a58a45b9432bcdc20046070b1e445932819c19731bcd8000a297508130051b10b831bde3c736ef2f46188d22d4a712752295332fd08db6ae2496f5e58abc118b476ae6b8c9e111a940658d245a162f6acae9841c7154a6a9df3a8063457c8f0c5154fb82b9eb02e70a30a2f8c4032e206367a7e98030b0864f06409172950a49ca0ef32801420a28cc970d00529c7284639be5b1e91ae2eae7c946cb8e65d3daeee05cf337198fce811f2538b644b1948e98426312ab8596b3581163648c973ce6a278f76c9d66d412ba726c7a424a0c837c7a42490a853702c07f4e78180e65912b720b33c58a4c40c407c9932841a56605884a96249066970c183103df3477f62a279a27e11145c3fb67ee4ab71d1cbceb15ae9907283266870b1d264865711122c502a4329872ce448028d25d4cdc9e1e163043087878f11b27339432855c10b231e3c3e46f8f10324a4462e8ee48a6139bd13b11cf1e0f131c28f1f20212aac80d17a573e1c49296792e250a8e3a0482f24ca613cedc2f8c85d19a7ccc9e1e16304eb44cffcd17dac312bc2d0a78f57a9a3e0629bb2dc793b43e0760420cf988a3b76e244578c214cedc97dfe1132249e8528a4690e21c78710bf13cf807813e252155cf440871b9342e0430ee5132749e4242c5c72bc22c7242c4a323763ca72431e308a64e24b087e7132f39e9ec1d6de6b678cc7def1184f8ed894e566e7aa67c2f61664e65ebd56ecd1595e3a893db6cbcb24620f0eb7362c89883b70b861fc42147bc85c9e85f841ee997d91181577c4837327157fa2873bdbd3f1fb20db2fcaf105fb98dc67168814a14701468c1821830c0d0ea1aecbdd906a6848a813ea3438843a0d0ea14ea8d3e0e88628cd26d35010aaebbaae13ea56434cac6005ad82aec700b72c91e5c12d4b6839389d4ea79309f5eed9515f0deaf485369f50bfa86728940a1544f5d42f2e928be4ec3a66569dd5fdf40cab30abeb4c5a0e503f6939380dcd1c64ea4ca88e86e6f4781d5f78c24353cb418c3d54479db64eaa883678baea8b71c7e9de74bffae9437d21918c4a6155a752851a90f735f7f2e921cda8d35128d36f5824874333d7dcabb9de17343473cdac09ad551d8555a8b8c3c61df31649420554057352051839caf20a30726483eadda7ba29757a967d3a4c1895dd67efbe1095bbaebbb801451985b39b740865d44d3fbdf041be349706b350b80145f9e2d385b2a946070a95b20165432aa552ad6a845036a8542821d445ddd30985b211521d750ef58542a81ca442a554adfa64567df7d353fde2109555aa1f3687a88c4209b1be882186c482925eaca030caf22b288c361a361a361a361ab2649981e6dd47a3c3f4d34dd94d9fcd2a3399549deae2672693c9f4f64a08728f7af6d3774a61960afb5c1c89e4d3331c12c999e9ab410dd16c3aeb6442fd1ea56306d40c28940e1d281a9a55cd0c9708eadefb4d0930c090e1de7b2f4df6fb4cc7553adedd67a99f9eddf485349b74609fd44d3a74dc9fde5e0941baebd33dfb7dccde61a2dc3dc344f9fef49e793a3da50383a0e56667dd9bdee18b7d9ea291e1b4c9703a05d17434384c9d3ad517deb6b1b9df64b8f7cff7debdfd359d8e4215dd9fbca370d819f5d5ef17da7c7ffac222f9741d38a4f93e950a353051575de63eb6cee9a9af67decf3bea8bf9f48544aacb7ca54271325fd05067956732d198ce71ed05517d32cb7c21cdde7bdaf4754e1df58534a33e3d9f13ea3d13f56df7261aec73c2b441cff4dd7b7110f770a82d91cdc68617d68bce568608070e46566c386c386c386c382425696fdc77df45a5de71a62f7beaabc9b0ea59f714cd5327d309b36854a7d380a9a76eaa39d75deaab79f44eefe99a77ed95a06ae1e6175839fb2985592adc80a29c6196ea41d9bbabb277cfb277343f3df5d347f38544722a759a87dd6b30085a6e8759dd4dcff009b33aec933acd53a7e950da1b34a99bb43752bf6988e620544793eaee1da2ac13d9a4aebd913ae1b0289f6efa5236f7629ba71edb749b9e99fa422239752ef5050dd17c0a87a8d780a253786b9ebaf97ea6ae3a2a75d553a8d7600fff8899a54a5d95323d8563837788b688b03e231b1b547335607191271712881c3366cc98219a5b060fb06092e53dc082c9919439f799863a9b1ed2ec3d3471a6af032233eadd87baa92688e627aefb4ca7f96caee3266c3a9da6fbc256eeb22eebb22eeb329a9bded9d8dce6a7675fa8420ea24afdf4af569795c23eaa8b6383a79f300d0e55c8a667abdf2f3cdd0683a0e59e30ebf4ee26dc8f9875c23e34376535e76477efbb6b60017948660bb820330dcdbbaee6a6d7e0f0621afc82cc26d4439aab8ff7b041a0e30b4d8f5f7da149f33e271da8e150825e9031dc9c8885a1708712727f41669973a76f355cec31c71366f93c9ffe2199593ea7db9fee82cc4332d3a0b0e9f47c7a36dddca89e4ae17bd5171bbc385ce9dc87a86c7acde97493a906ab9efa62832a1cde7cfacda7c7de615d75fa35852a9cbe50a8958350f80599691e7328d4ca34379deb8ee69399e6a9b7e7634f738ee63b9de3da0b22f3e90b5bd974a2f9e9a84ff5fb85ad7c3f3d1fd4553d93e6eb7cbff07e3bf56852d82736683a0ab71a34fdf4d309077197bf58a895b9470c84bb94b9cbda17aa90a34f3ccad9e351ce70d00b7f41e6f085ecf2434116704166799fcb90e5cd67c43a1103c68c19338685a1c8dcaaa9ee9430caf31c4dc1edfbc42bb27c6ca36262b23bc9700cad1714ea46a6980584e5e32181e0056924b570365fdcf898ad21464b52185eac603922298c29496128916118e5be67bb2f612c981c520b1a612306466280e48b29e48892a4749494254c8e49612021404b99454b52162f59ac2465c1a2c4655102292da598dc59a6644992c39b6396279d94ddad2426cb0e744e252fb975c821cd6078c9392629e190a4042649c98c3c39906760af6d9b6633066b659939dadd2f0c38c2c591170eafd9f363eed057ed5e3adca3bc0fbb99cb5c08953b51e26c51d3fea8632dc771c73c12b820de3b9a63ebb4b26ce978bf38b4760687376f58d35a59769e4f770fc76f66ea69e73e9939fb43820b2a34682fa4411dae1066e16e38ecdc36e77e5c02011b77cb31290b2a6a1559289143cac3862c98605a6481e4a6ca1976f5cbf3a3191b71e48ecbba68b859eb9572d06458a8956b4d52daac6bbac1653c5c2e9e2fc07c21c648e3c4958b96b1aa9db5b70b2f8d13d700d38598c689d91ee98471a1946151299623d5893bbf602e2572fd4d67ed05834ae3449bd92a4b906bad59e60513ccdaa3b04892eb6f6aad58d6c0b080c1302c90d8aff5bea97285971c7e268a3ac3156180495c2dc7a42bb8b8a952850b658efd4829edd9b02f64f974674e4ae9e269305ea398cd5ae66a1771f28ecccd9e1e103871e23bf9cd8c659dfc9a27f31e305f2e1610995bf293f98918a905e79cb315e36c99630ea531c6185d99c5346cc3b078cad126c78e3891079473aaa85c79ac3eb39a36edcce66cd178b5262ea533d2905aba8a5206577e4619678e0dce22b46c5332edc4e66777ceaa071ad3a886b14ff929ebabc4183d150dcb6ca5dbf789b3baada3a1805dbbe601f9409ed750dba474c6c06ad4562018900f64fa3ab1dd6260358ad13728c586a8954ea2dc9462b576b65f47b07a606695caace91336d6a42b96a0c260f5d5ef23a2d816c58cb006a098912a998091dbcb3d0449181cb49800871818bdba088719d02043890660e480c1ab2598dc8dc40a2e793bdd50f044dedeb5cea5216f476dbf390a236f6f6d776d6087ad2c91b36756e0c8d9bbac8a2372f69bd66140cefe2a6090b3b792aca892ca68d4b8e1ca94821baeaa50c9f5b4de52d143aeef2a15306040ae2b9bc17825514141a6f4ab1f32a54953acb1a453a918cddea4f5a2b3ec72c8118ba87e575445862c6ea800cc1626af2e7a62e5091b906144060f5a5ecd24f7152a4ba458220731a880e3d5455290c42011822d9a509282571781940509f6a259bae145d86a5032630ec618238a151ca270e228c6f1c30b984803071fbebc21b368a2078e4877d6de1092a25823cf77931b5a294515b94f5b274a23c923e4cecc14bd36d517d7ce69a79d1689fce2f6511adc0c8e2c48aed66101912fcad9cc19773e9352b08879f2aa1f5532c56bc60c8924bbb537cb4678c5af45af8a5713277b7c659f99e36e0f7972167b74f66637268329718b5e45af306e09b12c4f3f4f1bcc6a6681c8dca9cf2e64eec457d6c5f3de7d34b3da23c185c62e04f9b909f37def11830dfa700f3f909b725f8c52842b438eff82fadeb74f06871d0ea3e7a824cdd6c4390c19aa19010000028314000028100c88444291582c9a06bb2cf714000c8daa44704a16cac32c8a51ca18638c01041000000022222343d3060007ee4fa3e6eb4512a8d7e614f143b3de4f9380675f89b1d4be0686649dd4376a2c99f9df78c8b20a77fa756648b8951728d94a16a0c74797b5c7f2b4a27bfedc9b38ebc02636ddabf0ce4a6bc901e320b9ea5d6b3e6ad95940af4a7f63f451e083832a07c1f29bac33cb2be4b12f9e15452bc9e379feb4fb6cb4bfc60e156e734e1132b0fb1a7d1e9e8cc164b0fd6211b3f8a84eb8a6d8b40381a219455ee69b10427b07088373eebdd463296be8267c2ca918edaa6ded288b311d83037a694a8d345a26d0a116bd6348528b2ddad1e098526a82ce98793548b3232b575f62079e75e8f0fd54d6d41385dbf0fd55e956796f38c126f332e55033dfd6758964e0d20305cd6e94e0430762c4197cfdd870947d44f68e520fab1b550b8620aab030411d376dbc2588a38cecbe5400335f703ac9b5ac70188c34d21f6b08beb597e86a825b0cdf05fa5c22672d8d595e6bd4e670df96df613fd6de355b363341e541ee2c44de3fba4fab16135aa39b98220280e2921c7766a7aba7c83565e8cc56de6705926b374164593798b3807da58fc9631ae23b0a1290420f64d6ee1f77de06777833bb7f0fa2211e057160acd9b5f00dfa685501dc0002bf1bfddf09b35b97835f401e52df389ff0af7fa0ebdf2d50f7328bb526bc79bca03de7070aa2fe0776bfe9bbe62f6797383bffe52c11faa05f0fe6f61bd1e3d71bcfdfa9ea5400c0640f83d4d9ce896c0c640685e16f0e991f5d5eca6dd365abd639eb95f3a82fad1505e79ccf3935a17db99199f5f218f68dcfa6de50d3cdc80216e620f069d141f785a9e9321cf36b24519450aff44adcad4a5b9c1f1443539bd7ac13ba2daff72dda857f1926096c981a34bd32ef88f2e4e82b6e98fc96a786b2d0b58e44bcde9ef358ca9d93f990b592b974ff2f4f3cbe9ab0641481574eb2e519d3cc54c10b5b47eb52f862a0922c970c1c2cd628fd3612a16e85bc80245fa176cb5b7c37ebe1dc2b10231f73e875e5e674d3ca8ca63cd2a5d754b1521a62edf41ea715f4e36f7097ca92bb2389642067dbbc7ba89545f215a38d924ea3f3bf5d5e7d5711d6e57f2c8608eda8b0e6774e838c7efc5fa9d5184388610f5d76bb572d27c5fefbcfd53f1ef0615d93b08fe4923b3d619081f17d22d631deff728f6f900fa11be1a3f17b9936a52681561d090743207e460419ba4198ef199921550c6fab7ac3982fe6eda40ab84e1ed8b415a2f60f73b32e56fab8b3455f53c2a9914c5e52d169c9b3763239a270d18027e9505f4597edbaedcb02b7a57fb0210c167358610ec5651c21d01fa9652bed1fb0bedeb20dd936bfa553378cd6916e96ee3d5106f030b7527079c92dc29ad8fbf6b7accf7451b8645a3b1632a334bfd2f089a9c24c601fdda8ccbd1cdbbee353a35eada231835a6798106cae953091415afd16b4c95a3281fb5a870fe783f791d7cbf61286ba3d06bf19efaab8750fe189c76b284e8188204407a92346850572339bf68bdb3ef5dd00fa62c4a070ac1003a0d5cff1b0c10ea29148f7a68ed56dabd112fb479e66caeded8361095289ef5576d0b079f9c611a4d121650de6b865e0c925d7fcc3482495bc61fd66436298db79378d29a9180b4227f6ed0dd145527220c650a375310d023b94b32f36dedfebb59215ae1af5ec0e0be989267a9eeb9c9bdf5c17568d7bbc691b923358fbea1712c6529ff14e30f67de6da943382e3f6bb23cabf7012ac93c0f07a9418e80e6ab4f7dde1e86cad5d5778032cbe7e01db5a50d5574822c3afad7b312380350a4cf8756c4fa0c93a91cebbe5b1fdcdf642080a1a879cef15ea6b388838c84eec9d7872719d81b78ed06ebeb354d9d9c608b2c4081f9ba4c09d6a8d84eda3509150a4d641f02fc997e29f016f69f98de0b1df645fade5923820e0e2a0f413b2259a0a7a8ca968a9c5a551f106e5b4f2c44d3a544df7341c018c970cc017b23e31c4b69bf80039142d332b2bfc1e10d1e97b9db52d751c6b0914eb9f6bb57cb1a2ec81d7c3eedd9160a13f63835ff09b66504b5d4c5424116af7f6dd7d5638f8ba3d802148e2a766fe3636e7f51023a5e017d4b48fdf184ca8fbfb8ce4290a0ad7a19347d999389b37f60720f69c7023faae3ac6b609d937cb0e76c556f640be7e612d0db8b81753890a0892a49c2ad25966dd6e61fa686eda709f034cabb47361733ca282cc0dd977d52e0d2ba187ea1ae30252668833c1fbf238346f3fe336397fca6c5ba642205ce09a54d8d391acb33d6b482fad788c9d26c59f98acea67558a66bfcbfecc87f0c6cb37ccfef0504ae035de64bf1b99c8e88dfe5aad5ffd0406742e10e67c712fe80eb121450f6cfc84eb7721b3677fac96ce8a7fdb022b9b36e7a39e2a8a54a12d11ebfd9c2e552dceaa58a9706965711723e9a1294b1904d1012adf8f3275f890d7264e17c05ba7b6b8b2df4efafff5e3bd35e89d67129dc6c7d42f7503256c208e9fcbd53322a1d3bbecb7dd9908a0778e7df509047adefeda99893c7a2768df770299f436803eb0843f61695ee919a4572fd588a10a1316dc79192578a20c1cb9801df46201e9d51951d624b8f02163707fd04d114871f88f518c6293b580b26f8aae3cbda0a60862bc73ae5d2c4a79448643f94aeffcfde165824c6fecb2688b7e077a0572d7d0ac4f33ae19678f0f13160a2bf23be084015d27ba11492c90e693ca54698218e189347516d020ef68572d70f03c74fbc7b9b1e8e840d7352e6f4c40a2e68c5ea1b22b0298df1040cb35da9d439e1662a648ef3917dd52f80b3700ba71ed9f27584084d4f328b6259e5b15e1b7e59e9ff0f47894501388906edc3a0cba61e97c8f84258e7ca57c1328a1046f9a05930185f0bf5597c45bfc9e5d789a827601ae412670ed293f1135a2be2c43520e974f4ceb592e738889e7d4e16f0bb20d6b5e922503d6c00ba12f233014f080d5d24af1c5deb7d65c9ad363499d7b0cd436296d61e54773f841755e1502e388d83ec25fddf8b560dd74a1100d4d2716e56a2239b30d47db9ef082b847a004db0a2ca34717983eae4e7b45692bfba41580b3534b06b4269916b826040bb7a13045b1b365b4a50b55025b2be1f769768b9600e932e88e92d62a47500b808b07fbdad7e69ff286d3788a44939132b3ade65eb1e9c01e9288d59592b4dddf8669bf39daaefbc1b83e1f933365d1a6ab4109adbe0642bfcdf58b46756947b36e6e047fc545b3a1c52cc8af3efb52ed907bf690586b44fff6242d45232421193025afbf2eff766c7b4c55a31e9d3fa3b2c086a3c5ec3fcc6f4eb88f5c8cba849b3ecc2f9f2f14e879ae455a2450ec1b02c1d0f0892b138d6f574dfbef3df1f46139da7b1eade4f5be982748e3c4a25daabce5995ea099be5fa8d6981aa84022a1497814bb83b07c877a36eb091e2240d61ce99a8bb06fb5ae570aab9b5ef8aa5d83f75d2a789113922f0a20c45403c607d6bb324fd39776118eb15b504c0feb106f57312d5242163dc58a202234f6a47d1598966c3834270990066cd024258e383ada5ad4b335c3f33978db5a02344c559b28a368d5b7f08a17a1d1ee515d9340ee63715343d74c67c7747145f5a43c1dc920e91706df65f0ae1db52259effcdfddcb5458e402a3f91dba7141832afbfe6a8d23c8d994cf55071afcfa90896eaf671ac2aabdbd9c3c9d9fd97caf9581e1b5243312eb7b8fbc56195f1980d03d5f948f290aed945d85e3cb8432e51395178456b398987e376a4ff284e6105e983a06fb7961e27bad18ffc1ce39b72c40b56e6c26f13e2642e9dd4856cc43414bdb95c74cb7052631d09dd90685b3cfee0f05f259fc68df5ea5138c2e685657281ac5f82d80d33ff73a1e6a876656be277f38c487607a8347d4d1efb54908f4a7464b321f60b8280740944073b13e891e01282d32161152b6033d4517b1064e0c2bf0e193c7bf8858b0398c7dd1cb42d1b463b8a500df904ac1749d410ef9adac3c8729e0368a513016716894b26a6e6eee96bbcd24c2ff6366a044616631729fb05003595cd119e47e1dc6943ced11205834302b48e220f8402d9666225a1beb574cfac3e44ce884366c1e5ca04149b1d15e90c6800d0c66c61582d4dedaa9ecccb83363c2341b807a303047d59623dd4830bf675d054c6f95498d20c4358b042cbf9b0bf5b41a769ee7e3b7e153e651ed254aa0c98cabcac49a6ada16699407917314454f1e47781abaa75bb6f78fd89fe42ad5c3356562daa41e250cbbf8592fa5ff2f2587374584ac8500d3a13a1717ebcc50c4691ebd6a73b64222b4f63fde1c23dc589d304fab36bedfcb1770a62296fe50ced0a37935a6a1abd91a2f2ead870b675a3fc6ee53d2172ecc1af46f5b7b5f450917e80885b4351799f57172b00de2a7c76580c3d82bb91f04ef278ffc88f9760407ce880a68a7d522ded4b8bfd914649276983d65bb8ab497431157d194890b562ab9de33f5f31f9c876674810a080e413330380762a24442e9adc51e504321fb03f93e08161406f4afaa10ba1684107004018a49cf614053155312513b371df234d0dc209c9ba6090f54842f6f451b96c28de6c1eef996086e873232557341f914bbce808dda038cdcd311a402b929b8fe66d20fce156c9762fc883f08c0875ce7fda6566c089dcb00c8380443b5fa9126d111e7a2e82704ec02f9c68bf4282fa4cf133b5367f71ac600afdf1552d8e62fea30028e6799674794dd82fbc975364ad41420988626e56fbf120890b0358e57e5bbe9a107ab5766ab7e905e70b689c9b0e6fbd5622e482c7ffec5ff40b369caaf84769cc082a41b7033c6c2fe141903cc037a47f973c3508be6774d6353039ee98907617375a485a1681c03889fd7c90e0941c4d77bcf194592d4b9d04e3cb40527b4ff806b876db526da24cbdf328c2d432d662bf4c5144caad6d311c2aade4c7512b223b4e3006b7642674791d2b899a46554eae76b76f4f906486045650802c565d2f01f424e7704bbea3751e3927d36ed4067c43067937d1075d84651b0d2eeabfa1df436bf60b7affaea84a22752468f623a56947e6c1a6edf5b2697ad69fe7e6d159e1d6db5cf5444056c227193834f15f2a0e6267619530698c98715dc93ecb0f793e0b51944dc44811b4ed782136c6a34077a229d691fa69df108a04cf85f6d0656d91ca7224d7f0f79ab6f035171648c52d8dfe8efa2f5d05766ee3fdda989906e665c35bf6363190e34d0319921e8b898bbb1b59abd284c8fc9e431dcd057481bd2fe8bcf77f8964763384affab9e089ee568c68944d4619540e48bc6abe65e4d19a93fc0d24e898bf15e9cb732823704bbb57d41e5548cd10726afbeaa329e3cb59adf2f084c42187732ca0b3d73551f77e12c76aa92af5abaa75e77231a1c658994d4ab3e34a4da33ab611acf49cd4c8f8fb099c25d414195d6270583bdd10d90704e791c882e842e2a1cfd68198060235a954c0c19928cea4c829f43a58118f1cb88b1cef31b58602eb029eaac638101f58cb30db68c16d3c5990a5b664138634b2dc1ae30cbe56ca08e2797a0c507ec2a26b92480c450051053f686d742d7c6310e453edb08aa7bb35322172da4a1f1916faabc693c73785e4d96cc21973c03d17a2e650b883ffb4c43c45e064e20667cbf2fdb0646f1e119245193e20f2df13cc124e6a2d4ecff2a3ab271092824887c00a0fe5850073eee1fb9e95b86a127b851dfd31e8a2d94813a4462718b911ecd0ba0a081e6ad115e6f4a735df0eabce939e5d481a75e66531efe0eaaf0d12ec19d613026094ae18cfe7f993f54586a380a4382e42080cee00939b634a121ac0ffd9a21f0a225ba4110536ca4e817cc76adce5ac8acaf0ea6cf3dc02cfbb2138eeb43b90262b3123dc49cab3f53eb121909017d4c042c9eb298b3ee143ed7727a39d3ac127dd2a2b444e0212190106ebf5c24fafd086234801812aa8d5bf94cfa9288cde70361771652a1b9f8c0286ac2554cc45d20a3678c3bcf3f89b51810f59dd6787f953c711c916da1d52bd0994d4dfd9398e36d0edce3684834989c643eafe6c8778e2c82b843a3daa26970d78ae37e9c61200dae32bddb572e280c68c53334a73966cb2bc47635a5a52456ecf2133f80bf9634f7cbee14100119a5121d0b005b3179687abe1db40e77d6d17c0b37db7a3da132ecfc4bec9d94368c18a78ba278c0cf7bc3da4aedecacfba452bcfac9a5251e7a051abc54e009060a27c28e1ca0ad515408720264fa8cec0ea4f7f01f3c2f770dd61c24e2355902f82d0799d2e00f617a29f874ae19206fce18650211a8bc6b16ee8604d1d7363540470c3bd076b3083307940d0a549baa1a20aa6c195d3d333703cfd6d6afaf101b8c2b09c71b4de5524c2943e052bd5746bf42ea4c7e4c5b98696db83df7d2fd1090a052e25291661d54b2c172b446a3c075502eabbd76fb4f2bddee97b0436aef424ca917d673aac812bdba57f22e40eb29018d03fcb0ff3bca47114c7021f350e2a536c5fca4a4c47ecce16b14a264e403983c1d2f203aab08789a6c4dec95f76a5fc46fa712530af14fa0ed68e607202313479474e013da85326532d75acd56c9201d34c1c5334c15922bdad93b90905a9c68923cb13915e3791989cbf27c1106f1a1a03e42669b1b934c4f2a1f98da0c4f3ab740a282e3f10ca07ca4c7cb16d3cfc43c2d553a6d7e3c2112cefc7ae32df7c3a4458cb3921229dd81e0dd510b6d4e9a013d45fb059ab4bb60ea7683c0a0f31caf8d725f37cd51fef60103a55c0f9d4a8fbeff53bfade308a16cd926098c2def758d0bf2995c9621518598523bcab1c2f11ca2d89e891dbb478f3fc1a9e8c6c414e335076a1f6c3d21ec152bb0f9c9ee1017c04328c703e9499a84286db0ef9ae0d0ca4a0d111ff8da2d1bd4b455a85bb9a162655678616ffc9a1e8fc274b48a3d376d614c59f6176664e823582e940e04fd0e5d49dbcb8a83cc3c1021b3916467954b454eacfa662be7cc9a8355c9570644f944b3fcd439f089dfdc23c4213660b80d74ab067c191d57c8295ca1010a87da74ed05f05e1927947aa8f22f83b248062c3393d3591ca743735f7415b0db37b9b51b0beb5c9912ea257f6c7e1d14f78301ce06384c3b8903b820deea7a6f157ec18be6f0f0a795dc0998606fc4d46f9283224964d16dcb1a5d4d673556253cee12281e5c61d1ca706caa6a821366a2a9f531845285e0b0d5e0244021a81ee591afa40088ed1a2d76e6c0b7178dd749434993d6e118608780436fa104a681210b7ac9e3fd94928d9b993cca6b26c9f70672ef3145ae7642b9ff7ef80a12e58e49c90a98a6817c5e10dc123d692a7a2244fa5e628d552f1590e404bbeb64e616ff51055b3df4d70fe486631ec92600778bfe4abfd98919b7a4552b207334bcaf4c41ae451a37423bb3c6498cca26b5721aff680953cb965c0efccdb69ecd8c9229564e67558327becc3355a0e35c6955a7e0fe10de9cdf526342c58ab5804c16495a4554a39ce870c792c5cf87d42d2981a102737fb8ad27187654c1c995a6c8e3bc21d425e1502f74a8483adea78933ff88a802e019ce060eeccbf68326447b9b4c45f6f93061bf76cf1ce2729f0e281efe4bfe1bc7d6af41e81efa9af0220f4859c8a516ffa42801c6ed5d10b102edcfdc367aa65023fb0d44c1244841b1a8d9896a7f20ae29c08e9eda8f8b741b775ea9f07043a13e94ea150d74a2426410d6280d5910a3d8516c9154f2d814063f72c8d392ef2a55e5385322a0098d7da50dbc7a625c7810e52822cc73be8251156c59a34c1daaf821e5b94a39a4b0ed8daf3badb0ec92f23941a0cd7eae108c700d4d5c9e2ab4fcfa729ad02d2146241da49deee2a83a923828802e420c9c095bbd280d7d4fe4fc5c057cb47a5963c1603c280c4d560a61d5cc59bdd31326d3157c531c9853a9572132855ac0c31c5bf38870c9fadc9a7148b492ec9486e092d2ae91ad31fbfe0a0217ce7dd05ea79ed28932c0b227b197516cba8f875df88b913db9c774e615c5dedcdb8c63078f1d12c0ef6a26e1dd3c82993ab50b287e4b164c7af75c76977f62de85e4b749754c4a5d1b690829e366bcf39b839f330bc9c06005db344ece76897e45b973f001e0067511b9d473f7ea100445b5a5779583d47cf90296c014e08731051b328fd879f1f3bda11dcf903cdb412233d02e889a7a4878c49ed69a7258273b1dd2693d481e94d193e3115eac4a667ad20cd436ebba47633781c52c13a2bd4339817f9c0232a113e9db0ba14322377e2fd60bf94d5b52151ab600572bd250a472f84927f0ac0e27e52378bc64cb699375dc827a6c20a289790b4c1aefa10f27a5b3cc753ef3301c887ba717b5603d31fa6d32c8433f6db60908d5376b9b87742b50bb3382b900d96c189d4ffdb864e6db4cf326cced0a5f7c930e3b7e78db687e62ffcea1e3b03c76b76576145c6e8fa35aa1921b09a8529f7f96921a554ce51f184f28d586417b863cec91013c8c38a68ec7e9e05a33fe3125cfb7536461c527a29e85239a385faa58d54f1904dfd8c30b16eaffb25c185c95c10feb3dbdc330237a74bffbfd0507ec4cfdc5a0e260e971fb5d3c61cfd87682453c68c43b8b33db3af7555b1d83aa50fee23fe9ca546020a2cbbf1b3ac5b42e8c7da28e00c38d7cdbc855101622da49967c8550850a295515203804befd7cf1a53c400aead573fa709618e8c5237f63dd8ff5430df56c47fe20ee89d3b480beff1bca1536462e8b5ae16b949337b60aad416213fb8b1db40556653bab0080af9991e6552aa5ebb9d5fcf30a3bf7f36f5f13d8d4b421345b90eb9a64be0835936f7de09aa729819e762e4cbe9fe13c3d42d0030a2872c065dc297235548e41c8425b0628569d44cbda90870f3b9c541845126de0950464378e3d2108a1eba547449603ffa25ea3e7ea442233016df6da5422d122092e53c17d7db13a13d50b8d74cf7663dfea11f9b595e120bb803f08b30706d23cd74829c49ba71b4aea97399d0dc8d0bfacab2a1ca1fbbd24eb8e637b71497757c8fee4209b4c195928404869d263918116db67a69fb80fb04845771524bd1f7b2cfa41fa5c7947218b346a86f208e2e087a6523297450ed3bd12d03cc6c87d1f18c9a2db85b8fc2ebb2f2bfb4a46f24a9039d7454d5136ab3361bf5ff2ad20e8ad13c33a91c463dac20add850b713e7da1c2471239df11e854fffca523fbfb81a892c29802e893b587cd3d7135084c49bee41bda45cbe77ac741d5d4b42f1a0044ae4712a6a7ba4b93edca329e8d2a456c546009ef40dc6a102b77c16dbc4fb3e6431d0402cbf22b8768570dc4521cfddb472370bc1c91574a07bae1072dcc56d9540a56dd666df45dc72f29d4f4062a04ae149d51cfd155cd7a9a5905242e794677289709e7e14d11214c8f586dcde62e0d88fe8888e4c8c76cd4909aecfd0b0ae5b5fa57817fc94830ea6a0cfd9b01be5c2a20cc54e1a891788ec2eabefc9b070006732356277ac73e46f434f50009b1441c83278fae54fb7cd738b754bdfb28108bde1a3e1a9d5c48b737dfd82b985a22e1c34a59f1e3f8b8975b8b0620fa536c35f14a1a12d14af42d9901c0b9482fb32461845435c3e7b46b4d013b26306a1170b114095539355b2ce2fcc71826fc4b95a273680eff12846ddb95c342518b6c91e85463fdde3372988a0efa0ac131f429a84803d9d6741d4abd0abad9fdb54b5bcd166c6726dc9ed64a85eea1668007fe5b0d222e739571073224b5e308a19b7d917825b8a084c840074067a0af0c06af4d954be7a45b98ffc04e031a6bcc56f01f2c449e2332fb8e64e3d298d46fd68894d2c3b4a926c6b893f27a8eaf26f87b65ef0a7349040db77b57f81818db962515929a37ce020c7500244fd877fcc2aade6db430b139ef5ea8825ab325d3f6c80affe19247a98325f93061be26ad883c2c937847e59b9f54c8dc6c550eacf3a7b781a54a6f85d06b3c82c76dcf527f70fdab01b858d5adb1a78150436d386478e1300ccf0551c794b6c18693150d0f9b43b860f0ec8b604d81925d073351d008a90ac967c6e3fc2d5cb919491781ebe3ef7bbdbd8c8ba91ef76693be29199f04ae8ef42a954a30be835ec5ae938767f1a0425b874e69093b288deb916dc8cc2be3e4d77008412b4a15f7532086554bb38e1ad3dd2fe80f57bd3ccc108a2d503da72b8bee55a08e3f0ecbfb177f095b44a193f9304a68bf7fa218229362595514fd9495c3646235d18429ba5cc47909ee0168d1746b31a96dd1335499066c266194a7d38ab6b1a487eeba6181049f89ac9aa33a80cfc5d6cd97e7b2a644830bb04c3b104d0fc88c06aa588b1755f4043daa9b5e786dede33c17572247b37a6e212d0d349f0151a879bb8fcaca03c46691fddebedcb925e9c4459015be50829ed0b25d48b4c5901829876f97332426c928cc2a17ee4367356a14603892217fcdf4d0fde8761fe67c2f33c532f07c37a54705060d71c67f1cf167278630adcfdf2d5ee1af9968c2a93410549a30a165002ae99c33f9a7765112c0f71d0497dadb8c96408d3526bba67b11dc1b5a08544514430be502ffa126644483f3c280a8832f27f5fae57663838ea72dca41c573b311fd4492ac8f1dc5ed9cbaa6e7b5d9265bd8d0720a99aaa4b8b48ccb3844bca4ac8bbeba64dd3152e93a306ad8e3e7ea75c7892e88a2225b8c9c8f56ac0a472d8532c7be10ff878dc081545d276c92c2c82a76c9872ec9ca38ad5033746b0c02690eb30b23dbd85491814b575ebe63bfcaf328380dd861fe1bec0be3240817b7de5be8aaf015afa01f02642f05ccf50111d4741929e0877c6470818f3d5ec9e130006643fedd2aad795e07beee24ecae7036bc8aae4f627e18e5837a77501cf4e55fd9b99b2241f9e2097752b346707d5e3582edcd09a7c554a6f35b9a08a131e61f182a4021b42c15426954d7a064a816f63d08ea08a8bf7eaa0c0ca4798f73326cb064b74dcb7d8890d4af4f32288c0a683d94f1191725274e53c17bbdfcf0b9787f79a00fc41ed0ab492dc957759e4c77485853a4e0ea4841d243cba98936d6d12c1b1bb063903388eb14d0bcd5f38715b6c70a761f86b0e1434bf0d370fa377bcdf7ffa69091e04eba23e80faf6d6b61c4661445d5fc1920432bf30e6c073f268a29f4a363fa203a9b9879fb0a65a5b63748c753b680f974231914a127a1bb66eeaf52b3e1092f2619c7bbb8d4a25112c515f71dcf612dd594b30d339c323f1775fb63c50391b6929ecc696952269626e95119252e6f86b32a67a1c5799a9c27ae622df6ec47de472beda2a75198e1d2bdc83e392095140c41f4978b924534c863fb3d0964ee64c0a4b1a07b35750c7b98879df54523046cb9012837162fbf08a07759be78646070dbfa6002d084864d76528449f4153073724a69790dcd4cca653c3486df879ede5384fd6a44c1d4af95137ad7433b181fd0932c34dceb466889def1d91c3c3c6d4a42b194d960320d8d634dedff8ff5e5292a4e805b0eae72b99dba88aba0374326f149a70baf1e502ebff74d033d2cbfc44c52f67c52ce69c3974532e300354721537e27b4582e70c38f46268fbc48128879e823341a9dfbb80451c3111a2beae0dfcd03d531536ee896a0ab1c3f7574754d0a6240110a96eb80ec090c7e3e19fd1d8d4c7db9193c24e5e6ab9b39cda1c27b93e8fa60aafa94774fe18606d668ae95ef0b1667f0d037ff07fac883654bc287460add0a25751c510e46e7081e17595311bcc057d11b9f3c7d5c3ca81d996fbf8eee44995716c03ad3f3be73b49b5978ab3a204f734742fc628de10be4b6d4038c7cc1356f6257de804b73a0a6fcd2679bbd5edbeb3c47f5c7233d58972ad280dc70ac234198111c5a48e0e0bb297eff9eadd39a5c3b6e7d780bc1c908303a124c006f5237ed57c96ec4cb9972b1dadfd7c8c32090001c50b6ad76bb55155166a0529e91312043b6d1e227087fceff0b1f27ef1f82375f22c0cbae75b437873b47fc3a2f138f68382e658645abf0db5aa24112eb3c5ac7b714adbb2b071c5e81244f932262f88f69a8920ee52e86284f804998f37a753ed7cdc70f27829eb43f3bbe3b2987013728d16bf17e89450b1db8506284c1607f584904edfe1810919c069d8b16dd4d648c2cc335f58b91c9b6345a56d28c97f73b0754edbcbe31a3c0d07a14d6057bb58e01475f7f31db8a32385283e469ab4028ff0e13d33a13a71a5381df00a374b5a208166af11a10d9fcd38a52332d3c446e5c9caf8dfced3d8ec50311275496e7b3ed2b2dd5d10a7f43d4ca7c0dbbbb193b5037d977d9ad6a21ca4eb9911074033b471cca7362ef011370908f55117df7ec88ef041489cd6d8bbaa1a1628926098af57e2f1c243ade3f9dc252e4aeeac4215ee63f225547256165c7c14b77a57b12544d19272ebc43a39c76c0a181b20a56e5f5a687199c6c34f56de25c743488a0085e142cbbe61a93617fe0533bbac0bf09fd65fab89982b3df3e69244f011411c504e387ec5b5dd279573526e3bad4ab489616788a907f328c497931987a3c123518bc2f9e9cded04060908243ce1c6b449abaf43bc5887ba10650fd429f7b3be72c46eb66f0d138170f1b80032584a70b0a9a10fdd802c7928d47317e293ad513ff542883bfa84feff09d2edca1b1212b238e9e38a2519f7163d10e6c00f6061f41ea6315c46146627b8001451a48a1ec01884d1e3994ea6ffdd2d06f6cbcbeccf36d84fc6d6a8cb7cb6d338d947c77d83c1ba97436e964df05d25104366b4e6249b21bce1d69394cc3e18d6aad81226fdec0c04383789549a22709af4a62658e9ed2a38aa77e56e6ca4b55c8183917a9075911943771ec2ce5e3478c2d86168bf66e919983664fe73275f48157daf2aebef810c64f7e2f2d83ee90c452a5ae75f68949cb6542ea69da5ebe88827d1a15cbf6386f96af6a0d25ef8497d0d21317b3119cc87f82e5d9afdc5874112bd8c156d9a23a682c1892e0c27a832a92d6ce6d12acd582b7ea82244f605733822bfc23e8a6193ee715b57ea8302156b160476488a5a72d46cc71a64654852725814fac4751beeb84b8808f32f3a05ab4e997aaeb6c434a332f7cec896c2bf2eb0a8ee36283b73e5fff6f47ef43b97fce5519bc86612a4e3a815f7ca3a96cc187503d5139ac8e873fcc8b6f670bf893df083e96330b1a7054f790bb4c8208699fe729ff164254db17a43644a8afff9848718b94a046e81ceb051fc5a686c83e8cfe44aa9820547a40952e1c444b792e849d1766851f930ad0e609910005a1c3c50be1d7ab187bb4f7b404e79fc02c6ad0e33c2ceaba8220337a35b780d01ed0f1504a052b570b214319134060829585d4d83c784e82dfde381db530e1e3b9e566486d19a70acb0527f966d40347f535927400c7779036989b57b7dead94224af9b73bbbdc92f40e5276c124e6fbc20464bd4224eabc9770db3f5aeb5e70899976ed3fed39853ef7bd69faabbf00ae256ca4717ee3bbb27ef6ff36a01a0d6657c54127b9db3e1b53b67100071b7eadb366c5805509320795c761df6b521e3936654b4596ed58fb95cfb349c8a35470459eb1d32ee64dc9c4168ae0ebe37c14a66492b5f13e6778e055142a2fa6ef4dcdd1f83607f60b4909d5fa43bf6b244dbcc6055eb7bf4bf3e3bb32090184684023f6444614bb421bd832594304e2f60de1e68315405a1c450677f0382811534d2550dcb37069fb3a62708373332b186cd6b168b723c0905b9b992855d4fd822928b1a0816bfdab2962d5864d28a64f74f9dc90bd1e3b96ab40178e686299307dd524852370e9688a2916e51218ef30bd508ee92a6fe3270c47f2a888f5293f1176a7ee0347c72238993309295f2ccaec5d77e7e67457506647310548ed2557ee4797f860b2bb1bf1d88185355e119a9fb1836c85df2ff78762a990667a481cb9d8de809a94bcb44fa123df7b8fb04376cedae45e602947ce1b6eb69d4e80311c072eaa9d2503c756bc2323d21d05c24bfbcf44961a02f758311389c64c6589a781825a7265b4ac766f2fba5201e1e7f9e7aeb7e52bf520aa0016b5f557f73a76686a228edcb1404b0bd5af65a7d6d52910f19102986c4df252a48616a86bfed115fa0f3dc3ccabb71b992029fea93ae236dc734b065cd784c675b855d7b8512a81dafb235cd80e5ebb69d64b8a32b7f1396313c60328fc96699c1058ac48f48048f9057d2ec4cfb074332eb7683941cbc5bfa0e562b393386949d635c03780155ca08d867097448c49cbbfaf3aa0c5b53c2de738695ae0143aa83de00841b35198958862c5d67f415464c9b889333810400fdf535fd5a47c0c2960d0162ac18f1ad0482685c4d398c15fbe7d3178539fbe0d3ae58b141225b5088e60df10eb95dfbf9a7fc472a1b9d088330908f7b8695296879908d88487f4ba8663c2058ba7f32a86e400a17f1f317a1e0b3f8c09fa2ff18a056d3527ee51f90f0aba62c3afa867a73a10aabd99ef11304ca906c32ea38b05535d686fc8959d5982e68849cfd6a854ec0594dd522c3df601f752ebb8d0145ac21a243a994d1933ecc323ff813822e76ae52a917700592b77225aac33e77480770fdd0e804149b31b441f7a7107da9191a364b408ab365a64d16c458916fd7fb335232d5fa738361578ac48e8df7f3eee5039e86adf36bd634c5d05bf6dfa625ec539b80992f156e42a19b43152ae593f6f8bb644ac08895a7c13b8f5a6a4813257c907d6ee248e9cddb951719c5eb0090834fb174a4654df98cdbadd4642171a0efd8f3a388e325fed8e1f50582fd0d374124cacd7e58136eebd4c19b0549dc19e14a92d297d15fcb6bbf4c176907b351c257a0ec2979bffd710008ef5785deac5b533e4812097f7705df1ec5dc00481123308b9291d2cf1a52a54c2511d3f136ca7f581c1988ffcabc1eca7dd028fcbac7f07654837fafd1ef8a4842daf58c4a20729c7d5265c1a9fde73d65b31b971748c6746ad9057b373e020f37d28c6f4a6dbfd3e34834b1bd2d73bdf2c194355e0ecf3b6a28b26af92e151a510f537db15df6c91c4f76c9d2abbd16c15b669c3b23588aec15a2484c4b199a1686bc25a2f7561953f786d1e48de9a3c6e4cf61097533c2f654fff80fcdd393c143201627034950bfd11163641c74f5d041511d34c827ee43ff5ba691850007002b9baa9258fd5414d2585e9c00e39a718a94650b1399b51308906cf3f412b97fe69f2d89a76f13a313cfab33388b7ff58527b79ef4953c1cd44ef8a78eac81ee139b5447a2e63185fd92204abd314162aec6288c98754f44fa51c0b26694a27a6b6bd5910b05039a56fe33ee20f4c491303789ba40ab05ac91bb7c6d2fe0ef91ef9e1eae150e3c8b7c8ca70cd7df449bd9ebe81e6e0d96fc3b3f210cf046c3c6bed7e924ff8595fdf997ea14d92dbf9ac03fce945b986d33844d0abc6d549716322dabd44ec1bf5aa12c7a4dc69c980645ea2435357c7008986e4b282037535651297344bc8dfc51e1a103124453b61f1c52fff22a0c344e09503a0062a0745e4001416a01c96da5927908236437434a2db5d153a32428e927b70023057c37c0290e23b9f910e46fdb3a7c7443ae73005600f14d8b64741e7e90f149371be19c2785f02e0581a7d33f53ae21679593c678c836a88074c9bd43b2f7fffd285df1c6941432473da6ff632b925044b9740ccdd9f4d5a904d939e3e35aa9a1c7967ceec628403d46709481130c012e0505268d2ed0518ae2bcd24ce53e7df4dcc4ca324028c839562b715d807115701bc24938934a724683a0a502c25839f06675bce761131c6ad63903cdf24a73a004a026bc51a0e6e1a246ba40dc69477b471183423593437a629ac24d4d0225c750371a176732e48cf81f762447528c2899889de19f1d6af497f0442de3ddfbfd15d4bc1243b3655ba45b68d9160cad8974972a10497158eabc6be94029d125027d73400ad1563bf96b2441c21a169f26f4e694f6ebe54fec490536072854b4e4370462df2a40a28da9fec0cad1949e6297cd5d395731d0371d53059d82e2f52235f56c46369eeccfa4fa2f43da8ffbb8da2d5cfc390d1306ba6427b49934d3f07b7536bca05726ec02255140e00d553adbc3fe2e4e5578918bb2ac613dd563559b0dddea23ff02427ed56cbd93b88066b3ae597ef9aedee320345bfd1f4bd78df634110cf3b13897d59991abe4d13dc0a1d8551a50fc25c0320b93a71bb0ca660f45e2a8be07018cbb6f7eaf8f340138c5edd9a1334814786b60ed3a9741563ca749520988dcb8d7388a590ae3484f54b0f5e1c5cac1cd3dde54a354d9758c83861d41da6725e6d107264b8166965211ce64209031db09693f20e65bd9bf0786fc20dcba296ba3b0e3280c2590b00f9d1e877243e44582881cb2970a4a83cf1b235c9b1f0997e9964b90043623e5409c8bf81c554f0caaff70d12d1b1bef930a244137aafcb5684b4fd08e1829e19258f1980f1e1453b5b32e67e08bcedf5fd63b1e76d80110b21ec0b68acf9e8e2add347bfce41a0c4daf533ad8a20150cf45908211a1dae0e1ed824d565c5699b8527d3f65c93e171de37a581137bc099b2f2d203743a8268c1f36f92af0016104fb7a8bb728bfdb4a66b8518ca3d525747018dfc2c38a39f5c98e59f2fc96b1fed1c8fb48e0a1d6519b067643e0bb3bdb63830767c39e07199eaa9c8e318dc7c742c4c3d8caa9b877a38ba45885cfb10281adacc380c7d09676f4e05f7a9038b16e9841dca758be7e3a67b3a05a53051e44aef502dbf7ffc321ac9b49fc6bd0fca91309d1a662920b41ff29c95c34f28ee781c0e219655ad9f8a4b8f61a7f260e45a1eaade99b40d85fd2690ff69c821fdf40cf6540d1a9fc56c2384e54e630759bdb8657de3808d5eb6d1080d92e65ef3e3047dea3e5e91e878896d748530d90e4f20c37ef16973b5055a6d3d7874b27ac5221425dc957251db7ac4ad3e1335d23959f3348b30a6ce8a9ea8f7337655f32c778804cf1fca009ee367fe1fa63f64a0bef520d85d66e875998d0e74601bc674d5b20eb376d36ff0dbe6ad0df53376bb2aac4a501ed38566cc3ebdd76080513186de415a5e014f1502142422e5d7d52053ec4e6673886dbd847d750a9aa6e04ea1446e07746da7de1cff54f3fd22d7b3aa6981c35da5dc027bcd18fd0607ca79b82a54e85f0bdcc1ffcee0e765e683a7bb5a3a0e4aa2eaa5da1bd992a61c98d6692d23ddb3fdf4ee950b25eb65611f9ff27dbd050337adc664db09a61d6fe97d9e400f49152a10fe2316c1ad92a947638ae51316e747f5cfd621e13ed53f8b5efc7b54629c41e817105c701678cdff6f13ac94f81cd7f7ceabf111c1517766b41f6cfe686b55dc3c7f0af463da1b5a5a8182f581d254eeee91928094cf8c7bf9cc9fb5b3927f075946fed34f431fbb4b1bffe160acf63c6b39d89298d7e2bc96f308754202e0431be4a843c0ee582284024dbf6ae4fe70258353535603b936139a014c34148be2ce1fa0a5b596c610cc7887841eb7a527ef90b9bf7b9b9c01f74d78eda59c57e0f98200180170a4033f955a235fc648628b314488f61255cde1a64873f55ffadd35a2d338e49b10c50cb161414152cfd91d3f05c0d62a8925aa2650e7660560bb9c87eb234908542c89abc0d8a7f87be7c6e074054faf67f5bd7a0d407e88a51ab953977ece7200819a66caacc831de6770340562259ccf281fb24ac0297996d87b0471a2e61025b5e767ea3f54a8f0269c4924a70b400b56a26a7f1ad26594af87b4a8f44ad3a7afe8862f9c7848343b35eb3993c04c9532b9496bbf3753ec4187554aa5e9d356fcc29e4ad3a101371d034b6620f7f651d695d1284d2b418cc475a034d53909600a3aa9fdd7606e5e678cfcf367fa7ff849d3d7ad5653fc3e684b1a4c9ed880a6ec23f96101753830993532675a8d3e5af5b001a34c15f770a11d06da4e75a1a92e5f4fc1b8b70e4d97a91edd1b78af83afb7f586f24beb502c1159e136a996924e24975c512071857529012d75d87b23fedd307c13376b5070a93ea96f88a0f50c4f93665feb93c245064c894715682ca8f1f5e3db2f2b5cdfcc249c102859238d5fdaaf30b043b1a1651ae92809781d25cb451abfbc775ef7700eae587706c7d7a9970a64ea8248210c5bb0d46ebd71f295c8e5ca478c1059826cf6e9566ce0243c9d2738c975d1a9e07afa303d97c4890e3222b9515749a44451f070e500081f07f4b4d0c0de5902d1672c58c98b0e7a7fdcb6a0e8fda4178c8db0357537b8b7db164befca5e11f44487c949e4192303a32214d009988c7ffd20452e8e150123fcc5c5e37a3e6831f0fee1fea7fdd4043f0f68be7cdd64fc626045a4fd48b407afe25020c6bab7d4c35176e5f0206073b1ec7ee2059d386e9afb183becb6ff5bcc3c528293bcc459a67c428e8487b0e7b3baa3eb76ce697f744baf37853625cfd8d1b0b984be68c848cbacda5c0a700becb3985bcc17af44620cd7418e44902af90aab8938f0a2d26a82d386e367393f58e8344e78a3bfc0213cc8e67c66a943ae779584d26b27dd5a96f62bd7802882742b40c7813eb8e2883f653aa8fcf92ec3f2986b7afa38399203c73a7de0eee8f62fb9447980a323cbd103d0652855e9753572b0e4f6cf68ea6fd43df5376e899fe979b0701bcd5fa9c00885403fdcb57874e9404b9f5ebd7a2e00abd78425c4699d4427113fb13adf37c9ee9416901808789fa2c0bac5ba29f6dc163d5d4ab79b8afabdddccc524107550ce4fa04ece38055910a8fe997a826b6ba26321a09b6808c59dc5311b0ded158713693d9ed772c74ca310752143a18bce669b5fe8c82d113a9dc707afe494a71183c6fcfcb06984f22752c54e3cb1220f03ac3f49e8b7f8fd5f6574f57c7b7542d888765da5e6ee99ac2fc8fde2ba964be54c94be55002ba08bfe5df681888f65f07cdb51e4fbb5014451333fbebfcb15d09c31166f171af1034dca592a443c9c039f9ded84b93641ef7ce9418e5ce38faeb7b205aab7d0998e74a6e2afcfadb67a4471ed86d0cb3d89cb59468db50215917cee1f5800507f1e9d427adb222fb892f505ba33fd6818e1e207701b2ca7abb61c5f57b3d525dd57aab16d8faca20593efd0429aa121c7fc1f3f29b125e7ce05b22ae586964aecfda43d81a476df02e4dd83f2ac95fa793e7db7c2b8e766545b91fb22e2fd2bbe248a102dac1800183af5d7c0c92b4bf846410d56a3ed5cfe5e005b2dee1342142f6551ef6911b74494f62d3f3b9ff5c10bc757bda9b0a7bf24c0bfec4ba326ca1ed87718aead878bcc500edaef74671d7f6f7d8c94d00c0f41021640a2b3862b96c2dd9b60041d5fcf4a381342e976db0ab18a03fab31b436730278234da14411a36492855f7c66e0a131df233e24b21d816ac30d73a7be3bc7f7bd9043ab97e0f17493b3ead87bb9f6ce71dc57a26475cf219ba9796e54d320283a73dc616d346025093757a44d5934a031206c2ae18ce69c1bf4c0339f6c5765d2b4ab49f098155d4135ba98f0f73de99681ca4c560212df6e5b69afe027a1f475e52959410c8f4eada68365bd6406fc189f6b36a7fa062ad86b816327d0c894df4168f9918f4a0188a2752fcc576697be61012620496faceb78b7dedbc6e9fc7d37d9b812cf94f93772505a76918753685621d4e4f751bc0a8c05bb406a6c941adeefea4223317ac2b684170e28a109c5975701eb3ca43a72d5a730f7778a2b08236a4b45a3f06a8f27615d2125d9111f90dd84ae92e8bb968c0ff1be866b793ae2dccc5b7d5adb73b570cbd53f56b198a682f55dbc18eb53dd3456b360c5cfd2c43714b74698c430d194d96188044f070841e623e331e6da23a2b46b3899c5ea4319b2464dec4c1e3b55e2742462d98e6c334ae34e35687a47997ba835750fc19a66b16b73cbd59a21ec8805335c32259771396828a91c55f05c39fa1658558906416e54df20f17493247538fa39721396e3d2ad54008545ab7417083cba55f1d5e8f50a75b9d58041f42dcfa904ed405674a58634ee2d13c21e19eb6b921c1482be1810eff8934c9144537a07a5d98ec35ace4ee3a9471dc1db59c119dc3f6566ce514085617c4d4fb3fb7ac3e3ae25880b06b0c7bd86580b1345af5153169601b0ce4ad370600f85a247b4c2fe5c0da69b566b47726a68394564ab13a197dbc99639ba3538aa14511200ec5e715b338c99b4ffff58d02798acc21ef36c620c28d8d9e1bebf2515215f2a8b21bd7b47ad7b9338ae82220e723127e7e2c2b0838e0f61366f7167a0945659779834ef252767568f45c280c76f6884936246693b18f27f8128cd10db4a496a64936cea3131f02e4aef4c8ba985faaca464226e3d96348d814f094aab1b55b23225a358beb556f8e9349025f75a65d257dcd414151e9b106ba528fe60a387ba879c44c39380e6f00a25fac212d2d33975a1f559819b7a0a603302780972301a6f5b802f4b89ab16f8ba62a119fe9a03c6d41efacb3b59db1ad9f112bf0135b5babb0cbb670db86570cb9bc4d934178d57df834224ce10f7826ba325f6a2303bb195e58192c856b4430078d6b0dcad6879ee3c04d8a2d9061a136f5f6957ae0dcfc6f7cc7bcad7d0ad6b340223ff85c125517d4babc2cccd511b593eef00e9b039c3548172e84ccbc9ee65fb3c4a4404a3ffb44db80deb1a4cb632e7c3ee7e0e3ec8862dd22cd8d7c00aa9ef039e55d11c110de565e2676b216f6e0edda0b8f7f85d9e8bd8744b691703dd78d1092b99a1758d23658113a1ec229b05e24df3810bb118cc5459953e2dc50d351bcc7309c6a942aaac07dd06e5085292afc46a97a5f51aeb612c6a0458baea0e078fe1d1906eb9cd6ef61029bff2df8ba6ba71ef1260193f07b22c700fef3e2fa65f35411128debb62166d4373b214b6191b0b13937de1ce3f7169d5d7804306651f5746391e63a043baf40cd37e5f4fea62d9628857e1151bf0d176d51d2c61e87af8270181ee33e71978a64255353c04746ac97cf02d9e2549669961c7c7d45a29b1a339650dc9cbbed70a5258e29dae32be7d32ce7a24ea6e54cf70ea42a0f0958d7ce040c4c0dc233ab8d0771f9152230dde376e49707c64b431775439ced1bd56730e8c5e2cabb2ac61f6ba80c3fe8af7aa9b1f1955e1ccd4076f83447ecd9c4847b182a4bd8338b506e95bdd18e2a2fcbe6e7493fe6a5bc4ceb8bbd48d378feb1b7a808f71f25b9b37fb2a20806d91b7de2a830c08631e6f9a9c35e40a9dc64a320d877023d051f6464fa8cfd8439bd91c208080a8dcef1993f4b1f08407212f49f7ce31a7924173f0ad1efe6941920ed4368c8482e2e54ac551fb656bf02d27205da81a800e3e00f35533835d89b3100333f21c23a2a7bd23e22099f9bc254716e8e028a078c06d4c0ce6d49a524adb2c8d890581631a4680147e2d05bf0674c26b1f4c6b5c8380439c57d6f6211b3a087c6c15ea767dcb759beabb8fd12545fd2728ab106dfe9ae83c437403e1b7a8753bc37f257cfbd83bdc10dcb8331960e8f17313435a9f0582d169434817825d76960528cd0e5b7a0d2fa613b5fc523af731ef98ee8ef6acef13c98e7f8b67912f03f4bf7177f954c13a7ddb67cae82c1c6dd3d4076ed010d450cb1cdd6c21604650264b6d8a194f2e39164a5ab6bea69f4b59d060b4704e9d8cd58a89c5f43a12ffb1628b229ed92192093b70db108f980b92bd73429c47461fd62ac195c2c2ade5759910c4d47333d498c9f318f19229b1f0d4db93a83190a54394d9fae91fdbda154c900519dc3c931e9c8ae42f197b764b265c008eaa1babd48d04239b963d54330f7b362b80129670b6d345f64b8866c6c815d04898c66a5141924db9f54f152b177c9078748bf80441f6720d28e1c10fdf7dcfc77f802bf065ab3286be0cfc4e1a814264628d1f14d50cecf62f9db9c5a12070c52cfffde2482a97fbabb59656117e6f84b15541e2eb88298570e8059d5c11e79b755e3e1a8f60e8a057baf6a20e99390c6f8121281e6761c85e10634f6ddf4ca9ba03e8661539ec7ac75e7262e7545a228bfeb69da7071cdb92c28feef44dd7fdbd28527999b1e98362b422d6d82768b6c244d3e9ab2459a78264d31aee00d64cef1fbcc30839821cff140df68d39a72eefb6e039648fddfc57ff1f1503eb23a5febfa0697d5074a3020c22168e2636f171d839f20a2463a455ad494c4e3218d966e6ca7b56e20cb9315d2e16d7cc6ef22f8d67166905ee2a2ee28a1290a888aed9bc8e737993b1133deafc6891cbc341402cd6367c49229242dfa3d5afc58d77b447e0def1ec30eed745ae07f06457ae4def46d4991293d8b116480413401eaaec5281111958d037ed9765f7a645fc2d697a132df33dcbba5af15f51a959b904ed0dd8d2284fce66acb4bea53f8ddf777252454e0848ad5526b36c7e64a8ee6d73720933d0a906b2d101322b3c6dcd67f804eac424d9b12edc948bd099e5ef629d7f46f7c564cdbb2a9415c0021aa0dbde12e4bb0519a214627e4c3fc6fa6be5fb71f3fc241c6fb7c5a3ceb14fece792f4a13c20b775420061d8fd2a4dbc43083d80207a249994ccd87648fce672e97425f252ea6200dcd62617facee81f16bf45a4f2a4dfe45235469fe0c58d66b18fa5be394f78121c4921b6afec8c58fd119ff4f56c20272494157b5887347f9036e4a76164922df857ca881a621f83d0f807421fe84f51738da71b830cb8cf20c9ff8da8706b17b3ac8983a96920d889de18fd25e09621753c3ca59bf8ac982df71bb4747e9f3ccee0eef7f5b6ab00ab7440bf7b7f414eec3de678ee9dd5ca29060826f796b9e891c8612798731e842f8796cb095c4b3c868c93ff820a3bbf06a090fd661d8301b02675588ee982650afe7ee8d2d13d5a52b2ff5e6b232735b5d356789dd14321583f0e732e5e4953a206eb2c5336a503957920d5b5d5a14cda81ccb4a42403f202f56ebcfaca91c0a7e2a792ade21cd48b8535439e6403e719c0f7e14534faaf240d3823294aa1e11b4945d39fc519fa5004fad3d7de58081d9be2b9890a57561390404b56ccc6f4bff759ed70e5555ca72cef26639817396638fb7193abce502105d2d07c0e7ff1c0d587094738caeb7e09b09e57917cc9684021ab3dbac297ed5a6428192f98025141f58cf501d848284eb026612127704642c854f193631285f750354fbc62f1ca545e9e19bf63e1a2a77940a88e3ac6ca4cacad888ef0d2f8215e68b4d101ddebea3e0c6712496d59915e8909d5dae14f4f12410552ddb1c6f45ecafbfe916f0cc545553ec461a7597ae2f37bae7a1c4dae91814975ae4e7c2e2e8bcb0fb1cfc0eae110ad59cf75b46b4e5570de9751c17dd2057101d9716625b499a50fb2a796a943ff6a12cc833d035c553e9fb35e0c193b1db67ecb49a6c86e95a16fc970a6891c2866fdcc4419bc80dae1e7ea60d08db16af074a82e2a2cd2aff58e9c0eca87728ddae5ed0f885456f05d0d62077c4cf6558f58d04969f95ccbf9be2a01389f4264be17c06c446ac3b0f513b159cb3e9b7536a6f8a3c0b5d4f356dab800ff02a59bf90e44272f462e3a79baeec1bed21eba4d2ed84be37dcfa4129ee608de88f6f2d4d6bfe403307cbffc4be018dec4dd0ef3afb080fb9ef846ec93ee3e1dad81b4e7d6d090178d68551309454cbcdf26a63acbf4a37cee544b386edf962352d89543702fafa96ecebc1c3947811e6ab47332b0800561dd4b3223e6f51f3b7f9a95f65e20b5b7a17f4230c5b6c3a9e7702e5bfe12d1bda42fd10bb60b9bf193d1cca8b10afd2bbb29d260abdfe61b34b888e700483b95616c68930aa4ead19aee8bc2b1828595514ad0f6e22f14e3d16305281bef420e0ce2dffb8f6740b379d2257cd2d32ec5593ec4149c7e852ca7d6fccb23fde874c543055aeec177b82a63d4030a9829ea64346dd7be3645bb1af3248751310a1455b932899b2716449f8882471b481683c371fee24bf2d5508f72b535c461e2c40d4e65ec5e4ac47ce3917455a0c1c3c09fb9853acd88393425e50081491d6df3076470fcf1d7306322f8c730a06a765c44e13d06e835f00b8921563df34011034a6e45dcdc911640f6cfaf7036b42c4c32ff5bca484a3cb4f968f95013cb6f2be4be97a5a2c2353f41ad5385cb1be590d26c99384244359d46afc4dbeb97026e48e684c1194db61f76cf4e124adfe7a4306616cb03cc9ddf8e044607257a075fc6010c16afca0ba18ea84a1487932e262a0af489bf60f68eebde75e4150e33fec1a4364c2b1a04a0a2b228daddf9c125bcf795db2156d5a62f1e302529c4c5cde0fdc91ce1bad3cab96042427051ee1dd6a3f9cbc51b041a87fbf6de4485b743bc2bed73afa908498a9e3b7e411301cfae8c1080ae42899008b711d56953d9b4c868b42473c9dcd74148a7f943805466e4860c494e67e7742b8f88d8ec20633e5168eeedcb8a4992606c4c67d73fd3d301836912e229473bc40f761d4588f8d99b1e0d29c6159125124c90ee482040dad6d276bbf77eb94371d954f9562aa5276c9f2105cb2365b28635b8802d522f60dbb60643bb303b670413d7152899ed77a12a4ad6bf77344d7199be524048ddd1b65d2b0baf79d6e0fbd1eb8e4d621c769437cf70753d57fc7fc618a555a85a9084244b7acd201d47a209116b354c8a55e5b1ebbf1aff48eb24a72cc9397470b18566fb5c50f519f8f6675043ad0cff4bb706d48411d68217f043b265aac60bcc674d894828c864f6eec7a76058b0a20cd3a9e509e7a57814a46f2cab95501dbdafc646448ad6ad31c2fd2799d8c0499e0bff47213ed8550820dcdde0eedf5ecf874c5ea37d45ac9e18f1308e9bfc046adfcd15740c3480e4a55ffdef459e0dad349c0a65ada48572aaf71580044e1c27082ed688f159c60c5f4c21952194ec4f7b9ebd208e69fea6ebd389e64f17b8f07faf6a561ab7264140cf004cfa9c86a2519edcd10af6946342f83da7371f62d1cc78d0a1617aa3bcdaf84c229046658443eb048cf30b28f12f06ffe585ec3ca4a34bc689d77ef2ca01d73e6589124ecae06746bf1c9ddabc12c5b643a73c373af674ada5e92f86cf9d9f81dc43d6827f0c4650d519b83f0661511deb53664fc466b931c5512b38ecc3291a86be776801f19fc9894994b7e6e724924780003ccb20b9e00eb84b74b1312bf9ba75e140d88b915f8bb685948f218f233a10e4ae2b09cbf784304b38e2413a49d6839215299001aa7fbb0eb891c966aa9f93c7eb51655f308ce1b8e82f86b92a99540603f1cb9b9e7c8a8de9721efd0ce7fd9baf21d2c0cb711f52e284b7c25ab80a63a6d379a26bec169a00569e16bfb977602feab559a62fab7b15b21c12bcf2af331503e8fbb2368536fae8cc094f3887b3150041b3d31706031f72751b20d57ca113b4f6f0ec31c1a46349411ad27318341f28c7197fdf7a6d805079f8ad174fa2f7b4b71df3d473875c2f938bfad60cc3249df625815442c4294182ac14813ce08a86dacfdbe97490b5b8edd6cd86cc7ff60c205d4d8fb9c71449af6d23e3d5baf509396b3788bff2115c7a1f2441fd2e6a4e776e0453f604dd502c0d9617c92d4f71ef49cd67d004a4b181cd060a43f7ba3309f2370b3b6b215b6d5948f8d9dcda44dd25c2265b108c8ea42cce080bf29ec587c704c587a8c7110c78d43b3832833368ec1e4e2c4ac4cbff66132cfccd916ced4072a8693a307be70dfc0e0eca0ea799be537fdcf9169a3b19bcb55e89a92565713b53d0ee0ed6dd4ff982b2c1ffc05fdb45817a007be67443d65b02a31e61ddf58d8532da3a40c2baacf2b572f929103f24178305a5766831192308b43bf669a8cc7c30c9a0b5138cb226a44918649a041171312aae2a99be42f61de629a8479b57c12e24c6c0d0b00c457e7534cd1f983123ef377a1cb636674c0c9dc9ae8d3d9c8c298403625c7053911846fc1b0642deff16dfe501080440192ecc9507269a4fe0a853145ec07176a3d84bc3810eca6ec78e78f10fbba15e3789a25d1bd61e2a36083eddc32edb5ac19157a870d682025dfbd7e92b4bb602214e32f8640bab2924fbc4684312dac5b93af91a2a8d68e1365d99e1606bac0654aefac64c9e0dee51d99f8a39c995952042dc203e8d5f671377d2001fe2a70f00d94df491e975c7accf05640fc53c2e8457102b4579b52e27637f5b4bc398c0a328de4b6358bbadb46591f1e67e373396bcfeb3884a28bb9d18de249cf65d17b6990a219cc057146369493f84f54a480f5027339f49f68b1799d0c027ddd3749fc25021cc6427133524b82ec87754217f279c3f85f717ee41f48cafbade4de5b8e291668e6b6afd14803230f547c710fb4dc1e0ff14cb05a3b9250e78c5f3da040c9f4d49a911110efbbb52a20143cae6e55187f813ea93867c16b42b0ec317ced02027c96137753f908513287e9a94e0eb049073acb4e5e3d0e6f3f126ccd8a4b71a603e41323b5169ab5e6056881e949254a9c7680d1d3d47d3284a4a6cce92385643691327cfbd53a57fb4db95dfe472df35362313344da873cd19ca583667eb234d0a6c50762cef8ebd15a83d6beb69494b98b7d53271c42bb6ca68730481b496ab26b0a716c3252f3ee9ccd8c2ad07190850865a62b816ae970da1879307baf08a9c1cbfe53b2522afcc6e881a62da2d3d2a27d08ee5b9d32a0413535cf09134780958c400f4a747830a65b7137f9202888dd38caa9e3d34a7e5cfef8bb8664b84cbd6e5121830b270438ff67107d8baba2daa5d90d6c497b50c1d8fdc41bad598cb6d885654c78c3709845e9f84819de3ad8390aca9fb8d9f1ff0ed44e9ca80d4fca176be2f6abd5aeb9977decb02043420f6227fbf45925e6b54d4d71d2e273911f482589849ebd7fe3da4734733246fb093b4b15db1a9499e8c37a733f3e7007e22dfd506289a7a50fe301f54c2fabcb716967b487f9a72bd6234d0f4dc45c4e4dbb6798c651ed2150545a1f15dcbbd695238a09c2912eb0be38b25f086a20dd935c07dab819652625a0e62cb27803c7ceffd36e56b0885fd175ec0c0fe2b31525f272b5ab810a273cdbb6ee9e6ad425c072b82292e83eec34453e8b0121d1b95076f12ba5037af69951e8a828d90b7b39d0e9ef90683ba12aab72eb906c22ca1146625b783e889093d1a7972c0f7703cf5dd1b81fab3bd8b2acd874786fcb42012a3bc35447a07f07f2daa26bae690ecd89ba82723ef42dfc18c0ff0d4cf8e8bf22c1917308213020f50901bc42c537b7f8a6673ab5c869ac9d84d2fcc627fc198ad07128eac2d4859ca51bc565e43ff8d0984c2f72144c68ae2a563cc228498d4c81753353f134b509dcb3f92e47cd05d8b49c13056f153a8858c74fa33d87c964acadadc69c1ead9a05b12a57158d0cb96ad5c04b62d06c0fecfac237c86d177e03acfa231159d98b0f3a3623a040fe32a060d47d74715684130a132a4d2beb52e35cf80180cd4411d10ebbc7d1bcac7a13c5af24a0c5116508dcdeacc3053283a1b1f11589188d66a19072e923a984c6ce52e0a6c58d07ad021277fd7d19d8800c300d82f67e52bf2e0c8276f381d8354413047bee007a6cb1e197be1cac206e81423789ce19fb39ac7f21f97e4ea006b29abe91f0b2c3de154e2c122b512486784e3b67b41534dec3cf219a93d96895aebadaa00cec4815f7072a028c5307d571a960372c0ea4461a5dda896e5182d538a61c439d57c28066f7835e3847d6b9003b87180a4c92a0027b68e3fb18402b4d8e2cd1a2216d5c522dceb4e93cdd82578d6cd1ea85e6dca533b87e875cd00e74e5310d2d08b22f500d5d57813412b0bd81051a200e6b3fd9c50aee98af7bbbba23443f459e3d044531a54c667e3fe11ccc39aa5760689c7731f28300b4c41b979d6935960b731a5148c1bf578c027fa37df63df29c6f2daa1850b4f343fd1f1098d641d79eadd34898ee4a6003ba6d9e89fa4223e4965e037e1b5f552475ee0ceb62968d08a599cf047f5b0589e58c3af666a49f380272923b0813abc91f376f6a81de1390c2ce1ded4d0a373bfaa7ee220bb9dbc963aaf3127f91c83bf19226176c889fbebc24fcefaed2abb95e2e19d110ec1249a337dc8191509e0ef7716f0433c132b9d111832ef787c155602015294ec3d28aafa2f888482311655d62d681cadb031ab9edbb8f59ad1dd0e8dd15f915435e48dbdf0c4a53ac6161d92216a4d100a110e383925b8a2d7593287bbeea4829bdd2d3a475c9b3947c3a753a0d80e32df03b1e14c6716eb4390e6aface1af8b2248e8a84a14ab96413c3cfcbcae4d576b0a4cb58fbbd9bb3d3e1596ccbaba5b72028ddf0e09bbc570b7612c7e5ced498d1142c0764367aae27e29bd298302cf4a3eb8ea5de8966b7d30b284d57e0315cb9a5bbd7bb4eec66160e19fc6c02ae9428ff33988c1442fa5cfa22e7689ab025de81241a0b2018491d2dd851bb6d124e9ab833ec7ac34187c0b881c607de7d014259af7a40eefa2cb35b21a3b7907a4d400b67386252d262a6d6a6506c8d139e5525293b0d5f24ac39b28d25872e66870492f0f36b8b2792821b9912692a669735ec7759f1d32dca07e26823fa91ad416358130292503f25680c3ea165accddf481b6274cfc2cda724dc9ff7ad8ae4619d91d3f1afa8e0de5b810ab01481fc1f5d5c6eac71049c5e29cf65405fc96a34799b3fd1d1c703568a8525ac764fdbf6d3866e3a793af7369ccb30471ffb6fc7c83e1349463370d8955770001cfaf9232865a18a5bcf15f0d7da11495d708400b8a20395ed271b2c233992a28ddb434b41e111b87910dc000c20c8b49bdbb3a9838daee30170ef5bd7cd759c4c821dcdfaf6cd920006a472b9c78da3b3a9ba0d722a9725416922a2be854a833f2c7d5604f3cd8922059aea3c3b45ab8056dc70487fecd5a70c1db64819e26e6870501d05a18eb91d843d2a053213f61052b30805322a6000a300b20a2e6d9851f83713ba9d42a623d1bca6d6071e1ba121f748c08826824c3a5bd134c8b19eeca8759fdcd1e54eb94d61fb3a04488409c74fddc6c102f13960460cc0c0d6b105177b76949adc3e6749da5ddeaf10cc4eed90640e8adbbc198810cd9bc4c22a83373a619a0398445777dd0adda73825b82a65a0a149c71a5331a7017b0ed77cbcf27ca3ba105444015decdaed76804ce6210305dde2841173b4097e4e7cb6c06b2b2280ccac8176408e94ef6339a40ed990a9208660b04aa8ba359532fe72983b83595f8b704e940f11a8ac48741fd9482b1e1678d795e087a32285884746a7832edc8878b4b29990013202f57149ab5a2b8505e1664833d438a11350960774aa012a8d79f47845f585f4e28021f6588f09814d1ab2ba2faa8c876ccac9ac0aa10cf3621ba853dc49227a5b419e4488cab2987f7ce03f6828a35f0734a520223f5ebae347f7a9a90eb24f1eb2b1fe7b685cb1cc63a0cf3a9a474d4199ecb1ed826fb7bf801d910dda25f284600da076731a19072845c45b0e9d7058d315d23554fb003e053e2e6672ec46952d7a55b69aa61700eb87ea1a74381c66b112de1a82bf4994a7f860dc4374180cb3985157c7fb1b759f64a229c8fb374f7204bd3c2efb8802380287075bafea0f919f9e3db5d86697ecb2e2b214408a79e95039c358463f7d456ea4638deea726542cb001d826de84e8bbfbc947ea50e3082c2936dc9a7ce2223beb27170de7b696d51798d109a773b7975a3f23e41729d8e3424c4e6249acccc8fa6a1c89d361c84cc17a71089c7a02961e852429607c7734af0c2b2c531825835fb83da0404381e1d2b02a9f78b14220878a89fe28d95453001fdcd7f392f6f349fa8c8c7ad6f0cc70d580a9da6ada4a392198961899a801cf5c369546f670a6a697862cc11756ad078f6dc5ca2eff616348767d30bea4dd1b30937af10f15147625de308baf7b07de7b60d07b281b8204d4d90670f96acec5bc9291355049ab19126ebbff05146952e358e8d867ceb0e5b09f7626ff21527f4f90c2303be2fc3ca028ab0032f86395c3e55057a71dcdc58724e56c0fe985d583c055d615682f4deaf307f33a69ce4b793bc3ca4f6f00a3ae3f08bbee7cf9cb78871c4f4f7e16a56da2a75055af309a103836ca65df458500ef1efa01c8fdbfdc9e47c904481a918a5c55b2773015a25cc44ff1c7ffa6b023e1ab7b8147acf3be696eaee36f9ff019e473e1eb6a2d523a93a4852d37f90f065d2aaab65cfdd7a738d207db8052ca237fa84d3db3ca01bd686593fe87bcdc9fe08d5bd16866757682fc9b8d5e79699bb5a12351b30ea4cafe05c60a9f6f3f365eb2cc1b984d1eb74d5f6cd835628734696d8ff20a2f776d07d2bc3aa91220b596bb1f16ae7dafd5a391f862418b1ec49555e3a45d1da50f53154ec6215ae2b3a9903731696abaa482164523056c711d404522ca063ccc74b9eecd09e72c409c07815f7cf80cd236470010a95b9468936040629de4e328cfab7f7cb3c12b67b20ec472da5e6f1037b1e044f4cba68e3e3f3ee6fcb3fa12eaf2bfcead73654d0290444aa4d1bb62b424fefb8950857265816a1dd2785c41e9d18e78c8b6ff3e557e3d45129dc148d6909d413835cdd4c857b464218014f5599822c9256f3510b75bc82f988d007640b663bac005ebe50ed1ebd25b44e90f6eaa27b95aa9ff221e1f3308578f671a0c3bdcd047e7321f92e9631ef8aafbf099dbe92bfa9e22bd157526f3395d6b0b025ee0a129d9d66530c61ed2b3c1a2ae8dcc86bb092aacc46ece1d76a1d6165ade407201f5f67c033b12ebecad1fa33d9b3c8b8597d68923874e59414877d99a32bd1ade7df1a1d586075418e05043054ecc995e04c09ae904921b45cf6acc0193768db032525529dd5cf36571885a87a73c902a8cc1d1fb069a09077f1ead7cc6f4051241c1e838d57a229202de934b668dd52cc49fdb44220f55ce1a61497095bda3ef04db4a622e90387ed35b53a97f16eed82602b3d1093a6a5d963200f0e53330239c16a8ccbf1a4529ebc6f8a6f878c6e20f7747956dfac0fd90e4a96a791943398b74d728b70e356fa26c4761b3052d0ae55e1a77477515458ca83db4d2a56bee360504de15d31852923fea1334ac8d130212535901253143ad22138d03902a565b3e061e4add8d553cf98d215fc7c209a94166e04a2ea96faa1fcc919e410d92b989ec066c8a8d7963c194bc19e284a5c8165130d77c7d7240a2cea0d4e1113e746e9eee9cd6fc70b019d4d1ff086ae3a76756402e4dee6a07b02bd88769e5c1e4486f05f167496f0cec7835c9535839369fff62688380696d6ba69a9bc508d278677d7a727dbc48bbfed6d9b7c24e1afed177ab7fe8f607fa8881e0f72470f9a63a04f8fac6a6545323f2f404fe259e285559d344b1934ff53d067afacc66e03905149f722ff104f659234c585e3eb2c3a7659ac30000f4a5d3be8c10c04e280581bcc025e7943c661355b6ff0954ecce07917c24889d050a381b745f246f1194a5a2ff1231ac0a13a844695bd308b4c09e6918449f145a367efc4a88225a99f5bcf2f4e13b24cc5d6da13905849763dffc73bfee8869b139e767e9f781cf308519d764c90a55665657bd6b25eeb66ff5bda2f524d63ba5f7cd5e3dc72b43ea3e370951a4033cff7fbf74f00c85facfab132f37c4e34588b6d30c631c50b67e70e9c5f65f080f229e572baf44a602ef0f17e8545c79469015c9377a686e9d3c8c1817d0570bddc1e697b8da611c2872c0340a6871df28985eb7d04d11c27fc2cbbddeabdbb8df60025be8f7f6082d5a234d95c0c588b5c405b36d10530f556ac07de1ca02b2cab70191175328cf10b79bf64065ba029fe319812b3d41a62b276b8e547ab8f57fac7e205f09721572d40b529e8438181e22b71af1edb86ff86fdd084db5656d3894eaeb25b76fb43b66ef472678d628fd9bab665d0c4eea9c47add8ab3c96b33fad386f7ad7824e8e7f69e77ca8f02160caef57c13038315d6ba862fbec12bcdf5a9148116f547a435d6e070e82cd36c5efa22edba76e953220ab160a5b394c39bc9fc4fdbf7c8878f64d0bcbb7d97a9ab3add4a54395e2b930d372b1852d40653e6610e6fc0d95f7ca468f9974421d75e213a13a41ec5931f0c74bd8de54c3b36187e482ce79cf2c68f749007463a5027876cd714a5c93ebab7e8c3212667d219982f8bd5e013a936dd6c8e837873808a4af800dea60c17a5376f19c1a1110c4f5fbfebb71bc0276ba7786a79e15d0ab1879a42620219a02e05c9109af13f68ba723427c2a654fed465dbb6e390c676eb722c09af54362b0e649033678638bb2ee6b25c6b1be7f8af78774af00bd35e13e8b6393fbd9adcbb9e705ebf91486650162bc824794621a9ec4caa20248e85199375609a972c31544f5c1bcf7eef6900a329ed8c27eaea7991a4b3e606ee967d190e2339be8c7fb1390830892d9d83bfe541f1a82ea0f660cda59d004b3751f979f45a2920646075ceeb3684621b8a957830b7a6b5fc117375efb7f8d87901558dab4b6df4707fbeaaf9940faaa2265e401448d023ac5d15e5d3090b29a0e36e07fe577fcd8bf8ee254c9effa9266b5128873f16367a2636c3244e91aaa937a453a9281070b82a4c29005e4a60150052a5307a255d5621dca1a9e4321702b32bb3442ef66b001316bad971a892cd9ddf6de5bca94a40cb7050006ea05d469587b7d54b1a5f2bcfc0071daa54c439423a3dcdf48de531ae7add570c7296d7c9b2bd0777777bf4f5ba0d1a6d9486d2635c12f31e0d32ebd5d729de681daf4fbc03483a6dc4b72dfe80d769ba7019f9fd82d11d63089bbe68eeb214144fc4b4742fdd6433a480b3efde604769d0a84f190db0d3ba98296bb52c1a7d372cbbcbbfed46e3ad70892dca7df7e2a2b4a1d822dceafedd640426d366e017e6dd76673224ec46d9f5853620431c70d2a9272ff8e557277f7ee55709e8eeeb47903aee5484b7c23b7bbd966fb804db840dee91c4a73fc4b1b254e9b3d5ac1270e8ec386b02c9f9ffd756d5b32a5c2daf0de7bedb7e3850ea15f2609fc4202dc56745050d78455627142b9df0a7547590612f8ec20d418d8e25cc7be38c3a71f315d59a237fd14d5420a95c79260710fb83c16e73641f0f9e1446aaf843f49bcab32157c3a847e1947e0ef8887ebf48b51641545420d1b5e7e3827c571b75f83eee89cd37cc1da7a6f354fd124f76320cf93e4e20ea16b15732d21cc1fa8a2d98f736d140915cfc0e362103220ab5393727ffda921f4b3bac0a7ad32ec0b002a99f0e72b7024b95f90c296fb79d8e651651d427ff9037fb64d7c8ae516f86bc27148aebc20a5e98a122667ea51996a16fb4271c167bd92fbeb15f10a6d721e2fd42b62b6df1561e5a1344edb04c6b51654793a8a9fdc5f87fcb429a3824f7c035cdb9bf2d94157bc566b53073b2d0f69b36f804fafe57ebc053e9bc694bd866572f86c5acef9e9fc27d2d7cc5b994d22b46f5f31445094b40d6d827324d24731a9e0e412a05c691b7ad2dc9874947b4948611fe4d6e1838229f78bb8be644481cf8f5629620d52844249eec7f76d08fdad2178a6fe27c3df3ff6d3d0c08294ebfeee27b2fc5459122700138f57a2ce11553e406c099b6624d31c7ab4032d531c350f21d439333e43086921621c3f1cc620aa79c4625b5b308023a3a3a42d5bb66cd1420b202c7eeb45f1e55abdd77a71f5a24ab52a6770ac9ef53dac52e57a572b8b2a107ccbfb554bf4ca191cdeb7bea7d5fa1e5679ae903df105b37a9dad77950340c2ad7285318b3fd312590fb45aa98056e238c6c49c80c61572cb558e8f5f38b76262621e8f1f33aec605d4ccc2388e33385a3f7e4febc7b2677c170b333858dffa1e9c55df43db1cdb84c5c4b03acc228b93ec243bc94e322b56c026b0096c029baa54d1a2458b962bae08927af185f270e87928d4cbf55e887a2f7c6ffc10f59eea3faf56ab95caf33cd47baf53471e3f7cd4eb6ce1730864b2ea512c55193eea43d4ebd491511fbe4e1d398c513d0a55eef8d587e50a55f6b0de0bc35310d587a7202c9677c5f03d55c9f25c2f2e94e7a15e64c2171f0619f1939c62eac354102f955ad5d4cc982143060dcdcc8c8c4c4c0c49c2c0b85cadd638b258ab954a85712af5f282428962189e4e20a85295e737fee9c5c84f3da531d59fb7f5a9f2ecf28ad29b97f2ecb2f7e32b7b30e53896aa9b574f698eea57abf74c4f473e77dc0fecb8d97533eb3d95caf5aaf27c55ebfcec895fff66f1715982f8b5e6d721a3a202071507dda5b7a674a8e5fa291d6a4ab8e098d518d37ad7bb5c30303c5a2f8eef125f9e4c671706b9805c3066b14899a6a101b9a854ff59f558f5dfabc2564bf5acd6e35679766e3df9aa178b358eaed6c33c8a85bff5a299d582294350f30aaf56a3eac310af5e9d57e559592fd7b75e8e62bdabdcf196ea5763998385552a159e098b58610538063806380638c694295ee09915fe15fed5aac43bf08b21a8c9de8ed66a0551c45eac565eacbcd8d16aad5aaf536cadbc5d14ef87bf8b1429a018a018a018a0185450e1297569ad5efcd5ea15e35aad7e5cadb07882f7ae1f5f7c893362d9e3b9c4c7e28fe53902a6ecc18c3118af4611ecb2eab25a7da025b6ca735c89b72623037659bd4a35fe8af5eabc529d2bdcdaad793bbeb5abfaf114746ba9db0898643c2523e1cc14d6ada3fe4857c2706b3c496e3953024ef6c7c95ece9460bf874a6941aeef30d41ede95879f2ffdf449148e547f0d120c73f1fb3c12c50af638b5008e54b0a650ef7deae5bde0a0caae047dc7c1d7f919c707703c9d934ef8f4f33fbd7e4e0fa4525bda77540f08d9fbefd50342f63f01846c65068054b3bfaae7de7b7feffb8729323b0c05c1fff4725110fcbbd7583fb027e979a5d866d7a2a521ec3e7cf7f7140c20c313204d4ba04008110ff81495c20a48bc604b0fb618048103cfe9bbb2beb0db7438bcee48488b1c4539698ec812cd152192bb7eb905afcb18b25cbf47ad2e84954ec9d63befe8c7c22b52f5d84cbda0fe85024c021f3f7e62001204488612cc684266a0a156830d370c31010e27a099669a69a699664c02f7e13ffcc76370201ec4815c062f81cf9ce6427c06a7c16b5e83dbe037f8103781e3e027f0204781a7c055e044bc88af80c614406ffa79e84dff9fa469e2c0a6d018cd34d3c641e7a0afe8a5aed258b495bed2593496d6a2997a8be6a2bbe82cada5bde82fbaa9c1e8305a8cded25c7a8ceee2b29e42632de50634d6555841634d05151aeb2838a0b19e220734d6525c41631dc5525885c61a0a1634d636b042630dc5151a6ba42c68ac9fc04263fd440b1a6b27984e5bd05837c1058d3513f4c6bba0b15e220b8d754e0b8db5132f68ac95f882c63a8926100c1a6b24c2a0b13e420c1a6b23b6d05837e14263cda4c7a0b1ae4177a1b15e426fbc88def8fbbf4ed02a4f921ccb530996250970cde73f8d551d454b6ac0a489114720619484124e724b30d1c491134f9e4082c2065092a290620a9aa578e07bef3a5589daf8c3603838a6f9afa41472c1d5bf1377512da2311d4b684c0335a0b10c30a1310c34a1b10b184163163882c62a80048d51c088c67c92a0b1092841631270426311c8d1980a4bd0180498a0b1149aa0b107d09b46c1091a3be1098d39e0091a6b00128d9900058d9560031a6300141aebc911058d2d400a1ac331058d911085c646a082c61450058df148a1b14c6f64ce2acfef5b9527c6aaf224c97fd3c4c181e5ae324a6fc0d7e13a95da80efe08be549aa32f86179e2ef95c1d27eadd97bedd09b5e92ddc6aa3146dceede2d3fdd0f2ba1920d7e2c91c77bbbd3e947f53cef0bc3dc8f213f8c54103c89e2961f3eb008a5a4544cbcbca43026ea8c543e7458ad562c162be783084d894258af41d6fa17b0d980dd1821070a2af870e056b25f88dcddb5957232dc7232982027c30c39a02b39a02d392028404a0029f9016807a0222f4037e48084e0972eaa30cb6a5462893517648971490b08579016c088e338b660609c7489920b92432ec80db92031e48068c901b92207640a1a1a193366e480ccb69465071d7470452e0629723138c9f948928b2117432e86dc4fee27f7a325ec4017a3dcec496ec6c45b45aceb87570e8813796cf3deaeeb723e6839204679b435370b22a4c294fbbfc76208fd6014b8b38779c6e31f854ea136349ff7062ad75c513d3e54a13634f7f8707ad51f8ba70294fb45a7f1596a6bd61f2db1d8a6b53d589194fb69b0f84cf029b684e09324c527f8b4f9eb62c5ad6623b2c3fe88692ff0b0593a84fe13157cd2262330b6df47441755a5aa5495ea525daa4a950adde99717e06ad381de0401d59adbc89ec06755aa4a55a92ac9c6cfb6d981aaf4c97654255955527aa18bba21612bdd1067d8bb92070bcfa3ffc3268dd5bf2f1d6ed3cfe3019747122fcb9d5bf6e0a9f9e505b8f6d725f4a6bd72a612ddbaf296d5e67fc232cff70496a1bf2393d92a7572035cae4df0cb054bdf9be0136ca6325bcb64d038228e8dce874f0039654beea7e98fbab545e4585af21c4cd899d224f78fd032b7e5d6f95241e01915ee4c0a94e767690685ee53a0dd1fe9ca6e729bee57a18a506d3b39faeca59c448b6e9cb4686704d80d9ba5c1141ace7efd6bd9426dfa4e13754c14f86c1c912a37510b38a1cea14f55992ea9af0f0645ba6f37dbad8494fb5b080a3ebffcc2036e5b9b1fee731b2e5fb64747589cfa63c3543292fb6bd0a29c9923f669f61ff3c5429bfde00c571a102a0a3ebf9fef23c9aff1409e09a0c1529872ff98c4be933be01353ec8fa3956b766b63ca0c8a20a9953690e013a7e23486b569a34d1c384fb0d5129efef5dbec166b77d7ef09f6ff1ae3278528f78b15e58fedf70194529a546f4d6de441f676b74baab7a636b297524a294daab7a6d50c94524a6952bdad66c0f59d524a935633504a29a5df4c4feef2cc1f941066c9b5ee74038ea3d168341a8d46a3d168341a8d46a3d168341a8d46a3d168341a8d46a3d16834db4ac2f3ac2dc2f3acd2b5b9bd9df781a75044bda4b06ac51a5b2e183246668646c68c19cd6c6626338b99913398996b36a366e69ab566e38c355bcd54b39a9fa96678969abdcc50b37fcd50337116ce4eb357393bcdc0d9372b3b987d336fd6018d9937a3e1c1cc0300f87bab4948699cb7d60cd15d77fde9dfcead5771afb5d65550dbededbc0f3c8522ea2585552bd6d872c190313233336a5e29d75aebd75ace904133231343fe4b86ed1e2d9130aed6c87a9534360f62ad54b8ec60a6a9636aa3d40baaeb80864ccd2b6a12bda2dc7fa2e1414ced54f300002255c2e1ca2008801901800171dea704e23ea54fc9e52e8627598b8b5a8d08d304febcd38cfc8934762dad25f5bacf6128abb8bbef5daf350a61965cefeeee7edb2dd6e0ed458a09cc127adbe58314a8264142a64c5947b54c9fde86a1a902657f540d2a50a65fad9f8aa8bbe758c0822347689a689a6c000552120d34a420053d72b5a61c56d1875117445a8638d1f2939d64c992c34f3cade7dd5ba2641411eb0f1e1549b83d2cea7e87f2b7f5be4e9bafd723d3b1e61e5645dbacdf09de7d6b14d227f8a4a94e00b54873844f1aff27bc544d1026ee7650f8723881f5c02acc083eebadebaddeba1dd08b4e3728f496701df4e646931c5214113c820a6110c4547f5ae7026d53dfaf74162af9845da9439a0a2dd326d8cb77f0c228ec043eeb2d0bccfbeebb7750a84cb99eb04c3bd8eda82beb0de63a15f74eda5b63a39f85b599ebe77514b4c5e4425adbed0d8de0ce138feafb348975805a01818ae001fa41fbb44df5f9019f6deba6b6a136f541f80e90ab2781cf8a5352a354a49a6b82b3354cf059977e0849ebfec9fd75cb524d118c65b4294608dc4f95927c7c923a6bbb6e42b304f6b7d19b46029f34c97d923e1372f46054c38611e89dbd016bb3853ad7b0538df2ededc85abbea5509d324bf6db4a95f90b5ed969b742769daacb1019f6d6bdbf7614c92b65ca30caf3d81de957e5e77c397b3473e7a1551dbeb8ac527e40b4241f5b0a834bce4d08feca50bddbdd7ef75f7e161a1fee18d51fa91bb741944f17050af5851c46f68f2acd86f1fc771c8a8822f6438785c78def5ac07e469a172bf1c4677dbbddbbf9e7b96f674afeb89cd6341f0743a7585a1fa0090503dfed79f3aaac7ff03b7c4382608ad7f87ea29e1fb40106cef2602c698ea1f0012eefe2ec1fec82e74dd30e46e6bbfd20fecd36e6bbbbd9be8a395d03fb20b5d083a5bcf7fe06e1b06f6afd9bb7befbdd7d2bea299c0f8fb3e130513c7344d25f8ac38cfe57f92c4f8fb4c00ea6ad3a10387c3019f2d6b99ac65ae53a36deadf206a5294772c8e695ac7d5245b569cdb3c590304c6e50a5483da6bd29bfa7df40203b1f36e3bd1022987993ac1e2239f349ac0a21f070a316c958f0b1330866440c4921f6474f1810510367cd14517358071b900ea41c40e4c60d10477040b131e074cd1830c86b2900288925b0f5c521128800839e9e2821018e9a10b2290c4a094455297c4139cc3039ee4bac860a5042da8821aa1839521a880f203085917611c5d1f968a58b2a4c4ac3176e32521ba9786080011427648820a961ec6c8e143c80f51dc808a24349e9e819325a17c9a4760fc481fd327a90d559e7eb8092b548b262444846062ba81053c3d4c90c4881c88a0218c22aa542ebe9a439035024a128b49932b43200fb99f467b5f7522460e2d8e34620409431452e56db0f2dd05b8e26b9fa29d9413f8239f7eb5dddecefbc053e8a56a68e8fb39ddf8abaf254cf52fce2a55250e5954c34195356890a8ea8217df21652f111dd8c3a9bcd666fc41a022c4d00f6ef8847d3fe2dbfa260eeca866840376ad61fe2a7c82655149dcfaeb1b3d45031d3aa2b754397040a4f4e97f301d6209731b12564384cf5aab4a4ca2efac35ec3615663c01795d3cac60ff8aafef851343c904501dd4772a9fb0b2d628085484aa03fd20327e90849aba10621262126a126a920935093109310931c984b6c87e64424d42598498849884ae0865116292e143868f05d07caded509f68c736e9efe85b92a2f8965aea9452cac477187f29c0f67d866843b4ae9ce9a95d72579e5dd7dddb7524beb7eb2e8931ea3b22ba74a1a4fd72904fc3c4b17163670414ecfd30954273ae8c0c19f69924f8731bff282e0817742fa5f4e6e26c38dbbd3e389be36cb820c705e18270379c116bbb0e77f3c121c1dd1e676b1d12470417d4281f5c106e08892342714ade122e5cc66bddddba13a75941d7596b2dcd0a3adb75f63ffca26dfab4d96f51d65a6bddabedba6bddddba93bb05f6ee2d677a6a977ccbf3de7beff5acd7b9e79dd7d510461849fed98083dbed84c38144b8ceb1ef3384f37037ef7623c2212112225242844382e4d6a17c866e4690d8db6c2987344cf27237c8320232cdd920cb3e4320a55bf0fdfafd600b3dba1e5f39d353bb645b9e94de589fa1213e43433c1409b6e6645bfa0c9d35ec5027f80cd17c8668d96728a84d9aadcf10913669f619b2f90c1119927d867c86689dd323d37c5143403e4335f7d267c8bbd6dde98703cd17345f309df4c3e49b38f74b84eec8ab6d61547f9274d2173ef85dd446dfa9fcf0a9a43b4de2b31a65571d8169154194654ada1ccf71b29938366eec8c4024fba3e055c997ba287b92b0bb6d03689bf7d579b691b227652fcb992ff7c8fea00ac837718eda8b6c33795f842e88b24cdf913c4ae9496d36922365ff7eff3e4c3e4c6d8b2d558c31d25194cf8edb741280b94de7d349388f294a027de436fee68c0aa70f3f2c799c4cb7e924f06e639fbe3eebb5d669e1823a8708923321c9fe8e840a1e7fdf4286ecef449d93cafece452e3b2d72a3d6a13ceefee2fda9e4717ab0fc50d46ddc3defc836bb07bf07cfe995a4fe577ea17d9d4dd4b8a5b32ad59ede5018d08c0ae0073ef8a98ec0272cbbbbbbbbbbbbbbbbbb7bcd83dce637577a09237c9274d2c922f0ad73587892d4d9113a52922484adb57a83acd650652fc0673d3afa27498c8f409001d52e0c0683c16032c06707c982828282828a82faa893ba19bc2530180c0683c2751c077c92745276f3b2cadc4626ab61013e61dfd72c8427508b4c269355d9f729c10cd1236e85d2b90ef8fc1c6dfaf5e123dfbb01ffbf1f8131c8e2a3c9e2a3c9e21381e7dd7b6f5773776bf77eedbbbd5df77d5d67afe71ee4074eb170eade24d76baddd3562b1c6d06864b58cc656cbe5728d2e56c8c402ededbcefe630f4ba1cdeaeb3d65acfb35ecf0966011fa3a29e32fb87a0f5ae4110fcbe4ac317dbbd583944b15e54e00b4eb1700ab3542f2ad60ab562b144db512d9460b1c6508991d5eaec055763abe5125b2e976b74b142292cd6eaa3b9c262a9302bc57a61a15822cefb58a1fd581fcd958f05b2a49cc0efa494527abdefbdd7bdcff36e78eff5ba7b6977ebf70286d7ddcfbea43e9c7a41891ffe5462088260189e700db5d6d05108501daffcba9ca23ef54a5bfad3e81c9d4aa46dfc8d64af09597ae32f03043eeb1195d6a935b7e9f75ae4359aa2259c05a4231ff0519bfe4c4526e468d34d27db86c9fd61a6db3aba5e4099ba4644485385524a69aabcbbbb9398228531b306a0014029f6c0d2b81d74a5f7fa1eac39cd08658834a8991799540c265530949e94524a59f7ba8f638be55ac1a8481c9392799941d18832c219a71af0bf9757761d5c1ad603074007c014298d51dc6241284393da0e5adbfd6304895a6bbb178d6da24870b7b91a706e240441cdf58665c1da1bad7353a35884e8843cf555d892ebfbd080a7be0e2d86c889c9f53b80854aaebfc28e76b34392ebe37430c8b5691e616767e76575c84a868d536bb459bbd623f7a979cb1b376ed03c41d28cb0d3376eec8ce0b9224b9d0abaa328368a1648e413774a18819fc0c2841c317682852874828588102c489a842c242e8a09aedf96d21820b87e7b8f5aeb947035c36a862f7fafb3da2a5317792d53a54c71dee77d5e531b79d052e7d19932a8448c9a6b62ea900c0000400093160000200c0a064442b1248ac24cd4cb0314800f67844c60502e1888239114066214444110033114030021c41066906186a1e30d0732ccf19e5efd94d735aa43cb1420619d8f5369148e01b6ff505091e566f02dd09d32fec6f5522eaf52900788b2be7ed1e0ee865f7e148e7a697838108b6ee04256641a9866ad4a4700396d221c47d3a5fdc24c153252e302c4436d07c47c6f4ff7837862aa29546ce16ce75e82180dc1a1b15e5c138267fa46a1b7a632aba98d5020c019bbcaff4cda1f9506dc947fc24f05f7138b1a09c5920a1aa60cb0aa5b9dfd31ff9076a1e6c0b335e1658ee0d0ab30b91729caf90d3a614ae38c761d2ee57bc6ee29a8a8df87b3496ff83372aaae79f560672d906377c6f062701567ee6dc4dd4a59a3eafd6a86aad4a57e4cb90a8135a92f56ff55525c5c815d31a41a48527b1e8262d3376a05cc40d5874642e673a2940d3d809add648d744ece35e82d010ed30efc8c064dda955a1778a946b9b96a7a50d2bc99be27af671c8c237b62a0cdaf61cc043acb2d0eb04f6519cefe4d638a871d8b8b3cba8526f1bdb96f0e5f50fe7574b19544cab939dc2e1b6c597caa2856541d22ca275695d2e923208e463bf067aca8d915da2c8a7b600baa958c7f0e007c4fea5405ddaaaa16035ecd2fc3c94deb1e37105e0a4d1339f1439775076915869ffb2b946d3449b7e13ca74cd7ec15da380e2d0a05c78f60b49028e915c939ffd0452d46a191e27d83821dd965b2f3d435527a0df417c999875599fad2d18db5e41cf49689d2fc1a238742e0f61ee019a2f9c85525d8e5b0d80a49df6fd1455f7b0129ea24f6ba728532d94b08585a65f38770fff4a3859fed9af8f96a410b9189a8d288f0d14989d0aecb836308317cb0eff877ff7522044125cdb68315542bdc4fdeb798e3f8ea22cc9d6cc123241e0cd86d97d84d753103c23dd1e5cb2c974b359757b949708257a8afd87269779e97993f801346061f9ed44c805d05945336b863f0c632bd40a690a10531fdbff6475db254c0fa65504f035dbb9a024b610f4660be2d94344d9319e0784108203a395bf7dcb04e0a796583d04ca5b65572fc147135c2790e571c8552d6eeb542f2dfed43466b2509f853a9cdebe4fb78aef66727726d6584c76c2704efac4e88b60b95bb7d8d243166a84dd329ea3cb7f2903ecef6cc2e229a765a0c8b77de8f5155d48e3df7f64d8a463fa0e90d9c77b5687b88cabdfba1b24fa3f0c75f4a1c4cb9f62fef5bc3b5e7a810bc1364355684f8985d0110e82f618ab0b2d89dbe83abb6efc0b96cc289bf59a6d7c3b9ac62d422b4f1b16e4dfd8328211439106661352e0b276df6dcd9cbdbf4dd94eeef5d6e705fc52a61c487f9c92b3f180cc0cabaa09cd01cc1596dbe8ed5721b59ec247379fbe701a2f1a8c9a4f5f419b53326463297e56d082374bca34c1e56ccdea452f35f3786561d367e80dc3c8561c44d31e65327539377a6804543c81150c47953b147888dab704b03f7c9bde582e39f2c9a3d02ef99d2a43519dd2f7852294010c9128c0945fbdc231cc5ef4cb0284777b1061262b749edbee10db4c8ee803f6cdfe907d13d9410bd0e30769e14cb08313f01ad1529b2b4b609170d8b125e9c6d57d414623971fbf8cc57255936311115779dd131c7caa55871bed9a8595e33c221b73739e22b47ca72843047b839f2319acaa65e692c0c76b88e916f44fa8d0aad20d79c8f8ba0d982ebd8c529559b5170b84ff1821c9a19f0e3d4e90744b20a7605a5e0e9500210a8fddcbd9f9614bc1519a099af1ef67c1a170ed11ba24d92437208c5797daeb34e3be21c9e882e75d29cc0e953c0a8ef4118dd10e26facbeece85d9492f148eb1a652159337199f6c796a4c31793f5b84a39ae86a9fa2f89295b59e57c31175c53ba97e661e081ca6c3493f594b3216d767d25ce69e9aa663bee1d954e039d7fb4228d2dc8d805457370b9a1f6aa16068e02c4c8cdc5cf71148938e5f5be122049228a31aa34b4b456ab03a663c6311049f3362b8a8f00c4cbda04a3314be523cfa5c168c8504776458611dde0b5250a7e1952acd5a85927d1e7b92c4c44928ef60e0f13223201658b3a183718e15108f33502f4189d99fbbfe59a8c1c3c05950577304b1df0b4e5eec769108326f9afb20906a54d61ca544c820cd56cae0fde8eb3ed01e7d87975adc17ec9784b640b5d22e8eed095795016ce27ef88038a57a2f50be1214fcc2daf43d9e7754a25edacdeae0592f21e41307390fdce79ea2f247bc74b59aceebc7b16c3e790b2304fd0c8e2d7ca2d5d4782fe5629bb605155ab3345c59c0b7474655e202048fbc385a86501e4093e73206625d366a43189716b6027c9d24edf18b74ec976ff750f4667bc693f44292fcb258c6907759d1dfaad08ca8fdb0308f8d12c90679805bad33eec2a4a7e4b4f4826ca2bf706d535ae08323ced4986a90ed2ee1357f8c6b512249f9bd85a6a85e8071640888411ee8f0df585635a432f41804b67582a4acc5f3f34abd0b0e7f0e0692c530916a3019bb6ea267bd619a49c54a699161a9695fd9b4e6aaa0206ba757e8b8cce10e3d292a2fe97d62215c7bf30959d1305c5f0a99707ae73c66e3f2e37645ca875ea765b027df3f958ed26b069d36b638af354043d5ecc9ba97b41f2403e8ebfb28a7cac4b7a055a05d4ecdf0622dab19958cde3af993887ab8172c876a04676c5580230658b291e441c7aaf6bc1dd4d5114f45d560ecb479fb9fb0b657c2c21f2a31dd4d852243080d7575c54616692120b46abda4949ab6e9da08007b40d088ebaaaf0d48090ba3ede289bf53ac8533491aea82317616890cc849f200418548d0e1783b4d49d04e228695724fdd928d6f3038294c4cacfb0a2aacc0f4f5c6b47059317fce55a307e79250fbeaa69a88d7306c57fe8ec39fb9b79c667aee6f319d3dad21ae74a57eaefef16d7924961ce6f11b8336796ec16a4955648b9f94dc7f1042f2ad29f2d703a4e31cdc4a8aed96dc8270285c4d01f56d31bc2c43bfbf59cd031dee46503570b4f7065e7ca8017084052322f78ad2293ccf28af1f848173b7aa93342b56c6597004173462b3771aca42df85d673aaad43f93e8fd3bdee718d6a9b468362835f7f427b52b14aa9a3bfdb12ae14c8f3fae9137b58c730281a062fa0cd629e9f409a499ad8dd07ccde095c76add2c80d6e932a804230ecbfc3bada2f55a5a7376f867c4683b1947b2f7dd9ca03788b97a336744dd18635286e027228d995c9273aa8621da52778bed3317afc9b8ca8cf67d3d9bbb450ff7ec59f844429a86e6444734461c336ca77f1ad59ca169c802f0824cd0a73427d8d49ea4155e47c0f515c15218528b4ee4189a16f8d57f836e14e9360ea9e32d211de40ae002094b9fcb6f38e529ea60375dfc0a3b729f950bc4e5f21bd4f10094fad8b97724259298b281aa3a5a39b3d8d5a15b3b70e0fdc7f5354de09e7c51d445a218ca3b4231f0a9913db58bed4bd60d8641af8f0b870c382ebf9d010106e097571c7772574da4b4569357050b2832404774d671f0c03095cbff29883198f9141a0107013f217e30047100557884cd1d5dc980e4853bdb0837452b0db66afb599707c4eeb0363fe052fa20b9ce895151e76ae2ac7e81eb774701e529e5e636c0cf3eb0262cd53eac3c6ef44aa84655809f75d9c6fca92554e2155b6fc65251f207f0cb0a317709292377d1b3584241643fb710c07fb1759089f95e53f1282d16223c36d832e66fd5f41268e2c95657d860cf6669a6e51130f62a229f81678052ced347c84d810ae172cca8d863e6c579687190a48c062c5239ac3341805b2f6c85521ef81303b49e94490b31068ab708c2833110c9285b50815b30f5172666f33211f4f550db84d7a2487082953655cb227ee1e79ed351b0b266340d35a718522e431536118fb703b60d61d994cac818ae6a214e3cedd2365c9844bd7680b48ef8b00d273297270272068006b119cecb38dbd6c3da49dc21c44416504383d7557c5332d8424b48719a1c2735fc96ef5a7a75c3c2640ddd50c25c8e0a9ffd90560591227f07a0eaca3c309111d16045641c9822428013dba25885851f9c0d06b6906f83dd2f6c2ebefe7d11dc7fcff8568130fbed9110deb623161e68930948689cfb166385c6594465806fdee3b10b50b3586602fdb58037e1a3ae011882bcc4057a62641c2dd241bcfef9edcc76a182b009bce3a2d2e2b7008e010422fe666d686372e36079f250c1d172ebe263bb8f23ba225b134155c5d738d753cae4042fa8142d0e93cd5bfdbdae5b4e7766eb32206988e7ec6b7283c1d1bda0695459f442c27817371adc48fefeb05600ae298476449283f36354c599d54133b722c3e1e26809d255453745899917ace9cd3ec0ba937850bcc0198301f310c831c7efad47c249a68a2b0bb937dc952f5e167240117eb67cb5660974d182499b4761a2e4c833844e4eba358c936920060e3f27c661731e1b39c0e133312ca3f358c80508df81f16608e7ff8393fd240b62cca9a7862fcbc1dc4671adb6a04c897387a8d485da6278d53610070c9b13c361398f8d38f0b099182dd7694c880584ef8871734e63454c28dc8c1887753276c4406398fd984abf7cf4050f8ed1d0c6e413effceeeb6335dcf4734f2f83588d5109870510a59cae733062baa215b413417cbffd9d97c63e8d1a5e2d6ece1b4e8d425ce34ae67e288934b6964b27a4097c82625dc3c3bad422ad7de5091c92507885ae904505186ae333acd1d40092b3f89991d9c9f0cc552397fb140bfa999a2531514f233aefc0e35248c3c1182b8f1347d0c740848c6fdf88fb7235766f4195bff9532da7805c5e6cf27d84732f1c244dac366d195601b56a5ea83a8d168511fd0d15ae880d4c976f73ec888b7298be769296580525c408c8de7a685754eb545385f2d606149a8e619396622dfa9c9b6c403dc3165a76b9aba1a1d5093f534b7fcf89710bc29508d0c4ce4bd403f65aabc562c97e5f0c7d7b50542e1d901f5aa4698252940da5f3d580439d0172fad4d9fbd5d0156e09d035d4d72485c11abb4ba43149d96d7a7e69edfc61df3b0150c472224de08a7091eb03d2a7304b902249de7ce8905576a5476c7968b1f42c0f4d9454c5cb1b31a5b084d133600aa604dee6ed6c927495bceb225e9d3d702446a1b827292c642a5905acde6610d0c0b26d3a46264f4189cd13e90796f35becbbd7aed9ab4108415adc4d4fcbba702f1201c83ba466eab6e5495875cc690bea6113a0b49f0aa39087b9f203888d18f3bd733960d8b5741f130b616ead353e4eba4a3a32bd36820ec494b4cea50c83a72a5dd563f88d6d3952b99e924e9586be895327c00da2bf975045a3b31006e23973a8ca26dae8501ba0910d1049aa479fb45dd69789809429ecc8d2f166ae2f9b392a639ed03e8879cd42c04d22fb365fe8063a13b861222626f5ab11fffe17f504ca07d7be445e82e1937b626642d6a1ea896d6d562559522f7a4e351a40b0a20c42ee1d8258367440d4bfc998de733f841c9d27ed4aed57e2b1d337bdf8ffbd607cfd2c50be8e4bbf138cf7af04cf3f71eb67c1f2fa9190d24afc7f24705e806bbf0b96ef4c88bfdfeb30228b0f8663d1cb6529bee09e7d7a76901e76397cd1cf716739d4ea2c493636586339a742bd74e50b971d35d06549d708e90aaab9d6d8980bd5b14fd8b9a0837293f530e34fa5c1d4548d6df831b4549778ea110dd962164e478a83bb86aafb250d1e8743416d1af2390e8078d3d52e253f2d9af3380e817ed1e0776c085ae34a940e8178d3e4756008d44ea3767ddc0f80da35eb711006dbb94cc67d8ec220dc742517897808f485ae743703f87c31055be4213f406a7eae7889297919254a2a2a02d24a790a8179b563a9a29fcfcf8626a77cbf54700f12096d88aac59bfb668f23930e6b51759cd9879de3d944836fc5273652b17da7ade7e0f14cb62cf7a7ee5856805cb954b3e8af42d5d88d5c057b73968612ab502564a5ee70ac7f47623904c38d94dcc02a3c0255a56dda4ca961f9f7a88f3f47795f51bda539efb1fd0ad7143030a2bbe813aa8fe91d4dcc8560bb69c9c91c41bf763b51f3e63781951ffc6fa95f340be2ae54abb1c2a3353515ee76127e8d1effeb09c4d3fc2425f0b6c7165f5aeaa91761ecd09bac0adb9b84bf509ce282c16fb4021fb7360ef8cfbbf6e43d5a7f6c1d6ca11ce55a9025fab4b99f0c8f86494fbd4fabba5b1b8811c5390a9da4398fe0bd6be11a9d3e695fa103eb8f3976de233a8492c5b24dcbf7c445f0d16212973f642f99286327928cc6e9ce3c1744ff3fb740dc11beb09c8c909d468138ec7ab6c6a2f0c211cf47be033db3d84997681662a92086f92b45aae2a9fd16c5fd3dc44120f689909a0d78415fa19147ed8f7393de0f718cdc3d484b69dac79a40cd037d3e7a3972ddad4af947816c87ea1d1a3448c33b3651093d6384548e041304f47dab9a0f510d7fa1028f0987032d105aa5985d2506041bdd15933d900a35c98c25a75db773c8173daf056399b21c643d8af16f3363083594e095292bdd85df50bd90c9884c38cefad88b0d37fdab3af41086208941bcd11e7b3cf35e13e57474951a01403cdb2a861dda2fc8741bf30805e0ee39cb5d546ead8ac0920e34877c5f9cd692ee9da657f9be46cf21555574ccad8b06def703c099aed110bf6ce79f43118c7dd1e8c07e3730af90f414eb127eaae134f66a99443bcba9871be4c3bd99a1de0059547176edd32094903734723a331bf3acac40f0892533178ec797405890633c8ee5392ba7771f66dc8cea9099a9aff8e3d7659e534a82bddca50e815e38a51cb117540270c8ddfc28f4aa581a9a7eb46f7857cc79ee5213e8cdd5d2e7cde69712ded387b0d2d5804e04d0d0b94798ee93bffee2a1e25850cb98545e3cf20636242c528b713cc387819e546cd1946d9bf5682aaa4fea0984200465672ef2b29c0b98c41590ce009b652ad0190458302e567b10f075f70132374970053e03d62811d308b02d6245469286542cb8ce931e06afaf5c742407e283518380cf3eb0134464c9c2a1671e148d59a58ae5b8f0f9938de83612ce4b2a722dee68c74049904c8845cf3cf2404acb755e395aac113aab60c3ebaa6f8d0b2c62404e69000a2ba5fae9bfc742c60909dc1116e818417a025e3798bed99bbc59fdd86919c1b06b40cded300b7d4bbc2f2025e601507d2b4b3116e7a5ae77fec896fe10022f1daf676b7a2c46454d85881709c689e888729fcfb999193e72aeea48aa35cb11c3c0c3d9d015421c3e39cf2ccfb926b48d9c9cd3219493cddc5f28e71e7de03c33dbb009f4d898251210382310a685727ebc2530aba7cb513b0c33c81cef7e5fc6627d967969d5182855904f03164cf7aa5bbc7e360362ded0955b0d7e148e033eb4d0bb006b92500155d83bfa0cecf4a0ad30197e35c8efb67702b7f4857561a99410beee4bb6fa492c9835b6e29dbaf89d3d1a47549c63ef1b3ec107fe86b760958da76a5385d52b4e8ce66170eec078086e6621fb001390d3588a3abd516cc5294c57fb6c0f4d1e28b5e87f86002ac6e8977a05247119fa7fabbb32c330efc67c5371ced6e0cbe5b39f99d09b0cdc9e4c1a727d984fe4b08badf9c947b4230cd36ce85e8122b85df72458bbf170d1dcbf084e4ecf05ad1208f52fbc606400f81a345450fb138372ba75b08082abd7d69f744f1e5ed23b21be17374c11ae418d66a21428217cf5921911665b03cf991d34fae4852c1506f2c18257a7c502e9f6a80843ffb5f52b6d2819fda7e61e21faeb8158a59139e18a7876a43bb8fda1ebe8304da4c65c9daafbe80c1bbec6b0c3d0b665fcdcfefe1a1c1804e69e2be49ab55999d5ac6b3328a9042399d7a3999a989489b030327a17f46160c2b096811f3453a75f07591f43d2cea6e611737a36c2df8a955fc8d97ec6b2bbc2a35c21ce269a9e4b5ce032cf3d4eb33da347830a959c24c5cb1549dcbe4f7e184f1a2b41f033b139abe4021650cacf21309d5a1a9f0dc265f273360e048887350e3f854ad39dd27765cbc13cd2aa1f3b8fd35b8741b9a969bdd6f690d37512b96eaed672139b6958346c3f308216d9f625ce1a09d52235bc555ef480327e05b54035909b84c61ba43309853bf0db4256f076736b7462285725f05040d9df9c1e92d0298b6c2ad70dcd551d83db054380f5ce87929a828a078e3d5900e03e203e61f61fee6ad9f7f885df590c5f4e62beeea59bdbeffd3dfcc52e3145309202609a2a84c08317107eb235e9c7b1947b4fea6e3f623f748343dd299269f00697e22094bb1c2ce8438eaeaf6deed05a590c80d657d2ace8667a3d7545ec1b19b7b8ba5519393f105613788a0066e6e5146cc5d4362bd4cd4951825028580b8040b6191de4004958ca4793fd789f3983f2ebb02b5e072e2334571529b570793e600cc302a127c957a545240003afb60ebba13a19185b8360c330cee6529cc4dabacd3871f51d2f5a1cfa1623036fba3a1235331811196d9643bde1d3da213329651d03e5bad13da45723b9689de8b071a5633153a930e359e8743480ff797fcdb85845a58725810aa84187eb8556fdbddc66bf29b8410857e3155f365394bc1a545422b0431c0584bf24ec5b0a1512022bd4c1c1151c1bde49ca6dd599c90ec7e18ddbeb9d73725beb7892b79bdf8ccc378103b76333edd32bf18aee32b14a73a1a104ecd7b43f6a01bc462f5c88f6ee90a7fd05b400c1e02c826e7c0f62817be7b9ea36b3421bde79fd3f70cfc0503d7eac8b84fc3a40ac27d0835571c4070c87be85570dff546b063993e6e8e45435aa6f20ef2553e339109174ef0ad960e9b3fc71441b632b4d8b249ec0c5cf4fd343e2e71aafbc7e21882e75327d490e251433b69f25c2be0cb157b9a2365b320e73597ccbc8469c18c60959d6cce726999b3d15e42de8abe2334f95c627b04a6646522f708054ce071095be276bda735dfdb8919301e975482c3954ff1ba9225029f508f51dd42945529a9e503a1dad22790521f3b568ad2e0c47b2309a5ca8bf7412feb88f3c4d15a044ebb56e5a07aa961988d0b0c37fe59d12a4acf1ff367a871116ccdf6848d8fe14c6071300fb6e32696d623d6a227fbd246b5a293b80395197b7a72a75ac9c7df93312eef1cd2c16a3e029d5777282e0150c764e04442b384252ab72b6e3534073a881c4a84a7e5604e9d9e5d8f8b71836c1840125af1a4bf8972bebca37309c1f42e4b6d452b98e855959426331ea4181fe3ad9b4b33d4683445994838d19fc1a17685a9b5d253f53757ff922655bc9fc4d22bcacaaee321c9faea97bf31c80dcf9532540cfad03868898d8e44d6dcfe3af44bb0c26dde07cb6e3b8ec10745ad7f1afef0a4ead79a6e10d4d6ee2650901d298c0ed789f225f3d4015176cccec8e1cf9bd75a181cb1602931eec4c1cee3078a05fea4d29db4495b58f470826466e009c3e58c5911c1635c29205e8f8a3dc2cebdbe9ec0269ff7eb64da0de13be05cb4ba1cf2cb25fecd071e298c7b7abc175156981cd4130435f02e164ec5c19d9a9dbea984e1acae3ab1e5e9eda27248c36a03763d17f6859a463c7bf9dbd6957e7c61e76d48875b20b420aa2c2198536d22fa2bb8a2f9c58b5a2f523747770d11997299ea12eccd4cfe589c04fa92f10292a464890fc42f72782ba51f86f2d73680bc76d8cd3f1ecbdef3bb622a2595c07eb499bafdb46161346236e42998d2478aa374c8c8339c97229ea103a91b804ae1e39d19419599437f759e816fa271478342855df743426736267efd2cceca89cd1f39920c3e711f383462cece909518c7a0ab1586fa8724e752a4fb587a63336a91cbcaece1001defb3a6a979f08cc7110591b88e0f298a38c812536c44ad6e2f12d2c538bc113e852bdad90794a4eb4603ae6a482578c689af741daa376cd57e9406652060efbd121731d5bde0ee9586a715691fabcb709a90283ae5bf7916d1a86b3df7f6c0850751f4709702fc9d777550eba164e8dca979e0f2d508aaa556e95b2052ef72af521ab05b1625152332dd16c584d108da5cb90da2c0bd921ba33992ee4ac1e5e128f98e62cd908966d6f10fa780087c8e8f032a32bb305f4ed3bc4069c3367e41ba5f90de32bf1b3792c29a27d9d56da216a72da61a2cb16c0bdd03c11935a58176a4f562e9a08cf4a49232e8186286f88feefed0ec866f506080bea6235eac893b8ea322b73f8b2fa811d297824d3e2498228d284203633b47a632bf9e39140ac23c2e3763b82f8c4420b6c02d395506b3944abdb4d250516f4f80068934091604c5852f53b320bd57cba7eb8cfe384a859a5c37d5b7920dc3d4261cb1ee9b0f6ace810961477945dfa6302e94685ef8ea89bcd06a29e3e1f62b16460a8274abf0eec02dd3b293fdeeb6d1fc792003d00914dfdc9fdab7897ac4ec33e81ff7edc96d5552ff4e99afdb310e5abd9ecf5c747cbce8f1e0208196d6f4542c7b65ee9c062b61447107e29f74c094008599032324ca59986cc97ca339e9c75a784ec202c4fcb2f3591cc549e45f9825b4c26d7763a2028c3f367c7ff485a7a21fee0757abf7c245376e40f4eb991600b1b71e610fe81174e68a241d8bb9047377504b38d7a6e6c1b91dee68cfd2e12081ec1eed8689da461ad408ca2f0167d48148450837521cd234deb66e8cac9a6e3f30f4765cd431da664ba6861a0adf1a3057c031fe6c7951c385c7f804afb938d6828c9fe6e7b9167a4d25c5ad7b1bd6281f36307a2f75eff22384b829a6fe22b77c5b98e7988a244c0ca124491baf92b4b56de0cd1b3bfe1bc20db2b360b1fb059b66bc22b0adfa8331f0f8c871fbc430f6b405252287b969e14268464710a8dff8eb3133e2d5b81f731a6973f4efd4c336df47e7624345fafb32c1630590fe6bbdf3fb8e753196afb873d81c19bcfe2dcdc644986dd01942ae9bc4cd3f87b7ed7d3b3310dee7a01ba294a1f6080a41bba464bdcbbd214ef2e34e3bd03d258972b04f02549714608511156c3bf2b26394e28d00fdd8a526b32da26809507f3ae43013fcc93cc34fb676b29a0146c06d090ff191d549126788a3e204ac4327701fc2fb081c8ba0cd84e616b762e0864af921d859a5d947b724f05e2fbdc24aa1e2f4351beb2af7580b30b54cbe4d2c7a882e96bf1acf2a78dda3dc1fc4800d64a3feff4c7afcb8c9e653d4e4efe1a2b8691a4da205a83848b18bbadb9303247edcbfa1dcf5ba88b1db62d31ecbf3be4738a50cd23bccb3fecfff5dc9a3124216f8733c56c25580391be532445427e44fbb9badc41319c97084970526b8023d32022714b87bf069790e70a671ca20427cfc54796fe02cc8247ca5b82aa6e2dda5d82b2725f0c9366c4a0387b0c4694de5143b80f185d0374f1bd34bac5aafe337921986e57b8ad386f2cc61a797965ae98e0f8e1bea04dae9a86a42ee09d3aa372c7cd7fcd497bfc5a980f11a9a9d5024ec91c3e34a181d06c54a0c40a41c822c8993ecfd55b9acfd58c50da9c0b12210600ce1b24a08d8eeb0af4ec095f12bda475039633d80714258e95ce1e4a9f226fce173f480863ed953b7b1b4ee6a1ae549af567102a0bddbfa589a9b7307666a73c9eda14c00b08e5cc4fcd8ec3b8d404f5f4a44ae95ad2d890a224880ba7c8e861549fdf932de5860c274659f2ef5d22591f207a865687d8144f77a0f6b61e6735eb25e99a793c3f2e5673c928c1ee4d5988dd245066934bf5656dda78689211dec61a42971c0ceda8776c8604bd5e5b64e21f841c6212ac814e92968a5bdf4b0dad08cd8221c08afb6745c76786953ae8a7fca37476cb6977658e6d429d7bd0f0ddfbb39ac40f56019727135aeb0b9ec4549ff51b9a5a5a09cfdc3635322010f9b3e06bbbc68e281762839e54cb45282a3d1427dde7a8d8b445300a228aa40c5f369dd39efb5193c6cb7c06c44754e37e5de27d08944dfbbaba0192b1d6006fa512afdea77e62f07b4d6dd6379a7de5f5413b7238168081ddd41a804928dd7b2ff7a5dda643b3c160653869c021651b41ea71643d8635668b5989a7ab31fc91e4acdf3453d6cccf7cec601b774a87218112f0adf647af90b25bc4c07ea71bc65218d8d3db18e5ad22eeec4467a78140d0bf40351dcdbe8985d9579556b39683bfc80a91988a016d1911138767fd2b98ee0c58cdf5c876959a76381cc374bd954a267d112307f31cf6a67a298ef7a28ac0f2453f4af3ee193af368d1fb0b4a02a6bfb7f9e59a82872acb89db933d44caa7400ea90eee2d7e2babcb62632ef5f55ac3dd81014f70908df4a2cfb247b43d4b4bd749c591985a47697bc2d9c83976aaca9ed64e2c0ad8a0cb801000d68a57401ff12028b04da43a4fd970c4d529e8dd333fa0d89ea775e80477bf0cac0c1f006a161cf5f1abcc3d17f855aad8b9c798f1a33ec60c077f63417d71a9b492aa0749fabdc8b25853169d82486ef5b3977774492b02e2b012192c648010d3676a443f4e20836f9910e2ca05c51f6bba926a1982890a5db653f6030cacc6418ca34042cd38e2f780623eebf80c28821a65b7ebfb9f9d0fb409cfee8df6018395e123c7dd9743c5b9312dd04a052c32529c5bb9678c667db748b37a574ce0bd7340f1477ffefa41c1817c51fe872841372fa425c4455f14e3185d3a0696856239c6fc611459bcfd6ded0f6be78d7f26931cc6b511b922a262488b4987072d2a1f2a34a80c9132a172444bc447032d15d3717c8da9bbc1c9e99384699f1b18481a4337a92439c147a83a1c848966918141a4b8fc9d96754e460c590fa8155ed81714e831dca90b4ab8478bf30b02151105810a818a408d4041a244a020a12051905110033dd5c290f34604d3104fc32d7782e483dc3a0f6558d9934fc0a045f252ae7499974337580a9f86a3b48a8fcd92b34f115311d9b027b658f5a6bc54a6210d190d869c9dd8589d93d0dd8fe73b0c59676c88890362e893426288d8826566a0771a00072c1ee65672f011d1e991e35968e6358afad8969d2b4ab0ae7ba0d8de2b5031fe25ac18e735503032cf7b8445ab3d5dfc582e81f4edebd8bdf31a9359e101ba665975ecc722d5583f9e62b8d52739368ac8908fd1f73d4bf1f51f26732cf94ed00945a0927029190fa9f380eb882a4b2c9ad4b8c348521725473751ec3c4ce8c39e255975bd25053b4a8967804cfc91bbef64e0453e5e979d0772f1c2c898ca3d0fc9b9c188ccf82e3f1fc882c1fbad7ab1b2f4b211984346906f4f9e239c097c16423cf3ef000967482fb8ef870d076e2e0ec8807b849df467cb101e41383e77505bc1abbdceb73da500a7cf28e01bf91067002ca8aebf1490e2ab5182d8bea10b2d9bf48ce18244d3caf0feadc0eadc40755ba8abd1472f75cae4acb445899bb950eb96c413dbefb148f8469e5472a7f2f7ed35dc4fd251430c72c9d3574afff6f188bb296d77fb338f16bff941f0ad7313bc7051f740eca9b2aad20aa97e2723d99499f08250d510e4874a2a708795d44d07860a20b786d92d70e6fe7ec0f7ca708f2d35e305a61602c4630bff043939c5373d641569c48f0a7feff4480164e66a5777e34cc0981310baf5ba89d4ad8cfbfddf63e2616f6f6920b2d7cf55c66b088df03a37f9adc987c5eeb1345d11bc5226439d0b7c2e910fb1a2b6a36961209205e1af8d2dc70f4053866d2a3fd02bf9a550df84db536d5e09877646a565e2e38cab753190fef454c738cc72073d204469feb4e8a31f74039232f5539a64b39630657f6495eb191742c51dff17933a2218059da4d09cdee7267c292278d0a986638f4cb91abc770a663e6eadde6fd6d95452e45fc03343c71c7456fc6fd1e3646e6be85dffc8c98c5763ceb8b72d98ccbcda3c989bf000837a6dd8d7984e6ad0a788204c2b2dc22d61afb6e465267840413d223222eabf48879c99716fecc610b31202931350319caf3674d0edbf57d2f771f584d021529e29a22064ddd6112574b1c8554cbb82f74cc33c3aebe2317e8b585e3226a8a597d23f469e0494de5886ee438b2a563f71f3d2cc6256d1d0e3eb7389370adc5f24fd72f851636cba1dca96ad0970e37c0748e2b9e22c2cbc3b086a5c8d45af9a04581da1f6d287e725eacb0592d28d86469d8634f3a8a1171f5ed8ef6ae5c334adc9de073af0f25d082dd19d22d38ce37a965dfa4d23080be7a66b848d50373b3f72d4febc7811df817500fd4a4e7d1c341dd55a70b3932b6f5be643091fa1369fcd0134185e1f26cb8dc07eadb7e25c48bfc50602eceae76da5f4fe3ed66eebe60b1ba654c7a34c2d7605f5f6491d4f672bcae2f71c450da5fb3814691883f1734290b3b6490b3b39146c61842cfd4c2cf8552cae6414f7dd7eb6685aae594b8b77bb156faad8b3224a4d862f38671dc44536526a3298162d14f0bd44b67b6ffb0162b0b2e7b9309a0d958971e059a32e1857c948264da50ab27007c0a74219c0b072b0f73e6d1c645ca8428937468a8f6d63a80bac71744ecd5cda6b7a7345588207eccc66372f81c81b921f8983ac097926c28883ef4ef6225c5a247ddce8a3741bf50e376160923cbcb3a139563b763364452a27abbbfdb82bfda63851b6648178a778ebb0b019cafd0b71fe313ec095b792e20e75fa721c6f438b7a0ff6211a78a915c43d068d9401099ea97b5d79eb16ced7fd74c046ae11ed99c62ea2f71ba1fd3cbfbccc1b46f6649a0042c0bae093ec59c8ad7834216c85e1657b841fd846700d1792b0b15671c95de663d9445662da856bb0b96c5e3a19c508dc930f05fc0497a7453f0f7c7ea1ebc811348c6954c1692b628cbf053482a2d737108c059c428fd021a6137c17b0769c74a5deb7b11798720c5e9bb41332f3bae34ed4d5572cc2e21dbde0bd6968a42cbd1e52539cd223bf6761ee6d744bed4fbb43420f6aa71735c25dba49944f3504bb9d32ea8018c3589d45530630f0e8e3026d720c207808762d473368defec8b10bb09944c5bf08937ec6f04288569b13bb13921ef065a6251f4e41c908bb948821632360a8671f725ff52d06c2d6fed803d67ea43fd04c3420c1ee0902021b12ec71fc28b22f20683eb9e1f122f7289bbb6d5427783a9e75b9876d529df6e63a5107accd39bb35dae09b0dfc3085b1b27341354123cdd775ac5e01bddeb708d233d20c553472b80518bf26a8914619f6e0a53ebd78b09c67e73fba4bc45c4fd823afac905756b4500f52782c5c96b644657896eb2ed25d7d0402a4a85c33fe8a9d68b64760e69365fe037a23c957043794834ec0105b07910547e1ab93419070a5c099ff559b96595f1221d2e07cd5c678aacea44aa4a8d4eac685e11b1cde347510478c9caf611056ef13b793f560e88b3a19d69333f5680497bf819e9707757baf6d0c435d811cb1db02076bd73254b305ac12cfa12f00adef5942fe61c3c992e6a93cad6ef19aedc1f33680e905a885b64a0b8aef1f0c6e4bbd5aee045e93e87696c26b7d7e372b2ad25fc50641320a370fc29be8e6651e606c087eea43b16444f911a46ca35945a74ef1b2d4dde0023f0f27252181fd5d6c15428b622b3cac36e28bc4ecf8930f3c090464ebe7ae4b49f638526a2c418b4a0e3613594c1b35adefbcc69a84875ae78cec3cd24d570d52d27e480e15b6dbc6fe65a2a8f6f927874d7de68d8e5c82502799baaf0be44d76398531629f22812d21ad7ef4ea516be67a64e4c85f80891345bca90b8e4642250f4dd1aa164722508f490a703c8b940296bbcd30d57b243c0570a2fe0fb471a4e55e4cabab05bedbea511e41000826c9d8615352119863f5e1da9f0259465e7b14ca1740ebafc525a2c6409336068f035beb518eb27597d99afc3943f115407a18954f7d6ba8ee19091540610c150c01c822cb3ac1822623b218eb808a7e84daab34ac3129267364c7b693c502efe641cb2ba5bc9f80b4a8081a98609300f9dc54ac1c0fa223f75380a9d0bd9ec5ad274b547ad0da5b811a6e285a000976060022e4486e60a8053f1b4aae42db86627f3ce417feb84e03c27f999c68ca3c3aebd353252702cb91ee5a1fad1a98977c27f72aaa4ab2a7ddf5adf8ac89bc1ffa560c0f01862da25cc6fc06b22df90845daf0ae44ae105db09253738b23ca754397177d2ce455105dccbdf89edf71324909c6cad5b586e30a6cdc17f8e6531673229c2e03a0723a9613cb69f52eb5d325b0593d5dd0505fca096b6b8c2fa9b83973d9c1c77222808544d77c53d4b2abde369d64bc3819109cb961428cc3e09d1055b9eeedc92decc368e126ec62361882a71eddbc86acee4355d31d5c4987902dcb87d244464956ea51cb1a538e7753655ae87b909c4766d39e8565dee3e5387699d05129396a5c0b462f5184adc269971175a0733d0013caedee818997927285d600361c707fa4cb89164179e7aaba8800009abf0c502439a8ae174ab8fccb82685c74aba99d1271ac5f31c9e76f59a0e30b26258826fb9f9ace80437fc162b9810c8b4c7c30bb34745f919af70cb13941d4e28210a6659eeb6db61c4742e11bee5f1d17e32e11ac59452b4139a2b6c753782de95765ac1475ea6e809e123a9c138dd50402b7e460488496a2942b49f690a431f9ccca6e39860d3a59c6d20f93215c9410998ba1da4bb47173f007075de7a3032c747c8d9109fa70b0f2e2fad715df4413a83c5ff92cf4cbde32493769ddf60d3facdcc9964073b900793c1014f74291795ac6f52d926d088a47efe9b4a460782ce594ec5c4cb0fb3b68c4ff934e3500214dac15f0f344f215391d57f2f899ef7f6c3a80b30f0484a001993bda4848490523523bbd83ff6706e7e778393076c07cacba022bf601eb10ba59dae3f518f7315541c63ec98853e51f388919c7dbe8ba3564b9a59a3ac4cf43fbd92a7c1c07e3148d2c952e7b895651713c9bb07dfe74b74ef46409c05189627284ff6b4e52ea46f70ae9997e8a3ba3d94a28b2b6ad81225833b01df56dbc7854d134cef72c44516cfc5651e7345687db20b0004bf9eb390b4860fa6553945ec98d49a8caa7c297ad4410e0dc82755a1fa8a5dc5a3709ccae471bfa6ef5584aebdc423c37a169bbaf0cf6689017c24415049282a76ad8528d5754d36ba2d4d0293a0ea69b3bf20da5ce45fd7f55ce3d91219f3c330d5347b161353381771d5bfe9aa2b8ffdb33589a0d06b491425df704afb85fe51a10718ea415b2a0acfe15787dcdd63ec6a06368100d2753b9cf950fd84379269778e2d9317e2b70aeb97a7885a095622c16e3c2a45b6ce26180ef130be24fa260afc8d5ae9a229d429e5e16fac620969750a4881f27d31cd642fefd4bdee7ac84f389488b3ab1c0ee4956a715431a5e91e7d30e99569f52f2045de5105f17a2a64e61589a15aa81de08d3f572d66519c5ac8cf20c21db72905ac623ea14617acd7b3c075bc223dcfe5866665ea7c54190541f82bad938ffb1aa9d4afb5e1660560ea328615227edaac20c0609bd6132aa72d0624e967452aed6a3775fca4715fc8a8c79519a5e097070dac3b9f2faa51cf7a1e895fcc3415f64460c2554b8fe8cfe75868299208cae24d1ff5d4f7f4300a7b3aeb83ef93357164da3a3c8c5f5c35874c333fd19cf2c764b32f659d600464935c2992bdf1b97e2bb76b36472d67a83f3c7fdce1c67c8c6f17a44616135be7f9c4bfda21fc4a39f17fc4ccf2b4821202d8222c922789fab920dfc47bcce262c1956d6c5e5605b3b8f9128cad8346c183f5bfcfcc3607a52886407651b002a46ecd328203215a211a1c4807921ac9f2f84328a8f8c67eb91ef952f229654abf887f5d4c92a7d41c8f7d41b031bd5a95f5033b9a77e95c3d4ef4768f88cae44d26a9a1797c07b2dace08b3b54f5cbf359cc4f91fe8f9cdf917a55896e4b88750314f30069495a4be4aa9f86873439098e1a7562a53dceb64b76096b5940dd4c3024e83ae287310ee68423ea868481b62b8f6c883b51a255cfe4174717011127de161f1acf64968911957932a8c94e0599c067b965b1ab6acdfb66ec4ee52459cd238294ac1a2ccebfa43f10b78c159d9ee5eb404d74ca18696295808e54399fd9c13a7b247bdc2bce7845603a56164bcb0257fea759332487ada1b45441f4540695720aa820bc92c18fca5c68bc6218658825479e3f3fdad250e16e5bec2896ab183525c419095cc041ad0943088b4293ce39f4b250c0f3524072a2cc5258445e36dfd834f13c7ffd2adc5241a53e0e2de5b4066063d28012cdfb64da99a99a8bc39ad4476a8b114a976c504388368343deb662f14ed39ef62afa86cf851cd3afc1132d8ab5f9f892dd324fb6583254f59ac033c8d206911aaef902615b21e42ca26ea3f371fd517a0cf53a980471535cc81ef6410e4c8ea2833fe37736cdb9201c2327311615a34b7edee00ceddb18563772ef334ded6e9b87210a8c4c16618a0859b3f429311ced221a2e3de5e2a807c2ebad0caa58e0d3e807a45ee3622ecf026f0f69ad4b90d31ed87b519c180b56bbb52e89daf08fb6f0d3a92eb5a0159fe4bcce5250c158120ad1c98831fa6d94565c29f294a2ba92ea1b0b541131868d88391f56ad35c9cf1e70db2a351fbb6d6db8e03312edb003c631e3027b7f30ef8d984006b0ef1cb1b0cd874bfd2f9bfe2c790e7bb93f9a11e1598b53fadddfb2dc0f722e2bb356541d111bf1ba19d86c9f84b7cc5e5195701b63d379a998c52d017351b6fbbeab9670b664edd7e1b58cb66d135d42e8d0fb93ee1157a894b7971a25f37c5063af3009ebdf3d5ae41506373d2dd634586f517f2e1b15094549813f6a7f5be14c674b56968c01079e8dacd23163b702805b9772b1d75b74d059f2c5b36e4c18440bd45876e9f470f5fb919a20b6241470af3cb8cd127b3dfc166193ca5067af9e5029eaa93279b91ab2d9152c74acb073c9d524224acce1c380fa1c698ec587dd627e54b3290705b726e997a546a081c1c03c263655682cfbd90121450854c12b1126148fbc01df570404aa2d496a48b63b71798deedb3f540757929e5b22d4596941fcc41fa33384f8d1c974f51c3899bd4b3667d5865d3b27713a2b4320c3a8135e40792b1f6b1f21f8af418f02395b8305548ec38f75d0edac668869e317d5d8c251e5d0569bfe76561cec0bad8662d5ea5640552ac5c443a0634e70aaab8f7ef2f82908de60ddc649d6be678d4e3467a8fa804f81f4ca07fc98eefb20245547ac0375d820b5fa8427b3bac96453d0c3ddc8299d284ff19b89bdb718b39b8fdd2bd886d827f668a1c98d637a197c23622b44c549186bee6bb3316c327290faed9a20ea827750b0b4c1d0cdd6102d3f683ea47b83ccbbe61d5991ea77b142515078a98e92a4ac41c652b90635095dc8ab12e89fe6077ebc2754e4a64a615ce8ca11b8cddf1609625f390e33cc88945a72c879022322bc9faa092b74bac269d513d2f6d5ea64e03b39b7493e9ae9d0de74473fbdbe2b8ba6013e5d34659849d5e764efe1268ba6e3bf5a9af9dc493923761badd790e4a00ddcf24dae880be0a21a3d4dc2840c033106624c44984931906044c294803901033286240c8830106322c74480991403016624cc04981330231eb8901c0429eb63ce8ebe69a26cf7957686d21c1e51d1272d7367e09f8b8a330660757a0b4b97591dcd0735ff6c7e994c16105733d9f4a4e05a197ca4e7332bf40ec5e158b0811bd2375a8338fac5b1e5f2ace857d2c83ebbf0cb97a0f6466205f6f5b83e84820beb0471d6e9af96a25b1c664c151db9be87442bea9611f4ea69e9b06609fb20681e6b03ee82261e0a523cac0780bb9d183b174773553bc8a475f6b173c01d27aafc63d8c2da45670f139ad21db4f7422e2409d7d9037676c836021a720be39e79c4c1dff8ae28f728b339523708a023134d79097c5f310550a4d02dc385f8c1aa900258866a68108d8e72eb138a84a42a5b89745785965d995093bc47c9283ef8cac45c893c4dbad4194c38f89b72bda4e708ff05554ec65eec28131b1b63ed5ba5568275c632064aa8384a97d748bb6a0565e2e001343c7e094736c526940976e951466877bcebaa860d1384b4a27c209ff55853ec093bec59930034397ba5116db505530e1dff61a448e3f13cb7f4c306f73bbb2c65f8907b47715c618e5a827076a47ea31132416c4994724bb9e116f2891f63730171b8eceb153045644217770e83fe1e35488550a65e3195892197ba640a73e3b3d00acfe1ef302d0974054955491d9752b823d165d2154b3bbdf547828d4cf05b906649a42c0bb6b12a2646ae20ee42bb264a2a0e4c49600579ba3f6003bbd36a615cd56a36039cfaacbca93883d66dc5f0d841ae80f6350a65a3af42dea86838182aecdd556cca7c420d8b7e5f577145a0ba606a2be775e52544613a4c2b4e8cf68897ee5039f634a14717c9e4062f3de5c14ba9c4df5c4718d8f86b4ef03ecfdb238e98a6678b630555d284a1498bc992bdf7e717bbf4953e2a28b0b04be82b60c98d879ff5652667cf085e24217240139e7b2276987ffabc5a48790d6a036841e1ea2e03f527cc0621992b4217465aeb8845432fc62fd309b3a2a32fdec40f67cef2c88056656e2519fe23b2d0d0f08c9f20729a6f767b151c12af288d9b747ce6150b9d891044f81e853628bd47c9eb148f0aad1f5247288300a435422ffe4b235587cb83b5bfee089b29f36f66af876fa9ac733e1a3ce6e952ee4afd13726006b039f4c2298dad71b15462e518c075fbcf807e0fab3380c3cedcdab9401af3d23b513d67e683e618ed9d1b86f2c9119aa550c5f1a31be3642e4a374eb102dc82024ab3dd5a5d308ec24a07fe821dc6704a3436039ab0a10f1f8b250e6767bb93370844061dda0c9ea2a0e0dedce728d8d04a4a76b35fd681e010a0a3328c35100d073d739d239c8fc56275e22f8a69086f6291c042235364f9c9de726fb9b79432c9145f05a605c705f96670f3ddf1f2d5a0cb17001b88b100d07c0530f385c1f375b096c506105bd110fb8c8d03bd6ece15c91eac65b10df2a500d0a0d5046f3bf97219e46bc37c3b58bede8b7c3f17f982af7c57ae7c6974f2c52df25dc122df9a56be3639f9b270f2bdf92aec26d78e811ab0d9fec561e59b63936fab265f162bf26d81f3d5a1c9d7b5caf705e6ebe2c5cdf7bd7c615dbea1cd37032edf9d2d5f0d68be0098f96ee0f98a9f076b5985c97c03204e971d8bad6a489b67fb0f64fa2dd26d871482725725e51e351f6d4506f544a15545a8095256df012dabff33809a6cfbba83901e8eac800b11326fcdd8006ab296d5f7b754601ffe2dcae04a26298f1de5a3270a1094ba83439e32279324fb47c0674c106496750417a5307af2d71125fb9b80258a29d9ffc70e098a507ffb2de441021f1d9041f5fdc980e91a195af6514223a0df43b099fe77c7260d3b5033f0a379fc7fd8dc5264ff0d740cf7d0c719fcb9ad40c1431ee25af0405691fd36cffcae634c0f66d7e27ce9a0875d08354b3047adb26b689b673e28f368f30743991b6ea8b5564ab74a29add469e8a9874f9f3ebdbbadb5e20e1b8a3326e2f942063cb6b5184b4dd1450b831345510ed1a080da155adcb6554a29a51b4729e59ea87e9f67f06f38f8335bd8f7b63e68ffc66cbd8b5da88384e73bad61ebdcc06d1cc7d5fab572af84c471b5564a374a2bad525d10a594d6806334ac74ce49e7988feb31c013e067cf6eea98b1d9853f63f35ffc309146f0f123023c3a601de31973f518e009f0f5e75fc163d7a62b20e865ddcfa7ae80eee7b78f5aad36bfd361ab7c54f9a82961242a887263215325bfc88de54c55c6fe8ec4aaa24ab335bbbbce3927529546f2e84b140e39e4a249f4a82807e5a22e58a7842e4548e00e7ec434bce162bbc8fde7452f84709db5ce39e7a453c2e86cd59eb43f9f0164ce59c3a6ed475ed40d24cfd18bb253255cd4023162600c3104f6ef3a2b9d73d2490bf272f272c25161aed67a944491847c87319e01d3df2ae8b36d75ab2dcc54a585939290908e923a87a2a2225e7ab3ad84a9c89225539e28a5b47bb285b5acd5086856f3cce932283cbe8ef7e9d3a7e796d8c1b0e257fa1e9bdf4f5094942a9d73d289654889125100ad588b29026d86aac1ec78e24401b4622d7a4329131e5b3bdd6443466bb29a67e6d01b4a696d25c134b0c7fc5bad7f5184f9db0e1ffbc9dba9c9697c00e4346e78cca1b2ff53f6b047cafd44ed88da81b5d0683b28a574ce4ae79c7462b12820415295e85aaf534ae9362d0b5bade53c277c671079fa748c29c3635fdff01e61e4a0c9329a67fe8b16e0511c65e4692dc6ad96cf8ef946c33ecbba2c8c8e30b273226c20fd065bae6355b75ae99c73ce39e7ac1b9d736e948e00cb1108a575a394d6ba6d94d239eb9c74d22221dc2e523b2b9d73d2b904953e6be83e2775eaeeee52523a5d4ae992cb992fb9b19cf92922379633435916f98ceda79ba9e5c652e6284b6e2c659632adac4c73d53702a1b46f8f0e918bf3bdc8ef0d756c78e462a7c3ece00440e070858b0a2fb8209bdf7aebdb93f95e672580a5061eaa8a8c909a92cdbf1e1882fc412173a127cdea473c1c753a143951d1d17cb9341f1c028fb2a8050aa699ec7fa4d499c72ce9ce7047cd9072833978cc90421e334a0552a66f6700e1313b9a15516e56e433e8ac68963443a294c72c69a6344b3aca3c66b3a259d18c88c7ccc8c24c98b1284cfe8ceec1f61408903c65519eae54e3250631e8d1e245047714532de31c81250f2633512f23f0f360a262a2a294d258a6b07103c1cbf5ab4c6698cc5029401b9319262a262a262a2940527ea400490992026499cc388d66aa62a262a2aab9d84c55434ddc4929a54178b45912659744d8566a14033042846c1c1518bf803a4996589047bba4692eb9532ad21222da12142c51988e88054450b48721251a8698544a5b181a6287806847cc7096e36847c43cd18e3471440a731c679b9edc1713f2a7caec414a77a7b140fb522596dbc519c475259165b2bfe88357c9fe1f9d4f2955421b0294fda57bb9b126f8933f48f2a82e49e9ee40434613cb082295ecff304a905d66254a5176156e0932f7b794dd0d764f1bd99fcac69351cdca50cf94aa71832a49e9948a9121c2e8a9d13f27083a5cd451eb0730765c2c3904828e0f6a30ac8dc22ca496acfa1d31ca2711063a8c3b35ec0260b27c4a4247e57622cba70db3006da8bf64f9d493527a72a82983f6a30d4175e033604356c25e31e19382d6ce09047584065a293d1274e449d51122370286db36235ff248b311a73cc2721be162244a524a2bc7fd14a162b78db39666a4c84892ecbcae3343334264a488773daf46315a9ad0179a50134da809da91259a9012342128da4f124d68041ce8286532258f5f5b61f2259bb95304f9f519e0997e831e785e0581fb279e31db236db89ed73cf3ad8c315d54b86edc46b7ee2b41e6ee6fb8e77d6feff73df89ee7795e09277cdebb3861b8b823d670b1e51a83dd0a0cacb51847175ab7f6e9bb70b167691838f41478b4f67bdef6d0e00fbb6adc06b7d34b0a57163c3e0e2ba7e5be23051e2d8b97147864b9b2bca0c0636bc705e8f33637abe5726579458161e19701e863ddbf6f07f4b1eedf7782f4d5103f9cf0f234c4112e519ea6643366aa34e1d0a587289f607ea8c87899d2f2c409a6502101102a52949a2873e44a114038fd49c1c5132b48586882c80a36292120e9f28253940f2f10e153484350463c018312282a9ee4ca161882949922060c11f7222978000823a68e56206a62626ae2d2658b0aa4bc1071c26b34215081092a5cb4205164a9bbc430040d6776d0c2822f2e050a408cac1009f3840a9896aa2454047e94a0a108a889ea0939940215482a1061347485c88a0e5b0d6544906589124154704a010aa2ae8041da4273014521c846c5040e645a700495d9cc89a32cb52142966809f2313fb427508c3cbd008c0860c861014cc280298304162a50504f8c9c88300244942a51a4c04ae189312b541989010b9bd2d6460401268ad0142fa042c69fc032450d9f1bcb1442b2971b0b1933ef148eac39e794f45d4be091043ac32746e64f561c38d359e59ca1cf49a5bbbbb7bbaf5879c67ec311984529954fe55b80ca70b230ebca0ccb74127d3d58321ce7f4cf459f5356fa74864e2ec4481750e091e61cf4a395eae8e0e032d56180cb6ea795e4e955d40d6f2b1bf0dce846b7add229cf740f51fa3464b958dfb504ae734e5a87320d6d105408fb371e5d4b544adfe557980c5b89dae76a385b2d8c9f0bf1f8e5f961d64629985b2b372bed8a31b7e128350fc76d2ef2e4be724f398eb31cc7598ed23a5baa79386ef38dabde100b2ea573a2305d512429d2b3c91748960431761bdced143d261a81c79d9d2f3b1eb0720d6917cdd953451017154d28edb979de26956d5ad9e69449670d73d6aa427d114d198ee89c72ceeea42e5f434ea667e73957b8de4fad06359db588fc4c612cc7dd2f329d1dc54f98deb0da6283cdb37d6bd531b856deb870020c086b93760daa456a907fad498c20a89b6c5f71db77edbf35d35a04a5992f8964960f36071ed1dc38f08a640cffcf18739b7c9127ecf31a5a6e033da05fbfe2705a95c76a548b6095c8c5244492831a83572439a848aa934c945fe40eeb50f3f87f43b87fac43947b0ca332c42eb6cc9e1112b7badc604a36b90dce03eef676d9723ed93a58cbeef449ebc664e36cf72f5cbc5c3a2d58b47228ec26dbaed697f325f71727a7c502d3acc0ef7a9de5363a9d86b479ea7fc0679362bb493920b96e62bedc06f9daeea3300db2673b5ae4ede47b33c8f70bf30561f9ae3e5f9a17f96217f9ae78e55be3cad746275f568b7c6f58e48b9393936f8b05ab052b5f1d9b7c5d35f9be56e4eb02e7fbe26160bee117340af0648a26867c1143c50f1c937662c952159522429cc8c85c8c9412435c8070a2040d32e79664076284c25450902a21da0a32c7c961071b42a00413304764ce11ed60e2080f2e7001162d4960d070468a16aa96b8f0848321bb8f941f9c784272644448e6564a1122a8501591d4838c7b214a0537661400da0633747131f1422c065bc49530481c278798a8329b9230d3d9100c8d3626fbef884d86969494c1dc349a1279dc09e2b28801f7370746098c873aaee4e4e2a7e4e442506871a0215ca464fd3686188e5421eb14c8fab1540206b333b2964a41d68f8b4c9d919254a65831a2814492951e62a8aad1648229b213a80b46dd0c73afb5effde73412d06a417ec9e6effcfcec29cfdcb41caaf27c1b1d5cafcbdb73760369f5c921b3951cd71cc751bc1a81e4ef7bee499043a207db876067e7b405df268d4bbfcd451278c4130116583df8f35d2481ef7fb0b19f405885a3bcb0968bb5be0884bdbf3fb67cc420f8bb31419f01def073f10a1e6dae2dcffb09fa78d64512786ce5da72b13e8dd3dcbe4f87f75f8e8b43837c431a1a2f1c499043797bdb7dfff61d82f449bb6de75dcf2b5282045a515391bbcfa2244a6905c12225dbb671ab550662acb51d0d8df7057f9ee75d8c372edff7812b56d43cd57cabd58aa6a6a6c90f18e31536363535362c56931c582cd6cdcd4d13a22648389f144a02ae6c46b009194545d18344c524a869e9280911105517a8a6a5231892000dfd54810188aacb0b50486a4d2f2c011d25790188aa8b122816684a9a683f494b474994005175814ad2140426c9120b5b8e922401a26aba42a4b9d025f7dfdcb6ae2cd8ffc6fc44a0d2e76bd6e373e335c3a3e538ebd3d3bd66debddfb75a8d34bf66af999432aa868d9e9a1a166eb15a2e6c63c3c22d56cb85592e16e8d372bda59ffd30bd116f409f1d9cef359b45bd662d16200e3057e9d2e125ab7ccde4183cdad72bca45d48b2859e56b26e5f65bdec23103324806d574b93dbf5d595818b7f2f61807d1e7a475e35c596a749f08ae563418f4c13536363932a7737070707072725a2dbac3c22d56cbe5ca52ff5699b7efdb42aaf3b9b260d70bf4a1a00f76b9b260571611168619645077409ffac92a653892d051fe12031d952de0210d3f1611486a524f4eee0898bad8e14dad56abd5a6a6a6a6a6a6a6a6a6a6a6a66ab55aad56b3714d850913264c183faad56ab55aad56b37185e9f7c9c3a57f294ce69e5c1bd033565979ac9137eea30ee838e7b8e6b138b8cf615d36b575c57d057188e38a5c4720d9db3a30c7c7813b805450e17e16c4d1cd932b67579decbaefe33e10fcecd87d1dd8001a8cafbcd782f641cfb3a1b7fa3cd067a4f92ed8800fe430e8800b4a106cafab1598c3fbed57200e9bbd10cc61bbed0371d00ada0773782fbbd032c0cb3273e1c881bc85e3cc0de2982fbb2a56848484685168448c684496d08820a11111728636848a36648a36248a36e40b6d08140b2568e972ba94b2410065dbca53098c6cbdf51676df98db566977772d12457777ab45bb76d7d0465144fb296206cc96964e30fdd958aaa0d5ff7aa71e4076e9c12805252394767ccbed1d1958869436a40c19dff3b9985d3b3ea367ccd04e69e3023ce2d93e9fae77cf1d57d32bd89f877b5b4eba71f649d779f703572b31583e0d8803cccdc22b6c449f0eab53dcc659ac9b1b7963738373838383c3b2a9c1c15981717070687056200e0e4e27440621e16be18f86be66d5e5a298dbbbdf8a86a6e635abb1896ab9582cdc62b55cf846871d166eb15a2edc82c92816342d7470b95e635e2e5e44bd6631565cb957becb29ad75db38ceda0ef4a155a9267948debddf07622b6195a826c941336c45d7d425b156a953ea52ad32a52ee1e0489caa64c362ddc89c9b9c9c1c964d4d4ece0a9c93934393b30273727236e0a2e4941ec8bfd2e5f4d973526f3ad2b9c2756591a110240f8882c0bda3bb7b859570820b71efabea55d553855bac179957d56be6caf2129333e4de971826442c6c71b24f459321a949902c53b5a44a2e995ac2c4a476ce0f0c74ce5a6bdda8b5dd77bf10c0be256dc78139c0ec83049bb77de7ab2043b6a35e0d57cf36c4071226a7c8a50f240792269b74681effb187c84ec316573cefa6e05b2c94b252ebd034b8975ab2bfc42281903bf8937885d2cf724fb82730bbe37b52dac184e5835fb5dc505774ef1379223d3f84086eb1bec8137931e422891741a4b2cd5ec7e99831da2ffdfb656db1fe06eb5aaccfc1c016eb5f1d3e63458b3734db4145c927f9a4a347d4534bddda75d59dc0e56e1a37b4459c11278c7144f6f7965a9a46054224b2ffac8038a9976ff7bd0882e7e349e35acf68f3eefcee9a0f175dbe54bed59540146e50801b0717b67c5ef0685d30bedd43db2f411cac177c972562fac9b9646e6370602157e1755e88b81fece5a645194385a3b42cedb618883cb6ea0aaccd47d38ddfb893b19cf2c38494c73a8a52478b82248f3bad9caf853fd6fc700bf74c5a94153c1f3c6475f15883e9a00b554b28cacff604e672d3a090c9e38703bec94d83d2257340582a8fdfc7fa004ad48cb57d9bdc34274b649a9b0685c896825d8262a73708cdf6ef2cd9fd867f5e8377449623bcceeef2e1031c2a21928a9a368210641f28a51f143a43f0283ab90927481f8a60f2238352ff04e964cbec8b0c8a8e07d57eb56183de290cbeafbe6705bbd1810fabe77eb4018205b8b00317fd6d702f372ed4e1be673e08d3e1421c30f2cac6f7fe12b6c2211ffc1bd3e703411df930fa47cd3714c31e251d3b78f468ff1e3ea577847bb20ef7f4431d2e9c6fb30e1b3b5c43d9bf86672b61a28bdd0eb8c67cfe0f9bb31440f3f8c73a86ff0d9735d6a233a066e915bbe84ea28e1d3c7a5091d22a2918cd08aa08188dcad20f9dd2c68e516e271d3b78f4f0f92b20725e6c90e78f2c328d5c19c13294b1514a29dd6032dcade099a5548f0a8ce0333e4f1a8e98a679e65f39691060fef4e9314205922082022796c8f33b240c4a552124cd45d982fdee1fc850d9d2c40b403491ea6658610a6d8a19124a64f26f90e01f1f72225b05f620072201ee2080d892b9ffb165fbfd1cf7e422948b12ff804719255f76e13e6a8b94fa867dddc11cc8835c949e672dd7efcf8563e3e8bfdfd37b5fdeefef7fd41c2ec8609947ffc9f5efe5386b7ba44f42c3fcbbd07b0e36ce9fccfd44553dd59cbeb81529292b5f9c6a4f55f9e783c4a1266aaeb9e66857bf4b98b9863f6aaedfc9a52230c84dbb6129d36e38ca4d134117f93172d3444095e59749c3818a24a972209807f9f44bff21833bdf16a0183cf697fe01bde0b1bf38e83fcd23df451596cd7132687690b5d87f260dfc12fcb1b5fa11d3ac78efdbe946c7fabb5f01c3301ad80a06c2ba63630dd92d7d6ca9f90ef3bfb0b1a5727f7fe73f59be858dcf6d34a42e92d052991562f9391e025a0bd5058a4a6ef95d92037f57c7a44bcae572e51a19437e4b054173828586f434bdc708359c931adf79977b3f29d4e02403fe53cbf4afbd37b498e3da4e3c63ddb20b6b59eb09a640d33840c7280799be0c9a342e277f5a64f201a038c00b32fd1b6d9d280d59d0f0f69c094f24ff7ab00b93413afddf0391f5dcf75e84fbdef77bde7fa1091d9831fa5e38c28cd13721a432ef9b477e093267a0d53cfeb0e691bf3d7d3b6354be53b187f664fa1c0c16d65aee0c4eb040a45729a44bea2ee7e7b77eb472df36bfbd79bafbacf775f7f3eef75df0fb2488637e577152ca714fb9e742dbb273161123372d8721b92637ad06210dbe8c8152324193198a90390b6170f82630c30984e82074c5052776ab342847683433b9959b46c3182719d5b9bf0bca511147f0508549133222331c4152c60928cac85c86cc334513112d61bcc440029923614608156a607aa224e36210618a1278590113253f3c9101a9d2c213299c9a08512b22f3a2ecaf63d200325b8a62aa09e14408156440569842061b98a8c0e9cb0c5c93dc5c74a842061768e161494ae63fc20c9847a8e40dd834415424250000007316402020100c0743e2701c49c24099e50314800b6a7e445c4a34950723b1502086711c04310c0531108418630c32863185182a2d004950986994834221fb911ad4999122cd7a270fc5c724ce81223388c41b0869469c27a84fd278203be46305f92c859dcb4b405bd16ba709bdfb498cddb268589b693619525d4f2bb76cd8c4c5b2ea3b661c3bf6131e515136d4e8821759f29024095eb1eec50ee1266a7a708594405809dc357e4e2ceb6f79a5653f7abdbdca849e3bb9070756c5b623c178bcb9376a642e4c7722db0e11eb1d6bdf7ba85d7d7cbffcca74a19ac2d37f96059452d014ad73a488db202a3cab9fb2cec6937dc315f1cc72882d40c6f8d2f8480475e266476077f095eed6d2538e5b769765b7865609dfe4f2d59b6fb7578fa1dfd238657ef3932ead7b1459c817fa6d1d88809455608d3b890837138209f63335b5cf5e14d5582f0a54f4a21868eb0d671fba00c91f82fa81514bc45c5df2435132507c34730eea01055a184880a00c933c76453d2c8441ed1e299997027e3cd0428c84213b6254228265496a605d318eb41589b72fc898c5f7af8e11b8adb6dce045259c0413f21286a422c8242a578d58e84e4cdb958de0f6c431fd25152c69e02917c227c1295ab20a57176f412449ab15c429d70e1a2ba8ee96b86a784b0813f1cc84e15d5cedc2de9ff2fa4285c56f29618eb9dcb297643c7619ee0713298f0f0f28ba05b426e0ca18d69ad05cb64a2e77e523bb78c0ba203e2518cb38b47368403940d95d1e4908622197e1162e05c5ea2be0586b941847a6c0ef223614244038499745bc6d0e89096974212ed67155e93dec634ee580669f19312f9a4002b5c468e6d132fe1cb2e074531abf611cb3207f32f64d65833888f6230b319e43b5a69eb70253496b3d0393a81141f912a8383bbd628202db5d48b902313623c5059e7c30b98745a8c5f22476484d0b835f2a9312d87fa127f91694c83cb8d03dbc489ba1234224820e73a9b765c2af9b461b7f5e70ad1736fb450ffe0718e2e41a25e3c2bdf7ba2d4986ed3095c029a34271c4d0b8e4646a30459e684d416219fee59f021e8fb2cdf33602367e63a50b4cd1568a60a40a14aec31549910147a365da2eaad3f933382f5559bbede8c554e9da4ca6c5a16c0af8f41a4a14920dd8f74fd4886c275455c643536c6dd2a5ebc6917a5282714a7213cb212088491b9045ca300a769719f41c0182be5c88e8a4b097d1324f689d6d429270455d6f192c20dd4febacf9fc43bb4c6e7639829b9888bb0dbf9df589cc1551b0d6caf1ae08a29fecbcfcbf3d1c0fab8f6620e4015889a1a32464be222b684aeff8802459c5b855b81f740c2f07493271e7b1901710c0ba296136a2c8ab694681fb4ca789ab3e41b493f8fe6e17999fc4102d6fee882e353c81ccb986abb7b7d273627abd14391b4d65637679111895400c54661964c781126824c10c467db0af36c9a62dec0dc632e97246184d4b6e987fa875a3bd1fb52dbd68861547eb2277bcc835c93c46939109029694d15730b73b453d6c724052482128e3d09b268512b24b419e8b19984944e92a1bdd7eaa8e03345bd4a9e3aee0ae1c97ce2ad095f9f7c4521c8ba47295c3c99da5c080c57ddc95cbd6669850b166e4af72d70923fb6102b0d79f60d3a11a0fdf250ca9e935f9009b7fa6dbffa193efe5455cee65b6466d3c67553990fe4e47755a7adc1afa43b87d08ececd5eda99dc0f8ecec206a8186d26eb838710c3bbbf7886e39e841dda51d94daa5fe9d5602d286c5692d6e553e56bf9d7598f551727d458b3d32d82b2ad20ed2d8bd74b823b08efc902577e3dfb97732df7aac8bac25dd994e236caa01c315e0dc03f7b2a9c2505e923150f5603b685cc279b3abd397f4fbd220ca0eecd5778670759a0eb18c8add46adddd1b29ac9121bab0e8593cddf831f3ae1c026bc1fdc723e54b413f9405ec2b383569415cc76713581f5810ab6bc919e93377eb127600439a6cd7e84b6f927594d00638322c616fb554a61c992ebcd387baa27c6b3d5fd191b6b5ec7c9c01afb206658473dd51f8408f895725a591596ca8454fad1225f03590f414096bd918b30944b85c732c66f85b6d52843636c69c866f579d6abd05e923528ddd05a7ddbc65ff0c74008d36253ec03fe7b65bc3320f762055d39c8b46749966d0ad74b145135bc6d9b84adad662942169f253671992fcdf1735799f455bb9fed671f90b9b16d6f2e9faa41072c9931f5272855d824cab6548869529fa866a295a92528450c3fe2602ca709e6c09feebc70ae2442f2622fe4065096318b9a5d080a0bb0456680ded02f238e574324a254bb1d64b832108365805e738691fe85392582a11ee1364aedc6077e4080cc6a358c83e040e6270a355fcf2a049ac0412bfa41832d90065241e44d018deaf321374cf8f363289bbddba74fbc7df6af2ed3cbc519b0de344b5c79f61c2b1c07e47b045864cd603bf983fc520f0125763f29fd87cb5b41cc7c11a03ade8bde8d2d0ec66994ed0519bd725383ebb631835886d72b8496003401476294822d6d89e2ed25b78f1d93ddc588d9c077efe02f3b46c02d0ce037454e31407123fa9593a6cb32f4e9cf13ddda9a1cc64e6608c6791dd48765350502c46ca8126362fe0c7be0ff5bd08984f9efd139774e2d5832e903e6a2aca8b644203466456f534951c715e2ef3dd68d36ef67ef91ac80862a170ff9a69d048a508a41e1a1b76cbe76d532c6c24b4b5f2ba09a1b5ee106f84bb887d3661a009ef9bdd3fcb78dda2e645f41feda791d1443abdc0227460f640d9e07ef914ce911537e1d7acc234b82c62676fa7ee1640239f1ea8884bcb500abc0ee25ae04b01dace130ed33003e1b4f0fdc61e104816e167e1c6e30943a515c61f96f1582493458bf5e7fb8562914d2792ce3f3082d39c93a241521fe119b68a54641d192b273bf078afc6a8ff26b486c34041c4daf1bece1e553ae27a02c000981d806b521460aa4a86223f3d77ef2e09a1e0098c9eafb574223802568c612ba41ff17dcc3a39831945ad0d253028fc439ef9148eadfaedd05244dfe4230b4f752d02236dd75f949fe26bde40fcba7fe1043a1ef752a256480e24ce469b1f136a6bc8048b523816d658e47b5f3c343b513faa7769845896d6c20a5194e2744808dd9d8f18e1122f0c8efd8c6cc47abf33dc96902fa9f89f281373e92ff62fdef40510d0957ddc418c8da17ae18f998fe24ae1b5a073374f27d4285065e39ef36a824733a7c1141c11604bc20ed4538ba8a0bf225ec02c21c306df89e2e7e8ec917bf14f101c9bbd3e50dcd86b2e1f5cd595733d6e7a89836ba5bf50d29cd098825d79526122608aed4d4952f077a5488cd818f531802546b418a29329d52a1e601f91352a25f91cbe6e887cf4dd08d1853cb65d3c5e08f793b44e600eac2c5cc7f41e24915ee5a90403b9c2937e3f96fc7e97748f8c863a5c7ecf15eacbf7a4fe703909cd070059f95c28b00c7d94303bcf55ccb0ac17c52f8cb75351676fadc80ac6fea5b4248571d64ca3905e8084add60ae061189d9c7ada1cf33016e265f15173c517fa59ac4d37534705602380114c45ad44ddd72298277839d810fb20cb0dfeb59387da538f545db650496428b50e101bb31c256e7b9afdcc0a92d456f5bce0b99d713a8a3f7d60ed37712c4d295f83f718d99bc1899f01bd83d3c1a538570e02e8c6b3bfa759bb9d858bf63307f7d9e4e011e3739732d82ebd2581cde52a3a148619e44c344cfe4694b8a09218cae73eaea8481735390e84a64dc4d41876ed15b4f04bedc119106d24d1848034b95bc19a38dec3584f2b60ab604946947eec19e50ab714a44458a493bf901b34214cac1aea715f2f1393bd74884855a62c5aa5989e62da920bbbaa2f4cac989532e8b9b89485053843bb915de86d252611d1d6159a18805d78f8a7f0c6f8509c448005e20a9f00315dd0bb2ab26be5bd6687bcadc64b36f034c8105c324b58b988642054604feb55551e4ef4d4ec9957458975c4c72ee20f73eaa35bc2717553c10f59a202fb55ba88fbc20fbf8fbb6d1e0571f5c00c1593e93dafeece399f91fd97a7f13193c95a6f6ac82474763880104118b2397a74716acdc18d230a08a140aeaf07e7c4022d3b00f9989a74ac41c75ad68811fe6d88740eb43cc4d16492c138b6763739029351eefcbfaec33ad19ad70c590171dd13efbcbbaa37c6d94059d8a8eac0bfa27a01b76e3cbc3a6465d8182ba47f01fa319c922ada734e3080b46e2c0426e3c728515127abad3d5fb809edfabed30f0fd756b94c284ebb15b7e0715e233b50a0b9b7d803a050216fa40ee110340319ec6d2014f26ed444c792d96e67442ff9010c15b51bc8e0c882ecb42d90150cd31dc9fade2124f3900748b473fd2d472a8a04460e80f64579ca67e284660f865bc9db4cce9ff88a2981f9986d7f80b4f7ea4c7b8ca4d44954130e135694e155ae14a82f113bf9db148005bc75d8bc7c81a4b0d256080f86143c8c42e820d082c6178de451aa386a13084c85b4b7a72652a0a0761d2e323c41ae1e34c95c7c0f288df26375706cc38e7921d1125fe83aa82343b8b39425315f8dda4953aa9e2d5770b1c853f02274e2d2595588c40c5756184b0ebbf08226af95d10e43817813af912291f8fc4e9c63d835867030abc49193fb7649d146e17882cb1bcf441d45e4893b981fbb0d67fdbf007144b93611233ffc91bc37ac6bddec580f344b9db3c000136174ee80144bce144a42f3306d04c0e89ee5fdb555ee539bbafa8ae5e9eae067f4d422729d7544d133786b9db42c03b7c88a98f1ed39d9aaf46a94c97405d03441b5e23c9ae4e0b341840c2a628a4494052333e74572febeac653825e94ba12a12039c4f6b69925f120329d12731d37cf6a2be9bf0f28eeebd960d43a01590b168b264d366e7a262e00a5ef95765b805ae7da5bfe741dd9c69bca20ec0a0b3c646f5defe6df9b4fd10a1592eba0b7cea4a0f7bb60a7042a42fcb926de070d69fe1222aad62b391ed2bf9eabf4fc2456b11d2b822053aa40a59146c07df587b0fd83502cff0f20c184340ac0bfaf14bc97b7945f4f3dc30753ddf0418bbbb103e57fbb0f4b27238adfd6139a232eda786e8b5dd1a421e690d49870155205d28bcc99703a874afbdeb28566b66cc3921189780e977f5e9ec32ac5c777daa806aa56f99b22f1d5e0838e8ac1c3a2d1c8eff5d99e4c25dd3bcead8f00bd6cd5f0e56f2e7797f94d5efb4fe7029771f4d3f267a858db03c823ae985be3662b8d364094506d34804c9b9c93a9bb4d27a1ff252ca1e66e028d30b0d8d365f2e5610834f2a78c4d3a035f467427399ca6bbcaf008433be52c97bc1282ab26ca313a00d73186f61e9cdec1c1f25f2024d3c21424534fdce8959567d27edd4394376cf594c6c36df27a371ad2835c163d8dbe27c44020175b5e0f737b037112039ec0053dcca84ab41a5dbe921b77a0aef5061ca140c33c27296040f907ca5af35cbadfbd74efdb0470ba389228df575dacedda861208d100a1463ff111348ea252490e7cfc51ace3e3dc035ffe59a379bf89ea0cbffbe3c7d5c74e294555da8d117f35c5cdea201606c45cb7b4cc71e46d90316929d0f4ab6025d1eb246714eb412897504a4a2ac871c91bb63410c05fee79baa6bba8c3bb01f229cc2e7e6a045732f75bcd88805e30ccccac9859c95dd95a1b04f60b2150eba1484a0ff17c06c62689d4bfc83cf8a144ff0f668632c0933191b73368dcf0d338ff63bfe18eb5b8f0c84103be51d4cdd3549592ca096b65260c1a83628b988cb5a16fb563526a7a76ad80a1179fa79e91cc9081c2844781c7e46fd7d0d7d158d7b33da72857d6dd9ef1644299feeeb10e75bbf0f8c17d01c5bdc5183c90bca570a3e24f6dac9166f4a59b211990150c9693e09a9ca88227f34adc1ac4fdf0d9574e0bef149b5a8194716e61d97b10ca59a0183ddb0f722d4c50be0931c0ed4930a31062d3c414553495ebea859268d74fef503cfdd3ddf57fbf32261b8b3f8a196cee8e84c4c3e4da9abbd7c57eb790411a15bc71ee0dd4c00c66eac888a2dc6a41f95a47d9999fb3f5475f86b9f5ae8b7bc597f4a4cadb83696de01631128f82146980c2702510a889271862c27fa75b4e4df2c0a89c6d97bf3cf8e04c49ff0eb39081a119b912fd055341068d7d9a6b4abd74c6501cdbd008a91ae924a322feedfd83815c93f9851e05f36374c5fe024c1e5f70b8b2fe0530e160fa1bacff19a9e0e0dc9eabbc9a949881b13fd4ebaecea84d7f933696b202bdbaff0782dc840d0243a3090d1e0956b4e7fdcbca4b7b1ad1cdae682df7b7101b431c75904e6f0a082b1c4564dcfe08503c4688b26b94da1a987a0411e0ccd64ee0b2373d40d9ef2943eda7a92601174d03d7ee557ed47281f827088eb0754a35ef54722dbe47ee4d4515fba3f549f7542cd3a1a9efbc59dc9d32e29d9c7dafa67b5a8a80bc6bc6ddf33dff1c890b5b1f85632f545bae44b0c8f83df30ba1ba03bd9697c2088a641a836a26fdbfab0f069806dee82b1017781db51c56ae88bf1bf60b2469b3c56f2f49bd4a8d1778e7397ae8b785b09613125e54ab4476a5696f2d535fa5661d21e9265b85181633b2396c028b0b9f6eb48d3577151b29ea439cc65317aae0b80771e12e3ea392d726a458745505b2d5f0c8c1abcc406341d2fa8434ebae6c00f64811d23508b4ab3f2ee87deb83971b3add8183b1b5d8a5581be78935801fe324b397d0706889493a9740fe2584b510aac6edc16315b8e085cd93800d14906a043780f8a39b6011a0f3e0493cbf96a87b662dbae66c3429eac4b79f2f99829d28c3627a582700edf8492d6e54635d89696a78834a5e704cfd381e493089b8e9eb3f0ef1bf27916ac6baafd9182705c39ea86ba8c887810bf300069b936fad85abf92f07e28231aba489edc41d316c9db6666ab7ad17dc1fe931d8dec258683b6ae4e2f27e3005b7200b59406837240fd0fd19338e8cc41a40322605e235781b933c5abe1849164576e17a4b8c3478803770dca9b8166a57d7e9000bd33e05d5ed068046c19721a1e40b6d3a2bcc3a51b43e2b11df6e9ca48cd8f44ec20a5023ac2ecc56c621dd83455c1687aab86f1bcc379560931e023851d1ebc57dab56f568f12976327918b7311abb5ed471e31f080140ce4900ab56fb76c163169e5aa7d072fd2dcd1899804a72599a229e8714e10b1b629a0c6ad802ef3cfc5c16912419f12ed9ac4a22e0beadf06e4e33d9883e3e62fc0f24f90e499bb9e6b6000006ee4a798225cd28a85f60f208fb976bffefce832e2bd244e695b0c3e4e2a31d4ff1cca9dd676cf3f7ad1beee17761271acaff11e895f18576496e9f10e036a6a8ab1b048ccdc2243a45cb13ae6b937c120abc0b25bc8ea5df13b3e3c2f62dbf54e797d75cd7ae5dc96000c9a3aebc8aa6d5231803583144cd457bd90f44d7f1ab69029596521e059ee6c74e17baf972f129fc36ae6f57ec96b00bf087c34046c3c7d63557f85e697877af5d6363016b6de017baf190566aad4fca157a11eb3772fcc2a3530cd691eca72a858fee96e6974aa7683f3e3147f0b70d293ee050f4197bd7aec0bb5f06bf83ace68fad3b57ae01304d78e582698b7cdc98a782820f7690f4a332a2683f4ab03956f5a2d4aa56689d21231539341c61b8a0d60173b24f1714e9c1ffff543bdc32b389dcb5d4f23853d7a765b4bbfe7cbc1f147f04bbae96ea946ae950ec9630ada008105ddf520bb62df0b1746104206f6437a5c8a61747b20cc140fac23af62547b05363e1957f8bab941e1a3bde331b62dfc2d96114f0782b9a201c4af95f4ae8d32a4d5a1d487d83b32ada223a9cb0545edc65ca522852f059fecc558ac19e322b069435ca0009ebfea87184fdb99df62d699a61a4aebd5745b17775528c8a5d33ca5473e05e908396bca5c34912ad3b1b1fea5bdf297474588b8823cf7cb28c0b4b0fc48108eb2ff1cdbe247167b21b284842dbab6833415e920533e85badd0b3f43bb7216e9440e6752c48dc5851b89e8878144da337bb80658d84d353b7ed48e09c73f71001c775c4cd6ea10c67798c4925a9470d47e15d88222745be3c325760882b6098b85db713a522eaab75f6fa28aa5dea4ae13978ee5db7a68c4603e2202c8266ab58c7061abddafb35a1361f0acdd101f49a1b63be11d25926c0f162e62aa7cacb72a7e8a0de081e05f60687ad517db97c2e7f478b39bf3a85684531c0a6bd1cf89686f448929106d74f7d88ba0a00cf77c107ff34959ff84459c2393413fb8a3e713542c5f82390c58b20cda9ccc74795572c11c0cdbcf94aa473922349d65610e14e4a60435b011f77d062cb0a0a8d8a407060b0106284e1aa55d9fbd28a09df8a2a279acf800ee0395e35171534971538402a68cbc6f6f6fe4ff4410e7baa0e9a8d0cdf87777c1eceb5fce1b01055c756a27d38965566dd5050675ef0ea83006d99adcac40148297de9c307352dd358b9fc0ff98a3e70090fa270c1896285cbfd0c5b5af7f0b0c4ab6ba8195778611440170a5ab0ff4f37ca2bddbecb61accdb6d02eb91aca28c09cdef58177923db41b1166800f11524bd6fdfee2a6d805e1a9ec2704922cf909841c7c7c8b7f98517df0d0a92894be28a0ded4cdb12d34d85bf48b8168e209d8ca815cf9796e02321cc61ef90fe49022347d1c8b77982478478491279791a4b927952a8360ef258f5d86a6a8bc519265e60e514e06f3be3e95557d37945ad54e9cb640447288439ec32b7d71afaeecc48b2fd5326d9a29a07842ae2c31a220e019d1b9e91b86ec87b87370bab66cc096b62b45ff4df91b375b501e5cfada2deba21aea1888211f60ee6b60d13ede266c2395e80f4a315b014d363391e85295bd129af669d31ed2f308404b37844d85bdb155802ecfaa0fecd7e22c65d57ba99ae627b568ac87f41c84cc3535aa8b86285b8c6bf75c5a66504216d1f974925108ed1cee8f9c72c9dfe32d136b785bd258382150108027e18c0ccf2c8edc7dd876b5a08604389ebb4e56240c999276841945daddc9338e56d74d425d4944b282917dfed748a46fd142056f0e8267988215f3f0aae05b9b315ec223be829bd55b1eb279c61df5aa1fdb2a495a501371dab26e7d950814f2ceb25c0b277a6bf0defdbe2049e51cb393aa8fda160b8688c05c84b654d492804774524328416f7963721c4d0aca8066124ff7a193f3589b3646cd4265ab98984dc82f98b458213dc0e3a7d409582a40a388065b249f859597caf8dbca25385f02f8e4cd17cc50191483b52b49380a520dcbcb8f6de872866aaf7d83ea88e618a5d4322383bb9519f2da84150ba5205d5d579173919d49dc833724ec666cfd8a95164e113e81bc8ce52fd0e42fb9e2cf0de0b446e64bdb05c54619fb0583c129f3fb8e62e64b0b22b728f2b6640fafdcc216f4018247fa9e0f948d324b24ed594cd4e6a1897817c85649b2d390bcce0ae7c12b0d6618d90bbeaef823164ba280fa1c1129e066d82a7d03daa53278c3cdb361bffbd9c294ef80c5010fcae9869b4e832f7c31a5bbd278150f367ed4d3430660f98ebc37d56253bc15f607f0aa1b979646716c553bf4265ca1ce245c5ec55986370d6d11587029decdb48d081a6164349ed46a17fe0f0a8cfab563fde665962af64ddb9d75c8fd0c8d77a207237da3fc863ab0c2815dad16c03b1d49507f08137426463f67617bb497715689eac4557e9fc7aeecd521e197e32925342b25a35a0d5671c57b82b10f53856d3f1a39c2dadbba8a2464ba569fba8147f647610e66bb7172ec2401899e3093a74922c5af797665f2378b506f2eba5cb27ca0f3a5252bb862aaad4a1adab32db9a1cc5f23a9a798d32d8c306b69c71179385635b81baabaaf70568429a11493361a57ca1c1c07b85474b88492085a7c1291c3e342d677e78ff847e6aab2fe81ca194a750e6b7e5b0558468d3793ca6b5fff8b5602497719464f4f9816209191d2d62563c89daf9ad222e648b1ed829784d2fac5e6386f56f78412ecb9a0cffa7b0c8a38833a6c9fdd74d12abc6a3149449a5845229eb8c4a35951756bd1558198422011c74c0cefc4d52fecfcd5d7af5664bcf0f9f8d5bd96ec9641aa4e18ee4d1ef691b6206bc9eb1ac091e3983500531b2bbaf6958fec9280fd027cca2468a728ea2735f8b701914831e28ff2c4f8c30d2aff704afec9d0b2c6a3e47b399f126fdb7fa9d288d381d0bfc2d872fe650c19c6f993e23a34a079fcab365f87a5687b9865acf419e9a840e952c75c92689192d76892614f1cbf89e21f8690de5a251e868c2df9aac358ff43a280b391d387afbe6cae36d4a0be27fac9cfaa0d3b3f71bd626ec025e9440c90e9afbe5b022ea67869a1f705250cc68352cff0b51079268b0fdf499332e3c0950f9e211da9a1ec567716f83949e5d8b9f6eb4d550cd84fda4cfa9d948a0223faf681547043172c795856028e71576510f94085c832f699516818164518583acbe982471ea8454c12ff9a41f5fd06919bab16659aed7330a4275a7dae488fe597e070e6a97c42f2217909345c2e2467c112d47c34294dcf12add17c59a3fdb148b0a6f9eff5b61255526267b4014d65eb0f59bebc90c4f599b4b99a8dea36b7dc92deeadbfe30984a654b129dbaecf984126e3f3355aae277577ed4367a580c24539790f44b050f9bbf887649fd7b278940498b83c23af65badae5f4216574999a14d6506663d3ac491088a28f051deb70150f57bd9203adcaab1d05d5a0953acfab753608a75553b47f5dba9b0c957d43aa755ead52f3a8db88e5eb9b5d21ecb566505d5d3a2172b089835f346c6da640335b6556f57a5ab54b88530cb3872661a68db2b1a7482fb6201b8d08d2b6f256d2375729bc85114c81b1bfc5a1d8fc19861fa238693fa6d89547985dd0be3fa20870fd2e93270b6d3624d2cf5e5d12b8c5f9dcec404cdacd35c15c9043270ae36ec4e537b87c5a731931f0332eb45c97caf24f522ed639a5f8ba5bb34bb00cac47884615d9df759bbe3c9ccfb53d56c162af0c7d975912c4b7954d194fa061a905250714a9ac6f2a7e88022884b86ceb1cb5a54cebd8897d9e176b22522245b014f6922d0dda1706d7eb3bc1393974b07c444b4c68d82bc83180c2f50c19a1fd2414f1b687e04b07d7a19a79ff628e9ffccd79ed7309911548769041827a81f1c8fd483fdb9355b0496c83346dda478e4f921c531b911e27f9609ae567bf853f6ecfe9eabc0c5d83d078aa9e883f37764653f73f2f20ff8e9779a71fc72dee566a090ec6a45c56877a72e14a5fbb98aeb14a12b1b3addf1523bcc4417a60748166f387205b51cb380531a2685087f28c62c43fd5785d8e101a02e38f400be83590c136426b74b8fcda22ee4900f0521621dd5e8d67a58772d3cf6e794f4a99886aebe5d34d459fa9f84383235d2030c4cd2d0a02df7a6d362a30befc3a0b64beffad96991f5dd2a359214f68e248938579ebafca172331adc41895aaa8c7ac174221097095f86cb52031b84e5df97bf16dc9e69aa0fa21cec574c3e7951f4e00fe99f24c98a52d4aec374d4074b8c95abb29c34f18873f301f14578fd6b2a33b0ab846774a1a78eb57b0263d71476754155a0914181d7403bffe283732d558844d4fcab70685c28f9939a0be91e1d420f7061e64b17861098d4e375360b9ce26c6cfd438621b5e07eaab653bf73ee3df87271072cacd2eced6f781642812e0078accfa440175becf48ad36a3a5eb48b72f41d6af0ce903b4350c67b19e4ea875149ecade66b652d89bffa4e10e0028b0904a91a8804c73799fe95848128bd2143c3921385a7f022a2c92c62a59a401c009420f1d30bfcac03661f021cd32a7ad4ff4cceb7a91ee5a79e252b986500f7a9f540e9ad81d4a0791b4abb8203e39d78462954c3883dd18ff6ac4380a3d4d373418b0975449a184db3eb8e6a2d62054f7c9886e21150548bb7fe1237e50aeee14db733b3002696e918c8505252480567631ab9916f5358216d7b8f0389fa41aa564cc970dc4308ce6cfc42a62e7f2399567f9a37363df688cc33c8046ec8f20a206e2b977f2e632d5bd05665d904a46b281f5ebf1c9c247de5e0142f3e20b3cbeefc173135b1a8410d23cb423f9b0281ec13ca34aae91186c0850ac85826354d08490fdcc5bb8e6c9cbc38fc3dc1afcf2ede9eb0381230b37c56f2f0fb07dabc0ee7650b2003182afa659374c704fb56e6ad549f2aa16d0f1d8a1a0655e60cc78c06d64fbf19fa4079e643ac74b0c03737f8a309072d0fa1e4e55a71e8d943884615838a71aed57e060f42452215cf4297c45b1c72ba3b4c706996c33da6dfd9e523ea72e7d4b4cf0bb5eea5f2de5cabbe6de8b90d28c42a8bb5f73da46cefcf430b59f2efdeb5f9f850e356e4b1a38529c7f71c232155c21072d1170512765b8dada35ea11e066c1cd646cc1e8f5b28a53bb066a7f7a7aa71847cb2afed0955bb50a1d05f57209b6df5430ecddd26abb70a0f54e8521962f3d021563a76cdaa8dcb27b4139142ac4086fce90ba8c24b344b027b59eb42695807e4b676953f9b9e7047bf9b81497b8773d0e0b48b863985aba7f2617e5524d9993a65b7af9e8aa44c769b79a6f9d6b1cb317abfc59d6a727024680a13e8e24e29d8395c8a6f82a217a360ce15f0cae4f20baaa25b24080811164cce3222f5803d52c8cb894a325d83804221853fc9327f3c37ac11f14b2436a92d63602a0c9e83752332159a28afea4866e295ea1c450fe56a85ea8c63a15f19ced3b9c828b0a808c69060ff8c5c194d4b0fc5690e53a46e2c3dba030fd0f20214155a6ed747a12ca8a352efbd574de1fbda089015d09147232559423b6943811f59d3e5a807e33fd38d5794e1e965876781370093639f0bbfb574684edb9d5f2d1ddef46a6a8db8da94f2a75afe6b4aea2e15f428708558eb45ddc22688b51a179107602803723dacdf67700404ee565f3148a8326da4c668fe1dc178101878c96b2c64414d73f361e719954bec5b0d6ab2a41bd17a03ac9b2f2d7a4145222fe2c3a5a88a221e1370757107016ce08401f44c60c9af64d9e39dc3b9f143fa55598b3c1f1f8f9c5087481b6ca2b8f7624f326aeb0e07802672391141f9100d7d552268c157c9b2f3449162ddb97b166b6bbe8f545e44049e3e19b6320dc0f6e83f42d6dee2fabd4a256f3fa2b16f128dcab8791f4398688264ca082cdf20eaba10a992c9c0041115d8c27e62f00da5511be3f5a2614566c0fa7b38421570ae492b17e04cb85c10c95114c68047e865b6cbe71bbd6381300ed41f557f7bf5a8f69bf4215e8af3cbfff67377f68d5f4f5fe649d45633840af2a1f7aaef3bbae7e7643b0bc2b8ddae5c710be8576139985a3edffce88707a6322fa14a52dad6df0088bd8ebbfa23086e4d52451f966a3b19a5f992fc538689d2e5f1d3c7bacf5820ebd590ff56651f44a84723d7ac1d069dab3e920b463dd47d2fb0c9e507deda802200788ba99a38ac928e8301392586401ee84d20c63834e20e41189f95465ac6858d6411a99240346f8e8fb1a2e42c00aac9b101eea5011de7b82c129d9b6556a4b0947375f77507e633df7cb589767bdc6a6323a1ce60fc5e081c1f23ef59e452c06bcdacf41c3a3ffd4398e6254f544d16840698edd2fd55f9cdb066041a533a4e42c2d2a0b22d9f3dcd6dd8a6efa0382cf31cfa43086207a8bd3ef0c7c3d8ab48c911b25e7ec0e8ed7e2f5a623509141c542d4ec9ac73c7c69b7aa0081b432d6a0c7080c43f3fd884888daa1493c306829062b649abfe9b07400ed4eaceef2ceb632290b4ea90c0285e799ea7b46845cb419b2d64b9463c1f91a5c141559c54982bf3cb6c620134a7d628ed3b282d943a3545f1dd9042d2f239d70078b61bf2799b29a8ce9db69d8f0d749deba1f87e60c2811f8436d2e295171c96326ead0c58407d753d8f80d9f6c2f2b02d74d2e67def26ad6cc1fc00ec6c8eed51bc5939e4d7e54612f97c9e9731ab7826d3dd3674592df2460a395a1745d6a9b09cb0b074f4023e419abf993745460660a55734c3f4929237f9e300707ece2511ea23f1e26b7a5e68726832cb40b9e497e107cc4452e5ad91fd6d2d60fee339043f0b6d29381ac4e5b6e126b8dacff4968ee060c1ecdb6ab6ca2b80e8a7fbb7a42db8060050cf7ac321e79c89495ea0a42b5aaed98999ceca2f4256d5c8dbde1a4cc91841d34f284c6c21d8597c4808273efb4f7dffa8a4dfae914a8e5f411bbe69bc083525c38cc32c2d0c708ca611118033c2e6b28c5d895138050000726c5a5f12358ddfc82a00818b2da248b2bd9f278db22730446f63ceac40d0f4923ae54a04249c828f180538e4ad0b421d6c0178ccd3311659781523642bfb2c9eb8003cf1cbc82d4183aeb04d8b2c296a7e97f40a6119cbb482f6263cc81959c9e0314ebc787caac283ce7daf3683079b7f23bbaed1b01c33247585e160c5e321c5bdaab94ed516cb3f14232147dc82a973824c10de2914c433c0349262e0c07fa4460881ab053ec22baf3edbefb7024857a96d389309bf5f2d6108d8c93d131c542009da9468a88f66b400d15a08f1c361bf9ce019fbfcf2cefb04e6782221003922c00986bfdfa01d9cd4c326859bb9431c59e14c9f119a70e004ac8e06f76f3ae4f6c76e8092c2211719d7a4acb9b1a93032f96c99dbb8665594f50936a74c38e5681bf83855c2ff78436d41529c44f4d413ea059486db65523759436c089c0da61b5e2d5130a8afe0e97e307434dffa621c93e462c75c656b2115dc65186987d81dd7b1a9867af9e5f29f90bf9856c2a3827a6be1d415ef37988750044e9fe974069e120f46dbc3970c97f11bf13bd6ccdda4f933c95d2b2a5341484214e5d233cc8edb10cc11a0f5476763e30db1897cfcc7c8e091a0d0ab7d32018c798248c485a26da0bddd99d85194a3fecab628de5fdce8e543f28a17d6e188dbbb3e259f8eda4419f6e43119ef0f9ee974f2d46ae4c47cbfdd09162af4da46b0fa1ee72833ebbc184714cbcbaac4a244a7e4bae666a09ba064f5ef40d6c15ecd6aa92615c5e725983b60e304cd4e882a59d905e06a9d2ccaf9838de35c1737b9e2f675518d88d5ab1c7982a962a22d72ca361b4a70201ba01f8cb01281c9d06fe3ca664074b71ab33c632f7385fbb8c677182ab759c070cdd3c7fc1b8decb5ba8bb96c46a290535aa4192a6fc4b4a9b4374833d5c57e56ca6a972a035f88efe7864af57957437baaa914584d1e3e769452f025d0309b04f2c9db2eaef7e056b2c1aacb31e6c0eb3fbb4645e718ed9e4ae6dba828005d4ffcb89b08111952c8309c275878e94bf8f0c4c0ff42b80072c58ae85b2ac7f2210b311350a3f95935e3870c112131d4f169382130bd17610fbc3c55c2a444ea8f1d0ed3161cf1deee533314fcf05053fedc7d4d0ae771f84e436597616f8729e2f3a5867aa90e4b1bb36ccf311d4733ec3e8d9d00f85c69963afc5f6fc03e2bc5eddf5178da7fdd57cfc03d250d91baee927e0760d292012fb7f193ccfa8ab233e53a87e6f595400168ddbf03c1dfc7d745f4d46ecbbb83e7dcb48153a8fe236fc090079c1f8fb0a7661ca9e7adb2e044c4082a27740740a34047ec7a8ba3cc0d76746f181d9982fba44f4c22c66c11e203936232ff82dce0a1250c917768591d2d820fc7c577460cc325b41dcb20cb4bd193db6fdb6287d58b02ebb65b021387953e874e8fa941c80ddf14e16dfbea6dbf771b70d0db3e8d15571d809080408424f1ab25b209887e44192710f887e1d2c6b07d8c99ddac590e2a72166f0bdde430b0363b7cb0fb8db00a1e497fc46cdff2429cce901829ffd93d7f82f8c74af5cb0508fd6ae832157bdbde2939d1a600cde106a4f96d10895404623d0ad115c5fa5316bdf828d316e5c6da92754446b5b106cec67ae7bb0013304236424baf11eabeedc15f118af649033d0be4af981d0e743d522656c003046e849d75e8e170c16a4903883eb4c4dd79a1953ea14204ef620bd7381a554d8195f35252467cedfbcde722b279addc469d0970f4087ec858333bbe1164dc90a0a509a6b03e142fc6020af852fd35d89adecdf502d11c214a4c8096acd913fcbc896567bd13d8e7b5ceb76e9bd826caa1cc8c3cae40f38037265ec5977638b09f623dfdb68d10960a9c7748c77f988bb81ab454ba31fa3fe0724c6c685f2bc227a4091e63ac7e7ab2408b271880b3051d3a966f9421ce265b49d2f20e24bf3e0f290e6fef0f8b473129ee58edf8f3bbe83037b5a61ff897068d94201d62e56289d29a15dccec8fe9e62989480899c47a5c8111c65383a0281f1e07f29a20f89a10bda2366904d7ccda8685918170737e2fcade104fcaae2c5929e1b13ff1a71222892e3279f3564042e78ecd8b3b5827d5a7272836b65e4701fb4b89a8a4748cb78562129b25503448235aa4f018a5819434c3b993126bdfb2432abfbf8205fe95d31153e1c9eae4b90839bbb4bd04623cb3871a1bd92d863086a92aca757cf42632c8b3b9aed793b8751a22a3193ec1c7d886a770329305f5b1f6cdfd193905670594ba69bf35e8abc8924144a40df2883b6be3a8e9fbb4d4068639e4a78eea5d4ee826b11278bcfa6d32ba6747ec52f166ef4ab608ae39b7e210735c1b25d18920219d9b194c935be0489fd118de5103944d1c8ed17cc9ce8d7161dfa5c3b2838d479fe4a9cc4a4796b01653ee303cc649ec83a03c60554a0f51d155267109bf48496e1cecf34765e5b9e88939b6f2eb7aa3a427cf416c47dcdcc872bf9114b6e9c7cdb438ed6baa2aa7ef4387137a805bd2520b62fd1e209e0f8497c3cfdc99380c97cebab7f5a13fddff8b65047972bc341cf3188dff55713aaff22346c30ba6e807d7e2caa41730fabd32f1b94ac584fa31926298a7a8c2cb10c646727505bcea9da9d4f0afb091bc1819ce1ae6fc348a63b459cb560e4cd9ac2029e6097d72fafc3cd625eaf2bbdd89c1a1e32a354e90857345c0e11b8deb3be82e4052fa814afed96e56003a0439663a8cac1d821aeaf3a918acdb877cb41f2de5131d1dccb1e1555b1fcf0305ad07917d0517903c4d2fd44078570d161eef0ee074f5a2bf6c9ea03a9def823b9c488d6501ba5e692e68690f7129672c0fc3056d5f8aca317e8e2ff146a1dc1e82b75d9a1aca0c1577e5e7288157781f25752fbca2c056684c2f5fa848beaa6cca3f6cf32f46b0882bb09dbe72f5fe09704ab7c5b7a8a791c36829fd674acb74a5d81f903072f1697f6198503ffc24ca8d4b62af2dba648cebc479eabccddce0958bc82cc780b878501fb5cb6ff9bfbbc5790057fcbb6e3734861133d1932f204c107d217777f289766de21e2785d2bb84a003b9cb8945536384e1152b3c0dff730871602023f1002eb0883d886f537f1484f975a34d543de2f56464deeba9b96dd1c111a9b58cb82b77465811b58595885110119d70cb7bb66f8ce15616c2d00a116f697082849d003a8f4fbbe88708fb68df95f2c2f860b6cf4fee837cf9ecd9e6787fde7bd1e110b60cac5da7ca4fcb808450c27fc03b9ac07f0652367c4be83e605cf8d105c874f4d786f0cde37ec70c235c771e17d89d1c6cbf9474145a7140858450a70f5bdae43f69789edff158e6af81d46428b10e799820e9fcb21a119fd284201f998f8f640eaf95319e27077e1a71e8d613bd5bf597e6f4d3fb900eddf8351bb2c61e50d28759b8b0e1690fbbfd070d2b05861e0a343a6212302dd84db192f79504a4c63ed9f75e3a6d90bb53bd0fd3f2833779e5d7438ccd001baabd4bfc4afbfdcecfccb6692150d4f90dcc0fbab7c20b6d1f61f70b962fa848eeeee7273851f0894da8408c3724205baf0833c6067676b2d65046041a7e8d021cb22c08d4d08facf9dc48d7debfce494ae895234f37d3db6678552c20c2e5e8740cac0daa123c692fbfd72852b83a9f37db668818026fa87b215523dcb32cdaaa9f4b14ae08026889d8323b3c90660c0175dbd1641f3200e7e1b458fe921c1399fe215c528ca40cd26f4552dd4e96c7df30d29dac42ce7232bedff8627103e478931ff10dd182dc034ac8a56aa9e1a24d28a18180ecf10986d566a91e37b9c3a70ea2ded378499d80f6049336197d4a01cef65ec0312f7e19fc1870fa074b979a5ef0acb4db1e65540df4baa53c521336d2074a1d67c8450de282298e4ff2c0336a43b5e61b117b0904efd79219157a8bdcc7b446579752b29a13d1ca800415d6504a7f353df3a17ce0334909e216d6e4a77b4b5bab5e7c4c5127831a449e11e294af1076f3e0fc3ec3b232da8b131f26ea3a1a0991c784e86a5cd9331eea970b34a61f883ebf88d26f0a3d0e8475e661ab0ad775a21b0dc2466157f780694bb7421501bc2b451e895b756fd4f586ec43a9f9ad8f3ae2c5350df03cbccaa0acb8877f2a07d05043b440a3d4039e3612de27f32b950385d1ebe9a0899c6474360851875e89108ae0566536b7a2da7d1e904d2bdc8f67ca2ad4bf29dde88fcbe6b0f64257169f10b55d29d1fd18acbc5935ef9a567d35600eb6154e8b0df6fed195882a573caaf64af90555cea95915bcee7414042edd4d517c31cebc95d0bd028a1f0316604ba0f3691e227a2c0a138c739c9f1f127a05952d5f793ff32c84fc2e43e3507ffb058b10bc61d5716365d588aede4a6263b3617318d1491964c68a03f03e2dff40732a0c6b87e7168fbd07db19e2204053c4ab14015b19953398ae441a84458eb658c1c64a2197c3f3cdc649dc44162aa64788e780da6df91124502ed61706344a746b9762cc2011c28dca9a36c17e5665770fd2b78ae58f32b7b540e63b017ced77bc8c4b0b13d3c2031df4cc92c3a6391afc0a2c0c9c9befdff947f3bddd424e56a0c1b6f1c8bb1350416a96ecab171101c8671d4524b05f08960a6389c1ae281dead4ff0a1d5afab5f487087028f1950feccc4fc21153195cf300ecf24af370b42fb8d45b44874b02c7b3b5f0039debb4cb218c6dbb733b4b3007e450837a40686ec2b7ef17cff0d4e50e693ff84c2ce917c1162cd375b8e6441d3befbfe93808e62dda7bbd163478e18e750cf57f20029f6e88de2d1f2d256143dabb2e5f55a65256086a3c16cb21e3b3d520602dd55ccfca51d9b66bba3dc5055356c4b8783506aa4551a8531f99873c8192815a72549be032a2b1b4a924b866fa0a4317732811d57b024c580a37ef4515c5f1e25307b0cadbcf776be1116df50bb9bedb988e7cd31840570b716e44f1e7a9f80a6c92821ad734161dfd55118c976c9ccbf281cc824108b3eb48b11eae7078eae31f4195a1212ed9a111c1e503a9ddb2c1a2902e4996060b74bbba680b34d39044f047c73af4a47c50e6f4774dd28a8cd2208664d54cb6f5f6b6f643f549dd4076eb68e5a952c4212c57664b6777ce3cba24e5dcbb663cbed24bd6c727cb640efb29b20e9832d939007015745d17c0c2147214ad7222f1ac660a294a55151745545c9f6d51ebc62952c0e44ad730dd73e44ec45be143c037e6e7185b6407129ccd1cf2282b4e3ab75347f2bef6897fab24b61926c80ec3652b87ce8eebaab442d466e307b2b6664a9293943881bd348f10050023d4250931d41b13824fc551ef61b0f80ab097b160cab659bf7430fe17d8041c872b92b812df1d5fda2f8f8d303e4b03809b784e3e53f0f102bf224d51df3689043d9f9f3f567e0a4143c36d765f72489b17aedfb69578ae3a4d9b4c26c0a8ee77e42704f431ddcf95f92ed861807f4f71ab0b6d10b779a68d082c67ae8cdaf1d603df44b8d0e861de9d93040c60b7c039c5d4f2558649649ed3d541f4b1fc6cbe0e1e35b3c6558e92ffad0f1bee5b77f8776bccbbcbe34bf6a922bb4f5431f3fefe7a1d7600041ba542a08cdc5acc4ba12a6e4b7c5823f641af45e09274447d94c0d71beea10a6211e181d9901493cb6a1ae08bb506c1fe4a1faf41e293baf374e8d4dd87e7d3daade2a3138602b86a317a0311e4f3826bf2cb9e76e41f11d79fe3006790f69d95eacce5bf9704608399887d24d29da806873160a3f9df6a50bbef983f7dd8676c30fbfd8797e4df71f00b814234ec59d651414b30af8f89ed027dacc8c518a15f2921f8db2a35e8f28f72e6d4ccea7af2c8edb0e5df0fc45d0de688f193654c0549be408726fb767d2f79ba00584cc9aba16b7ead9c152b3b2eec72582ad6756593d576e1689f50150dfb1d58d16cc26db7dc3348e293121f842eea19dc20f88768271c0fcc18a78192fc1acc4f26ea4c17c498a0bc5fa99a1a116534432894575367c3a52012c474c9b09d67a0f9d0e2a7868aab254e2cb25f6bd932599432da822dc982582352bd1e0e0184e7b2386b50680f73c25a2d3dc797633ab6dd5c1c5758ca9a647c898682c88c908e013a686abfb761b14bfb4034fa022d08fce958b682b10c8b7e72ae0d3df9cd01240938c87bf3d6ca2be25be5a821f8f8c4d562d0807efb442acec2068e56cff42508d457a791539d1a3b0236f76b431e817159c7f98340659805fa30b2f2d23be316b9780ac2cc1f5af3983c983d3ce777ca4116e6c700bbbe6ae7f59ccc8f0a0c3b21df447a6ed942bfbc3547e39e89af3b2c33083b2f571ee7947ad848df5f80181f966252cca7781dfdeaea42ccf405eda804d1dc25f8dce3e6772ea2a375e3d01245a04aa105f9e59309ad9a8036d154b114b106eb1a97b12ef2231399a9348caa3963b4fd0ac14f3fc5047224ebb3492bae7e23e7bd7f5467fff79108663360a5fc6c84b329d874c7abb780abe8dc25e3284c71e0b1e10fb643791726f29654a32d209f609bc09b216a4c3f1bc1a55504a44ee40b8ab5145e581c1499ba39eac242d70ba6a078eb267a308cccd9594b9028f53c692bb065a0eb90e17db6fb97fe278a9fe0d67d439bf861b9e5cec30c74c7989544301327d2a4bf5e95b69023d0debfdea5ccdfe71ca9a4a6bcaa8c04e3381be2b0fefc32324657051eae0b2056ff6e6ecf15190861730fd9ac901fa34bc806f0742f943df73db1c71f473ad12d07bf573034b2c16bb210b97cb55ddd539cda9788de51be31b06a08295fb2a5f6f49c19ae97916101c83e4fa171c43d9e3f90f8c196b282494677823ec81a374f3444d1d737431358df4d2d4b6f94993cb92fd19d6e7c1440d618f393d354df4868fea77c825a7d2b2ace128e494e7c70220db801c80699d9f1bb280633159acba5cae1bb2e855afbc575ca73ad5368c72174ed99402ce5912f088b30e176bb2216e9aac17b94615784e6b310e85e64a9cab29cbdd3a5cec7e1ffd93ab81478f5011b89f94bbd61b62f6cfbc2901853fc8194a87862101a4e09c8f0b000879a360d2014cb2696ed04813a6819bb8417277efcc792d9b4e16192b3c92328944c23730be412219c1ebd99c3d67cfd93d27e98628a51594c6a801ce411243a1502894838e88ecef4d50ce524b111c65f93e830b7894b29913a4c9478f7464effeb1b7206956c86e3fb9990043f66f26fa493bd15240404a40969ae6f4b276caa41b377816a54c4b496ba552d6a7769a6690438831ab4f163ac35b023ceac84e8024740e57e36a5c8dab71357fcee6cfddfcbbd4901c5bbfe4c81f6663366742ca1881c79e31319bcd66dca9694612878edc3e9bd5f6acd074dadb896c18e5fe1a55b87bad3020059281204286b808c37d76846a5481bb6b75c14db342c2723149b796b8e80d8e72fc9032fe2f57e8989e6c6712b88619f56b7051ceb21039abf55f478dbf60e6c8110ba449760cb2bb62b0e13147b52d43c0fedd777845c8e94ab5f66905f2a37358a5fbacdc47bcfe12bf495a9d53058f38df70d185842117330c97e567470d6778c3456baded9cf6aac86c08c87247f6e2b23fd542d23c5648173b59cb0059ee4861257b54dd04417927365f93e6a2ff92aeebc2c9e466a54acd454fe2a24f96c8f225b9c64543e09b8b6c606042910d8d1b1ae14de8673ccc1741d5f822d324b2a1f136de46788343918d0d1be18d8c173d8d2f822a82f2af01da27704b71f1c5631ae0c380a1189dcdd0825a8b7148b482477afb3c0c2f7dbcd4c2c44b2e58583e9f170fe3fdc5bb8edc303fca40e3c7518d1f411b3fcac8317e3ecd73b45fc613c67b5ed36423acf1a2f182f1a85ea38edcbda7922f3f862e48ede7d8e5c57720fe06657e0147193b5eb8c0708101d22c3f2e5fe32e304a60c21f74a0745ed059f5fc8c2ad02b3535e30af80558539509585d20bd02022b0e0b58554666d3138eb555c351c4371c675f14f0489764ba44cee8c899fbfe34076df2cc70b43dc0410811218a2cd22478f59b3b2a058394f1f7a8a68986a147fe5e9370cda0e502560a563588ec5f6f78f4bc3c2f2f71210f3dd8cc430fd88997ea1529030689c3ff825b5019e4d15933ac80e7cfe802f60821659284a91a1e9de5514921458a9d29a4d01b934c6fd3e451518193e58e1454f2e8ac9d29a864674d13bd527176a890ed5011836d21491ee9cd4d14e50fdb0292ec4faf78a99ba0e71628b0dfb8e8b7efb7b74081476925f77b39c277c113b47fe7c9c5d66104feeedaefecedba2e033256c37dd7949cf1d30ccdfeb2658f033d4f418f114f8e8bdcdd41f7d9113a82dee44c02b27f4d35a00922a88868c20924720c90441249dcc00744702108940dbe13858de2e006f4e625f9b181fe0e9d27c5819cf1ac3c49a48c8ae54f6f206766e81142cadcf0c91e15165894c21e2164a9aec0082c2ab2bf4725230978a43755e9bed39b089c01b210015795cb006b8adee6c89fc6123c3a8bde2abd799e1fe96df4a876742a8f7fa5e0e9e4efcdcf02eed7e0a2d7c400e7a85284179a9420082d685004085cc0b9b5c080022c7650fe176c2939373ef28f9293715e2e3271b9c8c3478e71a8c65cc662b2b6fcd081949aaa2afffec870011ee96d9a6a623525ab39a918bdd1db8b0f400b523ef69deffbf01578fc28a5d44a39e33b6414018f9fff778023fbbf6769c545af554aeff91d8a2eb690509e5f5d5cac21dda1c7222d6385a5532778d24bd3eb6fd6b00273df3d49caccb077e82db20d69c7e0f39122bbb37a4aefb091d8c8a935aae8b057dd7d447637f77389479be2a27bf43d9b0576017612560c23f0f86965daedd39a261fb216feb492b05cecee295370fae54b96a84088cd02771417632ec6a2b8e8dd1deb1d0f54a30aeca2d680021e3fb04f142fd9ecff895939d2b5b6d2d2357ca4e6403f56be295e14cfc5cae7ef3475cd470ecb6e2d2b5f61a5921c59b2722d79b99c4489128b4d91d1a47869742b53bc34fa8d6664fcb4aae458f1d238c779a4c504892a309c9d28332954a2d8a864973b3548922b2b499733e5b3e4d3fab83e4c3e2f2f71397079fe3452ab1519155aad4a0e740a6b2746a54489c2c4f5729283e739bfd26f1b96641c9553fad9e10945f386a25985e2405d766ac0248759eed0e00ab93fb3cafc1fae2ad35565863f5c3d8576c59496302069242c8136a1a5c819da3d7dba605a23cfc7c02aca4422659e90a5290329fa5b1bc23e62e97fc0e6f93473d538fcfbc7b96a623ab159604f1e75c4c8bfe1e277f7fbf05a7a0f17fb270678d09eed9092d620658d945352a9e3434d73b30e39e3b6e5a24db26a9a8fc4d1efa022f2fcdc70f38c41093c5a16f861499909e620d9964d6297d8ce71d1df4df35a96bf65f5db56763fcdb26559d6472633c4d4028f9c14d95f76f2e5931efc69fa3147fe249228fe874218f74f93a344f56f7eb83198a174440ba02548824e0a35e2f14924eff00545cecc9067bad012f2133904d2d44da000d1b119f6ab09786c26729a0939d3d903135c406f91e90238fa5fb5f23aa148ae7150ca386d9ae9476bc531f40737299dfd4fbf079bc304000e7f9ac304a5e8997e7d29e330ff2f584ce63fcaeeee52c665c0008ffdead7ab5fd9fbe5a5717250f0a47c2b1f4b5311229038116536440fa2c031d1e084181550a0b302283329a57c59e32d4440c2122a22b4d080d27feac72e21ccf2cd027e40893ddf4fea3fb96e2e5bee8fc938ecb89264b9a3c41453963b4a54c9ef257147899d2c2a1125f7c7dc707cafbee78d40b2157395a71a8ef6bbb6167708488dd3f9367842dc001879d66a71b6b7d2e99f1d939bff46c0230d615c9421fab98532e52395704507aa27e8000c4f4001aadf234d0270b2e409267a000515b098d43f09b87ff608da2ce0fe9720db5e5be08da3fbb44d704c7f3e7db69c95c5bfc61b8491c79a71678f73ae2557c119b24d30e5dcb5e0591fcc7022cf39c30929433ec0fd330a5ab9af761efbd951dfbaad9d87e3767cb614b0672de338ae725dd7d95a2bf793fea4efb50d9ceb450b7874f9649fef1f37e2e25cad6cc366a8e4f318cb649ebf0002f624bb95391b0c7bb8f8d25b0ecab3b58434b56c8e5ccee890c1644d72900dc891b715596621e3d19d9a25ee4bdd930200c50063b73804cc60a3807ab2d4a734cc91c355ad56ab956ab95eb069eada1c794d5553d554b9a7a96b2ae81a0cba966a79cb5b1e228542a456ab837d36af613ac7945248391fa4913dcfc27a9e3aaee36a571382f1a80985a8e72dccc748eb22950d130ac96b05f6247bc85a8c4321717e689a1c15928564a1d0952c565043add734cd90b9dcaa96aa455be208f0f728a53332cf252edf41d2b40d240eff570a075ac8fedd8202eef7f1891cc07d7d1db8b0da399228c02d9701aa462a193ea1296bb55a304f149de2114bc552b11983359d52ca27238cade5d1a9d8951bb39b478c07f8466042f565e8869b87c41a6681c0427739f0b917a58c934623d934c0f48fc09462d60545361d0e25082185eabe08aa3f0f70940ded1ccd510c2c603b47610d0c06b3d42b1656621992ae6f97cbe5b9eb46062250373f2000c5fd0f0140d5bfe9250421c90f50373f745572505ca833ff878ea207a81aeab4cbd52f1a725026078583b95eb0980c16493407ae092893834229e7794d7a4d5a9d83598e8be27ac1626da178ae26d2343343eea6c04f40e1607246ce7002eef03a01df3c92dac5c15c742ec64571f143c3b021524605d2b483d4828371b069aa61c33cb9735c2e97cbe58ab95c9c0c744bc92db8da3f2aad431b17a5487ab6241cedc35a8c4321998f14ed42ad945692cbc7c2041e49d50526e6c6b49609343401a4e0a69476cbdca18c15c6186379049712d9a90d1260f76fb4a123f011d2d4b0397239a343ceb0402e1bfc9032139023ff9a142028db2bf0286dab297846d2563131b75ead564356ac966b369bdd66d3b4831cf96b6181988543a48c0c23f0e82b5f598b7128e42b5f75ae8b855a1d20c30c37fb652cc19fc7faa43ea94e5429aa12b2e765c8ce8563023a28d9134a69a528561d2b76c0a3861a1d1f3255c0a74c012b5004e6e1a2ff94d08bad3a59ab43ad843da9954e2965051d459233359fb2bf0c2d2d32f228764f7462278aa2288a1408558aff7f9b0516ddfc793903ca3e631c81c70aabb03a84fa84a4c9d138627286966a11c61a45ce4c4fd6ee96b26bb591c3bd9cf11a1773944eaf5a6b6a38fde9743a9d4ea75395754cd040ea1093fc3f3ba9bbbb3f5f0dd7252e253eaffb9eab0fd8f8e82165d7e5c82ce7286701b2011202d26479344d8c8dd998bd3e593c204b95136b105fd4c923168b8143401f362eb68f6a5226a6697290386a905288a28cc2a35d57051c8b3342d52a2bdd2a95ab542a15cccc9067dcc2e0886c83ecdf2a1aee7094b249644e3a67112244dce98d94f19737aa9c55371129e372c639ae7b761721d24466f79ce18dbdc959b16a54516b7873d32a95aa552a15c7f29e2882470d353a3e347d72a11749a71e353538c70496119707cf7900e51e6c9e200fe803a4610f17270f175dced11c59d10312045204d264e76848d3c4340e184d8218ae76dc14afc82e03067894b621369bad07576d8cb531b621ac19c0a4445be4c89123c7ec9e3946fa8db411d52a4957eea59673a3f188c5704ecbd42e67d24956ab20467fa965ff97dacb14e44cbf27059907cf00c85df8cdbe2528c11ccc09cc55d0b01c33ec28359e8045369115d1cd092c4ac75a4af544b930eba4f3249f9622b2896cd3d4b116d9b24ff1285efa66df142a3523b61c2b5e1a3dc977a5f54939f9a8bc34bed43e46609f23b1cfeaa355f96e1f9c4fce91ecff41d2b5c2bcd4475c7ca9f2527bb1bd5879b9e54073bf3bf1d2121793d2914aa9aaa9d862b84ff74e4771a0f96325168bc99638f152bb116476f1a0c92bf6032698e468da5dad7599181b4962031d49e3b1c6e17266be43a144f6c641f6ef969c9939b2a473ce3967addd72aa7234f8d15cfca6786c42f1cd5a6652c66f88b429e24725fc6652c63f6cd5376b93ef78ec9b7db38ff6d53edb37937db36f06930ab3b06121bbdfac0f73e4a03c1fc66681439d0f1346ce80ba1c239472392177c445a71d37a563d231991d93ecdfdd8b764cbac94de1681c15ae368e919c2396c977b069e2a670533ad7d8e158193bd7cb4bee444af6e7ae50c9d7765c27a59b75b29dacea8c7439dd112f49186b398ea3f5142fb54d828446a3d51640b928ceed644e4a76968b5c92ec73b288709821e7fd2a3b6704c80b2960239d029b72ab91336284cb39124423912727c49c819a20d44522679274eb0849c305d138fc67eccf6f91349c101287ff9c72c62504e32519481a2efc80cd9e69d21967e6beb2e45ae52c88a6e9648dc33f88dc94ca4b2b85c97ed3c92a15f5e6015d6e5cc4f1a19b75525cf418aef8f7cd1b524a4a2595524a49a9a4a1e8625349aba42fc09d6c9a3a9c0e67b68a66cadde0b4d9c96647c54bb35b19813161d245894d4a67b4344a1a122fad3a5697a46bc57438d9bf5b4dff0e678a8a498eac83c15446bc34c264da46aeec2431925d8a97665e9ad2d168c76456a566f39ec245e1605cccb91d2fc9bc44290d7fb8a474730e9122a4eb9098425d5228a5d425454af6beafbb296ddadd949e9a368c9cf1ecae299d944ef6d2834e96fd7df8113f178621e9e643678b61045ec5c2ccb3e23fa629877b8e999743ce80663fe4cc4c8691fd830cf1619a3afb554affd800ca39a0e0fe318797fdb343e400fbf775b07f431dbab773b44311165c61d540f52406452089401035d8020a5848f2031aa0fcbdfbb27ef73a707f4322967b22ddd79728afbf4ed4f66deadbefb7dcdf7412e4401175ff012488ff902fcb29673f66b3d90fdbf41b84273d9013917d622baee32938ca3bd9a35f8d2a70f7624dda06f0048f7dcb33dd53f2108f7edff76101618ebb97a5861570d13f035206e38c7d18f27d5840b8c5450f9b205e87cc9197662ff1917b0ee9a921a9972970178e720766bf6f7314459638204528f57f66febdc1422d1c90251729e25a6badb5d65a6badb5d6b006889b7074ec7f78b44f5a3f0ca0b6290f176f8e619c44755525bae99452868ec06328246766f8422f926a0264a23fe953a9141250fe3a6a76a248c90e44a52d65154a382ef4e46f09780c7da15028140a855c42a082fbc7cf4ee69c73d6c9d5397f01538705536c919574df85291dfa3fe8f48b6e134d4124d00cf624fbcb1a5584a02c9e46d224438e5c26fb5318501558ba98edb4328a8047f186e8a2288aa208abb46a45f697a8b62e63427090a61839f219d94413392463313131481c261ab27f0c0f7f1fae1d505182222ca1092cb028928216942734210320924c210072e47fbb3106c7648f91323199c7b416e3588c078d43c2d66f510afbcbb94493dca094a8063daf24090ca05c00ff02c81969fdbfd085239800092b728a80722a68f0842756b084178e09dcbd41cffdd921a308729643440e32471e649aacd76e18e50e874c5993d1962b1df30de362ff70d17dd4fe650f4286e001a4c0d4838fdc24c447fe57820881b997a3ace19e25b863447c9aa39613cd9da0048fce8b93e1042695d0ca3d78064120d0cb19364c924cc0a168fe29c708caa0183662b8a0dc201920d2a986076d81a60706293f0b430a2ced179c7832a63f1b293cdaf003337b8cb4e3979b40218f36b7bc0037b12293a048c24d014dc611b16ae29393b3240611b19d26ac8f885a8f262b8b4334db3dfb7b55c1238730842c7b14b0cd72e70585972c775841a839e8e62c0d35ed38ae524a029f9402512bad16003394767751b4f191ffe8c2591b5ac33ada4ab94a63e0edb81399ba57e9f4e34e29bd620afeb201d4b46972273ea24f298dc20e9dbd89947949991ba69fa239b24c61b8e6b16938e0dc3c78a048f6b7a148eed754893ca45cd8bd923a3c4fbfb590a68641a8855e4fd84de488fea5b4a7c8f4fb2565e8cb5ff8c790534a5df4d2bce1261be6d07191f02414b99f5a3cbb4956e4fe1ca72320c16369bc74b2db2e32db9f589136a64fba22aae07d764c96232426a2e41866ad575e60041643e0029421a4284d4185c3ca410cbc20f3182819c1c5fe28c82e450fa6647f981d26709065f0c00aee1edbc1e2ca6a0924d090a024154dc0108620bc9c8024071d0d74821004da4921fb4bc1031e9cb23f37e75492e4d34038a51d0593198c64d9f16c01e1a316976aec4007d9dfbbb14f2979dac04a9e73869f4b8f96ee3071c246761623d8f28ebfa49ca34b29a5acefe00e3f64291de62275272ed2f9d29920673ca43e9032b46966485f8d833e85a2a239744559b4455db3355bd3355f13366353e637fa9a266fcd117d6a1de350e87f14b3aa9ba62ea4af39a226bae3e1682dbd1113435f3117297dddbc75f394ab3cc757ce8ac564335acdd62b56b75c2f98ac0519e243a7e8e954c3c3c70f20018082473bcb74ce68b3366df3468ba028ec298a661b12b05cdf6bee9ff8133903fe90321548e3a8534e39e59453cae7b8e93e398e3a71b1d2282bd7972b5aaef14f85a5d3fc8ace750ab96691ab16b9bee75fd350f93f9a86864e6b1cf5eb5340ce74e84f9032f50300058f4ecb920aaabed7a6a908aabedb2ace4f15a6cd51fd6ac547f56bbd1113932b0c4cae361b4cc0d47677c84367f98efdf35c0806b871522e561f86745d5398b7047dcf0609707d6a336d1937c09246814757b9a4133750574b1a335cbf5f3fa44c0f81a5ad02bbca9790261f72d4dfc4a1f813dea1ade11a4eae882748fff163bc4615b8ad94f26ba6fcaea79a1a78f8b0a900900c0ca9f4717744f627d99cfc2f5cf851ce897bd4a753147e9c3873a0483ad5cc1005814798ec3bdc20330c0d29e32d69a5b4526a8306cd616e41a3d21ac2d00923924e352ac0300e238aa228762c4fd64001964ea4ae3891b292fd636e387139693da03ef73e766877011ebf86a902d850fd3e5e249de6fc41cdfd073449818f0f2e0c2f924e5524f99ffcfd33165f12aee33acf735cd7bdb51cd77121f5e857e90d3db8b31e12632931c6249228fe4f1ed32451b21d85319e1877ab89e8171851abdf50844715b873ffcd01fe3c621c7a3164828ed926ccd416d8b379cb76b3c5405140ef5f6ddeb2dd6cfe8ad9eead8f1e296af316ab07ebc6ce0dce04b2f161b3d3a374dfc6c74e0f1b9b95bef595972c6c24929c3d95a672eb0d75b6ee9533944fcf23e9c7f4aea7eff53ced79a8b7bce5a696f7ffe1a5b1a9b82dbbbffbbbcde79cd3845d4ab780171492011ff937696cdb4e1052d93f2e6f13dd01428ae563f97ca0e8e2bde18f2629ea85a24b457483d41b2a10766e93d4bdf73649a5545246669b1e3e66cfd9f88adef2d634b5cdd6b279cbe6ad4f87c7715c65e576c5c594e3b8caf61e699ada6623d948beb20db1e1d08bde9aa98fc30cc1714dfac891bb4a95b362a9e48c91ef5bedd0c08ae338ee7f9a82c891bfeda60129935558a8542a95aaa3b994b81e209e5a0568adf487e7c74e91c0042748354d8e150b7274cade1c2c7387222965eccbec13b8e234855316a71fb3542a954a857284422e2866e779dd8131747e57ae60979ea727b90886bc24e7cb0cbab8f87d20ccc7b002a6d6560a8eb2b5b5051ecb0816ef8628b6682d57abab5cf9542bb5456bb95a9cedacd88eb3419678356dad32406505e6e854a73acef4b1e5f1be102af33300925cbc37bce1a2388350c980907bef1217932ce051523909b9f7b25c1612add5a2b5682d5a8bd6a2b56831ff23feb20bbed7e586a1ef74ca2e264e602e262f27b096f8e556ebd43ac9643eaca5d1582d3a9054ce392bf73bcc4cb949a9fc82cb077af6e637ebac35f0dcbf058dc441de466098e6b18d701c5705a621fb677f1ae4cc05a48c3461408efcb5504216a8d00f84861deb2892a6837b938cca92a166855839ac91344c1a6a38a341ca00a1d168341a105927044ed6afa2959194214bf6412962193ac0230963397d5005762bb2a5bc4dc037bb9f6818c1a34b0e61a10139d3d95da48cffe97482424ab722fb7b24196a14d77de72d44c02329574a2bc9e59321011866a7490639f28f418a91d1c2f4a767d26956a1db5a8c4321e9213ff990d3e4281f4337b03d3501d31da44cdf1c0eb9827dec151217c944f6e75852ca2127f0e422177ab1aab61045511445519c266b310e85fe45b1c51669224d143d51a4e98cbd849113c8b2906f085be668345aad266766c8aacf5bd56aabae754dca4cc163cfbe50d45e286a5bb3ddba26926ed45ea686c1aa5fab7ead5e40aef58436f477dd6cd1b4a17843acd96e403a53c91c076476b2ebe47c8e9b0418e1c0719c18e3a228d66cb795afa0ac3e22a5d56ab55aad56aba5f08b4bd52dae6766b17988392709f36a4186dcf717e5e069ba21111d22df8f69fa844486786e5d17620d9926223a369eef8978de7b51bfcdf7d73fa20e1df0fd7d1d3ea983170eb950604f28eaf7dc50d4a1c8c77d996d3ce10d098043a4113b8eb31d5783d46ab55a90d495c18c2bd8e65822b2cbd0e974b2f69f047a1afa150f714ed3e428693b9da4edc6719a1c61a17ef886b0a1746678bbc99919f28cffcc6929f3c54dd794cdd8a4021e6172f20c2c3a1bdeff74018f7e9b267f75a1fd3eeff42665fc354d33f59f70145f377cbdbcfacdc412de70910978f42af946b609e0329dd25a39395b69a48c7f022a9700ce3ed7d6862729e33a864c9344c97c6fa71a1d2efaaa6f520606b755df7cd537964c41cff23a80421692f8dff5f8b9a10df3ad057ba859d45fd381a20e4f9daf0b7f9ea9a99a397d034f52c66f7ef39bdf96f8cd6f36c7c50b9ff6c051f6faf35cbebfc2ba4229cb0c95b0bc3fc751ae57cd9ab44e8a97a47d99afedaee781df7bb2aea48c7fff98c1e48ca7feec0f03bcefc302ea3eec7d7eb46e27ad94a99e951e7c60f91a498cfdf5e7cfaf808b40eaff70d13da11039cb1dc294a60b90f7177df62304e262ad5fd89eaeefa2882be0a915b437251f1899cc5a8c43a1956cd52b97fa5e7dafbb6b75a161972878cbc539bab60b569a248a7e877300b3820cf624fb73211bac5a28ce2ccde0c913b2139e4409c1c095e7cf9fb7285c480110495891021b0891c2882594b0851630c9e992dc80091fca0421bc20bb1070e0842654d9a10021fbb7d8eda3fed313aa44d1852f04e1044274482cf9c113206021092cd8400a4ed018021e5d44dcc414d9a378a6f0a4276fb0dc89c248fe647ba4fc6e4d9385cdd1fd97972fa5add99aed7653577573e44c63218405b6427e03a469b67a34cddc691cf7e58c42ca5c6973acc538147a5948c22e4d4d9b334d31febe5d59966d5997bdb44d2e2e5e28a0e56364f916669bc892b3a478df89e72cccc294c81796ef23e124dff728a8047fe3967701718210512daf0aa1f0c700453e62d0d4345d9513a127b2ab5925acc5d805c61741c588f12edfef22ea175dfe06c687eec3086f11d49f422fe31f705fc6fdd0690cb9f8f1545112f5a2ffc71cdd2f828a018a3ae4e10112e5638eeebb84373ce6e87e8cb008ea5d66f9c2084536303ec6c308753a50bf3fc64b94c813fac081f12e0f23bcd1f1e112de340a7fcb1741bd8012e5314091cdcbc7f05e5edee55f607ca360fccba3628012e54aa4a9abcdd17d276cea49be1d135ead62c546ab5171f14a9acef2bb69adb41bec6c9e678997c6fbf278ded3f292bbc9062d954a01e1c1b9ef51b94974df73e4be07c97d0fcb936449beef7159eebe2e6c9a7074680cb05197e625b963042a5eb2915fc022a8f9d99112d9c478978ff12ea1488746b97ca35c3e868f978f011641c508bf9c39ba598443f8ca3df80bf8ade6e8dedbe7862e072102bf78177f5f8422cfbff27d17effa2228d005c812796e5af9be8b50e409450e70f12fdee3093d397374ff45e849cdd1fd9b7b6f2e5e897a411f9432f45b1e3f0c172ea1c8c6c5bff817948e77354db7891cdd87629f58dd97ebbeee0d89978490a64b9ba3fb335ac899f9f7af179aa6fbfbf7bee7bee7b2fc058d32a435e2e29d14ac99ebb2cdf6bbb469bab74bcbf7bd0eeca8d038ee775ac8d17d2b842a0391ef8f9e9405bb2a2e7a2c1f057d1cfe6ccbe7f95e7c2c2e1fce9e8b172f1ab7bc007d2e2d1f8c970f0f99db45ba5c16cf7b5e7eba2a2edeee2665ee7bc0cee6e27d0eecacb838c36e0a52e6865d4dcadc16d0eb5e53e6b7893d21ef625efafe7ef79aa6fbb2f7354d93e5b957beff013d2d17ef77b569ea72ee6deeb8c963c4bb5abe2ce168f38d98ee95ef7b9eefb3a3a7b878ffc65ad63ba327cbef888bf791ac5cbc74aa5cbcdee8f4bbce1c0a4e232edebfafa6e970caae0fe48c87938a8e898bf73d1823e0b15be5dbe54899fb353ea99033d70b52a669eead3d2a17efc36c01d7a734bfddb738e4f9f99aad697296c53f86666ba769fcd638a29033ee0529439b2687224739d3e491cdd1fd298857fc124253e027f27d8e36cb9796efdb70c4358f2ddfe7c2f14e9179e8f2786ff7e65e9033370c52e6fe7dbf35cdbdd238eedf1735c1f64e2955a678e9febc3f6793e6a59bb5f77a38cad8fdaed2b6505bf19287f70300e5feebfeb51efe429e6701ddd734b91239ba0fb23170887be5fbdc12b2e42c17ef5f24a4787fe498e4fb9c6a9a72a649a403fe966f0989b43cfe15c7e25ad344517d6f7274fffe5f7bb790262a9b31e4d1592ec218461b31401e066f5c3c9111e07711baf89697a81bfc2e423c47fd38b47324daa1ef4b54e33802eedf18e0cff7efedbe2775dfa3baefc9a9b3fb7546abd96e5caab66acbf582c564377aaba9aaaa39755559018072ef8ff796ef3bcbdda9ec3e65b5a6a908ea3e068ba0a8eb4ad47d0a9b268aba4f6372a6f3fda8cc9dcaf27daf3f975496eeb456eaee7287d5c1a367ff589dd30861efdff0de7befbd9ee7794fb00bb26b61082cb6101b020aa2408201b8a0039b1528a8c10e8ef0b6f0826e0416afb85984239ec0a117ab097011b40638f473098cc43dcff33cd204c1f94e5069010efd34c069863d92b2277a9ee779eec9861d17d6908672ee248102ef147e51e2c9183761f93ce44cbffd4acaf2e58b241cfca52c028c0829593e922bb2fc1ed2d42690230f3b49d3348ec4e1ef1d84671624301039e392a62706e4cc0c9ba643297190802509dcb3669a1a67b691d8ec23486aa649a264990452c69724712df1648c7725cd072cf79efcf940d8f2630c3a548ffa7e049924e8e5df198f9c69f9df34fef2012015d0f2f23da980efa5686d06818d725009e871f72da02a8402853e78b400e79607fd28e64ea270cb833aef4060e8a21ce49ac0aa650cc2088102818efa803056f010179b86a6b212efadf70d2a51615408e549d4470bddebf0eec51b6ef2befb1c6ef27cf7b4ee3b3114e2e3c71c75d3b917783cf460b3fd5a5de4a1c8019eff5e078ff79f47c47b4f28f2700754fdfa627d52fd930f1cef6ff82d7bb22871d40d6bdcd6d082e5421937c01e7a89b244445c2863ea6c01d7b5fb5cf6719ce8a3efab91e58e0da24c264081e5c35ce1207fcf3bf79768dccc4b20117d17fffde7bdd7c1c57ff2bd2236feded3f7c21b9d2fbcb92932c40710590d8d266536de7f2def3d0d6d6e5e7ca088fe07fa7baf03cb7f2191ef593e647922221a8e9c0dd5f224ecfd8d8e0de85bc21b3c4733bc91e17fef98e525ca0b45f47b1dbcff42223a362ffe7b222defbd0e1f9117ff3d05f0835e445b40110d3f10c67ba0cbbf7c1154db6f5797b2e14db3725cac54e7bc80dccce54bc560857ec61741c9788972f9b15dfd2dde7fdedbbcf897f0a65f7c4b78a363d322fbc29b9b8679304ff6f58b77011b0445f5fb5dbc83a21a8a1ce0ff791dfa5ddcf7ffd81a17d19ab0c40a1758a9148ae55d5ec7c6c57ffe13dee8881cf07996b7f9d48fcde75dc21b4f85cecaf9fce8a98fe7b0668a664bd1dc3603e4648021300628e788f3686efb7e9ca997f7bfd1b1f9bc8bbfd1b181f19fbf51d180727996f046c786e55fc29b9767b171f12ce1cd4be82e4277854134ca05d6f212d5f2a3bb5a4251fd22a819ecc54bd48b5054436ee6b2cf37eaa363d3f2e26d58e8dfcc6771d9b0bc8bf066e6b084d3c562cdd17c0f64793fce1c2f24a263f3bdf712354e16912f14d93c083fe87178a323f2e1fd0324ca0b75e06e2ea8820c64104ba550f346e5a8ef7ff01e148ae8b33c683e018e80254a2683e5e9e4043c88220a2a5f48e4072f4c7d7098b4499ba329127d5ec927a4a9399a3f05cf8003cbb20879a42cef1be54ddba48142918df79ff75ea2b89a2d4f910e8dfabe51dfe7a4f20c4536df7ffefb4f28a221374371349a93e75f1ae0cf6397c3cdf2fcaeebbacfa3735217754d6ac1f9e01558a23c28eaea5c8a508ff185b73764e48cccdddd5dfb03b1cfd97d4b1c5dee7ece8a039562d7d54a654f4a01cfdbf007910e36b64079be51aa0fe5791545e1d80fc2a25acac0fd051bd51f1b8af28441900084b2ef28dfe1c38652cac0fdd7129c4e3ae4bf686f38cb0e300ea7eea8742db74539e9d4908000000000a314000028100a070422a16844a8c9792a7d14800c7a9a4e764e1bcac36194c330858c31c8184400000004046446c306b8a9a547014b2ec0dd293e0d829a00bef00586b2cdeb6c4ae54def8aec62eb776cd85c0ee70c4e4da2542caaba982f62447d3905de36fd6ccbce4bc5a5d5621f38472940023a0ba2ec7a0f42448954bc1c289c52b1194dd71889aec274a9478b519d2a212bbde1b7a2a277f08490cc78abc7e7a9c4d430646d2ee39db1235676cc03e3dbe8e4bf3f6c910bd8d1f10db5c49c5ca658c839043d51639583c6bee86341d10fcad3412358e37cefd436efed70f5ed9625f534182893acfa3a0b67943e93a4c24e752f941ab841f725ec2331cdf7521b5c297fa84ba2fc6f08a4522ffd34fb7bf2085ccda9b4c141d138d92e7d86d4733fe3b7c160d9e748e1e0666743d59c63fd7761fc8ec3936a64be076bb223c9017e6de99d43a870fba85c4c7116bb0db798d93f89679e3063a801253482685bdee203e8b5e28bc728dde143b193c2a420a8782c86b59670ce3a0b13a20e427ffc3179e911f73f78ae0193984b91cd1e570a081c0a380218d7c5f99081b93d504bc32ec3af3e4a0959b763b16c910141495f5a4c3694a1ec1ae8184c04ba697e71042e8505ec1ef3bc81aec994aee7147bab54a46d3b2d14a5079d709c3d723a9b3d0669515bc760b5e998bf2fb08a797c4999244e6ad4880f3e45947f7a86b2211c913fa43314ce0413477fb9b9f69002e845ae854b7d2e82de4dbad3fe6ff68e680a0aa745b2cde4a0bc472bc859139457de47f7d4f7ddc3e04c69fbf82aba7b95bc5b271943dc94ec8b38427604cee2434b7ca61d1dc0989925cdf82a7473b916538c34bc8b44d77add0cefbb749b165a3257929d579c9d3ce36042343b793e498c4ca7ef45a67487ec44ccef988605d98937a5179e9b5159203b99d7b2c3c7cebd43571ec51fcb158e196959f4881a1e333b42b76ba3cf2918ae5a484a84e0d030b916356c0cc9b5abec31773fed085a14156ab92fccb45735f39902be1ecf0eb22516b0a10919d8042a66fdd23af5f6f20cc82f049980bc9380c7bbc6eea83998d96783bb82b93ebc989c00c00c6b64e1ed28b3b3660c3c21c9b7254d8c961a97ba50dbbdd864468019244e1e326fe41e138e73383fd237c5bcd3e9cf9c3f86a712569e21ae987a99c0f4578215cb0c9b2995cd49c7cd43d84e245f47133d72f8df80ebb1bab133f54f61950532bf4000aa94e9119478f8af3d5f343a69e8217d673d9e837b27e31e8d4f53d2d378cd60449c86ce9972ec8f8829740c37d34152edfe0507b26010472976deb4d56adb69a85f44d71881fc54c0cd77c89524960f887fa0d644971013702f0e9eed168ac9c96a16ff717638d41fa00b94b8c023dca2a02768dba4978fac8911d24d4e2620c675777512f700a90f38c05c6ad24e1a50383afd4e5e749eeac9efd527f71e2509e1b9012703596d02efaf92e40ebeed46d3d477664bc2c3c6cccd7a390959863b6face254ecd4214c17d5c0acb57df27f5e50de43085fa85d618452432cd00da8dd21e8484d2a20a4754ebf11c17bbf1331ddeb60b00610894686c466744dec40a22a2654901cb06c1e3665a9eebad7774fb1241ff67268093c6b1c73d27d6bc6de0cd916b77f987ced37f9f30c254a9148b9584b8302043e9bc5d398961cbf4c444d79198966223e6357a6af8203cfa653d58f98757347f2fded011a836ec21f9e206802ed774bc591ee4bc41d1476fb225ae121027145271c1be877f6a0eb714d00f9132c35f7474327c9fbc44ff9be8933a26a80ac41bf04b2ec602ae8bf7593f0c3272b64dbbe83f59eb6720fe12168344e5aba00b7464477acd0167e1ec5c2758496f47a19edce1d204b57e192ad60d14a7b2b01e7bb652ae8b787c577dc73bf7b112dfcab6ea349998592c648108065ddcc98248c8cd232de3c0331de2aaf988d03f06f14b97b3c344994c177bf083dbb0b6519dbfd7f7e85ce2ebf10152bb61759fbc10ac469e4fcb9581fd050fa272f773694f42ba5c334b5240cf941eb6f32274a26a59ec0e3689225d7d719f8049942b017083ff08806a19a28a22324ba9e19229187490a42cccee70c59df83318e8efc64a7e0c60ae66a5e0edddf6cc5f0f730ee66716a76b1b6e75fa10b16a5c040d42d720a28dec8a2fb49b2b44993b6fcf5897bd7ef316cdaaf2f51439c61fb6619c843e6d3e0df7caebd1c183fb116cd06ed7b2cd7203d49f4394cd32740cfe547f4771ba77a919f3bb81f7706369885929c2a2579a6b05524ccf31a6d040078407f17771d01606737786076f41313c1c58dc8a1d8e44f7601cc104c9981d0d83ed9fe439c346fa1e74cd9d829250fdad8470af438f8d2c9eb7aec31fc6112da5fc04a4b9465751661c918fbaa29cd7cb39231ce7c84fde5151d611a7c801f335cc039dcfe45a93a08a991e99ac44672adef3b993684e9cc35a28e5a9a4f5a27ab68dac5af4180cde655c916954be97e5151e7eb582978aa79866b2e99d613ca0708d87e7b7c639044cb48aa9f049c5868ee792a8dce879501b5c10a822a5034a8c28b150f10ad9d45b71ccca4380f3f2c4e9279a44428258d2d7113ce7bd49222e8659714bd17a8300e9f523c442be619c07c7d6283d827c4418c632e7e5c2d95449cdb548640fe33b107802694069aa87add6d42e564595153ce057a3b2e08ac542961c10007037ee8972d95817ffd24ada6f508d722bee0d44160a57fa84b774e6058549fa00868374b32d772397c1c484db2e27380b23f9f2223bdda0d3a220ca03266d11b96f1fe4c1a35a7183f96f7309026519c88c68420aee0e7856a6d2e746815babaa72512455bca9f36dbc2ba8b764ab4467822cfb6ebd50a6366ca8bb2b784f98b11430a6b0428dcb7069cd096835e5483adefb16acd51ab7a05089270bbfa41809821fad40208b0a024100204fd2c3e1439e643f26321853f500598cf93592e83371b57549f5bfda072197f6297a2846273341e5b54bf76482e116df4181e05a02a275281fa2a635af4d09d0232e7ba08a94e4c1a75ea8a9c2dea6caa4e854dec48589f91ed1938aa3014e862859677c1eb8a42587ca3f56b4e2215419881a9b395aadd26503a4421cfc4332bb1fcb557693ccdf35346730a47f9c7185dec9ea551613e97dae4fe8f8b0b95f8f23f16a03f08e5b551e043de5330011088eb5c7e21f9d8e0fd7922e857ee0ffbf995e024f5b6542fa57fcd31abd45166e05133579f17e9704cbdc8916cf400757f054b0e4c8696e26bbf56756db056530b3b5e3ecc1d0a9e71319063dda6f599d788c61ee6519c508a0cfb055a5651190dc3876c40b33740c75782fecc80778ab075227f49fad81d74a43369c0644823373a3f21a065965286575c89c9214e35491599f35e1d00f5ff4e9398037ca67d33e1afe9d0b85b50fb1f894fb049fbe3bef040212ba488c3c754fb2d7e4522a080098beed6db80a3ebcc699222b8179b7791859494bc9ae44dd7c9f25ba19248d705d465dff442342abd15108e5a58e4305adab5dffed76b019941efb4bb2524af27f10eb37f2da2f7d7d5ddc2a124d96e326cc7f76b11a6447f3bcd519e43b42557980fbc824c1407bb7ddae236edff9eef0f24c1178c38e10159b4139031fed8163b66b4325d9377a6ea1a3084c95db7b1d057bb7934ea30e4eb01d8a9be32580857c44a51e4470a3c3cd77a43da0e420918a2f34268470f7403c3ea7200201b6b2fbb2a6409337f266767730971e4d897a5b2f2905e36a51c8fd389b89477341c1aa8356b87fdcf555a6452af10cb2c74de7572afa0593bba3c651ed3461ce3d3119e34b909ad81ca61b7d05a9305adacb5e3f9b3e1b9d6e02da4b931d24a4b1114915d8dcbfc97d0e79ada93e31c5f861c64ad7229f691fcfbae8600f5da4687e41efbcdffcd1bb2608a2f4bc0ad01a71b910422d3c0a480b60557ff7e220409efdb2aec45fb9ae5c25d098db6813b757d59fa34b6d11e2def872bef19f7a1065c44226060afe7918df170cc776bf8eb686f83669e679603a25a9224eef01ad7552a74d22489fbcdbb1e648b1a603f7a4fc2149dcacfe2df5f58a3c7b75b1e8a647c6d76c5230a5e1a12642ea2dd772746e622ee2b98e2e7e450dca38c2a2de71a251040cbd1a7f15dc734899881a9ba429be950bcab8a2f21d1278a248f2005c0bf98d46f46b69aeeb340a6a78cc5f8aded7c0a6625230c49a32bf44d3f1ab8c9b77d065ecd81d3ecfe58a7ed817c62ceccccf530cdd80003ef9e1bfa30c7a48113515fbb7e8c25375c806f2b6f45000231da289047571cfa3b98cf9f65ce281d01a9251d6f1e6990ec4a9d5bf1eebade2ed93516a0eb1dc6de106522c68415acf8e81219d6e21c3a540ddffd27b563e09ee13557ce2c50e554ba86e18dfb6d07260e752b512bf6cc304e98e6fb024501ad7c3ae6985a5afe5bde280eee2fa768cd8c86d759878a88931cbd498edb288985676e9cf63f9f9b08edf2960bc6c421e825e9a7b8df80609a8a48b376695ddf709142977c30b59235135de5c740de06a1019e8f4c202e8ca626fa03977cc6bac8d58bb125046417b4e16328aace478983861fbe56e5c7ab9e69020e63f6e34c7ff9ee32081b86b276fbbb91879fb6964defafa54fd54e9c47bc602cc56db0902433bb8d92e55860164affe6e5229639c7b86b396c17eb6f8b54d6bb1d71b964d5f5c8a5d44b5c5c7de5679a8604ed904a41ea69913bc12f9398b1db48c6826ed82abeb822bde9f3d6fa3fab728779114e8542e42ad4a3132f5a1b27569543daf08162a74918087d82e64a2afbe5dd79553e9db14541bf36bc2191e9700bfb5af9982d7197c6770b8eb5dbad7617b3d2be8320dd3ff73f4b20e4107f9169588677295cc12d2d812a05f37aa6f503eaa32c20b44a529cb2e82e81ac634177e8e397cedaeb61462965d03374085f3d610ca3152134600a6f6f87c261c076f794416823c96ff960cb50d0b38a1212cde596a1bf50581fa94577f0f8dff1076a930758b5cc349520ae7385c8e4910202d5efe773d877aa44861b29025b3a4fce0504fa3b57f52137c3d963a7b4b9ac72f7343bd63cb733c268a63747faa62bf3adcfe08084d03afb329734b813092176b15c90a05cc629ef2787f69ea2631a5430907726d8e02b65ec0bfb8baa40e28c879f47e2e87e4552d810ffe8361cdac73adf3c8b72a333dcdf6a0ed331e508bfda92f5683b6169cc95ac9606f2c86f223433eb87e1640aafd7044bae1ef3c4919234bb4ad145c0e1b06cc2e529c041f968041606897fd23bcb5c5190b253e9cfcc32e0ca2fe690c89cc302302e0ee3c2bd16d7f6863f80c76c64a6ddd2325b76ab4068028a4a87f70a84cb717a1b9e450a3076f676a32fb556b94ed08f4ca8f53a293d8a4880d73e356f0c45f75ed482e78f42598d8e497c2e01b4a1c1832f07888d2b991d234d19667062ca3e7695512fd099a41657dc95cc66358150e15fcfa8bf5c3b7dc32eae7e4444d62e77738f3429c07dbb135a5663ef8d11ac8287182b3ed56de05b0641189c75979afe00e485270d9372989e13dcea1324ea4ef1828bbe54a5b311b673d5b4205618c93d53a0e202e88b336b282e55f0331cd39e08cd6fc99adebbd2a8a569ba14cf55a82caef6254ff3b951493a56693cec313a275f296ec6bc8a9890bfbbd8d451571b6dd4c38c04dde0e7a17159b79be9841a2967aa6d54e4465a672950ce645aa6a96dd2a2b2924484b1ab9e129f6d938eb46de21e634ec5cdb211e70ff848b95dfe78aceec190793fde5ed9a10dba06d3308aefd577a4e5063143cfe4251bfdc66659900b25514f9c8eb8f1d265f519e56c84bc6773e1b293c20fafbf3d33611322ba62d0426dbf75f2cb51144df1c0db542915f5a5492565e51575f5ce9c372bc413c8c5ad5b5c850d61c14a32a39f82b6ef745bac5b700951bc0fa10c09b3cc1a433f55e04c66b8bd5974ba662b61f35016ba2287e6d444be65f4a35330fb1af6ade8c5699f0c79dfd717f0e2d180e0fc9ceb52423e68a6fc0a950eb617fdf21e876998f6391ee64fabd5ce035e678ce4aef7151ce66bb77295d8532f7169e945e3521d7c4d0e85380b48ed302130d6fc1396c383940e707381fa6169c2116c3f4d9166aaa5e6976a12d2ec41a9f95227cd33132cc5d94d4592d2103d9569c5bfd82afaa962a3429ff848f8e00362b79b6f7376fa6cccaaeb75596f92f001bd6119e7d1c0c548239637877abf8c6698fc87b83053c380a4347a0ab4a3461d0f21f1a737f52516cd60840c7f3287c1e0aba21f5c44af7abc4cc62a8dbd3cc0cc734310c4ac2d6c8088743e28456edf29f2d1302bc7c6b9ba689a18e49897ac9e20fa645e2cb4770e67ea4893993e58e652164d34c617987700dd52dac1dceb8c29581a2e36f2ce1a7c2842449ca5738f515ebb246356d399d9f7377c49b6f1c0a84b5af5e340164ff4bf670674c4c936ba7ba001ca282d22051b1a4249a8941201aaceee3dfe3c35d6c3e352938eae2ca6eaaef99d0748fb0776f313c61089572979349fda0b3290e8d1e17d6fa8ecb5db8159231898657dea3e03c1bc869ae08ce0290865c289c65c8e6413f2e4355018d352a71465370a64744c9f961ed254fdda0ce74b5c5cd0d2f41bf8206c12f7e0a36b536250e2cd77416781ca62fc561f7d0f6cf12d32de9e0558244a759cfec0010c426281c4b4f5c1e81eedc219ba7512369664e8c4684cda497ee1c49cf92fff30d72b441941b827477b2748b623b34ebbf9897931f8b87a1d2088cf85d8334ffa4a0ecf6651c43b566eee8932f650357abfd1c69f1db74d547f5312232e248ce72c90958b71d49bd172afaf4446ee8b385d74a455226efc2bdef809209c8027cc82c4d84aa49c033315d11f5b70d669ed2a9d558d71c1f95cb6f0f402fe93b842e83163fcde51755a887983ca1edc6890f0d938e387237fbb0e4535a7117ca59230621112ad3383f95ee95efad8d463e6f8001ccefbe360f79969316eab5ceefba4e5837f56e103380cf790743d64d6a95c891e4376321ab0268fde0926d8efbf06ec02b96adc5ab39e1c5128b5fcf383afb5adf5355193be9c0476eff14270a06d71f6fcdf6e25cc22e3edbe0c882c1273f2442160690cabd7c1b4e85545365dad933ff573b3218b173a1dda8183263469063a3ea03070b4fc2de95d2ef9e62b4083450f4e5c838aec7923881f3820d2dc7e8c2b6443f85a78ea027aff203b692fe8abc409053957321334708c49097417946f1ac183933a7786fc5b360c1c094db93e53c71c9438330373702b9fded5fa296280063c3b3a6b5bc681fd00136767a58526929aa83c87d0b5353891e42991010696495a91dc1c9c50e3218e01c6bd513ed2838109cb7358fdcb04851cfb35eb0c252198e2a994b7d0086e12c6dbab85936273cd4923c48cc0ac8bd97660c22e83b47568931c56aa0c8290ad7715e7bf8b421c2b4298a66b7cca3f2595a8dd2f14f7303329f2354a3ee146dc379c1b9647a3a0581602fcc9867aa46b6289212d16e6e36dd9746220748d65f798921a3f7b6ac8ec15ac90cd538265e6e2ed634b54f5fd2013ab0b3eecbd06acd1a4aa6292b6248c606ece89be50562f122836cd74bc0b36243d79a8e210569cb8ccf445de605a352dd41705598159678879e34bb4d1dcb41289d7622b6529753c6fa0ff794ac1fba8ae4284e0816b3923eb61cc139f139aaa5c0331d866505316c6ffb229f8f719c4aae7ac1f2849d4ce5629803c61c1dec774e61a6bc2d946c22f590056d4d1af942a8a3c5e8963725c68b4fc265965d06ec1150981f876c460b6af9448166ac1d41d33c977d48261ad1d593076fe6f441e7aba85a4152b52eb2b10907e0ac212c69bc6a93d8cb2a6757cb4149dbb37417473c814f5f9b8eb9900bdfd7ebfc7cbdcd6ec55264e3f465ed39cab6d82d3b2c1517c3ff6aeb1e1cd16fba496e126a8f1ff2e07cd59b68567cd86fdc0a2a79655e3f85749b9de11adb1d3248bec6ff0bd389fb968321b44efb97eaf3f7d6993d5e44368b552d45c00951ec148713c04652232441f8a4c32cab0ec6708575a446964c7c01780b38389c04f029b02cf0289b8a250e34ccbdd751a8b061c4cdb0c5615a1fba75a01a85881658e43017106303b89931dfe7200a968f9849ac8a2a64fb9ab801c8eeecc3c916d8174090eda3e9b1bad4420b2c095c7cf6c174d1b9a72ee86b8dcd52a67fb1738e7a0b9b3299f56da655a244a8675ca16e55395bebf1d247361cd133ba654683bf84c96470fb0ed14d3e6d1bb322be03d56cd4a1aa3e431e0376cf3038111229d997064db8fb9a208b29ac1403a3222d74d4ffa6b45d70799abf94f870d2380dfe446c1c2e13addf3af7a9219b7afd2a531c3fa981ca4352b93eb418f60636627b09341f99b18f5324ddf1cad99255ce69cf1a040a4c4164b8738d8987444575dff309dcccca8c194d104ea7a962da4ddb60fdc9a57ad14ddf10a8ed06220cad379268ed421a5d401959194b5887b4c832c1f7ad2fc422e95b687edcd7fcb1dc1bb481700ee7fdc4960a9a4e07fd8bc8bbd08555d33bd88315cba0c051cb383e46cf5c811882703d373a706c68ff28e100e0655d288c1598452526aab3f198c7706d35fca803ae78941027d4b8b5d386fe42cb8d3c1353f7053fc74401f6039a5d04e1bb56a691d729645c1b9530c041043746804f943a0dd4a92d1b83283904f4d5f8e7fded2de02793daf9c8c4022aa5bc890f0a1ca84b82fa389068e896723dc9903a0ac7a8c93a76de52c85eade94ffc8778653975a63af5026d0889632005d909d69d826a71d8b00cc4c6ed5330c8a8541d0feae35de37b10acd1593f60c2cd485893fbac1a9cb234535cfc03d982ccad7b45504dda3243659edb3c923649da868d2d5bb4cd9b81d4e4576e324ddad3c7ab34f0b8a28a075741c63b18e91c262c835071520a12c715880f5f2022b8e2c6da6e40b3a838778ed9ce39fcfe405edc817888c2ef8dd8cd3bc9eebf2fd54a033dd74b74ea39087333678d714de7026142fb7a01d228d026958ef80210f82abf38473cc22383b8bcdfa7102420d3967bd5a0a4c22d46bbe4c52778b0a4bdbf24a217695784a7eb06980fa82e3069ea2592634a78af0b774b9e5462b999c88ed800c4e5782c9f201e42744784cd679e5cb38936463610ae532b91b0cb293a284058a609fbf6352eb441e858333c5d96eb67dc4442ca099c35ebaf9d79a836e589987f79aedca0e3a2f655039d8ca9824bdb4ac619540612063d627e2a9dd0aeedbe376752128783b49fb31bfef3125e922daa607b76b1d53057cd03342ba85be06cfc80a2127965b0a673f220182449474a62a4319c15371ec6cf5a294063cf969368562fb8a4cc3fa0138ba0af8316d1a9c157416e9a216cee8d2c9d07c6380457f870e2eee9f6acf1041ad29c3fe3599145d242b90025435f8d8a5b4836c3902698067f96f63a06165b9d50efa4288712c288111974ffdfdbc5458f1d394e503a0d595c271b22f72779e698696782bee806b382e5d6eacc2f25e7b9fad21d8acecadd7733cb2be76c1d6d5c93f508e7ebd633d79d1fefa5224b39ddebfcd018daebdfc3912575d87c906605f87e9ee84a1b5e61c28fad6c497539aabf3d009ca1d32d38d1254b982d2c83d3bbfa33e41020b92e2bc8e434e97c7e1d05af1257a61bc466e10fd85cc215ddf246add5b6aba8ab1ea56536a2707d4da5d04cff32c5515259a4010091cb0317ff2e7b0591d0dd8d3908d1bcc800d07d475e5a45042db5092e45f4c5f260adcfd93518328134d408c7b462f62dc79a21db57c362800ad837557747091515b754e76d3cd8798eb7fadca240884ffb4d8eff04b075b55ba2d7ba70e2ea2613bb205c1f3cd3390b7c409f1ce8ed2834acfae9868e1a4a04988b0d35330855c36bb687133badaa5f418d58a7c06692218288c62c4a0e205fa1514cc494a63294bef13ebc0c6f756dc11a11468b81f865a290a12fe87b5b8e30887205077b2027c936554b1875b90642b1750c5497f634e4b0885fc6b9ed1a0a654da3895a1c35d0a54f636ae4ca5cd9ba4639ef030267dbf80526577fa65170c7a3d3994586d63e33008ac6ab772c447ea3eb1620a54f85f31f75dc455a74cab88e774dda270ae909a84dcba5de1187df87bb23918c8aa2b836173e3d0b5f40add4bf196eb51c26dba138fb07dd31adb08ea9544bbc2bba37a0ab27685c1c9b3ed98af00494c5e956d44ae41153d0401b232d0202125fe779a69c751c7c056cb14866ba14b117d1b112ad2b5fd0f7592ba1a7dea9357bb0d61d7f6a08557872d59e81a2f186c1632fb76e3959d19e97802cf6a62ef20da5abf456bb296712bcc9985faff5cb1c048abb522be7621fa76c8a7162ef92bef8a25db0b0b5f65f2044f5c693912010e034757c29a5b3dd0bae7fe00a84688ab0edb4b90453f6268f53eb538f6ca93e6131e6f04038c9cd0613ae1cce487a4d6ef584931a9806028ea337ea26b89c4ff19ef3b97f87d79ccf68b4aab32925059de44f35772c8e033717841ddb8e185d6373424721797c77507e07db455647fd6a3ce0083a8cd733d38dac581a3e1b3defe3519445d5339a24fccfd7c8ac160d5780c1dcac69ddee3970e9ae7c51a51ab997a0c1577656537ca019b7e76c23dfee2632f91e46503f9fc67511e4d477bec4a49b1b9a3dc8b8fa0fe4f6a34610ffe033d48ba13d7b59aa7d9e38410f83a611288d8578ddc281149e2912aef4dd300476ac4b58470c362d8b7fd7e71f1553b5a02b65cbda4aa2242e43990f5c1f8fe14ec001d2fa3a30fd697517dc9a126ef92477ac9f8df2909df2c8492a99fa46cd7f65ccbca5272e920a47b27c066cbbd74e424bf4cc0f2f8495823cd3fd9cfba059d650c722e7db0575a5f1908c942654edf1c8cd23d4abc16ed6b7e3cbfe912559a4f1eb0d29ccbba090c97ebf8f29f1695f6248ef07e513b291d64d01fb186baece453853c7292c18df111ad2e87ad9a088e0a757fde848e5f7ee5d893c1a0c2618816638d2a7ebbb0bcf626690cf0c36769e6059a54e5296b4495aa029e6845547ca15453193322d731323dae8e3ccb206b965bdb40a8b9a7d32c1ec5d1fbb65707b273d7f4dde777067d569fdfd59d1f601766c6cb2c06f266ed316b3836eaf23afbb524d6cd41e26d71428e4251fde2eae77a218d0c59b2c4f9462d2d0157b9f5210197e43b51341b0058c438788b145c351010231bcbd6d7fa94a21eac1cc730d0ac4a51f0e04fd74b4b2dff7e7a898ce5f75df6d898a3542a420c9bc3ea9a12dcf8554e3c64b26174d63f571027c53898530a5a246106e27a5c57fdebc6a4a0cc64a621b8019c7f8d6a95789727b2174170b0f6dc6563bec7f08b912c6d74fe505207ae828977ce172a4bb63d8017c4a2bd510a714c94c1e8c7a67b21c8bfd35853d0a219f9b1697f972af54829818f56099a293ec1e654708320f981badef57ad3eb6f943a50050d6c94b7282e85c855156fe14fa5c02677b7210d02eede5d0781e769d1de390c4b5a0e60c715d2c4c53958f489c34870605c47c28f586f74baae42c51f9c1c88e894e6959d62c65d29c8d6e577cac87023b8b421484c68e2d6afa0467f2fa8d25724a79724b8785005ad64e3b081a10e4d4a82c1b19aca0ecf278e804090bb38f962cfff7185662240e9a0a00ff5877682d3664613124a0128581741906e78f2d429c5fa16cd86867da54820411f6cb92aacdd9e488fe46efe795bb9c64c1adfbcafaaa3b78215c9b527f5ba127ee4f32869d0a6eb6159990890e5ff9fad4b2d1baa9fbafd7dc67f702a5c3f6abc3e11980b0f42569dd38b1fd409d735fd964319dd23380b47d3375f17925a4b45414e170e6a0ed7b18e8cc15cbc293d07ce45357442e6e1e3267c6e98a3fa6a41a37eff74470d0fa8334a04486d5951c5313c2b5ff20ce83f8f72ecdcf0e66f696ea459203a5f35242dcac9694325f0b6b7038d8afd6affd79a8037e6e724f2e37792ba1795c07b95dea8bf20deca1e68761dda5e009d1de9bb67b9dfdce3ebd3b019f2fe7c4858df7b930249c49c608b769996d2a59b2c7e565d5097995c044a29e95c82790cfb4b5a9a5656d0c237b3ae5fae37a663cd2973f0655a2fd4d48a65c9ce94b4183a45f9a2298732298613dd5b95236ff77210186684bd7f10711f67515c9ddb963433b57aab85b1979ba4f7cc3ae519d8d21bc80276cd438fb2809b4a6f03f96da464adb4a067ddcf53f5fcdc62d6a537af620124752151788c0f0e6473b61e6a496c6da8fa0ff3675aef364c0059fb3fb9c8e9c62883bf2cc3c3885c99cbb86d42beb2f9c4422e9576f129677748b0d18d8c5bbbb1c8b8434e7d2f1736425f85bee0e4a375fa050534887c5ae5a1393650e847f2636ab4c2f6932002be59df35a43cd8ae7490ed767ee08d1f53e82204060df418e44ff8283624a2004fd68c648f7c4c3d5a20f9ac3a3de043f298a73071feeac8123288337e0cc13cc58e883fffec54e3e9fc25771f930b76c02d6901fa5602bfe8e154102940ba5b71215d4f07955319b1ebb8b0d290dbf2ae4184ae152178d0296903bb65bccddd941940615971a022846bd5938520f66088297dbb7972ddd240ec5ae2206dc5a6290084bfb7d6d91038d0a0a9bb9a4ab805fd2e91e6d904d47b8a42dd82bd0ca0d5bf866928be8ba196f32e909ff425a6402030b3e3e64f07092812432b656934933516666ed7b80cdc21a51146f6e709105ab7134c109054cf4bccf9462b1a4136a8e7d2acc3a390ed61031f55514c42f766f25e59fedebd501f42081998e093c8e70705fcea2b711d0a76071a3afe9fde73905374ace40c3467ace05d38a527b82ae2a9e2272d59a9e0594a1e163d97b35bc1d7c520314bb08d24962e98ecba67a4bd47b3ffd949f822681a9c37bdb5ce2038193051e790d5d65e906885d1efd0dcfdf30a280c386908d2a9d1fbdad2664c6026da18f0b620230f00a1774a0e4c4f0a7a95f9e7dece71f0de5b4610d43a9242c0f900b210a540e967e89b5585b452020153041acd687b30531bd17a5c5a47b658c022b990a5d33c7799610b2983929b0c30418721fcb40ad99994275d26cd105c93049b8a58cd604c7456f2211365e6b19391ee18aef1791a4a886461bb2283964bb00e9dc2f2a71fbfd33e7a8736c766b47b57c6e066b41ade6e0b61072bcfc84dc3f5da0d74bdb1c20dfce98ba7f1dd64f6b92750cd278a7ef2cceebc338c1f4714a817cae495efb777fbcb30ccf5f28dd16fc3ac08199de98400cef521292f2eab615b45c9984917c431c9e468f6b328e02b47e47124e80516b6965aff16f070c534c210e1d717e132345be46b49a2a91d236b5544d3eebe8476f975d726bc66bf5052832d4cfcc07b454d3e2d4ac73245eaf8ef7fc650878dc931a5b6b924395631c5ec3f2f81d50f8b32bbbcc38d577e7abed331a2926b11f19873d689cd60770b497b322f77a824e5030436b9f02e862c1f341f4c884d3e54413a58e7b308c52932960dde5c60c6b69e9d9a0ead8ffcf26bfa0b5b9d03a2bc7b6190733e00d4e026a05dc854489b45810fe6eee0dc90f12e6212364baed6fee051da33590decb2868f3d76bb421230505e07617a017df87cb90b2f71bbca7ac9f1880f51f7603ed35f86870e8e358025d2040d2cbd35c8dd728ee498aa4fef11c52d63d5b5cb72485d27665bba7c4af7c980e4ce26adc603f3f6abc7cc480484a0bff81dfa6d7f50d964f13b7811f31587b14bacda42b23164bc80df1abeb4e5232b63a3ed3dee8d7bae12e2d5a5f0adb9080bbe6cb1ff7832b929a71fd5483ba763eb9634eb3bdd8f6f2dc1214a1f5489757f26db1d39cd626c16523d7a610b3376d9e745c93658f1a225c7d1d706f406d38d6789ce2c72b7a90d3caaef524c9249a409961bf7cf7379de40ba9d3dbc0e75b6ccc23c60d281c13412617d1f3d944ca20ac824e04ad182f22ad490dc70aa1aa89c5fae9d504b5ea89b4a4c4c97dd0f75fcf35530575a1034c9337f5b08cfbf2da29d0a8e7c27aa2a570ae305b9ffe5c92c2ca3c9b88f7ce5298385336f4a87c3ce9f15303f0d519f7c7342b2b0266a5362a660751937a6d23bf9a5d02e05758a5e9fb61b52f0442972d690431b33d45a83b2400c4631644b4c5e1e8e44cd9f2f9399c023afffa47328a4606f96e6d299110cf8811c5974c9703578aa0c25d469e7b47e16430a7204fb31101bf5402d67178abf7fe505b64fbd0511961904d61561da7a8de0600482eda1d3140914c66b70510af1560ccc32cc1fdf1c77a4c329cb95441605e86d824c2221dfd40e9c12551915407dc835a94eec5823722b702cc97ad51b5fd96ac9fb94489b96048100c8c68b4dab222bf692490859d216566d8ae4afe2d111857295e9b92a82311d42724021f4ef5122e222f638f343a3d4419c1541b9227b068e41d36c448c889f4ebd477cd200ddd065fbf60877295934b2a47707f8d88987c27344319e7d94f046d7d8cb1c4158996e82b7e32338d7a94d49114a9a919b3be9a428a5cd19ddd382736d0718c14e0acba1625aaad5169e3d290a37624d26ccd27117e422d338feecd3a18eead039a67d23f9eb7804149486050d4d2a623049be167a78aaa619a0225f6256ed9a985a9122f42175fe57388dac84d6288fa50d20426787830085640b5c28aa0d1013706f2209beb6e167ff98d74ec1a962616ccdd6cdeea9abcbcc10583d575390f95cad724254dd2e5319247ff63550b1c5438cd0402dec91552f79a0228268d9abd1153d121dd845010859c79b622cf0824671d7c986a7c295049903c00eb8703af4aa87e7fc56a7c31a5d6fc0a3a107864c49a2a9d7e009d2677df7be4a930df0f42ce854c7f08b2f991de746f6a41a5c72ddab7d1430f02eadf17fdfc929803b6c3e3cfc8a15d9a5bc0f0ff34ca5d9cc19c3327db67a429a8e5664b969720c2f3fb05ac24b57583cda4f2a605c3caecb8e47151084b6563632e3c1c3bcde194f7be9df1a7312c1330426d4399b01856e000c578cf2bd546cbcf3ab7059f7f7e371538130d6b8a8962955fc3aedbc65b999e51e26aff0d1e7be288ce770b818479615fc1ef38024d37ec361e707e435d16aef706f20e61c927b7b3ed3cd38a67701e1875c5f3da0ea3c2c5e409329b81ec4758a89947756ec3899293287f50a5f587b3c8567b61a4483437ee3c01a9d2fdb5e7dae53024277740cec66aa938260caaf5a1c01116c9369137f61689633e39650dba6fd1d23d4452b738e519b20c1f000370d3606a913d9fbeb4b232761cff7bceef9aed6ae9473338131e0507cab7d26587975ffab62f93e82113e8c40a64f2c167b085248e79e9f2345925f5e6967180a62457cb15aa0b1622fb6ef74acd6bd7faff298ee8f826ffbcce974f7f6d1a4d08846c255801d39aaaa388e677fabce10f7d84a9389c458cea70a159bbdbd41d0527aeb9ea2b259191500d99976d82f339bd4220b1e69a7eb06000823d344e262a8b29c959281a366bc2f4b059d30850e9ac4dd9145b91fd8e3cccc2a72b64e7c1808f3fd247a68cd43c269620d5f3c4d6f19a9d2323a73a796083ac1955d321ae58a5d03dd72474dd2b5b80442595a072c06bf458167ec5eb40f3710631db60f079f3cc6ebffdcc7476fdec5a0f20e0e4b93740ab512a283c3628474fad03c07c1fa2acfa01171b3a2766132c43689623d9852b8f001948224a1013d8e62da6a65e96eb104da88ae96077424b889440842004d84fefccb5322ef8b21b096d64aa20103e1cd70846fb5894663c6b86a8d6e4fd94ac9a9ddcbb109d7c8c2e03f491cf9bfd61651adb551c7966feccf602c991ed6d8f8b7b042acb255be3c844c90600b29df99cb665b4d51accfa81f0cb46193ec26083e7f645cf14afc30a9e0d83a84fc4ac0a52c7bafb355a55a32ddbe990670aeb41bcc50606ee1fe5fe40a5e6e2f113f49a1a9b6ad5e81e502b4d52e1f726690290ba22a0bca9c284ede79566c6b64cf8f6913e383a7fb149ae7dcfc8da4457c652e00c1b60446b7361f71ce4c3daf9fc8d1378c96f51cd36767fdce948f1414c2e352eeee2a215ed0907edeb833d34f0db9346761f5eb8f4a78964cce8c847a4aef29394ce19a16938e85ea50ac24dfb356056b9944f6f9c02c864a4e38dbb292bde5e19907b00340bf790f6b411528162f03ab1b1af6424b53579b5e55b17a8706a11c465010c5fc007e4b1745b3859bdc28875ab5be5766085bfee49e04bfde8896a6899ae858c2657d373ccef35b7249e2cd226011c53cc8402874475020d1854f52bf181773edeb35c15da7cdbed3a42d5a3c1bd5a13c3c3fc8136d4f11c8cc5afde40b480fc4a3183233700fc6b9d837d791bc96dad3223e800c64eef158675f3eeab61166de5867515d5be8851fd80c7dde932a271513315c3b2e2c3ebc18cb9c0051bcb249b30b46884d6c938d9a92bc307e136d84d13eb0f484b97d0a2557ead99656e576ebb4e8d9d4d664688636be722814c488446722b35ee5f5798cbfc651bd9591e55c807dbbd3543b0e3f65aa225aa5d6b482b22162509e10fa83d06973303030f5ad2825be68af5b2f1997c9d900f56416f387902c7bc9e165344c1eb867171c6b47f4cbbe15ae47bdc0e9ce7d98dfd41353378dc982d8c1e1f2921afb33b0e644b36176507f7e3f9a3ef1940f9ae2b4dfb8a1b463ebe5b6621a97738f18ce805e32074a559b70bea762e3f9194484e30fdda217b8efc0a27a415c71b5c0d71ae513c049008f4dcb8b84d0a96cf232e465b7a89c2d92cc6d0978f98d9b9609f0cc27c885cc3d7183ff733713b518e1c7b2f3ebd10c77e05bb1164d5568c775e8a391929b52ed31cf631c2ab7146378f5664653f07ca63901f19d120947ab6626f4be53e84328626cbcb51d24d39b9315578bc876fc79279639760972c33f4f7c0a261fe57ffa0f703e469a08360a61aa8c9691e3e7b1362656e678930348882ba626a3fdfb5ace9bc214bcdbc580845f998c50e6b3a0856c6e4342f5a9d3f4addf08211c1b120a8326dea3dbbfefef0a32d4eee64b666a6f1f63b3c848df67ac614c0eb40966264388f90146d5b4af08c2098bd4aff8b4abcb00f4efa045e8e2223b4e36cc5d5c09d0047021a1aa48cec02b40cb38732f3c1527270cc46fc7b39caa7a8b03a7bb7da87f2194668767bdc87bca860322ea6b479234bcd4adc49bcc357058269f3d9fa3d00a61428281d564e3a2a253a91227cafddf32cdbd3d44e8a9621911c0920e9feee318f68c63e34617adf3d50c84d4d231d1e5deccada2387749c34b9404f6014bacdfd8dd0cc02f1f6c9134bd7eef96cd7948fb69888f616823915d954b27942a9a837b54e55d2b2635cb37b5a3bb88042c85fb46b5c39954c5fdd567c5754c31067941a3b9afc8fd0302080b9ce82967fa87475d69808993442d2a9df0e614943232a22d8af0c6a60c3bac026e5a19060dd99f2dc28199f89d4f8afbf0a0fbac4a1dd513937f216d48170b9c5787e669dcb98f6882b69a480020b515c45796433cdcec44095d424c9ce40ae55b701e6e01604d3ac68472025ad222b5a3f5d8150c31b1d2dfd79cff40b06801faea29480123f966bea2eb95903d9ffec4392bc954a0a842b717a202661c665cb0c23a72d97ca0e23cc1461a41a5dce859bc571e2ade51325392d31a5930bfc8f56ce6e4ee9da2f7d4c2d8f60925beab2d6e91a1a817bd4557e7ded26efbab726025394c37059f3e53fc8020d8ca47c995852a500543a88cfe6695308d9d21dce3f0c471257c15043f917db7aee3c59dff8427211dc8f23d0a43a9fd8832fec62fcd90d2de4448dd9cd9dd2adb22d446e61a94ab8268cd2f2c59a505e08f49e7440040d4cab53fe764a352f5a50a0e3116c051a6cba4d39319a6c8e516ab05da7b7af2b1020a7a38014dc7ea66a98b4058b01bbdbfa2718bc63943252ce0a36cd2e843ca227b0cbb82071cfd207e924e35012566aae9c2290b4ccb4895bc9d117a2d78f248268d42021831fe7a8ac6be18133d98f6cf07c98485da1a9ae92645b9afb63891ac927a5db4334f8ae8b0dfab7dbcf5fd8edfc7714bc2143f5a81b1c3f4fe23ae5a91ca53af1f16ba5bb1924038faab343157718d77dfa3e5be29121bf61a4aef85d2da0c42e9967859c8363fc90005148d35749a729c1efda8be7372f2e8fe4ab281a117957fc9f1453f1d10781f8311a7cf397f8b9a20e82508bebc262dc2daef4bdf7c6d154c96cdb50fec6bf7f256a1e944410bc31413a144f0c3a0b8dd4b65abd2978ed0f526a9e5ef1e082c5a1f4ea0b4a638990673649a2d737b3dc241ba8a66609cb9cb202b28d00215bde4748c12ca4a1bcd40b99dfa350621b593234b34d8fec3d301805fc29ed099990cf4ba7467c115806ac8518a7432198e11bc00a109877122f1dc50a020f575b1a744dc1ef86fbb8357a459504bc1b2f3b8e0ec72737797d726701e6e15a46046a789b4c86177000e7bda302685da309705fe0e5da961801f1a06f5a3204f5cb8a9c2a6a7b0f77e0f5c0cdbd1359dfaf549aaf5bed233eab8651e65da0488c6c86d9aac0923b00273586a9920e6bfa56587dace5beb9a13ca6d60a5b926ec9f68823727a4df79737c61f4ce3527519aa51d0e80371c9955f5c0d7359f49efda78be38db4ca49a9e02ca964f757f186252563f14f166735def9bb4ec0536fde750df761b46fcf3eb0bff40500ece7e0e12689f1ea9b3070bfcb56e3b977df3fa1cff58474fa471b1b1fbc904ee7d3147104e409338940b1a1b697ac76a689064ca3145ecb79d58b27a1428aad13f6ab22f3de3b09d5d7970f4aee92634bb2475d75071c898e4dc56da4785b2aa7e502335a426bee622f06b7365a43c07e4054ad52a525e850d62a5a9cb4f7c44b2ba6216defdf910a3f484c8d969acb0367c75184adf31a575a021adc238e7102237383e6553561a061cc5abd345614f4d15ee7810e5644f9ab80a6df33831bddd1cef7ae0ca045c271314ce0411881b1b6cbc9d1d925ac365986ca8a9169dbdc53c87052229b1f9d06ce71e9b03ee43afd6452ee57754726bfc36da470799ec692f1244675815d7e4b560a7f182765b658b45d116afdc4c01aa673c1287eff943214e7e99d2d02ff5242394d6c1862a269b33a99dec821feebd4cf8961d25584fa6222bb1642a6d004aaa05a4ec71b4f8a04bd4d471771f36ec5dfab01ec57e6ef0abb81a26ed81b2fe9bf1c0802fecd7c330a269b4dd7474c5b043223171365e8dec97a69fdaf059381a533b3b1da53062c2ba3f4650599a4fb16ffcf77874f8ac0a2d1ea6ee54c3fcb03b1a6334011215d9a7039abbd3834953694c82bad08225cbb8e4d27ed5b79104c39be85b130194e8010446ca2e0ef83476a827ddec1a092564ab82167b83f0c67412106860527001a4153ef3e877adab0a2f0890a859171ebc1809d392d0b7df376b5c8f65e90cd77c79331ab1393481c43f218af8f41f9ca5c660ec93b442de1b731a8cdd1a99e2fcc2a3b50a990a8516832e0f6b7806e81e3d0c35109cec4d7aa3ed77333331866ee01ebc35363ba31254c3e4822ada4335729430906890673aa982cb3e49b9e0650c241c12c0858b08113046274a4de024a0cb98da899e41333152029b30ae3f290f93a903a1c468105d02cfd3c9f1e6f3566d6648591d85ce48c569a0a621b1d72a94a1834e613369ee6146e4b611a273e41066380e8eced18930a8b4eae44d5ae0530192b076645013cade45e17c5c1414b7fb1c846f9f434821192a548a956b8986b625ca8d0ccc81aa7890b70219a45e39f449a5c02686269c0e8d8821e229766887041107eeabcd28a48fba21ea50fe8cb011e8213d2c3d194a80988f68cdd2f46221a1a23756c4a6850472aaa317cb8d74737b0a678d0ca072395c9a607b7d41eaaaca5b22300f0fb60d415815da9908ad2f835fb6b6f94ebe416bc820c7230f8a002cded0066a908067ba3b00e7790228f41694950c8c6b8b36bc5f6de0f84f9dca71d98f09c1a17688731023c5851b2bead1794687706689862da7345be8a20e91dc6f68c3fbff51befda142065594c99494b07666b2faf8db99d101fe89380b6c79517edc51ac68c096319101bcc950a94d6682900d1c840bb4929e684ab2e3c536b774e86d2d4efa2d453d9e19ea12061e781fa3c55f481b0a431afb7d96035b7e423f184bb37840e1553988572661c9acec0853e5078c9dc8202bde9de374cac76952a026194023141843160aa0001a3ae680c81b6e267f97cda41175b1ed608258543854871b080e3b4e606c442ea06a490ce7274acef6769ea9d43841802939a5694304a66ed89cd6b9eedf045ee625207665f6035944e69838c1004b1dc17b141ad9aecbfe1f50e90121e31511e1f503656b03e6af9dda28115e2656b3daf3186ad04bc6a49995dc62b878ef161a813a760d81ca2a0443dde52c340f725e670d161237d0e33a6f4ecb0a4eac948dcc56da17d547645918ff3966daa1ef032ca2a58c03bdbf8c3eb92264e9fd2f79d915646097ffc07e6db40fc011e6ad75d1c720b97de154bc255c48c199ee34a7b0dfe41614f2d243f79d52d8aea9007457a0a26e3568bede6e01ed1b15181c793040c958264bf1ba84ce83c03a10ec94f1620bcb896442d38a6b00fdbc69a3bf54f06953a129a612be25dc08b0a1e70170db56185fe70118918398ee1d19eea8caa188002ef6b5a33a9b7428d075a3c42dddae1734cb52b69bbfb7015c2b25bd6c903bcbd172bbefe97489836d77b58c621e03d7bb007f717f09d61624af3beaaa857cc39c50738672cbe278fad6d113504315e735e2765bf0034fd5a8398d8aecef69026bd9b9e574e121b674e33290124bd661040f5b720bcf8ed8105bd03d170682e9a1070a01c7f50a13c1586e63987988ffab6f6e8a576034205f7b6163109009ba091ba281d0a03604f38118c54202928d351fab1e59d1986e3a9692d0cf0f5f9496798ed06aa276b8bb1adb8273f8eeb4d3d8b07166cd6abd92111ee6940faa73fe63379672b2c1176a93906d9cbc8d3556bcace402f7feb78ba0b7630e7124171be778a79f1bfd9a73e5d54581778c6f9d43f675a6e6260c4a079345618d298ea1aa70b7d5c6d3ce2c357ffd4bb4f1e96abc6daba12b1f846adcfc43ddc182aa6384bb633803c10732bf86246866a774373304ba624c0c1bcd8acee10014e6dc3bcbb30631f83e3c3c74ead7c6e6e87fe698758c7cfd63ec133dc07a8dd8e4d87b2a1f2d0595948bb8139c77292a999eae0e60009c66a4fa71fc7f6642a6fb84e2b2a045bf3d483166e98783f764b6cbb03832dc963f229e569793ff85ed24f7a3af194ec4289e0885eb0612f51516a5a52647d20bf5d5caf07ad7b5172c91add1530a1093f2e9269f1f62a6950b343f55cceb22e7895303eb8fdfe1bff0462d0540181c90c8bfc54d65aa9b241eb52eb77a7a2b4c4552404a7828254be8e8d6e93cd9d0dacee0f458c6c3729b38906610f216e109af542d9a53f9ec8b64cc8152103253f9e86ebdb3bb9e32389503d90f612fb5a0d13f2e10f73187645f1c6875225e621bc07149c700841a6805a14dddf669627b87ef89832e40e95d96eadd3cc3dc22d4aff5ffd12b2293123126d3618a190dfa9cb4ce1a1b7b94a42682df2910ae145b68899333eb819dd2febe237a5a11f14db04c66a9d2ff3dfc6482d9619b7fc2ab66c227d0f54e6bf50566e1afe06b482025369a27eda53d6dc361dd74ce9729d0131a72c9b54d8c83e6eac38adfa8aa5aeb828305430a5c417f678bb038017774f12fbc02d8628259d39b4c4f280a8aaa1feaae254e3b3dc0412f824d499011dfe30ae45098b245454b470ec1c868f06011e8f1d6cd804143b254a7e9cbd2be0162a6afb356b4406cc13be32b317d84058993d7ad68cf11fe8d4215938868954ec0c6535f8e7d3502c61ca3b8b4ea310b9639e4b961d2c5c7130ab26d95fbd0eda8a6e1636f37aaebb418c98e9ccd744a8f8d4d0c84f639dffd9eef3fcd63da04ca9895e385ed087537c32b80ee57432b38d4005449f11c5c9291da2476de5e3a1ebd182f26b363a7e6036dc5346df00cd36c42e003039a32141484110539272da9d8c4571ab37467b6c16ea05aab41b5c0ad57169bc752e3d113e6c2821eb98bf4ad8c6db99c325acad8b66432fdbf4694ddac60d1c72ea0762143bed5eca2dc44ef7b6a2f632ced9da7bc490054ca98713ce7a0f79b62b49711578ca15b8ac189084d92dd29c223406d6881cb1096f9018b628c0ba41800b4bbcc69e0dc8116bcaac966da24f75470e085c1670ef90c974d3a9cb439c4d2b3bb5155cbd7255cb7fd063b90d412019629a0ae0c6704aa07df18edbcee39b2ab93a07272ea1519cd594138c71f4a1ea0a44017656018b321d31aa3b87a6523dee4fc9db6620001ed391153130307f729ca512b5248f3d26125df95f343f52b20d0b769933d68d88abc01a672c1fce39a18ae167b4e5af9182e340e4aef51206b5cf453e836be352bd0cb64195680c7853bed4aef5fbd6792dc026af04531426d4d6c76589e688926684db9c6ecc0a45d64217948b3bbc24aded9ede724997d4116b81ae705823cbb8bcc06071225d997251ec6f61183f3a443984045b9f66dec04b856c151b3a03888db46ae23a05cc28da303ea8072137669eaae629fe5be5cb881aa7c2cf3eaf9970234841b28db234f70299b3011455352b8e1c35381e276991591b392d7fdf6a0e9c3286e6c1108379615c3576f8d307eac660a375e63617f2cbe89230f1840f7c6ffeac968033a37edf91704f7abed5c2a5cf1592521ef45e8ee14aae2054e8757e9de29ccafb60b5f5a196fea3492a6470e037bbd8832a0a41b6c04be45b49a2d2fdaa5a5adae85dfc424736d493a286b88a9f390c483c439be38dbbbee81934cd95827ac095583efe1bed7685a6af99af855d51f6424816cdf20c90e82f97ce08fd0b0fa0a2c580a5993723977064207bd285b59a30efe807741d5eaeb5518d8a25afdd78d215770592336239034d8ac06c57320b052690b42bfeca03e96257ca2c822eaab1182938478384df1c55902d8871bd8282a83219301148888f7cb53b30700574a629dd19215600247209073347b28a1ecf1d4718b57aa44d33e489742f8d46ff042a06886d903040700ca5ad1974206f1d6410e6fc5c6e003736753a64edb257e605702560220339b852fb215d15e7f5730d16e5c726720980b95ee8b52d9cc4014e967f30f99c4586857b03d65b8dbc784d5658aa3c2bf49a69f46c68506aadf0ebc704b0607c70cbb17cadfb4b813ba31b4a6cbba980accf43a47bb447fd8aca5736a06ff55669f78255a01f926dd8f1b6ecc9d8b3d6e1132a38a82805dc8307f0a55b50cf66ac0ac37738c349b23083a31e87723a67aa7f609538c290a093253ec49a3e62cb3ba9280ec0bad938add58144209417f90986fbce707556e74d45ddb6efadfc01f42f2c48ce8f3bf9a42e86b364e2ba7ec96ec8a2b1ebcf545e9ae165aeb3d8fee7dd35c9f8296557716f7b380fd9a4c61c01d31940b0db13515a7630dbb0718c056e2795d4129245d2ebf1234c0064ead14f193483dfa03eb0d7f23397b3c227d837294375f50c6fc85b4ae10b7973d496d33f90283ab59b8f1b0af63c5c0df11aa5a53f2ea0bd0b02fc0a503ddfe6130969c26a8d901c26d454be6844fc102cc2c219c14d67116d690c7e4fd4786d8329218aab9197c6f7e1178936b9d976b8f05745d96bf85fbd23c0c95453d2e4f77fea503576a61f548b41bb48961361e815105c133fe67cc627c8f6e5a1df8775800070e8512e3078478fd28987e59a09e9980697fd9d0e03b874b564bb8d541e2410be2e7e8c3ef90cbcf6fd29878f28efd2b68ad391b6ce0d66b8516d42d9d26963c21bd829fdabed390e20e33a87fe4a45e104a55cbe677748b85afb5007295416a0903a75264b9d664ef2a5ff7b9f6245b4a951e5fb7da14dffbb9139bc82d8dcdc568160ad2dcdd8ad76b9058b0a756ca452f7cb3dc4bde71035335cb328d0f95170e2bbb054fe5c39a693610a18cbdbf8e18a1235908d48e118a12638d40bbd502cfbd7bcc65909271590caaa6f5a1d28de6355f80de76e7abd78bb104da6c79f6d8bda992a0eb338cc571d5f1a8571f98338eaf08cb9bee772d25443d07ae28169131a4c40909ce90e98c42408b4b3d4b9c56dc8f1aa4032eef0ffb01b79bb90b07b7db4d70c24722d9fcd149103cba6e6f4aa2d830e94b4ff35b8e33b9f33cb836b4f075578c9a82d147032a0a9f857d691c8e4246e3ce7e46c84671ac18742f182c59d931a461b75297c0a48204c633c3775e5cc6f1fa4845c8b874e0f732045c4eb13ae588cdb46b318826df8c16cd4de54b98c22147f0cbc6780c13e64e30dddb6f938a9a31ed23d15c6ac22334d05bda7f3e78f1b5c4b90e6f1c715840c3e9ea8d4e369c89fd117f8d3218f65585ad37dd00453b8d21bde6856fdfade98444019d08435a8d6dbe32d5749d1f3b8f45b73177203102759a4212ee53b299e2ad2424f4406f6624f32359f369ad9e82d20913b2a0f8fa0ee3aea481ebecc3efdb104a1054bbb155e2e6e1a9f8c0d90cf39653e85de808f3a07b3e0cd8bc27c62e00a2cfeed58e710bdc0bd49b779ed1f9c0e7f07fdb244930d0b393728e15013798d0454f411917ba961ad9f745d35150c62395c1127f9a00366613abc866571830ea7b216ef6a074c671f7c625dd75616dc385a9a6ab5e928dd8e37c8e2fb267456489f0c5bdfcb6b972b1c4a1ee730144a3aaaeb6d9b0bb1bbbb789aeb79bd02e05b7a8b694a92b672c945c4284abc04e625b6863b4580258b56840c51884643d46e79b05a08f627659eee69719100f65f6dc442304fad8045242370532d8c1b6edb95043aed7a7994677ee4ef6fbe2d584991182a65f4211ad3eaae8b32ba943c35c37da1751d23f2000c94a97ef6e6916bff9b9fc83d347212a0c8b13950d090dead65c4276f1321c0ade4e2212448ff8ace264b10ad07ef513bde0f76e621cf3ecb3419fa2935e49ec01de01b515dfa0f78d9725497454c783527755f3bdfe1e63ab0e2e3ade7c3fd6698dd04c681e01dbaa839fed4a54686a78b169a9fbfeb85777afb835bfd3a72ac7b325e7aca350d2b725e36aba39a142b26dacf38741812e5c5816719554913798999fa6ccf3171d45cf827dbb782dbb2ba4d620bfd3e6722fa190a5c2e0596a34dcfaa01a5508d2916b7d729194c8e0157503a1b1c7998c76f848c83ceb3611d4069aa99dfc3759dd37d2e264bb23ee04636a5dac1588c0c27204cd0b0c8943469a81a802e03e616e1dcc43e002c8d6b848e6f091267ad6faf08db6eba63191a1dbb24a3dc3b19d98a432adea1a4c2c12c19f2736f6f41c61f56cc2c2e4e16b9cfc6e83fedb9c8e12d29686e3a6758d1c17b9fa730392ed9783d0a3dc5c4425db7ace6486c5d9f794ee0ef4cb8071c00a1b124ea5fec3b68aa3955087451ce0a906852642b7a54173c780e38664a54b24ba3e8ddca5a75a9285e1231912df1fc959f43cdc103e4d2996fe18a861dad300493cfaad5631050cfa46e23787ff588e4174ad6a2be689679aa494eb0875fd6f2c5a0fe5b711186bc35b6a9130e733f50ebfd321d656c4a57d534e614b38f82705bfbf648a1c2f45ff8842159cf5807f1c7bf610c59f7a462f59f8af54711db91b83f59bd42a1d6a524f28a8117adbc16e7d9c82a5d3803eda112597074ed39d92ffa2220c7da87f687137028e59f73247f98e0df016a7c98623049c3b6fd2f4fdb3e472060016097e378592ccf95fc1c4423e2881e2ce704c5093e55760d61e1099463bcd49b6c726c52c87c8e4df11702dc61df35515f422f976ed7cac2375e825fa49aca1f92c68e1d1d255c1a311d3c2d13d352351d7c2eb517ea1ea85388e2bf88ead10e7b500c46b2d25f5bc956a68cf64801eb82d20a7fe6ad53815320e9ea1297ae3faaac96262eabb9c70cc05ed88cf2b7d18be78001b6037e3888a565346cd921411b30b8211e5d6746e121948b88f6d077090c2ce125326f1f768d18ed3ee934dd516381ac48e2cb8bcee8a79357e78470e2a03c2a4217cc5ec70eb17458199a708b5027f22dfaf3577b1db207adc747bd37324bd22878b080c0c9e32507ed8c91cb2bc2ad5e1688e2ff8844d9c5130079a35c4e52ecff14f413797c1c8cb60239a6c69e65788dc067b8f8680828fe61d9d03c2807986606b0b0fb1ee1b41ebbe845dc4761f1be69278461c8452a7dde89c0f99d7f7a3a8021571d8cc321afa6ce354d9b66e8b224959102ff8837a028cb0a8efcbc76d95e933a2db87970eb687025d8424826c1200bf43f4bb41383a964cb37886d8a1cd9ab5e236686ce6c798d9d7d9d3aa0d05b504dfc7ce4f016dd4d43b7dd15711f8aecd46cad7a078038c4d9125a0bdd34374c810335b1a48b8a583099fa2c983b9c58252f215ea86f261b4950307bd89c1b3abb68da0ae0ac5334c984ad2837dfc907fbcc590457d8fa2759aeaecf61868b8a0e84af8c13d05fa83bb07f0e9ce24fc0a012278c2a6c4db01e27def98be0239c67c76c714a0f73cacf6926b67a46902767852bf17892d77a770af98f85979641c712ed40db59aee4002b7feae06e16bebfa1e17848bb8f7acca8590a72b3a9c183c0bd6c85481424d53d2bc2c6ad8905329f337948ad66e151ea2ec6ecb9499a811d86c888c93ea2d47da5d7e885f1ef494434487297450f126b27f75eb716c274f9c8cb6415a089f4e60961dd38799253987ba8116fb40b03b102318d46d6dc9912427967b2d08f21df21518afbd45e279e1e0f129eccda9a0a57833aa67559aaa6581238e974b566c23060ce7ddeaef7a25e55215237637799256093f4113810b3ef768570b05e9785c1f63421b8de6ae69d1023ffd8f0b9351f1adfc69af223f29136a55c190225948a9509ca8e2aeb3a23bdae9f9407f0b49aa71f253ec65f0f1923c1e88ed86ad2a6c1771adfc96187f9707a25ec954545e4425375d04e57c52ad450702eeabf108c4fcf0275ee1f077debc7411566d214a1ae38fcfcb2fa1db348330eee2f5ca51791fbb1978bef9d280474a5f746309706427e65eac1f2848c885139d8046d26903fc614b5b4cf9722895d4051a464d67e57ea93d1209d5c07b4abfcaa8150c33d3346dd031f60100f2cd3e123cf6c31a4ebbab085367d3779cb5c0f7699dd81e1cb98b882232f193c434c71174e62cbb7438d2b087ee35df86bc3dd97b6944c912c017116ec6d22c4eac6287fe7ebe8af597ddd01fb5d9814777562228a54af1316309b3d350d74fbaeebf90ac9e866dca21e2bafec1dff340473c30def94b973a23467c83f57a66685136b05c405daca2bb4ffd0adc45b2187db71309944c408a00406d38ba38098d9939e2a3b9a0fa60ee7bdb61476a5a432c6a201ccfe6df581b782eb45e52d4b2b226e021ab8583ca2c08706ce6a161cb1a943c927bce3aaa344d94279c301674c7b567a0154d423eea6f2995a81a456e7e07ac3c6d863bc07eff48459b42eebcda0f8c63f3534c19bd2229530e0b01c151101a55fd771730c8a4a6617d074a1c1a1e34f0e8f2933e9290ee2a01e48c3d082090ed6d4a2341b8227bb6feeacd14fb715c6a264c546778b56c539910fb58840b2e2e7c3a8e7274bd95913697382cb194576842352b14c7788f115287a03ca70674d0ca9d7febc1462d462b0fb7868a3a2c5c88f5eec5f557506dfe2882187eeb2d2b6edd7ac9e75bfed0f65959e0cd6b3b853298fb61a1eb5144be588feecce687b1d727a0865f123e65a07df538a3a8efb7a9302be5498fd139f7261d125592b6aaaf12752f715abb6eb305274accecb05b36afc8416a091c5a4bbff9bb6e864eacfea71aa3578b8724d89fc75914f8ea66bfaabcbbc0cd82bf2a5e426378ac53115e157cc34d7f6887edbff81acaf99e7931b3cb799561b1b33933f0d025eceed1a32b72003c47a6746464defdaca327d0500cbf868ff33dde550456cfed8eec39010619bd052d5c7e56a39ec8c2792c32611ef20c1ee0d4ab004887e92675be934092a8b5e8053de63aeb0804e4be3eb4ed355781e8a91e160f583fe6140c7a3bb4d90b326f74fdbc8379e9cec6610a5682b396c5a38dda062f81223ad4a68876e44902da0df0a2c4e90d9e524f3d65000a479eb950689a4c490c16fa324ae56920dd5c344a714a2261e5dd48b7a3625f19660345e70325a1cfc84f88c284c379e092d924887949c676ad7b51af47e4d9fcfdeccf9a9fa40aa9cd406122d0112faf8534e0bcf840fcbb4f4603c08f810ea1c1ce03ff494275d8601b211d594bc69324f24def14dd341807078b70df5c2b6c11c7b1f40e69692401854208f73d714cb1ab5a297e1e40b57c636ae795c56b84b7c12e8e191c0c6418aa0170f343b3be5a99ac112c6e61a37daddf55503a3a1aa7cb265f7092d87dbf884a6a24c99abc39c4cf11dbcd1ca5475481426f70b4fb6c5e2bd43b50341ec93aca59bd83eff4ef5c351368a24facade5b857bdac7e1ba731b11253c6413a62e511996e5308a23523f4d9d2ff1e20bf019f96623536f2cbacc4a991e8e33b004cff6dec2710997916981bdcf6ace3550c5ff62161b57c56cd6079586b6a2f5ce72b3f6f0d20e8d7c6b86d28e6b9e009413cea6113faa654b3b5a850dc9b53240833ea474d3b8a786a7ad2015ac11884108b46e8a5386d92a2dda1568fe53003bd5bd7d7f3d4d0984aa6554f094b6147f473f2ea6379f45c8e91072bcebeb608b0de62bed382abd7eadb93b5e17dcbfbeebe65374201e6dfbbac9baefcd2326315d71c315137efd4a362d9502a3b32c013544ae8ce3c7e5dc01072fb30e37ec36248c3acb674ebb46dc709ea991d0758afe31f2225e392c98e3255e087aa0da7060742cfd61f5e8bdc6df1b9ab17dc0fdbab6824804c920debfd3c29c410845902fd039170cd90ba7b4a0c4881e034c90532c5101a4a4a1fa1a0d1f81966309f8142d433f4e119a038472a9a6bd7e59a2e6a3ff840975ef6f4cbc4cf811574ccc72001990e956552a689efa92161db66d0cc02a9997af6d42958f8f404b34e83f8164a058cf99e434f201d5376740c55e8609195cef970608beae38273252027f44b1926891d9df42cf8406ee4b5eb090571229630a2125e81b835301e0500bcddff6d43171f2f1db35552caac1c33bc078701abf173afea254d3e38bb1ba63b46b41ff5702e1a34b3cae284eb09166a4bbc568e9cd97e3e0cbe4af04532c592a2175a9da7c386922086629042804834bb870774bd7f7b7e8b81cf4bd2d5cbd77420bd63f6dd3e056081d4949d708511c56315b2e920ea9e4a9d7f51c74fa5a4e93e3df12cbaf55e77f38d86fa16ad256e6ff6aeafe32ac5b4cd47155344d8979fe588ff8a1ce922864ac006b3700cdd4d5bff73e9774d864a366c2750318668da7f6f2e9145e7d5970c42233d35d5fd659b2060acdea3685ff7182982fff92a1c005bc7c65c705e389917a97823f046f91224b64017212833ab645b2cae4a24b55103690b9fe1c6d976f6251fc83c2b142c819891f3ddb025440dce853e794bad4e25a54d2745b594329bd899cf71133feeae951e78209c0fcc3c81f5dd2887cabb6200642cb35113d81efba83e15ed13adc4a0e65d0782ce2bc34ca31e15ef08ce798a18694c1c7ab482fa193a246a5db9137920c518ae314e7266063bd6451540096cd65655b12d2a632de710426b9516829adebb1f4a43e23c8f7b216667bd61dd7c47f956d744ed88fbdd9fd8d63c3a671d3f05aca5db5378d1e463cc7a37c356da70abff47e37ebdc358b3917d12797c174b7b288276d43ba8b989cf2cefbbc236a8e8938d0aa0c04dd84df96de1e93b3bdc2b8fd2337d496df7ecb1fef4eccb243dd3d9e5bf2fad2d98baf64cbb591d7b76af96693662a6aacf9d134990c7de2473d34fe8de84d0a9bb547e62bc873bd364408433d209d9798c744c858c5f82769b09b7fe8b90b4bc3f60e781327f35677bd9c5a80ab079a64fd7a6493ed67e4d4055f56dc3887312feda1ab7873e493a7c4d46795a5f6a05156d99bd213122a5f5a4dc613a04bfd1af1eb33809b875a4a48b85f026ac647ad1228f2082eb876e06eae99e07b878acfd74b371fe4b7cb0e4469e66ea55a713a763e5e5318a0f5e25eae3fa51f1564d62b9ca5775daa770dc2bb844405c9f8ba6fefa2b121432aefc6df2c377bde2a93b27d99bf4a981699d271e0bc9cd6595b7e3d1d1924153c52bbd9a123f152a22230055bd5745edd2810846d1a90f6652c506384eb4ade7ff4ddf445db742c113f368e2f2ca8fe7cfcc384ed1181110dcc8b89758212e3ec6e7482841fdcf7efeb55e785371df8a03870b1a83b3df38c7c2803acc8f4533142de07d117367f0795d513e71d651e0323d1ca912aa0c5f691f569e085740e84fe60b07c929c6e684be30d32a7532930e9f581f23edb8bcde5373e2987e85ab4fca86210da94832f43a674d7d8e5ecdfbc363612ce69f73aac5bbf67a3978099c8cdf1bb595481de88f73114010e26f65f29d767d6b0127a0c753311811dcb6d38c2e0b6cd7e9dc3dd4fe74e80adac927a6f0f3f0807c5607e4f170f804fab1a375603966233deeb3d86e1aa23ce6484a3e7b541528e728cbc9b8a78724beb15d3c50daa6a200ff8733d5fef6cb1b78afd90652e5ff9e639af408af5b6c4a27921f5d60428463eddc79da95e3d2997d11368974db682b4fa91cf31d441835af7f8346df204bd283abe937ee2b86faae7d8c1663bafde62002b733db01e4477bacc1404aa92fe73780465079c636f53156c28aab70654772a6028d90399b2a1e4a96dae7cae6c11f928c46f8ae66a7b231c429b878884c211a181c951d6f628bdc1e8c76e9e34064e5164ad4156242fa8b6a441bd16d3fb550710b53b69ebb40ac75eeb03687d629925308fa26d118aab9973c01f4762c871b92c4174cbecfc2440aba0ad12ff5ecee559fa9a9b3fdbd4565cfdbf82867c7a0f0e4b67a4cac65b5edfad0e1024508fe3e8839ef7bee821012f7b6a18c7db3ba5833d12456a76d022e73fc1c11bd8e79f0c2318abd5e89b35e0c034af32d12c56edc41c944cc36c5d4310b94d9bef6ef4c45fd5a754ec509ed26f664ae7e92147c249af7c19791f5d294bfc23afd81bbbefe91c0505b5712502c7e05fa3b8cf4395eaf9eab716ebcec9b96898c344cae4b8638f1e37a6861a0deb34618dc0f6989b5e339373dfb2b0f7772f8019e3c2c31ea4389bcccadf278f812a3f3992b61bc5e034091f9e8747a4ff1359146fd02ec1f9d7495f2009188fa475643df2fce0cd2e24e834585f3de16d631e055e82c870ab51a9f388538163b022085c472c53602228e2e022963e97b310de78d5cf73e7836fa1382ac56ca92c1fd364f37c0598acd14ef350c4912bee6c3d98b883f1d799b32da3c650d2892f77b833827bedaa1a94bb3e2597e67d4e5642919dafa07404b2d0357b2f4975415b8bbe501005d3e7a9d968f86924213df70fdaf02a160aae2781fa519bf0e8a673c5e32bc5fa2ec9b11bf965a20e8447f5b28e35fcc7855522f920c804812a0f75df12e3052ecae810a03a24f3e7904f8d4a975042d31d8e46add16e761161cbd8ac07b34c41ef01f640b96cab6c0b3fee4020eb7d47f9f8f78ec1215fcbe62ffb6d9c9d62f302953872c3bd9de390ba4be4fddd71940ee0cc8e559b9a1eb4fd0c60418a693220d8add8ed286781c16b1e72a34468955bea45222fb99113fa1d03e02ba2d85440b96e1e6a1c600fb15c70a24c02d655eca7d6e51352972ceaa1abe79049d24078a5a839fdfb60bc921d91a15dd762417a25f6fe576e28121b24c94780cdcc459ef11d05fe87cdce8f008de3ecfcda8ae978b41486c6c30d4293b69848bb6c16fc7b9cccb40bd9f816e4c03f193845797a8cc9900fa3225fa77eea1dcb2ca594e5dc5c603a43214f88c1e68900da1d5f017a6c92d9014501a81914b57ff7081816c70c2ab8deb437a5d2ab366432aeb085940298d14b1e920b3ec32f8d10e9d6d991d07a0d4d2b6d01e46d9854d51fe93808bf5e462d6f564a3d240ba6c007bf2f429cea22887f41665485000b6f7c5acd9143e64d10cb3850f8dcb8dfa8b2cb606b82bddbd1bfb823274eb8a1ebce004d4308f24804a0f8e72b6febb7e976067d09a5ce27f98518706b640815018a16be417968e9506ebfe070d72a0a0c833f076a58a362361d44953a0b7b178a61f3af6b9f4e1b55790bd32b6ee861ef02c53854cf04a0ee5d38b0359852616e7c9daa38db5633a3935cae460d7d25cf494dba7e09fab753dfe7f8f5c727d9651f916afdcd59e77699763d040289740dbcee025a2c53b9938057d6f6923717bf65da3613a4efb9184fb8779f6531e17ab9b13bb9b18844a2242092ddd076d3ee0ec287ff738ad785c1f943f68119873d02cc3f25ee16b8f578e1d630a416bb4e259101463d055356b093f5266b1a0c3f9d643135cbb2d07ba5dbba99a56ce69627ed7da22cfbca4216f79fd63220d135c6b6f5ce12e7cc066ac79bfbc210e8d4cb2e4f5bc56fc37ade5a7868b7f2e1b24ad851fd60c523a6d442ed5bf659b846ca59753fe6038f769b04b55a66833262565669a4d23506df97fd1105c4d4ea0553027eb836bee0a6841cc95e51f862f8b7ecf312c71add403c5ebc5c8bb9d0bac1aaaf23c6cc911e20eb21fa1a55c894fbd8356136982e95fe89ffa68e866c508081d9c7e14bbfef695ff8fac7257869a48fa1709fab75fa6f65f7773e7b8a99ed82795973b7d74fd78eace3dfb1af54e766603f2c16689f5af706068b9591c98d4a9ce6e559c47e647711bdfe1165b0dec94276c6300baf90cb0418c02d9c86a3ae19474db1ce57ca8d64f9e20bf9d60a686f983581aa09522538807709f91896fd8128e219ea7f2949b90da1c66288da064f11379eedde0415b5eed4d66e75b05dd7a672ff30b3a90ee24b880ca24a3216b99b4bac7898aca54aadc23013ccd36f76ff46e9ea9324c615d033a9543289206fcac8e13dc6e1aaeef833c68a7e221e1141787e9e0a2c9b298cc882b25b8724c6129a710905f151a425873ea89cedad980f3561d11063979646e932363369c3da6e6c6533c3bfc7dc5948efc42ddde4199b39cd5d545d9593582f9c9cbbe31c45c17d0694ac45f604fc22a6c95c4dc865339ea8216cdc24d19237d708920cade34c465723fed125511238ee03f19155a41e38041c161ca0cb2460a81185f795a7d0bb1b27f2748465327f9613dca3aad4393016d62e6948062da96e57477e3d8a503cdbcae8cf2dddb27387aee89ab409035d0c4813702dc6ceedde7f3dc2d40735cad4b77f0b11efc22fc557f69de3ef52e1c41387b70c88e4622722997bb01ff3503304d3b3df6a61f9c103c082b90f8be48d929047feaa0516a272b560f25a0b71f26841d4aec77a287bdd26a512d11406f802fda2bb1c7036be6ec54541421d0b2cc7eb969183e93f39a5b31e0af0ffcdf41aa1b458a6c1201b141dd348fd2f0e9922d46819d0fe2b1f4aec1ea60d2014234e77ba1235b91428665c43774381d7129f5f68e564c2d47c0288c6e4b10d61ec8b43559f1ce326ef910878c1672154dbca404c1c6616750cd51a3db2d476383397f21d50a3372228320b284919b0968a772f31be90db3fc76c522d3ede0d506634e7a4613e8e651fe256caef546c89c07502bc137a6af3d6462ca3c2c8eb6ed5de46af3cd78a13db3f25b1237b53d190d0d9332eb331db7d625e15c9d46d03f70c3fd089685db8ddadc410584039049080d53222650d4a94829c7c61d9482e0cc460c8c6a051545b9e4306ca0567ad85092b1475c00cefc1020fcd3999c27f77c28d872fea4111b1cc9991c2e5baa6ac096e12d1f5404179377d2952fc690785d3e11aefe140ddffbf1150fdd6a77abf3a0c406a78b4ddda59838bdf46f7bb2001ee5c8b5c691418c4646d66eb8dea82a41ab039e04bb4b07ed152282e6848b2870ed52aa05d8e76c82fed6bb9f997881c9f3345ce7849e7733cff7a11dd66b12097dfde8122b7dfa6e8d205fa2c158bafe58befaad25dec98e8eb3cc08d987e532cb1aaf9797b77299e12cb3c9ac38d7f5f21e299bc32b3d0a0f5f505eb0b7412fef9e85a687b4874003fdbbec7649239eb9ac9ea1539ab3b8138f269d597a1a6ae8bbfeec200a3ccdd01fde61e14047b5a97768c784d57420d1f7eb19aa1cb66ac2bfbb86ae15de7a90ebcd87bc72a7289043a8a2ac72dda01bc7a963f0af39aa961cbbe59a0ce008edf4cb5bbea899187ec940eef237f1caddc94dec495d1ff24a2342cd157c9e0dd00d03f1067c4b40dde51f61c4f739d98a87ffb12d7b5b753ceb79738b50a8bec3918fb4f3184177e0fb780a9dea246ae74401444ac8c7c88b613da340ae8cf76c7c524d075b607c06f62b8acb37b58f24aafcc8fe654f66fafc27e1f092d2c2ffae84e9a445a42f7fd1b92be1717c9dcfe649db1060a5e72da08796fad3949b978e3b8aec618b9285c2c416912f7f8fc25c444a1da391ba1670b0188f458e93d6668b12009e7d9acc699324502b3e5546d55371c84f76fdf88e98c87950e2663662b237ff5b36213141dbf1ec0e3b67930a9bdf8e99f3971dab2661d0f4bac6f0992406536e9d97edf4560e000271e9eabce3fc0252efe541a8d0b2aaadde49a45e3015b00d28c640ab305be0cea1924a052a14eb2d5644413d9840a89306fe23f38967f6339a23f60ce8d1d8c805249db92064e80e641c1b14121c0ae897b1c98d14215096f7513ecb0bb5e76e681f2ca96975894b4545c58d6b4dcc6bb52c2ed4ef89de7a816741f66eb47d6bfa59b9b5fdc06f494d25f2650b223f49ade5cfbc91239c403fda50136e4315bd4954e52d5c8df688a3a89f0df009a90348fc871e3c2d4d80efe748022f7680dcb669d1544ab00b2cb921ec6a3db1ede956c362a4f155247f8b29d2f2cbdff255facf1648093c06ed9a1ac000937648bddb20d9267c22df95b8d2d2d3af7a8fb1e01c99c52f320bf24c2e3e247a254c199464cb1251b88fa4f34336b5d506bcf3261e0214dea2b16c0f0f39a317c86b61a67c4ae7a1567cd48545dd6067a70e5d6c672869db7199f73736f51dfa5605f1a6b1c88328fd32e964b5fbd0aef6eb7b8ba51aa53773703aa0e8a447afa203fe8ec4d799dee3a22612b301ab441b5c9bb01d0e147274a7177b14aed661a8e9bf971a193402b692a9533bbf25558ed815ea76d19199cc9807512262608a39cc9d99f4b6220a5b55a6712046a742823e07c9a37c4017175af3a3066570f20113affd594af79622cdd431071d459d0055ac0bc2312aae8e3106ef4ac907218e95ccbd5c9e9e0fd1501bd4ad12b5ed0b74106535091eda74e44f1c4325dfb19679c8b521900f9fd2b6f9cfaf18a7b4f6ef4b7f9d8fa3dea6a68bebe4251324432bb74d9c2e1612f3ea339429f922488d0f4cee477e34c25b179f02df073f2b8948ed6f21a27d4220d0e147bd371db9ec50be27c6198b28cca701316193234d7350694b3348a7c91509dfa49641ee7c2cab9fe4ec0d34cb24cd18e8f383376f07692061eddbe33add07c91a388c88e82e640ff96b29be4869d78a8ff196949715c8d7f73017a781aabb082165f67489e68fa385ac4c412b1ad1a31dbb284db7ad4c83b90122434a668ece2e4986c5771334faf2b09e621d2df35010b295053c13aabb77333fcf9ded4c15a97cc03454bb2a3816a9038f541f1b0badfc621cd490043acc1bc5592050c2927476caef233fb3ec2f7999bd0d331c600add460cefaf4b6b32fedc58e1cc29214c1077f47bc9167aeb16039cd812db2b1895ebe878d856a1c6b80ba0cef8af7bcd1bdb046aadfbf8fed8486b84104236217befbd775d0c9c0bbf0b9a96850b9765cb6205ccb2832acb0c1e4e0f1b15dddd3e5f2efa22c014a1449f0a4dd3342352984cc1f403196ce1454c3bae421e7001175690396207333889694584d19af6258b526b37314dd3b83cb958e1eab008d183c54b8765051907af303b186bc95980842272bd40c7c7e522ca6ab8d18e85f6c50814b4a61521466bdad4ae1d8b2ce8148667185094502510b90edb69f9254b173da3e59723606831088c0f66a6fdced8bd77d11d3ebfe471e4d5f8f60a10dfc36ec65858dbc65a51a9982b1d1149aa27885079675d807c03be5c996a56cb2f57b468f901b11a116ded1722a0da6a316b6d069b0045efa7e517226a68dcf20b112b68f115448bb017efbd37680950f4ee71d58e786d2db80514bda654a3947ad9e5ab6776641be72cf704c9fe0aa1b3d685c25eacb5563b81286954763cb7b2a87e85a424a79b5ba0324fc5a808a9a79a3a9b097b3c8f0cf9b842eeedd1ec7a20485d6718f2d6ce9aad943bacadb48f46a0a7b3e5671721992d7f44496859250f4a5482c440275f93524a0f05d27b97524a2ff19105a7ba21a648608255b541ae04921e4877d42bc4be9ebea802d1a52f303003c33d7cbe08a1a6295df9003fad2dbacda0cdae9d9a853d09d0b6084b421d30dbb4cdb099833efb9e04485b84cd11727e245157f71d4877d867b741e88bec3ca1c37487c85387d01729a03302145bdd2dbac352987c80c43d8f7be61e21f4f968b6cd43a06c4977ccb992bfef3a7aebdf821340db126a06312780b725d40c607a02e0dbb0965d5ba9fc2244126165ea26adb656218210c20594d27aef4d0aacb537cbbe0891d42d335f9ed45c2dca172b611a6cf9c5ca96bed2616737d36173ef5647b451a8adc95f869d5d91363ec237bbe8126bdfd7b04848d8d9c3fb0016fafe49ee8f72daa3b00e57397388f8b3ff04cebb605ec64c6930a9edbf3c3db5fc62454d83d0f2cbd352bb66481ed3075805bcd6e6a3daf643c0a44a44ab743d3f6a9b362dc2cc21efea9dee563a21e408a005c301c0cd8b95c1af6aa87c3e1ecfd5e970aded06839a2af32e6771cda89d74e658b569d372e690563af912ad54d7a5a64ddd238436b5f62f55d4f4ade451bb53414a20fa24461a9038459b852a20b56d6aebc1b8a09b219e7a310b09a0a7d0f18928514500786f63335d9f00f0bebe8ea94248480c810330558071f26283587d95aa42483d38fdc08987324874a183587d455385909ebc80850c4e346591d2265665165343f020039b150c0144acbeaea950a63c6181e2d215cc37a4a7b54f8d66f6620bd6535142653c549849dda469531fd5ee09bb6611a9b7f9a69e5bee11f23980b676293474aa3115a2323f7300e5172b52dad593be6e1377a6b5d14caa99bdd76655a36d67968947d3687612ae6df628ec48d7f3435c3dab883857361367146acb18a663b2b0456154409a45db626553d9502119a34d30307182c31c61767d53cb8e6110aa9162e2ec23b55568f10328d4ce8e43146a6bf5a73291da042217d8c00947e608d34a79647496ee10ef93d8687a299be69ef9a25af351ed2b27b5183cd4a40c90dd93dd67f4778d1455d4f4cd47b5eb2b129bd4361f715dc2ec9eac6bd6f4594ba1d48346b2339ba1fb42913b7e57c4dde37e7fbf851c0dc9a3b31528a9a9d1dc6e441b2a8b1dfa0322a592e49db7f6a844b1b79c04379d499f0ef213b2d39bf7a27ad11ac9a9a4a43ebae9edb51e79bd0d49a1e98d48682a81ea8fb2b62245627f9409d1401bd93022a1a704aa379a6d9a360029849a6dddb6968f0402431a12681ec99b36892f4f505f9ec0a491727256e860c592154d7ade524aabe75591c6dafb7d5588c9324da5aa0206186fab55155338ae03c12aa278dec76255c144a55adddc54f10208b27070c494717383d36a89f922474c183166c43881e385882a50e61165307951d884aac1184fb12f62d2ba286ce29e22236b88344d31fb45ec1e292643c94382f5c7d62bb024b9e10a1112c8472309707e4e3a91e85c218c30c208238c30c200ef6b96364bfa43459582424de9ec48a1b323050f3b5d86a081955de0f84ce1f84cd11b8ca0946691cd29597dc09873ce3955840c65c59e14d8ab79f9d138029c979fd3c74a36dd413f7984b74902cdfb6c014a3b25ad36dba66a3926f4499d9a50ea8e17504e0a65a9149d7c7954c8d21f7bb92529a9e5d11550b4406c00e5cc313fffb223e8e44bdc8a10c127a2505dad0d528856ba43d74a85e84aa5f0997492d44daa3ff81be87b1b4aa09861e95aeb052381f08bd418ce630bb19b547fea90f7cd564dd59c9c0014ad1a275d675663d76c4f5a6e183061a4b484b912e687303bf8b897e3c22c8569a2691aee3a2ad050b1a65b73db36cef3a800438514154b503104155154aa1508520103153850e1c2cd1463dcdcdce0e04c2135c59497ce4a9f29e713357af8d10107ddcf1350aec44c1183450c0d625020e605f9da124d97c415de540f0a52a04b50fcc02546d3f418cdb64d9ea410e46a9a31fc252524c4f09b664cbb18d44304e79e2abb088d69f814d0f0b56ff832263f22db89289315f21185d14b307532a1f5d6036194de4617a0b86afa39955ddcb5428a0627a4534f40f037efbedd68b68a26a05741ac13d11c16803fe779275285744e87868282705a17c19c2ce58f772e07e356c6c943f3f2673ef3be1b1f20a769af1c1288de06983598615bc01c454ad8314f3f777cdf7800e9f9ae5df60c7bbef7a030fa656dabe17e86aed047a4bd02c5f96dc2eef6439225aa80020831a6b882c5ad3c5112049393175210339aadd29e2303f8aef427d0cff028ebee9d0db9397fefad9f5bf625893369cc1a30535cd04049254135719973defa854663775d3ebadd3d6f1888217a2d4472d2010b2b6ee8e1073b34e1800d56d4488541850c3cc4e83b5959435946840a493050a408a962f427084930f4474d9a7e851186a6ec82b3b727201116bc6011e6c9851aa4d181d0078ca8018d0e4f4cf0804d0a3e4c9a4571788071368722b4189c80c8c8707292413935f9c0a631c656e229335369a6d44cb1c9c152150aa2d6071be4d42d09fa23b7602ff407af09437f30fe16e04d4b2f3e885903eab4f4e283962e3e54e124065d5888ed5eac616dda2c1bb2d6621795526ab366b656d7bdf7de8bb55ab156edadad55a378decb6d202b862e8bf7de7bf1d46aa5d99c9752bc58acb5d65a6bad338bf55826ae5ab779f2ab52fef7f273808d2ec2b5d65ac1ae887befb59ff5d3565bb52cbbf766d67ed64f5beda5ad73ce39c1325a9d942b680043da3ecc587d43d05db5586bd7ccecc3bee0bd64f50d01beacb674c7bc5cadd5bb18ac60b4e4bd41d9192a5938c7a16066c0793187fcb1aa6fd5b16eb0ea036fb4cfc3c9bcaee5e9ec7860cdf5f33e21216081d25213dc7bd78e1c0490423c724b061063b96d5eb7510199e8414de744214327c01c2850e680913eb8c20464ddb002500539805c68b26ad9463527204f4b2f5e9ce8ec0b9075050c2f5268f0c2e41a01aa5a7af1f2c2eda2839b056cb5f4d2458bfb04e2b4f4d2a58b1890d5d24b97233427106ce9a5cb0f2e6c651078853b1cdcf2308843a907ce2e3780202d9374d305052b2f92583b68a96ce004ec02fc6c30b592628667868b0aeaebca70f9a2e08106d705132f8aa69e0d0d940e0a1de8e01b24713bda0d9eb6a032ab0c34e3047f3e300683737504050da101a30525d1b2db1928503c7966a6a080029699826209ddb6336330e6b286057ad84717502097a9d7410f639e173861c3b54052d41357a8d0608398186d52ba8192272d624489418cf680a7d2676f56a368690fc2f589364dc12402d88d4a815a417f148c143543d1543a55852c9326d54985aa5b687daa57b8e0d0df2ddd01eb0fbbaccb7adf2762efdeb9cf87f7794ffe9b591919b4f8a2bd5befdbe7c3f37c9858ee092d9a7bf7f9e0706b13d3f8f84c63fc4496c6acc63260d2f8dae703bb5abbfd7c68308881603a7b8bee2840674ee490b97648337d2d02da5e92f181e51922c65471e2c90cb40013ab55aabb281da595524a2ba594564a6bf530960f92f407a553fe003287fcfc82d0534b691e9240f27248f6687997fce56138a8570355857ad09ffada03aa07edd1833bf79ab1c62d5198c671b9c60ac06759c76df34eed13aa56cce5ec997874c3b944614d494bf593c97bbd74f23ebd4c845aeb8204aaef2c91db351bf1accdaeb5a004aa3d7cd8cfd0886b42a93f47b7b517e986206284c2a05428c903015d377c275425f3498175f56f955519e34fcb2208ca9f69c3a3dbf3446e8b3dda029956c86cd3772a49a0fae982cc51a790e98284d57bf65e9204aaff7cccadd6a5fac905cc98999dbc13d10d54a19fcaf54cc2aed709855f31fdac3593da280e162ed74a062c5c7910c40c1fc8a406210a40da322a87293d2fcf420bf6f32b41b68f7b9b2f87dc2c8e3d3fe4ed8be46d361a5b6c224a3fa315965e7021a9a584c90fd13d799ef616c62058e59a5ae90f7d0587daf6151db6b44761f4c70a62508b4774b42de279dfbd48ed9da81a69ed892df4cd221285d579ebe7eb6b38b73b67ad9f3308ee6d6afba6f5760aa346b814e88e8e48910b88520da5144c768c41d0e5fa61ae2ccb6ac6e60e21f5292c5c025a0a7bf574019cdfc2681dd5b4ab4d9b8bbc6c4e1d98f8f848fbb23b6af85183ad40615edfd0c3228c5aedb68a5c22130611c6e685298c1e07200cb796695a06227bc28083f66c88c2661385bd288c524a4483b28ed9c259c46842b007328d881387a6da2f5496c5143aabf7f296c2b4ec38006b16f145a2bbd86b2b829d4f5b9b45fcd53b30dc56b7c7ab6c555fcb15fad86dc3b4de7a6b3dba4d335ecd8a83168aafd6bcbea0d8eaebf3dd2c6aacdc025b210861c0fbeeaa77abd0fb7da7baf60b2f813c2f7fcae5f343bbadd742d9d389883ab156b482e9b86f436de98e15eb5375b10566f1b256a12a0c4f80bf2cdedea3b6e5c711d150dace42d92cb469d3864b965118ea9b8b3c2815ad516b82d46fd90bb74f347dbfe5d0d4f53d4236edaa47b9604d57fb65d742717bd177ede65202b1be85acf02614b7d78bdb16766f490924de9c6ef53759d4befd7e43ee351fba436667fd3b2becc9ee5d7ea5a25f853d42ee55bf57e59eec3d42bc7fdfb3d68928cd58939403c0c10925f629e23288d4f268156384c2e689501826a24145f6d566a21282481ed6763c4136d0d6e6f934a0ecec98be867a481eb3e727145046e5e0a4ada7025277bf1f767e0d40d232c4bebee6daf20b0226d1961863ee95fbb6693fca1ac9f6a36cc8061a9f8872f89b86b39421dc1ff6442d650862fdf55412681e689e664fb8e3af74c042f8cbe543b40089cf6531083e87cf5dee138430e011f7ac72f83e0806fb5d2eed55dc30f70bc32fe232fe5015e22e0671dcb92c6ed9823147c05ac6168ccbb0663774b20768a7daf685d2f666599659353a3abb0daaa7996633283d047e2e15782d9c61b6708e214361f774e2104e27147625a7b371b9a85ed32c1873849dcf19175def74de85f0f2e9baaecb79d775ac19f988764e2eaaa22be7bc9b5ed7755dd775accb4fc88ea8933371decdf09e30b7f92d0b67addf6613ca04869e5d7d57b7acb95a5b0b8d6ad7db95eed89ecd674d9d5dbc3050293a060b151aaa3f5732ed2e2d8b26c8ea04e30578b3aea14882ae6f7d86b67197c54ac715b68d4d8bf3dc17a436b569e608d935aba66e948872ac6f17ed548b9382aaa99e0fe1e5d3d22ebf8b477404f5978baab8ca5264c68401e3e5f618d2d15a168fe8d05ecf52e52f63cddb343347a681e155616d85e20423ce317d3f5445d7bdf2e684fa738f4190e6db7dbf9973ce39e78d6ade9c7e9f975fb660d8be7977136e1d0e65832bd5876f675b096a07c1607f06ba0e43e3e3bad26191eaece098cebe527d25c059c5e13e68be34b5090c6cd4683fe19e7511b6bae8b29d1dd1d133ebc2561285655fd125fa939d95459894ce70e8ecab2cba9a64ff3218dfde699e175a30b24d42c96dab5b168fe868fcec888ee62e1ed171444710978bf0b56f0ed0f0116ddb193ebeb4606cbff97c6c760a6b5ab660cc1c59ce849d7992d45edb4b35ac65d40d585afbe5a7c75d3a407b96c520dab3214fd96dc6699adedb5c940df15abbd5ee76330861407a7b2fec425c7fe615ed45385f2d8b2a20ddd2aae586291dd432ca0632da49e38e7262e6e6f2f2986bee930b7c65a6a91f10fb0ecbc69af689c64987f65d87431f7a9cb01506d59fec5f38446159d4132e6d8096514f9874675d1496e5ee186b58c31ad630d6f0892ac6586a58c31a16822fce2ed43a9104ad719ce5be779f61097ade621868d35263eddd7c4793b2fe42718536aa6dd8f4144dd05973a151e5a886af1de923da53d33eda56235285705ad7ecb39e57cb7e34a0e875961de4b2681bbfab745cc1aa6971fe8806a9fd59ab85e2949a23606da631aa2dcefe72d1f60de9b238d1b4e87dbebbb87a77343ddfa9f2116d553ea2abdcfdf37bf72e14a7382da52ad10457c3764acd1cda13856951374c75d7f3681a7797691fd79dd338eec3e7ba6b5ccc116ec423aadac479a56f8e0578645b958bbc2cce6ecef9ee66fe46f5d5c16be78e13b6c22fec6e42aec1504af52a9c5e5a15dede42c9a5d34ac0dd26528568bd762d6bed5eae340861c0232bf5696f8546ea8f769c9048fdd14a10caa95e85134cabc2ac59a1f482261449d01b09f0c15082e95538b9b42ab4fd85e2dcd2dabdb00b450935c4ebf9c9c51c6166d1043db978a79d3bae42f5dcb3cf01f85de642f1c8da4a55a20982dcde3e9fb86f9f0f0e4d631ca46b9c2717338726a17454d0ddcb97482765802c43c53aebefcc28483374f2989287087d67b64868121b9dc98f015b5706c832fd33a0285a4e6ca17b84d0c645720449e6a97116ad580f0216607df633a028de8752aa4a8b358bd9835ab417ef03eacf80e2bd98bd6624540c6a27eef74ccf2c8b4825b0ba5e663d14d862dc67d3ae658c6836f88cc82f2b3092a94007ade56704014b5ab0e52288ade5672487154c702d3f23950c0e5ad0b5fc8ce08062e5094f4d0cb288fa5a7e4668a8a087263aa8280f4b6244a165d5f233a2a385104a68c0969f9159c68a173ed8d0a64d8c63b5fc8cb06aa0850f65288d4a3346e5bebb211221b6b3dff7fcb87ddf434469c6b8dfb66d0481eedc91a880d4f84edebb6d7555c8fd0b575df8a93895d377a2aa2a72eabe9cc4c5baaee3be0abb7fa1ea37fc9e85463e32a31f454eabcb3e92a49dba0c7eefb8d8ea5c4ee262aacb46720f0150884dd24edc3bf95120ab92b8d8978da872121703dfe5242ed6d1bea19001b4e8f4fd08120eedc47dffde85aa83e1ea9502e0ea5d4e926662aad952acedd444426c480d584820d9221d61480d63640eea71e1c89d09294685052a43b4d7abbaae23e29d880ed1fea3e87239e9c63827ee44b5022972e22efb8809da29e9c6b8ebb47655b88150067d97f5e7cba32a6309055ec6be8be0ea3f6831094e1f9151f810d5da8beab58397f507cce32a7f72aafbd20498ce8a92dcf4118b8689ae3722e25dcf7e3e88283121c59450c98e14e36ebf21247496a954799c603a29280e8cd484f2c4644219835001a9ef3910c08035ab20a1da48b66951b2e9a224387dc406115708d1dab3d565fd59d17f59d61f714e5dc654585aa4495f5ea231ee45351fd9d6b2589fe52220485d9fa4d547241085a9ebe5972f9e5aa44c188034022f2d8ea04b57a519ebce854a68accb3df5dd97f00d9104a15ddf75375a59a09ee74e44ad53938e18f72e54d2b8ac843c144c739e742d481e48909af6a4596ca1bead9d2f3a42ef112421a6ba66143ece164a60ebd8338a06267d343bcb2848337d730ab666a751be851598294bccd37056305c70e1002be60e664cb0f752a0e8794d5c61028a04228ad8e282271bac012366b334b1059759b5fcc24494b62dbf30914454376716a709e0edf1a55fa2227a58ba9b9f9c2cafe51726a0c816181f30c1a445d0c62a54105dab50166699052af632d62d69bfa7c72c8c54222063f75a0e7b662e4136cd2a50166ebe0d653300a955982095227b156c16818d9e9faf945229f766efb2f08e01c556fd75dab6dc02154d3bc54753cb3d3f66dbf704c12ed8c67d0a05e3a1354363ac7db179d11d3d41e8670d87d0573aa47ee6ae227557c3225abf7a1acefa227bb068568fe6227ad76b164bb0f90295d44443699abe4709de67008a32ccfcad770d8132eb21ba309ef7b915560985d791d7abad955028bc92dca3fb241785a12343cf021c4261a8b35c745fad6dc1c5bccb1725aa98e28b1233f8a24417bac3de2be9bd1577b8eb0e67d1dece50bc97974edab92485b52adda8b669b55a3a6d28e26ba27d0d457bfc4eb452f2e82ed6bedd45da5d9745fbed44d5e25bfba2fa4c4927a918da412bcbae232b42aab32ccbb20c8b9954e917257a50a20577875b2bbda06bbe956566b4395b476b8b9b1de34a5533b06074505e86edc5689e8c694744d1da7d2eb55f21a1b2561e0aba69f9e5082cf50bcd882c53602cbc64f8e00765b4d12215db3eb6d046cb166190e1831fb4893165199ab64491a1694b94d87626a4d8966908051665d968852eb237c8fb5e6b1d304f73adb6d64fc8cc348bb68dc6d62e1739c042060895a1694b149896c5db805b745fbf1f924cdfdbef47ee9b6f87644baf129da53b8aeea794a651589a347d1d6da5e20fd974486d11c98af7937e52edf319c65a28ae00248bd9e7fc4ac09d65ed4475eb5a64f41f48b417a920c14c698282d6c6cea89440750aa1166acb8958732f9388d7f7d8d7eea9618fcd44c2744fcd13408a6597513f806919f58314fd2e4011262720db909165256ec61504198651c0496152ca7955220b3d4ea45ae9139d7c18660145dcf50fead2f5b028babe858990d2f55e0d9a2cb042c6dedb2ebb27bb26e7672bbd54d71731d5f538a96b776cc58b151b5a76ddbb20ddb1f67b35ad6a9af67bb57bc32c6b57729383d2dfbd8e4e8faa6e2ef2fedd3bfdf77befa647bf0678de89a80ca26527d5b7e350446a6c379b5be06254b6673eb03cc2b590adb52c12d9866c8d9f85d808268dcfbd7e3b0eb32c2205e11a0301c1ab2a710299fca80ae722ee98dba6d755eef4dde49e7d41b8e377acef0beffdeef5eea997b92f0237e249952aca2821032831297fb6cce1d77b1f10fce1d3db4f2a3f20f6f36300b559dcbacb3814029ca110a0dcaedd4e1d44e1024a680085cd89791880a4a585be59b47688edeef6b159e8165a7e43c0a4de90927adbba7738446244427b3fcada486b2981561e0ba1918de62ebb2c02571fb9ba85c65b9632041129b344346a48a05903b8b58cba02a56bc6195429d1c987e111a068e5a5ac3404700c152f2da38260d2422da38280d2dd4a9e4a2882e8bfb008f0025140ac69da6ffa137a7c01748734a293971a977a2fea4a5804383d1bba2b4d3e6970ae507579b58c1ac229041fe878220a064324600c9e2c70b81ca10ac283c20221967280a38537c58c2c3c3af4b48c7a5a8ab292a679422be0bc685d335437894e760dd2c9ee422a601570f6ec99e72b5427c9bcda9f5427f1a8edcf53491e486692ac91cca94e72d3f3f4a2d73469d2cf30d8465969b2fae98ed5671533abd7af720dd3f75c15357d0f5a59eafa55f615d8abdb83a1b8baea7675fcfafd589dc3ffcd2adc7eb3faf6555ebdcb3cedcbb4b0087cd18673562822350b27941268757a7075faf9008fd422feea6058b4ba6c5628aede815944ea5510efdbbd6fdfb255785559ace7c21e21f7dbef379c8b5c1fb54c8040f383152d6fc2206605c320261529cd723ad1ea6c76af0520a84579032001e85b741f80d602d0ddfc28608188818717a22411db8e9465d369ce91d2a0165b2de2b4b6b4cd396938e9a4a7348f93d24929a594d239670f41b65eb4b7dadf9a8becadf55e5bebd56ec7aed9d56c166bb7ba874ebe2ce511e745fca3d5b368bed5e29c00520c735debcc4eda459be547015926a69d887a9429cb272021868fe7330ae4b0828936b1b1ed0b98b2130b2dc82f4c625a4e7a76716c7576f959407e6112cb72ad56f3ba00450c82a59a189dbc2c90c25cf28708f2c7d6cb6737cce85540ba9ff5f75a6bb36cde15ba66d7565abffa09a9595ca1e9978990854545f396d6263af92941b412dd5117ce5b6898a69f2246dfb7f00a7d544d0045571f671a83a6744a124ded27274bcb1e85cd2969ba9333db287cbaef05499ed49a98b2a6bf0e204d6951926ddac8fad3663a5989728ae2d402a71344392965514e491a5e83555e6c9e169c0f61a27ae0d22d8f091fbc0859fadd872b2a7c807a7a0cd3a07c7002827cb7d2b4803b58630228820d83616d89a81ec8347d4bde8c1369520d88ce0543e2e3fe98cf3ea9887407644648eecd17897d910a340758c854697abcf4425213d56e762b13c07919d5c3941f227496dd6b6dad944e09f463dafc43841692657185cebe1f22fc16c93a2f0defb42e9c0082327c02caa81e9c4449c1d24d447748bc4990250f8212f09482a00434aa074109686f0f8212d04e81e2a594120425200390da860c61b6a093724e4a6bb5f6de2cd3348cb78de3bacef3be4fa55aad4090c5bab9c1c169b57272747476765cae193378787a7a7c7c68d0a821792031b2d1352490fcd16d481e496acf6c4302cd7979102565ca14ca82840420a0c7083c0e3024b4c3003a0a40800104e5100128041004f0030b000070bc6ee4f0366ad0f0e9e199e1dad1c969e1dcb0c095eaf33a6e933c646b9287e4215bca6ea2b3217918c9363d9d2450fd31c618638c2f0fd3344dd3344dbb7cd0b66ddbb66d573214db2e3f2485388ee3388ebb92a11877f91007509c4d3c8ce69a76ea5e3f9d240f2412aa8d486827a5d926967d6969a9cb4d43b1aeebbaaeebae6428d66559966559762543b1ec9ee7799ee75dc950cc3bcd1f2cf6b9625f138e7ddff75dc950eccbd349f5a0cc262cf3a9ab42a118700a69afaf63a450f6a996a11870f614b26a15e454bf79401003aa20dbf45bb638679665b80749319c9768522cbb162e2d2d350dc5b637d588e12f35a962f84a680c7f6949098e29add6242971c5943436494931ed4b4a6031a55a46524ccb4bdab7ac848be1ac6428a6e5a61db12c4f2e57c81d53c2c6481eef7a325d2f258f99d434e31667533d951ac2039afa23bbcad814e6610d98e46a62f2e4a4fec89602a5fec81627d40955484a20934b4fd9599cbf14a21606e05bc46730a679668a0350c4340c50a452160660198a41d76141435608700bfb04822da37888ea550f32af73ddebb2ab564ba75849670dba1ae22cb33401de45af33b1d5d92b088ac759d6ea51322696d2fba27680218a072e513c18d1ad19c5c394966ba27870d2a73b6a3d8287a6ae5d57f24545f06380f7f3a8ea1003145d2e9f5324c6b870a8699aa68114a6612d07a0cb47d3344dd392ce4445e1d2326a07284d8096513b3cf55f5eeb5af0d2db31409b651785e96003269c3047385a61d6b0030e6d69186f7aed79593cb2cddd92c179f7f2cb06a0f8c2f65e165d20ae42dee715bae3def33e9f3c9a007afb164d40d3633501f5f62ed9570ba9ea3d14a85f3d02f5ab8cd4aadc4301fad52340bf3a527b29e0ae3fd98f6c6fd993663b6ac9b060275f695ad3ae730d0a99d65ea178e9ed160a9bce326b6b09446de53744cbb0d66d5e90141a7f033813515b33fc6b34db751b02d15e5da127816ab62a09d4655d17e6dc8638afa10d5baf6187bf21f8f6da3704c9b3a1761c5658b49df555286e5ffd0b7b722efb738177853d39ff2ebba3f5cbf94dbd94402ed15ef5d5b96f8876d11eefe87c27ec11b25de7db75724fce7b847c07ffbd3efb0cfbc386f839e10fa4fede0a45eef838a1b81dff262c625d367e16bde31945f86006290c3fbb2a1ca2b07b3757eef1fdd08eb34fa883c2eeef670da0fdbd7cdd16d57c90d6bbf7fd4585a4fc7c28cdd7a6c52181ea6d766b9f7d21dd32db5fa5b40ac1accd661892c7d44b02d5832228e22daf424c7fe83feff4537d55f57db63dfacf47761ada0cbfac17dd3dadb5563a9bdc3b7f673ea23d3fb5d0e2f004a0172e8162d00e0aa31953a105d09f9a852d00c5a0201d433d8814317281fb9ae16b7bda68d3a64d5f5b3325474ea030aa691b6737b96533bb58fedad7efed9c291ca1306a8204a2a7444a600d9ba0a4d07006509c504fdabdd01df2cacca4b4cd138639db638112c8c60046c3a2eb64689facb5f6da15dace234d345644929e7c38a59eaa9d5ccc1cd6a29968ec953394924a498f8354d72c22852f8062504ba949f97b6f0b6db3799a5d86a14d539f85549e86f352522943fa69d77428bcbac81e5f76de41afbbdfe79745dadfb9df702ca1ef02fa7e2d34f71b7ea1a5b0cebb96a1f0ea22f92bbe1a634e084b7c7930403184103eef4786e87b7ca117ca5508baa6fd66af85575a1f745c47bdbb610c7af9224cbbc4d9de00142dbde8b2f4c7dede721cc7710fe22e2d181dbd9ff7cef30e84de436a2d147578a1c8fde2ad0b919a3ba263dfa01b83cec707ec83e10ddb8c2fd4eb41215098b5535ed54b02c96fd36a41e9ccf7e26ba4b5f616ba5efaac86f4d2eb614a2ba5af9ea5596ad3e28082abc5159a5e04db05863480b8c5e34e3242e5713863f2c035c132fd0b104b0fec600747f6c8b603649b366dda4c1cd41bf9a8cf8c346034dbfc6671ce50443a51cd422d3c483ab47cf6436e61035ecb28a9196ca5b70815b231b9451a2dc868f901a913065da3a45850bdf0e84f945452db96515bb069d1b60ac21b7cd149bac307eda1c74d27bd9db8663c8f90515ae0104583292117439a98d6b4282d82686d15d3b4336502d0324a0b309db58cd2228a1f8465402ccd98e96242b50b362b77f98e0b59e0be7a17b240a50897e559d02677fb22dc6d2ee2bde671aa6806c1faa3fd5a04646c89e6b9037e07fc48a588cee9e7bb1799efbacf6fb988ebab3caeeeca44ea8f36f318547fb4b3be935979249a6046ed3ad986dc6be85d158e548a4c7bee45ecf611bcfd968bd47bdacc239522e78a70a7dab9cc84ce99c7ef7454fd2608070cfdd45a44d5ca98883b2764a163814a912e4f282c80100566bf609e4ff547d30e8217306361a4120119bb5c66e15ec6c4f9d49afd2aac9f470327dd492aa9cae91498b17b221a5b2155aa4dd902e3a13543e116d6bed8bc4229fb10871194515940e9a223f378e276612f05ae714661be7e3bd7f23344816bb9854b54c4107ab68ccac2057d5f74a45ecacf04500c72dd21ba43c478eb4185668c4665d1a451b05c50496a99250f6498c5d0d48eab76508b2273c5865a4461a1d45bcb282c9ec8c88e149bcf3291a59f7ba41891fa7383eacfa5f5f3239522b6fe5c9b47b0d6118a52d01e842850c6e665ac5e0c925334874e8868de1ed0a705baa2c8488922d382908c4cd3d9a7ab04224636c044673781ee5075f613240faa43cbaf1074f4c8d219eeacd31135e669cb433400451d3d8f6f0873d51e2116600944a0eb5fcba8313cf4aa65d498262dc2c034e96415e2362dbb7da54963fd771b8ef6ac6be1a85df51b8ef7e07138e2eb3c0bc7d6c7ecddb770dc8e732e4c134589105ba670c1530ddf8dbf5eafd6471c9c2f79c5703e72d7d139ce1667b21863882ab218230d8bc5faceca23ebdec719c78103078e8e8e8e8ebc424b144344959981cd0fdff77d79fc9ef351e7afd7eb858383a352a9bc7031460d69aee0015311aae77cbc711c3e3e3e5dd7c520862bd6402105758397ee343ecef8aba7a7a74794152676a8e2c30f9200697c74f1f0f0b0582c029cf9218c2b4a7080a205ac9cd56a95e372b9beef837d418332a67022830f96be1bcff3727272542a550f9626ba9881931cc4f044757373d3751d4b872e92ba9061e64995ee353ede58ad56200872426c81050b1aa208e103f81a1f67d0a041c3f33c168b95adb1610c272634d8e2081d1d1d9d3cb25ee3a38e0d1b3670e0c051238f2258828a30ca100389286bbe871f6b9cc6ffd7eba552a9c42f7438224d184a55e4a07af891c66ddcb871a3eb3a08c4a08a131dc4a0b474021d1d1d9d3c760f3fdaf867cc9811e691012d88ba028c19d810031c7e60d122872a4fa0f001081a3b3b3b484bb04153860f68b0410733d868b55a4852a63c7181126a50e0831bd4c0c1c161b2859636519ec090c4141a3e3e3e30948162c2052a988891c6464f4fcf92991c5e8862054d54a1831a3c3c3c72cd1463be50e3848c165252cd1352343813c61267d84834353c29430922a2c8010f328b2f3080820c2456200331e497343f4051e506253374b1e179de016250a221892a3d5c295303070e1c3ac658a1410b18be9061caebf50a801417dc400a36485861c38d1b376a3cc9c205261428a9828a19533c45c1810cbaecc00524624a0c4a3384c10396a313a8e0490c125ba07ea0801726b63801040d5330f18100144728b9c00825a438e9f1f1f1015244932b4f309882cd138ba7a7a727d6031760a8e0045c5891e173f1f0f0a854aa292ab0010a24b86892724195e372b9baae438ab2450f9a34b1c1162566ba9b9c9c1c100491589025054c6620a5c90b24c0d5cdcd0d8bc54272a10630e8c18c962268d005cb5bad56dff7ed808817ac18a28c1667a67c383cef4b4888792a95ea0c130e5e70a181124f68a1f2f9f8c2810387a40207a52859d25461832dba9e8f375eaf97948286275a9ca88289982f409e8f336edcf812126237582c96082ae0e2c45483272cf081e5faa83363c69790109bf17d5f00b268024c9822b86cc1e6cbf9b8a3a3a3d36a1245105360b29099fac71a6ff9f8f87cbcf9d8dad9d9e9ba2e3be3c48b1c9262580aa3fb3fd2384e4f4fcfc7d5479c56eb4b4888b540109c001566a6f0c0c90f5f7af8471bf7e1e1e1f9e87dcc383838cfe38fa917ca18e28b283a3461e34a4c367c3ed6788fcbe5fa88e3639873f6c923929620b658e30332927081991a5762aa711ba7d1f391c6797272723ebe3e3e0cc39e3c223db900050f963c91a6092d366cd8f8c844e34a4c345ee336783efadc757373f3f1c6471bff79f28834c5490ea498e20b306698d4a851e32393cf95987c4ee3355c1f7b9eb35aad3ecef858c3860d1bae3c2239d1a1c90f55c478a205081a34687c64eab91253cf7d4e23e723cf6f3ccffba8f391468d1a3572f22877c0868b27539c38e1e4e3e3f39189e74a4c3cefb9cfcd47d7573870e0f8b8f3d187060d1a37799464c6fc8044172f4e4046989e9e9e8f4cae2b31b9cef39e3c7e5f7dccb9f77abd3eb63ef6f8f87c0909319f551e651447ec30830f633c8142898787e72353ce959872ee3a8ff7f1e6386edcb8f111e7234f4f4f8f974720355d54300614412c8de172b93e32dd5c89e9e63977e5b13b8e8fabbf66cc98f1317f74f1f07c0909311e1c797c299992e509256080e54c4e4ece47a6d5959856bf794e1ec1bf3e7abfa1a3a3f331fc98e3727d090931d72b8f2b291b60414366082088b8b9b9f9c8e45d89c9fbea377964fdc6471c9fb1b3b3f3f11f6f7272be848458ce8d3c86600b19a6ca3491449732abd5ea23138e2b31e1b8f7d5eb3aad56eba38d8fab9b9b2f2121766382145860b1810c276698c2f3be840031ef23d3eb4a4cafe3b89747d5753edef84e1e999ab218ce9996d418ce9700c5703ed6f8e89da9498badceb46428b6fa121262abaeeb5a0a3655bcf8408a144d70e0c0f191e9c695986efc751c3b1f67bcd56ab55aad56ab9557d8c923d213305c08a3832a384821e2f57a7d649a7125a619bff1571e419de3a4c062b19092c208424b9931585011e2c68d1b1f9974aec4a4f319bf9147d65b1f779e4f903f53ea608b1aaa44b5000c16843163c60c9dcfc8e317e2e0e0e0e0e0e0e0e40d8851a2031625ac9471032e74747474f2a8ba9197931a1861860c169c81a1b341e486892aa49a00c1c4164b80354a903f93c5621951f2820a14388161a909160d22f933bfef0322861ab0a0011545bce0e4dbb9cf10f8aebb4aa55221b14007a93051ac39a3c3939d2b31eda85aef09621dbc1213ebe0bbaeebe4156bb62cf1e4a9062836b4aec4d4face71f2d87dc6479cf3e8e8e8e8e8e8e85cc9504c27c3e4cffcceba12d377d64110fc92570ccce38c3c1e0088a72e5a6e88e205969d9d9d8f4c385762c279eb3b79e4aef3d1b5b3b3b3b3b3b3b3930faafe5d8949f5ef2c16eb4b5e31561e75f208022c76a0660c0c4e4624d16ab53e32815762028ff3561eb7b73ee6b0582c168bc5626557d65d7525a6eeaa7fdff7e5b195472422a496e041195c5cd981151c1c9c8f4c19789c3ce2b33ede64f076dd552ad597bc62aa3cb2f22873f064062c60810e4a74912206825f428018f891e95e8929fb3d9847eddfc75556a9542a954a7525433155c6f2672a71dfaec4c47d7bf7aefb9257accbe39747d984132910430559a29089121bbdbcb4b494a5fc991f99ec95b233dddb8f4c4b7662d999968810cbbe8400b1ecf523d3921931ee4c4b6ac4b82f79c5b833296dc757e2ceb41d1f694dcf81aec3c2a070a8fec8b770635620062bd8f4ac45f34d71a573da90754777603a42571d52480a8124743db5b2d63a0514ff900b28ea681d3d1a2079cca41df494d200ce79d935db1f429efc99934b97508a500a6d4ead658188e0446b675a7688b0caf5321826f452c574d4abb5457f2c90fde691ca7c9665fda91190b159472af32d70b14be7a5470a72d3f4d64b33aaa2d987c25cda2550f5a1b0cfe6300a9f0a76a5b49661ad4a64a14f6161f80411cd3cdb355bb055bdd31db6c1cf6621087aa73baa8ec388ac805cf7808551803d2cd8e2bc3da100e710a0cef2d5c47452ce164c3275f43506573aa354e8864880f4f300f6e1ac534c27654c5e7eb2b5232a4b93f6e608f3d2ab332391530409348f444e11a8049a3fc22d02b08fc046a284943e9a72e610655416297d34a70d31b54c5a76622fd492c93004d8cc311f6e01a5675d3e1bb5f554d334ad884acc0005e99c37cb12bd37d48b482db31009511622d94027f1ba7ed65b2ad2d3f0b693c14280ed642e1febea32b0057adfafb241166cb5bc57434c6132ecc19a34bbbcfdbd0cab549b647fc481814a6a6be518d9900f8824d35202c9df6cbf20754d9228b960496aa3ba26a96be63173d0cb6f68e6a00fb780f2e210a5a1bb9d8f307d27d8a2a0268bac8e20664c00ca282c6a3c4f82abcce52334447faa8e7bf1b6715fc779de875539c8642a379f8f9bc32640eafd75bb1cef5ef5f9b8338485809f5da3dcdce69c786a73ce6cda79672da2123380afe1538b29cd453863d1065181157b920c6867b804787f2fb7dc6c432de06caf89ee92cc8fdc36d32981aec36191764ae72ca243ec29962b2468913e496da7126c1f912d2b2125414161d2b4f4820b4931a52549a64a0d2970828b1c602113dbbe346a208ca761a8e4ec9684414c2ac5d0cc0000000400f314000020100c07440291483424d434c97714000d9fa43c6c4295caa22088611032c418620c20c4802122043033b36d00970c1f003cf59218add2bba698e40c77acde61f6c6de484b46b71f2480736d6c4f49226fceacee3348d712b3327cc460ce47f1d2a38c8756111521b70444864917968d778b8748a8f76292d65262ab1edc238aad6b0065cd824363e6bac6ba2773178c872a65c16785e9e297121cd287fa200500882a59ccd3d56862c064f0cc42a23db684f27f9fa8b39ecb542c23d4d1872d577e5666b06ad02c4a11847ebb181f02307a9b1c65b40433362716fa2fd2d088e545b8b349ac404b5659e589d234359a896ef5b5e2f84b7fff516f34a55d145aef7b9c97b417c35fee018f42d4900db337c65306c1172b3ab1de69f814886b936882072605390432440f3b101956bbe85a05db891ae2b7182bebd600545dcbb73c67f5e633cdbd28a404855689180137420bace03014e3394fa3786fc0b37048a9066d7f18c631655ed3766c563fa96eccc85ebbc4882c61d6e0fb83c5c07aef29775e5458200a08610d5d2145129fcb2b8d1cd80c030cf32221346f46d42f787840747816eed242042e8699b18526c3e28d268d37a39a88bd270385790131690799462a50c865aef66492897e26e0c95e4e2a586fb4f81a1938c9c8152fa415f1bbd882f534b570aa583f4bfcf44d781156acf67e6fd68a01d44ef919967198749a476d85341d88bf3ac0e786e6668d00b64e4c844a19b2e84480c55c16b1b8f7dc6a22eb8d13dcd3eea8f3ba0c9327b3b161646388f90ed6a377098091f757f4867fbcff4bd64bbf525bf2194be3fc6fb15a8c0f2b065d6f8c890a8024a2cf4d3d313e2a549620fa095ce4ae0bf7debddaf6f5092831aa56022e14bfe705c3714a489bf97ea7ecce95230be67801325d11f81049a0cdef0255e5692b1f1c00946e8ff15a322779d906e0d6be10a156467c04d477b32f427ac3bb6e857551bcdacb060833d4996538b0a1500dba215e6a588bc729943b1fb76dfa9f5d55c5b95b722153c8fbee7d4894b3c907c2271874202d72dd45356dd156b68a0c1371c1cb107334c63d980aa7200db8c69914c09d7dff2029ca092513a342660b3043107c08ec6126f4b889692758e761d62f29fda35a0a179a6e8898b13c9221be4032aedc033a7efc3e6d427c7afc4b63d969050331b53571e878f4215e18c686745ddf2172cdd152d87c137c30f8793280810a7947d6926961b53740f773147394afa6c718b5afd29f65d3f93127d8e14ee2e1171aa0a8a2c4eeba1b48301d8b089297d3ddfbd81c632382328cb22bb17aeb157afeccddf4bf01f97835d58808a0cadea8fe9067656b52964154719c30dd3f9557e0c585c25280d914b7e1697d2b4e56c0f2d182dd2102de49b9b3a3b94fc819fbd0cfa0ad4080668fd0166288af6c1191b90ee09fcb57686eb128d400beaa06d7c15854da657e306f6b1f248fb638096109db80bd89125c1fba5edd92c23a744998d5c514b3f4cd80f073043b7b080f614bcd7ec9fefbb1f50ea07e8642e84f2197e30d6c637d67218a31db0b0220f77a67ea30f43342e6af2ddfe3c0e16537e3b6195cefc247731e60dfcf10bd600025c483b9060b20e38fc0cdfde21125ef9f634a389c790edc4f3fbceffdd414563e3f47ed513201310141403abfd948a0cd0fea13cedd5a0070bfd021f235e92af0dcc2b165518e430fa0b32818cd350a27fcfb61794b2a610b014740f02f4c1d2a7eee50658c33f800d9bef8abd90189f12e74097608542ac65c59182082a1c2f58f88ec2ac8bb59e58a22308accb2d9623b866563ff0c118ba7a279af40bad1c299a150ff8d0614201d03e9567c810f33bf4d9ad06e9318fb6fb7047975ac78157c0954abbef00d6e7467f5b78e08f34bd851e01d80093478c0bdb9b55afd83ec83e49941fb407be7926af407aabb92e3046a07d65bd757db5fdc8e488ee3c71d406f7d5f4d7f75bb44b28b1f77c079eb7df5fce5e912493b7edc81f2debd6af803cb679220833cf0469c40e0611be58482876d9413701eb6514ec0b907e2cd45d5f15fa7ef4a36f25107ca3b07aae51f745f4982e4e3e1d3587f793b4432a7f707bfc6fba3c5b192067b3b48e330317b708d79a2c3e11af384908335e2090c076bfc31ad8a1a2e25f717e3430a84f8fee0bb20338bfff786ee5c27c846ef0699d9fedf19b893416e6ec4e7934a832f60ff62f8480140ef2dccc7b875069fd9fe9d1b24e77fdede08d5b015065fc0fe85f125c5418c2f0af5b87a0681d9fe19195c6741af6b06e5893002f61f78d841f3dd8406362ed9a0271f045900e4ff7a53672301a4d20f812c60ec7fbeb9b33dfc51e907401630f43f9f35c14d5589214e1a1e1035e0eb4fcd1e2048692f229c523c7004c80292fef79fb5e5a66a06f05a92fc68580f27d8bd33eca81081f6200e0cf73383c216c01cee33c2bad152401f08224d7998f5d3c961ab419081e90e7ba4676454cb3a180d836a60fd206ee94814afa73dd457a6b7a9ea930967cae7863f0d838e497751ba2a64a9795df707585071ed2e4a5f412c3d9ebbfe00073ae806f9d05374cca05feba10d80464477ada2627beeb340f257975b496f53ab27d19c91be4bfe34f819304dae8a8aedb9cf02e7afaed559ea15af4c6c9f7e16507f75ddca65af485d62dbd6b340f35757a744e89552ed70041ccab1668133aaf5fc36848a07adab6ab39eaa551974ce4fba7a41d49031c4623a0616728db5f6fc4d01fa321432ed8eedcd2d5cd24591d499d34376632ba8e5c1e371093928a0b0937489c415a32712a0985d693ad4002542bb61aeb5df080eb03f809b26dbfd5178b0d9ff883977b6bf6a060c586122669f028274b17577d3a593b9271f8cfd131178cadc88c9f4d4d04396b8f2dc41be0730ba241ba4d292ec2a2ed5018e7a6c01246129eaae596c055512f337b4fdb799f9c9247810d9fc471f4a6081cd1fd83efce98ffe425ef65877dc7740e9c5cc8b6fb82c0b8fd02ce2cc1ae010916cbe8a9d910d379b990c1394be80b6d88cd7820d1f0ac35f302038a859bb154bbbf4564f44e063ab5c8bd5af5987052c25897492ddb33f34aff60a628852b7f79f1a5902c4e2c3f5539a503130096a102f805c2a9008c18bd0f625852e21435f4b3cb4f5790f11d98668b20c9d1f06731e2d48d3c68f8132f073ddac1c2956c134466463ccea2160f4ea499b267c39d9a5db2234c0a15400ae1b6fee14c72ac7889a767725cabdb52b2e8f0194c404d579fd0781c3fc42b28bab8e74314578963b6626a9cfe5a16b19e470204b588f33a8aa63aef5cb7a3a316f4102d510ca7ac3d4b03af816a190b526af4f290448ab194c872cafc77e439a03519b6aede02eb6d654072175002eb367a9ba7948847702c0ff58464cabb9e10e3526b49c6516c284afcf8f9371effadf62299ee59b6adf63fefb8d38567773bf5a4565e8d6137d5f7c8a5c5f237c257c63ea5d170ee404901902f430b7b57947644b10251aa3e0081aeaee0688c4c83cd1c15149b2b37273de4ae3144dc5b652f48d7d1482e53c60e7e772e47511246ce88081d4fa3a2d21194c9ed00cd77a554c6748b681f9a9967ec2d0ab0ee7eb7acbda66aa9aa80df0631d498d418c9868842ad6ee4e63cf9dfbe82cb592b75cb3d75bc91f325fc8d72f92802e71af74f8d88b006ebb3454de384320f873ed9a6b106ffe3f6ed84a2847553f62ea0ed6c97db10e608937b5770f5c6c10a0459ff6c137961848735021206d8b14cdca3c36a1f8c4be31a905a0341648e6c6e083ff40f0145d235e93ac0c8b8593b6713bac589cb9eddd85e8b1f961a612184c4c189a81489ced7e7ce70b2d50b09c6c4ed54747b3e620a0e6d3e044944475bf1f37f3c623ae32d2ef9ada6d30c247e81781caa2e85ad736b1a10ed776b3b3e5b0ff8474b4549b5097665b6cf911c9dbf0ac0befa142cfd6430658bc7093314f3fc1b195786ad2d1026e5d91f9e3fee4a0ffd8bec35defb401247224ac494de4c06694c6064b767b3635682a35e0b43fd15138442fe9cb00bcc475ae176347af884ba8a2ea7576881d8677f62bee6ba575acd2e906091450a9fae0e3359f4ffd36892e0a95e6a9547550f28638c6ea4fa67e0eee5c43936a0c4a400456c0066a714eca2f41bff2d6f2535595cd71251e0bcb6cfb108ae8fb13df0543d38437017ff90183aebaee55d652459df17a2466f1637498ba366ddcf386b1c61940a5153e9de9a2f39291d48f7af02067b5bb582942c2589be026ab1505f57b40c6b5529c28dc1ca872098f6e3950dac3d5d8ce01a001fa475edce33d88afc1ca39f2a6c212d92878fde7460ed40ec4b878c06f19d67f2a8a522029c73a402bce689684d7ccb07fb668b2247bc1b4cbc6bb01d2f38deeaa3a649750d4269190dc9f7c82d5d9ce0c4e687b66dee93cc4ce7c47c32022abd2809ee67fe8db1804e5bd31514bd2d6f66823126071bd5975780797a91b2102eee4723ec33f41701e0d6406aa8f004abdc127b8e5f0e808ab7b4c1e3757c511cf8a01d14af0d90da1ea6586b360f7924500d06842d6a9db3ce0f527a0daebf6311db00398f4936dd20a7392644a1fa1c66906d34e81ef9eb94f837dcb87a7c20cf549fdb9bd9ab23cb3c021dda8101202460900987dcda8725f7ec2290e51715e42f459c847206512f59580894eec1720e084f616956b4ef181970dd018856431e0636977dfd801bcf872a7a1f255ceb39d1489c016465e3dc4226261ae4b3bf15bac5507b714aa6df8075c3d81b4bc602d069cfed630022a9e104c525ec50ba22126636f441358b46709f7d50141ae32fdc8c0e88e2a78677943794cc4bdc39ca3c4f726773e72aec2787b06b7ca377f44fa703bc4cc5120db85addaa2fb47dd1fc3b46b2789b6f8115ff4ff9e43ccc3469565d13901aa38db1c2d7fab664352aedf68d4e95f14197a1b6214547302961923293b3fd6573fc0f3261088321e591d50f385edf9ff9bcea77f87faace75dfd147ef74ee788c9f6a9aac3a1db63c1401d3686e358c640806dc60206366f50abf9352e999b1e9affca1bf5ada01ad6c04f37c343232225544390e83ae6efb33445358f4a35bda3974b7065d820bcc78f16ada9ce86e874e863720b072fdd7d32543fa4a66138bb368e8cf2e01147cd06900acc301ce801befb8c2ea5a0ca25c3f64839885e4881b431deed0e9b53f44f3a8292d96aa798b42025b81acada39a67d14d500aba67159d5fa445a9fee992c4022b31fd31855ad17513769895455da676a810d35bf79d823f9421ceab0f9cb851c93362f94e14d87ecd9eb5eb48f9550eff8c6ea0040785de0b9f9734034f3c6c5201f159bcda246b7d3fda2b85b3291d887aa8f75c9221eb3c423f6f120d8ef78196c0e89179ca2283815bfb4610e6a89bf4c3104585f7b57e538c72df99f2e209a862d83ddfe2430626603a61510818c12d0759cd51a0de67294689cbeea94a28088066d21e5a92e60a6cd4fee989e24ea99707a0aa5af96787bb47db5988c8ce46c254a1cfe7a003d3d2ad6facdf98c71a9342d4d6362244c48439e958c9e534b5f6d31301a863d9ba7e29ad86ed0173d9501729e242810185d3d5160087bdabf5a4d27013234002668c965ba5a558ea080bb3435e9c53f30fc172e51005f85d48d60b680e53890e44061b1e7b9d0ee11c499cceaf3920595f863cb74c7aea4e988594ac038356483b7b65c67813c9470e751f1a238e7e40fde33614d767f657d92c7791a66dce588157de084d50026d700dbf3cde3fbd7a144397a146829eb069c2465fea80693401d5b0791573df4d0cac434d3bd0847ec0c29ed7989c37a7f89359e09a2ce5e443020711a723f15f36434b212492979e7a76a40c6be904f44521aa4ed567fa6a19b8a3bb12d4733b6520bc47828280049ac0712a12a98b57e4e527d1da0cc8103d4a8f6999450d78e271ecfa346fced78f4280ac41ba9cbf8cba9864fd2dd5d9dfde9b73ff4e39d4fac7b5c9b1bc07002e640ff9b85108459fbe0ebb127fc6c8544ef763f9988f01c4bd6071a1a00a6867239d9aeb1af19409b6bb0d0c8e8d814056a5a3210c8aba76123d21a22f15876b7a7ac6f3d618e8d0460a9f12e8625f9eadf9979ec45f9023e046f1840281a40770da127388f5e13bb145eacdf83124021c41e71184ec220796da08a9b613f2c3fd5972c974971202e0d5a1875d1f68bb988a66ed240be732ea5ba65501e5327c1b857b7d285c66c2cb8a9e234ec56c0a16cfc5805aa52ac105cae4c8843fc6a7e9eb14631ea7066d891177d4b238b563cf3828af832339281628fea6bdf0489a658c4f5fd60611e22ff9221bf6dcc755c799829d883c8f688be5b9939f87fa03782ace29d51e05f144a864817c69c2515708e5002ddf9595e0a9109d8eae68dbb444f04c0a01e412604d56320cba95d93d0c713bc6135caea9e3bd5f577b3b6a52a24fb63257f2d2809788b1489b181dc958d54ca30ab5b499d2d2f870888b6d137c1a51436bec9750826f70e9e114c982be6c8242049500dfa2e59618a04912d1f971c899c4bf97d5bdf16cb19a2216cde5b3b94120786a527df0213291f321695ce3eff5f0e71a9f5765e4a88766328c7b52fcabff317964841fbac02ed1168a7120f0388528fe0ec452c541abbed987a130ea80f65cee0e489a0643fa0e884142eff951771e1726f3990eb30067077ad3e919e9b6046e87e5d4dd9cba542ce36ed8f1d50e5d1c7dcc795b545b975172aaddd2f615276d88b479221b01cab9a64dbde2be5844182b05a79a9e1452c052e2249aba19db5f847b2910ade620aa4d7f34ce374d01aef195724b8d3069b3285bbea55bd5996d860944df3c11a45007ac6e7d81843ff06cefb9349475c5a27b8dde233abef73f5e86b8749a62905e25e7c4aa3fb03eef6592891d26fd5e88ecd1b0f2ad4fce5a05d7ac101bc7893b9e6edbe3818d3374c94a832634bbcc1936580cce6f5df1b948377642665619033dd15bbfed2ca0156f89a343398d80c213b828271ab8ceb3ebc613032bb200013c152918034baacdabadb143184f49ec94e451b8eb327074cc125804d90ba1ba62e6ca1d851c9eea22b7830d7e7f6e260e800db20f4635f46c8c4e8fedc4739089a1f3bab438939bc5cee025292e7d8f9e054e0207f89c1fc8ed25af5cf2e18d536b462c31f99331a67a2d2c714d7450166d7e2b90708f482842f925b054e7da04ef8f5dbefda6dbdab2eb9089a3eb5f0b28fa8388a1c866b1032370160d35d932da093398874aee22038f010ec4c03d3196b9ea68051a4b4ce708ca45cd3e83cdd0ee97a09a1604c45c40439d439d0dbdc6ddf0047c0fd2c00b80158d18e9b388b472a17ad9d47bb1abfa4ecb338f45bbd608fe0e3d47abd9891da72a8ed009253cab51dac83e24cdcf2a52987ef293f32feb2b2759aea4a369563a2ab1cbc46ac1cfe25405bb0f53fc255c48eab6cb80938abd520c30591a7aafc3199e3b4065f2cb8643990d0bde217227d48a1f42fcf0ac35bdb66ffb6b4edd7f7e285db0d28e5b6ff9f2f0adf6e25c3af6cd756a7c0de84d585281cb5ed3f3e29d791f58d398fb9cc80ac5b42ab97a5b89a37185e03fcff1f5b2d8b5b3d0f411b0c96dd24629f00ba42124228c39739e15f2341197e8e0c8c8d040a715fd734b22d40c77baa3ae9971a3aac59a0dd788087bf57e930b1c54bc53cb141a40a6387279d21846525fe51ebc87e741323ee07fdb15449c15514e3c4d337215e6e4b3a07a998855d63a54785b2cc7623f09647afe835d5a7e00cf23b2d469abf374785cfd9d890b64e4de05d250614d2a0c36474f25ddd2e8c7b891efcefb536e592d940c7e7dd3d97b7292805317327abec6deff32d13ca352895bd3044dfa7ebee75233ed1b8f5a3471ddd160997b7858e9b9bd8f916980d3db9508cd6816417114aaeab5970082734824e7dd0bb8e0fc9f32476182bf4bef43a3694ab805028fa7833e5e2644fcdb21160c45e8b72a3337ca96230851e7e031d3480ed61b0c512f30276a3cdbb5c0b2df92dc8ebc476b417f375be167efb0798fb1b8002209a9125a6c794df1c94775ccffd0033b2e76a18206d3df7011e71c21b30637f11e19dbed07d909ad6f577a55ae9bb8014fe6482feaa094d61dabc23b691d1a0f8f055f36545dd888f955ac5878690ed930add1a25c5cc7319b892d2608b8a34d1b768f874923ad4a505b4c8b08b576869a90bab34f25d2643fd466864387134efe8ae11076eec816e98d748d40196efac4049398dfcde2fd8fa46df647c7086f4b780199ff7a3245bcb2d5aca3e575f9cc7255e4a856ccebe46bef659e193af04ac2cb7a1ce9ac08d741b5179819f6fc86c6633c327250f1393521bf73875a70bb63e904c72141a9b61bd83f99d7bc17721a728c2df903e7eb1895af40d9db41c22800176bcab35e51c23e109cdb2e456002684a3178d4919e3fdc72c2440b1ddadcc8b8ba0ff6061ae1501367a4dcf7bc362077905f714c7c5a043290a3f063c65d699784ee8c9c4891a1911c0504c9a021adbf0f66d42ea45df4800d50492b5b5b9c1379f692a04453df6812a6c3fcfb5591af54c340d1bd031ed6a9d240fae5b93ad2413f400e93adc213b5b5c1f41dfe182f1830517d04516169d0e80de4906677a8dd918b1f9e81433ff838aed69f7738b9b458af65c1f91cfedba522e430e21cf94e4a385ce1c86adf4e11baa0c093253da1ccaa8f417bb41770621f378e1b85c4cd36d512f2d2ee578b418e6318572de55ca17c9c4e8523f1bf2c9f320354da6716f5a33113182107b375191824811bb8ee0dfc29a70d1486a83172214842686fb0071927a45d84dd9188517908a997c62b88794021efac7e157a272a7c667944c4b2af84be39d2770701c73602e4b2e107a5262d1060d0351208cffb6f832390cbf8e1eb88d75e9a341a9320bdb355478ce783f307c7eca17d189a1ff9723aa6abaa76900bb3050a66e77dda87c73a7ef486fa853f0eeb5304088083156cc932295999c111ecb63e2aec0e33574bf1b2f028080a80dc919ddb9c3ef2038af1c382b9f9647b5c28411f06bc4e5ab461b7c7a1407373f51bdf7dd49ca757b9b33ade932aec051ff49351fc0ef9c526585f224428e27ae785165133e176360d6667cd2d0abe7625a134b5010ce5857dd3e98906802f72a1528b83e6f1d083f26fc9b5d492486bbec50aaac9871b4637ee8ec053d575f583caaa7bced0a5ee7cfc2f4822dceeadc71efc2cadcb18d1003be8d872449550190a429a84e426da2e5698e5b2e53805bb7fad92a17fa5b1ec1bab57db6e3c4096a75ac09d1fe58a13d1359e7e75cedd0191cfc96f4e34103d8361c0aa8b926ed75e0ffcd963254f0f49f625b930f5e6a3de6068ee76254dac95781ca68e87ba0fc4cc5a58d30f63991f1417e07d121ac906d8dd7c86849de7099c461f70432ce5021cd1377d8aaea89bdde44bb402e4e4569eb2aefee6f139236b6708fe8b514ae54c280ea83899efafd320e09eee55d4e36db69b2390dd503fb6bfca23f42e592f38c2ec0c56e719b7a5b5f61a5e702982dbf06e43ba110e485357ac5b99131656a53bbd52c98965c70fd26a08945cf7741e1454c0882148c9db612701bf64666531a70cb4ffc13260cbef54b6b4b55ad8a6b4b55ff44c737d95eb1b48aa2dfa22a50ca82316aff37d18033767f480029cbb406e8f1697d0dd8f0156b3e55f95e498bad86a8a80e38a0d8ce3e832a1fc6368441db355a2b15ae726633622b538bbebd73bb915155e8370fa55bbec40e542d482042ba8c628ff16f8ca2cb240e608b90e21a590ad50150c1159e1b904565ef8c5c4903dec80e4d06f1e76346989aa5d89b4aeca05ac854c465b47d0d2610859d4055aebf4ace4f25e7479de3af96f7a7caf157cbfb53e7f8abe4fcaa72fd55727e2a393fea1c7fb5bc3f558ebf5ade9f3ac7dfa1986d200e661f4713fccaae7391d409a503a40b08f1b300eadb5ba9f1e0c04844d2df5e8c09ff3c02624ffd33dc02e1483110a87406429217e9b3132f596d314e08a64d39db61e9227cfcecd9abc58bcb6f2ebc6eb9f2fe92ea8b6737d41fb2b8dc76a5c507924b941f8fedaa19706d47a5a5e88fa464d884133aa1ccbaf628a406389b8cf2e166e8a7ee6f51a802c9a66d3c8955b98aa312e2a9ec0ac954fe275962ef6f435524c8d71754fa9b266be3ffa58eb05984c25ad6884b7da766210ed0d8be3f2e20491a293a5d02e2e01f0f294cf0877532c42e5bee51b8baad4e5a3760be7fe251791b76788fa86b84601bc9254dfea2e8d5ab5aa803074486b1971df1933a06cb5d0afdfbffb27224b60195170a13e7a80fb6f6cd5c8139ff7b99ee4f5e81086fd1891cf74af11f9fbcac9ad38c7010f7e014c32300e8a450fb0c6bc9d3793c083a58ccbe87ff9a0defae2ca44ecb2bb3ea905be06f5616345213ff61cf7d0019cd84dad7e817def95a653e3bcd852e5f68cd38c78fb5b8aec749d863ce468a8dcdb07e08f5a7d8855f7dcbc29110015bd0ea0b601f9fe9b54c13c6febfa4c3d3c8a6032b23199439812f6bc8d5d0355232df94009d1fbd60f757c9bd8121b6845c561784cff4db483430a6353c6afc935400f4601c82504e270089834059fbaedf995be94939a9260a88920713c82f71bb4e01dc8776507a2654388432a28e62d9711439e5c2587e451b49ab1bd62e7b4b3b95280897107674ca421a6f1b1ee1ab9e801bc8e552ab348db7056a30d1567144c1d2b9a6ca8531f37c946f1126b4d02152660d44f941a06b222a95e9d196c76ca20734b34dd90629d04c9f1fc80a84098d423805a85962d207766ce0f0018c1e401bd03a0e106067d6add5d6f0cd68d673405e44aee172cf5e1be295b71ce4f2bf46be938ad379d1937f92285ca2e85bf7f02d6bc6703b2569220339f7a0ac390f303b28a559eaba3a964ebc6bc314647d1a57fdd8c184e1b783866f83ceea83452fe67e93be82f1eae2a7bd40626f9b862b46166ac0b15e30538b32df3dc9e13290bdf9403c92716998d786c83da2251644880ec58b3d2a42086511d6d8574d5089109edab051efa61c22e41c8fa4a307dc8ff3cf931e0280b288248d001060abf29cae62cdf8698dcc2b9b00db1e811a5a6d86d46f96fe6363cec490aa1a3065bc085bd313f589041c19f84ea6d5545900e76a8bcfe06b57190dc7c09c9a9900a906940dfcc2e6ce46901133f5eaa312604e38963da23255395a108512fa06b2101c18c08ab99047f9187453fe3acc02923d745901f45fee7eef0a5fce072bf92c70cf04ddc809949904f0543925750e0cf64b0c23d612550b62b5feb09ceacbd19dd54af97dffd43d280ee6f9ca1d1adebdf450eb1160b5b775bd82773c2395a294f7aab42642a845989d39051a0849b419970a218da81a9002efa33fe82d2054ac06f3f93bc883dff73948fe46ad8471985ed3b89e3108a1660d7c90ccdb13b3c8ce98816fc82c7907ec6616a968377e4554aeba8f04091818df5ebffc17e7f5a6dac18ab58099caa73bb14f12effb29f2d06a07a875d521ea26f0cf010440d04c84f800f43555c3067772910a4679360b1b1a9d974794810b460d157dc093efd384d05efa6d459307c3fa51e3686a2591e9a73eebee094499d2f0c6e87608ffcee4a9fc5c2bc84f7219e546d621a26d621af21bbcd42c1e0ab8679c00dc89e57cb24600f2f60d5e8e36c916a07f030d0565ae6aa68d49550ef4eb20be073eccfb67d53a8d886a20b9969672f82c42dafc94ca9deacf501fd7acdafa49575cda1cbae8af2df4600822c251203060a63670323537648ee31df6ca0758e30038d032d2c18aa8abfecb39c3d71a9fae5f8a55419e9b831f62c4128a5cc6762285de97b50d192974fd95680082a66027b57aa81b6fd02d0d200763f3809f9afe144399e3e3ff6e79f9b60b2e68ae49665586f0db73364dc75eebcfec0183c66ec5e24a065babbb181e4283bdfe0396f3fec13f2d19eb54a04297dc68b92d7ae21c84fdf7877b0b1e64baeeaa90958649135d958d5a1f121b824243d930e20efd8ab48c450c5cce97b867a8ee2757500242556f27e0230e3789bef5384bde0cc634f2e911e8f4d7ccfa42660497c2640e27de99d97aa52be48e358494da53378db20b8307180593abb0c0bd4e3a7cd5e3d000d5a65f27606d805b9dd85a009fbee5b9b1297485abab303de0bcdf024b10e2c00da2c75eb664c3ca158b56dd3550df2a0e4673b63be8664d8298ab9e0d949b2b5e14db08ada23bac0d33d10393acca5498e6132c09a0d7ea19f364badbb04c0362cacdf639e8c362bacc9d636ae0589f7d7ab8fa51e674d3bb59eec11081c29d3de0e51d98a2229efe39d4115a48380be1a3fe47c865d629f0777172cf99ee0550596b1721296132adf833b8ded1ff0c635d550a731c1fd53878ddfb114529d93dc9ca95ccc78093e0a1cfbe112c1c81ed9a19bc4c9e03f40ed2c2cfeda5cbca4314a5e350371a382d439484268e144d40884bc4b3f6dd2302b4cd5b79a201ea089e11ea718b0daa7d759c322da82a6e4b1ae151ab2a5334d1a6e3583828a8fe5906c59c5e80823de219d7b46190aab8f6d91177e4d4c76d0d9803f8a8e8a7d25213c5dda55877909afd9a221f156bebd4a04ea5959710a2545ef5ad868a92ed9e393f6425f2521b64b9f6e33784a135e2b47d5e8245eb45018adf9e60235cbbbac84c534b19c9dbe15d51a228b46a5b7ca2fb5dd47e00742f7bf912ff05f33f4bbb15470860842c6602a5671bb4f6bc8111afc32412d632013f154c1e404e29f98642f8d1ce31b61e44b0d4850b0a88140101ad777ed260be2aa308b0778b6ffb9f647700b8cec886748753301c8a1b94e191c6f1ffc809b941671262f47e470da7aefe645fdabd7690545858c7ba72535f8c93462f5bfedf20833f7538626bbe8fdbd0022632c09a85034f37d55cdbb4043dac676575e6a5fcbb168367b4cf79a5674d2560aad9df8c0519e347a99048afa1d7ab49ee3ad88f8b052e9236032f3714e02d0f86612a5ba5da8b8791b0d2b884156e3b53e15432954d82d8f44e8404b9fb686c9d660aafad9eb72ee167cb870dc2870f66a3b728b112e643d77204589b48cd24ef8d7c3398edec8b9d04a456dc8af1ea307b01df1f9c8124c8a4e0f609d157ec7b1b00cbc32d0446c283befbec67f0092370eac1d4efe3ba513d831f6f2a0485e562e7d1d777b318de7dea2650848949c897bedc4b0eac15af6e3232239489b38299703af385c6350062e234277c949eb388bf3c71071636fa78dcad7bb35649f4b99cda7602b08cc419b242e8003428ad2de84829e439630820d26c6ed15803e2f8226998f0bd70e168ddbec01052f2b5719ddc076c047e5589e28bcebbda98f043f28b94333092776a3b664a7a442294367a9cc12e3eb916c106cdadf37821ee138cd01590a280ccb7196f7359ff43601220037f15351f90c8bfe326b2912c63b1abb60d27beec7ab089cfd8a6b8a8668712082f0d5e1ae218bba4f881c4080eda61215dfa81de9db77eaaabe03621077bbc0e31c8061a842a50e498040eabb93fadf6dcae0421ff97c4fff000b6b95d20fdc102bc277845228196140465e344b3b2d3a988607305fb635b78224f2bb0e6059a117773a6b6404c20a67c08812763ec899d02f16483a6aa2d17ad33824e5560024c864aa7159a65e66476f9cea7c2039774265c70ff6d090b2dea90f41ae935410510c95460736b1432b2b1d31150c090dd98f556740ff5a7c19bf02594d043063641973d8593184dc99041e9b758bdbe5eeebf04187186c2be40d04a7f70fa1ace7b20d848828a8b205ec7f63aa8c4244b2ebcc686d7562989c842791a9717a79ce48fcc533cd4a61fcd622c088a738f3e9c63071408b960c00d6080692bfda90c834b9bd843014a8b4fad45e3d9b781ea33198e685edd572c7e9c764dc035d98f8a0124007c00db41b49668c1e30a788b1902a18fd9e542dc1a6650b8083ce4d15c887dab119fffdeb35bbd8bdc3a199ab109a81751412579f325e27e1bb6073756f0610fd36e4221ab192d92a5864fd49458dc9f28e0155a7f5dc7c77d0db38b29a706f1e33446432e14cf8d4685d21c249515a775f2b15f5b8cd0b6bdefb6eaf7d85e19602f31aedfa55bc2d088aee2dcc7b4deb2e4055a2c383c64cb0b88879c18650774ed4484f0afd1dcf17b884ebc54abf837cc8e8d716c10151c5a2153df11441d06b853f8afb29a002b90432b91138863e06601eeb070858addacfd919382e8ecb0c8738e6ee90bad64f5d97b99cd5df16c84b2ec7b892c4626f19bacf8affe41b1ffd2870aa71bb20ca8d08199d7c37f9142d2e71e8b2963629e3ba95860f7561223e3550826b091c6302b4a7b92d06dd6a32e09870c5997bcb3086a10ed122fd48eb37847dba56fc0caa07cbc8e4d02c0448abb2af94701380069cf61895482432839be705177b24fe6027dbe8ea2677b81d25aaa76febc862134c6bea7fd3ffff034cb208078f74348795c947d5c98437e4309ad73fc2ddb62481810cd8c68f09e2de766074287bfa634c3726a452e3a3ed3566fa58e0666e193008b340df8f169bb9d0146fa04037e443ff187d976f89ce99acfa1ebbfef362d7a55cc56831d515b5c405e5c20816970d389276c91c505a33b7b16651be3de8d3610c8ec6b8eeee8025fc08467053de9315ff1506123b7d152819543244fe18d774f346f426d1db3995f1339b8160dbc426e6b8bb86ceb0cd8f131c235b949383eaaa49060c43ea11e3947ed36035bbcc1e70cd23602bcd80050556f7caad37c7df14ea10130ae8e0ca06dadd032158d2081050aa3d0b7a2f9453705808aaac28b258f43e3c3976829375de84941fd8c364062fa585e75a94ed8569e0487e3b6dd0cb23e3cc84186fcfe04c3874d7789f8194a6035d1f88ab96047335a0d1aec2f12d113de20ea0d8bd41b353a145157296fe8a5820b49b1e5b2f832a672ca0dbd8977fce6a15f8f59ea5763a93797fad35fd7fef409ff8997bd4e20631a39b5fdc30c8893f7cfd4417329e531e1b1b8551063296bc59442dfa3a51bf84e97a86040e0282e890732f24d7b45f78ba72ca4802e835b645a25340425bd52e880f2f76f5737007b433936ba70f2a77cbc9ef8a3905e8aeb576b8b3a0da2493b6cefa1f3cc723799d966c800376b09851d05e951d839c60b5acd483a5be2029e3cb180d273a8c97f34c3696b96f1614340c5bea19fcfb57548e082978e9caeffaa7c3e6a8465ac69884ae9a5fa8795764de3277d8497a8556540c78d0ac89589766de4f95f967479524e6a8ad52f06b0f73661badfd876fe4389c3b992c1932575e5142a12d8c3283e62d77c4dbd490278891645b5cf5d79ff47a1f0da6bf7fed837e1ad123167495919232c4ecacdf8df5fc8363388ca7d80152f20c0be8096d0b089ca1fdd1b89b9f012f347df3f260bba9fd6349ea90be4b3a67a6cf2ba67c001768ebf14d94b970e4af867b8a377a38ebc2c4b00ea9c32a9a0b2c27211720284b3990c960442b2c5676fb7870969426e45f2fa55c3d90f2c130f9639d6bcbf9d301b184449a49f57033d1f0b8f648612f632c9194a66d7c90625f0273b34a616da80100cedecb1c346acdabf2890a37f519703134e080eba6b3bb577a8e50ec452cb5d36dedfb39efdc8bfe76ad77b960d94dc5793eb081ccce4be737fe328ed64daa249a962ac38ec6abbe62998a55b743b1802103038994fb32de13b30ceeb256ab7686515f238c411ce8fd53ea3b291a5e069565cb2a463b456970b402db7b4b59c2bdae5e8f4cfe7850fe29b9ff434e96138f4d97d219a91c02433d794d7ef3fa957fecaaea390fbc37f883aa5aa6d9e3e61313d8819408ac00b01421722d3ed85ed9b5a42074497db80e134b6e47de5541652d8c4406c6b4f2ef915242464f507d0faf8d40fc3b85c70c28f6383830908ad1285e98ed57b019218e6ab345e2d861f32b5335d95b6cb57e8f69b1690ca37fc3b2539cd7d0c5139ac2405a42e8ccdd221699ce49fe0b31af59b240262e2cfa7c31413343f3cb9b639ca99082e8ddceaab25785449014f0f87daeef5bff1a93cda2a04145657a65d3e4dbd34cd5a55c5272f2589614a12b18953a987b45f5279a5319eece2433086bbb413aa4d8e0e79810d7ac1c9da442b321de3f24b628475bb58ce3f8b647402b7cf0776fb36de6be8f82eab211afef4962028fa7b6c869c7fa7abd36c787fb881ac081e9abe97bb8662e01fcb5a178691b92d8df73514bb6603fcff49a98d6e69ee73675127ccec4de8abb6abd11c571120d2a4c9c93df0f2c1336e0370c5e0d341b3a7bda4abde45f3ef5c24ad485300d14e39c80693bc79076a5cab199bc4d87eeecca899552f768295efe5aaea468806a434d58b1bd452e84c7693000bd1dc17d22f03e3e7d56e51dbdea735b2a20e2099319d38dfb254d8162fc1920d2fec08231ef93c4facac015d28421d7eaa69233612782027f3946845d8b4ecfc9bc53e0b6ef99e5243eced19046f2ff3eead6c03a1e2fbe59e64c51cd16ac3edfc6c2543ba940de71212c87a65aa58cb1e4e8af50ff4bacba03a45fa62bff84e2e90e82c35e9a17477024cd3e1bd252ac79174569461529a7d2400135431132aa4dc3a3d1eca9074dfdd01b88a1750c01aa7f6b8db8f784c3ca268fce810ea9cf79a949ba7c218136276239c1a19647358be4ae93d0db7ea0e099e9e201711a8e1794da1eec4d5152b212ddcaf2511ab6f0f14e417782cca263030e270f6517e533d4c3e786556f2f33a3a7391efa57dd00cdb1f21e33a1089b236164faa61d1fb629f31e4a043b276b7d0af04f8917a905a8ab0b739b2f45f6614bcd01800069f5d08fffe2b901b54b546103ba68bae5e9681bef7972d0a9740eeefa74777e20868c3cf2c038304331c80650b0d11218394f0dae64525b3276f5a8b293d6fa6aedcdffe2e579d76ddfcdebde318e0beee8733db0e5735f34de8a9dc0bae70ba7f6c75754c0f296e633c14502c2985f570abbdf43c256205546046df4303c43c9e3b807b9a5bea358093815e30adc0865d468236e471c7ceed8491214e586eab5d8b057313d6e2377e011e040dc8b99a5a34e4bfcdfefd4cee2d21eafeb9b6380bb64999f4a03aff982d3145010f6854aeea347c2a75dc1585f6ae5a93dbc339edd7ce8b1e95faf57b80420bc5054ea54664b2111c90f563ace99304f558845cbeb39bd24d2dc720f264c4c09eade6024e681d6e4d00cd1cb756e96e945fe6d058d5aaa841cbfb35867ea4871139fad8fae24f2431c431b78d763a74eca3e19d1107de288c209fbebcf5434100c1ed3dabaaae7db3c7ef768d1e0414f6e0098b732f8ccd195164fa44787ca48c5cd5af50046139ef2563734a146d0af255af9d8ca577b5f4ffee958472a86cb567a250aab3692385aad4bb0cbed9e18734a706388e04de02873821584f740b7413becb3e6aa949540a291da42553c9937844918882aa350590d950a2b0f09ad361b72b52e92bd2be83b62bec9992ddc2ef64c814b2dce7202374eaef7b87fd87cddf5cfaa070cb70859865dc09995b75e38229f9666dea7d86c758a01deb0019cc98f8f80d547a31f96dfc34f7ad137ff40b078010831ec5f66ef11ec79dd7897e5016a27ee7433ec94fe44e194476a31fae1abe1898e6ef1f217330600a51772845c99a58dc458fb586d9b4461d85c17877b44531c759e8495a5c1b947c3320046546c7646d425446441ec625af8aeea8b996f2072a25ca75c6701d696ca661f42d0fbd79a9301b671f0b10a9683e4c69d7b85e20492cb52103ec0dd3b50725600eb38f9e1c73477e753a054f7e27890ad265d309091fc20483a89447c4725302c8d840b6902a184564fa69836f7b264f9a886418dd8af14b4464794cd9169fe1479c2892dd07c79d7bb1b256a69a3d591ea7638b36525612cd5f8c37d8023fcc2453922727ac17991d488cb123dc6305af30c6f7e09a2c130f447e461070739983dc69a79869afc2f22244be79dcbc425ecbf5ebd25175f0959084c4852f193e3c42a7496c5499c218f0a4f1d6da180846cc32b069a2693517b9e143655ad208fbb0e0c94fba56a566fead23db25984ea519fcc6bccf4f10ab93359675e629a61bb0aeb7aad21cbb69d0d6b2165a4da24b1ead27297c2ef953d2fb56e428bdf119c857cce8e3e72d3840437195cfe4f48398d3f1f140bbab5ad5cb598e910bfe54076c60cd938324bfb80c4c1b4b7f9857101fe3a167b4112a5150fa32c8b2c02ac6b39834317ff020dd31976d79907eb9322c631b18181d28591b4f7c29a9e89501a20ae4165ce26e4aa0953e0ec577fa29b33e0f8b8ac71d4d7facaac4d6e82132e0702dbde595d3e3c28a26983b56dc1dcd2e35ad2bca263f48dabc33e619d7c66beddd552451d0d82e343d94fbb1f56e1c6ed1f926f0c1436c930c4744b9c42e283adac80362d586090c18c5facaee896c99914bcf61db531360366050601e296c622d155b88ada2f6996583afc6e2094a0c404affe21e03984faf0eec8c5f8851a6f3c886caa2d6a45657f2e2680451839b8f5506ba9ad094d6118b933ae99a0114c5dca9e727e4adae010a422b21c985352aaac231c6d1d30fc4b1f9b0f67e33de2ad88c1410ad6cd8635e094b3c94b9a2e30b9771e14ba302e86a4066a24c17c832eb442145578c11bb28b275d3ec9269ab1b9d171340fa8a732f98dd2c5310a0c4ebdac0ef893ca3009ad3d08524de5595a1641caee26bbd35b310b1621f42a53e0ba7f9b83869c2eff83444c5343ffb7062be5eb2b42064d800dee3e434d12c6d22910657b56ed776eb15f18f6af15ed5bba861cc443526199e5671064598e41160f608715a384919c07bce9c626e591fcd28bae7f542c41f401c9a56e1c9225cede9bea8203b1eb04b7eaeddf1a56b12978ae89f8c8fdc183101de812691a76fb525c6eec4f77146ead13f56facc004ba5bf294d5998881f4a8254ec9c0364be2449628b9ed5eaacc1f500120d04cfb053f00e122870b796ce2d89936b4911680a2d1f3f6384ba29592fc67ac0095be8472f54633425970479cfa723d5caa4115ec4b2f0dc2418f71cea39d4dd9a19b5c8793f846ca887e2117c8c7ddd80e0efe7cb3e87d1408a8315d59adae5e045f011b165df43b150580378406a733bc47cebb9884ee42fb402719017dca8d348ec47e46291f9e84c8da4cdb1bb46e6f830c155a6016a493da9b40720c60a43903b9b5dd807d6043a15b1bdfd0b2e56cc71d28cab1ea5892a252966a387589676ee3a8db4cb113f7730fdbb95ab6810d09814a71771c0e566baf178a5ac484f3b54bd8bc9d5914bbc64558990f4101ee161542e1afd17918e405cfac6a9447755ebfd5cbb458e42f7497895aa618dafc41ba16bbfaf4aefcfbace56237f6007d2408de9fa3c1a300ebbb454d25ed2ca5774f801e5c07ca8f173e0db6c8066bca834942b65706065a07fab99155d2153910dce3d49139002c18daaa32ddcdce29cdca649d7ed2d0c5ac55719924d499591067d8c240721476a069a4b21cbc2387f15ec365934f089e68f7cdf78fd306579fa222663ca8479bd52be7dd31e85250833bb4901af3083c482810b457d39413ccd341171a91599a924396e6a9331f8a2654fccd7dbf49b768a3da7d802de758436f7ac790e7140e8c1096cc3b79f193d0819f6187846983f01deb695f0c9bcd92b7df7bf148573d0ce74260d4a67d19a534b6faed63f1db2135d4348be5a2502c9192e3b7a4efab2be1afda474050c4a888bc086f172d42359d80c293534c75da7bbe131e1cb5e49843e4cfd76ecc30e55da21f8d0cace97e4fe6591bfa328b8c7395827c4d463f7f7084eeccc5c2f5b7a9656ad8212582a89dd954f3279a24d9f79c23ad80955528fe86554244ebd0962f1b4c8d029dcd1c9bbb1e0db8e20365aeae6f7708db4ed7745c31025c97be014582bd777b904220ca32513822a0299cf8c9dd9acdd175b041e04d3d964c15d12ea300f9187c50a2f4588479ffd48b2ead3b39cce2509a7ce73ee7b41291705176251b0c476ad76eff1768c1f73869241453edfa879edca4675ddfd221e6ec2c96fb6b0dd9c51527be2c0a65cae707162a7b5437dab4aebea731fd430b6a068669e96d4e72732bbd8aeb6b83ef9dbd1e7807e9b89ca7232dd29b06981612c98de8f933239dc09ccad8fff6aa2622e2dea10c8ef8645e6839cc9532e3727d65d24577f2ca4e4d942b65c6c0551a148a9d4b6df27b9c46ca0acc93a9b03e8b92a788abd2b1c22ee6d96ba30d6e986881a72fc4c3436c1e9337d01a2e831c57ca37b90181965cf24864f79d4a03559573af21d095ae681cad420ad38d062cc32f0313a6d3d0d39dcc3a59d105f71d7d4c5a0efa8ddf2c2df17926b163d08b365c482c61a318532bc536436046313d1337db001edf32433ca5d01fed13b764491065e3f41fdd647d52d0bda47ae297454762e4734b71b3ddc80b556088148f69ee3197e12faa028d73496847793201c7203c21ab4747fd6d3f39a99b8325a4618101878b9c8850986898593ff073ded90d618759cf968c6affa2a9d49c894e0c103f8f2d9cc7def29720cdf391bea7874b4c9e2267be6e1cd0bfddc787a910fbb583d9dde7c5a8cae5f98d08492269da8e925faa4c2e6b235975f3566014cf6be0e4800c1ca3000bef0bede8b633d62a0e3aa57d887cbf5082f494fe0897f70cfa7883b18649d18e9e74e12cce41318699934713bfd8d72bcb48815b11f2029ed4f7e7bf61d01e9ef7e3b79474d63b1da5246f67cb0976f25eb06b8a3f6ff77cb18476666dec20203a19cf66ea2d5d1dc6481de6aa6038896ddc5b6a23c89c8b527ea9c847bd292b8501821ec371841aa8e80852a56e2b74ed43f69b832eaf8ae541233cf034e35d6551fd9aaa8745520b4190e53084369719b1818309fc90ed9c0f8cc0e346b547e27c5963d6a70551ef96aa0ec1bb66ee2ff36586f89581afbe02b18abead73826db99964adc8accbe2b0e575e1e4b02285c9f1edcae4fcd25c21c24cd017f181cf8e2608fd065c150f484c34e03ed9b0e04f0899a6d79e7a3b24f07b1d786827edb11c69190a2b2a4a7012114fe7426c0962c8d0daf68520523242c4cd8a79d28532f30db1f2a69287c2e5351e83597cbca39b565558813bfacc3e066b34a29dcbf7eb687d8a3eac0f74ebdc84d8687a2bdc14621b570d9ae68957f21bb1d170617a6d3222d29162b8fbf7844a1fe6e77511cce701f42fbe9810ac88e67ecb366fc2f7d09b0dbc4e311da54556b170c685297de1b582e8628a820a372fb3338d7206446931abbab099436b668ea1ef97ff835a10e79a7bb7b8548c64af3bc7447eb332f90dc4ca2823d6843d6977558b47ca46cf70f47a84d6664cb51b9e3c7e1724a6511add330e6502c9401abe234a5ca06386a12b8c9bf33ed1ff1152df4bed80fc88ffeca8607b2c31ce74c5af8af3120f184dbc4a3b4ef868cceb73ba5bbf9de2ac03d9c0b3402a22c4c576a2bb8938f11ababc51f60bc2ed69c6efcdcf14c32287630cb5dcdb8344976a06d3a94b563b185b5d1a2a7dde5f7f423054a0d7c6de0da97c6f1d0424041be051c3c1575792bc367782e2c5ec59bf39821312eaaf2943f6408a6da2cd1ca9408e719cf214d18352ad75ee87f548fcee57048f811aa8015dd06d2203870c48d97f29f34317a463a187fdad7f8a624cbe52ddd82df970e149f237a52b22357e243cfcf1d0bf8fb648e25a145cc12ccfa9cdffa277ed573dd5459163a89e1c91ba51b5b77c5bf38915b1ed8246371a76dd6b112454a02258a2552efac28748b60a1713a13586c6993628432e86e02a57013e3b0edb26274b2c84983aa8d6151a742436d9c66294d8c2c43dbd3cff4e7a6dec0280132db05d4ca5758cb6efbde6443886e99e8df14768d3e4541ee22ab6182c230ea1de82ea2542052af55a2e300d404c33a4a5564966250fdcdaee95913187886e2e5d9cf139f460e04fe525f5ed80bbd14622a7ab6df195acf716858afde0cf5458c0c151ae669c02de8dcd2a3bd6a9edafad2a3e0374e7c0bf7a26252ef1b58bff91481c96a3b682b47d9249951d0c0cddafa6c9768e8f9027a19df7ce421f68eb96ac4e09348b1c49f86b3566ac8233e25dc4e50180dd13d8afcd6b60ec31555db2ffc2129b403b2a3f75c376147dd61d00e4f3f992a3aef3b9620006a3dcb894cc4fa3e276586c25df299cd082aed8a8bba8315e8cb0945b221631934d295d9cd4228f6f1d15650d8deb1fe015654cf02b37054667d2b8c406c054431762bde5c0772e93c794c78141eee7d42c425a437c49ffb70efade4470fff1eb15f0e76dfca6139b15500e0187b1ed594938e2b5bb0330ba7c3bd21197de90b01eb5eb627d7a3269b090dc0d2b018d113ddb145b43df6327abcc90327cc3fd40fc00f69f73f02e8653e44739fdec51f882c81c0023d9d717dbe2e3bbee73358c5d40b265cd0d41cdee8ff41515e20a4228219b62a95a28ab7b5d0529687c67efa7e456fe8c7faaf64b5f42b72e153acc6f3ff626d55d55b798ab449d30d6eaab007e4c31cadcabc479172aff0e624ed5a29bf0f64f8526f5a3ff5da46fc5cbb9da2ad109bf38405e30e3b709c729623630dfd8c44f1ba60c8d4f4a9a572465f72f1ac4b3f9bb4c0830621aa513ecce2c687f8548bf44b8d2366a5cc3e6e3c0e6e9f46280ccdf54fe32832e5c47cf0f60ffbbb3854904bae2fffe82ddedf855c3ae0f00625e96f8bf669ca167bae8de609b70d3026e8dd66cc3e167769b62d29496f8eb0b891500bc82c99890faf9131fac1af68dca11964a8bddf7508c1363316956668e022c1f379206672a50be5f4c0126879eddea0b5264a63b78c9b97bed59ee80a0dc7644b56034659e640fb23f81cbc109bfc7bec422a99fcb2d05ea2f29a8b42cd38d34def0866b3fa2875c5ba2e9f0d1d9f44dd88bed2f53210338cdca23f5e5f010431c495ae6ef18e604fae4ab4f61f7fbb8895e756678a2448642e9e92c834dc494a6c8dcda9d10b4cd3038d9214f5255a8dca37cf205efb06b7c6afe9d079cae4f572ca01fb0836fb11210fcf3130b89890d64dd107ce9dfdbb2f8674cfc7884e99b9e9627b08b0cd805027582305efea400573c86e0e5c370abae2ff43e58e54d0763b86b841b0c0164b3781650c00abe410f7ce7e7c3619ac4f3caf5037c0e431a4ef9ee40c1cb335da382d591dacd7634404fcf9b5386d81b240f9fa0e1ba2eeb6b6326bd3d80417c64ac8cee3be97fe3e2b028b387489dd4e1815c13631bc5771aaaa0ce907371f91f3762f2e265bbcad13d52a51d7bb2c77915f3ba262b7377b1fa0370fcaa9429dc1fdc1c287a483749753b35969c8bcdcd2475b30c04c4305154cb4d16180948a4bdfda0a1f413806dc99b10cd9996b501b43760847881dbef3f9b720e14528463dc83bd89c331f0b6ff7ff06c0894aa8f43e1e1ced65a8e561376ec6ac3353f2a323209ca99ec2c87d165e08c179f822b1fb3921419e865a635228369a6a1e9f296727628b9bb01fe91382e27b887b7789d9c3cf244df1789cf610de8e384af0fdfb28f68fc977cec030e29b4287cd36636a20879fb87f7d23b7ec10cebbe502f2fc20f0df3b8dd3974cb2bc6c6a17f404ecf8f290534db1074ae80f8ac3b62da12b3cb91371291d06f6c2c68aad6a4e9c5d4f03a3e50ec73ab72d4a838d08ceffa84a8222a9179dbe36356f22ad65a37ab16c3b8c0b07776cec712451f0c9216486e8765d631628b077e786f25f6c09a8be12d8e2333abdc7afaf39800d52c3ec5c62b677526ed0de58320b967ad33a5a9ca941634fc473c9cd9c89d998264a4be68995708709d93897e0531aa2b93072e59430c51baba74b703b0bc5f81666dc1d582dc95cc90d050a3daefb7c449e8d38de9b2cca11c8decbd7976315b0dd0a65c0136f5afd94eae521072fdf87d10af8eb58bee8ab3dc0117807e3a5fac951eaf41654ee97b8c6b7fd270afd9432abf842e285db1ad1af4c345fa3bd00b6386fcb6f148ea0b54d002d1655be3987d122c5108e96057a0a6a16f8873a265d3784ea235444357df72e1b71a94f5e7c8e53acf8299e65008d7243f3091595f01d74a6626108ed64da46d604ad09a0dfae61362e9559739a1bb4e118ec62487b2d64e3e59ea15cd4fe4cb68b2030faea69cca8cfbeee368a707e4543e9906a5029e42e92023820ba48398e5c1ad6030ad737f5d2fc8ba6ad767847241007231fce55cda4d178828d8883a7672886153b837dffdd01728db373bdd274ce57e7c098464eedf8b9c1767dca1120200b3c3fac144e18e40bb9c8eeedbddf98877d8a7bbdc0d4b9547d2345051fa19ae842ddce7a31f7f0e7e4ba1845cbc65fff5c11eb390c24c9052073c60dfb3dd1d9eba0d55e50bca2656f72aa1e18882d9c2b7d9f4cc9a1839efa5bc164a48745648cd80ffd8a2b4235ec590a50d7f845c9131a6e900a3b354770bbf2430303fc0f6707ed934b80f9a9bf34467e4a31932b70a5e1fb41a59ccdc898c572d353f26573a5d9006c7a6aefff04a7da015a0f2aa93812e84c971b4d5e6c3bba680ddb52aa978d35af8e9ec358d517f47503ae7f7a2b9c19643e19c1953503af6826f0b6a3da01dc9a0a6254b22e99281b154f1ac6abe6673b5955780a6d988d5755c4a47c7aa037bfe4d893ffd259d7c09116adcc6a962bf180055fc309e438bcf74764ce9f0f1f7953aad086168252d3472755fa285674dc0cc45e8e6d9f79a3462bbfabb9e69e1fa06cfb24a4e25322eb8ecdc68fcbd764657e93ebd6a1f25e263bbda65698fe29ec8665988348df2b141311237c505c071cd1cebc290aced7fee869b2590f0c08c3d5020599923b46d4cc067bdf5dfaa905be4cd0a296431609c5752fe6f6afe15cef1dd44bd3768c56698314dcf570dff3d09010ad8e561a9cdc06e5429a89653fd9cb3eb02870e674c66e42183266dd74f94c7cc73537daa934c4c67e11d15037dc921abb5c1f83a812e5e3e1b9b75991c02ab33451791c6bbee7dad375bd6845c2e4aca87238a035fdada0440ba17e92f15c3516d5d261f5f94afebbe658c8a768c65f1951c428f0935674d87f9e76709969971e816ac80f6849cc50a39ebd5c138a4275c659636208ac3d846a3ff0aab876b2a0fd070d721ed3ec0f4dbbf72100d639a032d8ec3033fc4d6cf5f73d2cfc219c0c8fe52b33ce91d5d0c05d1ac80d44b71a6099bfe7fc6e96e969620ddd9e840528da9e855d700e4bef0a90d5ae666bf86012fb73e6b923528836ea7486ab5821e07c301ab80dbb2a009845d2a5551ced523a2ed5ca2bf458cff833f7c975cc3e45358dff0f9c2fe34dc0976e167a5a61d538a3918cc2059ef186238554ebe9f3f4afbdf2f792e90d8a1375c0cc247e6dc056a7421d7c2837cbe9ace2ea8f9a3070a51aa2cccea19d467bb37561a502a2d07ba507f9172fe7608502a141acceaf25639fc8580a4c351d225de7bc3bfd190cd18f1ba6b4d2a20c83b29158ed795d658fa7fc5566a77a3cc04fc682f37c97d83d655e3764e46f74fc458c0ba43668fe2c01a3a75c4d6c5d49a5aced5309e9bdc191577cd4e7e81009b452480ed7b4953c0c30948ee70e06483bfeaa45b31a1f4e2329d7d4381da3caa4f76c48666006de24e3c71fadd2b73ddc505d7e68e0010648886ea4c7b1872e901af3ef1ab6e99dd7267925287a58008a18d9a351701aaf6708c1c910cd5e551826e32c3406202c48fc19ee87c588a5532c924740dad8a97ba3726e18abb32ffad4c03a0a58b73edebe6e680f256f6df9f955960ace13cc493d42fa92524fb2c3008ad476485b3896c7d6b52ee8b08d174c4a74299bf242d53a3b62a5feeca001f688bb940401c1f6a7b66f8556c8cab936afe1a4b2f39021a0e809782cff543bb044de9968d6d58ce3f19d67f1757d4c539d0a96fe343f66fb0157040c1e6fd4952dc5b607d1af149f10bfc053a3d66fadbeac8998d844263369139aa92b4d354625ec2decfd50e27c4af88dc6983e4084f42a77c05c9b28e099b6fffd7fff2f3c922f258d847333a1df9a11fe629b339cc00ee12dfe4a346e6c157043f2b02ef288af3ad6b8baa3a5006a5b3182d05f7139ffd1e0968b1d28feab3840ad46630dbf07145a53e3ba6b2ab8a3e5870b26759d09e387c12b81a8812ae9028c283eb74df4b66d84ed623ccbb20728573421bef80e0f39e5ff6fd6cbd4cf05015535659d2428b404386ca0d999af5313e46b9b5a696227e753b6b90c9ea079589c26744d8f2e3a06a76d0e3e0ad4b019bbfbceb5b0ca11099e505446ac2312c19c9ddaf671342843fb96a1ff8e74d9edf1ab8805036346aaeb9c61c26c39d6b7c0ba61cfd03dc9999b0adb7f470f7411366d35111614a981b18419f173f9d18bd55c648a3255d96e90f41f3c97a9cc7dc32fbc4499fe3fcd37a213453aa431ce7a3502453a41de12a57b416b2819f3adfe3f7359b439035f3685ec44ac494ad12b1b024b1269e442eccb26c1228b759943590d9f121e2ec23ace21de028aa5554ac075a570bf23a49f90a055ddc7fcffd7cf2a766e0ad2d9ee874fa14dabc6d1fc0b133b9077590556a75c34c9c100016ac25aff297eca835773c0d3fc1386a92cb70190b0e38d02d9744f1bb8e9c69077866ff769e94caabc831173031e42a56a1033fb4771d2496fec9b73b48ae85c6f09a77d8d2fd45dff35ec913b8b2be3be4fab327212db665839b4b30127553504fc64e3018421dd88315448c14b4b4140f3eff580b91fc0acbbcb50856f5c3d3e64441e518e8f70c0297c96f9bf1961ab659ed18334426633c6645f2b32b23039f9039dc7330850a7f36a11df3175fcc1ddd56e8c1331933c9090756ed79f44e140779d7ee8fff4fe35e2dba865934c838659e7c7c154145af581a95e313e8b96a8c84bd79988116ca066f1b2d2fe9bceadfb2be888d9d03ba5211e13368ebac095f5d3f22236682290020b106b60da97f440b7bf0c1002baf5ca6c393752ab6a16f445c498fac32fe4545608a83501604e5986e89ffcb1e21c1b15c5702008f372d98431ab00ec2727adb3f9b481b5ec46964a48a03c547953644fa82299ba1633bb1325de173c888b6d0fba73f60ac71769ae9bc1a1864722a0bf2522edbe0cef58d2593b8ef84fa148f83b3989325a3c466cf37d921f2454a80bfffd0c5600fc7614d21432477c2e9bf60e8db96aeb8979c45cb15fc5de508c8dc132c2fb716938f86e0042822bcb045626759f42ebe86830c21fef26c142d11d10e81beeb796f71e697b4bda6e87a65f798ab10ee020567bb90f47ecd7d178026066f5051fc09e3643b135964493d3a9150c10aeb77c1a67a0e9ad9b0b98bf225a1093bcd4113a7ccd98754a23a29c9a595ec357dc38ee5a00ad444877c45b8dddf57ffd059dc316c983ae51688eeceb41eec7c5208a29d7066c0f27eea60f108bf9e4a493a6090ebb33ef52a2d5e8e8258fed06f91a675b5632e4ab8587569ea745e32fd5d53ed44e97b1df1dc15274fdec844bf609ef7be6888b9a4b3bebcc14901ed2d6ce75720882b7ddf5a6f471fad1b971229b6445be6677ed343f2fdddebfd7f4a9ac608216abc26000e7e22a335b56fa77ad8b8c9aa5db01582009ec456c75382ef6475991d20d4abd8a5b19c5ed7e5056997443495f622b4471dd17dcca916e52c247bcca08eef683b10ad20d4a7a88bd0286eb7d40563aba41299fe25740e3b6cf94558d6e50c253acd548dcee3365f5a21b4af613b32216f7fdc7ad507493125e62558e1af71dfbc859ed886e5948bbaf80d80956da463a742367d91737e24c78b891db1c5602151452c53dba09ece79d52098b27db75b3d8c98c7d8c45570752b7203bd7982e035ef26b82df4833e2072826e826cd881eb6ecaef05332a547fa51a1a20c6f47c513a86341ae762c859430519387acd21db5403eae259f9b767943f3ef067e8a9bc94736eabd3bdf76ec70e531ddde0d2bb96c7a8229b788be98de956671ec3b8e67ed0bce7eda623ba58c004e36e27a6d1bb1901766da6e47eeb61de178675b2487c2c18da6b9ab581eb85327cef0c589e1d24421139838b133eb4d03999dd89ff96606e11e0b5975dcbc15501f4a4f966a689465f63686c9e5de0cf3b9377ff6f1bc8d475b1a120187d67a6a155592886a4663f3a5dfd82682bdf2a3065420dbedc4d7cbe8794b064064f48a9da37462f39f8696661d0e07561daf837faa13606581f6c8f6a1cc7b9007ee86c91cc0adceaae33c4d662f378da9b3e4daecb2ffb3bb3ac4b2c958fc484a9ce3b1addb2eabe86fa20eda992b4111a34e38eca5dc6ac4029976b4c5285cd9ded1e4c1856668f67800c02f2eaf655b9de333099d66258283435a1122427acf282ff1df2888087ef5d879789ff79a8d1590dedc6ca2a1c4e16ea9e788056efbd1d77dd89078dbdc42f4b1bb1e36bfae2d2a11dc0ba61a30a69dfac579121fea16adbac7b616050ea273a5d3eac59c554d04b9c9e47cdde1ee423cfabbf207603158716d89c40a474c9c35f32fbed84f1269c1be6ce1dbd542c741b1274655cf57aba07cad011ddb1c88880eaccdc780b22c1fd4aed8d23b28f5268fd996094772325b6534b06b366f8d510b926025c964f44014b745ab08fc515bd03ced035efbe32409e413a3a9f5622942a171c3e048dcb4a83ffe0619b715d418f17cdc1d0dde925b4d04ee3d54707dba453d900ce9ba8b70dea42de0969aa8f86ad901bdf4b2d460e64720a39ad3129d133e453bd66d9bed4010729b3cb37a18b58c4d871a7806e88f124ef0c8209af016a799b3166077a92508e98e6955acad131e49b664f73c26d7441c25c85911f05fa4cdb90eff8c4fde928a848176e4e65d76418d2573387599336d2e94b088ebee90a2e55ae3ea4dda87455a9ec6f6e426f0a6d75d2b4e31212e757c85e7a8ba25dbac58a80d2689217b07ca313138113cc427a92f947eabcaab4da4a3d85d7a1c96c94e3fd9f88683756a907129fdccd626173953838a69a2e13cb73146e4bb94eb7dcffeec28d3afef7a75ed2ffaf59359a087e818f5d71a459eece76fe84774bbfd7337606c40162bb991d64fd930c580a8df05ce481d769b53dba94eac66a7681b45c6a04a3ce7f5c9743ddd01bb69223fea1ff8aeb6a4d782689f3bcc87db30e744a8d2cdbc52ec5654fa4db4a756d76dd1e10aa670b137450e28b9cb5d666bf8283aa86bfa28fd83cd88639082545e0605b954d647f26d617f8d374555c00a4c2d16c25e7b57b92427f26cdada6f0cc28f11749e3435d4d92b9b1583ff494d2c616d3200ebd8b7d753c2f16e6412197866a4b970b0af782ba18b7be7de2a05fe2ea294b66da682076a3fc45d010aae87afab12d65d23372135797cc3989fe22aa1817bde71d55156727cdba514ea6b8f9422b3a51cca8f98a9d8e045c08f8ce951a58cd5dcc6b71c94771b308d8758f0d8a8b710fa7471d66624e49ab59e2ab2294e6c2683eca725bd96fe214d3c5a807d7fd4d7c86a81f419dd97e737527af61b954d293832dac46a45a04e4b36ae453d68d308688acbed87eb6274b810c088258805bcab1325f857c6f5a2c0b5dee3fbd61b6f1efdd8a3b2e80cc4b30b405cbbb50719fbf185abf4015b97b4fb8887e12fc15d79df35ceb0ff6358f6fd5cc51de8eb6962a29d68f436efeaf98a480450fe1d1ddbe2e092f8a9847f7d9ef01046d2cd03a73966651f2a62494754fff0599a1a2bc83cb98010f54e711fa83ba98b5c42eac7cf9894de7720bdb6df40be3b469d2390264107c87016746a082e5d337e92935177209288434da097957266a6431655b39646ca3ec312464cdc060e1af0c918601708842bc5199aed13adb74143befcbc5384d86d747a292e08fb6eed3eb7b5d950c63cc04f2f674a4a0cd5ec0d9a7cf49897b1bbbfc7bc99afa11822f978fee6017de40f56fbef600f6814d8cf120fc9c1baa54628ee9cd958bb94c55df5e7408f5a011c430adf7826a9649d828b76cb3e708ae6fb70442773edc0290a177d7b5f1fea71f0e02aad92d586143c8c0154d0c99cf5b3c6e00e044277fa4518af4134e9e13c6711af5b5e3a42db5cf78a401dcdb233be5389a101a5f0ffd43dc90e8704e83a87d4b9b357c579521dc3288ffe4c1effcbabb1b18bdddcc492deba69ed5245d1346f0acab78b61fe1b14482fe23e918e12ee461d413e76aa4c520844ba022e5b80ba2a804ec398aeb749b153100d143dddda970424e98ff5c56a804aaf253451201abdfe7c4245fef3ce987dac407c4c8e1d024c27749b1deb6c21f9dd7747fe1e30458ddc52ca8b48d0fc9fd6ec3a6e6e49a3940d81e0e6db257a720047a3fcea6b266a75efbcf37b4463fcd19be9e1e09f19c62bc3278d4918eecc437806c651a6f2c9b1df0684146c608f4b25753df88dc7167e0bcf1f323a996ebc4d4c3126baaf192e4fed095a35ae853fd0633b3797998e067197738185f1c1e04b8c8facf61dea4c8cf0b00cb2e0b4a2dbddd3ee849e7695f7fb8ed4efd2924025f0b88b9d9ec9cbfc1bf00796d165553b515dcf2daa994e15d09bc4bdcf48a178d163444bbd57e6cc0742de2c71a540c237df3bff4647b466b829e522a811c4c701d1aaf027c2447c141bee3916fa72d4486c5dedf7d52fe7ccdb4c3d025fcae073635c9af3553831834a86d898a7909064a376cce3f9d30b48eaaa51ba9422202014733d6d8df4843a7d08eb4881474a746efcca5dd10a42996132f02dd1a6c280555a22da7876a9232a419858cd62f61d53307ee6b4b24b3f5008d437c8f04b876467ef742406a65e6e9c4e90cd0f4d129bdf40a10688a19d8603b689af258c516eb150408370db4b401524e9e5ca1fd6454082a66e5f691e08f4c1ad588040c29271836039841d60a0d8c0093739105b4d8ac9bba389042a5c10ead217ae207275946848090f0b10516a29bf395871410a2871cac98323a16741b7f1936ce05fb4b1742b36e4aa4119d55764d1e541b8001523d1f8668f4e4bacc855d1cd6f3dcb27e1291ffedaf58140fbd05d4a5b5e83c7b99e1f1e5d566ee0fae4755e051bd6f824be81d18da8678e0915c5d03b630ecaddb54cc33295a26dba5d32009a8196db505b948ddac2d3d5de38ebe46122f09bfd7d53a0de29552f53e07104a1a131b7a225f1b7bd2db935c2bc17f4073a005913b7a4971cd9e44483640a1bfd0e4f3171493a41c55cea0ca18609a3b3d32fcf1d7bfbaec028562925cce67454b1d89e910a92c19726b22aba75700bba9c3efc28bb5b1cc88d126059717ad88d67cc5d7509caa839763a491a7791fd1721572d2a15f2e188fc186fa75aac025fe9d08b0321553e3b32150c3e19bbe6bea9d98d9acd9534ebc9c2cc70175f1e37a085292fcf12dde3493091a5a7855f6df950cb060da258123a079a010f00024945e1aa0e02e04c3a76b03856b847e126a567b2e59139de0ea8fad5ae86aeeba3310963dfdb3051780d4005795e38e52169cb827485cf8f6c1c178806bbed339b4772a24da88ed8b7faad8e96e593d53838c5d22bfab598fc9a001a1b432bfe6dfba33ca446c1f7de37bdcf2c9a54a083a28cd15f1285dabdd6d9b0ff91b61a94706f05a5da1b1a38f1c8b3bc6d78a9e59df0f0925ad6fd5007d734a66176366258c29b19566657cbe5fbee2b5b5de7895e9a4e4041cda31e633b5d3633f8b21f6db469adf8f597da2a162f7bf3fc70540d6fa2f833c8d5d4e43b265656f25a6e26daaa8b5e75316bd696ad309f9233dc9fe5a90831d199fb72545b700c3f5e1da288eabc17992073110246c354fc81f2b40b52efd0eae03c272874090558e03904fa52ef6cb4cbf54386396760e54e056517a3d49b4784cba1495aa124b0338968ace52f5ded0b9817e2d05534751af50dcc53ea65d07a849fc886a185ac96d1a2826886e236c9018f0552fffe0a81ef9134b560b4a2bfd9d8665ae3b920ac93733a5163b3934b04dc778b0256faf53666b3f92f0e08698f7ec93b5573062b7a163ebe856f7b57111795daf8a8788076a464c8662d6a30dc24c040322ced1dd00a8df06aad8c414ac72297fb4516083a46e255d08ca59b7e340126754b503fcbb03847c52f5960321c1c738e014fd22988450c6fa661f9a85ceddfd6d8d49149b42f49f4f350a43b88dafa10085facc89b4c831e2d9ecb603a9b60bbb1f624c02621a893c0c1d0974e247d50c74a441304ca2b155ebb399d9fcd8f3f6478364c701a79c8fb47f73e50a98b474f860d62446629d54dc598742608176d3cb9aeef1a1b44d9f2921915ba4623279d3922ed64f27fa55ae05277ac4b734e9659e6faeea6b2dbc017882f5e2306ed18e84d6f84091e4301329fbd48ec4eb100c2047b7e85ee5ba347fdbbd92dcfcbe0493dccc214310b304c0b6d6e41f4902b0f283f277f6e480d6c822eaf728f9167b37279e94e116410320762102133ebf9707ab96c2b36997a2d848bed2968b9915c5e15855717f866d95962f51e218812020a9534b5ce64901f22b4e4c356910f1954192543f592a68860efd1dad883e7f3632096a5cb51aa0b743ecc07103b90a8d7ee89843ee2e3b6469f07e2d2153b1fb525cdf72cee8d22009526d93e6be425158d7cc16c7da2cad84dedd6578c25678489bfaa0acda51c104871ddf0566597395a235cd5940794d8833a78466957b854571e64c283d4f08ce21ce1205be181381bca7c56d50328f66069fe4645ce82bbf92b563f90047290222cd833e02092ffda722994d5cb814d41c5e7f758ae93df38b7933f59d814857c7e8756cdb9422dca1130f32d700be8f31d7007883383167773685a40064070b6f9c4004af233d897a40a7d9833e27c8695851ab38f321f88308c76fd02590ef3ba0db5423d1067e8b9c850916fa0cfe0174a01202ff27f804ba8ae7d89584a812a6a92e912e7a7367f62074a9c933b1f8b9c9f35ba1958e65a45551ce762655e820220dea9985e547aa33e2f681a5737bf39beb21a4e182ac2332ea0562acbbc1c54a4317ff389cdc766e0361fa8bb143eac256251be34947f5ce6e520bb2d1122b00096771987a7c8d940eb7565b9d057239a77ec06fbe0325d682cbbdcee422a961b06f04b9ed8f78c67491f54f5dd8bf984b3705ae5db9d86050ed07909d5a44fe194e862e68514a29628ff40ff0dd3f0ad03f76f14023b9505652e82f27eb6873070f0c9d9416c081ba6b8aa7369c5e8c89d0bd5bf758970d09cc175a4f31261cce02c179761871d64bce8aa33c0c414626a94deaecec89aa2ab49cbb8e0c6b86d3e2714dd30917ee60a4e86c32c93f2ec4c4384848904ab672d34aee96e99f09a55b6adc1130e2e8cc53134056355a58908152c92925fa36b238c4e3458720bb18ff2b2a5078b3e9e213070010fddfb31fcd6fcd6fd06ca1982209787107a92b3e69129f284e7d93088ab047c911b1f74a30c09767b2e0b898f1005a7f0eae6edd53e1bf94d3a986d7471fdd50d8b7c866de8c02e113b1a57803cc37f6aacdd1aa8c85c42b30816173c5b81adfe84b3e0a2b4f69ef2905286386d5e1a398be38a59edcffa9b6572e5849021d6643c338ca8873fa6b39c0c1601474e68fc39e698f8040c83055bb6cc017499307112945eea360dbdb5a4851e1ab0b835014851f2dfd142b98be6116ef4f6b2847e98764f3501878fcaeecb7d0e304b692f23f6b05dd950c17f9b1cd568b3176c16fa030acd0171d4017b5cd1ffc9af6f17cc1e571b94f43aa51f3f59142b06aa701ff879b5a2fd4e0d537b9429a8d277e04f95cc6369570fbe5d4e43b98f377cad5f7243e017825ad980cc7cad46a512469631eb20c3ec18fe9c61e6a3967dc22127a73b58ba32efd5a731b06838fe8edf7a8c81fa67f4678019385fa8e5f24c01a0315e4599216afc600909248a8a0424fef95896e34b796ff02a133f992f14ec5a6740f126911c3f4ce47bcfb5aa30dc33f88f2c3347f95a23eca3416b346e818cf87545a8c0b0034d5f1189a2209d9f95efe750fd3cc37179d0a2025d73c0ab2454576ff6f6b16eec9046f845d6ae0d197c08c0547430ff3502cd6cb7da0906855a79483738d89c5ee754cace7983c1780a36ba969d89c84e076387814ac947e9f7629da57427b487e9c67fbc080d46a856b9d5e6cf5d15d97663e3b5277b8516625eba381c44273c21d0a6e7cf2337949255cecdb65ef3aeb24d00e6acb9cdab88bc5fd1c13df27e6b66f950802804527c147418463bae3078c741838e980cb1bac87337603ed52a0d29283354ad939c8991b9b032e4768711b895c4d7c04aae6f6baf95781688fef92c981a06fe597e13ddd0d0dab339ea12163a04a9983c446c55a58852c9f55a6bdb6d514fc7d542b2af8f93334df1db94b760537cc3c01809e0d2f73391faa82a19e89ffbacd3a3b91b6442fb43a4db2983cc05b7c66e294706f6a60c4c1794fd3ad7c1ee9c3702b1bab898f08bfa64e0a168cd61cab0a61e81d1e87c9e7616220344938bf70f5046310507ca3918f9933559c26faff32d0fee4dba6fa312b52b5c1083f21ba646e4990dabc01b54327d3c68d316c146b8a287614bb137699153ed8527e493b5c6ff90ddd663b1a7a01fd653c710220a33593e137ec798351418685a5a9ca908de81403065cc1bb51a832fee355f4c327abdfb57da0d15c24d397c6204e91f3fdee2a01e55ef78e980c8d3dd39c9942d4afbedad8e63ef199e0ec5ce68e6a16b6e7046640d03ca4bee735c40141ea503caec6c67853e3fc4113039f9a4ae9c10ad1e52b58352a2d604dddc214d29d8fc48c007879f177b1cba44b301fe8666dd1364ee5095bdc4929c559617b375063b327266562ef5c8d33862099184ec2df7965b4a29654a015207e306ea069c05fadde6986886a3975ced222f4b7ede67ab541dfd6da1c3905242e9515ed78ebcdafd61869f2932da37e78331c6e8028ef668ffae0ba4944f4a2218ffb507c580091b3831e2073b7841811018f9a18b305d4029e2eac28afcdc3e4f3df70efc731a2b16ceb3b9a448713558fa5c6445eb922042f8e42b72430b9a00210b089c3839810e7418e04d1119c06c71a406432091c3169d4782243878e8bda4818878e8cde4dd68112767878f183cf41558884005ae1084b08787560011716ed0acba857a2ea2c2e8bb15d10e551cbde9b9880a31cf5b0a1d16362061a48a28b0f4a013dd68891628c1050a952674e2141f3da5e463b462868f02d0895768092ab010512e7aa9766f1548c1e10725bc041131a143c3132e3630018208243ed0692e7f49f1cd6aa220aca0891e868062899314e84c000b1c746008c8874b129711655bd4e549171f807401faf95a1ae29bd6d2467dd4605eeb2579402fa893e09aa804d744c74213bdb71eedf37d3b0bd7444f126374c8bd85fe3a09a9e43f47ac8ef5235467f3d849300e251a0826d7eec9ebe5ec762d83727abbe6e1a3338c18441f637030381427c39d38133739aec4913848136f52a9e82b48135990263a0ea48939398c433a7b4eb7806bdac80d58d89044e7e788eb7494a780f69f23299d5e011fa05dde96c235ed47ac4eefc007688f6ee18d911e8234469a874e40bb916eb1e08d914e02698c34500ebc31d241d0a36fb7a7f001dab322d8a3468abab4b82bb8a3e97cbb275b357ae42215fb8bb61cf1b84df376d1d111972f415c9e289a4286a2297e3cde199cd0e1afebba9e8bb828f1443c6f1ae85ae61d0dccbb1ad4bb1b4d73b909374c00bef961e3a1cfb0cd5cd1eefc9ff08a0aafaa44619a860e79087a777b88bb6128000098a1621c22a464c480819239992c47276d5acd307a4d1961330ee83f9806ba917684623033bcbbf1cc43cffebab05d0f3d7c58d8204230f41c086ccbe01b194cd317d3b00de455934002974a0f8f88fe3d227a031771f1e10a172b8f7aabeb840aa2e7a22e4cfe75b901d11226cf441f6f30ef7969300d0d661afe1cc4c75b01ae797e6d60c238923c276df37cfef91301e3e8efa1e77f4dd81f08f7049137c8ead1f8e7702836b152ca6b444a197d4aee0d858d48eba1e452c3776c3d5f26173b64544a08cfdb0ee50051651a35e270649be2c2818facf3b0e72229b8f8e87ddd8edaa358230bacff968fde47cff42f4616582e9262098b7a2e92e2ca031ac19627b67c798ea286287e342e463e3c174521f4dd8c975148f9194e63f51a405d7a0d7afdd148192bbf6d460ff6ba29d45bbd786bb0969986a45204064028b1032a3bd4f0d385125c9e5c45a0c8e0c450124b1451430e5b861853994a41c5c8caa521092e42d48a3b43d1962a5f9f8bb6b0a05599c695615593371bedb87fced0dfe3bed896cd71f269f769ef916e0c9cce949f29edd41f7d9462ae7ace455074f9e7715a54ffc354cff906d772a8143783f3d2692cb9048a2a4f9f9d00f35ce44495eff84a911344f0952cff9cf58307c511ff22e51ad359ce6dd231968b8600e63bbee22ff477b0b3978ddecd1c1ceefd9c2e2f4e0dce3104a38ffebe2f2b8b6ef58f993927c791ede9382fbc17d2623e5ae005fad287cc8f0e617408210b2d60d236f8a70c9df5ebd8b39b8788be9fb78643f0066ab96e87733bd62a95ddce621736960e87b582a994ed6cdf223acfbbc65279dabbe5ef1199d217060161c11247e8d6bf26d22d9d9c21d7cfe7ddba3c28bc2b84c7fcf317ae7fb72b82e41d60598775e4ed960e0cf3edccc5b3e901450b7875d9f480e2075ef1773cc4438f5c0948580ef3fc1d173de4f2138688314db6b0e18a0e749a250715ec20063ad02dbcc90144952a56f0c588231d74a0a75000e60b155e74200f903029e2c20a1118e1810ef4550d92089305071282d0e2071a2871848b2974a0e38c004c0dc2e8c02b082db139699cd775c539e33cfde458a6e7f0fed88e897074e6eda8bc9cc506737a894c998e75a720cd9b4d1f25326552ef9ef43461c329b97e998f3ebbfdc21ea92bf2716aa9528790845f0862963c8ecf9c42af453687dc9bbe752ec4f0d5dbdfed1ce3986bb4db6db57de369d7b8fe4b338fbe796f3d706cb7ab913a75de9c10fae8b561d5411f7342cae67507c757a799c74d07f55835cf6ef7b6cfbaea43986ba056338ea707c7d7db028eb740e643e833d740e895cb68a55cd34ebb22b4a598da578a4950dbe0cd8f0c8ff5e72c84258f79ffe6d93fdf66c65189b9bc14db52d830df1cf31d39df5c23db50c05090cf663e9ecd9f73e6dab329dd92735578ce9b8e61ef71cf7ad5b6cdeba6f5f60093e73c367966b76ddb4cf6765de4f5cb0dbb6fdba65792d6db03a824d930994c26d2ed5e0c98f7a6c3c633d764ccc40a9ed946f67ed302e6a5733d65db762ba73279bfc94f9ccae4cd1b04a4db4ebac96ba53ee5b66d9bbdd834dd0e7ee6b3d3c06f1eb96ef3cce167ce454248f25c397e196e4ae578bb3c996b5c7b6f10b8fc75170e237c5784063bd9773e30975c87390f261dc29f2ea70f99ff7eba94b5356c3e9fd2dba57da61ba8a082a322462806360f01ceaddeea9a29cc787b18cbc3cbca1ebca2b20ee97c639452ca8e35a33396e7917e39fdf67999b09aa5f6862b56a8c41ed6437fadc5870a1f5f1355110383142c1fe3101fde8a9d89d831b301dbcd78aed1bb18b1963ad4426fc5de415ba472bc14a243e06b3e7d5b4dae060bc87611f8f16ce60c2034bce7d9902e768760bb1c2f493624977e420f6379d24d49df4a5c8d47339dc21b7f34d363865a3d5fb9e00c5e642c76d3bcbbf10e6f5270f5d0e4a41a8fe6f28ddbf156975b2e0707d25c9a439aabd2399d44df2bc21c72d84de6d9bdb41eadb5a85cb9b28682414a829404290952420a5242229148a793475712d457e25f9df69792d3298992a013494910298992a02b4a48249256baa49418053e7943fd49da04fe786dde7550c9db63b7dd78c130b975cd494e3dba89e3b78a2687c1f1a3319950d5dfeb4c1e65eec99f9770842595fc957004255d9e1249f3ae47fbcd37a7b7eb25ada44d385d9ecd49de1ba9ef7609fd66ba5d91bf3cb692b611a3e46dc706b0f843ecf7bcae207ff5fcc563c68cf9e2be10bf2f8f741dd2edb56f054f27547d6d72de6ea41afb7641415dd5c4d14723fdb2be7193ebacf4cd2f4efe4cd1aa5bcee424ae1469c6498c0629095212a42448499012d333d920e5fdb9e80b111fdb571d23f4cb637739e11b0a7cf46ca66f28f4acf1ea51ffe4a7bbc12d7e9e00cf455a2c81c59317e1b9e80a245fa1267fee6b41310fcc75fbcb75fbe8ad62fc214f1e7d447947ffba5dc9d9bbea24948c533fa1b81ed4493371cc35dbb377bb5d0fea35df4ab707f535f3edb293b8128eb0d5bbcc1fe69bbf2d059ee9f1ebe5c9503f9dbd9bbe79d74f7c941ffdf248af7e79a6cbafd8953feffdf2f276970be9315f5d488fd101e1531a6e46eaa176653fe0cd69e34723398e6f456fe6936bafd325473b9b18c7f04122f7a888bce615025fb2f351e995bc68f1f3da53cfe2892caabce3a4589df975bb9dccaf1e995ff2ba848268e634bbd1c9f3d56ab57242e5d5ea5dc1155cc115bc564e9c442027585e9085d0972e7fe5e9972aaf05115a30f92cbe7c7d1a839ef2b3b191499bd0dfd715858604618163b6a5401d7a8c1c9dc4cbb178056291056fba05a4e44ca6d3e9a6e9daf4b735d15b4def166992bc04efad17d74018766117766157c5b00b62b16b8fe8a44d28f9c963d0c9e1c5aed3e5c1b458a32c3c4a5cd790eb202c5e41d0a1470ebb5dc40093e8589547c587c73cc2e89087c7ae1a85c02d056905f3ab8b3efcf5aabc1b16a419a2511e9567535d89d5e5352eef56f15eac8194b0299fee9806e123d2f5c3d0fde4bbe874dbc1b008f46c98b40998d32814fba29a479ecbb11ed42f7f5d7c93f5e5f92807d26499f0763d2bed5d0e3187d121e6d12f787974ec311a3d32691b97635b0a9476949f4e8a406f356f52acb9659cf5ae2978030452a378a757925b4a29a5b644a9a5b47479322739a599936e74d2362c75ebd5725d2265f22f9871f2dd53294a6ff786fe5ad5281991aeb05635a854794318b0f2979778f8cb499767dd053e9b4738ac1b5a9e78572ed0250b16cc1b689666fc6b35049f7abb89f307f45697675b0fede963f268802e9fd489d05f6e5ba5db59d2dda29388ad7ef5daeaab6397c3d730ef86c0af7e6134cb2ecd328f404eda04143a06655874d25868cc40001a0348a504b042a594c68dca4c4d2cf4f0855ed1fafe5b6463fb0ade5024dfed16cc770bf172c573acfc6c3cf2abdddddd5daa61dbb9df0f5e8e48f8374d564395de34a9a4c37811aee7157c17281a3366cc18b8edc487a87f2a292dd00ffd0dc186f656efbee049d953767fe1807f32f5565e96f4a379fe70fed58881ed52719552cd6b017f339e4dbc50da9f7bfb0a6f88da7e24e6b9c88a2cdf959ead307ade76e68ccd794c8373eab5427acc335739b7ec3c2b0996630d80aa5fdf15a0bc0b00db377586e538239c111539865cbc309873ce795d2a2b7d2ea997083bc21dc28a6065aa8efe94a9cab01c2f4a6350caaad9522a8c8ab23f53fa29e0d9c4cbe1f5fabd2f32bbb30cd96ebd9653d4fe793697af783c1e19900ffdf27e36fa62bd75b43b9107918f10b8b614e2a675b1834d5499138410420821b4a8d40c937523d5962c69ca272164669255cd4bdfbe5f1cacbc343a4125768bb09bfd99021d93108b0e3148afea8253a6a06af6674a947e2bab9e4349e23ad1f9ef0ad1a1c45b2d8ca1fb299dd4ed5bd149fdc2c076da53a7ae59149df3428118c46e662f9f4e9d60527be9735f60253fce02fdd163840da9cd7934541dfd978a2fbf45d8697fa648afceb5d90605cc62398fc675796cf750a585fe338539f55ea9bbfbfb461e3a8a3c1dd1df83c073e873e32181fb9027faf3f83c109f6cbed0fe4cd19e022e10f6790d32ce38cb1e665eb43c177919faaec64337c07391171e9eb7149e7dab1a6f05fda2c07635605de263996b4e9de4cf4f5785b92a73ead537b75795dd1d1586f5d8bcaa300877b60b6f47ba8cf9e6b47ae650d3e05569aec23c53658eb98a6e57a5dd9d9a5d56d1d81b8fd20bfdfd5d9bd4ca31d8da9b8e1ed5b1ce7ea79a391563cdabca7cf88f1e98d3eafc41fef2b619f40ef2aeaade1deca2aa7977e2e5cb0ebda94fe72323f6ccab77aca57ae657f8aa308fce5c935d15751536b1bba3a2d0e574e92a7a777e049937876bd8e5f5c1354ca49a9757b757755d15a5aae92aea577655543a73cde5aa797754d359efcf0ee7dd61710dbb3febd9e54ebc7c6d6d7a344383896b666898a1618606949fbc9e50d15acb351e2463c10cd065ea49a55ed3346d041fc179bb7c043f01d1d123865b37f909869f646464b8c6c43540fee4a6db0149a566805233402919130a25422a3563c60c50ea8100f9ae27954aa55229d44d718dc9532c203394d4190ed8cecaab79a73241016ce3792742d3b0e952dccc0c36f5f171724ed8f156373ae0cb9b43ccb35ae6b5d6eab57a6d6d8603b63dd658a3e59ad40665bb31a474a648d415539f4c41e5a6d78ebe5a39f8b25739feecd107afbc2fc487cfdb8c0fe1e5697fef0615c678d139e725abbc556ca218233333330f31c658393a333373eca1b78ade41af872a394b5bb1f297cf74c056efcc2506a6381122cbcb1eb6f2f3b6c059b27e2300c2ce0c83a669104208211d22bb45c4b74dd334cd731e84104208b53be3adb4db959e9412f7a2cc4005c63139967cd338d54ec9372fdd0d62be396f4e728dcb38150fad04e155ed680e5d73e82a1e1abc999f6e676f07bb4d0891cf1cf30d7a062176df4f6b091093b7ea242f4914b64bd17843f03ea1b77aa6a64ec2440123e56b6946c91177c91204c943bf56581eead38e3cf4000f84a0e2a163589575c219582a26cf797109c6013d628947c42c91cac91f94b95d919751edcc1cf8accf8af28b53f1b81a06a597b92686bfabdab9fca9785c97b94686cbb85dc3b81deca65bcf814288589fd3653821f05f7779e8370adbc5280fa1c728cfe639f784ded06b71ef877b499600317912e5ada488c9381888b4fabaaef7de7b8f0e91443aca93795dd7f5de7befbdebca17e549015ad24241178b76862652d7ff3c928ab820e207f05c14c6888f5f4b11909e6518865979ea56a394622bbc9b1662219b9d7cbc131eebb12667c4622e25ca11eb5fac8ccc8512c3f9dba146a1c68fa6a364b144b46337057e6ae5cab351d1db40df561ed18c8f0d43e5bb06fa288fe639f6a3f3a73ef363b921f276d135906cda5e0120f0e607a4e9be502c81c140a495d91d2c9433bc9171863727677863af149dd6f5dcf89253a7ef4914296fd56ee23824b63d070c1568a0f2346dab30380e89c5bcd33824362b711c124b7a594c5c0fce578740cfa67a1b411a268c83c22330591a4b5381340ddb51b763a22cdf2e733b9c2bdf7ebadd8aa8f328f4a9b598744eb5435d965cd6dac5c738158f2c9e30a78ec938bdaa9dcca98a07cae915d2635032f774e3eda4974a264e0891c74a2e63f8925b4e087cecd2d27d3f6fd54ee25eeb2d017a4c648c21e8311884edb4dbc54679faa467dce5909b8e713d6df473fa1b7aabf627f456bd6ad722106a496508217c7c4d208fa66f2270fd601c90ced810d2211c5472c54a101254ac1d6366669e31fce58cf96caf025990bd02ef2687c809393556fd04d7f46322c004e915de0e157c68da0f2258ddfaa797fcd86ec74641b40bc35b3537e409dbd9b7f1e1addaa29e0d2685a5c2ccf888ef86345d6f8793b3e3adfa84b7ea2eff301f332af0687c8dbfb09b9a28c9f978ab151ee94e613b26ca993dd4fee4d1740771ddc2a18f8c6aad517cec61a35afdbaaeebba3ce7d19cd70283c1ba4e5285add8e55966f4115efaa011ace7911e5b524a2915e2803163bef8cb29eb3b1ffdd76d81f5f4f244971847593f27c9e79c94dbeebb3208237db0089733568fd1e7acb55e213f5e7a74c9f5dc7898d1709494524a597dc65bd54b338a712ddc781eeaf2ba5a6c878ade4fe2a07599ae94524ad902836120f0f208bccb87300e182ee3979ff06c507ef90cbf9c856763fdbaaecec6f02e25c33b4f79b77a11bc63e1fce058803e20cd6b22ebef76382c116eea762b1937c63d5dd3b5f684923171995baebfad48faaa9b3892f452bf27b86ed5b15e4b84773198eee62d3ef630982b047b790e6c23ac8423eca5c23ea3bf9cc17cbc3d6df4f03e2d3e386ae1066d979286a75018876118d6b13ef556d99df15652b6708372d9ed6e7ce6b2bedae5a8396af5992516f32e47ac15ab58f5ce1fab58e6327a79415e33cbb2ca5badb5567fabecca17e4f3489ffe12f3b7799722dd2bb45a33cef29a577fae713492362c3a8d50cc8db78e951cc3dcdeebefd5a7bd58a5059ce7998e653efdf28bc7cdc7ecf6e0bc9cb55ed7755d17ad388fdd78cc570e6f34c7528f39e65ce359ce6e1a173ea93bd33a72832cbaf07100025a3968265cbc8067b6f862091458cc800746266881e034c5881c6c9841132684788b95175ee209ae415b21b5103ef858135ab0c8931984d8d204972a84745082286a4d121bf8a0a8074df4500226b230162d1e4247611e6031018fa9b283974498241f98a20b2f59c20c6169c5c036695171021d5050c5171d687072848f133e2703b47cbc55a32573e03380160e4b6630c3a503de811757123eac1698115a5b7c88f0b96975691080d1810f092d312de6c2081e88b9d24408f80815b40c3ae0e383a6010b7c62b494601bf4123c44d197a7e569f161217ce153d3aa8207237cbad4f281c2070b1f4e82abe02c27904232c9a083171c9008c3c50870c0e2d3c23a700215b49034b9e10810592bcc3c00006eb466b4180925f15a4141828b2d32e8a22807127c71455642932f9ee8e0871e74e10307a184565b81858f542db6d23670c287b570100bb8814f0f3eb5a5b5807c847c08d06a404b0a1f233e096825e15a50f8b40f50ad2d3e5ffce0c38096123d047b6926b8f00fa0d4c0b14b7294d3a4d31bbe08e2d2deea9a42455ff0f0d2a423a5943785fa185157dce083a3c55778e163c3a695a3a5858f8c5614442518c20e1c85f88116496421c30f5c30020f605a245102254d42f00384f6a2890d3e382d2a9e681d68b452e013858f4ccb053970c0a76b10a165e45380d6155314d1432c441b711122401204971f199e4f87d172c307c620f1450823a8088ac6dcf0527a8d7713758a90e0080f20c892831723273009600552003b7091cd00d9e9a8ec546b4f4a0646c96a1ac965306d4339759bd5ed94d58ce3a915c86baf546b9665d5559b65c7646e87ba3da99a7957cd65c420f9f88a612e3456b5cee4d449192acbbc1d06eaf6a43e6b19926337b336b3405e23c9b80c57728d3bddccfa65ef6d21f53cec98b377169b31d2c35a3a8a1640b8a83a84b17386065bb90757dd0ba1ef1ed88551d234cd4f305c33353f0cae9371f61227a4bf3acfe62d73bb7fabf595baea9b56da583d3657a16e0f55bd3d986b30ade4d56be9743b93174bde8bbcf8f9ab47f5ae59116c731931503f3e23b9b0b98966327ce358480c5d7fdd387e195c7772181e8313d23aaa7330b813d714f3ec76413ef313cab19a5dd4c96588505e714824128a95f3993f0ce52814c97da436926fb7dbbcba0a45badd8fcffc919c545db5dd9d2ec867fe64543c4ebef9c94f5cc933ce743b7bbdf280dee385f83c0c354ee5c20ec931df5ce5c2ddd1b099231663a26fcfb8ae878f1ebb2fc06fbf5bd8e9fdf185b1b307f72cd20e6664602c6cdfca5f8d6733e50c795335581c8a072dffd8db4a5379c24ee4dd74abb5c01bebecfd04e3c89c1d06f6e1d95bcabb61b19eefb05c97b899a2f135faa6855e03055d2eb66b26fda487f54d34e7b579824ab79a4a53a9b56afc240dd3305292feed761af80cbef6f356ac25bb30ccbf4e582273c2b0635ed79565cebf655acd58c06ea781af0e3fe354f0b1c25b75bd3be4df31b6a954e79afd11cf269b35c37ca579bf763b0dfc9ce1342eaea9d06b643bbeb243051f2b94b46c36bc8bc639e79c3362f1ea16911d6c97e39fe738e119b5b3204d7b0a42222c38df3d2a442b1cbf5b6c5703e749c1b0fba2bc55d0e5da5b31b94d5c54b01f3b5eebd15cb2e32b57aebc2a5ed879a950611cfcd521f5393b18311bedb10ef598f3bc30e813522ae47a5a393ae18c4b9a3e266fd5421b3d4f74d94623748fca8c076cf6320ea34eafdbd3466f28de27f482629603af6ef8468547d32bd87048ec7b3708d88b5986dd1eeda9ef38e1072d6533337741348304422983b85dd847e7f438393a7df6b410478e1ce1a32153e5c2ce54b9b0f37ac68885dec9dbd3513ede1ed6f2f0be00df7fe2a52c99a5b3370f4b8f555e7a8c3e93c4b6c71eb622e5114de37551e57c6f3eae42adb7f6e773ca09258410fa930ce1eca8b9117c74f4858f784bbd49a4a4a6692c689a47a0d6e69669b763bde6d9ed70b4dbf195d7b4db559f41d9aa2956e431ae67152510578bab45aba075404969f2ed28294d8e40cdb8408875c6eba38b62375e3dab1e1973662a5ddaf8e7a98f2ddba11e765cf44feb2c6ce746ee16778b16844bd80e358335243efee7396f92c03410fa0bf2edd8bb5d3b090ce78c56bb5fd84e7bd8f47eb1cfb1a8dcc5135f4baf07155d3618a17ffd5aba94524bdb78ef757b7737bdd306d606a93fdf346d835bc9377f5c0f929baa6b5ca7b2ce0fe43567ae4b3d9087cea46b2997ee4e76f93edfb4db6ddbed807c4f0a655340b014f5cdc743c7340884fab67126d7b892a73697bf798ccb282032645c1833f5307a52bf6d7eb98ccf6d7b8fe23a02bc748e5e2e1db5396fd6ee602c18ebdde0dc124c6d4e378c42b843533dbec352df3c7398aa57a56d1bdd6ed793a27ce559cf3da9d48ee72bf2f4b60d548ec1d2aaf973c8d59fc30cf34dd5c3e425e75791aa33a7715d108d74774cb7a49518dbb80bf2d0e1ed823cbb762a715d902f7965be91c1341276da0e734df7e36190a75e390bbb20af99bc722597c12edd52975c83912e14189ef3605c7e8ebaf67213676f07eda3387aba2a5a65a8578e3e198e677abbc60d892fe95f30f682b17c3b7887c49f2c5a9dbac94b10d2bb63fde425373974e857159ad2a8c4ac96a5490c99aa810400004314000020100c074482b15830221448313e14000a99aa46604898c7a22089510c031903000000004000000000408c010349170ddfcaef976e7f817ba9bbedff7fffc7fd6f317789fb22bebfe07bc9ddf6e3f7fe7fff7ff9b9014ceb823798b80693ef3ed241509c7efe7ffefced63a2b0aff5eaffc6efcdffad7fdcfe18e12e7d5fda3715fcdb2a805f7a57cb476926d562f179f9ab7f63529dca287f646cfe50f811eddf1154495aeb2dffb4fcd37fe87fe9fc53fe537fa87ee9176c5bb0b7a83034f48c3562efff48fb1b4897249d297c2f4d5777bfa2fd19982e25ba2a682f25ba52e85e8aaee26e427034ebd8db1245af02fb52347bf39ffa4ffb434f8cf5a260fc68ff1130294f5c96640050f6b9dfcfffcf7f3fc98cf84f6b60bf246fab40bfe4bd69cfbf904ba96ee680be52b8d946f496caad0af694dc6d8f7eafffbeff51ca559a3755a057f2ced43399b0dc985bd52b7d7fe9fddffede7f6fffefffb73f777eafffaffde7f64fe05deadef2f4ebedef405709df56017ea97bc3d7df2dbf17fef7bf7a990cdc58f34d06ba2bf2510839ac43af8a447ba1cb1999b151c8b634cdb2fb3f06a44a85ae0ade4ae8edfd2fd1ff06a85274356dfe02d452349b9b7f02e952a7310a6b2f4d47b9c19fd22ffd2ffd9fe61f7acd060d0c857b2fda6097d008c3870968ab8288529cd6be0dda4b6201ea2d497fe3f90be64a8ebb10b097a0bbd8fed0a3217a4d1c5bf694c4ca652cfc6c4e201b11b3e3cb6cfc08a64ad15eed2669ec3dffa1fa39822a4963bde3df94bf817429daab8d7e69ffa7fd5920557234a6b0bd44d15481add4686b617b89a235037ba9d19ac2f612455b05f652a3ad85ed258ad60ceca5466b0dbc97126d15b497a2b5b8fb174e2d6dba19bc2da1576bef47105da23446e17b491ad3fb7f219452a157c19b12babdc92f9d7fdafea93f74fcd2ff4f331944b7b437e993eecca14a538d9566cec27d6a952c2a6d2ad363c9b545b0d6b64cd551c0a7895c0cb24c7822df34385a4d409cdc8a0995dfc9ad1724fe3ffc169afb164ace8f6505fddb4b623cba632bac7ed3bccbb8a088e4f11f046408874947d46104158649ba21906b945f86493349a36896fca0930f4b49cec0ab4c94f104555760143f96daa71ad853eade0aef0fb2ef256ec5bdfe02af52b92d047ba5726b19c12bcddb2ad02b796b7affd7bfd7dfebffcb3f6eacbbfaec0b7ac27a8f7f8f386ebfff1d9052a26855605b8a6e6fa669ed5d3fa3f817429730ad45742f357ab3f8ad9468aaa0ad149db5fd35f56f30554273adcd8f207a89d28cc2372549ab02772569e6f69ffa4bd92f05ff94fee9fba1ffd2fed3ffa97fa8bfa6fe0d3e3dd5004a4ad0fa204cc92580b3d19333620ecf813387580ca9a05400478ff2f551a9c04d9ea28d06ef7016e6113579e20cc0151c444e9b3ca7ab3e3f7c5061dbaa7a3a779ca3e9934901a5cdf618e8649d2d8a441740f5d6d32471c1b735953e1637f4315654fc19e1b98cc5cf88c883a5e2a557e1827fe6998c0b49be0a6206fbef8b0122a47b34615caa9dda64d495facf1ae6738c883a12c72a976d354096309fa172f93a2aa76834a0422bfdea98dc5c96827638294e266f91684bf7bf4ddb1fe2aebe8ab74af52ec3129460054854e46880936d6197de4f75a67aa33ca8145d1eeb44488d0278c5669496d0769887cd0f08349945970f7b714c0171a800265ebf03092551fd4e698fe83da3016f8bcf55647f179dceae5754bbd85bba2f2c6a51d7831f68fb50386706234d85519447d777aa7736311af4e775a7f6222478a6407848c42b45ae11287c56fe295c98b52450d540159aac67195d74e8866237f5d16005372a439ebd03e355aa3023556ea21800a30957de3dc621937b6d3c8738cb904b69d910202435c26e94207862dac743a598aeaf4353286828b662aa5c7f78c3af9853012247863a8ad7f51e67c2e7ff211814ef2a84453fd4ceb4433629c68feb7adbaff7630674f4d843c3c1671d05c450d34434e03f2b708a37be4d0cf42d636449629a272974bc2155bacf9425f2aff6447cb18ab3be250fc0eeae9133a957830580a65781590a1c79e9c1ad0dc264ca015247408fabc4721906dc142a9ff8e5b3a7f2511f5e3188adbeca24389d18d31fd1bda89f5483f6d9538d519056566d9bf880c42e661944fe28c84fff642d0b266795a833bdd05de883e7a6479b584d862047bce9bfe71468eedad6a6051416a853c5ce46f046bb8cede99c93cce0422c5dad5ba505f346ec121f7542bfa4654252db66a1bf3512ddc68ad052e93be407b5bdc0853e35bd4c81ad466273f348e5bd8d1eaf6afe098c4487c9da6224299462c3518966cbec8529ed0a0fb5bcacc4787ef1575b077d0744795e403a055e82fb4038bf16729bafc38026066b94472b272329ffbba5e893b9836eadd02f8247d09b58eafc75d6917318ead989267f0b83b99f98f03325abeb52b0a316c9c2f217f05561dce574ef0b879ebaaf5457da8a0aaf8cbd998fec221a41a520332ad2939cedfefd52508afc49ea58a658c583b20abe5bd5d81c4f92384676d32621f29ef3272ca34c10c29952a4b39ef2bb030d9ae8b65e2f5425248d7819a019b26b5e9074a3e92028c747eef63c856b5239c5b0d74291b2f4d39018883d8f519057b45a46d43fe2104dbe991a35aaa3f23b3e7af0cc3ead86aff205b9f210ecc73c8c034b2a45e629cc99bd01b5a62a093b09aaacd3685ae10b02e8d64012757690a67bc128115c549c029d2fd80d2ec485965d290cb91940b8e1f0dd1fe8242e349f72e41e43443923868f0a9523f61cbc8335785ec189c785d209f2053e971780c92cb4c8cd5aa5b85c85fd6e8d54a85582480559d335996dc061d780980bc7bffe2f0c97125781b4f11b10e7cc95e57691d77a5c6f3f6e3f39b11d94b65fd6b026409094b09cd8d80f478405e7e981fd3cb1e3c66a68480fe9ca409b8af24c7fb61447abd4101c863ead52d57d7348ceab6ab8971212d87e68e634ec668affd5151b86a06adb3ba3621779125dc41da670e836a9def81301fcd82f49ebe3c7b3f49f9eb8f9cefe4b5302bcb2481439eef502deb7ba694bbea6dfb3cfb1b3deb1a14dfdba85725963fd87ae3f9a43212ec65c54a3687ea06101d6d814efbb6924b46539005757de4680583ed271a11130617b84f5e82dd14dc4fad398ea9b807a2aa7eaf6fe776518fd5410267a29a20730a74afba8bb4f8430d364f771edff8b9733ee5441225d419a2bfc320c410361f5ece80d9417c0e84bf64133df572c185050aaf512c484b260e409c338338b4d49e5cb0e078245e74489ee9b05b27df246b2ec6fe1d4536fe2f2d340c2e453dd43a87038ffd85110daa63e06a253cb869050df715741b7c3db72d4ee4f840e80b4053a567f3aea5ce50a65723f416611b27f5c7bbcf8015b1f5dc0058d8d8091fa8d910620cc27476ba69d242118fdcdd4d3224e8c3b075b4419081f8bd96834a143aac38890340367be226b6141ca1af36e1f6e93944f81c11edf85d6b55374324899e3bf3fe788b2cb52e8aec96cea8899ba50737e92c0af15a80437dcecf9c18be03c3c6407b8b59972655e86b4bbf8ad2a32f13d6bfcd25c03b5ea3ad499d55cfaea7a3140cb47417a6c11c5431af9e27012c5942c7f435c705aa970454558e2b435444dcb2192f0a9c0fdb9439f4f33afd769f4bb752f2ba3396e0815bd4098671ddbcfb17c22628ad59562e596c9e47ea619d06a92cf0810747a49292a1f963cc23b06a81f8ae81df8d2b23febfdbf59c60d7d9958699cc22d0b60d3448380a2ab045bce48e3a9c0110d91e9f5e3abe1960c59dfa1d21f1cf1d088999168f85225a8ff4528f810838348aa3d1740059ca015f3615d98dcfb95055743104ebc6b96def10532bb47f641761d2bf9e649d27a9f8833dfe2c4f2142e3fd275dbf8e0861b1ec57f33d728cded563bfaddabcaf641a2c0545a60357c68b68504478d17d1ae19cd033f7ddd00295ee7f8740865b36a9fcbf87bced308392516b4ad30bfd2855118bb35522a826b20d16ca5e992b4480392c5c2be53885c4380e0aa94cd64398463acdb970ac231b2a95ce26619102433bec4a80dba08d7296caf6919be27ff98e5a64822ba7b3f4606705e336c850ef081bd11446aedfa2e25c1c6c36716898168221339b0eeb785d00ee7d16758426e766e213c60228588b2adc8fc620ec0f8266334b999006b59c3f4ca4ea23ce1e372cbaddc7df01372253b1e3b38f50681974b1714496fcfab7d98b3f6f60c240bb4cee92a66d86f2b535c28606b4574f4a19e03851d990bb7b34ef659534cb18f86c5b53502d60b41281c7cbaa10b480a530299ebb01890c05967c095b3abb202a410c1e498daeb5d0f666ceb48b900385c94a73094e9c6d126d9279dc09f43a2db6ed8cb3ed083fdc7c3f97f1ba9f6791ea9f9dd3dd3ba9f39dfa847fe24b5bbf22a4b9b5357a5ff232b428badd8c5ce8420110eff85b59ee97f4b828aa602db508250ab118636ebbecfed716b4f7bca1ea928bfaefb0110d9b9e0b6495ad668048954c61f380409c4c448d0d10e3b2097c56628d8128f61abf232a834cb8a4fb710ca2ae8d83544402e93cd205c9cb87c4f7754dbc6c43113e7a6217267668303d3ae5dc2f764e6b1922b1be61f656b019c555db4ff242919149ff1d1d598fbe5b41248591918690b9a1a75df41ca01759719c7448a2bbe5e1277549f63a0cf44ec43c8364864ce45933d350980843a773741b07d3aa3de216c6be87483189c0e6fb495a8510d8b1004d16a8ee0b9035acada1c35ffcb85c59cf98387ae8dc01bf01b4232af60477089cea5b40a0d93b6d332cefc1d072d0845b363c6412a1a5aab27b18425f10c4bda54aa6c597cbe889614ff57177640b56d70a22463195ad0d94c3f41816377a4a556735819f1eee218e79bc90ccd9e47b15a0269785fb36723aa712b698a57aacddb7c299937485078a7dae81604e39a00f4a769a93e512a42b1df214e66940f205a9838a8f1701aa4b748d252cac2d903bfab841bfd7f373b379094a66dee6eb7b3a2d04a06b563661d26b151a920a172a43ebcd1132a8c42f5efacde6967f34cf33da8f22febe349bdbbd216b5144f049cce508e3b7c54a9e0bbc087fdb8532f25cf2dee98dcd243d56e1d0d272c7105fddb446d8762cde5e53f245907e34a5eb88f8e2aec7469f0b0a14ec07005a6a929c7182e338060364138b6c4b6dcbfea0bde8244ded761dc15625dc29cbda6d24fa70e06e7f55145eafa99ab2ac829dd00247cc58d72a4c6522401a72c11484f1816311b21333f8411ea5f12f673745a442db249663fef71c9a8ce3a4e842edf3c5daa0ad505aa07272f1c93541b37c932f2051a95fe26c4448e3cd8e89118604b9610db110da2812ee486893e043eb9d24fd64b62ea46d19fe5e28a6c984660685df7d8783a60d576a3529913839fa90a1a1ab6cea88a2197a39c0afafdfe305144db3834756131a7e1fcd8ed5d13eb816fbeebff29b6535b2e9c6b67c3eac2ef29e5d6d1b528241b4dafcba2e18f92789d72e92c7309c39740ec34b847ebe1e599346d3beac0cb2ca1508ec40ff2ba6664bef0ff8d24dd9aac4fae43d719fd85864a4c001f2cc1b1470933517d716e1437be47ae366612b578a17f3c79444a55a06480217317442efa9982b9211ce8497e8b2d87e4213bf3c3e4dbd89cbce6bbd97a9643e92bc03dcb2a53f9858063892ed9a80ab022dd4b5bbb7c16020bb35662388495df2d33cb3085f37fc79765eb472540a02c5624fbe77df5b2dc5251886908008b22bbe3b054bffe757ecb5154a63f474d95e91997b46ba17310796afd8af0622aa34753d97d3d3c9ed4f489165017b050a9c2ac8756eb05993ea589ad128e6e0d25d97556ecd6a3b2e3d5a0ed5ff0db7b8e4109ada4eebdfbb64a52ff21b024413a559b4b914cc0408529f95f09c9c466c6720a7d5a6c162d1758949aed5b657ace9412b4b4932e9dab1d116c0164c4f1bd55e536ff23700779f70326a98460ad489e541c4879a2e4402491d80484ed0a74fcaa5997c14e718083a3d785cc87adfc1a0e568fc70c551a31e2e33f6eccfd37c712ab48fe53ca5a250f4f136e064a0b8d407f4c6d202427ce2fb9120c34f75ac89ae00a429520718e809bfe1efb618c3ce7c553cf047df82aa25550d8d6225e70bd5625dfe1f9c9ad53cd55dd556f9a23eb96a852f3a1f5ee68402ac48e8c4d3a83ded3352be92e9560f9fdae2e406d55dd7116b19bf50df12b0724d1eba47c5bd371c76ce4123b5c6d5d945e5382b7f27620cd2c8bf3141dae8de6fc8cef41b76ca3b7bdbda506bf31c91a9db034e6d06c198210a192a63a463b19f3eefde856f6a05769c9ce6b24e28a7844f65fd9ae3191ae99d8f395d4325c9c1100cc116aa9836411049f2ff17d6b477dad6c469be87fdf3c170b6e428ec944641dbebc3778128ed5b4249a29c823b8894c89edd863096f84b475bb287fde49474b46356689489a7701fe2039b908db59f913bbf5588560289fff8ac963cab21a1fa02977046390a21518256bafa809bedbb0443472c458b13460ba1b424d34d1d85be28d17e9d9fa297a61c60f52a2291ea670f7f1daba5fea04b5e6a250cb7cfc4c41670382a4ed87a9996a3b388d46c30876c63595099b707138fc5ad82d29a8912b1f4cdb290fc4ce646016084fc260973b773ae82a9d9c477328d0e0c47b8b0ce2a2f57f46a4f958d42cf2f26008722451b3cbd9bd15a9d8964c34cfd437fe29b91bbe9367b783f679422746e90c668f2ab32a001c60672b986b86650bf8568b929015fcb6113bb7f06809f6a69950bfea46694c4b9bf8c46cef091a0e37d52321959ddda4408f715d7f789331ee4ed888470bf9a693a4512beeeeb0c0950dee0a1d868d042ccc151156ae377b98fc7909b13768283f6e1ad2c9558642a3bc8e20f0f97423f434f8386997c65db686698afe037b4e2a009c7c75910e1711d1007bcdba1ecab698a3889a013e74aff660dbb739857f0d3eed7f3a44c80645f097e5fbabeb417138e563eee2806e0873fe1f16d757eb70a98b3b6ad7622103e79f62ab9b1c9cfc8469aec9a72a0c6bfdcef8cebc1be5683ed932dc3f202bd65dc397470301aca59b4c9ba24fd3015fe33939257c9dcddf06376cd70623a3196228d5b358251a36bf7cd3fa6d568363e2636c287f71487c6b4bb6d9a64e90f4a91a852b18e6ba42998181205f310bf243b85cc6862e9e0ec1302bf0c65d1ba1ffb7d91d03694fdc04b03a602920380909de74452dfdeeb582924b022fde565861a8c52909e1928acf78c1884ca6215dca18a072fecbdd58ea3b6f8b0ad40bd6f8cb8a82463cabaeaca3de90dd82d4241612f6e7e8e583b2767fca5860488046fa5c850579a1e70affd07b3c54eed311a3f15d71e9114c9ced71ff200e58eeb26e37bade1e03b8ab704e44576a96610e14a2b31f815fe723bf1051948c8bbe6569bd0ba54f938d0d2a11c98409ed17efb1d44892070abc75a8a2ce1e11053c7e2eccb5729cd2e08f4286319583ab7f71bc8e1bc2f1d14c65c5674ae5b3b8e4237403f6098ab01e4e371d788ed6f3f19b9868bfbfaee6cb229143c04ed6fc4f6a22d3f898fe4f43605f39328d68ad16ab6c45e14252227d8e0371899bcc28759448fe9df4a2528e95617589ad7169348e27fd8965551573e1d64905c04904f259d2cb37949e5fc1ba22c440cb5d986bbccd6f89d28384d514b170aa40233a8dc72494b45f6fba1470e7d52c8bd9eadb180ae7b4161a31ee9b8d9697555b1c49c69034cd25198403282c1d3128f4594a6587a515074abfa5a8060a42a571d42c5f2279a9de89ac333998946a75b21f8f110ca96b356726fa6f8178a37515feb7905ccaf9768e8db2b168147d22122f2db72d5852a8dec2266b8f57920511062c1dbba9e16e1ad371886466189cfdcaf2654dc29c7c5b3a695da300e47cbe4a308b820dc467929c259ee7b65f4774e200d7aedb879fac2f594d0be87240e81940cef157eeb41ccb1de8d4a3dcf67e2eab2a027dac453ef88b7eb361157388c5f1509e5d64d90deca5d919ca6f51a5d4481322df044c328fff9b7a4d3092637c878e21cfbf3d706979a321edbde8b91639b9f2d508dde7d373a028ab92b2d9d766f43cddf654a0d7872f6fd03aa4f5f6b292d1f9eb88f9cf312a17b38167ca6514a3d43bbbc52048657ba2c5b20c401826957cde6c34d134bbca72c9688414f6b151f4a9380f659eb8b9b6e22e6ca1e64c3618e1cdc4a9fcf8a43f61f2c0d34c90a28f49935a965f17762bad62943ef6aaee9cf782f396c1103c0861188304ed4bde8ad74e707e897f754af411c82a0537beedb0a2c8397abdd3a94ff734f49cb48aa6267f6bd326896c90fbb5f5159fe07140f7062b05040bcebd9058f3b1143e6c5c7503099438b68b8563a2e4f2d3581d8224b4754d043d7cbdfe0c841d8c46e65eb37d76ce12fdcf2deeef3d3bde3fb1f4cc1470350a8c30da894daa767b1b5603a6d824c17e6713a2cd622e15a9428073ce13109f6335c705ef83aed636c471d5064a0f0f6e2fffb9269893775b6febb681399987e903b1e2e8608ad769e3a87caaf57c4ce4b6e409780c12234148108c98cc232c305064fdddbf2505d0e4ec4018f1e54e611b4a47cacc5c2e41b103a0d39d0af362c6eaa163f8dcf58fc92943ec5bfa3d347c5621bec1ac211cafc7fa532a9d3a38a2c058f9fa66e796c49a30807f401b49791ac10ea3f715e95593cccb8c38944c25f83236d5e70f7a082cefb3fba978db46197b33be743c6adb89054dc7a12eb143584fd5b3dc828f4c38920e1d0cb5135fcff465454c2da2c377f6b5592ae05b453ea0d6fc0d88b3c834a8d20f846583576531cf6c5b1d9e7437a89be5711690b4271b5a9ae1428ba84ed35220e028710512755a62a6d311d8e44c1dd682520d4ab9686145e7e0b90f2429182e53e69f0194df823092fb38e7fe63dd12c4600d87805fa4cf0ecb5d3c46bf136285b6abe90d1ac45c27442cbb5eebef9af37e6742d762e9af0ff3c0b69561c1a46d89cdf54721417b1b71c7c189dcdf3d1d4d578a12f4c546842fa02352e1323fd7bcc47514d95075aa5a95f416a4bd3c7dbd50a31a94cf6bd2ae9d9052d1a85de9e4c7488962d2d584a63d5a29832a13679d7dd0dd8506a41178aceb78061e33f1f5dcb6c26641852bfa78cb339cd9f6b2a3852cf6b09df26420a6f524b3fdb405927f07f52ee6a53f0b15a3e22e6170a52f762ecca26cc5b601d8a98e30e70cde1fdf9141f9054bc892c4d77dac966764ca36c081a63d9bc4d8ce2000f1084f85b1747b33f331ef15e0921c19dfeb42213cff3cbe00bd7fdc005e5e9bb0384739e02cfeb6cbe3f85baea26e22f2f84c10f33149dab6eb92a206fc40c614f0527e144dc5b1f10be5baa08168af50594e54df352c9ead4a56a19ac23df3ca01250930c12b1d014f959c85c27e42672d0a248643c4d0abba0e78a0b9c878d632af1c9b2c9e8849991f3070c1e668943f1aa21d50bbf251a48a55d8adfe1c8d9673ff23d9adf3cd23677fb05e0fda74d04474ddd9e599ab2c8eb3c5dd532d6abd2844b1b63a6caa5ec424402a41eef307bda60f17d3c70a18ccc90368aa2ea8da8855b3329b0a5423a087df14841ec2267243e117ca2de1f4fe8a04473ce075d8785e8e20f9e454efc2d156066a84021a576f20d6d11b60c8f3370ecdc7f4dabb34c37466b0683648beae2c5531560219194408d30d30736f60b090eef28e8a140aff787df1dcbe864ba34ed4eb8ee80d040ca5957e4be2df581e11b43ba179b33c4ff8dd3988231986a26114c37b6a70ebba3a9d93561144eda4a315b6e7967b0ef0b9570a06fc5b70cff02bcd6cffb2aeb27f78b5f51229d7c6ab3d634e442da08cd053c1cdcfdbe02de42b797de10a5649af46174da86efd7a49522c8ce2b9bdaad7ea9c24b474277a0f24b974ad98dde4fe8a7927e4c8426dffb2ea90424f78489ef03ed218328c4aefc51784c233959016d39f073837974f483ff0610f3504b70ff00a009224befd3295e77a3ce3115e6a529faa77dc1db83653b93e00d9081d0f5b7f1bc82364d884800a1a5db6476bbf5e5a887410e64ee361b1ce7c184c6578c223744f65d76dc2ecdba19956203e26aa56a4ea84b30ea77376f934f3eebb229a1fcd65f48348e5004c97c90d74ef6ad3052f80dffaaa8e119b544fbb3b32f7e8a98c857af6a8b9aa5ca8b725706391ddc59be33eeb8cce40eed6722f8dc0330021e3519447db2b54ef29a95bfcc875a314532d9e63fd85f19ac965dcdb41d534996b686f72ea0d6a2850490aca872cad2b3015c120d391cee0816a2ba6c5f508242784ea2952f8289ea679033a57c0e0d7388f94b664c6d663a1e46c9439d749fd7e422958a4391688e87457c8ac6343d10ca31d977725e4bc9a7586cc9ea2c6c0124be816187932ae6645dd456e7a2908dca776ee3e417ac9cd2876e4b2af254dc46406a71f7367093519e74e4ac85bc7b55b076abe295b6871fd98c01c4dae15b4706394440f394a3b9bc28c9de224647486bc934da4ed68996559aabf6e5dcbc80c06b1384ffea6b3ffdb553cf67144fed0175f1c1912d42ac58f722a1cc2faa460889270fe7b66ea02522a3023450144ce722467ff66d57990a4ad8f147f11ee7903c2ae4da74f2e6686db11d964d7ec3f82935ec39bf4fe01ed9ec4faf9732032504186be65647b33d910ca51013299a2260f4df0170eb6c8ab43c88b606f4a6d147ee70ffebbabcc9477af1a1fbd7785a629b1433fba32d147952a7f180ab78fbaf157c48f5c67966681b406aa6e04871cbeb912ad58a3564c6e223ee28a101ab6870ae6b0aabb6dcb63492befdf42e54c2aaef7bd2d9cb9d0d80c9e6c0f93e6949e7693f7779c7451de532a08c3f948aecffbfb291dabe067594a35e86a4d47f02d6c362f761eb24d1906255dfa2125534efa24ee5d277ab108dc78cca592514e848ccadc37e0f3da533b7bbd48831cbdfd8c39ea71102cca2b03165624a00beeeaa15d65f207c0a6e458067ef2d7b7cc40d8de231c96dbcac3301dfc13e0fc6565b6df0585b433eb1baa7243e54ddae4426362bb993f1a827b49b6fef1cfe0068aa8673a42cd74a624c0b4b49e5c3806de25a5df94156561146278c8fe324900f610ae68541f7f5f704e1ab8756a22a504edfb7548cb715c552fc63a97b7694957cf8a412aaeb4a3d9e8ef55520b8c6d8dc233213d05ecb7249a0de6791f1a2bd646c63565efa7b70b0533499a88d6e0851ecd4368f99564ca106d2a9e19b47e6e1925ef541d16f9d98cb6723c2c49029e9e18993447176667109d616e98ae75f25786d06f4054c33f6f35da9f98bd5c346902c4540f696eaf574153625326aea5aa4c4d93bc56b2f4a430c710c11cf3270357395ef369e2923ec9e52a03cb17050e8200ae83e362486aa418164dbbc06257e90cd503518a46d89bba6df1b2c646f4d86e614beb67590aef5894e67b24fb3318dcdcdf4e01948fdcdbb91fe2f2b4d2b3c53e29f327cf4d23b1ad528f9e9d2684c33d5e3f397a965f76fcb00ddd05f59d8cf76ce9dca18d97e2b1677265f15235f47f426a8d0164564bbd9ec9f6bba92cdf097d3b546c9db28b82aa124a1ba7f8522568e6d1a0c61de26d89849cefd63962eb3bea8f9dafea7eb575e597b3136b260327da178c881e63e42c2d6b5b67b4728cc4ebc7401a069a951b5762a789c73ec8731d5a586736397f14568f4a76eca667cd544830606fe316f104ff51f4d2af6ec4eee3718e887b89b20fa5cd026adf38ccb67134e2d11e2c22a8e04dacc4efeb37c673818028d341d632f30b868e69dbeb91529b980e727cab57bc31b59436c3c1603520a8c01f10ee61da992359b39fa68c99b3abda07f55a9f0d9eb563c733f0304ca12dbeb05169f7de795b0276e062b1ce8d45c50d3c01c605ffabd8e5eee76068a93871977b9d5c19e51b40809ea21445b0a060c44315a8006c6f4099c35f9a762e6fbd05b26124a240c0efba1caec5e251a206102118effe14449a1fcbbb1641d4913e2393cb90dee9945ac230a27370b549a1297ebf1c31b46f66ad5e86f23d3952aabb2a3b6135328261e0fae6a53316b1d3e4624e5e2bae60ed678eb1ee2e2e3598369cd2928e1250576f601b04d89edc28650d5ebbf3e1c3c0f1bb0d24227103c53716d20e14bde0a09b344f9baf57c81705cf4b669a380415df86ce59a725f0ea6c8a093ce7128769ddf3ccf2e9c3fbc479681cd9434b8cc4caf13c413209972e2f63da88ffea630cb762c32d197d7677af6a219b18083091fde5ed578f0ab5c531e23b18a582f017c1611f14d794f9945508c61c660a549a29540f67666e5c9a2a6eba2a01b948058bf6f3d3ee5391439891ebf77ff07b64d1f4ce5a3ad9ecf040b7386e6e803abaa9d51eb6cd0b6339744ba9f1724c7713bdafcbdc920e976ed1ff45a5c9cb383838804035897315dd721a323447f128f75a0180b44cefd472ecf09322f7fce038452ec81b122299a07ec791d01b89a8c8cb9c256aecaa86cba89045affe3b1a298c048d73233ad62b99f1650a6a8bd2177cb3633a0983decab4d458e3683f22809754583fa5aa4d9934b4a85fd9efd09c93b7dcd9ffab57876426a9853f55bc3082203f47e3acb56f9eb88d5a51e101bea9486c1089da11fd18625aa8c110d2cac9f81158094f60e06c8de4ca6c5d35aa7132563f5c3c2f1c6dd73a31293b573682d0d01a789e2b88fbd48d68f55394ddde4d08226d81c1bf8d267c1994c903fdb49ddfcce2deae3e23931c474108d7a30876e7490b5b6fae4c1df6d597ff1c95ad1fa68798b81f5a1b321a1d977841bfb1e966aae6ea22a2f4b7914d2a7e2f5d44d0f2de05e716a9cf18f8e1684d02e8d424aab5abba8c6021650b1fc027f1dc3545bb4ea56bfd28d1d52a93b91755b90eacd03cbee55e56f7b2ff845db5626e2d3dad4df7d20cfcedf2172fec64ed9dcfda762b87032e400fffa664ee322a75f5aeb585eab29f22c873905e2f7dd9115bfc6962ff477254b04002a3ae2aa44638abdaa42359d05a6050b1ee64a0416c8d5607fd4287d18298f3bd91c5f3331d558308be86cb8fb596e2956b122bbd5f4be564f28164c12252e607f79f9f9f70562fb5511aaaf9bd954d19fae519a603ac97394b4776956a15c611e73b7c09461f2cba94f1e51b5d8700ea06727dbc037628dc9dcf32034c2f5bf1e033927d99942ddd66ee61efea6d41f08fb6b9c22c77a58cce75e3812e907b23dbca77288ee7c4ab60d6fe9cd76e76df913fa73893fc75059c3c793bfcaeba4940140af1c0290e95765826896938d2a57c2ce774a43e7d83342e18d782a69ef463fba22cd8c0823058eb2cacd0259a69c17628fcf5397e7501f152e0d09fc3c3fcbec8e66d06f2cf9716ead330a486627154d4f5e5ba4fdb5b8e60de76f00af28bc8a1a7c94a1269a742c9d18265e78996298d31d542cde63658be9e9b6e4c1188b9b824820bd1ecd8e213ba802b65d9357e48018ffefc80bb033fe29fa318a909423982694d4e059dd3ffa37b96a1a7567cb99457fcc62c07c6a8b4330a1612aadb45c4f59909199c1342828c7fa6e60e784f887361992481428e2f8b83559cf337e7290c6d5f9eabcdee2e8422e1e9ffebf647038a0116600918ab98d4a85aff98fe70f0201fff7dedc080cc9cf9178ed0876c3b0d3a352c0f1fb7dc540e26c6d243ef8ea0f7bc7605cb14c5e1a5ee0f752def8913a568535d821be0a6645227a16f5973aceb236d0bfd1e82c20cb92e8535fdc25737b53a12734a24f0b583b66a15c2863f94ad2f76c84c886130896f2c80ed2496701812d90fc76f672cf6fa98830fd95532d7eeae1c8811f1dd1e79746418b94c74f7eda824b77c1ac63129efacbca215cee7c6eee0cea294f35296666d8344a266660e24561945e9b9dcfabebcd09a95b8ee51d1107f833e10010761d4a17359ad5633ad8912c55ffcf78911c90933bb16da893f861ceb77948b7303a77d20896612a60d99b5bea75abd8febf3d1cc559682df214a9996d8660924c3557947fde5c3fc7e8879077c60f42c62050884217759b0ed814d02cdea0844a6cb24ac9f63999b4ecff755a7c6eaa1a7cf79125ccf2c282f92a1f6e9648bff0d790fdef1d6c9536737f27d8d78d4c2a72bf56a50af31623cdad97864b8e11010e14fb8b17e8588eaac9d8fc03cf7b5f4068f53901472234ca0f185c1298b8ae29e58704c874220c9e714237d282a6600618c0d8cb66b45cdfe1363f6c7fdd5d5f1244087c572a21fd0cb2256f0377fa02d869c578624611ab7a78b2ebc2101e4fdc1f1336213f6f53d3645ba89d50389dae85af176f477fd68b41bcb45a6c060e1b6072bbfbba29ce1d3f01366ff32dd96761dd63a81eb6ca89277eed3daa38249b8bfa4eb20f57209f49042dd46321710bf5e496a7e80f4e33e4c6c9771354463ec822adcf43034c4f84a0386ddace07e7ef35271c6a529932cfebe259645e71170e1807250ce4b16b004a2d9711e190d1df1e0fafb1980ea63508d1515d20ffdec220fbdabd2dd301b55bbffbd0ec18daba1c5be786d34c2fab28b6914e2edc58ea3f92df8b0c0a0544cf5303c321d281ffa08a1f11de72e73053249eec384f83e8699081c70465d43998af2aa2bc116e2fae346e9df07a0f8087521a9c1fab6c1614f370028019432a63927c0e95e197cf16c871611515cb66b67316a83e4f13a79181437b9cd792be893218a6e07fc1486afe712e52a96ab0dbed20a7e8bc4e05a44ef1f24379a67483d6a3f393c1aedcddb87813eac2d7abac0fc5fbbdd0039fb922644715cd7e1e988a02d9b5e405a01beacf404b73ec3033e6672a39c21d053b39143a5bd1fea2643c31c12803b1467d46cb4f44238d98aca0488e1d6551f7e2ce64c49a998f6a1e6e53a5ff84fe6c4244e2b6b5cb1d00c6ed6b5bec616966ffac232057b36dcd91d45b953505c25b2c9c21a8661ce7025696249170fb422f6338f02b3d5c1567c185c7e6a93f84a97820fdcc8b1a8b7b3314ec81a40945e2a4199fc6e05ed5512e1611e6b4ee56a2aa7841a4e5c4146527563b64ff137d1b988160abfa72616d15ea1b19d84b01c543dbf33123248b1ab52853aa50320194dd98a562367f77ff0f498db501af5d92073dbb1f2dce4e2916f56c731946c27e24a07cc90095a634c1937bb158bc4b96e8cd1f9fdae641cb6a466286a51a786664a474d66a99787aa07ad0ce5c2bcb5b5332402bd1f644b421810680e1c486f742791a86945af665b0ccda4957208d12409f2eee24c1a610a052ed90de4a857806ee109fe957626b043cecd0c9113508908062e9bb7cd561bb0dbdf4fd51db9f331df19e0143bc2ef27d2d5b557d55b8dd03e29338f7ea31a8f48168a9df040ea6332f916641b8993ddbb95ca20760d43c126bb7a18a8f9d4a44c763dc3b57bc8c4dfe209bb316165eaedbe24bc0b49e045138d1f7919f17ec9069e1583d9adfe91a450984b748082b0506aa8814627ee307770cb32ab3f5948c362e36fc7e4d13a6401cf70c49ed0755f216d936dc6f5e2e116d517853d2a8bd1c1c5e67ad165ae0db3f9babfe1c719a1b9058b1129d8ff031340810fda153b7335a947aaf88ba69815d697627f52490ba680f42f6e0b36c27378f81f30719087a0fbb2b664771639f2590c4ba48da4756c6897e4d1853944836e6c56b371f92c6e981b9a56eae88a2d444a3c0d51f87899c865267fb8740a818d1604ec66ba05d1afe73aaccfd370afc84abe882775c0887a3e12b683ec02ba2aa4189a88f970d6c4494f75c6a7c1df606703d4c12d82ecb46d591f1236ca9a0ccc8445131e9fc18815a29969707934511e69c7350372675587f0c471cd84a3f971d267d22a4598f6e51547456388f26720998e32edb4e55d5e97f0db4f40724debd2ee88b1a40381f9a05f982c02fd3afd8b35266fc5f16d603f25364311cc890f9d321d500c25e845dd39f6ca807df88e8a5523e3343171d892cf773b1d7b53ae063f85af4d359172544b0ed7f3d1e4357d706bd201b23a432c2888e22eda0ea232d94ceb3fa5a548c615b74f2e9c3b54512607fe87310522e7d1a1e84f3186314156df1410359a4be8317978848e9e880a2096da529735721b5451f344ef2702d3704674c1e65ba57cc68354bd369327ce8656216a025ac91309b360520c9f796a2e59764b34b09da81221d402b41a97ee4b076ad1449e089f72cb8d932762fd1464f56bb7d3342d3467f0ef0593a0ca969fee6d111c623396a8e571b6a69d7c67fc130956bc9816092665e7359351b28663241f767e16f314e467ec4f1d599d34cc577a800eca72b7cc4ac6719bfa489a4dcaa8155e696125381c50386302520b220b5ff251124194f04861353aed76c5b55394a860b91326fe202d3a83881d47fbdb0d334747d6cb4c538621c6655cfb3e0527821d9086936481842cec2689b2ebcd1184a8d985ef90cc480654c0dc51ab8a1ea7011e78e8a5cdf400938619cb2490a2cfba40f994cac67e882cf858dcbc6df7743058275d5517b8a7c37b06572786bc292dd9597f28961a6ebe9654dbd6f1d23a2bc202632b65e9c30074afe52f341b0b1fe85bf4162ab7fbab45436ee8e6cc4e25022f7ec346a59f9abcd9eb352a6384b49e4011bb7e2bc9da95a7734f0c60eab5fd69f97d9ac9e2fb868b24583584ad0ec26cd3895fd740019dd33e28dbd98983883663bc015394d549894461c0f84ac5c09835cfa2d5f8eb84e21caff1b1240a25bad5aa261d86c3a33f1fb7a5011c81c82652f6c5a956f238c5355fe89d419dc4c12a380894b63b136ad833e4b5f72cacaa1aef0542ad42e124659fc5c68bbf80a76ab206f8a8680768ad24270a348f59350e66d02ff0e3787fb694c151b3f5389ea35f5b751379828f5edc1673bdf38e82ff9eee06160fb9fe7bf69e2dc8f9c93d8d769db39896b560ce06cf328a9ddbc869a843832514cf0ded0f9e3fb6e519f32de31b826f196470ad9d814d64ae3045b97dcaf66fcbe422e264511aa15133dfb090211b54333c1268b8c0ae80aae298be084de6b154b4d8c8ddd37e07829650d715e68b8f7edea25e74c1960d78d2bd3c4577720e547d99fb3badbdb0afde4017e77adf7141ab295c0a9caa8b4fc04de85a51f4f87afc3dc3900b20bbb880fc07d6b91f3667dd6f24406597ecc56b46e40d170af7adbf890327097dd7f730e088fc6db925290f408444cace8bf6a2b7212d4c3c417943d539306e470cce8eff0f37ac7bc533567a1410d7f33e292c32bfafb1650638810ebb7a21e32f0b8d3200d828bc41f4babd857c098fdf0965153adcd482d033ee8cad9f5cf43318909f37e068d42e0c7bca12e3e3ec7c6eb5b4c7fecc4400d4e9bd451b1eee85ff876f0e9bed2e63db314536854e0d8aa40f627c35beb4891b474338c6b59a8e2ce1189acf3a66c832cf41d84405147da662bc2bbfee2399a139852f82f21386251f03f7ba3cfcd4f540a7349348ab08bc5008c32c7e467c2313e4be7336ca0586e6e9d83df17bfbbd8fc93bd4173b260b7a6d45a2e42a5a4421cccbd6fd373eb1affbce33b2407e9fc065b33b80a2d8f05f1234b0d961f4cc1bf57a54b1ba81a64ddbaa87baaf01944c80715f194f169157922420ca1001949621c97c3912b729960a32151c204f22629813fedb3457cffc0f709b345302dadd76ae504b90776ebb9711771a12efa27a1c686ba566fee0e1778bf8e012c9b24de47bb16376869a5666120b97f94568f984dbbadd77e6d4c47d3110b4f0f361f72b499c13cfdb4a58fa5279f1f10cf6f1b681eac1f0db20db780f1252b7d53948dbd31ca7cb3172343149d80a19d5794fde1cfca316f4a7cb652c09704bc732fb8283283a777b8f58a72d9ec7f9071a1cb17087e142995774d8f7c50545254f958b44441b8bf7a4086e11651b97daa22bc69ad58ccc87129f1fbbfd44d919c4d500a7e0c7d72615a05e64372e882f868cb9bdc36ff7750e001a918701ca6a032e7324077e6ee6bb861a810f3f83149896194288e85a2feff60247d0f418b1c8f6e4ae8e9a17f491b87e8585ea7dcea56fd8e2d56f14174208a2133890e866bce0ce51a95cbd3f942b0f0f64b656a2bd0b029bc285c4bb328c51ed56248113aa210b072b95c72387bf577fd9a51dcf7d51bbf3647aabbe1e1f27d665d46b774a1448bd14e361f97d454ca8029faf3e19bfaf8583dd814557a58c34c5bd7a4d88ffa5da8fa8c6a42c2dcecf50fd75494a7b89db50d8b586616613afdb3fb210d2099bbb2f4b0567c854e006893c087b175cd53f1f18e360a7dd86e665992f55a582aa4166a01b466e8b275be8b1dfe92ffb40352951e200c5980c49208d8fd3dd11d9e7c2e51ca20572f2016dffce41167774d7f30c56d6e3fd1c5bb0842c6033640af94f6e84aa4fce72f12ca91d93821aceb3940733d5a20c1e47a4b8f64cffe8b1e9acea674e80fe87bb7329211c12f55905396d3563f426b89247fc596706a88f24c5de4d2a647ff677d01688646368fe026f3c3e3872a407854335e17d5c49586aa24a48b13921290a8a2d4e5948c07952ab6291cdf2006d6910fb0001223860cc94546c795f4fed7308310a45eadfb2140c4142c10e5f03284522a450c20cfb607342a96618bac518356ae68e8c1a40d33e428218b618990de88a3d1cfa7d557c28997bd96439e09cf9e20a480bd5c3f6615308bb0694050a9ec74cc8898cb5bf62d11d63307c9f47ff0cd6a8ef4e562645d4384c954646e4345c405b2997c244217d7338a674b2cf20e9f3c824805cc81c034dc4cd6a5903308d9e8a0bc3b7086f60523f9841441411975d6bac46226c94619427d9bba40a6c77f8d00fccab10153d8d3e42cae7708cbdcad2c0bf1200b7f3c32a03cec1085029d6f6ef06d7a9d9277d7f00f664cfccb8a1350862f71ba91ee4dcc7535310c6daa9032650e3c8aeaa876183cb783834ed5fcacbac25b2289ed7f1c34b3f033ed7066e17a70ea37e9e79422c0a0b5b3b76295096653625c52e9d08238ca6d232075bcb4e25111115e63f74951281e30d10e8d4e7963cc4698d18c86229e09c8a2786108e700819a5be71e8db046074bedfb32c509b800830822cdeda4901ed9733da09added9930b55c1dd95a492f54714ec1d51413bf5df88fe338b7b82e94682dd0c0dee4e101a00fcafcdebaaa828cebc6793a1f12f4a582694262d436500e91147b179084da488c910652e5fc2ff1beb97349c58ac9b11fd00b0cc49eac84d75d6c626900cc6bc3baec012b98a021ab63d5cc45c9612a9d9f1fb3444750d673db24397c1b3483ecea85b03ddcb4e178fdcdcff94247578f7461ac0188ddcaf4ec8c5f6cbeaa1aee8e0891cc7f3ef252a96ea6d8be15e17b406fa01fbbfcc56757e26a2d4d7cb30144fda4ee92c28b8f82211e3884a036634c3373217255a0852b0f4d488be11d978630dd8e984cb30146087118657d0b2f092675ea2ed80098675b7b9fb7564b36fefe9a46661c8730cc497a1cc87221cc2780773f518c37b00e8391d09163b2abd2cab7d1207da88f1f820b001bf80a47869f6f70269d3e9fa922bb81cb7e112b0e46ed6d86ee6d107f469d3c4b600f96877f9a4cf2cbb88941d1a1cd575f48f31593325fc4f7e046a20421c4ff4d420396fc5dfb37464b03a4f2cd031eabf99f918a974dc789f4e8cf8114af9d9e4b2e518cbf49c4a56a4f34b8dbe882d3b149f7b0511ce08d174025fba3cb80b0b837f93a807f4cfe24214ac67779afae511bec9b0b084a5a0948e2fa2b687c95f63af2d1d094ccf4d412dba587d3b047a70a3fee73689ab8de38516f04bfbba343b3a6fb3540a9ba6b87f1b78b01babbc259bc786e0c60537ef5604bb1b5fd58fe7087a4a8ba38ea9d21a6860caa69b771711f51da20f8668ac104d13a2aa41b45b1075241035d387a2124c1ac6ad3b7f025bbb763cfde46dd9adbc9f84c4d0a05a3e84d496cd19a422ada88aac164891551deb45927055c77fd4a6f89ff10b44ff849f15b51d8bd5b9d0731da991fe109c6fed1457ab2092ea95850bf8aff8b9b3c1f4930001c20bfcdfa2441cb822fb27b1248373e4edf150f95a4866d8b9eaea30d3a24fca8c0dceab57e59a68fdcc9d1255175014c480224414a4fd71e9ff597e6bf8f6f7848481e072870dde19021b0c65fc68a912008520df8f548abd7cf1703c9597e7e81d665a9bdbab524872b9f3b0a4ebb48cc1053fbc196c9a8ff4a6d832925549fc87f1675c3654783ec24597f4a7febfee2d0b5131f150a615a84841a55754e8a9dd5093e239b57174b4d34365ce2e45ec4fa2ae048ff18953053e53a452dfb64e7121c162b613bf6dc78a64b08c069deda44eddc2de03c3684ec9b65b65a60bd5d4869055702477365ba7bfe58b4584c45ce20c4d9b3d843621ddd9a57a50a80e145b48108a7554f14569acc7787b3b0f09a6de412f3b3a1a1aba4a3b724205e49d0f5a350cc70646489930b141bd50478ccc532c98da4b4de0fe04176a2fc22b2224e8c9087abd4f9ee92123ce9f6d704d8737caf38ba80fff734dbb0bb84ddac5e3f1c607ca7b2f945207b556929d3374102c10ea3b7b836624400785034ab5c0ce246bf255140e894852a48b05e426978e303eaf2b9cf9be912b4736768be010ce5608b795de5820bde03dd18a6c2859ec280bbd776c746b4fdfbf187807f63d5e59a2ad31d710852e06de1f5c86f190e535c41c1d3ca380beeb9605f4deede5e7acaf73534268751b257107d654f17a874a45391b0d7958cd0bce32316a197561484aba4972b3c3333670b7a3e099456d80647d30d442d2ef2236b030abae0340368b0c6fdfd03f02da12ecbfc5d59d96d8059695d48a652d5fe6f91e97a99185a7568f6a875c841d30bedbf96187c1aca5010948862e35fbafebc68c3ad6945264c4064039239c8ad5a8e369d98aefe8462d0f22fb66ff68fb3039c38543354be090a2279230683bd818350b4eecb6fe1491251d39ca34a6a40f76d3f01ee48e5f610723d4c5d9e03474c12123a7726195581e9ce178c6ca7dd4b8662190363ffbee42a8ca3a33c8583efb5768ac35934b316501f80e0abf90c1f1f47b0879f4aedea069dfa1c37cb4d14b226397ceaf8f6a5cc8208f5ae366523e44a737d1b5e6d5c661754728d19deb88b4261d766aa1ea4be586a534ad75533a9ef18455133366b3a0018281d609b30d239c9ae4846f802c4c69def705ee7de69e1bb05628f561223f236954169e035d8fb405dc16db9af00681ed7996b5301fee6ccb6df431b4471e8c08fe2c3af5fc237eb36d8e7091a0215894d755026f0080d62e122457240ceace1ba55bf068d87866815747bdec2f79a848cb3203575b11b2af1814da43582bc0166d9850fe462315c487fcf37ad47a4834df06b481b264192c6555aa44f2b06594ea6acc2b195e11bfb8637ce3aa0d83ce06a8d43f3911220f9d99b3399c9161bd5f0a22ebabdabdc408c6f7a7c2ea2c50f61e41b53f40953f47cb5980052b1808120616cb658995e1c1fa8f864c14ecf5aa2bdab3e1b83f8b92a4c8a87a7174a5aa4899377fb13636e03b2902aa518259b19b63202ca95875c0b1fa7f102e04a63b5340c564a77206fc1d57eda7166cc2aea422f414fcf5b6aa1b111b4af3880effb65d1f8ad07c8771b555804a755305a406973324fd1c8959cb268755aa7dfb42567c2ffb55e43eeddd141304785415e4892e05749f3ef8e77e5e42b699ce5beba7efc90e56f5e32f0ad18390082076f40b81aa1dbf5354e4f0c864eb53d30fe0752bcea29edb6d0d4271455967b17c0b75f0f6f3a16c1295515177a09c9255ba7e626da4c494f576e4117e59b213349ac5e75e55a2593557b290819b299ee7b0bc8c5a9236f1c00d11abba15f1ddd3cc9384c853a1c6ae1aad66a7b530ce331846882a39f2b56abc21471b2690aeadc7fc318e56a3edb4ed62e2fea37aa5cdf09d3a2b11b9634248d7657a80d008bcb750d7fe93a2af996d07558280e447ec2607fd390d1a5e37e0d60e25deeb11ca70a0e36eb09a90a55fca88889a486e55c0a497cc87314dc2f5957ae0d9b149c487949e3491a8a31e1257662929466a1a348b4c898f16dc4c6db96457c3649aab40603cada5c5bfd462c0f41358407cf0ac1178bbef13a0a3cfd06cec029646f9e9167d1a52adf4b1b931ce4e24d3b8013b762219491e1c43e4fd6765039aae85547515552145e08cce908ad11316e0f3cb5531f1c956481aa0788253444c941dae934a4e0bd57ff87ea81fe15e50c376d1a824f62a2f6f92cf4fdefc0649b528a762ffb601625c0de182705b3e4f70932a6ea370aafa789cc255f0fd1c0162a81b0fa469d6750ff1e3e14f2b01ad452557abd9a3fbde14c80414a6399d1b1c7a3b24d09cbc732ae055545993ed9828d411b54ecdd7c748d442ff3646a2a6cabc6de77c4a24b33118a5cd6f3cecb986b67c384bda86917150fc750a6b999f30a7486980bb4886fb4660fe4e6b1d5e7baf22552883d4c341a66dc99fbf5981f009efd8603390e0f87041d643161c6ee53e5f1636f47f509a8e2cde23a8ebc3594ef83302db7d01e55a6c37110193eee0a18e82803076134483a650bdd5ad84850f97e7f1c663e3545e9c76086d2baf74f9708432d2a63a5c1abb9ac8c0e409472c5ca7f4fd4874ac1cd38ddf497a10dd813e5b176c8b316f88c5977013c281d762858233ddda1b5605d15052c1c275ae1551fc29bd88516d39b645783600825749bc8b44c015fd270b00161515e2bddc7678b9f7bd1d412ddfb3da7dd67dd8c721932fb570ad9e64dc8d42d64e43982b7b701680988a364d6b178ae97d9fb868570dca03f57010091324737c770f7b669f5c83bd22555eb4ba116ed8b83797530e91ac32cfe9031a4b147cd790582ccfdad617a106d95c1c3cc40fbf34d65ec8824d6a92c375ce17142c776fc79e2c6d3f14ca3a607343e3c08b2a53b12fb067eb871441704b6be7a1ba3b696350b359cbffb467d30bf124a0573b8b9ea6beb779f336eb4f23eb80273d586fec40fd493586b3a38c05211d2670094ecaa524a63f297226021135e5e37e7d4d7bd5a8321ded2f20b744b90e70b91fabda0bcdc41f9e319199486d43d1fb129ddef31fcee9df1251b3b8b672040125b9bb07d3dbd9ad4460787d13dc441b68b7f19e02f5ff33278f290968ef5bdd4ed2ce15e7555871f0e5bd0b1e4701da2bcfaa5e232a79e413e39ebfd72dcb0ca16e63300b03651a3ae8d310d8d2c2f84741231cd06223133ef63829d635ffc0d7192dd1d02ddd8aca9700ffa4eefc8095309ff70a99b56207d3af92b16f2715188a7b76de97866c50ac6f2777c2caffd3f0c27696bbb84aac133168af30aba3dc02653b0b919d33045d3a82bd297635588f355c06203497dbacb9c9807c6f853f2b25d5341350e735f7b04fc8f527afd02ac2398b8a5ebd4e2f841306947c81fec813e8a996a76e25db1e9a2177cd1760c9f1d260b94e1cff4b9263e19fb270b8110ba4a2142b84bcfd1787feb8d1a64b09ccc1b349367e8a6d0683c37ce03a4d53793a6b0265c985b2f985cd2e2cb1867159313b39f0578723e24d05fa76cf3b667fca02d564d7b6a523b2629fa60efdd123d6083e26b9b8436e148206b38dc5b073a3938a0e2484fc7a18387fff39e6e3c3c9057e2ec1db752ef8d6b79e3630260f06938292cad1ea0de4a917643275adbebe55c2ea5789bb518a083fde44c7da315d9efd631847205489e6dc5a408181ddd2ad635ab7961e1c44c16e73946aaf2068b0cfa964ccb5d57b4e7b9b82171a97d5ab4c76c72d08fa6bc1f4a5c708f6e959e2d0b021832adde41fda4fc38831c67a38123e4c1b25aa5ce2f6e041d1c5fed284eca3df3e06669d5eb7608645b6e0e139e88df346b3406d5597de54326738a69a9d7ee55303f747bed7e0a771667d05bbc1964d841d7a68dc7537a43985984a5eca084cda8da30147e9259909ec6c35371542b4d30c8e47bf3073af6c955febb3c10552680c90e41700ca4b1976a891b93da5d6dab3bc779d60dd6a9e4e17745fb9d0f83c01d0ceafcee845a3c973bc61175221c8154cba27b240f1947dd769727a18546b3a9001598a9cae0ba46c1f59c10bc911f07a2e0e376821045bcc81032de6d1b9bf9a6eaf4357f41a234b1863eec95f8dde6a83a6d93781ce68eb090e11c165556bfd4a9a22f85ef6af2b095a5a3ec69a25cabc66f034d3edbf46d36a43b6a48a50cca95493b895b0e2c568b5ffa2de47772cdca7017e76d44de6847ad23eacd7f9f1cda940b11dcb0ed41720d6bba90b7a5cd9cad538d66c035c460cb01b5ca479a29e46dbb649ed77956d94bd42294fb3178ad89a0f9d1e2f0e82fa0dc34bdf154521eefbf9548f95838d2a2a3dfee0ac5792ca772607f5a71b10985caed28cf5bba81607b168fb45a1b3d065803068020ed72b5f6bc29c89776b2f2a5f67c30dbfc67d7752d83e545a6fe8f4301857072febc3e83243a52d1d1110965888f5a97029606393fe6e3e5701fe3283f03eb8a6a6b779235b1feb4bd434b7e475c4b387550dbcb1e4e0f0f1609d8b4e95d280b54c2613ef1f9af517e56fd275258dd4e4e4022a3bae7b58300eb1930ed0a49c6f4f78e275e1c751237bb445d41edbabd3f81cdbb7c9ed3a1a9da72378344c1ccf5bac42ad94f92f9db95f9c90d199903d8a401d065a81a051cfdb032384ecd57e157620fb37217b6fb2a594524a29652708df06f406df8ffa4eea3a4b6625fb4cdbed6b690b118a2fdaea8724ede047d29ebb36c3c5c8c4ee67cb32f395261723131bc1863a5c3ab36599998181799bf4fcb9a82a26d6f56fb1aedfd469eafb6de60e6aeaf973489d2f9b413f48ea5c89ca45ed5cd4ad62dd6686a8629dbfb6953fdf833cec9f4e53d73a4bb9a8fa00f1c3ce497d5c977b49006cc09a3d74006502281a0943a8271c4f880dd12684732814197c9c3fa109c09317dc5395db9393f00909f814e4c946ee6928a7c79907ddf3f410eb5fa7670f2d3a9c0f700423b53c94ea646d402fdee08ebaf16a387b58f590ea268f0c9e1dc1783aade9af6103075caa47536804ac9de22cca840494a9c3de412c62e0207b9f596bd377ce67770892c2055d15a8b131518a3c8555f9d0375d58575438ac9284f96cfe438a970ecdf240644d08a7b266a5b383d4a0b1d3d3090cafc2b51318b7fafbfd6da72cd989cae63addf3e0747a3a95d0cd0da715dbc170b2da0d719a1a47ddeb3a3d9d927a19bfd7e6bdf7d6299c50e834b909f9b5e3a8fb2631dde43975184077a1698b18ea3c7c93930c400fba26accf7641a7d335f9d0f9744d38427e41a7fba8261a3a5d530a1c2636384c67385359661ad34c609b490b7e9e93c98ac949cb7761c7568225bf19aa0344f05005d8e701c107f2a1cfe37dcfe3f1cc0bbdf252179a394deaa0c6b063acd3a52e6723f1e5817b4d3da61948404e389b540833f3d9517dbf0e0a56e3c251b4233ed06c0c41b570c667eb4e4fa6192b6eafdad67a71582b7ef3823d515ebeebce2169e6eeaef6eead9f9a39ec17d4d5d45de8f6e9c954a25bd1830f2ae5c93d9361a7e2077a86183d43e8c0e22660f4e440081c74a067d740076e081cd06dd840d7e9c9834cbf9d9e3cc47453d75f74d96d61e1fde0c2a1d5b381046cc82e0d146f49474f69c6ee8a4711ef0b8f133c156f762da4d9e918c3cb22d64bd2b20b3345c8096f0d8bc7a3488e28193bae24ed6cec706164470a9e531a95353ba932bb226349507873f2509c20a6849d932a33523c164c6a6ceca02cbde0f9581ae2495943d16637e54caf04190f0b6cb7e6d5bb11a54656132bde50105e96130ea55e508cdd093a589c3a84749cf168a84015a667820b6fec0acf6beb8b094c8eec664cedaa9e5ce49892c183918388c72487895e8b168a56e06d29ebc1f0d23b9165d7a34b4a131e95243b30223d1d3e78464bbc201abd18388c88e040c153016dc746cd0f3231bef8f8e23da1b233e1c9ce49092f8d4aed471b1e3cad1a3b2aa5a39d92920a1e11b5de0a36bb2566b480e90d6dd925559101a59763096f8711254076534dbcb01b3d2318426eacd831dd08da7db1c02b018d90147631c27843acb891528609efc5d5ae8a101a3d7860705841da21d968d164a3441a373b34b32b313c13ba98c0b2c3e24ad212437263081ad4938eaf196b6a14ad50e304afcc1b5e94344ac6ec9e889169e19199b23b73b20382d5ab518428aac98e9e50d28e2417504929765c69bb37e3b7867765fcca9c00460cec84959d972dde0cadad24bbb222587ef0cc98784437dcc4d8b140a385160d13476f7666d4f090cad800d35301e6c4ca2e852dde192da924bb1a45784d3f5630ed6edc001283c68c163c2e334cf464bcd985a9d98d95e1b500c3b302b6eb62a537638be7450b4b925d9422477ef0ba984ab8b1e31223888c164c324c2079c36b41cd0e4d192f305dc0ccac406ded92681d49c22b518467e4c74e0cd36ee9066f4c0c2d482d7659904cf08abce921a9d94595e1918149016c775ae1596df17268f55c2451a1c8eecc0f304c3d6ef0881126468b9d550c13bca237bd146a765d659ec020017b6165cad62e4d8b5725490f4711147eecb68c9c69a766e437d020f558c0285282918285b5aab33f5ba19bcf864c37e9c98302a69bbf537b11d64dfe2faef05ef2bed7acfa620a687240e555f30bba6a7b72ae978f3997f9e2de7e9ba1e22190f228d6efdb29c9adcd38ccb9bcf052c210dd7e257b49463344aee750a863aed70373adbfb4996626a54ef3bdf7b36b591c36308072e059fc800d1d3660f282cd5037e0e06ee860cfa32a02e037c898b9b2460c654766fc3a3d8f967493b75b61acea1d6c0f255d8c3b9d9e47368e8ebaa94b6314251ae11001d0e969a40297d155de6914c4cb10bcbef756237230e3fe02b5ce83aec84b675dd193105fd0e9744548c25b1424bca0d315f1d015c1182fd02c9dee798a86bab9013c93efb579efbdf96ecd883b3d8b4e786873136f1930fc6203bf3e5b9b51ecf424da2a1b6d9d9e444cfa6ecc98b1a4463d8e3bc03c5a7d8483471ed7a83b3d8958dc934868e7c6b16b36610734cb83e5a91cc6bdcdface7defbdcbdcc8a3cb8d1778e3a87bb1d3b3c5503779c2314e63ce165cc29e909c4ecf165bb4c7d441ebb1adae773e5aeb9e06b3ba17846f087317c04ecf1659dde465319da3feb2da929a8bde73e29c73de9231777ab648d27b47543c14c6dde9d90288d6f59a6c9d9e2d98faadd3b3858ceb0674b1e4e22b4556076f0aa90ee230858e0ee6f0923a29883aa8430d7a4fb7e4ce2de989e2a9d31345960e6e17432e907878af4e23b17ebf333dfcd24130bc640e950e86e12573493a285ed236a483b7d092388abb89dd92f4146aea40b6dea05c0e631e1aaf07a407a4e3de8f1e905388a807d583021a5242172540a014217b0154c28a0a46424e682554387d80fec871788088509218c48290d71b6ac64c8842a1594f847a4142aed6aa8f0204c5104242cb24110aca71c34b2883202d56f509163a86eb4c6d7212722354bf3420a885100efa4414d118f2c5cc93929b2634390e2083820a536daaa03c09a26dc06a0936140c88d047a970a16b5410cac05930e44bcd8b133b663431a1e1a8968f31586a48f150caf242031ed8fe7b910443e83aaf4060b5564033d56c8d083927a535b6b6dcf73bba19f8c74b3344985fa7b4274a4b64794a33b44737dba37ebfc7850529de2717551950499419df8c7b5c46cc71505835b3c67e05fe762bf5d56d2af7fdfe3eadf7edf737eaf0cddb0fce8faf45907fb7dbed96bbcab9ddbe8f3f0e772b45e4de83cdc97d0e97f35f99a379b8cf707ee3347f31d46737c3cdd11b97fb74de9ee9f071244df16b09eab00716d6db32fe889f7bc5d92fde3eeb069e576c4f687baa287e187e1d4b13f755875931db03da325ba9f8e9f03d58911471d7c2927bb8a0e61caa57a34ecfa9a41ef20d44101a6c035dcbdc94e5a9757be88002b95ed868eaf206d1db3286ddacddaca588bbb6f6b667dfb76d387face9a63debd7c461fd043d7fa0d91e31075535c0af23e2aeadd934fef46b5d9af4c4a6ce54085797664ec5bd1842d611d0e939e48ada9e6b73b6d95a10cc3b679bdf8223ac542d2d500fdf8ee3385ee1c6f176037f84edb752c4eda34942ffb97df8a3b5a539c2de1ebce298802be3edc1b71527e2ea78fbf04d9da95e1fa7c3c592fffd102ce9589abd6ea9a9216dab903321a790acbe804e4f2144b61cfbb524a8ce12b524725756c4f500a8f3aff8ca524de5a4fa1de1c1528a7353a5888b7bfa14a71f87d369dce3fe8e8ffbf0adf8c10f06c1d20c41307c50e7f7df705e7c1d51fc1cb234c712771343b00c01d473218ee54441d0825cb967df0f567c7f84edb5493f40a76710a520449d019d9e40beca7be9adcfe9bd5404079d3fbd7f39ade5882c7ee06f8a7fc56e86fd3cfc8ff312f7b79df37b1cc707714a5347aa8fa5c94bbacb2ba3586e6d86284d9d262b7e6002fdd84af3e2ffbefee5e54f7d1184fa6169d6c7e53db58eeff272ce96a87efab348fccb5cc7c94fa7b346d6c81a594c54ed1198bf6c916c566b9bd68dafc9119c20c4152560796cb6d0668dea0370dee6e48cb6f7602be6b7fb18677bc4c370c812514d85562a7c4b145a281be70f658da0a47ace4f22041aea217467f5c81a850085113fc59ce2280faf256189acd2b665226e917468e36fda2370d4f6a8dbd78de54f7d5bfe90834e6bdb575dad25d2efe18e648572234d5a6687749703dde2577a396ca82528d65a45db8be27bb0a048f29d7b3e31c2dd64eed668002290c8bf473061d0b7ae47150906f823258037e09e7f00211902cb9325901f675b698dacd1833bfcac11077fb62ef3bdad11287ee0f6686b6b5435c8d46c47459eeadf1252b7d50e7d2896c10d967df9c1ccbf4a454ddb5726e0ca781fbc5f936e38168ed9a170cc4e2911916a4836147e60186aadb788b437894f7c057f81a0266de1d8b658386ff27b6579be4f87649fcd668742b1a1133631c8f6a1982d44fbf4195a38a64331a86bdbeb3c09dbeb7d168e612e2da3c5b23d59b689c51a1fcb168a856676e8fb50ec0bcb6c64e1d80ec97afdfdbbdcfab74e979377dedb7eb5b7866255036d75c81cd2cce19026eee6bdc25cf88a1d02ffa89bf70a141f046ff5cd3bd46b098eba3a8663550310e4fa8ab5d692837bcd91589afa4c0412231075fda07eaeb95985da6bea514582415355022d5636c7fce1587d539f75ad3bebfabf8cd6f59b16abeb11d80ce1d89a9182391c23ea14ad8366088a6689bae65cd7c1f2875b6b0ba1b343e1d8f785647c876319570de0c4b64b1384a16ad3b67a5459d871645159d0cae22f58c5aa5f896cb5e7c7fce8133fa8ff997b6361f1c32eaf2679349438a4ce66f80fa771e54ffdbeeffbf67f5ffdfd8196ccbd92b4739b7525da38fb4d59a9af434db88d9b6c0f8b5c9ba07a709fbf03b3831e22ec8f653479cf1deb5e491306bd3eb624ee1ca4a02daca439f66b49985a2775d3e6affe3647e8affca99f78015c69dafe7d1e11be15f36fb1fca9fffdcefbb1e580f3bb6e5bbfe66d9fac435583fc5cfc60c43d586bfd3eac1ff81e6c254ddc41f16f6fbf0741523f6823b9ba48e6ce49dac33cc2cddd83cdba67cad581cd901f477ab03c23d0af2e923ae4eaf96180b3ba48e21e9266870d7a66f1fac11d82647e5bdebb047f780842674dc4b7ce3a572790a0534aacf3747a4a5df5b3320157c66ac64ccd39ffb6e5a67252dd96b37dbb1370c5bc9ff75ffbd5ec863a4d51b9289da55c54d5e096f47e15d3f8a1d437747a4695e9611df7d3c7573f819c408efa299593da4b3d3ff8b9a9b236417de207b6d6a89c14cf855d24cb937f933bc9f2e4b7e456b23cd9f6d83e043549f55fdc8395cc17e741323765289b215bbbedef9c94e65f495b9a78846d4fcb0525d7a4dbd2dc7fab58ae897d9d6b02a56bb0d411d321b31c7242335597fbc8ca887968ede311f390ffb524cc1cd4beda2208b7df07499d25db531ffc1c547d807ed0cc4d5511b7ff6cf1025c9b392911cc49f5fada8678b1fcf66bce8be6addaaffad6cf41550df473f103fb3c3fb6f2f387fc58fc704511b5efdeb7edbd8317871f69bb48d6b58e6d4f589a240875fe35a8734e1db003beedb4d7ffbecf24a1db9e2a20f7510588540140b7aadf74e89cf70e185078c08a6260d1a1a7a88d9416d0f87852834ae162724a21480b2b68f0235a67b6b349091c0c2b00d0e9e984ac879d9e4e5a10c250024309ce3b9c75c050a2627c6f8c5a7f6a01bafd167cdf1f81cdf90e0805e8f60bd0adcd1850ac8df44d0d9d8707438b1d1010e8f65b40b3ba7ebad6f18f7efb2248087302a00ed81b02dd3e043e10c1c397cd6942d96902965af9158613f79e5a41dcea4f13cebac9eb3e72cef8b1e5b1f7ed150e4633d06ee27a66c24533dcafbc973606008380828e1f571c06a0e3922be9a19d4cb2b6d6447b3f15f5de9c7f449cf3a3bd59ec21cb8228a3d9211128c618e74aed91d65a5ba49c31ada51dcad6c81ed9a34aa140adb1b6bd7ecddff67aff60ce3109e67bade52248f4abede5f6ef8fed963cb495a60de47f2fa0ffc7f6f8f5bdfcade8817efc3a8c1fe3b8edd1997bdf6bda7efbddcfff7ab85b8320d1dfd4bfeff333fa7f7459fedc9256ea03aa939d9e52278e40f56b66c9da2958e6a42c8f051f2c31d9990e50e764ddb4416896e7accb68eaf47b866d140441b0dc09ff07fcfc21f8f94130b4e408dc79b75f2e0a676c56d5fbe240cfcb5871cdd2bbc24933e41f72d0c671c7173b01b3923a88a3b8dbb36a0963228cf1d16571311e62713111516693bf67366217d4de63339a3c3cdb8a4b36a9e7359aba269bd4f3db260b65a52ce5b0499e9e5feb34e940e948d99e6d7bdaf7b729efe7f6b6cf469a40e0388ee3f87bfcfd63b9bf07eab7c791e6882e9abc6b114702f51b59c5ba4886087ba8496cfbb4d6764ae75812d42b964e4f25501dc4ddefb5309abc6ce44fc50f1d5818450e548b7bf0d67befbd386fde3e7cfcf48633fe487270257e10c7311c4b7c479c7114c9d1f2881f70469c6bf994c177b81c322839d7e9f1c7fc7d97836e1f972978c3affc480d55340720e23323eeb8ffdc92c7f2dcff117b63cb337e051fac97da1eb4220816e7c3cf8561b80302fedbe3d2cc7933f73a7fc33732477690f3e57c395057380fe250e746c2ed756e25c6e2071d92f69cdbed77c2fdb7f0430f38a40428b07433d8bfbdcee3e0c7b90f6d4fcee35c79b318e394d4f2dc428c83737b1c9c07713a609c0fc9d0f2e03c1541e0e0fcfd101a7aeeadf821875382c8fdf638f2edd2e530da0cf875ca91a45f48e68cbf83ffbe7e1c728f15a87d0744def4438fcd6876e836c4e5a0c16ae8f6791eb5f8e186f33ffaebe37cc579f181bad8887e356e2481fa25739834759a4c12966e24269f32f89ac163f143586eb01c32e850bf0cc8de9ad1e43b9de31dfcbc07440e7b05286079e8ef80c839cb4343a00aa054c7068088d65a8fb0fc04dddca97b9722581e1e42d76958d6af3766d47487be8d7edea12588b38ebbc6222d7744b0bd36a339a29b3bfbc7b07fe3984500c36f9720720fc35e9be85e96d1dc0005abd7b35ef90aab53b8cf54876f87f687a1f861f8a3edb17df839db73fbf0c30ac5c5cf9fd33d075c070f1d589efcfafb2a7eb08103cbc381e5c939141b4dfd22b93f0c4baac1b7d96c1b36e8f07d1c7401050772db437b2a8c1ee037b1e5a17544afa5b9533f8486ae69f8b5ee80a0df667b2a8acfc5e764ed4a923acdeaf4c4faea31e8243a09fa869904d225fe20a2525dee549e8f5a1e12fa4e2d41e45ebf82bc34f7d8414b5afe37522431873124c79c8dd4550d747307440ea1e179b486febdfe48de2333d21dfe9b7fb69cfe8e2d41e41ddb6f07b2d52da587c6da8ba6b7c2b89f769347b5d63a1c73ba0b7f31c618e452c0e7a948a47a7efb0348c096b1be696f2e973af1432dc34b86bdb3d10c3bbe607b7e9ef758dfdc67ad2bce59dc83afed5abf49e6c6abd176dacdb0e3de82da47d84ed7d6a80322d041a8413b20e0a06e2f40b37858276dcae993866d31e6395bacc107c8cdf9e9cebd255563ffb492eaf43462d613d0e96915d4d7d6d6d2fa7d0ff6924f22d81efb574756663dc42ea0fbfdc71dcca2cd56a715560779b8932fefb72441e703448b1ee8cf3de70e62073fed2f30017ea08e4b11c62ee0d715cb432bfdb157a83a747b2541c33a60351082b9a1d36ae906cb437fec96c41dc491a6864ee9074a73dd8a1f407aabc5f8567bdb01a15b72ec58fc90b3979991a1d348503dabbcd0b1a2c83aabb674939f5553ddc4f4acca72569d5443544121ed6298491ded350cc3fa62687b20bdc7c6fb5be3ffc8dcf86534791d63dbe3eff104a828815a04ab9b21f6a12711a95e3be7e204e8e36a71aef8def68354577a6f360d05da7b71df57efa7759aba997f721922ecf739ce72f8077116e32858ee7cf0fd4fd5ff8da824d7212781fa26312e2f794f08c9401ade0a8a37923475ddf62178233fa0fd163e152d0082fdf6f86fa569fbfa197cad7f5731fb2fd81e7e002e19a0ce2d573d009d9e5bba7aeef4dc02a59b1b784828b031c6e4871aa92e6328400323b244cc912d1f3ef569adb808d6f52ac3e10418b363c84bca099622663940337404117a223475444b6badb5d65a6f2da3e6dc266333fd4293716918402fd2d8203212c5c9d80a15cc2644be38d94881a4cbb7e4f56deea5a6b862985c14d921036d0b061334229797355d4ea89850061b49220bcba1630b0afc4c1520392ad861460b8a8bd50c214a55c34dd056d40e13693546d79af866cb4cd593d5d4112edd84cd0a26299a04c1325365015b583c994ac14385151baa52d84a3b53060b57996f8c172a37d25270a13443ed015ed092babea471b2844c0e06a2148da10975a521a5651753bc9438530ba384a862798585a413119831466c8acad444d0a30a0b191e6325ae8cc97182d24a3aab72534299a55e37ce2c1c0751bb2ef0cd971b65f2cae9c582d18baa1a35c90a8a30499415283465c94aa2f60597bf88ed6c7b20bd104a1bb2854b596e05434aa274ed58b1e34ac554575e58fd2073f1a5a69af07213168de158c3630a0616aa355ca4450a4b5294aac4daf8e42f3d7b9d618634aaa51a44be1011a989c9c009119a3552544091e493956ce9c1246bca491a8fa2acb5e6393095c69acd354dcf5e2d7a9ed226afd0d48bc55658d1951869def03055aae4f830fba296020aa11e486a1aaf669ed3ae951738b5bc4298ae135f2eaae8909142ce8d690516b4583da93a31d79aebb14a75da5780285c56c2502d712293e2631346ca9616636c0ca9505b0015b31b5ac595423bc40c51120665c8279740ab070aa5302d98cdf0c9643de79c73de4517ca45068482f8d0e2d10687189829526e6e5450e1d16346571a306af43b4332d4c4048d1e676339630b398c9c29bdf9ea4aa36976cdc9d2967b47adb5d6373752204d474b522421d391e4a351f83aaa9183c597133efa4bd75a6bb1aeb5de6a7c701d1173034709240a9490a4a386d1991f41720c5c05091a2154e78ed30b8616aac2a0e032c6c462ea9e5e4ce05a4f97aa32497af460d3a60b5d53a24b870a1a5f5a582c58ce39679ed1546c012f2f90d0a0cad440810b062e516252b0c1640d47925a0853be74947961444a140fab7223678c968e2443c8a26ca441b58932c348888e28ab16539680d6880eac1658a2b6c4b295289be5602aecb53ae34acc16193f968831b345e47144a9aac886092a646b560a0a38594b694ac0b0f062460c04529630fd40e2a116c401325f4e6872da08e3f4d59546c4a21665284b8f18595cd46cde72b393a57b94c1ad582b9820a4840d1592215c0b95233bfa0506510e2d132790269a736526b019e384085856962a4b72706b8ed078a15a43c5844b898971a4028dcc0aea024792d4b04af155a607962ea72e287e25c5ee2ac2014242f646c51ab3244f547cf21315634acad0aec08eae96506e73b584729babc5a5765d549ef60129252de90126869033a84e75797d21943143a40525355268ad4063e82a49c78d264a56a884e54418d232e165e8858e3535baa3ea0429566a8a988a6a781d8140563ea2b0005172b5856c2d7b60e5491a2f574796a4d5a7b3e9b656e2cb0a5e5098a468a9351b59eb12c245480889d789e6a360869230b910933285a9e2621835ed006264c4c79a101955602898842c9da83225c69d32853b89367dc246c912941d519c7015518dd981163426660886a562ba80f93ab1634b8c2854aaac6022260b852b53d430517135d80272d642952729b0e0e2d524d44b59d2a4904089fa92b32485f3451b2b542ef81420196145ba4c594384090b4d428e2821f981c40945574ed99694122c26aa8871b1a67717eaa522b7e06a2a0d911b2f243a3897d71130cb122eb1356ab450a1d1a35ca698697a66c65497549b2b2062b4ce5a6bad75ce187bc0cb271ba623ceed32ebfde001c2465c8eb548d75d60fc1674a5036ccd8c152b3e231851117346450ac5988f2e73231ebf2d976f7581d96b1a6319e93917e151cd0b1022535f68d6ea092b4bb61120c132c5ca8b8ba94c5acd2f858bed099f12de5c4439070a0253e34d150b66b078f8e4aa184a3ca05630f2828d4f8ef2044be1507a7e5d8e9eb3b40f26a5245034ccd42814224bb85851fb71b504bfe0654b70a4609383c69a103fa10a9b1ca012685650c8b2a40209d55ae572d333ee9ab29897a34ccd1a0f154253fc4917193ee5c51097b1296964d8d42749563bd478996286ac2e51b1196fb85cb0b0c44d0e4ad37815396345c916295595469926a3c2448b2426a4c21459dbd949cf5c627ae6da72ed10a65a53cac29c78118615d4848a1a0690aa4b088a364c55caacd6c9d5e6aa99d045a4e7e7e5b40a240447092527d8a02d9d31395950ea2a0bbba2cac1826b1f804b88af28415f44b2766c6555011315a4890a96305c9e561c200c438daa5c9587e0ada78eebf4dc4ac2d94a598ae203cce4866e64bb66880e1b589e5cda255b26f8b9d582963632486a6e82ac49f5f0b95fdc087171034658952f9f8bc146069d9e52d04829cb024d6b3b8833ed5f6b6b5090cfd500cdf2b925bd196a27a102595b6980f4c91194b6cd29e54c81a631f0e5360fddbf47f76f92eda154966a34d99e5b7fba54bbe372f7faf6b45fb62c4a8a7edf9ab13d3a666bd0b4261b4242f574c555f5e573e91a205ad4bc143d39e3c3e79630f5a6dfabb57e77939cc5caccce5440b341f68425c25075ea2a0b4cbf50b8ae5c16dc1761015470c4ae070984f0a4dfd700073a300218a3b9c10828d2b0c2b270594104526acc8cbc88892d712552df09a50ae7841c271c7d42740ca7637c40513a014ae3bc9fe2e71c0b631879637ccb135c74fb1b20732605b5a12262c5c7221135e932e6a3480c13d6edf43c81e83e8d40c793f45ac293d20d1b594e464d31a893174f94a841514385191290be098638727f27b90d07e610177e589ae1e370e18338d2dcd9d92f7ed0e713b48e23cd0f68ff09614b15d8cf99ebdb7124ede2077dbb5f2892f76da4eddc03ca43f06de4ed22d9828a7b59afbdf653ebabd36e7b0f162c039ac4a8444c988e5ac90c250d000263160000200c0c874362b12c4d523029db031480097abc42523e124865a228864110c4300c83000c0300408821c01003a14152f1005afa437bcf93c628b1aaed63c47da03e68b60aeed5e95dfde6901eb4bbe1c0d952a512a1b4cb3ed44a2824d1724a3f07793955ed8de59144810f761d146c65df519e6f50c38d156d8372c5df4b3f3681ef88c3a62ec66365d18e5db82abac9b284b4ddb85521b366b49774f1c20ec62e52a730cdb12c1c60cd7971e6bfb4566404819e64c2a42015626733505e4c91d18f2a64f74247393eb9a49dc61890023882163b86434c73113e5c153ee677119f26b45c26c4519b55dd6cdbb0739f6967bb6e6060f50a0d923f9e0f34a93d401899a54c9b55b72ef2d964d61c93b3aab93d7e7c80fd544b715cc946f7c41f97ac6e2271fb6208b18ab2fbf45984a4744085011ae3d407961383a8035a942156ebde4fbacb0a46c0fbeba51e507afbae65c5a1482e37a30fc4b04f13ee3640a894f28d49b2a1819a9c9a09980fc5339c74a0ff63eecdc2306368acc23339061de50e084a65ce82c70f0e64dc488d617288aa5a7367f345c4c1a64c4ac19210da9da9833ed76e52d0a384e279457e6622a60a28a431400a37414085fa0dc76c4801083133df04a698594b5292e5cf082c4bcdf20d49daae3c527bf79a7404372507b78aa87d841dc6d2ffd7ae39993a76b1526eae46c7214481d093c3828290a57c81ceb138dab8764a10ae22a17ba9c0d584d7e96ca6146741f4748578628a06b2b2e806a8cbf4a4d0c80d93ba2c89b31e37a97c841dc62f53679d458f59b23ce9379807ebb149f06059be8f7b01f722317d3b1b1d69484d1efc183d764a8d034c15c0d1e0f8b1beab71eb6c6ec0b664bac3d39f153c508d305733e18bbb09715366288b34e380d42bfe15adbd4845f7bfe7fa002421f61737282314a9149dfd93a934369861bb4972b10aa55ec394d7390db84f795f14db0ccb8399bd6d303a5240e25450762600cb098ef13a0a0fc9e9252d9e87521a1f1a4ed04c5cc2bc8215f09ded0715a3b817caca4f503f4b54da76c36320539dec819f36e105142599e68b856e1c4c858ed207c5568129d7b64cbcdded3f0cd7b20a616c400edc23986db7a39285e2f8d68525e62b54f3f352f215143ff63ba5e6c7bc75dc272873240c934321651d239e84bdd123718363b8646973333a32f2843be212fc4a4bd3d09b50e7a4c794104b9c81463b1a490de227b58641dbe79ef8ce24520c08e0e184de6fee8873bd83d92a5a47efbb6957182888d4db1a47f143b9d1b44c6a65034a3f724b0236804bad8d7dc449c7ab2cd7b66e9c18b7c8633823c7c43c4cd36721a5b24ad149d5d5a42218666103b839b6f5f21251e14a51f3c313abd8ed9c5ee43df64bf137644323d83615c408b65c59e866c903baba712e62c18a05a86d6a365b21200cc25486a20d29527862842840d8189444cb2d06c6c7c40d9c0b462e93c49d698ee97ea680d30d3de5c52c80bd10c95ee008bc695ecc51aeb6a89206622a24fa0cb71f73f4959de39ca3e497be7ea3b111b4b515380e0c46ea711983dc13e25a6317038584aa51d05a96e6ba442afa6f8584751f0db3acecb2840445962a36f988fe257f87be064aa6feed144b2954f2431a7d5bdb129bb909a3b018055ebd03270b929551e8b99d5267b8d47113eb9238141954a2eb2f0d994f92f39ac1a88032bbeeda64015004933f098512e8a78e9d269bc8e1456477387d7f05f8405af88a0ea150e96a6aec5c0215469900f22588067f91450e044c5a30b50d7c32f77e42d038bc924867d12149626d5500656dcea961070109792d6927636267ea732d2b441ac0f7abc26bcc733c1c41c7984f8f32e65fbc4d7d8dc26ea45842113e2e25f04bbc80b5c66f21f32bf009bedcaae0f76373900bbe38ad1beac16f7c882116e62b82b98bd4d4d99b60a8803205d8fb4d1188442ecd150275df6ef87bd3a51be14011dc06c66bb2345df21f61c15e502595baf795a9797554873e8d5f0098814e07722c3d24fd2df586043c7612947375c8db6d7f39494425f7e0f15551ace3e16beb5b2042f841d71fcb56ec83133a1a720fca3f7207e14a4ebda68b32bbafcafc000e68411125e0ae611d56279e733b28b5330a3c6d812061b34e535d4feca2b10c3713e06d8dd15d26987b6e37b9e144e9d39581460d34da4a88e076c0b5ef867494c3db91ff6848f90e07381687730141c4169b65e2ef2afb0711e05464f204a56b92715115866527daa1ce3b1bc0fbe7eb00f2fbcb75c1b60a6eaa043e6ecf6b54bc8e5d80c255399c73a5e5db31fe6163f4c3b2927ca2e08604207d12f7c927fc70e8ade665cbfa4e34954e07c6a79920957ed99953eeaf0535c72cb29f2388ba3c9fcd9f870f57bb2c7a714918f985165b461a77c99cdc44c5467c364e26b4246dbc76a180386d954df24227cfcbf93ef429629cd6869627129d6e71a921d1886926d0a20fb118d132848241644550f47b45942671bfc20bca54191821f5da2e158bd329e8d32371d2b738602a114f1c936f894463fca187154524799fd67c570d9d140abc297a112bc8ac2c3d78b590d37a3695e266ac7bff21c5761681ab05925e76853c699000adcadc10c355d5ab19f11d16c77143f57fba158ffc003ff1ff831b04134975f6d933330062791bc49738589a008d5e04627a1b0af81b047b55bf2499afa003c2813c71ae70601b9366444dae7ac4756644972591394c3fd2fb036efabf22781edaa8195017dac053cc6da4fc818ba1c48e4036bcf9bc3ae945ce981d5232e6ebc6b222406fc81ba00b47bb687111df0d4cf1ca7c75c699658d53f8be2d0593b31e63d3df6c863b05421a34f700cb9563a59dd6adc133a881a6f47276c2c50a1c8113d7f3fd754a5bdf379ecec963eefbeba9b458c947e0204ac21eb3d1c60f98c081cf0f50e3796d02392a3bfd7e5eb019cd9bceb3deacd142cbd27fb0375e0170e8a208346e26562b10b317e08179ca546db5e122cd510d5ba7e87d49c7916674e016e909c2f600fb8991f7c70277238eb5f3fb6b06f111d19986e881ae03b596443aef6d3d867b3eb29ab7fed3d7920474a99d7db1f6f074636268228f4b32ffcf66961a09b6245b8275f8ebfd4a26b8d8183f297022d0b3a7579560efd1ff3987c7a2842d4dc679b7b7968e5fc3067f53175330033ff70a330d534485e996ffcee27807b316f7220649f9f9b9e84806adf4b1a363901bb7c21da1fbb97d7b0efc7f6605e151ce9d25e5b60b666fdb29db96041d92405396f68380a7ca69d1393656a028d3a2834f0bea4082d4f44ec6765d8ff34d7d88dd47b205a36f2740114b30069d4c0fe74ff18832c1b6211fb187c6c0215399c13e587d6a637ae53317086bc4e99c2cd3b2762fcc0fc57cfaaa40f9f5133ea55bb25f76b7efe5bd8957045cd56ffb3c33ed1845818f78536b7199644f93b74991ba169a522847cc74df75532cea935f143f8347f88dc07a4b10bf8270f4cc6fb472dcb2a13a3d4c52d93311523dc9d343476ebefb315753ac87cc83d3cc5c1400f1acfa4f665b32a56062ac5cbb0c3b78c09a4aaf728a8a504ed46963865719683d6c855f2e7234cdbba04a9a0caeaeb3fbd498ed43c295f8e23f568281bf5b1b3560c0533da52473ce5a688de00b625411f2cf3e8c73718481fdbf88f21b02f97e5aa54021875a7e651a8a685568f20bc05f58fb6dad2b37cce2118f078c6b00bfd0077344e9d19d38f7371845c9e017718d284708c66e000c19480d772b4a993604613523296e7b3cc9269d36a414e5204561356ac3db44f4916ecea4451aa83d879121073dede37a6c71fd8e4b3752b6c4aa7167d8bb8e243bf50e4eb6aef06ed53fc21c44dc5fa2169c8204ed4ff009f1a7ed39ba224836bf452acba531b88f85003d34d8893fc8c48ed030a91226c15ca3234e6b0d66fc62048f0102f1f05c8bc5ee0b1367283ab13b36defa4ac02166b149196c893e9d9afc65c107197b9729112c0aaea51e92f0d2c63cd8d9d980148d8e1c39d3dcfcc5d9e8fdaa8abd4050787ebc9e961cd467fe6f689f14fd28f62aa3deeffb84e12831523b64a7c3ada273fb38456dab97a99a65bb391133ca1e42db9f43bc090c256b2d112769fd689c533ce6ef4b34a2074bc014737a3d72524ae91a996e504208d75a5d783b99b504ccc58a25668a0ce66a42815b3d2ead6fcfc7e7bc52ff5659821d58fd03471da39a8a57bb0077dd9f0e5d194c01460394b883cbb0097ac5d884fd1322b638cdd6ea9be96ef11e6a658206f394529ab723444789b8ce49bb88f3d2daf9e7e9c1a32597ff482cb799fc9fc9af977b2127b5669496ee1de833dc893baff8cc06296308b2f1f65e5f125d0ce61149a1dc9bc490db0aa03637b63e30f7c0fe11bf5b7a8595b5d279401ada6889c7051cc56ccc92221662fb672a8422aeb0608c7f2b69995dfe75c1481b411ddab9ae3336b2df9bb778116c10fe8f6aec2ff448652ef174749e4351df2060fd70ad2b257721b00809028e537055a66a3cebd735c4e92cf16a18e2c51c70f0bda749edc26980130f7d46a048887fec08314873c8ee75a6cd69bd971c51b4b2924ced51aa8afe8bccf116ce2d63b63d84162f129de762ee2986879b9c802d944905740f83bf697dfc2330f7ae27098722afc66050be6e2a7efc49dd853a845eeddeec9c06d8a19d831e86760180ee9a3e83a58949a40859953d401d45cef3dc333a49ad0e7d7177938a9b9865e495802f48fe5330c16bb35253af89adcb6bbd0ebe261efb6f634d71d5ddd3c536f087cde94a3eb9e018e2c5c27c14899d103471bd1bed1e2c99a6496f4e029dd280cac05fa4101134ca217e1ae006b7a136ca215498341655496b13c227a67fb07a30f96cab5d10e7143d6c3eff1d0c08f12ddd7da639132679e51b9243848534e0499149dff80f56ebc8e127df0fb4541f2e00f7d3da1ff0036d18cfa7838342419aefaf16ac8eecc7d3595f4f1fc205ec9d2a549c7681997e9fe673452c1487a40ce82e3730cd5bc408f3ffffcf7926e27f3111b0290bb05df81e04b7461001b6f8baa75bb95d6cdd7f3c20d2b57a7cc8d9ffc902b27f644c1538019db7713c093167e3eabfd7a6f5d851a050b957398c55601a51966494ba1988218223a6bf00bf7de93869a21810dbead08539b6d7c5a91727dbab2073e546973049d022975a31745e8e8a2d89cdddc57755fba12387fc62be74a0b851c15809dfc3987f35f3c822eedba4ede6b3f907e2132fbed601d709a8a6b3fa620d27d5dc5c1c195e0226bb63348b1097c48751ea6c1506ff0b414dae8c582441ee96f16c3e50fc75b899232cec42a6a37bffc8ffadd58999efc4ec795444e642f28912f5ab7b667cb4411ed23412706c263440a91c3a0d650517b7f8e74e05b086c4c0b2f93749929ae8b20713c327582af94098ecb964397131702cf2d427ae3cb99ba37cbee2cf39c87a016118f3a4b74c540128e824dab403d9a35c32cc9c957dfccdb731b5e22323c9b4041b6b3c96e0647534d904f221fcb0d7b6c24096336c38028a84c033e3a363c30f3a7abb81aa75aa545817ed3395c54597db3a9d594f1b405b3fede6f3d9f95a31d8c5b1114fab0e78c4c7df41e8b04ca5681a9800fc042f048aa548f3f0cdf204339e706c19054a1f0a516f9bfa96820c1a0ee14a79c68404813a54e4219537b56b8a639be0523e562f907702740472248d702c1156b5e1b8df0b20bbd4c43654efe2ffd1dee4ef616e37c6be143943d18d48fc3315e5ac7e68bf5429f86420eaefe2cd4d7eb11a269a3685329c5eab80f4156df74838cc7364bb15961e31064b67b39df2a9215c24dfa41a87e92d3441f86b5a95cbd5e6aeefe4d310137a75de1f00223cf76e1698d813ad7fa18cd2e053242153d16a6d1c096b938fb81a92646348ee8db60747a5117f233fb66e84ab434c3e6bc8c4771a25caa7ac31cf7292c9adca47eef28175c1011551b1a20761c9932c6a3ecfffa730d28174af8231c20ef97205a43edeb6077fc2eac277401fc9c2202eb2bbe161331801a2b765983b6a436e37518b38cbac9104e007e63a5816919dccfebf8713648fb01c5e3304056c2d8031fb4dc21446add271cba0e56bbf507288ed9089f612989f3090d80668f9210e553cc3f73196972a6adb72e666de20f6285b7e0760ec30f7ccd744d8258f2b807898760dd9004e76291fa755486176444f1e20116f2d6435ce77c4f8e0b4e8dea76a599b9413b550fb16a050ae41b7c532bf5699778a9cb45669bd4e84d380a6f1fadf872c57c255f3f1d4f3a61c1015a76283c7e386ebc41ed643950ec88102e978cbb3d093d87a08f985f7c1f91cee777db00dd2d3fe3b346cadc64431efcac7c0f0c6774dc42a0b2bf06753eaf3bed667430e7ba4c6a8c64e483b9884f1bbc4f223cd09f073836ce2ec44a24f187c272706c058cd6e0e1e9f51345eaf4be60255349c55a12decdef141d14e9de09141922bf77e7969b88119f8b287235331b36d1362501d26da3d1f90395680775a15b022eb2e536752ae674827516e5dc84c8823c243ea2e357f99deeb64bb8bf1d6e7c8ddb25afb1e1164f5fbe4a6e07b85cd0fb0af7d219050196a2a99945a5fbaad238b7b059b71bcd29d70707d98eccc9e938f6022eb5e3c260c21431613a9530fecb3e2e3b834186ad5021311478cf58fd9a2e4465f8bd6265b097351d2743133c06a69cdee064625cf952ae44516749fad217a84d51f280a72836128b1ffcdffb76984b974e6cf5ee87592b361370a35fc2a5d0b3f559ba6c13d7c0a85982541a1ae093fc9641afa3d6913f09eb90f5a6c5d01123d04f71ac8a240284bf68e7f0cb2f8936b2b0b45ebeeb8295cc59169f11f8b6c02cc7f89566c6557776887e6865e763be496a062f31419cef3342d6dd96a2a9bba915e5f55bddb68bccb2f574e9d99125a9737e4f8d46534d0b0429db9d48b444d38b6415f851802d3dd55ced8330578b91f88ef7653e754e2add5af5e817a090e5b9db633c463ea81eee52d042f858698adc69408061d8d79433cdc5f6b33a3889a526bf752f4541145497af329f6cd6c84501a88b6e649c90f59d0e08d9ab9d34ee16b1d58abf8160efe58026cf232df61953614da6a48cb399bf83cc0b6fd1425d19873ef2d31c569901c3291ddbb1c393f9b6a52530fe10ca646abd564b9c9f03bf5d85dfef39eb3524206fe6e6559d47038af6bf500c41cc00ad9d83d3801135d491c5d0837fe0eea8c06eb8fddfc8d38f5235386eac4697e8d04704259aea675f26cfc43bb171dab150a5b978140e3c6245739713c0ec507aac94362a7f8151561501758744b55895192d6549c54fee057ea0feab91d9a5facc2a001554e31bc87fa52d184223fb2552fde4b520d49b1579dc680fb8738f532e3ebda944b0e6f694a5c08964f3e710cf498040a220aa9289d774e7aa01db573b44495b5e71fa2438b863201e6d797ca9b062c5b03a69bd524bb6278d0ce94d0e3b17dc1b007e536974acf594b23a98dbf062f0e5a101328aa2cf2bd4bd4f8c3d26392f639ca15fdfefe19060c0a941e7c7b331e4a31ca11bb283896cffe6c421504aa20549fb320a8fc21f7a721bbe316edcc2a2a0b09d520cdac948411f97d4718da179f50870e1cb1e2cba1843109c091ddeb9ad23252f9f7a9b53f22440a70aae79e6a8d14fec2a970a40ccb2686f7802788947a796c198cdc7977bca0f380fdd6ef84c134c9482dc17ab05da628a1067882b3fe9fe8c47ef8a087dbfb7968258214bcae972b5ffe75e1087a7c7af60fea1dc27fd4fb2cb3a0912987021fe06f74498f4c1b8fe84ac0d758966334cd75aefd266a777f4fabb32dc39389fa7b29b38a00c0921e670ad0f9a188ed2926f2e8518feaee390478119b8543a84b22932b33385c0ba143cf1ce1e441a7f3a215a7fcbf6a7470c5b1ccff9cc0fea2d1b3efea1bbb3577a542ae2b0255b892182ad0f441d919f4bed56288ef17131969c1f6cd4a6617eebc7740b0b429c5c7192b6360ed2908a1d7270f32ed9c65dd9c3cff61d93041f63118251224ebcd507fac1c96aa70530c117fa8e7a878ef29f9c58bce992f2f7d3e27d8016553aac653511a2483775066c8d06ddb277c74f32036123fc30b1ac4b363e286c78be3a6dfb3acfa6fd3365aea3b4baa6f0755751593685c0b566bf290428b4dfecaea7c8528384d83e7d1f32cdf8775b06ff83635a6a7cc4ff5bbb414886ab09a0e0f66ebe9f6b6fe1aeb8582aaea2a53225c681a649c3fe81aac74ba5e8204b78a6c2db7e87832af5871cb4c530c9c23843c64c5b7eb0d0dd908cb4c061ae05da2541dd20bc61a921261c6944007c8332b17f3e6ea6cd409dbc84274a1e9da0a2e577853fd39fc730769dee23376cec04998d78eca88e9a8c5cf6b46a145248602f07d763b1575582936ae687457368d5196ac793bfc339341611da9376f6756810ba55d7a55221033138807fbf7850cf0fe73326d37a7174246bc908e61a6c29363cd4d9c90b90663f1760825f8538607b31967e556d0e94c95e802f6646acf90bb32ef7ce88cda84ae33060d436258a409424d59ff790ef3ad1c8a3aa67713a89f0df3245406d000c97dca75a093885af12f57135dae14d0471b0aa5e301d0459d00946a1329b0c869c193380501a56d87094d63caccba5c228f65096d66a8f387a2e131d6fdc7d4c017b20a4c79c43c63a76bfbea58ac2532b73e31a0d417824765aaea25444263879bbaf48e38ed9720799a245349fef8437aabe5d97904c5ea5c06aab734f82a63ab29499884deb4f0112e35af7abd474e93798872e010ac2351aadc8b2acb37a5295eb1b71b450d1f9f3810488427a067700c8814fa7281c366709d700f8f29e379b9b04264591a92783ad86c24c2b8e18f1986f1d29e47d16a68b4c16d36920ed6d8f14906f1eff1bb9d8ef43572b1d44674b66d9bf38c38d90fc441ad4a979d37fc35b3041991b2a3200be55adee830dccb55e350c3e125f0b60ad139dcf40b6b2aa75caed6da70ce5d1042426bbd237186e9e86f49e99d4225547c28ba705e6f933a9645e4fbecdefebefbe5d7ff4fb21f9bd642ee5812a7e66a977fffd1a24b5855f80cbf31b1106af611c9367fd6a30a05531b3f92546e210596d2bfbc2e7224218a8bb39ac25381bac4adffef47b0e7b137417dac779fb7e350092fe506050a43dab17565fd3b52715723a75acdbb52ecca690c60cd440d3e3e12790bb7aa3dca00d94de6aa639d81c1430451ac0fc8176e6f55ffb13109b8c6bc701e508660120adb0443ccaa0b0e841046ed4fb759738b31fb6004f9a11659035fb7e3933745fc92cf6a52fe445afb1b9bec0cb1838f92b71bc290db3a7cb831feb4f016c72d9f28fcd60fceb784cebc9e5d7d79bf028b822e830c3a47ecff086d433dfa361561f89a311324fc455425ca20abc6410a1788eec58860697bc06a9074d009bf6a1a137ddbba1953883f83f1b3cc83994f11d9fdb5f4682de8d9878a10ab78cef22b516f6b269e74d8ef462a1920ca43ed2a5e41314475ee016cf07a4d9aa6c9390328abf505caa9f7fa5b946d8e957505806f70674888163c46f974cd4572f7c9f1067b94b26f03668fa16a2640ed87a3d99886ff5948ce9f887b741796bdd2127204c6fa4b942cc4675f70747e0c9d7d4be27d8f46d664edf8b5bd788fa0d424b865d1471f9a7f3c3f99dbbf50537b4241998b9feec9ad5542a28483fe6c95fa427ae073ff0d8fc8c78b8006db95939f917b43566e93dac3e302abfb3ccf526fe3dc6678ae56751af5e566518cb3de3b885e8d6d70d172fb36733af62767e7d119bba63f275880a3142d94f32482868d08fe90c240433ff100d8d4951c99fe7782387d3bf4f9c6ab855f6046d583c6108b41bd800b709b67cf0649c6b3d07546459926cc968963861dc857e6fd6a5f35ad958e03e1515bbc50024b70efa4d6a9432a494c2e8bfc06986ab56685f04f64c76ecf37fa3ee11c363a178ea534e190f597c6906de5c0f11ceeb4df3bcbfcfb20f65c423624de6d6cda41a00084aeef6983763931050632c7d5a2e89a31fc03a4b23078495452c9243136eb1943e4a5be0dfc90986cee848059b99c9ba67d006f8a01b4b796cddd21c9411dfa4b6170fb2348f90ccc7d943c2913093b11799d628222de1aeb43f570c5ddb729b8fbdf83c7dd3e89b8cb12b56d9b07072dcd94a029e3ba2a1c02c1d00c15e9799e1d669165a1dccdb83903ea435460fb0940043c759c48ef91194ea7b16adb5cf6bb143edb0f1e33c92c78bcb82c491e73ea28a2c365f7ba5228ea2d003a3ee8ffe835d17e773a65812a14b84441dfafbe09c02f92e7dd1ebe19cf0caa2f160d1abe626bb723730782591026e8e57077d61d51c92ce4746a1e7ad7ece6c286d1201b5f9dddd5485d8a6ccdd735a6f6353378de061f8c2db6889305668b30ee620fc411bb0ae6056098bf2f823d75d9cd93fa2a98d1fcca349baa1b8f9a030f82ebcb0da77c050131375a0bfa960e2c85194469954049b148f0412c2992fd29c9be37e08d6920e91000136a16ec6738c9e3621152a56d378bcd24801dd78f57390a2296dad3ea0abe025074ed085617b6744f52e3cf8920603dcf00204200cb9f27aa5a3a25fcb65cc022873232ae8e2c0e61adbe4771dd86d9bd152b53133934c45dbef0789e17b9a11f205da4809aa03afe729abcd7c0cce40a249d29dd3d90408e7208a052bf08f1511e6e0e1a6d2b223a935eb0ef171c4504b5204744f44458ef32f8238223c174e01600c10a9b5b387cfa0bb1ce3cb471f29294e42d86b6727b7e541e2c87741dd1296d4fc657be9ff2c34acd771eb7bf76c69a66a9c0c5001afd320e7108f8dfffd2f5f70611b3a7518ca45722fc39e18505be2edcc4e5ba1fd10a976f772b4578d17a98fca5c1dc86d7934589f32178351750df27cc5b6b31157340598287a99859a0a3d2c4493d11c7684c45ed3f051340e3cc19ba8e8c419953ad5025d127ca1061f0059cecd41bd3ae4887db8961ac248d1d8a2298504edbb326ec94c9dc8c24446539303275d65affefe0fdab56d1609bda3ec43b92a313d02340a0a25f1131e7b5c0c34373fac7c0c33b8f919bd5a0c076829e5a49e4e137d404f699b5085aafb0dcf3ba2c48a657543a43af0b2c46a81b2079539f50da24dd3ee10f002b63e32d4ad297f2cf7830c99a51a8483b97fadae0b36e0d2af28c716a0f1340e9cc007bfd6bd96c769325047630677d0b633c6889fc1fb5f6c5929aead3c694fcb82a102a13142ed4ec4915004f033b84be070ef6d5a324778cb67d24d998837818fa6f807a00388e28c42614806043156b6f58d3cb7de1d33dcadffac6c0c1c52c5e8b4d3abce4b492970e4792014963e8acf76e0c385cc7ae67bd6d99f44691b6bd5b29bef3a3b6f1631b5a1beba1b512b33978af6c7b1524d566f043425b1e847fb2538a28ad3b8bfbbc300a4cbd817ce5cc4a631654c8d8f250e252f8df847ddfae1ae36c5323be2070a5e773d231ab7a5e632d3f7b241277a972d6737d2e78cd4f282876b48c3a6368cdd4b03eb3dc6b7aa11b5dbba6d470ea20e4bec834b3b859c77d16361abfaa490aeb2ce20d220eca6176a2d03cafc252eede1449a29c96ff667aa3dd3afb3b60cea11ed6aef075f4538a0d86e6f98771db81b5c6438a7ca0f5e0f6d8cd3f25df35cbe812491a8a451925e16a0cf5593c188a019c4b49e7fcd4afb2497a811771590496004ad3cc2b3227b0ae9c211f1998b550ce779e8ce82b065da3329a8c214e247883b993aa7f27722375a86348c407c718598944641c6766ac625c7f6e420b7a4a93bdadc6c4edc5cdd2442adae21a93c467c78ff6cadaf2910aa464c07e3daf3b72c8b5d553ef3ef45bc9e72053d4f100012f1e9b035794c360133332b4605079fa0c2ec9d1bb9b1af4389ce9445d02ea74ab2e6c4b819ec8bb4e1b485f86d7c437c8a5f2279a9bcf76b5e301d7974ac081e20f5a281ffafa58057fc08ceb5c67f33953982d4061bd9ba086bda12140abacd66e77c15bb49855e98eb384a62c571daa561eead389553cfc3cda2bc4b3f22561cc6b21a6cf87a72c3e3289ec1c51726b2818d8c977862e906f53f13604a4fe3c3ddf5e3fe6e6ee0ecb39d81c0d90cf47fea40bcf764192772123588f9efaa4c6f6be7d793c8e67d727f99d5fb8169df5ab4aebdb9ec0c0db3eca9381a449215ecefbd19aaf47f6ea2d20db9c4545e11360a944a4ad119ca523c3f340f83e6f9b2eb54db2f35633f82159e9b6a672bf692aa487e0a1caff9b52e4d04dad57d2c3b53fb813b32430d862ad40d47be4bdec2be0161d408e77010fcc7ef78c201e46118c12991a2595de231af1a4d28b4aa1f00b7a102d785a8be02d5e729d9b6f4fafa66e07b82ce8b04e42cfe5134d6f82fb48e8494610628c7d76d8ea44f5be72e38149f1251bea74e31b1e34431bf38ed7990df0fb3f6c9676f49f1cd5868718e5075b46b926e7c360c16964592aea9935370b31475b5c429192f8b5f0036f13d3c5e9be1a699f2896fa8c5d6f1b0dc12f35a3c267f3f291e20d86aabd0068df32e132ec2398777a328c6926a9dab7870cc6dba5e77e7fc7a1f8a7785865e042be82928c0d10aea15c72f42375eba510a3655ce6d6ef6568d708035da6a029ee334c48175dab03a7bbefa1be4da63b1d2cb57dd1e208374821898bf221813a59f2a4f243dcb1a41f707f7647918b4c7147b54ae113fa8f405f7a4f15522f2f17757afcee1c372d42fe6a255559588602574254187c9488650c5a6f7ab223960bc54a7637d6d8bd729afb5d86774945cc20381d20fb4ad7e82f7b24bbb96e55403fd27ab08dac1d098fe4eed86ecdd9c34dc175479bfbe93ede912df118421423aa7da77f4373379246b2e699e0c557ad135a6697fa2044c65edbbba25f7daaf82e883848687850167c8de15c209afab9a1bb40cc4fa5b99d0ba94762239e01119caf817e110b6c9ed9c98cb433b0ca4fe7bc69709d4d8d0112fb5143894ee92cb732a36438d0895c1a657bffe7fd3592f941d685d93b2e27215e38ccd659d4c8bc1e1101ee14d925eb79dadc6e3f1b2924cd2bcebcd9178f16f488b01f563f073046f190411aa80e61a3bdc962546711fe0e9b41ac2850fac6e7c3a7a09b8ca305b9acfb987e4c1248b5b3979b82402c29ab2afa53a4db28f20582af7e154da3c3b95fc03b233f4b4ffecce4942d1e8ae395454075e57f5580acee44007c0e1522cb2f7f90f92aac4597a308e8b4b6e0efeae9b822f6bf5e5c00d2e40a948b697902687963b8ec0426684a839582cb0b96042c8194fcf6dc2250256ed050ee2b8e6da420a4c04a64d352ddbd51ece4a82860248689178100f6e9cf9b7e3f00d2432b0852e8392675f7e8b01b2b1a1808a8216b17a64293a1c1d0c158d7238ad243a3d6432024c4ae512bf04148a3085e81a95512275c7b81a94a982e4e942f90b97e12e6265c24185d7195603e13a55bcae45945b0f55c70ba1b25cfb676152a905f09026301ea8b4bfadc52bd9eb73dbd79b331fc4582cd257e810bab5d6de3a69fd22cf80f81d1b8c0e02db709bf1d363e2900ccecda465f083507905dc781610e60d12af66a5e628fff57a36386e73297880500c7e05a7bccfe970052fe1211a00b4cb53d00e675b03b2ef6e25505c5908911e07a2037337f03bcb61dc0e30590465145671b00a49e22e5b3e550fd7412694c4263387df5d1dc9d799b527a076ae4fc670006a43971389492fa7ba8aa4707a6c6f0a88f7ce2ca66fc572f40d47826e36c7f9a12b4c34a968fd80079196d80165c7ee925e3a7ef278ffc0bf193a3efbc34b5420fd5c68b883f8e61746e96d2a99fd0a4c28f4e514631c1d4fa3e8bf5e356e1ef3ac8ba990b6e241a75e6c412bcb9b861dd9db8c836d69a5d855e7374ac2979cb1e17570036049faf59b6bd0c0da350ff1a1822bd98d45bc67537413ba15f0f77ab8ba7f40f9f3f7ae35084a728d020604e0c3f7233f50590e25a70670a0f71f6b831ed71325a95ac40df9b47424df50ac37f9a9b4eaf3941b03b2768ce80933bb474dfa08f24a9701a95452055f4d204b98b1d532daa490b4488d9d9575b0552fefb0f4d4e84d15f31e662e2a94046d5e7c5a6e66995258d3a6a0382f5bc6dfa6efb12a2f62a408c1869a866175a91784b375bbbbc4b0775fb2b34831ced388f724827999dddb5aa390401f79de96c6b3869c7ed2d27a387e98b0487fea8e931da2dd3ad3e7b4a8e1f7282507221d83a039f79e7250cf9407b2d1d79e3e5140260e5b04f214d485d542a2fa885a0a8a20768198e0b93f3848523e9f7d8564f7b16b2d4f7469467cfe02e230b43c721e4c5bd771bd65ad9629b1abcea5814c7be5b8fb317758ff4e2bf3928b1b676aeac4e006c9526ffb084eb182bc667d304e110f3b53b48c61bfee40548af7f64ffba106302849c46f5878666f565ad2e96886d95c2807212e8ac3e22bbb92bd686cf4d922fa227bdb8548468f22c6af048453738658453dfd295062dc4c34b0c3f03c7623bbef8daa991cc3fd50dd8da17cb8bedc7ff159ffa8e60cbaf9fa71f86947d778ea8e12e2f8e104eac46c68fd5c5bbc6339e140cdf107792728e938c17f0973ff687a16f5c5118d7ac96c22dcda14f99f0a73381d7878eaf4353463671a0fde0bcf4e2b5090d6a22171d352008bddc5111227bdb6b2074e8ceda8b57a2e4ce40122c77606ff77d8bf7df45539735a54c705c63e8bc77e47557387555200175b1a06d5098df13ff2a8b8ae14b4908eed146e931436fc4bd32377048379545e7cc4e9ce670f7f5a4c69c89403547554e1213c6a69b9352d69bec44b31719c94b25fc1d72c10a6eb657e4a0ddd6c9059ce65116995575cea10855bcae7c6cd07a66dda32a1d4868d5d517a943645e3445acdad2928c423a420dba8827e5c2ca5f254d8ee00a205666c6220601036c2b95738a3c318049b8f5310910a7548cc99173426eaad76de409ba5cf5e086f2eed6fa3984e8fef31ecb833a268785ba38d38d1db0c363186f973227df7d5ae95b59a5b3f9e9256e36d814c9277e3c0c61bf249a88ed65c48a4bf853def5f2fcbd6e1cc97a0a934b795e23f652993610784ff7a5fcadd82f61776e41100fe792457637ae4f14e0c4b97001f01d3c6fccddec4494c2be46405f5c1112ef55ae969a7a9617ae3cddcf16aa9cb73901a6c5b3217704b8cfa3a7966367c8104984e358b4c57d4e4a9fe020fc70a499cd02d7e54efd3e85b476d20d91a523b3b591f9d811a1272cc423616fabd03f5f29a33eae8210a3163d29dd943942d9fe6868acd6e2860163a402b43afb4337792a1902348279a0aa8caae38eb6c5e01460ad00b3d267d797f658dbfc7b6f21ab03d29f349edd441cbed51d94ad1bb1133c6411c0cf2c2f79f24ebde0f1bfbeb421e75209f32f06f552314939974b9e2acc73a4306712559cbae60646d5fbf51db6506ef8b77043d6dcc1d7ea1858113099fe0a41790630bb4d67bb2b1990b758fa5657fcb495b821a2fcb443172f5eeecd65cdaef2fb38b809bb39724d06ce4f5bceef031fb56ad50897727498d8aa2d7bdd1da5d48af7fa31124a2f76e25d1ea909b06416f3c7a67efa547ca5abdef5fd4397d653fb0369073205921135b6048878fca96bbbcaab73643b7b135281992f213a0c6e80cfc2868cbb079f63e9b3f981daadb70ec6d35a9d3a87d08b580cc629842fdca6e24751c7cbf48c12e74c25811b59838488d7bd1ce4d5250994cbf406611532b6e02601b34c67fea7f220b719c9072dd7ee749cf36bf5cb4c25e086b42f1dacfc17df93a7eba19d6986e7b39408948f6b1e5fec293e044f476604bd7b621067f69c55d0b8d9a2060e92ddb3f1cde230d9ec60eff451c13ca40f5a95dfd1d893997c807a78d49f7474e9fb94c2df14a895c1f8362a38e2ecb23c5d9cf041ba855e735240b0ad91380bf6014ec4dd48f2ec3d96e7b6107d5bc238285de4c832230733c6f0dd9b9be2e7cd498f6162f230230b37fbd63114cfaae37087d53f5c50ec7705efec42fd056a9d3027f5f4b889f076b5616ca0354ed3a1ca9d9c75b0344dcc17ac5ecb0b1c94226d6ff6a8d90ede4ea1209979ae13de52e842d8136639c5d7b89589b4da9a27aa17828feeee3d8e3e2fa79a187d040da9020d86c7db8c1bb1586fd49449f0c4cf0f75ba3be4881b13ceb06b09fdab004377e326a5c24ea9ece14e29b7acd6b74fa9f319e66c7de08aadeb63e33a9bb94d981466c7dcd7b0d183012dd37cf295d6a350ed2294bdf0b2d91185fa44931c63212e00b262a9a58397bc8f7ed323c756941a16b2e4bbf0e445a0474d4b980a68f6af19a0a147ee82098989b5ef4698b4bfe4b045117f10733ba5944c4ab16200ba130489e3bd61ef55ac0f69938646ad40c088367fc3b1f928cd5620a401b8852364f4379de26e20d68c1c26e9bac9ab8361f01078e21fb01cae48e0338c3863313e0297b8a5c424db5ac36ce4d50b7477d6129938bcc16f97ae6bb855272e880c8bce9b2533bae4412b99c164bcc89b504289384ac7250ad5230df3fc1d927200d93c47d149160a11d7b719a7668e05c09719fb6d8628ee7e2c3565f68746b4bc79c688b309398f8c863a73d288acc8639bc7a3f279db521d0c59b860a7f5de4d6d46280bd31961d4bb461264a8a468b2b372708f5ccf09d5f3983f28b158121f9f477c91c25cc694f2848f6788ea1cda7787ee29413c98bb11237fbb59f068821f9286c74d9d3b2e6d165ac65ae4c8140b265b78d324f26706b7423875672c46c71c290e071a7f4ffc14ff0ddf3912cc37758a2251c75b3a3ce100945250aaa7ccf80557cbc431c3d108b9eed447d54b49b7d0ee3d84d3542075cb70ba37a7577da186c622433e30ce33b84e60425925473b61eb50b7228d46880d141e1d71c55f60cf0855fd2406c1a21279f9de74368650b9523a53539b6a356dfaffa331ce794a190bf8dbaf5dd77682cc26927a298fb703ea62136acab2961f5107bae75f1ed6e2e60ef55471f850f87af92d8f06db07dd7c6f4fbc017f6349327e77e8b50d909b966904126ccd12a624aeeb73bf859902da21b42fb010e3b33e786129c1d4244b6765580f096bb4e5b85426d6837989dd91ebb24ba88d4c7345515cc3783dd0dcd86b1528bc33b13e3852e4e938b4d011b3ed90779b571967e72230e62ee6545c7c84ca20860824d6f98de7ea59b8540bd425f913619bd472c6e119c997505e16abf99454e378e9bbefe3a8cf4c4cf6116bd6f1f770face06098c9c3c9cc75a99de75d73841d65cbfab5bc82c299c43b11b63b19ff1f63d410c8c010a2a7cfdac03ad8d9cb1b8f40b29c18b9c639b2cfc250e8e6d51f8e1df006cd731d88455d86fc577fe9ebe8b283dd2160ae0dd114a2d5e7a31b019a8afb3e8154e559521b5022e75fd1dc96aa1590b6bbda799f4fa506063d208b48dc5c7178632779b7a152c412372529bdbe834711b7b64cedf55ec3f41583ccb9c733c8b00f337fb5d6b7af0fa212e90b45c26ecba965da6ee8223faf877451e1a6a37f9db33657693ff93019c8405b53d500c52d18ac1ce613f986664385ba9aaa812fcbdcd526a6aceaf67daf745b2f480995e1a4027e6fc2209ee1a36a9a5cbb2c718ea1ea5424e73d8f6229305126a698305318132f342283638b51611e4897ad5d8cc4f1f41a415dd00211edd241465a803328cdabe99a9d2a62c386d5c560d1a47e69a358c3d36dcd42b4611a6aa61ec9991f26d5ca74a616955e951b16a0863271c0e1368c33dfe747d1235540b90790c4917dc553453f5d1b3da00e85e7e1f65bc9cb9ebfb7206165574c2df439d7c3be1f573acfbe41340588d8f373d00415eea2d6f81801b29c6887ef0fae21452426812ac1010862661f26510868da1c809b3284ec3c988c64a77cf836c2a2e60b5331b80fb4b7728831fbf5f9e858ab64200829075f9f051ca1b8f0be66abff0e34097e21ad909c1f27fed0723d406d35bbed6ac8a7f73e264add09e19316eb78a207e680c23d057f756c2185f071b75956128d0e70d8e9f08ca621c014b3b129646d557e7296905fa7f2b719f38cea06b40a939bb1802bac84b12ebe54e392c5534715a65d4bf77bce9a36cb80f4203a907d98de50887a8de2c7641d59410acb9555893e65f4d225008d67aeefac82a65c2f0f6f6e53f9e3c899d50d0080476094e0750efe9cc0f5d06240fa0f63fe915ab8000433146ad13895faf1ee55e22299cc4b48b8afeb3c2154c45411b02617679369c9efb27feb40547ce2345944f29ea8321a01d00af345260fc859171d5b756bea44b4220e669d0daab1916549ad2d69926a5a2dc2d1d13af9b1a3ddc0c4c9188709736b11cca35b050d2465076b51c24b331ebba67eae289153edd5727ec2d09a465a1f29a3f7167aa7be6c11b805118ab1babf60928eb1d00af7218f5f99ff47705972c3a13020c7c586527c0bb2bd3ef6b9b272ef8c8d795f6af311b9610f30b3066dc1ddc12ed2f5fc09cab3a805a3011256e5eccbb81f74ed34e367dfd6cea4641c47d838631b5b2ae7e1bc4bea8639ea45761ad81c87c3a8a4250ae03f0c8ebcd588af9c042c87e920c4dc21022a1e8300b221a6e4c19388ea37561dcfaca709b57d9d73f31ce1828b538808190bb1c5c673b0a7be92191abe6bb13477df24410abeee7d66c70e1124f210b270704144119b5a947fa4788e8d68a936a5c48a2f92c560023b0800197695d9a59367343ff2390fec71ed5ee73073d550ebf88be830696e3c2e9d982f9879b9b187e2829e1203ca6abc8bd7e7e111bcb778aa0af26b079c62976730b9dc7054d3b070c26c0dfd4d6201156de8592276ec9a87b9df18bff66a55765492843989bee72cda3da3073497962088491faa76202046322868cfa5918bda9c71b4b716d0852b76281ff094180f5b614629c9e0358c855704fe6984c731f6264330eec26d127be00236bb6ada9d961211527d6108caac71c6ce9c7e417606447dfa18f56f932c7345af5aeb695f975ebac74fa48206b5c4431d8b8a951c04baec93b4fdad66797f2864fb61bd84828605def408be2dd329be15bc65bd076afc1964e7a97db1dce304a9b15735ae4fe1a39d07ef7ae6b6f43523da90e01c9faf66d1464d090127b3e44d5b3a1ebe6aeb5b538cb3681a9409a0a5f522fd05151a9b31ab55b166292eff1450814aff3d28b88b4507193172496c6b3c2837fe68add7c31b1afe56bc1445b89db6b557cf3fd10d2264ac5f50524c4dd7d741a71cd212a1fee8e2c5cd88f3733e1ce27d8e8d7be479b52e3050d6e1f68785e8e0c61d268f145d607bc94c1ac4c1d140cd8722e9343a43ca1221644e2864439b92c01550a420748852249f1289c31c668e928b103acca0c6c4209c021634ddfae0e270a90316898a0050dbb2390202c07c0d8105705019264c854209e8383cfb8308bcca54204301e10658d5c0a0844a6fd79e8512c208c074e4bc1d90cbdcc0d8971725902ca0f236a21416156b495172c4258009ce64640126e8472c5e030aa86a5078707b260c9e18414dfe24895920c0b2e73a4ca061ca2946684c868491ce31212c4e04175529809e110328c28e5991c8a320445e305e0b05823a3fd99108998a1e38c0d269118d4725224a2d4e40492e7a60a0702c638206c060d97cb225025216ca06921a4140fd55e4e32b07b00cc420859284c9ef63241853086ce906b0f3cba00973141190c7d25c4a21966888da15704383a46ae79b4109ae8710e8244942a4c812c6f9219cf5ce9521813e182311e202531610a65140e0304e2ad7c8c88280a81076258b11b10e5c9e424346f44d0805009e2e021311654e68a2061121c19ed0711b1a084108fe218069622e8245a8608b2089b41e30c035e1158084c848588b990f87bdcc960ef01eb101889cb036dd307eca3f08f94a6e0731debdb4b092b0fdbbec1a3acfa6fb7508362d1b2698d0cc792235a330e7b16e19b15835b9d88b41a646f5d98f66cd5ae65c3168948201096e009b1cad483904d80be7f51abffe549b2c5b2a49de614b5eece5ef07069fbe59f65f2a27268a788b1914ee80ad655571e2a3df5a878cc5db716330ea29edd71bb088238ae4aaa04ad64b4ee060076bf46c5016cd6f40708d7d141a7d2ec6d65a44b5a1b5c3d9d797a4e7beb06bf3e0c36a46cb544f1649f8c629f102e617355167ca16e230a0654ea17cbd476af62c35426d53061c31c959f198447011b7558b0ed675b921b4872619040db4190ed67bdba483939e4ca8a6ef6a7cc5459f40f87abe0e22517ea5d127a83db150a9fe7f50c8fadf2bacf78f68c67747fb51bbe9c10efd2111eaded49dc065d7f74c476e2ae0a89e390150cccd8747e95603e1829332b12538644272d7b51d064a62dfa0ab542f806520143f4c5308f02befa7fcc16dc9827fc1ac5f27dafdb5731f0e6d18aa76d99eb3b03c7e9c21545eb1b11fd611fc34c0321986eea13b06e61ddc4775daabd05f04ca4623324b31f984d31885d7d55e3c6ada7fa01597f7a57206fb77cfdcdd1ac1a060623554761e57e307b16356b9f5a64bdf5cc449e533a7bdad85de86d46e31e3afb1f139c1ab3f77c95bcaf1aa5f547c48e8c6d424917888656420f19de08067bbba657c6b7fe10cfd55682b9dfed9cc02cef9a43cb5af2e0e7d903b800d7fb0bfbdba792032240d6bd464f292b845add94406efb5c7e61713007f2884b27405480260df2a9a4d92376937e43a75c702ddeb5124efbcfe2fd4f187eb4ecf64521f0da1efada56a4057b9072747ac430247251f929e1a4d9cda529bd4f55fd667e29c83689785445a90a4a080e53a7c763044aa1d09dd8e680a88916ac056c9cd85e77ebd4f09b053fde5fa0bb0aaab839d1708c137359b0b8b1ca779af913754bfb0be7e4234b01f2fe06c7d9f65c6cf8003f4e71de1eae79af51f070fd5424511e10d0d362c21b59f7cfe2cf1671789cd79b6c5f4d98eb6698b21b7c1d6d9af3f38d5ea14183423e272dd3e900e668727e62d6493411a9ffa8b0882edfcf6cfc3c68750236641c04ad4fb1e6888f5b37d694e7309b8ddfdcbcce087fb42b2dc14acbd987e836a37788931967d4ce1d2e60b617273f840dcfac78b7919dead26baf8a46c1050daaa9762aa5896fdf0eb8ba1b55505dc3b4f8a1d39781b1a7b85242382423b6b9d0268dc0620ee377e34c79e675209c565ccad3a2956f904fbffaaf8dc686041b54f8a833590c9c282d9e89bc35ec5fa9ac73a1076d861c8fed13c0a3c77a27daa554561a9d9c22e970c4f8b10553a0bc957dc2ae7007438ee9edd65cc588e3f789b9f5974593635b4011c75c864f890df00227940cccb38286ecf62f3a90a221feea52c0e6829999bf2b6a0388ee53e4ccc10ca12784dc98c33c656ac8b54ce7e2ffde8106dbfe60e4ef37c2fc5ed4061a7531638b18c1b8267c6b359ee6461883e0aa193423c3c428a1a09a6a864963e51e748d565be92a08c3cc3164936eb029569abd6f9fe126da879772d17e90f72f1b9f8170850a98a3d4c789e49433445b59939abed62c865dc69b08f9ac7e4826ad001b379c8a2b7e4b84f6f88cd2d97e381d1082b40abb24b8b4214706b7d227d123aa0556ecfdd2adc380edf2e137374bccb7ecd532a8a61c0c31e1d24ba32299139e67b2d2efd164931ea7c80b628efa95c66bf0b461fe40a5437f4fbe7c71528a86a5ca21e68ade8485ae4df583e81de69f9b181e00c5ba716fe34ba083b7ffd58e10c0032ca463dc1b52782052b6181e9b8c2ab39e20d17977eacdd1167e96c4db0dfa11582bb5923db0b9f46e1e7ff1fd7bedaf01e592fbf531bfc4ff19715da26555b051eace9efff17f2b7e65824640ded0e71aaace42f0583271636850c9caeef673977f06fca510b72e21a0746deffdc5fda7b0bf4463aa60a0d4baddffbbf4f7fd8be5b7fa53fe77ef07e87f0262254db3092096725be1f7431caa442216718a12fae2445341dd058cac27c3da215d125da1e31877b5d46fc0c8544241b0d0d812af24fa0af127c23ffdcf8d7ffc4c06256616102cb55677f8b9fffff77becafa1d725e5b5e1e7f73324d6a24d126bc078e54539a4dac734c624f850ec5a02eab3855a5e400cca9236f74393eaffde39dfb5c7be7ff742fe4c52dad950cac66ec06207391b1156cd62e3e20eaad44fcf9139742b5b09d0bac04eec32379a377934eb3b0992221f662050e6e52ec4123384c6900a05fed6bac9d68808adeca595dd3b94057b059c0534645c6738f04abfce27bdd6fab3866be8b5049d42e6936dd6c87482de100d2b4540af93d28a00dde9bf59818bde5097b9be0c9570d135a434d6f786680bbaf52ac5908d14439dd64ff7dcedb7c10e289472646e04cb0916905594950fb76487b8568e5c95b811ba026596139716b180e039755751ea145af974fa729363f58c74fad2e26e3f163a70d1850248be984fba8b6133e154c0114191a3d39f4f2f764f9dfed4a06ba88ba1d39f9b49a73f391574fa9323d2e94fdd44a73f6fb7df0a2234459a859b91e029fc23d3145183b266e182aea18ca4d3a718ffe8f4e965a2d3a7f5dbbafd6a72884d5d1a78fbc13681e9f42b357af1d2e8f42b065d43db0f9d7eb54d9d7eb53b3afd6a3fd8102eba866042b42ea994eac27e4caa96d2ad4b3a7d6be9dbdaedd7e1c045d7d0285fcc2a2774faaf1ef962730dbd96e8f4b796d2acd2e96f5b05378b25956e7f021cd429e4af44b2e0ad2d2d9146985d740deda0e813740d25e1ae21bdaaa02cf73a3fc5500a15f2d6b3fd603b6489aed2d3d356816a500db2b4881a5123aa9ebbf4281504462e63fd18637d03b729017fe266f8ac872a090e0417b94d0f6e8385719cc77ec4f2040b932e86630f2223203f600112323362c1f1440585a9681caf1019af1c19afd83072fe92b7da4d6603c5673f559ce8364355b8701e7bdce55885a98b21ddf5ad95c5d835d317eb9c6fbbcd0ebeed7bef9d57de9b15ed935abb51d0b2c0b9add2ace52440d20a549e806ae2c444e79220093146292052c2a3044fb656d61376b33629694c17ed51177997ba4b5211be37e94817edd7655210bdd6318988b576c338a9270988de8b73b6a2343535a7b595a24ebf267523b7390ea947a7bf9940cca31522a3959fd1ca10a3d14a0da395a0bdbbae1babac80852465ce49713344081e6e08f94031724313073d2051e68a1314c0cca07367112cb9c9163d4b6a82344bba1192d3c16a2ce8726c82872eaeb8b16793314a9110518a8c516e90618cf24287758071d6fa87314a0b526bcd712314aa283f1b8a980ed3196f475b6ed64c079f3dbc3ee5562208ba9438f561f285ddb66dd35aaf2628a72a529538727686cb9f5f976bf0f9f7bd08d060d8baddce7e806b99e36ec379a70b270dab05bbecd56abc9d960ceb5b20c389bd1a0663126766aff6499cfa3736b2b733254e7d2d71e6efdd5d9c3d3db5debbeb3aed4580ab2bef031edb736fdde9efb6ee3caf9635c825cedc9eeedb8b00abebbc0e58de07b9de4c8c77e7ed581a4efd5ead8232fc21d4b71a043dfff43018a382224c59a55e61cb155bd216bacb9fe980c2d4e508054a2f4097e393a42e9f10a711ed863a7d75fcdc13fdc8cecef049c3231aea9ec169149ec0df491767285fe07ff5fbd7865d77a22ed29721c7bed1169b7c21c2b412e34ebd9d57c7dbec0c17733f1a254efdb027d72eca1a707317b3ac01dbe3c760081b1864bfec3028bda15468c9969b35d3c1e7ef0ae6215e7fe399de036ebe15cc12c73a91e39323a3f149921c5dba40399929f179b375ab1b7e0ccad8867a8dc2817220ecc0adfb3810f610b6fc6228862b3aaee162d7b10b6ce5ccc11cfd62ac8bdf279083b3a061cf23d56e735cc7752ffe26e6116cf7a83df3b9daf0896f1f5217b307875c2875b26f56b85901ca4f134841927a74dce5d884501341374e5bea4e63f586fe8a02b6a7874e0ac8221d0af27ae3f54d29a593ca7095b73e9b623521c6af19c5363bacb8728277850501e098ff334c4c96373d1e0d8d4732dce05065476b5685c6cba626168341c50c16808d137775395289ea622c565dc0782a535e18504162055241c27d547c782a43f405548438155478dc0050c1b1aaa172c2962179810100a9cacb02a4265d0ca96895026988a3b0390289482c86c4420743ea794d715796554b4ac78f38d6117aa5030a6f4a10cd141f9794322c2959a444f1a4a040ca09b4142134527a7452685810854b2cca152f8a941ebc09e8d67b9b7e32bd17076e530417633a16fbb0e9084bc190cc90c4a505a018cae85ca53328282983c40e4d6ee48c4c3d7dc987251b967c2ced5852610905a52794c4281d292529196dd483fd302848802ee9077983345841f673dfdd5f435dd4e09e066bdb2f9cd9f46d05b0a2ef4bd3b98f86077a365ef59d3befebde7eba6fad35d55a6a1daeeceb705dacde4cda22a74b0d3af7751f2c96ef9538f46731703116d210cf8bd36fbaf56a61b703b04138304fe1326897d370d3be81a204ba0533e858884d69adac1aa3003dd390ce309b4f1736f386732169e0c4bce6974f6702f4ded5556bad157f72d78d3fdaebae55eb7bb7d6f77afbaba1837e9facb39ffb6af8649dd54baabf7befbdf7de9bf3b6dd9cb7cd82d5b7bf1a3464958ea7b5d6de2775f4273b06b285ecdcc69cf7c926456e28430415105392228c20c1df5c41e7bc2fcca1c7872548dc58d2c140b6f04009880c3d50fa21619841cf3e932d6e643833e859d7a8e1f33a521e40f4fa7c9f1c1d290ba02502e66340677873b6e936efcbf9687bdb0ff7be6967bfad6fdbdd8ed391f2453df2d3f32799fafd42e0f4825499be39244bf457998ee8f99b4bfd7e9b8d211fa2be395e5d78a03483bc91dd03a52012477631d6e9ec36d3859ce0bc994f71fdbc9ebf39d38000382c0690c18d010c10cef6aa5e8d80ae7eadfeb1fa94385383f931175dfd567d7f79abc8c046002b3000bbd5d55bae2f9a0a15b057b7d29fc48975b0cfdff8e57265dcadecd72ff7fd65fc89f5d3fd72b0d93c79a71f2ca8a7d39f19c1e76f295fa8d85171a3a4e7080b182c5e6a36c6579b5fa9add3abd53e7fc3f6626fc74a6badbc19e33c7396749bd163ecdfdf072ee8f6ad9d1267cbf36a1058ab8d9b35bbf1aa765877196bacb1c69ae5d5a8a73dacb1c61a6b8efb9a7dce669eb99f7d35ed8e9679c5ad404e67ac8312c12464879492c6332f6c3969b5dbc532af9a88c07b056ba0cc0ee6b455b66eb198bdfb27bdb7ced8acf56af656d975375faf4665c6b9d229f3b6b26fb1377f5bfcd476b1d502a5c4b1200c7ab7f9b5efdbbcdafd40ead4b0e17df73658bff2be7b1058abad66df8252e26858d7b9ab55ae9bdf071e08341aa739dfb118e75beb6ddfeeed6d2971c4dcf5d6ff8107c2f46a96e209ca40f0befb0f3c50d60ea45e6dceaa5e937d820390d2b1cd6f3f7fcd7edeacd9edaceadcd67dffee3a6f27f7fd9b9bd2e3b8957de94d501663bffddad6169c7d66f933faf6e2ec32fb5566c15a35c1cec8b4a502b5b26f7ad8010a5517f3a805cca88569aae94891a61b3acc6ed6fa90724713d06dfac11963a6334923539891a90bc63967a625bac4ab8bc3be197aaa011e827dfbc99e2ecee854c2a02e64f7bf1a3f5927bf7efcfd641dfcf2134de8f2b70f04daa3935f7f3e341d5cc387031dfc3f56277fa59eec821ee0971d04ae935fca17b218dc94befd08397d034560f520f9654fcff893df05f8fcd9bd8d5a26fb86879b2258a8b408d152849620222d38b4fc6479d2824296a3a42c44b2e010b2f494c547cc4b49969c988496b02831b19ae02f9965331b9cd5e5a845c90641b410512d3834be3707ce51312501c9720409efba1cb3f448c2575d8e4b54dd09bebb1c97a008591a82b30863305eb38207068f3d1311d35017c371941203da0f9596c4434dcad9c990ea6486fd492b5670829354d28e9f1b74700c4018d99124a54415123a784a1315d826558f2b8611fb706cc2d21405c9aeaf7ba599c50e28946aadb5d65aab67e445144bd412b572d52c275651563e9e115bb1ad74a9d717698ad09d0b771fc189e16cd05250e4a84fdd92ee5cb8fb084e0c678396b2d95b4384a6e8c6cd441843611e37099a22823aadfac6cd44180af3b849dc6d9be5c0a7e40b6ae607de74b0f68a6d0106663383371dec15db02bed6c2848a2c05436980fda015ac459682a101b84e293d096df4b33df4ab5354431fedfb66852a94a5cdad0da88bca124f65a1392f1e29dd8c7a7ddc53abad4577c8da3a45557f53da365affd62ebdfec55e07b376c1d21649f9e2d5e5cfcf53ab1b5b52b99de1f407a98bbcd7076131f9b46d00cf6f4f21e84fbd01eaaaec9bee22fd469875cbdb4695ac142e49b840e132c4a5884b0f2e44b8fc70098a12c3a5469452d454d451545214519451d40f734e4bfbb441541eb46a84ce82b6219b7475b55bced8264a940d5de458a260e026886ae1d5e50865c68a116ebb1ca1a87e404d413561ac6737a0a8f8807262058a09d492aabb1ca188f8214514283bac0c31e60622bde30a37248a12647420a182243ab474b7da2dc5909cd3c16aaad313d3939879648f4f34e42ea783d53c31f144172de1a22c92c2350c1efb255d0c9964e1986a831a385622c28db80cdcc98ce660f0d86fa95aca3574c0f3dbdbc775b9bb85d10de456e47cd24df7af7fc18c877841ce06b47941573444973f93eab5d65a6b4d62cbafb2e39db77ef1a5e4e9734a29a594524af9e442a47549ff6bcd3ba641f12f28e6482c35098ab42efffecc079f9f679fe9e0ffb0990c5cccbfd55aabf87c0aa3ca0b6ea0954a487bb3e496b4eaeddc0bdec7b38a7a3b34e73d31ae5e0dd37bfbb66dd6de5a31a5f97e3323bdb3f50a832c64b59bd32938a36f224f9741ebf42ba5a05da2a32d72c26ddb36318b3cdd2671d176da3971dc828a39731e8bfd8bbc639d9fe3db8be1b66da0c8d32fdd40f1feece1a098f3b34091afbcfc1d28867d8b3c3d7fd67546858b1309eee026083edfda5a6db6998aa6a3430573913e82dd04c1453ee3c1ea94255fc86e6712216da155e804d44c0d6e8bcce98fc6acd2e1be067f4da7b5ded5d6e7e7ef82729b3912e7853ae594534e39e5cc07a750bc7ef81d0693817fcdb1bf5932fbb2ed67f4d9e7f3cc23bbdc6cedd6db99f5ebd72cc892c922a03fff066d6830cfe83b60edf69a7bcf1363ead530bdb78bf9d66db3b67731dbadd6ebd5eaa5bd7b35daef3743c2671773f66ab3dfed65ed82614843f9336431b6b75fdbc09c19b5db459855b3aa9b60675c7a91ec7db3c20c6a7c22323e1d199f6818a17074d142d5d0c5fc64a68b21d40f282150445d9ea8c6718b129191d0b86568dcf2336e091a9dccc8aa2c2f04d1a0c265c8171d35627ee45002189238f3c24412c2e4a4a3c7081f0c90e244061b45ba38a1a05f68d220070f4ac2d070e46409090ec094420d1c4dd4a0c443228d3e3a404db95215146304224a91266a280569179a723861bbddf9374328a5b403408ca9d28108273b5cd14047452db4f0f484c61212500e1d0a5b1152ea9482193e7aa6981153c5043f4d33821c7184912135f0c8c1870e6da1532715f42961354e559cc62d2e1cfd604952e404238674ee8d2c4eb450456806269a0512d41dfb083fe1e85b9723548f99156b57985931b31202753b5c5f8ad6eb5ddd27d27a873bdce10e77b8c31d6ebd2b85eb4b91e25f3cb559d5f9bbfe05fb57ce9cc762ff6128e6745006e3a0eb5fff7a7d224f7fb52c78e941c0f5fcc5d7a70065d05e2f3086ebf9bb6842205708e472d1f0168a173b143b2c9041bbe045f021506bb56a7d22adb7dee5aa799905319a87a908802cd65d6f412cecae4ff1520528e674d7c39e220500ac01c52c030170c11528c640f17b0b14c3de7a1a500cbb489160a098d35bcf4131e7f27451068d46abf1eaa1780e8ab48e028548eb3268349e9e0b2ea8409e969b2078fd591524e4ddee5f9a64929352e8f373520a525b46c22481eeccaa59149f3f439a21cd90ea8f8ca914449759971b233c874f3cfc29d2448c41913645167dcf3979ea043d6003d72f4afcf639cd694e739ad39cd61f8b2e4aa3ce2ea1724aa26d97a3535111398486f1787431c64ac613e451091e7bc838168b7de8c4c3e52184530c3338b190c47197a3d38d294e15c5c33449e52e47a72096e9361de1dcbd4d45b6be3118b9e9869d85029bd3d95bd1608cb1f5bcef3e9facd36a75efd5f0c9d1613ddf39df7beb6765d1ae75a5bf2971365dd5c7dee65dfd605e573f97ce5ee7f2babd8275dbd32f1a4e77abfa77f38ff549590091b5b146e1c5d05d67afdb5f0eadded4af4b11424ea6bb0bce3aefbd77de7b7b79ef5d42094649369822304436ce7963bd31d658638d75877597b1c61a6bac3dac3d8d35d658639df7de2594f02369054cf8669df3de9bd39ce67cc7629c6fad77de7b639bf7de259400c3d01821257032944b18a5cd5aa4d1489131cc102063981e631817a6c6303e63981e282318a695cf94721c6363d2395b6268a5f44b17731703a577a93533d95a472798941083023145e01f3049c89829a3834c17324a6492c81c2123858c10999e314a6676d661aa88190c94314cca0c8d39c289126c8e9489a10c0e324a648ec80c9101aa32660aca9823148c211a334399a232426cad46e80e163ec10ac008b90246088c0e9b27605298aa02339582a932535241432cf5200606243118818309519ce4e0634b8f225234b64cbd3005e44b972f4c4ca1a0847f2923b5c3171e3a5a73be3f3f116615c7d56e3fd3db51d1b3cd1763232c7236a05d20699d765be9ee839110485814164d96b547390aa02e70c881bd3afc2c7538d8360eecd579d399de74b31e7456a1d0c897a02f42bef47c01927a92a2921aa594a48ca476983a32f5648ac8d4125348534f5f92be749122fac284ac807cc2e6cbd08cc6f4f1a1c9489fe72b5bbe62bbdd1b1c6c6818a586dcd0e9d7501a83f19a053840ca06211efb1c52333c0151c3941d53629a5c51929304103f6a38c2441729214a5f8e4c1dd1c0522c94c00b15135ebc78711ac2cb942d5e96f0a284948fc6f5cba0739fb4d405f714466fe8efaa014ecc6a4035b004e0310943285974fd494e7fdb66ef6575374156881d152120a59452eea72fd25ca0384394d564e791792f3b4f5fd15a4f5f7edce7ad56cf49706756f516d8adc04fdce206f37f22adf39f9fc8d327cc7a2950dcd577af4fa4f5577dfd6af51dffd737f9a3b83430ebbd58b582e247ebf25b5bbe4071f6d7af5616cf00e2a1f1f4ee69f7ad3e863928c626287e48038a391c0c14b38d7150fc097e078a39f461d4d7f420e0fad66f5f08aecfbf37b7b9cd6d6e7372833268dd25a59492beed9bdbdce636b7b99f423a0f642a3e7be6cf4fa019b47afe1eb7f7de7bd3642bd87bcf7f83b2d6af7ebf98338be21e286bbd6cfe8b83b2f9faee65ad15f71281fbae93751cc7fdeb9b4571a068413991e6388d66d12412d2a2ef011a9b3f33e8f5f3f97394267b81def39f4f29a59482b2d5bf9e9b45710eca562f6b7df7dcbf7e82b256f7da9955fdc57df7da3f857439d5651bdc11e5549f4266513cbbbe0fcc9ebff5cd9e3f048ab55e843dcdc7f8321fbd00e9b3b57a1a6fb57abd5eafd7ebb5fa16cdaf60afdf953bcd27f297ef7d22cc9dee6708ddcf97bce3e9997a5dd7d5b27cae058ab0e9e5858e3f7bc1d1f15b126670af4ff1d2eb00c5eb5dcf01f5dd755dd7753268afe72fd2b814ff62bd7e572bbf60ad9f21649e16edf579efbdf7deb217b8c3f1b85a2f9f93911bb0fa58ce9cc762ffab17c31528e67cb2fcdd6712f6cbefc02c67489cfbfdf91365d49fcecdaaf04c3c801f0a1082c88f0a3f445346324a8b0f132401244b11931722bcfc10ae40738883ea50057ac311501ca6406df8435fb3a3495fb3a311f014f033bc884b900f9fc297780f3cea072e58b8482161d3dff493935a1ada4d4ad967d039794ccd79959e9e261515120e7d429fd027b4714139fb8c6d6e3d55f7d9195e7fefd5ea37ff58b93fff467875114ce8e9fc8240439bed917edf12e12e4f4afb6b8f7ebf066df4a8dfa746d60cd5549d44fafd2984b66009514d9934e7fd095c0bcc23d6dff7bc0eae9ec01128aeded2b0ca9d6debbaa7f48915a8684a08cfce70fbf4cbc087811e695927d872c5a8bbd919aebd18b88b33ba2d0a96d0a894cdb5372d848a4803009000d316400018140a090422390e44792007ef0114800a688e3a583e34134724b1402c0aa4180a8220886218868118048290614e21c69c1200fad9138f19cbb323475208e04828b5663f5952b8a100aee13805d321793a83073122a9dece72f7a4ab62f2a468083d232e5d4df0d39ef37aa36d40f599055299fc9f413a2c5e6ef73054de43b3319f9c45bd803a44be29154c843c68bdf1ea728f1098b0080276b02439dcd9917f1ddf48002b8ab39d0c8b471bb217e4f7e000628807a473e207b838a276c32d707b880e5b8ba0c4ac40810816419d35d0a3e06d5211d141896320f28b7ce33f3b1a72fe28bb676fbd1fe87e6dcff8862030102101f5476440b410fefc93393c3d7fe208bae75712818e3cca4ec8d31d13a806b08950e688ad6dfbbb46b670d0cd23670f6f210571482cd342ca5dd2051ad6592ca49839418cbc28e60aa9d64996a9f57a5f26a18810e40b5e1d8bceb6880811c4079a331bc051a1c0430afe430f41c9041b922148f307fba59eb0f336d4d007ec1d730be6de4e26046dc8adc8b9e34f618106f8c1ac9d9f20dde0b441908cdca5bcd2a83973227cd6ceabf0392d61925b6d798364323407820008110ba3a12054c10419df260b854dfdf3280a7832a50c856da60690cbf037404d7c350489fa80b597b9c7166e86950064d3c7b1fcf04f3237b1a1661420840c64337fd4fb1f12a2fe7dd274fc5013f8324d2b56c05289f2993c9b656a4a48f43c6d8c7be324f15f0404250a5b38fa03fd81b45553a41b9e95b6b9b50fc48186079e98658e4bd8fc9e4ec98c7c2298e3c0dda842644a3b584fd0df28fbf840d8c9536d7fcb64a625f5401056422ec7eba59cffb708a844d41c980d9d9ade4a601a926142d0a13682cfe563deaf3cd1a990c12afed94ec881436b9787dcf80e8f9e0943cb7f989e6e91b3417b73f3a022c58376d3e6f79cd034c373fe0ad218207463804fb3ce1c660a8340457a1e7eef1a761a5323754ef126c1627610c2acf7e8f3cb30d72b6098601145368e84d735a1b7bc59d66ddffa7444da43c199788f50c726e063261eedfac89b7d922bee2fbb439299eada27050631b3bc4d043339bfc03a925cb26721528be1c5ecead4c30e5cff72415a50f5c6ef1522fbccd3e92e53995c1ee50ed08d73f7c4567095254b1dda41b1d3197576fa1ae1e90c1fea31cdd99d7ca5c1e054d79efc23137fbeef780c52df6427a6ae167d36ede8f0dd5add15297808462e00dd61bb13035e4bc30900e7258b9b92d45d04df876284c96b24a3590eea49c480b9945f0c576d1523a0321831a4b2fe38969a31e8d43b65f45a2a18d7335631b36e841fa74c488ff18b7a667c2b902360bcf7359cf708338127073d7afe3744d498ba038ec32558b96da2045fcca1e69258ecc0f16a67d9881a273a6d9996912758b3093dd45ce23f34143a70b230be82c218f47dbdde407f3e3b7139d4942b00b3b1a865213e60639d59f58019d9461d1371d79c7166a625855305a8f55d375080dc812513adbbe060c3434de6a23558494b0d6bd1a731997a980b6b849bceb38278aac7b9c507ffb4b029fca3c6a319c407cf0f2c1a78c2b27ee4158421db92378ba283226ec7cd5094c53c462312b7b67c61f24dc9ac0aaac1ee73152c55c8449e834168996148934447e52c8031b6a460f9f7b7c64f50a857afe2c2160bf22b2a01d8cfdfb18d27e89d60440b553e82805c17845372f7de82aa3443dac0689516e3c5d395044663025afbeb0ce805c25cc2286f4e5e3f45e171176bb4ac6f638220ff6747174ebcba450ecf612a31e65008c2268ca6eeb4b5bcbcd222e47021258c6a1ff2a640253d0805229060f20c159319680a11f5342380d6d79282e053d1628b05f31595006ce58fdf0329e89a26fff466e00e521174c1e582251991007a4420aaa17c63a0e814e2904f4de1b36fb95158744fc6872b26ebf82c34914c2e40e46f8244cbb63341103e566c1f4229a4e654e46f2944db43e01fdea49a56d1a82757005bf5b0e89b4b0bd8a06e80b8b651980bb21c485ca09c3d05ac83368da401d114894487de05e5b265b044e8c600c4dc3aa8b780cd6a005f8e236ab97d186a6de86024e8562b39505a2bc6892ce1d8c1153a62d247a67d0e736529ad73e641efb8c657d5b5f9f4af2af0a46103bdcc30601bef2927e5a018a2cd57d0fdf1765d4e24ccf1475d04c79a0c8ed733f30edf7c6fe9bc4960fa46f173d3697b51c70f57ba4beeedde3d23ec6def9020d476f28efa54359156f45a4382ec50f75e78cd3855fbad68b1c581792db168104b8301464699eff657740b7ab251e792beabd273b3b36b46238a25e57d2f371344a6aba74f6d62397e8fcdee367e050d705fc7d8e35129bd1cc4ae8704ad28af6d61483b3f5da2cb7a7f8a9ef082a6070c941e8bcfe37c757bbbef62ef7f4e85b4b5b34f5972208b37d4f7da294f18c618247997a59b5c799e4e0dc59de2f4ecdfb54f7cf3dbdb5a21e636bd04808d6c1f9d5429366b2f04b9bb48f751a17f2f5abde166ac553785f20ca8955654664840f3b42be718094ee37ab358452a00b9ab963ca38d97e22574f3d44fb14b502149be617d4599e2591fbf08c40dd663c2cdaf6b3fd994d918fac35d28ffdf24069b7c04de060530756a8366fa86e3d7ee6b27df3639712c01e9a099013316e3d2aa396d36319ec68f7281549dc59ccf060c086316d8109c676e4e16526945f394b55932e2ad367a50d813e1736d348266c31d81349f3220f764c3be0439b163cd378c290018567556798003153a94b42fae2e2b978478983426383a1a919f70231f034a4a9d6e1dfa2ad212341c81e8fa6d2709a633cf1ef91884af304e32625cd2884af17a0119a79dbe9fbd04c719cfb990aa7b634bf8ba210bd33966442dc16ca5c453fe983cef32e7fc755c69900819036c1b14fcd601d235f632b36015cced74fbf974155b0f48d6936b578c1a322709b06a104a33f0a5402a5052944a31a628eca8f2451e10c022754b97f6421019940fcb8571222087555de0b37d29bb105167cfa01edd01a72103b1f4e0542f8178285f1e25b44427ea1e05186cf8383fb9744a708875cf0f957d115be2b8ed80c8ac0bd3e70ad8c9ef8b3a5002d3a3e1aacfe485935960c5f9089b1d713a7c168b45c2574942c3594307fd1fb76c488b4ca6285add44d16b5393cf241a1d1f89453988ca4354812935a2ea4ea988b89156afe5b8c43776021871c570cb91d56cebd2c6634a3662ee3d72634189e2a0cd01cf0134cd0bfb71fc8cb6ee0e071d905df1f4924c308919d2000e821f56bcc137999d0595fe6e420c36d2f2dc2ca18c4554dfc63ac9c634336fb4ab0b2e90a53c9a0f13b3eee2687db4d1cfedf41ce86ef510c0a2072a1ccb129b04a065f0c75fa20c6c1831f6fb4fc842d7a938d36a4220304015ef93608bc4a5254dcd14c1a4151064194eaa96495cfe50d929e780094890d01ba842136fe1c7122678331554b144e6455e55a85a423a8cc4195bad62f1d4a032e37e2222c2cd87511d0d5434382b668d125529fcb45ab65a7217a3002687d9def4803bdf96a30b9ff5f3ca0b370981f19eb04a672205a0142c7ef1ca2920591c381e180bc66113c1b16cac5c631c9d096e0a2728ddf52a261293c9f93f98c594455f9462e903b924b9b1cf67816a6b5dc2d97e2da4b93e5bde4032439c9624ff84e9f15d24e88361fa6a12c801690454afe9ffd0b5f9481b85b49aca1c8347d212c3da109b888037bd1346e2ef99b9fb957e6890aa2e2475a6e3c5aa437b4e71e578cc7c1d503e1235c1c0a03d0e01022ac9483379420d63f6722768a2452b76df61fa9d7d2274f7024de47792973aa70c95d88e324ab180a312f0494a5ceeab0a8afd59d4f6075ebd75c5ffb19c2f0d61d6dd0d6b114a14f628241afd541139caa791d9180f4a9a3e65478662e690b72961f048f421c8d6ac4cc41afdb26367cc4ba11daad0fdb03da2af3e1d08fd66bd9e027be07412d83a4595df6d66420490fa38825abfee9692758a1a16cbe4309ad2be768a14b81ca5468ae27d84c2ff092e985a7aaaa7ab41434aef2e3ea5eccccd6934fc858aee82d8e721aff226c73f0dcd7e81332c279bbe04cd93cc2daaa6bfe55748bb09c42eafd8ab4eba18ac9e304a29f0d466d9ccdcffa2e15ff91052ef1672dc106d42c422407849af4d5ee54daeff1a9ae281372c45091f9561a2d4b16b178ffa35e18e065795596cf0e26ad955e9c6ffb68c21f53224e65aabdb68c53129811a0f7723eb2be4d5c1dfa0fad7977599558c0de3cef846aa1d79f1fad380f24ac41459ff3295aa9c66c73e491e023ee94cf51ab1bb319ed52fced6a6b3c0c8fabfcbf1e03aec94560a5c731a9f170ff677fa093f40c5511c5cda7fe431b6c69249fa53763b041d17dfeeac4c5802fc7619bac7dc031ff3e102513a154e07af9a9568be31a46d1c3630a279cecf44a7a980dceb6339527d919b9133d336e6ebe1675657bdba5b34e41e253647d14d88e91be54cb788cc2990e505e41edddb1d50c8a36263a46cca7c374520f5394e0745ed917b3df7455e151dd48fa77c4cee7508a21da13d60e10c814b9d6c07f86938d29bdce3237e9e32136f888f5add29345a4c83d9d987ca0952b985a146738703a151d13f3a96b87e6ab5b7cf7bb695c6e47adb3d2e292944fadd1565f8832da31f4d7b4fbb77c66772a3a06dd58cc8489b80cb9ca1f0e6a85de32678eeb0a1a0e6dee6298b53a0c5fcb16e14bedf96f2331506b04b5f56633c246f887c8865431376da73437fa998482c37d30457a4d0106cd8d26d9e4aa69e6f252d76ef018a52a536eb1dd6c0790d9778ee66eecb0a3c22b835edfd45dea68713d782ee9cd2ae8e5e07b16d2faebb2f8a3f5ec975a8955dc18da4e981c59a7b4af10aeb73863f67b28d61d5fc7a133d9cf4dc0990763a1417401e5bfbb0e70f28ef03d64e69f96eebe736622e2051e13f042cfce780949bc745416ef744aa6afc7ef626c54564c685ccf3acace98df7908178ab695d31b439ae1e451f59e1c3bd493c595d41c0fe44e62c28544456c2f8130a50e08cff7f9a81de209a0211388d4c3376b7acfca81e4007c481efb18a513d8f673cdb2fbedf630909138f16de83d5e13b0002c8c96f426fa019a64bd3841ad68b643c04c29aed144a5bcdd1d9c90f48fda9e5c1d9bdcb8289a82ef030c17ba7d5f8e3d424af84155b91c46f62f0161cfd93c217aab73528e05cc44f4f040ede276848edea5885cb00a82a04bda7723257279508e3c6ea352297f104ac209d919df651fb503b1893637bee664b28a7052fdff1989ed4933b053fbebb6620b683409099562e2f1b465a5de4ed590ce9e6999386bb72b16c879109a8b3dfb9333e775fe871dcf9f28ad8873a7ec891100dba4c0345a62237e1184ddc09f7de4be5ec3272131825a79436bcf3d3b1615a33bbc7f6b9a231c10f45195fbea6a74a9361b8f88f0d29862c2953599d34b398c3b307e624930742874bce231cc1081628882758d1f8604d917777d51b1f02c2107185e83b0c78d56abfba36159fad6b2402f6abdd799d5795f3d28ba5f06430a1b1a5a7b528e58f17b58aa0ecc8e46450837433b9cc5155590b11dabe44474ccd634237f5e7af6662a63f0721ceaa00dc9516acb8d2ce386624c2f7e95290865f83c370e4a4dcf71f11882084952f23d0fc2a8246b3fd511d88880a67fbb2b1a2ac9ff5a0949cdc483a02e4e82b0115a10e7ea05ae66bbfe003042093820e3b4fbe78995be078509c39e82495c218214e359b7fdf3ac0e2edd1d78e8261086556fcd380afdab8db7ab68b8d706ede3b63672b00279a8e587939fef523c34b2fa241f35b9333ffc3515298d275d4476c8af99c982a6b1f33e6df0800a2557fbad70880352529805ce17d1aee619e8525a80c3ce53083e941f086ad029a01fbb4ba1aff4ff08ca46a5742cb8163d9ff4580869cd82a02f9ba50ae2dc3582552ceb01eede385356b976a20988a6e411b8299efc7ac2d184c699f813b2fe6781718aa061dc3830aac3c23bdd63206bb0d6f4dbf173de488270958357ee15c42176937db759ad5658ef025dc16579a1ed395e6857e621ba867ad6f80baa07b2c142c07220ad20322c1d5d04130061410f84eea025c7249d55b31a4456278cfa0bfcd192000c894d486c751f5c5a38c3980a963a85e5caf8d8dda584e219cf24b3f4d1feb70e96d581b1ae76086c61f7cc318c60677b4edd3b6233ca7c9f44d9130fddb060a8455b4b02248d217be42bfe89acd88f45e901e3772e97b5306f67b86e23e08236743f72811724328209c830bef2c67e5a161670a896f077b0cc26c734d5f4c65079053a6b13f7f9af0d11a91526ede448e1bfb25ffb6c60f8939de66265cb63f35448b079c4265f73c67002e5f5155b5625c7e566f8b6cb85d64da337b7133d688cd90845dd74334b63f7e4324dbc58fb9fa5500ef8f960e25908cb6cf504087b1ef893160679366e91b6357614d06809ea679183ad6f4947ec7430dd18b34a546cacf2c9b8c38906557af198759cf8b4a1bedf49997e42aab2c6027998177583d1fa8e279862ee5f4ddd124c935e30cc04066b9a03f20035c090349a041f225c8072ba64ee94925698243dfe38c077cfceb5a8c7ac1c889a92c897d4c7818c5eb04ee31133fc1e63db0d63253fe1702c108fd4214844ea4ba81248532f80b1c053256daef44af66dd1277e7a300a23b6be8a3a075649f2a715599e42d1771ff01c3c16fc480554a27e91ed51d7d1c2b470130e978326ed26f7da0fbf1b44aa92c599dc238ecd10622f71cf2628545cabe26d11687225b7cd5ec5d5b7ab8e1103699528066550e21a72a0e610e00dfef6685b524c378fbc21972314b62041eea24dc8211920d68d72b1f098f050f1993350040df11fb6ebb701801d9fb6dd9bc1dcebfe45a07b2a3f9ed35adce57171621aa02169e8f3da25e283395b60911dbb7724c9857f90bb22f60d187cda10e4df5ff14784b95bfafcb88a05f25338f09aaa5a6e834e635b89c0b5b5329d93164289da2bd2bbe0add838a5c4c97d0c99dbd4d7a86123fbe270f97d29f547a94b4e5186b2009862d5a804ee64043c3d56d131dc6d2d183d5faa87d6f0d1ab3881b730015e48fc47c1eb25b1a6eaaae0de8d200d373d1950b891612f69920cb76e260431d860315403117666803051b296f04041a78ef61f7b8421110171810ab45b066fae473b46ea0b6a92b7143a8dc891b71a8116d3c6953ac1a89de2a16ee2de119c72f4d4a69d0feb12d9a190406024440d7c67c8b27e77d1ff06fe37fd93250586d5cf870a2a32eb0c027a39d009d06e00aa1360d7442b9681585ae8af75a73a94515761d02e299f81a10fcc36b815f621e11216d88098a164d4a43bcf825667dbe89424675cf97ed7c8a7ab9d19518fb6f4320c64c375a2b6c3477926f763620d7c84c87f6bf695d4c81c1f584354f3f0f54299a7fb82c5d248353ca170482c44706e0a18914e04b86d8951c28dbea3c69123b11b04843a3117ca8f147f5623d9b288e169e39f9efafeba2f7d503619dc0ff0f559069170870d6b0eb6cfa0d6dc28809bc0a81f3599853beacf7a6b34143662c3610fd2161f22a91d7092a5e49d3e2ed9c1d03d7d02ecb608fa81d65f24ed578330a1805c7c80f14061e3e073234d441615dc4832cb470f41923f90a7d59530918a906215f21a59329726cc8cb41ea05ebf6897b222f2f7ae60503bca169a1d03505a7b07f8b1685f5de001171fc4f693e33abe8d53b21e9c9396d81a2050ed739a3e9e00f9174686a614bac3a350792ab63dfecf676b40f771cfb0e8b7eb13ba7794ed1758fd2d49b2ca22e9a93974895903099c32e05e70d811a889a02ba4fc3cb071971f637a962392bb40930a9cfaf242668156331945c33938e03cdac91c6a0e28e6142454d65b8af32c2755499e1534696d122f58b3663063b068340fa313c8e28c617ab0c93c0da33de9417a0edec2345f455fee34fa6c45b243fc557afa5de3b18310e328883a7c80f51e232fb189bc40d4c2d32b618acc37a26c738d7542cfbdd3b2618e987a064ccfeb64bb7f15e2dabb03db08860caeeb55ae9603f15b4e9aa76402d141e858d11be458e5de24ba37b76f86c9ec4e12c3ece33139ab53e2e84e1077eb53ea22b6164fddff2a4b123c8ba8df9b74e16b4a884c147fac86228fb02d11373c6d55bca68a03c0602ec4ef318e6a5020a81edd79f7ad1b0513510a9173cbeb84244b12fa2fef81118eabf4a25f5b14bff60a35e4a6bfe337d3f20a8d13b6e0a5315849df2131c46da73458180ed84a056f3815aff04ba4e31d227f02fa3ce423902c86cce0f12b37d67548b47cd81258993f2e097fa407f6c7d07518754a9ebc60a25c0c55b88e44e32fe2fd9aff60b8f1fd3b7a960afa0415ee2e2f05aa9012f957a7330243c1206da88fe374074d2d16d241d4e15a5c3e82346f7e6b2ad1f19654d6474949ac23c44a365bda5a375c960050b36c8882c261e750d0faaf240aa448793139cee2ffce3140954b8580f9f1fcc1c34285dd47a7c853b34ed9661a4e8b69d871a363cee1a73c26c40a6fadb7b46d5926046e78ad6d6685294b3c315c57c524843c4603100f9d2cfd932e4e56eca0abfba5a04275b91bc14a2837ff1174a3e6c25c91a8dd6f2e1a1a8ba3b8385fb019054849a3ed1cfa8d950d020c9d362d63acf2d86e2075228549dde1829c5484771910de1cca1d10644c6ebbbbab5c1d28947b5e8b070cefce70140517bb663553f57f31dcf668e8ed18c035b9a3403e2fc8cde8270e4fad67fd4efa662ab6764715ee848d029d7f9d8e3cc82e44aa60b22912c632823331c50588322d8bc2c84353f8b8168511f0505312aa224c4c88808a5214ed98476d342fbb601ccb107534818fbfdff06dc68c68d7de5f81bd438fd8e1e9109bb4d02c6bdd9b09ea7d57e3fc531f5de90c6c51f45c5c053ef3933eb641ca6852d76ede0cb6374740c68bb4e924d980314174058253aed44136975870e9e47815ff8efe2c9c698d335b6f3e6bc6af620698807130d0bef7e285eac9a345b0d22f616427a92344837a5f36d1a4203f4e6a95b0f149d4734664d40b3bc8178ae6613d691cda2fea350f7aa3c47bda918a34dd6e0a0938053af8d4b8aaaa6d3dc5a5c72afe222dacc6093d61186e9a08a3e47cf1ed0944838157e26903b6cd875b0a8d46196e80c99c98683796379cdcece88b8b1b527d5fc7ce08d8d4cf04d9f388724d90a3b9651f0107ce328541ea756f5f8d485463015f01113240dd9a5fb76aa7b20c00eea57e5027431f0caf0441b0efe561f2f0295a8fc502283a163e7f9f89b1faa545d8331368e63b574ef9b34b8681a059d84cb229e71eb6d8724a62907004639d35499ee29500c92dc882264e7bc54de52550310017cc0471d0995495d1e304425a35c40bf438d8c4f100e33c68ac1c4b0313e3ba7b6126bcffcc05c0339afc8f57ea580d9771923466c84b6b9221009e3496abe951503cdd27617b5a5252ff812f28b0463d751278c76890f2d80e095423023972894b648628ebd0df769e0dd46bb2c2a05d9fff1bec729d385f75fc21e42b79083f48ff94c311b4e971eee241f860a880bde517712c2eb0db04e12076d9c57e072b18274516c5efce4a19fee57cd3df43c23a71be23d30314939531e06219f465dbde2239087b195e8289c281c2e1e6cf437bfb1d4d1f248db02677ded7a16204a897174ed65f139594f9749a7a5f9162a504dfe073caf2f539e00da60dde4cedc6e985d89b3fcb06efa17ca4310dfe73719fe4512c1b5bde03e5aa97b52a2d82ed77a896413270fd839ea77fb02291aaed554d507bb2a4a3defba3b6cc8346f95bd47071ae907254d46232f1c76e7cc0c8aa14e8617ae252b6932617c41113b38560eb8fdf0e903fc1f3bb2f6c75e1c9da71baf130ab5187dcc8454cd05ead9a4f348e5c07daa202365a4219edd464cea63190143766e165278aa907715005acbee9f807f5dcc28f78c09556586b499aeb29e4435c48ffd9d70910b951c6390869e64eb856c29d6aa844381bf3aa1f7e529ad11489bb26bd7f30d7b96cf6e78cd42abfd51afb579a5a7f6173ea94d864451415a50eb3b80ed261c1b851718e098d528f79c5ba3e714728dc232802c6826428fc2f67f677779d5f65fab7168581485dc2931c25e643a15a7044528982670c9a0ec1a64d8ba4e7139de2635c4e5fa6d9f93842b545637b50541d37fa5b8cd565098fafb2b8fc9d048378e492cfdacca02dd9dc8cbdff7fd0479a0bc4ba5bfbf723b335ef980a24ac8233c69623d16bdec0ed2788833e39c4a366990493a6c3cbef9c7797d0752f4f2d45b8450fed43c123d46f2491aa4511f028c6ada14c1bfd288097bf51b07270c206c250ca26d2da031f40d225e28ea8ea1dd22a655bfde3a145c32e6c9e7a6792a3552277b53e78e5001a127c5a354051a2eed6c89cd80f7f90fbb2ef9a944c664689459ee7f3303fea99001e03508724b2c9e381a8535b9f7a0c1c86d72e871ae3e29b8d7c60159740f779f44cf21d6c43e6fc4ff0252964232f21f3ed20658ccfd5b8f21b549ee1ab3dd4d93802be3137bdd470ae550a512e172087bc36af3df8059c76ce4d746b2c4e967df92a74316f6414241027010881dc5ff102a112a840f3525486094a4ac9b5f6acfb90167803aacedbaaed86264440c96c939808c60046800b1ff00461bb3894fa64858b52145c02a70f596f5ef7ef88008e199c5e3ec4593a87409ecc3ce2a10e77a04672047a5adc659b58428735c60e5ceb99e8c53a73c5c739dd0ff5cc590673c27f18299752342c9af5665c7bfbe96d081c2010335f02c92dd452cbcd24a8b8cc8c7fb94a37dc33dbe34c882bd581b9f1e7dfa1d66d282592d9abd4dd0387667dbdd24574d7195a0a513fb27e25c1737a63badb8b9f695935e1f277cc1f36cd87ac1cb2cf51110e4bb64f49f4aa33820b527ae0598f333e97e552496b6d3017b002936aada32f767029f926a51ab5a5d199d2213ebbc6101ca4c34b4558035240297ffdb2089cd19a883c0054d44077c7dc8591994fade51b63e6d609b7391f52de9f98c25119a97f0cffb90c1e63ee50f5a7f2343f2989da8e3f74498b63d7fb0bb01d9c4f2dc3c4089d5308d9dc9523a3cf1fb6b2b0c4aaf54877099a1f298e99347258a981fecfb76e91ed6da52af53facd84af2f065ccca7bc0126c7c56eccecdbc683c4adb178c2ee0c79a8b99778cccdf71aa19d099c141fd67c0fcd9dec72ca1b35b036e1324dc18b6b02eb717036eca75341f2c92c8fd9bf516b66059cd0c49c6bb0a679c944952a156b2c32a046714fd2021f39668d124043611aad8fce6725ba0a59fc2c5f4e5db883e4a90db641a919bc1f91bf31891c4a7d60da8b017b2ddf93b28fad247fd36d4879bf8c68b9c27d806fbcdcbfc93646b23126f52008e7f3ec77ebb41b5fafd608b981cbb31a170651f847b9aa9e4570db94898ebedb88111114261aa55641a9fe448d2120a1ad86cea0f724f6990987d57feb62302c920d38a303da07112efd8ec20c3ba65a1053b916087f9062c3075fa615ba9ba5725d37f7dba1878303dd8b60f0eb1f6854852dc6619e909a908e06daf93829e20aa482c549c6cbe8e822e3b8422b6b343a6299fd43eec4071367ef4eb425039d276847e982435f686b63a85f90eb848da8cde0713dad15915451efbd1b188ea6de10fc0465e65bf05afa29fc9536dfddc4e51def0116ab55206f0de0c188444b9d9b1bf3849c0cdf80e5f6dfd5f21766988171e33039eae219714b993fd2a1d0a70abadeecc6e3713833219f5c9318f111806eed2d046c07511fd13dcd13f371d9f23b33e2c3cabadae39b61a9ca45f5b4da1e4ce7ee12cca3e2e9b99fceb4680d5b11b5c08033251281b7158dfdfe3643cb2f366060afdd85d129fc7068883f8da162a14d87fc50000ba1a07943b1859faa0df7eaf5e1d36ea2ebead8b3204b7449b827e9fadcf3fc23e6d8e9c07c4ee28677ce667d4b64bf95d037c0248d846afa0ce90170a655b28ae79438e3060636e0589c337cf95be87b1dd8448dea50f0aeb9a74c0830e4bcb4441866160b58c428dbab1586c602de98de06a29ba05f32eed37401b6acd0f2940776ce28bca5c09276354bd773257aa8651a5c72e078166a6a01ab2cd428668abbc1e09fbcc1970aeafd1550410bcd040308d710ed06dcaaf8c764ffad5edcf7b350da15b0ea05558dd408512c5d51e2293fcbad41182d8c9cfa64df83ff59faec4a6c93786741094ea8aec04e949494c309fd81603bb42214018a947bbfb2c2f3315e69f7c65c7793c57267842dc1fa0dfd4986e2e4cb36a9174b7fe306185e1ddc9c90e1b03b54f10931b9588a97aa55ad87d1979c5e88a76c66e9763a66cb3af633426b447e59d282bb2d62e8f3ea4ee19eb5428caeac8d177095119b76d51eaa7f14ea295b01471f62089236bf7d31da69482659a9af88d64b52b265d76196eb17873ccf26a8597510260399c63cbe7bf56d668da3a77a310cde367380c52a5664f74de1b6a66d86f52adf5c6137c4ff496d1c2c521d5a7437b72db94ee11dd22b2f14118ee57d0f0f61a0debbb70c1d761aa31e1ff439b481079ce826dc7a9e99c45534ba7e0eabc564ccb8ac4f22f47acb9681a63d6fd197b3a966343ff732b1f59be18afcfeae36d6045cd789b2c98f9fc1617becb9f237170d3c900286a69c0cc8be9eda5c0ca535c93596e380bc4dc53865fdc0ec5f3672cf64845e6bdaa316be5fc4ca36b03b8f617aef86863b570156e37c098da5271792ca0eae8c04ac085911e1aab07aeca0c513e6bfe47fa7990059be81c05f632ded3b00200d7d70f07279893301bf90d87b0fe22dcca32b76cf64f706d2a81a53ebaea9e13b5f7b01090d2c69640d00a82b034edcf54c3681de82d070ab6cc1977635b6d699a574b4f103a839e2f90d63b6f69f25f6a383c67ca43f440347d8e65ed4bb7fb10a3569c1c42d9413a3b81f51ca94467949a23eab43cc19b52446b10acf41a69de994ea911b093c0f7bb88bac6908174c1672080ba58f0e236ffda256778999b7aa22560b384b49379aa4d681f27acfb8c138e13926c6ac9d9bfbba3bf7636540a41a478049601c5aacb9c9996e07c5793a8288f21a0951b86952b623721376658db49f96f8ae149994ad59712ece0a159a2a7e82634d54f3309481a69dad80b9d0d78de2faa023c307d850aa962dd873fa92830d704058c1b95cc9dd75e7b26b61afb8812a33854793164b0f48b225e96ad7c7b1754fd0e1c221dc4640e34881df7fad042a4d0e14f59b9ceef70d821a06bb9222cf96ab1eedbac8154e177be18ff68119cc11f53ee623375e04a41d7dddd2fbed7fb07a095b189f26bd1839381da0c7199d2d547f1d269d411871eceee945684000902bd3395a05b68d898bd43789694b5cf4bcdb2e000ee234d40d445aa23e703e5ac9d467f63ad6e5e8634d3e68cd60ab82f9e9c5ee61a309bcb9efd2fc2eba5ab18d281990e6f2371251438b82e24946f839f43fd646567e7d54d6e0a1b42d62ae36218f744a4c997fc235677c7365888bdcd8e03e5895e766232226c0e0e0a74b81f9d91d10d7e2c240b2da43cabd1a1a3b66a7530f6be0aa974b690e5a0ae3b0c8fb64bea2a3bcca7b7db43b407724e1b8aa403a3c5dea915ee523805459e537e274fb5bebbd3999aa63d4d6aad1b9dd6613c6e9ba7f8c4d07a463f13be128f55e5a31e500daa996e864ed4b3aedfec42e08313cfb9468195764e4b33759cc8af0aad7d1f116737a8278feb992827e5516ada32c4875cd88f30b57c454a35a69ad983c09bd00c25086cc19281160e517cf0d42d33a676e74cdd94d546f7c4eee9f6cb3d31e106787535f6b6d9dffd7e66027743c099006bfc9fcca79bb273a202be7cdcd92c1a60f7fcf7a118fdf481dc6cf888580c0f907d81935305e9307bd184203ea4129592d87ac8985410262ef9c4608d411bdc0844c05292679888ae79e936f813a499bf0ce65f54754d30d2cfbdd75d0c13da801d5419f80ecd99205ea61b6a2faf376c2c330a419a47dfce2ce3ec7f44b92dc6e3b0222010a2608d3f9547760216c7a0f3f93ae2bc690fd6ede99079d943ed7366a3b89b90775a3ea649bf88c5bd0fad30c48878381daa8fe5172228572fca3b21f73c848b8c928a7299c351050c675982670859919234c8fe9e8329ea113bfec13af6db0ef050ae099ac2d8b43d85519cdaae0664996a1c2a200f430efc48d34065e23659266242ec13c934af8a90370d637aabfb9b99973a9c87ac8f2642e48e833e341dc2b4d816ff5cbb54ab4ab4f11953db5ba68b1ac82dde5fb8379894b98cef0c042cd4f08014d9080413ff332bfa6d6e827ea36d1829f2802544b45e87d007744e5fae8c367644f638b34256b7a8a976582334ace912df39d347ac9005c4767474773054ec5a5464292df8c70ea6a3778ab3c80a0894141ae79bb6c549c92379950e903ec3995f7310455cac810e15d566264470a9a8c65083a6482848b808b78f05e0069ab43a47a63ad1828db0e21364e1d8d08295220bc29251da9f062642d6d992db09052b78edefbe4d53a0f3dcade771ac90d3c1dd3ac330952d350e9cba938a281824174112e7483ed0d7ff82b6656d318ad9e28d8e5a666c0e612c45eaf2863fe9c1eb0a21d14dde96c6c5bf7af052787d87a15980712943dc51c7f45acb3e75e77180a6ffa1eaba37b96d9a73415aaab86770d83dc89e3ceda0b3e39b74ba1da4e788ac56c83a3a7ebf4082a4b5b6b51e9b05378fbf8a9d08320ac1e08f10a6e9ea12052bf5e16e886c4123f0feb01311b9eb40fecc805ab3c8660b7ddd9201e0b475b2564126fcacabba6e9c291357895f519f58facf15103d213300076bc59bc5235c359ce5d01d4db8c44a480662ce53ff85c8d3c626254e5399305367e734d20078894c07e405ab76f2089dbe739f89b95fa56bc5c555a9b537e780d874d8af186ec13f83a52c19cc89d87e3332357a315f1d385f1e78c59b6b79011ea9a7efe0b420469cdbe202094eb56e9ea0bdf54279d3003ae507bdf530f74211c501eb8b0543be62eb3786c073df689a4727b94c2ae885d1d9c44fb293743bd0892743917b7a5833d8111362d5124a7c92401ebed79dfc48c15c00e5f2b2b648576b34da413d806c21542790ddeee0d93eb1573b4e15c71fe2127584b5c541b23aee281c7d1c1c555ad1a2167ba3d67b46cba4ce817837ecec17425aa7f5756eda37f0fa8ece9a210a3020af265fa4245e26611727bac12abc27f871e498b8cff6471db3cafeaa3e93b89c484d195cd2ab3abbcedebc3288b78e0dc0b557a54439e41431345a77ca0c870073d8d5bb291070510612443dc16f5a0b9f56be4e4c50517cc4b9a68809b715187eb6d5c4362a9cc044b1b70142758d08db030485bc3cf139de78a1d913ca5838e61bf1673f620c8d33dce32478e398a763378b53a921923bfb730cc64d789cdd2a93cd4526d1efe3de2b859d3140b0837aee2ef3d97784a78c706d14d217855d526ead386224b0981cc63093670876f10598100c8953aab65757b866ab45276230332e67fbf3d7f2b1e6ed94f17709f1acbfd8ee1814601dff8ac53a775ac4e0ab03922c6ace478e8d581db71204ef040db75101320f7da711033615cc07641d2aaaedf4e3461c5e9b4238ab462e9db8d5e205d0d7f4b42353039f26887d78feefc4fc309a4900064298c06bd100b15193c7a384e8c130c75b2e8b851f400f0b9e57070ab95086a7b267e1efde3550aa4e304fe0f08085d5840ef4da05f39bd5b1ac78be5af7a4e5f1c022c3c3f73e770a5c1e900cce95111026525214e422fd67ab5391c609069058cdbcb1add3e5a62bcf28e128a8d7fe9fdec9d42941a4c73d4cc40e3af0601edc08b896f257a103abad7557c95b0691955e939539391126c7fedd7a4171cc4639faef1018621b2d705f5a893a1df9e5b973b9f86dbd89350affee49a69a967fabd72f0ecdd3093d01e2cb7fb58b8dacf8f5de3c86f639e2efda23a5c1f0adc89e948d2c8e5166e71e0ba1491091e609d7e1507005fa4c770f39b794be287d021868ba4113f9df81bc181e2acfcbdf438c36b4fb93a9d07e901f8f8bce3873af6705740770a6dc8c23ce6fde0dda0d913a7a3146fa25fe0c65bc33a69fb045b1572f3ad619ca325d5e1a845417e6a22c97e49ff8d1564b1bb768d9d769bec8de3ae1389f1114c43511608213aaeb562cfc4deed80e06625ccf49e2226b8c79093e87c166a959960a4440712fa54c44f4cfdfe1dfc7938e87d96aca95cb6d303b324b87e7fb0a85c5d6e3920b26978b97a0b4588558c6c5a2be09846aedf2fda6af07f79acd31158c3049fdaace187aaaba133264b95097c3a24699c6e0101802bc2b63c0526283caf27e6bab86d5aeb0d48f3c6f1d7869bcd708f9502341ee7560e4faec691dbaee8ccf11b0d09bb12b36ce28f2adae55cdca6f5149bd70fbcbbd35c0c1374317579df146ad2acb8936e0f769caf132c8c78bc4cc6ff50eb39bcd0d39985f627c673a34d66823300dd258b5473425d29c62cec9642f54ab697c9032351fbd7f79ac88c24d252d4bfaddc8f2cd3e5ef6525dbb7340d5ba884bc17151e82d3f63cd72be0b2066722712ed2b5f4f6a5e79ef6fc3a929d2721b603ebd5dcd855d20278595af1771e17b4f8c5b337820b54648c903092816602a9b90f845301ed6eddb59737c546503c7fa49f400b179a799d505769c2fa613a9e7da7e8af22a00b50835bc9b12add1cd9a4e98c34ce81818c3e2a9067dd2a2e2e9aa5096a04bdc066071c0d34688c096d184d0eda09c833950c8311562e319637c41e6a2c5ff0159b54fc2eef1162a8c41aa949d913355870ad62540dc951fbd61668d78e877eef1635b20ad9d9d400d0f3f0f850c1c17bcf1c51233120984e30722f382cf1385e4bee98470dee41367849307498140b826be0478375258061d35a26681f2571991d778dd573605100c3bb8e0a45a25da44661cb058714b0ee8bbc8ca893316a66db5b0668c99aebdcf4921a449d8b7dd84f439eb28dd2e09916439dd440271579a20b22496e959114606ae4a99579968a1394745e3e06214452635590a72c2b8ebeeacf24f476481ee154e254a684c035e56e677d14d94ad1af193cb9c55953144130111f78ccc85c3563a1e66046d0b841a2dba2f45ed449e0a984f135b92c296fa202b8748e490a7d8a2dfd7eb1de23d5b504b8c5bff1f55faea365dbfbdecb0c23b3e18223ef4fd545bba2c76b33cddb49c4208ee72ab635ec4293ba5e35c7902299b9f99059c629e8c2cd55a7c01074f92d732352f1004ce18e8153871300f98004f7473344b78c6eadda89736e42c5dc976fa4d12247e08b864891d5152496c809c24b43a5e203a38d21fa4c40643f31a6ceea7748881875a75a674d00539d1d30a4325d6ee371ce44c56ed5fa774c73de7065e2806ac9b0fa6137e8ea179efcab8fbf45ea43adfc513ffebbdd90fd8e89419a36c700b7bf3c5fc404e02cd9f87b866c8bc625a4498f6402a7a92c7c1dbd4728dd6e865a67c6471f9a1dc8f922b9f85d9165f9ec858b4ec99ac9abeda5f3662a450dde529a4e55016495eaba5c28e94c91c6d49ee639cf303eb22abecb11d98beb1162b5bcb63e9189435512908f13d999aadd37dac6601e429e6d93de6d8335756bcf0cf1c25835bbdfeb6f65a4c6dec2a91e547d81177a015cd3b5adfccbf29e8e845709d20d4d490cff9bfc5e868bda817eeb958d3ffa64f23ef2f3694d524fa47453b3c5d992132abb8c7597012e459dbbe7162ccb573abcc67116a2bd79c21d8906a2ea19081bb7faf1ef7deee9dc549598e0c156d2311c9312243d297ee9f7f0097b0f368b25ccb8e0db4ce814a711e11acd59afbf89692a04c251aebaa3a22ad0e9a3518697ce2ec201539c584ac62bb8a08e29681b2f500bece1c530a6475cd618a6f8e4daab41e989f87e6bcfdda0f134c2ba9ee5e9927fd27bae5a4eadb24601647fe895c948af159ae511c2f1b90720f7b4714edb3304a9d818e7a9c212ac31c7eb1fc4f6cf5afbb9be051ffd291a07e47d82f527f583e0c204c955e30002e44419e12e7d17e403055ab14b8270130d2ec896e77d5d49862f6bba9c48274c3065a1e987d3c08bf000b5b9bbdb008cb4e5c1b517d53b21aa27b13eb2ea5558ad16e520b70aff1851d4f6ded7fc250610ef89a07f9cc9821447ec7883421c81581a11444484d0ae4d229671150259da9e2fb37a852d73dd97c13d034ba4530a73d71626b80c65dfdc581afcaabc12c75c86520da935b165256a2a5a590e99c1847ee795633c8ad12db9f4f56c17a0934c4e81f66090bc941f90f576a80097b1b4f49ab3471dd19ce53e5a43a9bb37cb816f5221f2da3f2c7ac10632c62fa43654203986468da6a7ae723476126aac9da36f5cf8a3bb33134c15d157a441b95f90fd96349d622d432c578e4c2551f88f864a87b344db61064ce0eb96d8f8d0af6cb9a80107441e7f6304440fa258aea5f9c1017df3c6f0ae655e961fa58a73b51a843145168a03b11cf3906d9167c02e6c0e10c1f0d6f37244895a31ef46fad2880582deb03b929d5b7e4a1d86292bbdc7e3266aebad774f6fddeadb4bc6d3f80fe05fdfed9a250e2385f7ad45e99cebe118c6a0c004c87d581b0e6bb364509b550e7b40ceb73e1a66f728b89be91db4c89c7b2f14616c9cfb144eabfc00a6cd10685774f062fe54609e833cb717b0ee7f5f817bae0dc1192f38fb44cfb11f85771e09c259eb3cc7a162788754fe98b87d96240cc2eb37446d6594d038bc7a13691bc329e3e1d51b216893337437848757572491ad4f59825aa6754e02aeda5bbd1627b0b25117045b036a7bce7f5e40125a690e134de811b4ac5efd2b433d7c3055fc0bc84cc96edf931e7651d97f8e55e41883526fbd359c22994284e610e0dac69940bb33f467a0bccf03c3de8ad8b931da21f867a283eab2c936602269adb5d65a68c9cade22b794324919f4079f087c072d0fd038a5b4d66aada5c12e0f8f0ff99092d2f491b2e846cb0334b7e581fab3e563277bd21dbae3484873c81c324aa21b2d0f68ee00377b979892d64eceb9b593736eede49c5b3adcd0380568dabab16d1bdeb1c3068a2d90c32ac3016451052c109b58011426284932e7f499411699109198d0027d9ab3484e25b29473c264d3e443101b01ac04838007a11150522110c4233083d408d83b95500810000742587a6d31841f9c044161831dfc70c3111dd881120c016ccb1b1f37008104c90f215c604326d104104000822792bce0061b32c8964ebc51464aa54fa68fc6a8421ce2aca1c3183ef1c5044a1ba7138dc14d4ca68f61d6483591d1a347195b469e4c388553168845c2f0cb784f5fc68ba4d13dfdf1bfa73fde1aa9a7f4a78439fdeae96b1aa37afa5688c67ca12db24c668d54688f58a1a42d6b8550a1942e4cb6fdac02a58dd5aac8daa2ad52bd3dd2de6a3fba35fd8c9ba4687f057eb4655f054a2d5d6cf5428984ce1648ba5819e962efcfbe1cb881a3cca8daf6332cb745d25e7d90650cec545b416663199b86f7e38beac75fbd94354eafbd9430ddffd3985528435bb3c6296c61ceb0af0a5fda48a564688cde7c43a1be8559a365ceb06f33b9844ee994d2db71267073516b6207b4266adf81528a299003b51dedd6b6f05699c7aceddce698f002135e5047b82f658d3a67d4bf2f5e4a9811a458bfe5a584697177f12630f50f92f02018e34700593e044bf83a6b0d29d6af8f554f5f8e286cd46fd40740c2a05ea431e1a3fe45d2d01ef51f8d91a89fa8c734067cd46b1af3af5285d8452a1a693cc2d76ff999409286f675db3812fedf478c07bbd75cf7fa159001d9aabf658b260352acbfa5583f5bac5b7918bff2526e1821b645230d822ca82fe16d6c3cc8820a595ef807bfe61f7cd483210f23a8b006fc12421e311e7c1e24601a53c2d7d7928626658d185f6bbd21fa40abfe7bd4af7ebaf8995af9c0224af8155844f8aa121e15c6f84ac2d7c74163c0afef028df9af7873cfbdfc91eeeea5fccef3f4cb9670a45b3f0b88828ba88f316b0440ce407d45fd299c5f0228d216ea5d802fd205f562658523de31404c5ba8270194e2aa7e0d5538d68d922ea8d08ebe4daf85be2d65d79d6c8ff3270b410d7c912efe20f8a0a4d917803d855a3c1b99608a061b8d7337e6cfd609bc2a27edb6c8541421044545d8219bd1dfeb2d898a60030e53b4982204144c319a62059dd1df4fa9c11212a3d5caa52782829062882194349101c52008cfa70ad20d98c0614a9316bc6ca916206019ad16004c68bc5425690acef43997a424ed948bef340a295288bc6ca916293430a18714294432294a60a0c4446b41c5bdda8cfe5e6989c65ffa74ea1eb2b040a9cf3925f589d9aeca3a6b485958f0af4fe361a5de0116eafbd3541bf7ea6f43e7062ccdad214b0df6f61580d9592ba5944e893b1afa44a699b4098bbd34d45467997fb62e71c7d19085c6432c5d58f0b74f411ab7f6a99dbe8257392d9d93dec7bee63e76312b2f9d136716d3fbd82be06299d5389a4c6d46e7d4682852916595ad519a1986dc46391bd6ea9827634fef0cf40d47fbc38277f677b454d0b896539401d51c230a84798cee90f3286dc77cb6e34ca8ee20114dcf1e890ab9bb533c64fb534a6925aad5de1b8b613f5bac81ce0c7077c6625958d03e7b1a2d2cdafe99f5d94ead2dda1e8ed85751bad45003445b87fdd96e93cd4c29cb18a32674b51fcd475b818664ce707ac7960f12ed675f0d8986a462f85a7cabdc31210a3d6a3c3c9a9075ea826c3f7b629116ab9836d093d20741e92231fcf76bf05f7c294763e7942e12bbb406ff7d05e0502694a1ad4b31e568dc7bc1dc0c62d10cb30a4793edc49b056bc55c16d2d8f00a6ccb5ab67dfe1aedb32d6b19368b8a6a4ecda14014c8c8c8799c670ecd21a9340fe075a7ee6cf9eeeeee543ea594521aac22ed29bfd65a69acf5217bcab7d65626533e86512653fe0d45265a6eacd6dadaf3c7d6d6b20e7f7d1a1cb2e08d85e3b8efdbfa63569f060bad8ff50959c20ad4700518fb8662b8028c6d4351ba5cdf6a9052440a12294494922831512aa28444498812112d969474b478a2459216544ce999023445670a0aa62099b204869f1baeb8018a901e10d8c0b2406a82075390a007af259620dac418d45fb6548bd2d166d992480a0e538aec31861090ef7bd1891b2411e188fa0cf238378b02a40dfb3ca4908d0cd4cf807d53dd527481b6276c008c73ca64ac02236c175bc2acbeedac550176be78a31c0318e07a62c7d81e0935dc2fd8d9534d49b7ad557bad9d314aa9cf39e79458eef0cae799654a16dad1b05deeec8d73833bdbed05778365621c8b0c5db072d748211b7575552a550a8542a150a7d504553b9f5c984c26ed799ee775a7adc3d2a5cb388edb72ce396bddd6f94f10dc196b3e25f6b00659e8156829f4a889d0494e58adbfc75b1265e1430ca6d34aadc4e4fb01dc00b24a15df9686d5f79532b3dd7c624685a413e0ec5e9c444417e3063fdcab82149af9927ac058c33809488e7183a41ab21a454a467fd0e30703fd7d515a90a402cd87a413241191f443520f4940926a8822e54994a4284ba23489d28289b12082d6ee0d42ce1c0b27f8fb25302c094bb120c1ad181644b20c8b9e2842a2188942444b92356fc337534d4529a5f7627c2fc698f6f2620f638c7196590bcacc7a9af779fb1b5e6c70ef7dbef75ef0eeb9318b3186b1b097d57b47f85eb4b0b8800163e5c31dbe60d6427cb346428a65e563ad5cb850a5b20e63b6e3bcbd75315027934ea5bc2eebaed7715bc771f866d904f102d8b91f59662fdc868b10d100c5300cc3b070749e6dbf173b22e7f19e25db7ec721d9f6373fb2ed632f42440318cd71226742719692fcc89b64605728a6fb32d098e9f3227e1269d7baad0c8fb634663e79e9c251c4d97669dbdfc2f19b3e139bf7de7bb3ccce811ffb5187cc68ab11940a0509354510e4ecda816b072f203a3db95554545454545454f40292c50bc8931c2469f202c2e405c4a7891710a021c02a905e407ebc38e0e405c407901b1e2cd963dd1e843d621d243a4f9a5ce15214b10327e59c3a43747ee674771d9ea457101c27484b9a000d1139d2819d214baf0ee818bd72507ae5c083254d8ebc7248d253e49503ce2b07212f9d9c97ced24b270a510d327d8ce5bc773a8639b596d65aaba5d462ee58ab0abdc27c297f8a2fd24582ee7352a218620f312e1bfe28e050244612710087edafc20b879eed5f23670683edafb325dba798db69b5d8bd18bb17e32cbb38bb18675ade382ee76de3ba6edb38aef33c8eebba79675602295e3e9c78f9087af930c1cb47113ff0f0f2b163a4f4c4c90bc705d888944378e51ce9e09543035b6b0c5a20f4ca017ae594e095a3f3ca11e295d383f4cab90922e50b87e8c7107e30f921841f497e3cf901f4e3c80f213f4af08388d28f9c1b8a8c766a665a96016d7fca641bd2b2a6dd2064fb5b138cf8750311a4d70d1e78f970f2ba01c8eb869b978f9b978f1a5c40ca0a6444797c48e9072f0e08b58052263e23fa2b02c311811240383da080934396b77ce1d4b0c30edcfdbe175f360ce1872a96bc6c207ad9e082970d412fd0d8919f8ab77cd9f003295ac8132f1b82bc6cc8b9dd962f1b8420c292ee496cf9f547d238c91bfca088273a90309388c989a4a18dd00f4c2da8902d9fea20616612e59134bc974f77248d6e6ee12e7025ee8484f1243e2469702fdf85248dcd6120c587a42148182a4449d2c8489286267d20451a8484a14fa6cf954b4891be2061ea1117617001c6fe90a2c5e9b11a5a452145faaa24544aaa22a474a0f2511d91d2215594aa02e5442a2705e4340414104a05a720ec0f09730a8214711ce664b44fab1e9bbe6935b48a42ab92d8f43d9592aa085d4a079b3ea7f2511db1a574d8f473aa285585867262d3cf52392920f734844d1fa380502ac0c61515a7205645d285fec9c86156af531024cc8a89acd6be20e230a6252629a6d8542fe92a52a46ff2a18b6824b4125e13cfb3c2d3f182783c7448ba263a284ef206269314a625a6297415bd64f2a191d045b4125e0ebc269e155e104fc7e3a16ba243d24181612d33c961b823ee8a2cb81e0e0829d2e788d8966cdb14792957d97ce4221989ac849e454c22d388d7715770475c161c105c0f47c426c5b6649b2257c94b9b8f8c442e9295b8b7822c9ec461b4265a0eacd854d3d1824891bec64386246b428af43328f011be0267d14d2d66d2dc82d372a035d1acd082683a1a0f591319920c0a7c053ec25960ec4288c3e01e0c0426e22eb952dc29b025accaf5b1b9128741d6301015f76022ae1477c99d02ab822d5d1f5916aed0270e8315c19068920329d2b742a33e5021540419860456045362d39738074d426b8583dfcef588c3581d17e9db20a71e1747cbc3a53e9030f2e91321e0221b24b43a33b43c6cfa78cb9275ead994c5235de8d72524ab67d3677d408a54c95e1131b122922e49f4c81a42c41ab2e99f7a569b85a4e70c2746b409382448c20700411881136d420d3a06da0aad54b5fefe55c314af1a960091eb8f13bae342487308917c9b3d8d9cf2501faa4a76fa78c6c428f40cc528b418851ef1967362405e3d7ed0638915489ad4578f9f8b61455e3d745e3d46f0ead14325c9eb86caeba6c946a4654d23a2c264fbdba011bf6e5e37af9b2a4aaf9bd74d952b7654f141152aaac8a0ca0baa34510505558c54e1a9e253e5a6ca0e95252a465494a83ca1348522737aad24b0b605155c9411a325e5c2e755c3ceabc7d2088808f1aa6167c89c73ce578fa5570d3af2d54369a7bc2b744d41e091906942029926364cf460e9074676a28860c7c655a2879b2484e8514568e67bf1550392570d525e355c9124cb39dd29add55a0c937fe528630321e3b7f6f18f22d7695bb61d97ed962fb6f76d0e37607f32a7556449b14dcb3fbe7c2829fa8f55bb38bdc742d15112e604f989277cc78512db326d4eedb517e9625f0365e0af14e3db6d6e9f6429a355421bafec10a5e1a8c3fed89fec76686a1fed83b1d6dff77f43eab327f62b34f0632aa13d6a52b6cb2b1ee9fb33f4d2af1390c9f41d0929fbdac7a176224ea18730d6fafbfe87ecd0f67094d937a49876b2fd2d5deddc2a660e502793b641bc8edbb296cd3a844791294dc91160bc686171b1f2b156aa14ea64d25ec76d59c3b933a04204c7164932323b98e1a801a2237bdca4fc6d5a2113c3041c4829820f18f163831b1ea0a00606f0c1c80e109038d941164234c0a513295388000640a8c0718288228a5e472110c293251c2065035e74989c20498f201e6c900181440bb0c0a28810f430a3903206179000003cf0987892399dd2235b10a140d0e9be34c524f4c4342665855d42cbcfd8d642011d0116504c00b2c5ce16374520a2c58314b249971d9ca3b13737f5595680b169e84843cce9943a0982bb918115acb562a225a23d6e3babb804598e301d875b04c8bd4917e95ebdd73c5bf6c8e7640dcb3367603d7306e599337a660dad47e3e9e9d9f47e1ec10eb143ac53ea1a922156884d5beae7a226347e30b6e59935b42273067d4a9f88f5b146c819d41eb1a98776888b3dd41bd28a50ad04986b4016f480a40b05ba9827e409d1180d4803dad4135a21db1a908b542ba244919f234b606d68d31fed102d8974a18f819a9086c4450d0a39836a299033e853259b6a2a902ef4721a9074a13f04c808394423a2f9481a563b62d3cf197d8da73e9d95ce9e7bc30a62bb5b1dd0636d05e1a4bf4794958a20842326245987e9b4b62c862d60b2a468b598ccbd26ece877916ed452706ecad18814a82d18eb68e8efb408124368a13d08fdd20ec48cfe7ea9674967a9880e6e277fbefc1f220b4416f8e7e9e0dcd9bb1172c8b4d18e71983f2b9b29eb72a6f7e6f5c27b7192c77a4ecf7bace930c7fcd10bf1e94d7fbb2daba8f3f03c0fe55d5003c7ba35ad35efbeea671ce5bd4a857a0d158e3bbcfb56fe62bd027e59c7fda843f35e357752286a7afc59eb7e9eb4d0393a9944049da37bbbe7097f97655e38daec8d9bfa4f60f71c37c399e33037f4242e66d9e6cd1d9e223d3b42b4cb6d5c98fd04b7ed66f3a74a2df4dc630a9bbe9c2ae068a166c353f4f8183f46849f21ce99c7bcd9311d68ceb038db7c2d0b94e00e0f9a429a6e28f784641963f49b4dabc432939a942fddcb7900d3ea538f4271a9540a8542a1b84fa552cfa154618efb2bd38fa97087efcbfad5497b2f1e85f2501eca4379a89fa128ef438163dd28ef55aa30c7fc173fe31f386e60e748fd8b7f0143f52855ea3d6eb64c96e962aeccc97a0e463856c066a7fe056a0a519670d42ec2f15b09c7ffc2515485e3cbeab9cf2870058e27d6676c6b2911d9340b9de3f496c5fdc9cbd97198940e8fe9e909543d0b3cbd099ccf81a65538aac2d34f204f3f957bfea0ead19c61fa13680abdbfa0fe19aaa7e7bd78865e3e00edec5b076ef8e8b6948e6e386f1c668635c9451d32ecc0000f9c96143d4aa2711ae062ad2cf4bce18cc16166386170182e1c6db6f7109080c3744fffb583903d4ea1712ecd25af1d7436fd99a442f142aeebae1db9b002361fbddf77b32509362d53379973a220caf8185f8b4ecd1cdab27f438a0dd9d65a6badb556ba7cb4cb478f52480b5f44f1fffba6918bd67fbe17fbf2b32f13afff28b968a710d6df8b2fef6281b6f6676866dd68db99e3f950ea52a2310b586bad9d93db723767e5b6dccd39ad5b241650f0167d0e9cc9ae26f4f8e25a81a63fbe6419285bf64dc160217dc17a63e9add91af59d608caf76aea06dab6dfa3354a38f5f36cd9cfb40bed9338b89fd9c73ce392b14dfe305b69499b17129d1f567e8ad610a18a594d68a84b1d6dff72f8a154ad52e8ee7c0217b8d2a946a2d466bb535ac46f571b898d0935628d6731148f66ff9d261c9ce32cb39e78f03619a66c371ee04d48b61169b40f3c7835c6822d1982dbf07d1cf2d2268faaf9d57901b76f66d7318ec62217d69b3c35b5b48d25d46e8512ed9f45d46d45aa70765e01121cca544dfe7c029c45bf4b78c7e11398714538af4d1773da1e923edf91e3489b4a1ce76b6eb72ceb9b3df650ff220ad81b42fd17afe389027d15a731c669fcec7f34fa699e79129348f4c241ee4411ee4f9fdf900ce766df9e229cad6669bede7dc3d95b7eb72ee2a5285d2a552dd57a3d4d7a3d4522ad575f9b9d9d5a4542a69731c46e73c4dd3d4d39bdc4c8563056c76770ab12753a1542815ca95c2c2582fbf1eb1306cc99592b08aa4aa46584dc230d68f15e962d8079e60036cf5d8ab50d774bd7beb7df11bebb57fc1fa16d6b3b0de05eb5758ff81ab5087cc565dacbf7d3f2e6b374b6d2bcf7cf8e0732ff63ef0f480b49dbc7a2872efbd0e74af2fb9b38673890f2571a13b7f3c49ce4239e7136c90b98bfa9afa7b3989528563f7525f7de711e9e216ead87676d2c21d3528b5dd292e447d09c618d398d3e370bc4ff19f52dd731e38916c0fe59d382e1cb11b8e3b2af699b6a37a90077990076da0da788ee5d0430f0f49f4fe0edff4c98b07242f1e8abc84285529a9a4924a9ac29e2f2f9ef2c78a14eea09462aafda5dfaf5ed29815177ffa96efb66f01594017e00af881381c318cc2a7d0147ae1288a346ba10e994db30aa54249a9fcfa80b10c3a3f6b9ec485341d64ed6fe00e1d14347f9082e68ccc6b8f234d3c37969e641e01a231abbfdb952e84b465a14441064c41a7bcb5e119dfb66ddbb62dfb6ddbb62dcbb60c447d9ea0ddaf3265d9c54237cb404fdc4993fb1bc6392bf2797ff426fbbe0bf761b8d9449a491eb3fa1bbeb8887d2b498f7ac332f0f413acbbfabd17e3257b9c77c31868d6b89f799289b72be4fdfc3cbad09efffae6f0df3efbec33ffd56f736f3ae6cde63bd09c714da0a3ba393bafd3df4ded7d9e9bf65be8417346f75ea7ffeea87ffa0caac014b84fe05c72b23568b7369390245137912eb6e9dfed5d601ddb12fe153893bc753fdf57812ed0d6fd14288b34e039db044aa4ad416c73a0f49ba57d7fcb409d48db044aa2adc1ba3d709c464ff6fdcd8382e68cdb81d783660dfafe1ee6fc77fb9bf1a6e1f913e441acd7909b2d6ef9daa168e37f7911454cb3ecb3ecab91c3e02ccb2cc620ce9ebecd5e5e4471fc2c938102c508a9072f0f1479e9b06487bc7440b25f428cf600b67c09f9d92f213b3b6fecb1c95a6b6d4d72982953a1681c0d568da4b55f9132ee86c5dc8d2bf3bdecbcd434aaefd3c7fdfaf5eb7729df9b25945943f577e57edfdd7de5286c7777cf2a709c3a64ee884f9f1db45b06ed5f3c5f5b9130fd0ede70aca306b65f21bea3635ffb6b9bb3af75776c63eed6ea6cfba32f714fb2ede63d309a06a3ad43c689fcc3e9c4c5fa2d2c747d593186bd44494d79580cd4a3b9a4596b649326f6598716497bdf2ce6bf8539b051878c110a4e6414c5206a19ba42bbd6bf98ccc62c86616fb37fc6d1a4404e46ef910215058e27709c46bbca6ae4a2dd64aab847995d656c6641d3cf97340673e188b5febe51dc1e9a300cc3300c33698f99be4299334c3fe3d904cecfba2ce03ddf7dfeab54d9445dab401ab9b1377137b090bb915285a3cd56fd4d00fed135845ef9ef574f3faf582c168bf5b1582b2c960b168b85c56a61b15eb0584740295d301068df104bb259acbb2b8bc5fa0d6c9663d8ea2587fdea1dc47ee5be72ffec6f0898ecc9cd3037cae70c17bc8f81d97dd40d0769e4be2e1f17025b7091be032579180f71a8307f7e8426916b045afbb6a552ae22747daa527d2a4c6117e794b5c33e0b5d4210f9d35fd19efece718e1c47e7e885f5fcc205daa244e10356c00ffcdec6c6ca7f210f23d8f3f87ea5c6c5affc4ac863e55dac2692285a1b259112cea6afd42293c2f7d83c82b11ec3b0d5538761fdea635a9e7e66dd70fec81cc156ab9f73de8b61feab573dcb66b354ab145ca440ab5086057b90055bf91a17cff2dfaf1c99402c20a6adec5d642b6fc3587abb2cd62625d1e967dc851a18c66fa346bd513fe28d423d0be8025c013f309f381ca86dba6aa3abadb236fb6dd8ca6a156659f659a64a811e7723c562b15c381afbf9abd5df7babea31d5afc05186bd7d0acc3f39eec6b66949348a264ed671db787278dbb5c3c28b8ddb6ee1054a9631a4eb871e3f17117a52fcf9573f4b1c1fdc773418f1a7617bef2ff7dde693e585edbdafd9def3d05aafeeeed66ea0f427aa580860cb570892b60cc65acb504a75d073fbcfa739c3e1adeaaef5e3bffa317e3d8f3ed67f5fc3faefc5b3582dcfa22fbee5c7f9e34a4b1e03a3beb030601cf93c7201e7c5b77c7611d193e53e0cac677918be5fa1c1484dcbaf3c0d2f4216fa2ccf7a96a7a125647981e5595fc3c2fa9aff7e25cc9fa9cd3ebd73374e9fa774e1e8ebe0b8c3da6cb7a6bfa6cfe028c336cd2324f7c9f121926e55ea25f7aacf7463bd8d0dff9ef535dfb358ff85352bfffd4a6863c3c37147cdae1f42171245a3fe682ab9c0d1c25fa0cd85384ca5dbd71ce3e2eb6ff5fda5e78c72c8755cdc6c329928fd7c7a39e3367b03756cfb14b6e062cd393466fed0fa7368f52e22f4387f66dcf356befe149234e8c77c5f7f12d118d6d723a44837e7f3f3081e1a23e9f4f1b086e1e459016578cbff638562a8b35f81dcfc5181a369a7c09cad73f9e8d173dc6f0c4e9d7a0843a6a00b2ed69c5b70b13e0e2ab7bb7e48dae2a1ad07380142cf7003cf1fd70fbd71276c8331ed481add9435e6d19c51b904cc2517c5faa6df42df912e26f128cf711e79e00c7e235deabbe7646e53baafa58bdd903286317dcff11cd7f118d6d7ffefbb976381aef3238afffee3f5a9e7f4681976380c0f87b9c199395387c5ff6f2a65846b08cdfaef4789f4a30b2ed68fc1c5faf34739545f86afcea1f9e30a811e3d27c7612e8fff05e7769d1d210ed3338488c35c175931dffc8f054af962ca00f847ff1ba65c9c9c962e9ec298bba1ddeb3a92892860acf5f7798e1ff19ccc5d3b9abe06d68b4d9fb5bb1b83d24597d3bd7637ac5b722b6cfb86385cf0185c08e53192b2d4bbbed0970f6b31e4585e40fde96b50e12994b4552369cba3ff0017e9bb6cd0f4b3d7a88f9f55600a3c815ef53ceb7998e7792f1d46569f32b6bcdc0dee4da6700670dc5c381e38eaed693a411ddbd60ee20de46ee0b7af5d1c91b29b2cb347df5501970dfa299ef835198c806ab78b437c19c0850cb89b0b47e3b79a04c71d5b4a0962709c4764d8b54e22205c3e5a46a6294a43ad69db6f97117a7c0de71c6ed7103d5d4180a0c80f421bc79d3e73600e2ec70c779b5e6ecc81a797dc0c779fc21cdccbfd197833cbddb8d99bc009eabf09d0cfddf05ee66e1b37b0e9cddbbdf43376e706d2bf9ab5b9a00bc8bd4fb38537c4d225df4fbd8d8ded862c2fa03ef53546eef3c035a84f7d2ae411dad8e85e72375c1cd09c7451ba98b9c7d2257be00ce56ee40ccc17cc61fa2c7b9306e59e1abce086b7e7fe82db73e08d6d6fdbdf7b6fc665d95f2f64b9df8154e33e5330c76b9ae45e721dc7fd8c6b207decb9cfbf3d05f36ff4396ab325f7d4855ca43b632f390dab5f692897d03ad7ea52b20268dffe8d39bd3f8d41bdcb2dd73fd590e585d49fbe26f5271ea74fd5b026f5a847853c509fcaae1ff4f83b941145677f7ad48f32a9c9f61d18e011c3033c46f5be9d38afceb7ddcfb80cb1cbee71e1e3185983a3cdd67f83e35c387a9c47be33bdf7d3667ba08e6d9ba896bb4aaee3dedf5f56d4890b451765f60c47ba73380660fbd0b67d885b8020e422fdc7dec6c6a461c8c3087d1ed8dfb006f3b88fa79c40764e219182325c9c3f279d22b3b0e02f9fc631a642a753a1d3a9d0e954e8742a743a153a5d5468709675f2ddc7093d4ee8e1faa13597d635c4a882c37cf493a131353538688c8ccc908c8cadff69daf2e9f487a7a1093f68171ee913fabe1fba0587193fecd9041e70bc455f2a6180c6cc28cdb848ab680fe5e7f4a3760757161ae38b6198a5eecaa252c7d2054b1721cd4ef77fc9e5ec3fa9f68a737e9bb37e0ee3be4687dcd77861c636ab1acddb66410eebece7908585ededd36c32872e1c3d5f03b1ff198a75c86c2cd4e0472b389a367d2aefbfb950cefc7de2fbd2f167d083e68f0379d00c0e155e688b7e26b3297dd78d07b96eac942c63648cb5febe7f5126058cfe29d3268fcb5ef6ac50aa513d823267cc108607c4e0227d09d0981fb1178eba0b47fdfdbfecd657a1a45a5534de74a027a8342dd6a639c9d4d00800005000f315000030140e8783229120caa24450e60e14000d7ba04a58461bc7e2a13088611406610c31ca18438c01c0184290523243360091c2b032b848390fa3868efe95687c66c407bc0e1b16d73d529ea1690d56e3c62415d9fc60808da85b2ab21f3f649b41274458cd80eb0502f618a976229b5ddcfdf801b6362e2ddb8c46625122ab4e09c5ba5733e3f71a9639d17ffd4ea0b9a01b42174deb8976d1c5119a4d3dcd0d6775e438980880e27d3ec66c14202c07c93fd9f7477f3735e10b10ff7035f46f70e408f757818a8e88977a41339c954e3548376ff358267181512c1ffe56b3b567e1056d3389d0e537259c98008f5a6e47b5d99aa8668a2192de0e11cfd55bf8a1577472cc33c538ca41bb1c95225706ec9b1abe112ae52cbf6db9443e97357050fc44570fee7d65fee5b516489c6cc7d9d4bbb678c987fe2ea6df693ffa9111f873313de282af13e2ba122226e570c7b09c19e9c32b2c2343b53b5238efc0f2da96572267714518c9f67d360b3839403527e7806f8fce174dbdcd818320fd83d9881074ac3b380bef3704ef3e106b7bb74a427fa1f9639a4ae2e2825667a77ec5f8085383dbe2484465d13353e99841096947f72ae9596eddba8cc4aa11402f4ba5fc0368dfa6991a32827f62af9eaab3d76fba7630fac37d5d882bf44730da6d3193cae91ad9087c9848731ca8450ea0f5448877bb5d49cae2770ebf525742f9723e540cb396085ffe15fb1eeea8e2f3201250d06cb0b788f05d3bc5920dd881a7510186a4a43ee9c4e9615bc2763b0335f61d614128f6b15685da680ca6eeb04ddc8d1587a8eb72bcec3aab3db95a32f1c4e7e5421c1f6bf44525de0b6e23ed643431a35e7ced22987f0ac923a4ed1733a1cb0120017de2306dbe7d7d11bf7ff6b9d95b39d77af029c2ad1bae78cb0123878a71be8ab76476ceb04635f5f6ebd2b25d56b79dfb595451cd852c1a61e4a5bb8084f798ab72ec3b7404042334329d6a708a7fb2fb8c6a99de2fcd707192c99170a4899e8204a4327c863a217f88f1a62938a455389a0dfaf728d5fe8b830fa6ae6a18585da82b222ea2a7201a0871e9a9b7c8838a91a11d8c57da1b1b2f9761c312c84f530213e79f4c9e01727e5e152dbde6d04687d41a699ecef24650344ade2a42ff86acb26265c72adf561050e897272ec09a2de9953294881e4f24c3b73993ce67fd5a7e28bd1106e7ce5ab0961a3143d4bd4e6ccde07f41d868de95563c46be99042092d117c358bfc0b72babd4053c200d25fa1bb61cce97ad313337a815da32f13b846a95247a9d08fcd8f1d36450b6d77f74d98790e1bdcf908bea28f6b990d429044f70082ba357a0efa6fa3d7335ebea9ca16d0a725a30ba5b47164a3003c7f5fa7199990257e8d3347e0bc0d1fac1b0b990c6e0967145a77e3977f520a2fae8375e69a26a3db3a82aedaf37da3c3052a5ba493256a631667b55c0b081226a0374f435568144aaa0bba87d6dda299e35f9f3f52722fb5f451470a9608b764924ea9a54053d3b764f1d82b957a58584775c5678c226e0fbb1430b5616ac285fd7a21f5a0cca6f3ab3b99f71f2e31c5b64bb21c11fbacc495c11f9a756cb5b54b874a0f0540542f4781de5a9b6fbd34e10f90ef4c21eda2e100cf9a5289aa892aed102a2275ef67b2f838e28d002e7ca0756e29b164d489cfce16f98761dce3ff07bc32c67d2481c7a1ea76946254d484c62ad5b2d886f703846ee527971768814ba585630e4bc9f4ca309a5dba198190bcdac95243cb000a31c71b2ff2d4697ec56dfc49ffced2c5ebcef84ec588b06d282bd5b9a7c56b04d428337fbd07861bb71102182ffc87390fedfc6b1a4b2828debe038148862e247b3efe6251a32d7dee8f833190f006b50fc99171c739b7a6e99641d083597faff341c44ff216437f382ad05bfd316c802ffd473ff401c6bbdce99f3928869bb6b64ec423ace3a6ff128e720f2a844f2122787782a61dbd825a71b5f2cc507b0a565caa0085b420873364c9e2554b19a9845b8727674ad17b445f762aef61653b47bb336b59986c36daa8ee5b3258f316a86aa19b7d1813ee5c3f9f5f833073e0b33f33d1297c3c7612b397c84deccbb229c8a091f124ed590de29d76ee38f8cbae42df1df36ae99196abfd96348e2cb2158f5d0e8a37482b8f3428f4a565855653b67cd17fed716d176837bdde6d93fe89c29f7863f365e5ac767fe8152300090379316b83ecbe5a1c43e60444f3b8e1e21d1a1bb9270647b4d5ea3e5036bd05da219fd230ac9f2a96bfa6dd32f53a77fe56f990c1398df98b9b6700860835a25cfa8e1ac2998c4f91546c3cd4ad227f908fe01df242d2214efcfb16e2b5ec257e46aed440bda075eba588abd08844aac726b586f53904f42f0b4db607f15c146bc8ece07a9a67ee6bfe14dbad03fc0b90a40335e4a71c984f822d2c7fa709c7be2989dccd0f67e8dc0762a7cde81ebd7cbbc8a3caf56ac290afe4768627cf9e686f95d8c6e05992f9c4e4be47bf53964f8c159e81156e5ffd6c4ecec872f1d339d62a85503164fadce43f134b90ff5afa07add9b6e09cc7888080e5ab52f0142d7f844916210693365e2c052c9ed3866195e02f046021d3e666aa86d0539c60b8b57e71061f5f203ae8f666ef1cd4808befeb61303fc4bf3781f5be80bf3c0c111f722ee729ab27e26f73879e0a8307eddce54de4102d04b3845f80db4ec3c31ba0ef9c813b81adff64674b66ea15eeb1931f85f89962137bebd0fc911c58f84d5d37d26cb7c30ae56a65906570a03571afaae4a6a85071d458f035b04c8b09792d0a44682a55934f229d5046fa2d4f4ccef12aba2e5a29937543ee8aba755e04c92e6fa3941bc0c2e216b0495401b72b8677f2034b93384c1e17a3d0500fa17a22bebbc3b0dfe28bf7a6602802108ccbebc65a17c7b945e8cf5d8a7cb0648a5ef3c46803816cb2127eb6bb80510058fcbae9a83b9bd3ce82fc792d3e0b71a497c1982824e2c6796df504420dded21742ceefb084ac35531056a1d559518f965cbd63612e235f2aeaded830dd74f5578bcb293a6e8419694b8b40ce825dea2d57434ad39840ca08a2b79c62966c1897b7e0bc863245318fc35d0d4b40e020be625a8372a3da46c9b179e7f1c295559b4fece85f9fe3f6521a2345f7dac172c6e73da9a4bdd1f52b0a0bd40e87376cc868c0b36d654cc2bd5ed28cc58f946a194b0b83b76bd056bbd900a5e03fe74acf33e31e2f581d742d272d96c109210727b4368b1a1a4e30a9ffc8aeb90ebcdfd05da5e754719ad79d7cf9e3da43cdc943edaab209a82ae7bca52a25f375368553cf3092741d5296688eb546b2d1defe09cc0ca93a709036f9b3fdbe9fb66b86706ab3257cec58950253a5a38367d9cd50bbb43c54e3114e90110d74de6d3e9fd85c17f30278d188848424f921ebb0cfa11fbd9c7982c3c2cadf34638f1d091d74ea3f1893c4786768220109c080eb6248d751ce8b6b7946e46fafd72ce4dc96ae046e474f5ac0950a50a0a5841ac6e281afac21abc7a1860f5e8d57fb43fcf4529803673c17b19711832f9febaeeb5252bb1898f088aa5fd88e8d74efb96b3e7dc935167a5675a9bfd28115c34734999585be39a37e598ea3830d2bd1aef982ede7ccad77faa2bb07e58658fd0cc2dbf525dad26ec636acd145b32bf6e0d6592deb5faaec988fb9e011a6613d0b2f914cfaab7d9f634ad000b113ac4ae930e95b9aac74fd2348f5dc9eee4114d801fbf08756189d8f11c6a5b5a17d7263c6c8b98946c4317ed4a0f418e65b619969c9dbdd71ec67db5ef59f3227c1bd5af73d08293cd609ee25de368423bfda605fbbf6202ec3c8544bf82ef30627dd30075e78da07f7be67d12361d99085c5f70fbe8712e47f6343d173a0ee636678d88f3b23c447696455c91f4e5224ce982e90213188c6224ce34f2e4e6f57559515437fef9d4a9cffd438d2af33af4762f1455a641629268c987a7870e1c90b4b88d5b0914c9756ea2abe8012dd958eb609f6d53cddc07b533764a19cb666ff486b2cfe2e2d5dc13012f55ef85319999973cc46740203ff43ee6b60bdc1219031853fa51020439db0f80863579055c5fa53dc00dcc6edc1dde8055a45658589fa29032faa17e3304458a4742e12199040a88f9b9d7d6ce12954b04ac5dcd53b126deaccb3d08ca5a1d7406ccf49f3da4f877a144ad76abe401b33a6a61d3e1c14eaa80df919b9c06c2babd4091504c205df1fdc0c45444512206cbb9fb2263aaa82433b5c99818e45d69ad1129b999abdec3ddf09178af03cc83b5cb11b4b908042dd0f5cceb69f0f5358bbc1b260616c977fadf5e691e5363b3aa4e3afc41b9aaaa971ec7f6bed81ec45f27a5f29a85b15e4c98ed7f74ac45e5374c0dd926307c18e1972169c7f95dede3f3137bca4f241b07ef34b0464d22b14121701cd30644712c10635d16dc035e36bf767930f872045371d8cb02a6c406b4596e02b136f4c912c01114a6971e9bdc549c822987a14db3cc40600f1c43c3a6f94fbc0a57278d206324725699f5f28c09633d48b39161e10a05c64f0143397581f2a22936c49381e9a531923cd609fdd8ef414fde931848449963192f70b07adbb76f18b18b78673b81b240ec342c768226f125d6840c26e446d3f5f2b6e0ce8d51ca3aa811510aadeba8eddc00f245c7b0d53bb91f5d736bd68ce2ab50846eca7c297209e04aa7243d213614b4099fb2b4b36cff8c1854d1b47744997dd1b4eaeb494e8b2b260ca22501db291fcdaa4e83c1acc96e2934621afe4443c834c5139d96182ecafc14f4083c857070b412569d0dde5b2c04d03430567cd73c58c0bd8366388301da140f67270745a625bfa19f293a94fb4d7ab3a0df690ed47b3b74eba310d008c1c50b0bb1142190d9ea41a2a4ed2457621dcc1019111cf8d41163b7de6237cf88b350c74764720915128132a8232d320983064dce67ffa85c37255d556b42c24935b79f69b1728bb1a71cdec60bec5656b8e2af8797d26423988dffeeb1c525b08778bf082e708712323efb765996309a18434dda9a2f4a967cdc11c94080893ab3cb0ddd3e088dd5fffe13d3ee06173da5547a301a1789223aecfabb6301b092b34f8b790f7600e0a91937f86596bbb12be1675c00f6c8776e6e3a0324f4959bb8aeb0210893665a73b05144f3d0279891ed64b471bda9751798b8d786808bac0058482f3791d319f667b11b29e0d6067ebfdbe12e965a5baffdf36b9f64b144595e8db33692dcd9e4026756a8a4eae7016ef4d98ae72dd5a4342d3f3a9057cb3aa2c08912114bca5a848abb86a5d4e5901126b8c4b01057c2dae2c3b9d9a1bb168a823613fb14929e2b3ffdc9ae601cbcb2882d80caa8283856eb3d2d2f87b059266bbfa91c1b93c8b18730dcbc7743d605171cf75e39983361fd6a71b9c0f0696ac3fcdae554983f3f86cbcf854f23aba7bcda47559d5f86d0b61552c8dae1071a10e5af486a5080b7eaa0c358cbf2c5776e0363768345f5fbc592f62cf98af11bcc6bbce8ad2c3739d64a70f1e035237a39994d86bc3b333f28b93b9fc7c3a804ac3aabd6061d6dd801d695b7051d01e5bf774f93b7ef376e4840bacb8188fb175941b248027d582d70ba050752ed7d57b5c8cc9f09ffd291d24e13cb83f703b2697b2aaeb0bbe509d1bfa8f4bc9ec78363e8cb1d78f71eccd6d4e29430e3131de483f26762958c0677e6b85cc3d4b4352056576c29ed866846a50c26b53300b119d4c105cb20acc520be40a66117ae1026b77f70a1ed0366293248b0917156bdefe715a4f0ec08ed612eb622835404a669df3f9c375345c3807f1b070db423bf3d2446c4dd98866b8cc89ad572b81abbcb2005a71a4a5f649bffe0f8e615d71ac5b23ae4195111180784b242113c793097a0b9f3a638904ee289145f924a327126f4ea96123a46f895eb8166d4928d307fd63ba15de285edee0eea59f0313dcc8f38e27e684f457b47cf77426cfdda37edc2c4c2da77d4bdaa651b3c66f3d4f71c74d21ad8d57e4a52509d8d5f0f748f7caa8156e8e4d09b7d534a8db70e72e04a7e1d42b3f49c20060eb89602060b4a00da8d193fd059f4cf9e50e01e87a23bbe93587295f18a0b47bc143ba55d6f5a75bfc4528dec2b86ac3608005e22d09562898d2c914381d9eb41d12dc9312236d052858a77dac9abaaae6f76e3cf1ff708b0e948da9712a5db51409b6ce08e37d51d9017b2f5f87e5c11fd6469a33868973f4c22a944332ea4c5a7d4edef662c0ac1ba609970394562e90d3fb672a06d940d14a6727d396093990f5b99615dcf823bf0e488ae1bdfcf371a2cc3536616c0b42c20a4f656cf77614a685b9251a0d6bfe8f40653de5de1d6b1eee39ec64a2f4f6ff2839129746bf3076a4cfef35cb3814ca88192d38358eb78a861b2b0a7eb6d58458ddd78cfad399e6bd5a8399e15a600b03220e74cf9962314a24c0756a592208f4b15553531dde7b446c062e23a7e6314b55aa6c444a206b4ed34d9d1ba23b21f1b0e351f215741e6e40bfedae83ad94c3a521e7fa98cf6754036cc7b4537b83347908077ee4d9b759c9386fc41abbec1aa5210f35f1de9031251cf5f155ac46c6cc835b7ce6a35a60e3408b9547def66fb283430a1c2c92e77aaf3b2db8ac1b4d531a822a6ce367cd71f8557d5467bee9546cf8c3cb674fe240f155b8ba235a420215830313d5033913349b8310207ad571d2f3b31da5125309248cec8344ac1d9369b3901f15407eee8260da52f0c583667893870f23cebe8d8615dbec8ff50450a09cf53d63ede7071475b2ea5731b9951f8206b98f5f037e1657903fae1bad2267c982b828d28cfd7f3c12c1532b7298438aabaa3b8dec69fec006b10729706eb46e8c611dca9bc6509cae1ed6364c30a77182733ed2ab7ca274044810c46774e089e4fca8448fcc0b81613e9074a605831bb22ce5fbe674a1ff795d68d75bd3d219d9dff28f4796c29a2a62a3b6b2004b105cfe5d150c2b9d5f41a714fc34b08a0e5e6a4505e5c496801d5153284d1d697b9024e0083339c465423442b603b3afcc56c21607a6ab76c31044c4ad7de23b4ea747157cf54d964d559b7e4edbadddad4f4c922a7f20d72441019727328d171ac82f597d479b22037c1d6ceaef735a4558a10f4daa26e9e4536f1fffbe5a385195e64b77f24175875c26aecf6d6bfc447054073ff35fdcb9f1aa9081dd362277d861c669ebe27805c3a036c94f90d851424cb5640a0922cf3bbdbd26f3ca06cf0367c6c714077d014a2d5be0aeb498f0ecb8d13a5f8dc8dcaaee55d917e5742b8cdb7e9f558ada1df406330e4c03ce90f5692c5c259ca2347c63c13f08ca9c85ff0980fd55f6de482982752dccd9176bde2475403e37731486a09163cd80a6784c7c7c5a7323eb8cb63b5ea81df1cb5f635d0e6bc686550523b9ce2b914c7eb3511d9cca76a84a598b7e3098fb8381ef59380ead5a5e4ae42007ad7cc9160c240748d0c56ab5f29edca8b088ca9f9d5f2af2ab0fc8e20c550109e76777da49b238cdd0ff749dabb1b91e850e418c22113b86fc42656fc44978eef44e3fd013ab0f80a32e697520345f3e54800d40b343dd8333b2d22b51bff7f0788320bf325ed9fc2c9a242eb90c30143095ed586e84d3a6482f6f01ea84f9489c12841215d8e5bc0f0186ec61359a95541c47351e176ae1548fc80cc8b427024858f7df009cf2a0484e927e7b6d28c18663f779c4b67252dcef4f0c67d97deec10380f02d2d463a090a3d496e0a099868ba0c7c5c431c077f76bb3740f8d831170b9e0e00ba8d109a6acfcdf59ad35d49040a3e0993226129a0264db9f7f415f98200d0a39f8858ea5184eb017e706e14dbacb84720ef72f844595b4506f3de62a58fc8aeb12ae706518f42f9558d048d02c3d715d3d24c2c10d31c3e7109c91fe45efdbca02b8f832b22b0b4d74b153d43807c070b7336c0a6286dc8a184360ad95d6dc1201f4df11321c85214c18d6342873a96398d3d46d78f687fe43d55228c7358f3b99e1ff42f9358c42cae5256609071d231fa6db3a142f7d5ccac9fe1667a4f83216da6d332a3da5580db4131f4b0c55d363e7e40a830a2e5d13278834d33aa7cf4267cc25059dd62e1e6e78d0f807da9026ebed1702f6b73803e10849945510ec911d8cb6ddb618e024cfd60c9ac47c77da6ca13095ab46f10267f426d32a15d83bce36e9974556e1f54b9c65981d935850cdd6f05892521fe62104d7982edf82c0a5d51253002e1b0938e0511a23d1243e0f3499dd27e6610f9ec96901da2b0f2f4083baf4e77883996814d8d532194675785f33937e5d3ddef39976cd60ea3ffaddb6bda320cac3c2a60bd48384c618e798715ea0da1e8126168fb8335a7874f4b85e8dee96fc1479c6bbde82142821f132c14d8512df3302fd5404bb261dca235e73f227b39c29abbab40e04ba79e205bade922895d0b6c99113f636a76ea59a9c3498bb07ce9fc4a21d4d12608f30fe5628978676d9f5163af38a57adb7949a050e1dbd399e699e91aa62c9254de11f51cbe61c8ea9a6ba0874a474701dc49811197061b5ccc44541cede508140cfcd99231f58d3cb8dc52dac6a1161d892584185b525c591b51336b9381a8c65d6e3fa2880b763e4cad3ebe79914fd3f2ef1c356e1684b84d8847a0b763a137582733a8d3ba8b784e99613a449f990b48aea1f05cb984c16c4c4934c5290bd517e37e14fdc67232bdad09c39e456559ba6d828e272d829304041c819f9a5591b92021578463e8dc5b47d0142189e5ced641efb3c7577387801abdd4d5589d6ecec92aadf3e9fb221a46ff842c7091e0f744e12da33d7baa3a4d6c0781e1e64a2ad868994348fc37bf2b5afbf8f0d04800263d5a7db1bd27f6f1236b27964ea0660e3a060e2afda34efc29eb0f683eca59090a2c3912cd943a7e77fabeb23deaa3be774c52a80e8e094b79afc25f6d2d6e45ea66cc5fea6c9e68978b61cf4ff95e6b109233ec372c5650d1f32b3100f08e123a323216ac88b4c6fb4e1d52e4e1c7e4a485eb9adcecde8c6714c586f038142cbe669562ce07919397169ee21609e0611ac04d4058435138d63aa5d9d638c836eca3c094a30dbbce346318d0a9a6b1b7769dba701417db7a1d91db94e4415b6e37c24078bb82c0b7635a668f22717c615b169147e9770887da3c710881ace1e5b003c35601d80ba43d908247299b139d3849817057bd8693374737a0e3e1e9e3dcee4fc888558d1e98e97d4b0cfa8d84579b7ee9233123d99909f2e5a300a0f04c19d0b3643041482176c8f2377f45ef8c4aa1f0525f01fb1994a62f06f1c2c1dda90905efe5d096beb708af3a7fe4359c85790941d12f68346982e7271bb6352190c2b4a3b835e815a2cd5b6c09009a81379c029745240dfde5786081b9825f04f7079ce441d508f072174f672e63ef44410a84963991093970517ac597d8e6f8bef255b8979e726548bd6035178ccb08d31fca73724b63ea7a010463528d45e185d1e51c04b8e8e62e674a5b1d41ec5f3c6a097bcfaf225f9f8b7ac0bd3b2a016f5a3e8c2a544d8da9ed683d9d979bfceaacacc1063f2d3a09c89b3d74425f2bad7144906ef643222e1c922191fc161e2d56c25ddc82fcca07735859bd1c3c05788c5d9be60180793f0b28ba117f1f12ebb1d1b6a889298445614cb7d95475d5e479fbd1f015521580bc4ec66e8aeb09eebe09124ae8efdb25b632a01e37eb0ac61f93cc953558e3fe182ae394bc0305227ce8202e6d88b288d26418dacb465e8e2e6fc89651c67853f3d3f2a94224b2d24a2f016d43a0b0d69edb416deb457c14a9b409e7da440cd8e225ade91dfb5f46984d26c8e914c1829f8d70b7f3c3e0b90e01081a024988580a51216026f66b1853f032c625828c67e50e10aeb16fa7d56100d1460097c90978dfc2807efb8e0e76fc1816c1b12a0c2fc3799189a5f19012a64d1e96426700ace8945a8df624f659de1b0b1402a809432ce09d5f0a38ea182017cc592fa4043ecdebbd860a4b993a15b098cdc26fcd9aaa77c883d84609617d9cde16f3d61be26d7dc300a3815dc8d6ac660f29798eadb1e647f439944fde4562fe075d43fb83f5f5c2fd3b845cdfb15cb301fe57b55c923009acdb987db7cf5877cee34cff08029987b648a2f2298fd514f2c721b137eb8d970b0c74426dc0537508653274064ff9e26b668f0858339655e26d31e8835ec8c0f69690a6235c2ed26b35cc19e02d207d077c171bd1ee6705531603d0af00abecc1d8c2032166cb83f8c7bb866541d927ed2b6d8cbb3600dfd7c203e07fa6f05ef7057c9bd53063fd372df3c06f07631ec325c5942194b67e551ccd4ff8e096c74f782f1230698bf5363b1756efb23a69a52d1e648b0768977efa5cf1a98f03647d76f28b5a41e8a0667b44d559878eacbb5cdc9f623fd309a66eb596e7b0549dbe182155f66233f250533e68aeabf7e9bb9c2fd52cc069600375499db2a17e7dc156f9b8351fe606dfea8c3e67b615bc2744cf652bac9b5c13361c093dbf124c8f919d24ce1904095edb892543988c41f285ecc94308b615ec55102aea660971180a0c2be8288095c3d99c3ad8b960cce4769777cb2b6dd44d062faeadde03f13bfbb4b48d603006d6b46aaca6283aedff164e65b255603c38057f550feb08fa3a3e732b2006c6f6f93cacafce75cbbe71f6eca188c2ca5e7c6935ea4a5527ff1ff9ffeaf307d9ca10b04a23ac4716c63fc5d8e44d4c4f42fa592e218103aab8f344d0257300d12577c69fa246ad039ac08011a3fec5730f0f253ebad73a6b9e990de62e63a369dcfd7894e02cd85b43b2e332022f825812488a849027e9e917f9648fb333e368e7d39202a2648889a6016c9bc3789a705444d743b842ed10b26a64b8500525e70f2e3662c06dc35c60223a2a62899bc5c220aa169209845b3cedf34ba4003f1f24df2d81d74f9ff34e9d8e9f1d27931bca1dd062af6d164a38c708dc4fc317c4793c272bd517884baa0080ba9dc54a3c1c758a91c51b428a53d35b8d1207e1516af68ebe5b45de5b6e33cefddd3ab066912a9b2f6c79b00ddff4cb4c726ce3cdb68d0954408666c24e01600e7e8a311add1039dae6cd8071274479376a4863e7018d2493f96e8e1f23a39e008d05f9215633a1d43b225ac931a28fe06ac749acc221d24b845621bd868a6837435c4713c452f16940b619e26c7a9b16a9a0fcadc34ff04fb081674204bcda0004b048cce931751add43702058ff406505350bb0dfc83dedc26187f35c1e3addd00a84453b22e122c7f2a363af09fc0a43ca9d17c6b2ba97102deb622a04556cb0e92209dc8eb3faad58faf92bc85480f39d2ba3190f8c6524c57610722d33982d45652b9667c2c3cfc2776d052b7fa8140b18a3b99acb5338285d49421c5f74d4874beed6b2b61801d535db749f068f321fe4d65c47a65619cb795244a05b83a7d5b412eedc494bdce81c2cde1568275a82077f411680904ae457736becf20c9e2b2479d98c4ce80c49601ba92cc42def25173d42d4dc4f7ee9523c029b6ec95a6759d2d9ed71113511a5edc8413c6f0404ae2371d92f75420c097fd19aec479774c44283847a495c75352dc5989a3a5cd2c9b12f8b338621b138376cfd6878441edf85b70ea4b6c5854a118f5cee3b812473522589e5bf689da2db91b2ffce520c5c96140732584a7263c681a3c0f5e4d2773cf3270aed9129cc9f84b32804de14a7884d1821e89d56db176f7fab09514774e4e6256a686d47425555d6c63ab2b8991e2b025986ab0a30daa90444d17055f6f765d09a8f550af64342e2542f48e1f8ed1731f48c0df1afb732bc96a9e3f71bbe359537c80da5a980bcf5b49588cbfb3b3398633a92c642b141b5b63ab09ebcc0c122d490851d3d64a7ef07ecc15e4329cb792188cfd26919314bc2b70c0bbd2cb47109e6d12b7e8b1843472acbc4f91caab8488367ba4b427267e889aa49f9847d8082d8052a67cc6a79046b1e1b121d7b8ad63d83b9f21f3570c1a323b1d592310fa31caae1e133fdb31b92ec7bc6e5636d923c20e4b091c02fb41359d9eedf9e865f15535527e5dee3debccc49e92231926c2ed511b53d99b24985bf0869081788d11913b9c882420b3532f23f2eedeb5c44f6a31318829b21fa9cfdfe6d0c2a812892432ce84cea84d0b74535802d3fcf9becabffe48c23c5dc3e8ad2b259801e3e1fd30520a17a16f637b5cdf7087e01a388b4cbee4bc1995f7bd93032001171cd80109c04852c499bac0d799e93c88039cb47ec1050640f32cfcd2c5d51f5049428cdb2fa251a25cac0e1544ee2c2fa9d329e31ad2fe3162ce61c38cb08d0ce3739655f85f51b63de31dba1849f005533603ada1bce0cd42c204ffd91fefacaf972292b8b88e4474d51fb6dc807aecccbc25624baac9fee02217b61fc366a2c7c6bbdb2f4b69fac3b0277f1a4a1859054b74ba12f7a0dde6cd4b38e7634d7e18e86ab75f48f40858e6148566aca4af76d393e7e5ef724dcfab3641e9f9b3fc4f719ad494ff8238f40144798321062830c46e70c4140004536455250917ed52242370b305528b35bee7c51b2db68923de6b585dfd25801a1e6163e0a617e8b07c44db047d34ac85c2f17ef8d148a0932229ea911a0a8efcffddd2405921c771272f4b827fb44e1068b22c490029319e6f345c5bec8eadf21359491ae8303a1d555d2c159625d91889872aa3c841284e6a2662cf82149a739fd9a7b7ef757d0dc2f5cc384746aa3fe49bf8ee124dfde377704bd36322f2c5247d4b62a018b7b11b21297cb60511ee5df24eb92d1e17cce88b82028be1d4f270fae8d3a9adcb2287c81e18d0635580d68541ef07defa10ce1c177ff81491c49fcbf290b57531f5a70c36fb924bfecb3c8fc8bc928b855d0990983f887d319000748419ab1e66a93e436c40261f14b9502c4cce8f8bfeaeb001be50c559400ab6e03e7a224ad1af16c2bb4b6ed40080ef3c7a166a92a7be8dfa327845bc20ed73539f082077336e57073adaaaac61feb1344a8eb6f8c874bb02e9b3644a1ef1bcd9092b8390f2643423fa3cc2d1785d8f6bf756c51f26c1711f64a967030ec1f55c099359478234caa6fa26d7483c360394639bc2831fb3e5861a2756333201677611bc732a663684e2110d1789800a3c0b499ddf2ad816fa8b90b061ddfd21b1751f2a6ffda61e3e3544ee0eeba1fad4757b9301e604dc2b4a577d6b13225c3464e851387a6025d41a8f3d8bfcc32a375677fb83ed5553a6ee6f9acc6e09d37d830624618f707262aee5faf35e17666c18b4a129fa41fb4e0e6c47b73ff05d700a25532ca0db1b0cb3f6679787881b6aafc173cd432f77cf87cf013dbce6d7c1f5b91439b23efefee52be10572221929fbbf5b593cf3e494b7cef7524625603e43957ef839a8f26df972189f4413a88593707ac6331af23921b4e58b228bcb97d81aa40227090fda5c3a1192d2192f12621c1fb0b570235b3c90db73efab1211eef2ada67fb75495325e84a570a3e55f83108222aa27b5a014b3c6064292f8d986047403211cadb6400cd41c25b5209ac7d8fabc92dde3d5c2e2a4fc856818e41df09ccf8786a4012155f7efc377081fb1e66c59f03cd52d8ea51cd5e4633f00c8bb23b7031ab01628e9e785848954fa03063a1c8cac509cb9c650a14c61e942880cfc873e64fac21087e1b5f02785f946ee1ded14023bbe8660dcebd3a35d00d1686c1944f4aa2bacdbcd1351acda5052051c6e63aa05bcee64cb203c158eef563afc7f0b91ed969420645b95b8b5e022dfc21cbbfd7347a64398a6fbaaab12de3e849d3b3c65ef83b788c8c700184482e8122c704fcc8f7523e8bd431c139a193aa84ac713068be0bff84cfc9f253a111eccccd283a279a33f566569089c7a1ff2b2f7d81898f2811012cc7eb5b80a08f36c9f6b7ea0bb7ba9e847c77c590f7f23fcdbf5bfce307c2d5762a0e9062fdb20dcab792f8c49252e573caa9734b05a01873fa745c172be13fa87c133816196ef79e84626e67cf78b454f0181f3cd4c9b192515f26022544f52c1de7fcab890b643034d6385defab23396c5fb8e96c38760445372b4fa5b2454ed7adc81daf8f05f7a90a88c06fd955111019e0744caea781b6418d0cae15109be1e77638a8f851cd191ac8f6d65f1c84e609b6d7444b5d0c44972e589145c518f2be78ab2cea144045e2ec03bef4ef527b728ae703e04df1357e8a429c340d888c1e70219712ee6248c217d5f499c62f0e4fe0291fa6c104fa43194c598b044c1b7b0d4c48290492686731b8070891843d945b2f2c5ef3d61c7a6f860b6b0d0a4d654f8429181327ca06824023194349063bbf1e38e39694f283e417674a249d67139179b61fdaa03aae0e530941f19fc02496fad87f241e251441bae9d918084540bb6345f2e5143093502dd12aab47aab0001679ab49c403e952c64558f06eb1d361b0f4dd30322a833bbb58503b4708a6f5a728de5af6d572474a06834092591a097d35d9100f804307aabb2084df66d815c624d6c5baabd2bccc6ce23f8d6beb4e0df13b981df4b6c1f7ca9a4238e07960c1d47bd3e99770c034824d602d3a8d677a017e5b919b0be6499278988374416ee6dcc095db1a475befe80347213b828be91f5142424c29cfb11412a5e26b24d32d74b1107a3fb46b7dc5a823070971472c4c974f95bf7befe9c7e302e5faf92151f559638ea7566ca3b4eb26460e1951c169c11bb630ae9b025a49a840478d39482ee91afb0c0fe212671e1d0a278d30b80a16e722d288980adb24538a35ed79a574d3fd317619472413c39e4d991692104ccd23a905c8c76b09e115b1c3118ab4bcb7a66affe96949cfc51ad91312d085c0b11e702c76b28898d3756aec4d4770d6d805f6a3a7914577d7c41e2836d681c47905af49ee422a8bce222fb93087d4c5612013d87fc7d0f6308ece3f16e21a18135e241068e4ad70241d18e5c0d46d4c94e8347860f535f0ee71c09ea161288df04d0be6813c3c298a4cdc9c990e81d8051481fafa5df30bf65a6b0b2163008e9c3fae87a292c072ef3bebc92cef734f95c74243766542330a0174c93dad3e42f498793c232a772ee08a9c29ab85b2183605b7e08d48448c4fd74389fb232a22300d83140460013067830028c8812066d3ec8fc4b7abdb342a0a884611475d0037a5003e5a006ed00657660caf4145166f44e1bcbd57b120d5bfaa7dca595804ccf4db452c874c0cdeb4ff57b19c781089e3247137baf804959a0bb87e444b19d0f96fe866ffa8f9cc4fc62d982132f6de4f2a4ffad9a61ed0953d4d2951486d6503839b980998d0fb2f387a3996295815a5178e503c67783b425d211f158049b2596cca97efb9291da578529c87650554246d1070ba05439a6a8fd39ce1c5885802e8aa6fc5e7182c3d4d2e5547b0b116a4519e90fb6f0c2ac2eca9547b9342ac1a29330b78e663b6c7d028335d9b0d53034a43aa4de964e934fd59dfbbab0e1ef8f1a2bbd47f6b23985878b50aaa5d84e62123db8deee4044293d653bc40974d8957602134a114669e71e39e876afc5d51324369bd73275a24cd69b01ade8b1e0ebed04224029732975b889523365bb892be0c6270b81ee5a99616959cd619ca06a08b0286fed645a3eb77fb6fcb5ffb7ff6ff36bf3ddfedbead3fabff5bfcd57cb7ffbdf964fdbffd6ff363e6d9fdb3fdb7eda7fdbfeb6f8b4f96fff6df169fddbfacf6d1f7ff97cc3a6edbf1474193878031eb6cec7c9d6388a91353c8a4afe636b6616b278a54aedf35658dd297869429d13ca07db100eba3582719422f5ac21f2458a7d44ff273a1f57a33715f186840eb58dd6ec2107eb51df5481f1c6c051fba01c6bca377267e97aa2df83aae5fcaeabea84c1de8131c0a8fe8c6986e91984df18d09c9a897a68c5421d24c228d9ee835a158ce9732d63ad17685e735c2d20964c1f75ed14a347a33fa0fd3c2c8bdf36ac008f85f79b22950a34921657bc8ff96022f7741f77308fff806ba4c164da342cab4712ce340d8f3866974ed70fbb26c236f2cd819c394d585866eba23fd1766ab7dc573b574d4b3361e9562f6966cb6881b7d49260bf7b9a256f7760fb606477d36512520ae750a4938391779e4220e6d8ca034e83a041fd9eee02c79a61ea3b0859e3297e98db7b5a69793d964144f9aae01e86e642c0f8b030f11543c29c53dbc6ef1a0048812e8e0076c6df79ea8969fc888bd97cc03c87d182fa87e667704b54c60319e297da3a2879e3befe3e3227b0b04c4c8b51b8a74864db1d76cea1387e05029d5eeb91d058a47c8a0884c513193e4b5f39f6eb221aff32c8454cc5b58022cbdd7c32d50cb92a640a5dda2e45446c01ba29487bb7a7df6936501f55406cfcf991189c419e6c17c010bfb10049d4398dea0fc89cb0569b84c2314e54cf4fccac0e7f40b0311f61d27c9d11df90d9a11461d1ba96ab6228964195c29c36c7921fc44535da599d99573ae85cd4c8c5656f20f3885ad5ebbc60810a8e9920b233ab7f22d44217c4036a9f9b886080b57954449d84018fcdb322046fdba7332a75e8d6b05a4c14b9bdf3171a78ce8458eea321a4ab2ca12ffb15d4f56a64fef04c6406b8c82cfd76d60f05f7f1a1469a8d088f05d1e7f4aa58d0c149b0889d2497f260150c3b4d4f07f246519c008712067ca38900f8ac09984d716e21cb3a3905a91983cc50042b99bd70d0ef48789d4609f1caa33cd3930bd6431eb026cf7b9dccae4b7cf4b77d634bb283ccbf6fd204563f4f7399df96e8c1617275c4812b3d92c4ff726be35e92f32cbc0fca2027d8acc37944f68d72026f80106c3b82cab5130d13e7fc3d45f48e5680f3f376e5403ac9b2f9c44161373f425f00258832d97cc43c3bdce29c2b351dd1973ac235c57103d69e890e81ba8171dd6c5f69ff477b186b8e0dcaa41ed1e5725aa649bc2cbee96ea510c5d76e4a21700bffb565d48ba162c649a11b52d43b322c0d08f7bd3fa2991141b000faa38ee445990761b06668018de48d770a802ec0751a59007e1480bae0b06ae6cf3c280375419ed69084f16e1545c129089937368b7ac13e30f69f155a1cfcae4f6a1feea025f1fec1f7aa830364a943e3e7378c09b6f4f899dd4545ec6b0b4c6b97fe836846c3da1316007e2ca1b9ba00b2f7bccc81fb0ab9d8ffea3a5222eff16befa56a25cc49c41f5c96b3b7dc6c10cdfd04bfa2e5d2d1e7839544be52e5a623f7c3fa09be92e5de4161508efb83515a5d5de62cd858ce5debe4b722d3451ad711b82b206ebf9f3e46394b3328d70f7e29000879c6af9f49816dde2ff23ba7e436dcee186b093a65cba1e3ff193b123fe5c871077256b919fd1abf8ab607d1c038c4a861f73ee56ad67f68850180f82d972b02e16a1259250713e4f98f0b5da6a2e9a6223994e853444e3bfe67b192c829bddc3a90a7cae1db8d31cd9ffb9edcf8da67db51751beefed17b147da5427388a04a49f20258c0981f44e62f109c2a07d13d33d1d5c51508de251613fe15960b76c6f3b55fe47d0994202eb3cae97af699750c418f48fde10a27258c041ca3484a220c4875b07b85b159e272b0dd413ece28a06849413a70502a4eaf7f24d40d2105ef0b55476099598204e0164e484420acb49a72ffaef25d7c9a0e9f9ed0c7743055538ed9cceaa79923580e4fac0e877add0d2b25654095952f93b4fee6af31bf8a9c4dd783985ac0889b8093082566ec0905c7a6229f0803eedd4c4f71e468c106d48348d82cf28c25ece41ea180bf7021ffdbd9aca54ba831ca2b6d1a1493c1641ca3c270e44b1d5e6c152aa8ee42336c694a5232315e0a843919692d242941bfb71530f1375c1469aab1e542cb51ccc2c440b48959c08e4dfc4206233c7d7281ae749d91cd0341a1342321dec016f54cb14373c6f3a9b3e32302d487567759346b20fd30fc3a9c5a02149548b04c0a4c26804432d09bbf3106155b5b1d447d12483d25277929ec811fa75de152153e666cc4f096f72dbab483d40b3212db953c398812d88e560df998d70b2a38db9c7d897c4068634a37ae54172603285dbd2ae1e2bc5cd82d589209519aef2e1ab0acfe10306a81d087bff9ee594a5a49ce35ac0930165f7fe0d8f3ff2982a08aad342b85486e186e3c6f360844c2478f3e64aa654411125c6cca04f1c1a2641e509a425dd307e8302944fa947c3cbff0878ff9ce27f9b3c4c0fe05df489f1d261acfc7642cdd834fd871ffa9ecff74018aaad783c39d993edf106f18ff8e1a6cdbd0b9abf7ae67b5c644703e9f6c2a5660c90879709773f89e446f5c6b8c316ab2b439b89b868316896a0f43e25a670394fbdaf4edb53aca078a02ed03eeb2c33f7c79eadb10f7fafe0d973686bf1d3ce8bf5d09c4b737a210fa9b9ebf528dc61502a0f53059a19f88e60084e8205eff334cf6fe974b081c9cc83a12bbf658faede0865defd037b1ef92093700395ebb5fd2fc765474ceb43368ec85d4ab0066b2fe2564cdc2c90c1841637d912c65e18925996c7f107d78a52dda671ff040e04002c5e30efb44b3e4a12797d8874e09655598528ff2d1b743b74a3214a94ee01516954055f2a8fef7e2eb10702879d0e53c0f7bc4790a0386a6ff481ed8bbda5b69f2330a94bde15cfe11e811f427d043809fe03f1232bc73c3c866bf6269a360cf9020db048befd49bcdbe833bb42541a127182dbd471ac745f0f9a256155c3ba98619c11d3b59d87f4a19f19cc36a5497c33f4f479bddd95f491ff50b7de5ea82cf569760790d5b8b171de54bbb2ead3ad7164807bc565d30625dcd3189e9f010f650a293a6bd8037b61f087ca10dec0bf3aa84c1dfac40fb240be1217c5977edae81b8bc94d7173913fb96d042e458ad2e493330a0d50b9e4435555d3619b6a231687d6981fe58c617050d4942961fbacb41027b8671f231ad3e381e2b1c36e06fb7ba59547a9f2cd44e8e03f7a8f2408fc15e00e03db56902e2577830bc4f076ca3e474174f1ff6b88a8badf0262d1ec8ef97a20be35d47051d4dfe556dc6ae1465a45fb59c83b05940b3fff211f88688e73829a64aef493de3924622f5938e5472010d8c47bf80170c93f7a88fa8d0dcc6d02da128782c52f114f5a9c2964ffcd74bab75d94d963048d08b25600c43ac06f81375c0942e5ccfdc958b4ff35758e3258ea90f06e5e6bd9ca4de8be55a5c4ecdac470e65f94322d202aae80a3e329aa8f5ed3906850112ac63ace3cd1ab71aa9433a380cb9c0764bfd479f8e15d3c6ecd84b18f3990fc9c9e649939e9a783a6e226cb4bb8b4f063ddc265a08d4abbc7a2120aaec50b61116db2c96a9b2860634c79b0c3e64a5e9eac6df80bc6d64e8b9628953a3d1a99ad125d2ea91d69a92d91e3c196fc2ac835d45e25680f752793295da5e12b153d262f3c837665237a3f400e039e61a775e7df40e050d0d98e9ec19cf9e89670aa5505181ec7eba3c4c62f41a146a9c12d8b5095eb8ee583097f6343f21d4ed0fa86956433b552073c895f31c73cc25478e73e73c772e72e594738eb9e6962bd7b9e8ab7f5afeda7f5bfcb4fdb7fc6ffff176877f9b07dc2f4d87b17018724074750da8562eead901f0414351ba3573d44a20c2ed70555a91291ef4b9dc19fe407e1ebefe305f7a38a6f726de43e270440d96c87c9bd6770b7a56d04688566f0502772e86d750b51c744f2c6ba6d668ff813618e9315491e3fabacccfe6d35b10a9f10c134cb5af8bc940ec494b62987b0e1d5b79919fef3702726e4f1ffbbad3d025a756ecfd6a6ecd1a6db01cfdca3bcef1a8a63a9df1307c627fdab25703b067fc061aa6cd2c2e80170d29d5af69bf4b66b800837687538b2c4a2e6b0f2584ea1319f841158cbde94b5a48b90486a7e479ece59b0a23a2a99a7405660bd322aba4e6a2f65f3aa4e304b61e997af14040f836d0e910e0f0d070787d209ed6e98a3f83437d74cde02a2352e2d9a178390b0ece258b2d18d773c611353ad4ba42a64141b1ded450855302abf945da18251860e6760aea05e3ce94462d5d3fd61d4da677cb2b8dfb3857176bb061898005fa3965f2fb4be9594cfc6850511c162576c64fd5490e0f088b12e7b75935940d040f585f7af5d611d90f533a690ae362a34f20b546d17fe484f8b80645a32803efb86a0aa34a354e35675488550319ca282a4629bb16f5e5317e8a62df90fddc467be9267572cad9e09b6da4c2a59286380928e0fc58db8d70d1d870ca195b88d812db4d49d9201acac5ca07e025b6d722d6365263a83ffabf8ce731a78251fd3d59684f42a9f2e4509f74dcc643f1e24f0ced439e1623bd0e81450c26ac25b134ad7409bd939183895befdcd9d3db8f692b8b86cdfadd169604adb6a4ed2e464be132bbe8b3d8cf46c6f9fc9bb4789951fdf4c947d8717e00e5c4d58fa2c8205f5aebe213f508b2a8e7b815392d083b7606f6d630634b9541d4e50c83e6eaf4b9e117ff141e3dc2431111d362e98a8d8c927532ec55ca6be352084de2bd2fb60ec0ac15f410da5af52ddb5b556405976268028d21ee611459a465e82dfe34fbe0ff9bd4683d458e234d5321fa79b9308380a35da09e004da11e2787e1bafc4923e6b53dc4446778d576d35b7043b524f63d7fcf6b9d65f1dc64a0920c752768021e1a8bf9ac45550fd799952229b7f94fbff525f8766ad646a58ef06c09f3eead8d0ac0120f56b96d7e51034cdb41aeee47225a5249dfda28d44062b6a05d86ff04172c11543b0076140268159a976c1d87a321e76f15d19b7e650ab45694fe96f5b936d9cec9ca8349fff91c7993b4814b802a136c7e887d9f3eb27308954f80a9bb90d3729e9ed486f2b3f19c9ed53e02fabe0bf19cbc04cdedf4e40357aed95778c99d5e151952b3593a9fb8c8f4afb1154e345a2941a8a8f93b7471ce41879ff2b83f61bec192b8fdb7c6c6019e93b63172936ec788aa8c0848e4e5d82a77e9ce1cbf1aca20884f7d0724b47823b188d1efa854c01ea3601315eebcc86fb10b17265a4c1b28e6e9be5fc586dc2d7178cc9f285df12a571be21ce19d1c2e51918814810bd03a849f57e20cf4fd3717aeabb55fd1cdfa7d20a20eb72708bb41f483a4ca4c5e3bccd7f20098e8a107dbd1a11b26b1aa00d8d59417ae9a5e0a9ce5888cfde66af97ffd4f2fbf741c414185a27b226d3ec7635bd7f4d4ea6b1176d302e70bb0969a606d9b1d147c7a8d8f5f1ad2b6e7480760ac79ef138dddbea8a1f046d4adf575ab2e79049ca0c42066867c7f3a6a056895d3e31cec877333a602b1a8197e11d57e6f1e9391cf151c69f5dae6197d155ce60734f366ea93fb96fae32a62963837e8808650b39da01b9089b42f86564d8d95f07636b8a01ced89a001eca8f052ef667594783728d0f1af465a231dab49a7ba514d4cbec4041b4e6ce5a19d8b866e7b4902c9ce6ee45fc0a9f53e061415dc6a959ecc19a85f4a29dc53303eec976bfc15041d175dccacaad9a5f7ef9e157d431cea5298040abb41970dcd4b86b9c12ddf19eb1cf2833c21e7c265432c30ac5e9e1c31c8e8e2fef63497ef7059401f13e87526982f8d95b294deabc446b71e673656c081572680329528e806169eb45f00c11323cd5395e809357e943a2b9f119c34406e63fece0db1ee31dd960a76eed5bbc6191b414ba8fa188237271fe2733e7a136e60e30bfdbf0a67d14bd00005438bec43e313f13feb9b0a27fe13e72dc7be1cabdece739972cf3a3b2315ec0e38e8864b2d0db490e670e021f870df5d3d1287f1460258f21970a0710cdf2583f4d58c6e6a38b7dcad391043fbedc88fa1f1a70483e531357309b8efb02147cc32394b25d9c76b6c66fecc82eff91127a79f59ecdd37d963a6e1e58327a3abf07db04684ac9358a0fd231aa00bae9441b9f445cd86711e770ee08b7d211d9cc6bdd6b2b410bdf2f9e2a6aae6b9f52b4e0b4557c49aa621fbd6c5f930552d6fd8e727de21fb1a087bd2074f05a11c403a872a6d8902bdae66a1a6f2d9ce82abdc9ed9a2613d76fef51b4b2c2582a9665ee46bc2649be0a9de00c843e7eed687120aaeab786ca1e7b5ac0c58db893d46edfeb0e03fbd034d604938d0c96c8fb8ac4325f8c3e06c34fe67d9bd755089e9bccc4ab541ad2bd1170f7a207721279870a6e6727ad0386a725efcd0ede1b3fe419de8a486d88933a0c38e444b2c6f530381e46213a2a69ca6493055670441285ac6531b13f336837f90f6825cc10d65d8da69cab3c77b96fe628ff4e05c946cc0bc6b389ecb56245ec28e411255bf992c3ca517c2e4c3656d3fa9b9d872ab2402e197cf4675d232b905b0c864654e9b1f4bc7cfea14df9651b29af52419988399a80a2ce7302d54f201b5d168c156b7a87f0ef572dfe5a3943c601da3b8cb66ac2ab10ad55bc52afb7b4db734e2e829a5731fbed789f9f9dd38638433013600c6fe2d64017d128f6c024bd3fc7ede0bbc41bf2be70d70bac88db45dd8bb43dc94eafb153da010251ec1e6a31a1062e85227be33e8d7e6b768bb2a12b5954fcc906f692f044cb8b0659ab2fb3a87f1bcf8aebea437e39454f62ad8aa9ed91ae1a3d6ced1c8821570b49859dcf4b361ad4ad1d66c76be4a2d5ae7505b2e7da5580a2d574e64d8a346384bae937eed4b84d89315f7b95be9b73971c5a5d5469f269a73946c49fdfdef3147104d4461b7e5df7d0e46daaf2b293c10d7ee7c35d4454a5c950d9bc204e1da4e6086398d3973e2d0c59f1d9c04e82d667bcc4670065909713e612f022eb19fa14f0fcec19e899ca965d2b5a0d9cf3877f6fc1041ace49d23f28e458d100abd313f482c20efcd1fa2a5f7b1efbb7d75d6b5de81eda3cb1fd0d9162d46c3ce228e974d0cf6d69a963cf73461a4ebd2d04d8f0e1f5c6e2f018bdbf2d5b43569ce34689490c6ee364ba80b73a94b72ddf1968270bd1d69de53daa137c2513e8fe2b10bb598b2e06550467124af56066539ac4fb0e0b1e1580afc737bd75954689819acb5080177e997713d97f795c6c0bead8404f1ab5b20467633144c727634f74622332bd0132fd64fa7d5b5e65ce1cbbe676edfac891b207c817f69517a1efcab336cb46873de1d58b80d6c3b1963798b64a010a43593c8a37fb7f886822feb02f0cbe7c664de65681b3c74edf5268ff64a9ef764bb33e1b9823adbdec6bbf060cee701df62b09bf32193d99299b10baac737516bd4b9df07ea7acbba96f4738e213025cf7cc241e6888fdb9c58f0a64cd8d43defb19e91f602452ca7ddee75e7531db33557d488ddfb914821561169e7ffbb8ea571db5662df42502696659a8e5873de61989236ea4064e44d26359b54f8e83e7e719c7416b4587b0f722ac540ea118acc4f3011987f573b53410b5763a4274afb21d7d9129962aaa969cd45d3cf45930ba6627bdc40736549b7039c7d8f19aeec035959cefba98347210e91a369bf8a474bc8ee2366c6a0873b7ab5d9ebfa464590c3a3950dad902e140a9f86039a812f4dd78b08e0afa6170c72e79c1a4bf13d8bd17e92e6661b0dc7c9c3273412a8ea66977313ecf8c9e4e2a673a21b9cc3f5be9153e23ed0208d48a5080c2dcd0dd9c6adb5b3640f9967d409f199e91edfebcf15acdc9ba43952eedbe43f81c5f924e049524ea018badaa93fc3416ab49648b10025b23a6f3d2823ec9c9c497b6201ac74eb33bf11db1b5f684e83f49216584e423cd5ae12a0cf442130210d1b749b88bdeb8f695fd1d4ad7ffeceed3a2c33adf14665257c86bd95d8cf02b3e500228e118c616d495fb63b58e8129fe95c98d4b572075f0f9022781ef82578ab09739f8de7703d09d1433021c84ea70ef42a6aa425b90bf9f13db8de7c4aaa9657f9f44f0620d229754bc18fbe8e142d8c7e75aec323209b9a141a2f95e3839a2be293f44ec601d031c0a9338438de200cc91261d24a4fc6e2082342b7acbde7d4ddc3a6b716f151be830040fdd09243efc283b96ba3ecc476e37f2242d5fb97fdd6b538fc9f2bedbdb26b8100ef75108bb4e011cc077469c0472b3de82baae50d6fed0609d41d547a30b80b368d27c40e807c0f6dc3b830c48ebc4df71de09671b8caf8c58bb7f39eee44ce37c9f93750e000fec2030125742e085017db480331f813cea1969d258d0e1d6cd237106bbc25e00e181c360b634ef1b0bafca9179c1323d4c6e502bf7ea80acef45cf26f87a20b24ef4c1a94e72e5bc756a7fdf4c182601f8f2c0ee3227d614aea7909c42d292ba75060e005ba2b3dd4b849398da624eef768fadb66842ee9152f561eec1b2da49f006c240a9f9403a948ca2c5815af7831366ea95829c0fd0fee55d82651a1abfdda5a37a5240954c50fcc367a2ca7b611c436e5304edb56d310844a87993ea24925becbd21eeadb826e743f457194be5fe928418a96d0948acb0c386a081fad36e440efc9c2b304b368efc426858c525b2951d017877d695a624b41cc9d324476bfc2f39f760d50afa9452a17faaead978886923cb08e721695d42bf41092a372612557b5c7374a5bea554bd7b1a5e9c502f1786c453ebb700b411c1e305057085ad630b2f50e6b1d20deb9a5e9e06354a72cd7659f26bb734a2485b97cb542b40196acd1581b3b0012980639f2afdf5005882cc88a44ac57c0a33cbb8a2fbea1d9cbe558dd01bc6041a212052df7808531d6382ed2c79006f9e7ecabff84ebd8604c6f34f3755fb1af7d9a43490fd5797e2e7b857f04ccfb0f5ccb3bea154f5a2a98325382528db48bab7a10e812f513036e7f2ca0eec9bf3a0028aa01b7538a7e6c0f52bc5dc240f802ec596cb918839942313a76df3fb087743f9ff802a1f11fd60a7d4d119b74c85539d0e467ab1dfa0091ff35da09173e1d47d89bdf2097b701aa49bd66ab917690e69053bae5bdbc52d93d3e7ae9745cde1692bd0f327b6e84905d00391c18b041309f09bbbb5e4ef4e68e1047f70ed3911ef038f461c244136708b7af88e9cc2be6c6de1af52e3df34ff9ff0f3289daea4e979529202529115ce82e5a864765220419cb71b85e0f02c3c25e86453c71ba610f8da1953eea08449b71e6a898e23b378c63c773a0d2f6b659c1ade62c96c8b61b9fefb5a1779fb0512276cdaad5f8c9b1a8c026ba29cbe6eb7b142874601f2915f867e6ff1b19688b9ba32b9a2311e8b135548a18066d8ea897334388f2c76b41949130b8e4ca801fd5a0e7d821889fc5bfaafe66cec8ed67460e2ac521bbf14bbb01ec84ba4a8f526132efa7e3d2d26912575329ad33a71263d7b5c740417e1f833e184e295876f498486147259c38cf2f6047e487ed60f7cf23cde4970e10b5c2a40b96069f486d432eb9c2b2fe1d98a2036e156c9baf7cfa93149e7e282447a766945e89f720d449681b5434ed571010af0a7eb8da71938f617ff371d7b2b5c252c2f6ac7f58a0530851bc06ac5da885cd480bf973302b4e03fc390a697161f9f10d41aedea849d6c5faa60fa3b46b3d5c07cc2b0801f9c162a77aa5b58c6201057386925fa96b69d5b5e784a7c434c1e7ce35a497edc55e18612fec7228e6b23f059ada4497132f2fc4819e1b5fdb515200eda594bc34b1ac3bf00d566c2ad490b8276589c61aec0d11237003f827b022ed2570037c17bc22f753f336db226d2afbc10e831e6785d738e07a2d970a3b589123bde7d9abb1c2d3873f66ee00b88ae8d2b801da59642b3735506cfcb8cccb02b8096e65a3f8ff23791241fc78234a6d03b00f96bc9ff1fd574928f0151f69ff05faf8e54f87d9ea2b97c62a41638788bfac69614f53c5f74b587c4cb12b8980ac79e14e6e7fb1f79bc5c668afbabc75be378bfe302d9dd488f42c781301ea854910bb30778a00b0814225fc1423a44a8899443450d51cc9304fed0260c41c2e4809bf85a8a17bf2f4322f229f4487b2e941410c619c65749c9bf9f1074411b430feec23900fb6643a6996abde09502f780bd8ed9bfb19acda7a071b369ddccaea088336c6ce8a9c7c7812ed037a251754475c42c56a13cad8906752f0a91a51332b6042fd34b7e9f8b125b514c950a193b4fb9cb4bea245f2e22153489efa1f35f9561e73b51724c70cf9cd7d57e1b8aa1478610a6c61d3c46435de7f3689fffcb1877b3278138aec2a6fffb4fcdc078df47b0c5ed9895d1441647443e6743eaf05479d24ceebc1d4d349e201ba99a0feb616c1e63be584e9c05c8053277fe4536c81bb4fae0c107d0de3d3e3a56c83faf8a96f8094166fb478e756612397c407fb8550020b20e2e6347ecfc8000cc37868023024fdce9671eae8f36e50864560a9bc82dcb2fc8cba283e183184f4efaf855f9d7838f8ebe34df5fe9d14b35bf8c490756553a8af22d584436fa8920d7f497c7ffe1486f09b4929185e3758805e54162826abe344971a988b9cc12fdff9784ca0e46c24730b2501603e3000c0413d944a32dced712d5f374b5e3002a8c98c3b2bdeeac27baa280fa7dab9367356fcbbc384377c8b474084fa41efbe73c96a44bef234e3020d54309901c5034c473fc4977ce4fb7ce607be083edaa584882f7023f8ec9b6833e613ef9952017ac57867561e6809b51f94cefb3ae9d74f7117f8b3a0796cfc2bcca1d39fbc853a42e875488b9e2f15ea80cd034883f1aeaa87813586cec7d3e12d72b03ddebdd42d8ee04e567b0df31b3caa831e5827c7c0abde1412df8f89ef6092e619541a001fd87d93a3255bf4b467ea6e52b3410ca4e8a3ba3d3ac66d2942f3ac5a29169b21e7c0e772a70bd374ada7332e832041ce30753def80e4f75dcb13119ece8d55394304b2a2d153f879cea9fd911cf11fd8fa352134f1cd4862e2e204862b80896fbb6b0a1dd8694be493d6904a151ee4d437483fe4e58dc949a4e1f9d6493dad93ffbbcdcb251c1e2967142e9ea3cb144628aff2d99225fbf57f91b16f776e31be53ca3534652f32241b99a4b661270fe31044c6b33ec53b0dc025245b227129602e0bbacdcd4b1e4096c38d969ab38d039746f1559979176e1a46cfc019eb82f0a097910bba46b10621c7d21466c3733729b95b332060f340544085a9d1df3c46f709b63b42862cfb1a8faf8ab448144e113ae4610b155202f464057e20c7ea1937101033a90398e8ae8e3aee6ccad7869b5a8e656feead63ac2a80a5675591957579971529ce11e7f806b2a54a1c8f01cdc836bbf79632a53618e019aa1a1f4429f8716f98d7de3dd6a7797ceac15bbf7ac6ed8a2e3cc860ccbf03f3869faede81ee8e73f35151e97edab3796f9b717e6673ded9755dfd6d94feaf3cea25b7c7b09f8e91aeebbac96d3cbac6a4ab35d2684c1e9f7ada755d576bd795d9ea02eafd6e8dfbddffb40ac6afd39d56c1f87dfa09fa75c5ffccc9ecd47bb78cd86a148c5d7fdb285d5bf3d6db7adcfa9dc8edef33bb7501f3865da75f57ac076f8fffe92718237776fa75c5f073abe7fee92718e7fdb4bebb56d7b7c71ee7fc463976281366c277e76d83f07de2c86e5c76e2708e21366d1072f17b10ebe9edf16f1cefce1bc7fbe4e2f7c00fe317c7e3466e41411b843b0e168c91b7de317e0bba0e7be1a7608c670ce33e8e253663209fc727e18ed33b86f137fcac51a58f28f5566ab97f2685d7f518a23143cdbc957b9a6e76c70835df9a4717d4ec6aee445b4fd3857bdfb7ea10c7a1780793d813752c8aad55b1765ff775f306e3a953a73cb929ec14ebc247b12efc13fb768bc4be93d8887d5b65c45f1827f6d895dadf00bff4d3e9bedf096f775ef8f8b739c36ff8f9eaa7eff7f5b7ad6b646670b76f320dc3cc0cbff54e32335865c4f0f3c2c7563257bbfbddaf3559bce177dedaf93b6f7fa1281ddeda998d46e4cecf2f0dbb4e2bd9512f6f8d244f9cf78b444dec7186bebbad6e2ce73e75b63e5dc6f1739f23799056e8f3452a974aa4f39873de48e797326f5d24d2ddc827e0bf71c243db3c4ecf79275966d3dbf8657ce66c34e6576fa39e718fc971dd77fdcddf60e386ff8211f91e7fbbda8e91c118deaf62ecf1fb234f4c20f6c41f5a62226ae2b7d813890cc6ca2a07db7eac37725b61a4f1e9dcbab17b8497dbfac24ee40b2737f28595806eec6e668677c32f2cf7fbb5ea0d6fbddf7a7fbd5f2fec34c21986619759e137acf7fbebb8a1dbe3f302348637fc8426c9deb2f0f6a755466cfdfdefebfc82f7c32fbcf5ed577534a2549265366bde647d628f3d3e8c91dbd5af12e932f7726ba6516bbd955a5b9d2ecc7cc5786975f7d705687cb4e68ddcc80cee13f0bf8e5a239def7ee46fdf5fbfe1fdfe86c6c7d7f097fed2cf0b50a8cb58fefb47e9fee6f78afb4b49f6e57eb9cf0bd0189aa19e58643076776be7d73f2f7886ea4d96d9dee3fea7d168f40cd5b3be3befa356469cf7f1cbf8843eadafce4fb2d737f2fe7f52f027fcfc0274e3df7e55f16f78e1ad991bf27ee311f975dc46a4f3ebf8ac60dceea6607ceac1328eff9d941b698461e63e6e23f379018a844e38ba2ff71713b993fb9dbe99c827e0d6cc0dae7e5e80b71b77d2f9857c5e80c6c7e7932d3ffb19a218574d1863a3b75e7e2d91fbcbaf2af6e7d1ef33289f80fe04fc573f27fc86bf7c1bb7fbe5cf0b507feabd6e8623244eec6636bddf2ed3afca392676b7d65b3301dffdbf22a4480c0b9912a4539cb712489cf8b5be5bcfb82b34636dde4ae57b99de466595f5dddb777f2b9f7a4f3de5ceeeb42ab7bb151285d88875fc4c39bfaa58b93768e6862c979d800ff8470a4ae3466edfc9ed3237c0dbf804fc58f9b4feabacfaaaf0d473f5b2fb7decf7717e26dfd5a2f4c0771b1fc5c60d7facf4c0771f83fcc95f17a031597c8cf59da6dfc75eeed64f3d781b37ccdcf0eee37e9915de4bbbdb9ab7bbf585776737cedbddb01c9c9f7af03e6ed769859917de7ddc30b302d3ef0133e0c7aff7db8fdf67f4ad9418244ef42f1c666591c5d925b3bafb3d26f576b5d5756eddf8ad61b172c34eeb88f8b85f3df6a5a9dccfac10161f3759fc7b2b233e6e68ec6f59bfaa18d08ddd185bb9b76e0c3fadd9faaf8e974ebde3f6d8f5374037d6cf77ff76ddaf970c2c169015e7b12e4deb9771bffbf9657cd825f3b2dfca87f5e0619cdca6dcf0619eeff307dec8e3711b8fc7a3f1787cb7fb27439f9fe7f97d9a59cb3fcc33e891e297222c62b8e54c9c3e8724e54e4c62e33e2291fbe1d8f7c7f93ab94db9fd7f23b712767eac3312b91f46228d1b69cc8731fcb42e95dbeac6c6edc7e336dae06235ee8cfce3711b91c67d4ceee473e718825e768145e1e640d4edb5b01124c763e01ec8b747a9acd5a88961e4ce5b0fe9c6c7ad77ecbaa09181893eb6c4f046c2eed1b98499158ef9a8df33bcdd187e5a61c4ef7390194899c86387a5441e361277944adc61c8531fa52be3ecba79c284441d6762df474f24541393897d2f1375d4c9a0267147a0c41d5b12772426eec893e9d0bb7fcef9f975010a7d24b03291c795d8137914c663b127ea508c8f3d7ac43bf6441e9662a5c620233e56088b957af9c8bcddb874f371ff7e61e784ccac10f6423f91479ed82af6441e6762e52fad3072bf635f9aeefe6e7723df0d8d8d1b7e9f17a0b11182cecc096f664ec8fbbfe0fdc21b1abbb16fab1b7f65a87ec7bc34adfffcaa90e37703aeb0ca88e3675680371cf5e0e717fcbc008ddf0d8dc1b41da55ec325ce61a56736bf0e32b6a4a9c4e71029403a3ac5e9dde18325296730616a5323545cdebec58efef6e5db05287d4c49d313739c897fc7c7cce68938eacc78ad954f224d9c099a449a385b7b9a38807e1f2adeea38ef238dc1d85f2b97441a431269a6a4b9e2fcd8a5a0b7bf7de9fdb17e22c19e91d2379ce107079d806eecdbe8acd08cfdab4252506cdcd9686c7cfa559d8aadf0ce1e0bc86cd937849dd963fcbaf11b2a76372bdd0827d688e3fe1fe7db47220d49b127d21814bb83bd0b68d489adcde3a0d833d4efe3bcdd695dba56cb0c3d26ce503c66e83ff5d1f5b22e4a07cb6df07e7796b16bdbc0b1e3921bb9df0d81c3eb868adf4d0285bb6fa3932caff986c98edbeddd7012f2e74fe410f27f209c2fdfc70d43908b078f33eee3f6b82f7f7ef00dc3f8f4674632d3fccd27cb409da87b2676a357626b5595bf15ce206cd38936d428df8f7377d3dd59d07f6db8d53a4f9bef7413699c89dd9de5662476dd641137c69e48e3e96e37f89beb65aefdd089d2c1c6089b9e38182a5e90c994555ef65b6b9017357159ec83ba7c510689dfadf47723a156d1006ecec330b405b1d168cd1b562a8df01bbbaeeb42d0d9af4236c6ee9c2bb7fb845f57fbdbfb9b1bf711ce6a360763a5d23960b9056cffdaeeb5bd6b3b17619042c32b5fce1c3ef7bb8db9eacc79bc6216759639c99caec39a7bcc29e6843ac39c099c6869db2d3e3e9fd604cea775efa7b5abc0d3da24f0b41ee364d93e8e41b7151a1fb7351a1fcb9ef0201d36c8b8e878e5180a39a8db0c6cb2014febf13826e0696d36c59e5d5d50afa775efb0279ce0198de1416ef1818db4fa2063e151eb693d369b5d584f6bd7864607b9c56e6ed12814baf71f8fcdae6d8c46e3a7463acf20edc4ef4e73828181816d34a70103060c806da5335d384fabc379f3c64d6cdcee65f08663e3d3ea6e2b3c287ef7d30a2186072d722565c577c3a1e0c1277cb731c813192a1a8d2e26d8d127215bdcd90e3b3b3bc3018daba14b0dc62578da7007e3c29e389271678409122448902041820441c2c2c2c2c2c2c2c20aa15028140a85420dc5c4c4c4c4c4c4c4ae8c8d8d8d8d8d8d8d7d21232323232323233b53565656565656b671b8c595edd7cccccccccccc6ce3708b33dbef46da71649dd70f1527312214bfdb8a448c3ebfc4ef3e7b1e930f1bb36be63496398d7574d8bbc99cc6431df6ee31a7f18c0e7bb798d3f84587bd1bea3486398d099cc6c2e4a04686d26dd0fd0e7a1b74bf5b49e86d09f67b74ddec26104b902041585858d8164b10f6e4e26ea858585818140a7dda806eb130e3a2f8dd38dce2a04f42b6b8044fe3201df64c127ad9bb8fa162ab5e5468946475adeeb6fac99061630b72e19060bb0e83afc41fe71a7ae9b9fb07dd9d4b1566b6e3e0e060fc6eb88fbfb9afa8749dc7ed056ff77874026aba1b16e402026c27d8067682a72017f709688c8f1b6cbfdbaa17b9575c45dd8660bfdb0da5db0eec176cbffbada3db0cecac4cbe366677bf83baed07bd67de2bf1fbbe85f1fbbe84f19b0b5fb74efcba7de2775bdd4105ac7ad1de5657521ea4dbb45b14badf2ee7663eabacb0b8deed85c0e91aeab0771f701a6eaea7550f8a5fada7d50dab70573daddbf9b436df0de64cf6d161ef36e0cc85ba4d2f4a06d161ef7ef7d3ea56e0698d12785aa1039ed62de069edf27a5a8fb15bd7d3ea16dd7a5aa350e8be7a5a775732885ee41aeab657ea45c9d78bf422a35e94f522f719877c5abdcebbb353322683c4ef4e06d16d1e06cfe8308fdf9deca3db3eeeddc941bacde30e0beb18f6b932e8cba233927498bf8a3accdfc138eb6c7c6ad962f7b23c46a36974f76b341a8d7be9688c213d9f2a19397429ce7adcf0561e6167d346ec2d62772f61bd5ce6b6a6d1dffc74dc8cad7dcaa60c02590293b11aef9758eb41c7454d495d8a3b87820e460975d853bb866ea1fbe5357cafb85ff2203f151f8fc7a70d1c3aeeb87130883b3eb9e4a3368cb52ed461eed39a9fee152fd3fb07c5d61f1c64f59331e86e27a0e6bbbfc3a9505cde27a031ce7b9090304890c24243c32b573c0c7ed1611ebb339815c60035b5b2492644528c0a21924a442445870d2229325f080b1149d950441c7508c9975fa42688987ca8e87dd4901ad56951cee29545378b858b67167b10c656779186a950a6f2983a94c7541a534cce98daa24c264d1db11e114d112296faf407b15426c4528f104be159fcb3c8c994a4454b8b8f4e3d3a45e8d49ed77543c5790e9b3388a7be209eaa8278ca06e2292588a78a208e5a84b8480ac662eca314cb540a8052574a49294558cab0542129c35235489522056a541e3147628ec44689893225464aac14e2283564321566ba92c946a6229814330d623a84c912a63a9806611a83290e26434c5f30f5c0c404538e04989ad6a51899ec5feefea7bf4f37435d12641e13b294c7d2a14b8a98062f0dba24e9d2e1a53e97ae5c3af3e892e1252496be58a263c9d0921c4b87994a215eea816809d152a70c75ddf60e214468509c3d6c8cc4f9a538a4f02c22d4044a4f9c6f77ea2ba0b4a4195566caa0218853e2c8d07247ca294975a69c9a22f668b189e5f0b67e214e198338258a5818a3d16814d3d364c68e28258c9ae15511314888527a1cc520e92c26862c76c4287fe265ec88520677287d2b5dac8e181e313c62786688d911b32366e717190bb5d61a1b8bb569fa166bd3146bd3ccdbb7a292dc3d7bf6ecd9b3bbe936b768140adddbedb069757363f2c86d6f28341af5c39c73cef95011bea374b0adffb86cd3d45bf9af33ce75663fceddc87733959ba6756ff8e9effe3cb1121abbcebcb715e38690ad3b86c64c0f39cef8db78b89b471931bc5fe30df8d9d5f5ba3a9984a9f4d6cda69f989b660c5786ce598ef6c766b8472fcb6fc4da34dddddda17a5b39f4461e0b04cbe90d77700fd3dbcac3f256c2f9ddd5304cd5f4dfcd67d3cbf26f6dd775ad5babb9b79c6e0e6b6e2d6713cbd9dc57ce66fe67b32a5365665ee628f2dd6e554bd7edddefaea2622e1f2eb3359f56b7e37e93bfad4d0959d76a65157f553e02510c2bb549d44d05647539134256fe864637d5d33a1753f5f977a3a2721af75e3ead5def9bdddc621780a6d5332d97c7a69899e6de7b278a25f99de485c50ac50a8f47b7b8ce93eaabfeff5b1c974be4b3cb088da99ea1706c391e91c7a775bf4f2b347e9fd668347edff88b24abd7d902763c369b49b038993c2691c96432b9e82d598f59028c92dee753ec4af33793268e6697eb4acaba2fe9778b4cf5c930838b5c312c4d6b5440fce657bb49e4f10f099964dd1c8d33fcb4fa9f68341a8d463fcbb884a3cdd81ac5d2ac8b1236adbee81082aecbd00cb781b332b36b6f63d7090931c4eed30a37dde2e3d2f955e1bf26e4189a3704e7344397ce7f94a184577458de62579aca37398870efaeae66f3251d8fcd6657d7de2f2933c961392ba7199a2164b6ac3c7c9fb9d0ea871032d42dc54aa7d5a7781df77193e536e63e6e35879dc6e3cec718362ae10d3fad1232f4370ce7c9d05c5898dd9dddbc9562639ad67cf8637258fe2fff255bfdd0ea8787127258d62e98152cfe386f652e74a51896e64358d2fc1d2b335518a558a30df88a4502ebc3054c13dec8e451a9542a954cedc7587bb9446eaa9db772cf6d09c10d6e4e9944269149641299442691492412b993492412894422914964129944269149643479542a954a241299442691496412998c2addf68642a351b12e4daa8d448a753122b77f69c5ea2c2988d56926c5ea349562789485735c9a99c4b68879a94284b225fedd443eb598cb25161616d6725bedab6655b3d9543aad75b132339bcd26722fb75289546edf26142671144a91d8b8c9dc923262ac5df5428893cd6653fba0eaa8542ab76fac445e616de54e2693cabab8b97d914d67d5fba5b9dcafefe53e1e8fcd2e24539bdcbe914fb13b4e313b46b124794b133e640e7a8c6672e79dd45a6bad95cf0ac89d77f2b895cbed4c3aad49b7b9586b0d8546f7516f7777cf3bf9b46659b9c5ccbdac6a5275716d25b17692b98fce6555936bebaaaa79d4c2c27a5ab3dc62a553cb69cdb2ca72eeb91d9f4aa58e1e9362599a5619415eb7bda1d068742eb973d2a9dcc7e68eb19e566896a675eed87c5a9b3a7a3ceeb95945a350a811466aa4466aa4466aa44ef62135522335522335f2f9d5dccc4d15f5417ddc8ec7bda1d06834cbf1b893fb0b561e93c9a4d66259dc8c5a6bad359c779fce3aebacb3ce7a1995b46850dcd5a78edbde5068f418cd2296a59914cbd23c26c5b264717bb33e4092addc7923372891cced715d9cdc48277267e7ae8bb5d654cca7de4a5f3e276464f269b5dac88d7c5aebe2ed1b7f73c34fe65e3aad75f1522b0b4bb98f75f17127ab94482412a9dc47e64e3a975a595854c9abaaaaa7d56ae7bd74ee58e9dcbe56abe686b7ef8e954badb515b9338458ef17b98f47ad7556beefabbb923bc31b8677d3a967dcbf955d5dc8edcfed1b1beb901ab9dcc79dd45ea70941b9999b6aebbdbf94faf9056fe5466e312d4daae54e6ee4d752e9a7f7f1a88f5a8b6969ea5df5dcbe75ba4d92a2d5437525eb74b945a149fdfc4a32f772e72e312d4de6f34bb9bfe07ddcfa0b3e6ee4fe523e931376f2e9f7a7901be9b47e21b72f8afdf00bf99ce08787b12f8a7d1f9d625a9aeedbaa543e934899f3ffff53cc49d3eac230ac63c4fa5df7cdfb9deeefac5d576b3ff75de8786c5a3d6178672177d5bb8fba4d0b6b2793fbe86f573bf96c229fd67f991b94f14bb595b92b2bcb2960cba9e5cc4b2cf732e35e3a8d1e1f9bca6d747f5729b7914ab9b552a9cc5bb99f29a7a4722e8f569acc7c786c2a95ef72b9541e9d3fc6fa6ae28ce62a2709291fc54b21968ccc0dcd6d346e2ce49ba4aa5a5b5b5b5bbb72ad92cfd76552506ee656ba92948a7919aaf714cbb9773c1e8fc7ad4c32e7981a964caa2ae6dc9595dbacd29d8c4766ce2fd359a5b97cba8a19fadbeac63ab3bdee768ddb1add615d4e57b9ddeac6ca8df436d7c3b4ab54ee573337bc5d47572e9973cce5532d73d552bb56cbf76a0963259f5e36a67cf35e3ad279a0715ecd6ff9e3b1d9dcdb173d5dc50cd5dbeb728ed27959de9f9944e3c4503571deefd3da656d8acd685a5d511d3a7f9b73bbd1dc56b7381b1ffea199ca8f1373d2b47a9f3add87833ea41f1da3cfe4f3a3cc332fe390a120f2d3daf5a87928d61b7916eb6d1510eb33011b0cfa7edce0dbe5656e8f73cdb4c2cc707e7665e8bbc338350fd5da965001f1eb716a62a3f1d5b071331f6ea37a2aa7841cf61a95fb3d1e8fcbe57267e38691c69d84a08fb0bb39ac4fa7ff3e4dcd42b72fecf4ff6e2e26b7addbe0369f73b3e439433f56bece67f286392c8b3969fe76e6178add70372b879181358d58c248351d4a165573838320610e0307102450d44df3f6387dd86233c7e53df7c6f749c1631475d33cd705dfedf1fbf56e3fba925c4cef74f7750ff3a3fb41f22822756267ec8844a6448913fbfe82443ef361861e9148f7025ea6f73e1e9b48311a4d6b8102fee6b176dd6412e9ca80dd33cbac3053cde4f67d6742c8ca24f2d8a5fca7b52e561ea1cde8eeca4d2d4debf6dd62689ad6e5d275fd2856a6d9d5d5d5d595c79594b56bc995a4dd43a56736e417dd2756566534f9cc1757e743b888a298172dae1d60c7cbe57269dc5714fe549c65ecc24ad3b4da57bb2eb6e2dabedb57cccbf68db1c4bc60616d5f2cf74780aeedfbb505bdc4bcecb82ebe22b0afb29a5c595acd2cae2681e700ada7f57814f06c36ad729f187ef756d2b4eef8dd755e5e59312b2b1b8981c9d2e2da322e8d4be3d2b8342e8d4ba3969696f6e3adadada7d899ae2dadad7db5b7b2c4c06c6d8981c9ca7a5ab79a4dae2e3130544c2a2615b38b8a8b292786440c89189232ca0a7937dda3062c105b6d105d3aec27bcc7a6764d2157381e8d1a86b3fbbaaffbbaaffbea1c23cb70b39ba84961932b4d08bb7680b9cfda7d61d8e9cc0a3b2b2b2b2b8b6bcb5d62bdcb2c78a965dccad0adfd50e4a6607c2e97190b0b2bcb4941eb99a544be1fbd0cb9b313b9032c99728fc4c27299725a4ca4f349a7d8ea8a2997f544767d7905e882b98c59cc39ade56f2d33d7520758be5e4bf80b0bebe9cea397c15bdbc8c58505c3585c5b6fdc5bd995f4f086e1596c9e036a082a1fdd342b65d1f757c181db1fdc1d55c4dbdb1d15f0ed4dba954ee50ca57b6c687f745b6db68ab787c5da6db5d516543aed9ef4baa2aadd5ea9d5beea1d354be5fbd352b37dd8ec344dc1df740f9ba7a566f3b6745a094ddc5dbb57956ea912faf8ee5a6cff364ca9d32bb54ffbf7416f83742b95b0a28a77c546a03a089b52574cab59bb180a774715a1a5d36aa9d915d72a1df58ffae74737cdd34ae7dedea6526a1edd9d1f1f9d1fdf94eaa2aacd3ad864d30ad2ac9403dc8a6b15bb62fb87a5ebe3cbe6d1f5f1d1f5f1fdd1a529f8a35ba1e50b13d7449b359bee55ffecd8ccd0d0ccd2cab078d76a19754f7aa7bdaea86ab5d2bcad94c31770f707ee3e2aa624e2429f3403959a05119723ee9b8001c299f8c195bab71dec69954fefaefae77796c26c4add6eab7c7cd8bb2761a67727b5c36637d56e2bcddb6ea9f62acd6ef795da87dd580dfe0fa8daeabea34ae0cd077fb6586c76535748b3d8ad36d97c50d8877c3075f76d82eb544a957270f732e7f3a683476774d4ad745add93029a6da9daeab6da82bae5aab80c4007703ec5ded151a7d86b35bbcddb4eab2ca65769dc94aa0d41dd4aa77d2122f4f165e71c4ca97d7dd5ec56fbc6a795b28053ac9b5ea97d7dd2baea5e564add53eabe52a9765b9bc09534805ea97c2ba85aba2975fab77777ad5effb657aa969aeddb54bb3deaf52acdbbdb7d7cd9bc3da566a57b77d4e9b6ca57dd83c3504892bbd37993411e07eede40d09dc1db0237b74dc91c7757e1cd373857aade9dd48e8e5acd6ef9caa85b2a60755be5ab66fbceecfeb4532af6eaeecc0fde5ce0c9dd3d78f36dcedda9e5b0af542a8b2dd56e53b5526af6ee5add817b7bd2bbea15bbc55eb17c59aa1ddfdf75ebdd61f7ecf62e3bd39e9de94db5655bec54aab787ed3bd362fba8d933bd2c968543c95b0b2ef807ea56bafdb0e25a5d21d56aa919b6d83c6d9ff4aaa5a36ea55b2d5da0748f9a7d7be3a36eb5815a3a6956da47b7a5eeed49fbe8b47f7b7f7c7f7711565cabd7aa948fea81fa47fdeb9077b795f669ab1202a57b540f97a8601d02f420ca244876ae10823ba105cb3892495a91e12364a77191af9cca08b8e1e8cc81aa1b1892388330d38c341933a66c53d791ae3d80b04888910862478344b0e73e62de7423e1bedfe078b3ad87075ea5fb2acddb6eafd42c150f8f0a28cddbd8edd64ea9d4ebcebbabe6b1d8641bbbbd56a752ecde94babdfbcb6eb557ecdd0edcbb62b7b66a26dd78d83ceddf0eb4db53eaa6daed2df6baafd23b77477377cba9de6c7377ea9e9d5df51a38a5fa6d06dbad744bb7d2e9d6064a59ec49f794aaade66df7f42add795a69de96d651fff6a422dedea6d42b8b0dd4e98a6b35ef4e7ab7a959e9a68e70b3a54bbdb956aaef4f0f8bdd5b9066162db39b9651abd9ad430d38ddbdeacdb53a0fa4ead1ed49efb05aaab8fb9d37d50eb99a199a195ad9de159bad025ea951f74c424dc256baa20a28bdbe5216d4ebdb0546928cac8183063bacc5b40adde25131bc79c86ed8e25131ecbd77f2c56e31add251574ca9747a77d2ec766310007fc14b440d1ce051f7de430de0f6f6fa87bddb63fb4adda3a39bee61b5a29bc9f5623cdb6aa7bb4183bbacd6ee1d6be0cd682977a74eb1d7bddfa853ecdda6eed949f3eea4d4ecf56f4fa959eaf64add6f7bd26b96babd56c57841db65787b54ed6ed0606ff35654a97966d415536a465202448508318738c286db2da6553f7727f4e6d9236dd62c30bbbd52cffaa47c13dc8d50dc9d8637cf38b86bb3667d523eaabbd7f0a6199aeb19959addda9d69afd8eaf68ebab787bd73b0afd4bdcf59677775f66756e92fcd66d0f531e86280c5f61b3dcd6856197cdfa51141a1192e1434976b39450bbc63d0c580dc4a0ae8aa31882ce19ad004945b78799c707483939a8116a2c1e399c12c1433906ddac92624a3c1b739c32bd0e072fb643388eca2ca4606efd95b84504bb9a58486db63b0ca59e5d4655667c72eab5334deb1a3dbeb405769b863a741b43338096f19d44ad8cb2553a2e977972e5972c23b662c017bc149d8bacc5a6621bb905bc612da140dd84b7fa1f1d6193c6075f936dd8101eedbb20ab6725f97e9082e8725179c8d238c5f460daf16d5c34afdba4bad75d6467dd4c8a400571b4318afaa3824ad8cb0f1b5d15573cfdc3f06d002661c0bbc5a06a9b6ccb082ddafa3041aae221a4fbaeda71603203408b18f9d3a7f2b3e08092217f7a0411bf69a09d3598266d5d178c2c4060da7f6fc49e4b3a7009068211208ae4491203e74da98f162e5cc0cc191bf2d106dd69326c54380fec8212323860a1426486cd040614201025c5b6ad264f0d225060cba0102b0d702548a12f9f10d9e5a04f509c509ae2d2b4174e6b86963a60c18203f74d0a928316283860a7cf6ccd1b3a670ce50213e74e4b46153650a8f1b3534290a02d4868d9a303606a9d30a72564c45488f14d9919306cd182c427c50a7742a509c1851418ec15b981593cf1e3b4d9608b1419daab05061821c0387f488cf9e3b73d2a0190306cb901f365258a8d080c15b9b1a5ad89595eba7203d4a74c7ce1c3969d080c13244c80f1f361ad1a540f1e0ccac14290c17aaa8100908d283078911d1283e7804b6e0823ca517b3a997541e75d4e266c9585c2b9f96d1dce89b29cbf498de5b05b280ff327ae900dfe572fd1612ebea4a37ddaa255593e9b50ca01490b4421a8fb031c3f0fbea77d8c6a84123121660747b937ac012c40c07d9253b42e1e4d1cd5d56bdbb84e95c169aa9addc4135940cc254d98874c99803dcba0c26452ca72e19d58cacf6f586701f867b33d8008304ab1ad94dba18c2400d2e9af1ee58a041b13e33fe7db32a00614676bd7459df3b1dbc63800661b800071b5a55713734851939060320472cb396592e2668f51db5c94f83705b24050c6366c0a306eb80348d48cd7cf55c1d3d661c5d2a78c05729981140946458201bc75048a8b2f28560655ce05ea09e9833f8f66506d60b4d4e48228051b862c60534e6e078034009051aef1220c9ad66d406f30ec38e3883ca3fbc25359869551f628066600cc03623695c00278f54baad02053d2039014e523dcb0c268d15981f8e735f721392c8b9e587291c00835c2e99802c3809bf6131e1a452eea9a2ca60f23847c06e403e9650bebaf93edc014ebe0c60310771ca3f6482e31c9c3406604a4082b91a905c590210786d891dc9da74d3439fc17c1ca011c0c9a399510153415b050ec6a56bf47adf341b72e926d8108c4863d23d7b2fb86e10fefdd2ce772b8a3cdee905720cba8ec92d64db8ca59ad6a0543b425d30170cce322846e54a78c75e0248305740159a1e4063d0ecec359e2e73f5fbe2a982482244d8ab972e7d0ebf78c93265870c182db47a78d4bb3a15284c901011e203070c16e6dedc1440111c30b0dd39724e65b214c00307079e5e018c867af258a9d241eec1db00ada5128ea3060d972b56a6488162d8240434c199d91225203e9c2ad5c9ce44264c6de8b056438054f11c30481aaf0809d286243408cb95b7056c5c59cae4d128e0cb4c191481f0cc8903c74d19203e7aeca04e3768b0506182dc9b1a5ad8951515d375f243478eab456b6bbc74c92263848836b6ae2c17b10f27110e1ab0218d30181c68c244394284c78b274e9c00d9a0c1018304cb27e58ecaa15cc58d294b7203c88cde455f280bca819080967f3262e693d56430da4bd673ad0ff6058e035e01cc00992b6b7d9600acf72a5b7dd3a5caca379991c763361adfecbefe87dd3de95e4d0424dcafd56c1f1e757a67275de0d6c6b6a6a6200d2d0a0b381087efefda3c30b8a7d73f2cde2edb7529d8146cb2b41375d54dadeeedadf68f6fbf6daf55ba16d5a9344b97dd6ae9f8b059bc1ce34add6b21e5cb26a272d128354a06ad01dc8e9ad1dd51a763c444f1ae550d520d6365d5bc32b932aa1c95ed936651b335aea6dd66a57d6a124413d86d073b45f404de9f5d9aa601ad3858e7463ea3e745d7dd06ef46c39fbe566ff4aa7fb79eea8f696e9beb222e01633e1e61fd3a5736f3ec59f91ddc07ef4606af6bbdf42af8fdb9f4fbaa6565f6ffd779eedff8f95fc32ef2e737e62d0ffff01b3d3fd34c67188626f7bb39bb41de7593ef293fd2dfa71ef3ff5bf37f3e86c85ff933ece6af943f7778ae7f9d8f2132d5bf76f57ffe87f34778b5914aeba8bfc9e787ddace93ebbc77fa45a5ebe83e3bf60bac11b7376d17432e70fab62fb172e9a7282bb21fb1bbb9ea9bcaba1ee9b5ffb6be41bbde7f7773f3fa63f66b1fffce6acff15fcd91f7f9973ce708407fb9cb39b3faac9fe95018e089e79e59591fc9b03bcfbfa3d73c83bf9aee72aecbbee7d6877c279873027eb87df353ef37561ce47b7f7dde0eceebc4422d06e32eaa215887e4ec247e3ffdbe76c48c38fccae06fc67fefbd7658f54e63f1a3f43c804f2002dc075ed5ff570cecf749bdacd0172ce0fbf8bf748b057bef9dfa76afbffffaf5cc1a844e6b73b2e8df93bfcf15fe7777fee07e4055980fecff9df7e405666a3fbfad5ff6daf1ffac85ffe3f83279093daf847f7f3ffdb3fbc95b3decdffbabf202b5f6702af75ce6e767f41ceef95938ffca39bffffed07e4a451bf7b74ffbf6d7f971892811e7b5f3ff2ddae4722df9427be08bc01f77386b391fa4dada872ee3f7ffeff32377a9fa790f18a2830f9462195d4e704a347964c381b75210165918f701672115010a922a47c3c84544d13108cb01b4048ad8a1f1849097880a206410323029c2c3012105dc0a8eb6c81944a4b1b2326589b33f96c8cde145bdd29276c7bd1cb16912240b6e84a26abab821d338c8a8d6db24c05eaf6b2c0e6ba7243ac145ef70af1edd670d76ec2dda13ee84d0296b45933e9563aa5a34eb177d5eb1ff58ad550b7afd8eab66f0355d563783c1b23dc9f857f96b97c65a08bcfa4debc68c1c201051c3d6b76c5ae9066a7ef0750748732ede974bd7468f0101d5021d44037514565e2ca13427b78770a04155c9c1f1303b4d8c0b8ccc1fb82208cdf15909141557c2c5cfbf412719873a575966310a12759367e729c2834137cf7ac61520104ba8a021901d4e8f952288e7be8e8878f274b06b68fceaab4dc4c6945499066461cbc776dd0931e88ea54c80a924b57b74bd336d602efee622ae38b4fdcd8926986bb1bc0b109eb4693d76176abf50aa2ad6ed89b5ed2a65789a69782a617d4eb361e76876de8ded469557bad6e6d756fab9b4160569a95e6dd6d69756f03edbc8ca002706a06805457b7575cab77d53d6dd86e00b7a10de0f6b5ba826a97c2ccccecc49829eefbad19804600bd00277cbf25f7db168fbab777b26e9bb7a29add7b8b47ddabd3521b381b3470773d8080665729f7adade66db5556ade568323dd03bdd9257529760f8f2eb03a3de3fbbb467703075bbadda34ea9812d600bd07784bbb3f026d78b6b96badd4afbceb25b6d8a1349b2b024140a63c34892255fecfdb6c9f68bbdf7deee0e75f704ee8ec0b9d8f69b9919578026d75558743bd8596ade161b55db705bbbadaea84eb1d707f4e6d6db8aaadd19dfdf35f9b6b7d23da5eadd55afd2beade65b53cb92efd949b77f7c5a88bedfa654bb1d389552b37bd20c596c362bc7029bcd62e3b498b8fb9837b5fcb450b8fbb5bad552a73bef6e2be50b8352efb27f58ad96ba7b0e6f66c5c962b57b7b523eedd9949a95e669cfb659acf6ac99d597a54eb3d8bd27dd62b75bba03f7b677d46c167bb7b7d8ebd652b1d3bbeb1fdebe62b5d5acb48f0f7bb7a7d46915109bed2bcb52b57feebec09b596478d89dc56aa53b6f5b65b1b3d4e9b52ae5a36637356fbba95be9dedfdd9ef4ae997574776c96ea6207da6deab40a589d6eec766ffbf8a8dbad148b12d61f9f5ea97bfb67b7f756bab54dac31d32bb5894503ab6fe76d575ca97b1b0fbba977d53dedce62f1b2d2ad7653575ca5d93c16dc73260deed951decb6c5901032577fcf5c4c8bdf0c8a057c541f0c761e89ea0e9ae25b9fb34d123fa43d0c06d1f1f954e5b35c3fbb3736e814ea7522e61502a1f564ba7ad9a8569ffae553eb329d4ee4f4b37a5eadd51f3eeccb65729846726bd84a1b16d38b88d06dd70635d3e80a840a182043a0a153ed0918833ec060e7618f44add33c3fbb3d3b2d797c5a3dbc1d6fe5dab58a2dbc1de5ea57c665318ee8ec39bcde69fb69a5d7116b882ba9566b7dab33bea346dbb8777c6f777c5e056553ad2e68a46110b4212b42727010c0d19e3e80b0b9c2ef447015713263dcec46afaf0c70a26672a249c0242a6a9b4713e82a0b7202a03d33c06255c50e1c20a9f1b0274df16e82664c7a05358960e1140730929284c964d969ac192e614489384a085bdab779f02999a5546d8202ba5611e5a7e642a03818957a75c290d20060c56a648685aca7d482d112434c58a04b847b9cc1542881f50381273e4505ed2c890cc212405a26f7ff28cc22d139c5e383f28ca93f1f2ec3d4bfca06841254ec640588a13d7a667dc484d463373a8cd071093d8ec1993b73ecd51929552f804c5962f4565c91b35430b7a1c98f28c124d78b22689219d23264fc788d81814a390188a29f25beaac7d9053e7488a063d7e088e1338869c5822e78d8d673106c423288188ba58083e8a4dc8162fc6c0d0bbb1fdb8287c529228c9c4c2c2de2728f498a65e7d3e284d9f39244395acca57002450f8a6382906888af31ba004840faa41e7f8c34b0bd510065ff32511d5ad471d2e572478944b7751d0fec4219500ce099f6c4880804bc9534ecdf90025ba4dd13269308fcc3f008991b6e70525147d60ee768864cf0b3b462d31ee04663c58d0225411a40d77cda54525395bec7c794a92a43f549aee9edac30442a9536210cd70916814804ad6e954921e6af220b11c08f3583a15430da4e374889557a547a7ee4ce520b3a986dfa13a74aa421630b02455ed103f7f4e993d42d18c2336c600ce732a2bc9834673fabc90b125cea2283d5f0e84a0a2a19551b3a868c75131549b2a2dbd318b710090d04704c895257cb62c620985858e0fe1164691298b40aa285af3e40ca43340982c6e15896201d61716634d9145134734dce821040d82103d161fd85173aa4ecd4df4838dc50339ece8de3d410b3c04179364c870b992e5d4e099ada94c9c1a852292088e26047ba60049d18247824957e8d3d4141a435bf6c060d851b181c2942111bd277bd21cb0730484a91b72104948e0e5470f1a0ca6f46cd4f9a32871ce0306124c7108e3b68294d85a981f70a6d632a9250bb9c4b6405233f56588838f1e246d90742233e582b637f01ca0f14607ac54a420472861dde60a37082885e74db3085b065222dab24a81a101771598a2cc9e11cb5247bae4a92004428b0f7ca7dc522f283179b2308089079e52a5a44dfcb600e152c50e994ea526f8e980028a1642490d4ba5c87cf429c025888c52708f4a59b111212453ac17687988d4a7532cc09462a3e6d0863fa40e69e95be4a2a364ce1d77f7c53ca4dc44f2e2a31b78c9297277476e41e08e9492c4e0eed4bfec96aadd93e2b9fbd3dddd29962f9a1f2c40db0e7636fb7727b6dfb4d2050bdc16b42d605bb0b6406d818205690bd01644172c7073736b7363735b73537353e096e686e616755bd0e6d6d6d6c6d6b6d6a6d6a6a02dad0dad2ddab680cd8dad8d8d8d6d8d4d8d4d015b1a1b1a5b946dc19adb5adb1adbdada9ada9a82b5b435b4b5e8da023537b5363536b535353535056a696a686a51b5050adc14b4296053b0a6404d810205690ad01444152c48734b6b4b634b5b4b534b539096968696164d5b80e686d686c686b686a686a6002d0d0d0d2d8ab620ea166d8bb245d7a26a5105d1b4285a341a6d11753c77d77af3d8c3ddeda2daac19dfdff56ccb8747cd62efbe7974d1024514c591cf1dc5164516c515c5f369e7ee48f713de348aca62eda4ee5ec0dd09b8fb007717e0ee5fee5ec1dd2de2e2f0720fe0ee595cae85e5ee578ef4d2342e9b46b0fda69d5effb0761b0fbbb77fd88dddd2b97bd3ddabdc9dca97bb01dcd666cddaccd0cab4d46de076ff2d4af73f74f714de84c1dca7d83bea14cd6ccd2c5ae6b6a6cd1afc21f9eff1cfe2ee76de7c07edaa7bee47dc7d8537dfa36bb366596c5f9a59d40cad6cca57d5d2d9a551f5a47bee06dc3dcf9b2e10d766cdd8d6d2a479daa8990234b36899969aa795e6d15dabd8bb6dd5ee0c0f2d1a5d4393dad9a5a54ddbd0f0d8cab055332d752bcdde990566b7daea0a6af60cbb222bbd1b6c1175f734f7bfbabb9f37dda35f03b567ee1fe6ee586fea1c59eadf9e1470d765b37275fb2add57ecae0b83f649b32cae7f6f6fdbbd3f2dd543dd9e52f7f6a477ee9edcfe6103a518badc7debcdac469b35bba302d2b19066adbc990ddd9d05760f2f4b05c4eec06df54eda27bdcb7dbeadeef56977dd565ab7e5cd97e4ee57decc12dcf7a480583e6ab6f98beecee5cd8ce5ee59defc53ee0d5a50a7d76a96aabd56c3b6b60add57eade86db54bb3dddfbc3e6697718d2dd8f4677a772cf31dcbdcf9baf61cb87b7c55ef7b43add7c526a76abdd2baed5c0bd2c757afddbd4bcedbe52f358ec2c369ba5eeab744fa9d7ecdf969add5ea97cd4bd3ebeeade56a5d9ed5e71ad6eb752be2c166f4bdd1d76f71fe35fc6ddb3de7410eedaacd95960569ab5abee9ddd65b55bed5ff6ccaeba77f6775d51d6e2ef5add2bbbb2c05ef5ae7f656a6c746c6e2dcaa87b76d2adf64c7bad4af3eef6b0d8ed59dfdf56fb97353bbb4aab5badd48eaa3da3f261f3cedc9de94d5f73772d6ffa769f52f7aa52bcada56e03edf6c6c3ee2bb6ba95de61f7f6a43b308be5a3f2b9fbabdddd75f7a5bb6777cf62b359b92e2f79947e383818bbee4a2349a97430eb7f416edf48bd7fe9b4b1dc38769cde48a78dbc09779c76075de4d6ce4177239f3670ec381aeece6e8681dcbf974e4119714be4fe0d43b905b980d0fb9f82bff516ccfbab8372e76d02b97f0b720191dccaa60e5b2e917bef8d7c463517a3bbdf8dd3fb370c77e76d42efdf1ee772583e053f4ebb4e8fcb34b273502f9dca9d99727a3f870cff84b1dcbf03f313061710cb671d12f9fc411df66e41e40feeb0778f0d6a1af58edbb83d6ef9b42a9332e204957be982606e77c3486ef729a8f76f417789740a72596e250c260c2ec60d23b97372e70d22f9643e21e8b0778c4f9c7330b9974c390ec927071df68ef5691ab7f383e830e353cfb8fd300e1f426a272b49583f0af594dd74997b361b946429b1dedb61a9b4291e9a1e4e8a3aae8f25d47c690da8bcc750e40a66605eac015472212a065e2357376bea7be25df8acbe46569abc298d12679203504e11698a6f08b24257fa9ae0db3d82720f4711de49c98dd660e6c71348d0c1b176b87c82873a5f3169c073d854f60844817237bd1f8f65121e9ffb10ea8b1cf1ca5cb0dc656341484f4833f89e0214e4f35a08c98e5efc7d8d0899320a48552ebd20e21504e3e965dcd8e1737b9c3f4a4b4af3c902f91e2d0e3d0a2524de8bc4964e1221eb8089d31f3326e621e96d476c337d4215369c911b24efc86d2e27ff147caea2c0ffa0f071229930389d619a77b3657dcd14f2942b35b183d53c52e302e83c7af9c840f05508305f4b6c7ccfe48b8d2ba866c3fd1af0d164d611cfe844e16bd94cf9b540566791cdf44b0a91712d7de2269cd45c2a08896f62e684cec3c5c6ab88b4a61dd9a83a01ae3d198a00235ec24fce1761127229499038152674f4dd4e64349464e5d716b0c9872824c9762cb4c05463005fc085d285f0c6c9e718e1e7624032f806ac471e0b00d887a063e2d72afbab3495bec4a7c667e8c3c1a953a64e88b5276bddc54e28c3836bf91c5daf02a57cea2bd17374e0a04d6162e4522c2f6e60edc0e7991ed022305c793072505881043087f146c42d5501cb235a33025652ea837f4973c39da81d6abe4f64790705449733c74ecea2e9d20f89bdfc14b0144f41d0f0eb70c9fb4aa1b24e03108d2b76926a243b42fd1501dacc7506fe416994f7a33dba9340834c83819dc31f1a6918a9e209fde0ca5ccab2b286024db7c01f9d33d810f19e0a539187b8f093dd0071e19f0c58727970d2e24c2070d051177b7ec4c1fc261b1f8f448e83b6e481d1a721b1c3e10899b9a5536e7e4681b06fb394a7df35882f08d194b780a6c3119970940997d079bf2d6e3c88094b4f27ce938cc565eebf5c01e563884a9ea18df53b91a978bbab2cd748fce3f9a4e0016bf86b93731469d39a1001ca735cf8f22303731e0b9b485f49f1cf978935dd851b010f760598790c0af43e7376b89c1aa33ccc06a6969403ebd35380394b0c0a2fe1c40bed6684d4635a2a7a3082027dda8ed7346a1078520a141f46013bb9d1e207374928ea3d31076943766f5a08e09ab78b1ce137b8b107964265f46d320eb84002a478b435355a2d86d6ff96a1ef8bc93c1a2d47799144f4af3e01ba01381c8e36e7ca43750dfa514e99998c09f00e6e24bd97c53f0faac4a20e5017c087809174b83c00fc92487bfe439901f9f3c4d0748010ea0844fa329d17426e878d91a70045928b2234e76d3460ce8118ad34030e707e0e1b25bfc44acbd55cabbc71879b7f24e3e93de23ebc5a283a1dc5117c8a1725f48f897ea8330b9c03993cefe4e27246660a7d18070178171448dc4f23f93484defc9a444d0f9785967d88faa417bd729f8d817c9b394ebc612130fd0243955341f3e28ef2434aefe8e3474fa092e4d33c2d7a9b20c67b8528a5b92e317fc4222db95301246ea5f3fc691290af911af56ed8bef81a0e47ba45182d1eaa7090d6cea9722b8a369a2b43a207000f001a8609a9fff0744387e97143bf5b40bc96be6a7e8b22fda41746dec84a282da6c2246d0046a27708f5c17ba0fc129270e9a387a5b4f1947f9c25374ee054986f114aebdf80b0b99596ef67f031e47ad4e2321a210c7ecb9413fe4ae8e16e9a2efd9039015cec48815c66411237452de4787e69bcd399a8662e09e5075506681a1812f98f0d67b98405e47bd283e6a6f951e9f186ec31968921fa2d3eed3258f4c379c8607b3c8b4edc8f1123b9ee18e53324aaf0889dbc5c41a7430e6630cf73919ba43b8061f080812832971b65dec11c03971347f82c1033eda942a2d3f810e2b592027019059e7911012b6ff485fac63844e78a4d4ab87e36a4c825a452f7cb44a04ff0038a8b22d2313f3d017a2bca435753818fd63a42c15f8400f3ba2aa363b7f47d970abe870931f840bfd8d334886537cb1b6f4809c6fba414f0ba1c639e111f215f6a8880ec5b63dc50212adec188746d94045ac9882bc3b15344eba97ec9284c097a13248ad30f0cddb8db2a2f9bb9c0ea6da1aabe01a2866e73c7e117a51ebec7abe63964c965095d213c45a1a52622438a3f1900e815b5c8f49a10ffb29e281b57224245ae24098e5bcdd469403ee0be90ce943d45d0f34f64ce2781927047169a5ac51fac47f1658a0b62081c97d106945b2a04492728f4c975a043fa6c5a24e9178214e408441eee03fbe04c222ddd4794402e88b8e3c5cab0bca93488fac3ddf2b598d1d125c2c4f91c0448b20d25563e791621071ab07c4a7f6e5e5708c6e7cd6191cf80f0e436a65c39579a221f84c7d72370b972a00d61ee5c00a59e33d2843f45886665a12ecd76e6bf0fa0c2f78302e93be100ba2ecfe0736a8bf308390cbd0e1484d720a28b0b5872e90871ddef403c3486bb34a7f2c92bbf68cb7b2a20e64b7af1f71dd8203e5722e66b40b21c008c1447a085896ea428c5d351a223eb41ff1d68e55e3e3d3db212c52e4db564670151129a00ac232382c8e19209eca2b9fc04f59b2045ded322a7bcb88d3e0150edf150f1f26fd3003a0bc9d1471092f0744d2f9f22a12ea8801e37a3e3cfd1dcc9bd6019259d97a593034111266381cbe168908fbe0f1f1fbf74a59ab787bf4fab54411fb9cb929d57a072232e9cbed3a530cd68ccdd7be96be4c24043f56c0770b85db60f3e8bcde89360520fc145260f60a289e33d61c61353e427ecd83218972b7f28e722e378b3f43c6a027d5628525fe80fcee9348ae45d1a5df82b89f43e069b06b94a9ddd6735437f97959133c105f4941867f49700b29c82c191cc64cb0fec4609c2c705d8e637561e3d968534599007e503ca90fb508964f8101a12f284b9c0b7524175c033393c54264ab9c89d202e01c614dd8503a0f3805423cf1985c62705bed05806b63ccb4b919ca4cae4ef1056caa10a21b812b90d39d0e2853c09915dc680e34e267c142aa7792be3796f26721d0850b25c004e9eecca9b7ce3fa47f7d1703eeef84153d9aef135192e7e0e53a02ff46188f7f8350f63f0d57e4ac20712abf27630f4f00d7d4e78200a767e288b953c85c4d9838101d140acf86b89d1f0465b94ee230a90ec24141efdce21f26e257abc881e33741814707e0d2717f0a30b6faf898ad843a10fb2155078f96a2a89f388e4ae25c01ed700a186ff7182c4052cd67835087a9c0cd2ccb9042179a3180a321a11448ee2020a3d8150c71fb306b80f3a15bec40b2cf9130744df01c5a2ac2de2e933bc9f74008d9868245d35e02c1c15396c500bd786852dafa2691116626693a63ae5fac05b5a4ecc722a235fecf100ec10d17fb4fcef0e4572b747a13b70a0237721c0fa39427e3458124b0e8827e4c99031e532e428724a5b89de459b1f3dd8dce3241ea5c808a02b9e80293e7e054b9e07c1f3cc7d3646e5017012641a1a02e807d12c58c6a2b7cfa265ea95f1a0e98b68f19bb11223475194d112629cf149c841396d4b00379405d423c2c0e6bb6c2d8fe6b0ccaff151fa194cccffa131f813463cfcac2ace0358407b327617be4a15a4633a63e246fcc0034209e1817a3dfcada4789327751eb0c9a63fcdf9e49a004be4ff82f29c08c5808fcc19cf292b93d14a01070dc18197cc020d8de7c836ca75561a9f3994d082e45cb896b8899e74808b1fbb8c654f2ecadc9282c43c8143d40d1d3dfd6ecde1435fa4fd11b9fd6b9d7b16ab2b6f24f1359f1b41af6e7df21ca3ca645287457498307abe00254a2e130d49beeec0a057391593dd4462e3bad8e6792d092fdfd269d1733271d41ff82cfa5e22397fa059e21f59f5b9803e3fbfe7caa74c4655c86bf031f916613cf8a08f30ddc2899e7752e5c89f1ca9e27baa6038dde09a1f914285de6109c14301842533b7d0e54930c6bc5fc950cf27470657cb86ea15542df9366e9a64153ce4b4080e95349f9544fa861c400ef84e7320a59fef3224c8b1069c8fa8064636245ce15f64cc3ec40ce4270af1977234f5493512f98d6a819b183cf5570270f24a207f9e4f4afc665af8fda3af0a3ea04a252f953d72091c30b2a11150f21c974f6f94492edece1f332ed721811c93e27a8b60489187cca1b946b2623c9728389a838708ce6c12c003d431e4133625d07aa2b2030240efa3bc395cf9a7d04b2bb8fd9717428d8494e9255525c8471448f2aa256a3cc12824cfa3ce81b6f1a5e0390032d21a74f8c820765cd15c3e8238a117c537d4210eda506f4a6611c35076133dd155c0ec79628b39b90cc181b71164908e1579f8f301917ce6cd01b7e350e763c33eaf681bc04717e57c4fb348bed0ccf3382534e5330c147d1c381779cbace3312101b9cf5001e744c52003b018e59720c6d01b06e764bd0338fed45489f3e96b92172d22fc4150705eec998e1c01c2db7f8863275fd863e5ffb24c3c4f9edd3b93f8bd8642cc67e4038847a92146070ac3f740f65479465f550f282df26f6756bc470018b2112fd2e79020a729cd01e0035420d08494703836c3056d36a7cb318095f21225c2fc213ecf6404beb205ba4eee22c1585f31052827c1c1e1e14cc757c559febe454d2e5660000e691325c70156e7573453de4882cb0f4cb9e276720efc562e725794c59f147ae3ba49878f9d84c965f2207236a5d8fe9415311e69c0d5053968e231beae74d6852da77367c8157575e541413cef82472232d36b2e1381b095ab1018d2409a63f20be8c41dcc7275934ed81fe1f31f38c352eeb023826fea22a4776c35cee7539e478801f85170061f6434f7735bcce8433a107c4813334e6947258771e83e24cc0c6f9489857e7208c1a7420ebd2824645fb735e771047564351748690c72b43c9a2c579e050faa3c2092570e80458573f212e025a32098658051e301282e78be197e4e4131ed5dc0638e23488a0b40b3fa43448dbe0ba4a41e035f7a1b898f72872b465f610e2f5358f0ba229a3bbd78e980531023e339a9719d8a81c59c089494c783b8c60b2df2c95342f5b991e244793a1ff2dc2b0501b2294a66af331e92ad62bc7089255e7a436012184b80b5afd2218a364448efff22a5398134433e062851eec692fb385ad8e9aa33e7cf19a0427f9802c3496c91682c7794dccfb08bdf3082e2419488a3ab4e55fac2b6badf2235c919ccf893f9ecd1e05faafe64116fbef80b06db178327bf27647c9213fd61e2805948573be5cea5681dba2d22c07d9fb6b00c0808957b4570ff0b033d0f88429f637dc9e1608e77720a37640e2380a67cc78e8d6398b4c88d6ec9ffb227c84fb425f8c32cdb9be2d2e1c70274f1e819271f43b5e06130bcf9aba2bd3700cbf89788144de08f889722c84e074843f05a98ae1a80a8190d5647c21b40a0d863536879b4867e009c887a2930947eb8b647732d31e0826e0cbc2600c21c4f06a9d620c78337abc67c9f3b2b5e8eda06b7945675a32343bfa3a5f854b118faaa42da233aa52197e591a1f3984ddfaa3e1219cdde8c47a03cd3783a99781239b09941a012ffa2911e8d6cc4e82959fa721a762efc49a3ad93f0b3e87d4497bee513e2dbe120e7c6bc7cab590757fb2be05cd3324fe20a4a3ed4a6caef1942e22dd415ba205380f6d37f7fc391810c03efea11d878e6137cfe642f1c4a5c288e6d1ecbaa3d9617d01f71572987b1793d1e59ec4a7a6a7912528c99c988af4f2008939e7204cf0b0ac08b0ec1a9c72bb380e91b3a34bc9423995fbe4d701b4a0db9d2904c0e6a308d0b5e01f581570d1e60d106571440f8544872ee89eec90b9970e0e150d83e66c9a87ff235705768cf1df6b67b5c52979fbc97b41024481ed0d2ceade1872def1dc233769149f153be27bfe494a5e7628ee9ac1a649e650c885f6813c911545fe84202691e3600ea36ac801ea6cb9227477972176192fc974153eea10c5ece2129fa4ce404d022ba88702f826c3c589c587e8f04ca7399ece4206453729d9102d989582717479442796ec5f3237d31903fcc28a391562aef626dfd6cd21ccfb4e2e958e6827c13380f398ac38333fab927b2b5e64a8c8e9cc8023c3f8547d2570264e85df028e289b424bcb40bc47be15d3da831fb4340ff3cd81a27afa698203b79d025ffa13429b72910e5de282346d75de9f19e606ae9431492bc55a52c3c1e4578f9d19f09f7a02090fbc1e0e4835035c868472c4f336344de8a4af43f3ba47c003948f998d740560cb4c835bc297258e0959fa140c4f174b1e38c72dcc94e42ce1d1d4968404ed0b891c00419462033efa9805726234598e1ac02c6332a4dff8e6d35922f49198f00466e214931b2930e8b5c027f5d4e8ac9a16fca4be13d666cf1409a960fc809dcebe972e6131351720c709df3e179d06a74e8f8b74352fcaa94a1679329c7cb2d393c833a07fe6740cf0db960f9e995015ea0c3008f30814d1613c0c2ed9b83e5e1a439f14e7178bd855191de21cfed4b0251969354c1c97eb6e81c4fc892873139b51904881e17c392931004e230a105daadc1a46764204bb3cdd8723e4006dc2b94e283c15874175c0777503797a9ca24b88c3e899e63139ab7f2a19733e5d1f122c286fc220109ef227af4788b5ade99a1d0d50f20e4a51383bbe5b8e0a73899a3dd5060e363acf4b9601ae4fc0103d715096417235b73d704283fa587a75d1f14de0728304dc440255f33632c57e9f27e229f217d84d495334741c80ba2a71e2a47fa7b22213f05568986d1c5813bd07420977294e1d78cd2e0eec03d076595c3d5b0e8ed05f078f3962dc1f05e344ebccf178fb2226496174b60885b10142a8f727f7c194026b4a4527d5cc8a61bcec2450107340500ad34faf0393cd4dcc0909a2f0e86e900b0687c13343d1c8e04ba6764dc931ddc35f1453146690c77123c291a6f72130f45b2a7d0f03e1104a40b75a870ad100cfa161a16b494461ebec717385d22d0f303d419a0cf54203a724eab5754597b0b7a28bddea10c1e4509070f9065fc9a40033c939b4e9f08aec5c72776788c5146321c30405e0174ef4385255f9141979c47408917345325bb90407915191c1c910ba1f71208c2ab451a5f0891396e128ea09b6aeab49a390ed9cb2473952d2bf2816c1c178c1ac40f216ae27f733afc221cdbac22fef36c6618f1c4103f7c4595500ef0088993552a92bd2442e46d56087848a048b899d64d36fbe2c46f48e2f16010ddfe8687bf3ce694244fc4e8804664e44de652c4e4caad05d2584196b296157879c086419de404e0df790de45253b87f832711f6b344c53d24b5f9ca03399ee146a81775a2c14bb108fc54940b47a00182270350f2883794fc0d507f7c4f0aac53b104c7d31838923f19dbbc8c444379d38213ce454222dff19cf3931204e06e8e6af90326245a2df02dcb65f8f7db6eda0b1389071344c28f280ce386da16d01ca0f86513676bbe041946598dc4d5e58a6c69029f22f9559ea75f23e5f3d4287832103a8d3c9405054e02cf752485d9cc2610f6dd380f1dfbc88047e58278923f079fa7474fffc130c43521153d1bba44996af19a3d71187444987ae4aa9f016f75e9d05ff134f65f88d9e71815f91d57b62641679347f042f15792a60fb8f5e3f97850fb0c0f10e84b1b4cb85b444f5f2a237cabb7cec38fe8389c1464b262033437138592ab3a71f938c438190a922b0fa542cd29a4d0e283005d7d960e2ade4c864eae12c7f401889dd086c8f8c9772e46bc14e208653163e6e0271542df16a1509f3119e04a624dffc6529c4fdcb29791cb1c5e462c2d37f221e7e3a8a0faa852a11c0660f6a308f1724a108664acbdc8dda836b461a0368733402a93f054c88dcc2cba001c8817f442500f512394c14634c9f0d71ea7f2e9c0bb47c1991382f37cc3e459ea365911f2cb634d072a31c31139107c4a312cfd1c43519e45e943de88c89c05174e390f1386bb857972222aa26e28eb7f464c14ff4bf3f78990d0bc14d69a6790c08e07207bfb3083373c092244df82caf0781064c9694e30df85c59287d4a89337ec597bc362ac0cc26cee453cfcf380985c72bd32d865246a60ae06296d3cced194c7a218c8e1ac82b9c3011bcec08d842c0acea07b3199ba2e4ae697490e33a50b7ede88109a7b3de2fa2612a99b6983b8dc07003e0576873b1d08f100c214f87371a261f498f2148c5c325ac9e03cd717256c486d2f97b0b206ef3111e173b0dc6b32c6cf000d22ade587f6545944e52362d2b81f11355ecc0d1fbfc64a993371dbeee006a6fc000912ff54aaeec568dcf01061a2b40330649c8de08adce2070a9f1ae6d020fc83ef28b1e0d9326df2ba2f939c422034990a579a31eb5a20237a11e5f584832cb7b12421afc5cf4ce00dd41b8288732f56ef5249b37f719ba63fad7d78397a691e9320a18f4928f2685a40f2b14291dcec429c2f8ef273c053487782c194d39160c2899080e17e916ab82107addb1975e0778831ea10696d7e46dc8ccfeb6af3866f11dc340224fc912839788213539f1c42fd2648be5e4a2649ae9597caff5cef7229e493cf335492358d2df1c242669e8d32c73719c2f0761c7a7c9351178d21cec84fe103e7fb0cd2e1591e89f0bf106b1e0307042eca47f32f045ae399326cf84c664cbd214b1ea7302acc4b25525f5209b707e00a952650f87caffc86ff15682ed2dafc1c12d2de2fc4a3df13bb72312189fea15e208d4589c35fadaffbc4bddfc08ae6865e2f4ec952a0cf7494e159c826fd121774df2590888cc76488675183a5adc80cfa6b5b960cd7c5753bedfb4e103f789544338f0174e5a7d12e3d2a47e2cbc10342674853fc40c69c617801ba983e3272993011f48253601ace4fd0ab91bb947528ce7132ca08cf0612a68f50a2872f5961f804a8229c08a040973043aa5d64c97bac4e6c3e0cc80cc7d0e98cbff15273203b90ba53244137dbf1ea40da284e15ff6908421ce4020eb65a4a830b8f61caa2770a06b4dc20ee8d7680a14c6e3b54f7700e7cd2609ad4bc3d1864bdcb7288bba5063c236a350f6270f2a40459f135cb3a5fabca70205d4d1e879dc44c65f8c5357377ab372ffcd14eb3521653aa7bc185b01681843bc255b3b0252bdd93de691598a199a995e951f7a4d3b205686b6b6954c0ecdf5dd5a953a70a98a25eb702d1565409227b7849b5da2a83a84bfeba7c04ba32101080894e03f7ac926080aca019590fda4668f990d18040d6179792aec99537330ce0b4466e40006b479c4857a2004f7e2eb9880b795ae9dcb52acd7370ad007747158187c566397c787ba356b35bba3eedb44a27dd4a25e45d2b4858a1e5db4ae9b657aa364dc11f20b68fae85946f2aa5e6d1d1699873037c7b936ea512a6d4adb6aacd523950b8e3eed30a58bc6b85bd3d6c8415d7ea9e5df503354b9da366b17774d7ea8a6a7603752b5d41cdae581153f9b01fa857ac06105329756e2aa5e669d0bbc3eec5e965a57c59ea56ca224dc1df9505764a37a56ab5d43b6cb6cf01758a8d2002ee8aadd2b1a05efbf8b2737bd2ed15eba21a4f9eac920f3f04c09e8ca479044e61679713976d7281107d7e89904bdac81ed90b81eba1992c687b150d8c68aa2d5ade28b08fdbc1b2c7dfec18d10c9a5ede869760d6d2f3f17c015865e7dc866742a0832fd9123f1f4edbbfe077e8708522bc5be9875382ebe44bb0d8f13148b6fc873f8e9ed3913319ec800d77a37c83456819f9489306bc618650596f43152da4849c1c63449d6b174980179ef8e2365162bfc1d9023f1449cdef308bf4534e10f82c66d3ef714bf19d1669c986d410391231fb9453817cc21f34d78308ed9101dae4167183bec8eaca4111127c29261669bfc5223fc791683074465e8c441cf7e980eae7bcf892e3c2c4651d4e36e50d56e4d7e88174172520c996a6588d6d62173e6c125c96ea10f2261c1dd1ae32c9ab4519e2543eb8f8317c669a8a163edf2767e6d79001e46cd50d99941bc07fa0c64ee3512efa8248634f67e3cead3411b51e426dbe8ed8226d37ca42c62af141a70d30a3b1788031badd75d2006839f3a00c7c8ec8a0cffb185a73d4cf0cefd44ce3ce238307544a910b8852482f5e85fc8947cc0e4a89f9195b78f20ab92f7fef70f0447b591c5419924c251afd126bbaf40eadb42773c04e0b82b4e6bf44fae2197228721f4ff07819adbf1cc40fc63b601157d6537566fcdb8293a7d859d30696607a098234b29781039f25449c3e0346c18dc0b1f4820984381c4b5632812e3acf8702ed038185704095c27e4e80fc547c3078a52f818f9582f67d43ac781874493673d2f0c44d893c8ccbc2af7002750b0b0efc010613aee9d28a3c03ce0a5cf5c54fb329b3e83e826bde9b46e8295e92644a786fb9cf9a98c643d20996a18983c7669ef20c08157ec3dd9cc690c2cbef6514d98c9314bf459496a7ba5974356c005f04a339b7d236211f3aeef044026bfe5282e4c93d03f29df11d8d73ebe35e6cf8a49d123a0f1091ecc6e8a5bf68487ced1400984c1720794bed8d36dc42ea33a141a3012844e83bbd10a4111dea78b13d61dff480e71551d8a1c3c8993a21284567a404f0cbf00a1f2ecddac769c9a3157ce8e3f195aa7f63e2880b52f4c12554d1be46a7c84d0607ffec09034dc00adad3d0afd661a849b6f281cfbd935c3edf5a0d4d64bb24b7b802d47ab657be50806816008726238e72751923652fa38f542348f0e59dc6fabc871d5e1e498c99ab29165f92a19976a31379232f47bd214af78bcc14f8832853bcc8a63df90836c9bd04107e87313817e103ef2b2198e3360e1df59d45ca4fa14391275a1420c38880295358a3f3163c3c781f3061cb7107ce349d9eaa9cd716e1e55c3df2ad5387396d8795fb45536424040d5fc3818e7f448acf4bd98374241667fccb4c5816756092eb40d39403a100723b2444bcaa0991df28cce469829afc8228047a2f9186e78270279f5a0ca0e3aab09b5662835671c70bfc6351d497d0ead19be64ab81b287b9a8ede96b7b2c3aa07f8b9e173d2d87ec19b92af7201f765d8787c12eca037dace71029da87814d7f478f200fa8209097c8190e93f038072aa9e3d1e05ca947f2e79e44d30b4b8811f7a9a06984e5f6071a9edae60644993b0dc4f6f67190036822f4791cf078044f03d29b092818c60ba825d1e5ed4e0bb68eae470162184388503a69c4c9e233e403ae4cd3038e275fe84722f833efe0519f3332c32941531b2fa258bd2feedee851f3a7ae05f69804e0680325a7103ec0e1ee8d096a0141c498723590c23003e0e94531ffa71e2dd5146de6d7cc8217da0ea175eaeb4dd99c43f9258f20e0a21791e7d067dc31533073221f1178850bda0b1fd6a801dfcd0888a47c4805176e421c72bf9c3e54dec587a25552359ae4f87bf319973ae3f3a5c0e9d956cb675bed5c61457c0a3ca25b801fe4d0312b97a0253ae32f6242360f1e57ff849d15898b646412952ce04b7e771cc616a2e2d14bda71e0f7e049c0b6d078883db558291fba898f9aebc079f6048030fac10e44f5c9972b43856323cb6e1690cca94db70d8e190dad47d15492447b305c51346ff78de34c7b708207e464187374144e2740c2db95b038cd9ededcfe5034bcc7a893cbc57f6d23486306aaf10bc26dfc550a6378f893ece6186a13604e2d12b4181d47803327d02062a7c13924c7e2789c941616d793e8b717461def4f5585192875478f3364e6c321505db39f49df902089e1e29ce46ceb369e95bceb0bd570b357ec40e15bd06410c0de7e3947b270de0e3308cf41620f397c13c4aa0f1040be40e4c3657ce9d4b5f05c75d9e6adae38ddc40d09c06297e0d08d1efb364c6c92c7ef049116ebc5505167a3347f81446991c510399974425c2fd88a23ea43b877cc18b3c3f8e9991ebf2307c85172b721c48a2727c444be630288f9b990671a573c472d81e34af18384abbb153e24dda48f05f584a7d851965ffd500cdb585147d812424ef0721c77f8a4343f319a2c599b05d7a25a4007d84d442eeea72f13938a9c95420723e2d6ecdd3d104bf8c1754af294c0b47337125930918e26ace90e93051c01e4a95a39b62ad2c1bcb8078414c00f265aa44b58f10595f9cf2e47de301e90971bc0ee5a9c75b6291a8b53aaa1c479f0efe4341032fa2d8295339ce70034556788cb1062f2686865732eae36108c9d11b3e25fd2c919cc622ee784f244cb8a20d28decf5ba28661b57d349c28682618c24c086209eb416f5ccc9983976c88022d48efe93fa8284ff361ed155182ca23df7c711b546377b264bb12487e9c461791eca24219a7114187d68216c0a370563894ad221e227bc7117d6c723b3346b8a73080df42c49bb9fca2de8092824ce345fc989488598c1a2d4e07879da7094c93937e4664b0b0079a6cb04326bc52fa0d46f0e00fa2e27cd455c040eec2f206bb42ae11ac0e4f6527c7dbe932e695685e7fe586ea916b827a069796a74165fa359c34f901431ee83f7b0af87608943ca82df63b2c373a1946f52642647d8f9614d7f267475f81e5789716a67e4d41a54c7525ce6b6404c9290119f2bea953e9a16c38e17661e9f269ac04b8a0a734ab193a7b9b3078f2263ea9c96e8620bc911e89bc891f4e6f07cdaa4d74d0e4893ab0c917e8e01f90604b473162f855841c34293788fe10528f8f8416e871e4e9a0e1e8ecfda7b7e9931191e473786a7b344298bc8eacc52b79c97e061a7bf485407cf20c5151d70b449a4c9db4e2cde10087f32821c41505010007c38af51916818f27909f1b48f4f710aeeabec628313f7167e93f60a0e0808a025c0fe2910f24e99246322a8e3b2938b9acefcba73165237fb083fc1a6e718ee5802697738dbf2f4a91cc83c4f395d891f8207fc4e42e893abc4e8f232d23ab9afd9e381cc9c9cc580602dd4c88613eea81a1ee93a6e8083c75f2c52e8d3e461021c74b4bbe2588f51c7ff04b39fce14ee8eafc8f4423341d2e69ae45ca0f5d638fc75f1175cc9bca70fc28c10439905af694fc56b8599c4499000e10ef61919147347196b9666cf1528fe86024135e681c6fc0d5e3224cee0a40c388be08f9447880e8d7cfa45f23d5c897d80df013850f720c6b06570c12c0d33970fe812d8ab4a234668e41aa46135810e6007071e5314478f8dd0d4379c113536fe299421fb152f264e21e9d55a143be50e5818be351a99c034b9e5b6a8a8a1c05550546d340980583c0e5036808bc03a53b9acd94b897b36af1190e0172158572590526b6d743e0ff66daf370780ce96cda91d71128f821dc8879335fb8b2da96275f077b712857d03f43292e93f2b1744ecd339f5267f8691604f051d853df444a7eb55c67be440e22c60505443d9c4c14603d44509e6f500038804000b41810672ea03e229c401f0a5f638381fb69eb5f8283ddeaca94e65495c8c36a3c7a1f522a7e0059c4f12431bd0816c12c89c0a0c714404d6b21153872cbc553152579142d6e6ed6a4c95f4923e8a3b860f407eaba5c497021fee30cb946bc28f213390eb85b3e270e0a003c07b3c91dd14d9adb044ac74554a5d035dce07945371e7452408aefd02853c6b381f95e71029fce20aea7438df3382c17dc0b9070246bdedc4c8f291aec2bcc932010cd11b018702ab552fa84114edea560e712357c3ce002bbbfd3ccef670a98b7cbadd3679122e6fd10638de6a38ce4a605f2f4372069710d2972f2ae1c3c1c8602f7ab6c6cb7c2098d635814a6cfb48067642253de5376e0d57038e04f485eded7494bfff5c1e47a3675bd21cfe3341c1d715139a81ee9c68d2be8f3f22293bc381e291632a33f515d86efeaef941992c96c503e1d24103786251e59921148c62a4263f2571fe3ab7738c1fbfed0c86b94a60fe8268b1ea275e90bb86993a101b6bca02a40ffd077ca170338f323a22b2fa0c24f4b62a3c59d65f8725799368f3b03a7eb64cd1c110d375d8758e54dd451d47ea2613401458bef01440ff28e1279dc3c7465b292809caf231597032fa5f13fa34cfd234c6eb41724105c43fa27b008825fc156df1a69925b20b49489e8d9f1392855de4c973bee0670501b0205e9ad5b34fe46fbe6d52762b2a00fff9912e52c07c2152fe105fd4360893f67e0809e71dc90650040caf545d8731883644e788a781f091b5e4a58d6721a293137919bcaa67c6cb51860d6e31172e7a39cb6be8d8a4a8f289218277481edfbb08b0e055a438f294bf198ace8710f3808bfc31a581e520a87270034c55f1ba6fe8d2b8c3bf000e2672ca6f11af0a82fb238275b413b920d5f46deab01e169902ae271ca207848681ec16c718a32db9610f7d04689acc5d40517899ed665a821a2afb8a24bedd83e051c1dcec585d4dbc234ff21ac3c1f0a2a7e8496f18a298e3c198325ee9403c40b152df135d34f6fe345036de58f95832235436b5be4f91c3342fec192c9dfa0f0ef282cafbf33c988aba650926cc98a13780f2fd32b62f9030fd9d44953a540e246caa3e4590cc21e4187474fa7809c7f63498bfb21f1f47336d9f9a0b1b44c2289f6d712a3b2a837395ff581c95fe979f0866ee65568c1e2a01424723837e078d61d09da0c9a42df60cfdc75c6270f4203b5231a9db45e81a50710d17a1df01b4da586826e10d64433505e792f5671798a204c9fe2c5943cc5b0cd53da23e2b14a3078d399e4a9d330cf2a83e3cf70c0f2480038a2b75e58722a34453a6f8ecbd39a58c92d8edcf8b5e9606e420af2012e59d02204649daa08608e323be5177e2c7d090a6fe6737129074293f447105b578c46d9c36903468ba968915fd44133a0b8342780a5f45f720c711a809af21977d16f188397dd981d7e0e4dee4ba984c3590ce1e4629ce6bc01347c1a071143a70278438ff142dfc34f34a740a3c7af5040f0013601f2a66286c754204eee1143c5abc12ac9d6305daf93b60139d324b42fc467c7b9007af45a7a1df9559b5bbed0458c0f1a85f78808bd7829043e656c5cc29dd26826f2527faf8984ff4bc1c7b90020e9a15ffc9e8ec215b741c3c59f11b270517d671e881c03371487c4e53c59a011dc2d7a2428d25fd4c7f767e664b7b00c850f7305e94d13a2502e838bb87356245fcca1a031e9e3c5a7f182c4b5a12f3c8d0d5a5713c6e1f300597a96ea703988727c20e7a32f94c1a7135f24f150897cbc0409355ec81d0c2790e0ed037900de82d297bfc900cabf50f1f2265e90c92cc0409d872233fa4c5fa9b774c522df81c7f2a2153fff06ba7a145484bec41506ffe2f5e12a5042296bc12bf39cdcf0f0298e1eafd7658d3b1fff7c78e3b90422e455ea0a1fa93c3e5b063b0f6a50ee3f9d80e4a5ccbe68217eb07c70c4367fca54c151b030957b8c48f1818e001d53d8a177c34472a6a8241fb7a6521e6441546e1a407b2724f9f075ac5c742747d6cce9e900ce8f067320057d2e8b294b1e5ae086439264c445f530cc4930587a0e574c9a6c4b05977204cee13c5b1ed1283f4d882a7d2b90324fc884014781b8e90bcd48fc0662aeafb74392a7b04ef02d210e3eb6fbe1630a38e5eba21d574321a8c752a8840e11fdf2660c9faf0b30755cc9a3bdb78b844d598ccd9e6b260426b711c9cdef6cadb98c2d8cfece1c13be26ce92e6b3ccfa4da6aa99c1169da790e1c3875de77c8d49a4f211532d5e1209387f12af3d9f4fd2782a49f2196a7c381b36025cc958d75b61907c3718ae34902f48f71065ee254bb3c8eb209ed288581ce43ed1166e5cda9317e3a5cb9b41d0d8a708e521abb191e4480ce5b20097d4e7a994f8684c2abe25d1227d45aac3b35245994ad99447040326230e027b45931eb92848355e3bbd3a9d43025e914b013d8186a9efe306c77d2ca0910f500aa57bd4a1f38bda6c7d9ed8989c64020ad7411b45baeb0601f8c597063900202def9724aa0f3126eb686282bc0dcb89ccc1d1f4f526d8c8648248f9941e5d59d000903781c98f763182c53ff110c6e14498e4802f967b4c92f27aa80ae9b26a985ff172f52bd80d6f208998fe3c4bfa4a8cbb69719c1c37caea5e5561a32704610063b993f255a68019bf1efa1e0e49c9cebfaa2f5537c6af828dfe830606ba8f4fa9af92849426b1647e2039144ff676e41120e2c89f5eb0f13f2d2abc1a1185ef0646030d06d2f31b8428a1ab1660f8742bd1689f74bc9c120b5f884f96bcc687275d81005f3e6e38f3cc5293b2a6c1fd0a72309a8118a3bc053b216bddf091976440e37234e6fc88d69c2b1124701e7a7ffe4be2078de92cc3832293e5ad7c48f70418456b2a23f7543fb0decea2135f2641217d46f8c99f18be1cc8da84d78294c1b192cabc942743fe508c2b2bb33ce83051007328362c6e9108689eb9a6c75857c7306370c2c9158060c59749f893c7a8297a422af2b2131a659e118dca742db238202ca5ec8768eb2311667d23eeec3fe19990532861f25d90b0fa1017423ec73ae969ac8971208989745aa5086e82509a466455e3fbfc9b6c2542a00ca9c29fbfcaf8f17efc065cc0d2009da2ba220bfa32a42978cd30a2ed89d00970d881632c1b6f5e2171432f683ed4164a1e00f7c3d5d04d710b9776b8082f4477e235e0df0a6afac88406af49c4d90bc04e9f6ad4d8cf5800e3c32402c97594b4f84f871cb8f2adc2fb75fad2055c0aba9a654f27d1327c9016747e12d2fa28e46471d7cac47f49f1d14f4971e6b707af5f534df3e8153f575308fa00b045d02de458711358d36c182b5fee29e15b14ce71159dea781a86475fb7c62aff9555f118012472b645b777e045c0374384fab32bd2cf44a8f0cb345dcad7022e320aaae6fff082f7956c48d2824631c85701a62e9c414932110468b94d96cf6bbd4d703d3039f3641d96daae4fa0bb31b4e15b283ab8123464198b1ae89361ca7aa2748d7b8171406330e0c6013844e8291847f9a740577f4aebe2abccc19a522345cf820a0867f0f4e23d4a34759b1a326b316fb8865aa7b2853bacf76d12226f34400f265c9b3a9ac12eae033217f2e0990f3985a8ab971140ea03f0c2f71f2ac17fb8c8c5016d087e8a2da83f40a351569391c93b44b97c12924e2e0883d82fc950c2a35db8f4823b775c71cae1337012e7035841a7537cf61110007ba9c7e5014b4c309c1822ffe29001cd6049f89402e7e8163e2ebd1e2718fab0cf88c7d001f1bdaa02e5735d7b74050a7cfe4e130a794d81505fc50f8f63cd00e16cac8cfa6c66ea37a4f9a233c971e16df6b0c837e6e85cd118937723a8c211c0b9a20d1c30e46676626f87417e3d8f4a653c3928f27312954c060dd0bf80b1ee5c8d505fa6a57d0369d6641658ec34da8d361e8852597e63c7c8dfbd90e6ab1696dc41a6333939e5929bb9f37a9d3fd9eff2f7438b505e1d8974cea725b1e07a849c3200757c1c8d5714779403fb1fc290c6b257e8711a9cfed246c98fe4d8a1edd45993bf6e5c61106e0c69e35b8b771939ca7fd65199ce753f1c1e44d9c5127e3380e8bc7e348c78c46d1b8de5908fc355c9d038482472b4b52f39c01c432f251ca4fb9a09dc2c09053f3146e19b6c29741e3eca7c9a62eb4f6ad870390ecdbf2142ea93748c7a1f1e165f821caa2b4a5ca28f677b72e01803ef030ea08e20e8edc5163981e51648c9240a33b9766c9465157022e80f7f834e4649f8474a7f7c5118a68fb4418d3be952ca0b1442f33800aa3946dc9767d38384cebb7bf34ee44d26d344cf030874f57d5d88fe04dfa6fcf5a4f0b540a56800a4289f0a8f51190c963a9fc491a72ce4c8c9435168a149d959c97d685ff420a44b990b94049d09ce528f2082e52e5e1df1b3b44b5a4c0c876f8932fa361192bc4887a656f3a2c67b6078f3c616d4cfe063866b7111f8b1360fb4192fed77b40a6ff0927a44158232214057af05479f6e9186d09358aad31ac0467c8326826fd440922765e6493b42dbfaaacba8cfe0a9c25378e0458f3a35e833e903c6177bc3c75020f9304ef0f8080a11de050f400e638a9617dad4e4210cf1f154d2fc3c001f3f8a4850dc86f2938e1286e9771ecc1b509d79179a00780d7456df30e6254bb13edd111847ffe9cbe21b713a723448f2fc034036dd24119fab8121bd070472190e860797c08229394920228de849cb3374c565ab99426ee94df13f8c28f0ab252e2783d2c81db5893d1952a2dc4aca84472078c6c7207991c38800e30148a8e18212697fc303918329d0c3e1e418d41df0c4f0111616fcd81c6bd6121ba2d1f4dc3e4d94026e8b2d06f2076a9f0e2250f98aa00d5eeacf875f0457c25dbecd7847790f5c6a7ce030fa323da9eaa19f9228c1e33823e63bfc21cc51aa555fe603fc679194f85c28065a8f48766902429a031c0f1773a4ed7d745d79324e21ce43c3893fa405cf2f19d0c04b30c0e08299519717e5439f00adc3c779d2f0071c81da5a2a871654422cfb8149e1e628c3c54d8851f17e37d0be4b1dcfcb357e5e891b22fe66d18e4fdac1722f6b0c3cca150cd98e80227f706694fb3122f4b71294a14049e37cd424faa6440efe265ae8c3b6d69c815c9e9c68059cacb6d5a29f2c8ed15110a139531ec447f3b5e58572e72a7725487437113ac83ab9e643a120e1432cf578b1241e5c8882166e48d1c8bb0931a0ddc12a0ee746497ec928fa92268fccf6ecf487ccab1cd593e4bb1c4af08a01fe3c4c28673a4c63eee58089fe61f5c30f2cf0a40f5d12cb742869653bb0afcc218ee2bba38ad0fbf951202b5a234a87d9720936c4a488ee81c982ebe971fefbe8c6d3599bf2921e60694a7b7dfc9121b3d7b227bd5b84385ea80aee4d6502c0e7f44cfd8c0330996dc19c0f0913e9178912f38b96a0d0670018f516d8d232da962d4ecd4aa0b196a8f21d4636f40ceb8767a266d075d307ff8d03776f9f2269b2883462dc330f6f7fe0c9d52fc5f087a304742b5cb6fc90284f8ed66575b80a22f41bc405cf698d14cf32f4f03ec6501e13008bb32930fa9c9aad572472ca432d2af2ea99200e684d20b7010a2d7361d3f292aa7664c4e3076fe2c3cfab15eca02ddcb1d2657b8c0f2553bd2caa9df22765997e613cf371e0035ad31633ef0310f6df90609d06169a756c72f31f3710b3b4ca8bb792a7c6e1b43a389a2b3ef98de1098fdbd4a7aff2940a9c24a8f44d53b5410c228410340220000000001315000038180c08c542f15896057a9ca80f14000b8a964a684a9c49e334886118838c21c81002000180004200cccc4cd506004f29c012e6b92cc7652bf8bd343092795fd3aba97bc963cf3195ed16bee2213fe59efc148263b3a1017b3f2539c783dfbb403d7cc6dd9097f6df66df040b11192e97f292222d30c8a0e251145cc3340221d0c900181eac4e34156e48cbf1462557e8a4ad479dc12621affd82a102dca98d26f56a4d0b8dadbab747b0bad5b106f6734ef62a4e5498dcbdfa9a178cc97469ea20d2f3308d8f8806b7be4f34b64156e529752be170f7b8d218ebf4814f8316c83d5ec28fe20414247b0ade4299f7e03836029cdb484fd97191d6cbb3d1cf8a19a240681ba93df156cb1acb2cd4669d0588230f33a89dd1cefdd03382708ddbc0ab73be23503f2470a66c8ce38a681852c973535cbbfc0f48ff74a0724683e30f6094922dfd0ce74833f74b7e345538ccf73a89b3272bea022cbfb3216430c086518197dc2d6906eb0c7259a80161cf055bf2f932624d5144f1011cb6a7757b351cfa4af825385d39c443ad261b315779dfe127af8a15367a1caa0b645efda0cf5546ff17ee9ccaa8d36eee42354088914d0ecc36e03617d0bca8bd0d102f10c69dfa0313e307aa9b22b453981689228d51f5371c101ce0f069ceba93de17d6ee7c7fcba9f386a33677d897f7ab35a6567fbf349e25d44ebfa1add7eaffeb39677972bf3033a5efbb7acb6ab0a35ec8bba084e7ae80c079585168074c391c5b3328df21ae1c028dd3137d8fdaf1b19cea5a2f3355ace7d6c95deabf16c303881d0045836cd6e126efa5c5b48953d416b96fd30103fa3dfbc015d38fa4d8dc422414cdb12337d1f14ce45831742efdfe532eb69b3777bee7fb1d787b81f5aede2ce01fdd3acc2f8cafeb10577cca1edc5214b175b3768a8be74d759bd72ae42c01cdb2f9f7d00850df67831b0db78367e7abd4030dd4071ebf5e80785cd9f073fb9b8a33de00193b9a9f46c453a6984effd29b43c9d3566fd0abfd5aa2efb1295c8fcb0d300cc0a7f41d086852637af9d837a632a81588a4bc1f6a8b51df309bd215a3a38bbdfa0cd84c0df7236452880689bea6f88d40f40970538ba1e0c50f4196ed016937393ae102471a8bc7cedf42e6a89083ab16ff8f85e1c8709263277372bf29a6d1bfdbb2b65ab6200d5e7cd286db62c482a380b78360b0eff600e4e7af4ead874bb0067024574fedf98749a875732d4db9540ba1faf7be5a96a7e815fc012e5feb8809bb5b07ad7ca96c77c21e5570d99d3de217162c7afadce31b23c67ff04dfe9f14ce99e9c56fd19292debf5fec251f99de6f09fa9f6726bbfae74699fa81b27a181913baf8ae311cf88617a7913ba3468e98b9dfa0a0aa9833dd18fb00cce07385910decfe7bc63ed15e9bf47ea9191b3f8323c66f32df5bde5137bbe6a5fc5f923fbd6968558a7e711ec90c3f37dabfb6b874ef4186233e137f876f63cb393c9fd616a8ffd98455d2f612f5db4277503646109e7aa7948e0b218455bf1ab3519700edaf46e6414c9b55be69cbc5f949796671994f27b96b0b288295a53625fb65edba3d04e6e43cf0e771d2b11413f8d6ef89aee6d3b3f3c51fb8c8203ff11063f3624f0ece980b7f9db8ffefa5a4a545ff4b8211113439f37039d8ee13ffa248a5393659cf6525ce15f9106285f336b8ba39cbf6fdd8f38fa6b8659cae286cf65246da5df96775e80f7dcec7f9a745fee552943fd38ce5a47e6ca14e0b9ddf1e10d5cce5d12bb7d3ba836d08b3ed1065f6fd311f6b4b9423dd5c731b1ba324390285adc268de8ebf3174580f847353f3ef80000c77b581f7af3250a4de4606988a27e68d7659836d427a379cdaf56e54f48a3b6b655fda6ae78a76bc1b5d095c4704dfc86fe204a97375faabe15f66f1fa7e5bfb6d00afbfcd6fb182c4f93aebb78ac6d78f18ec774b07abadd3d82aa48cc91b688b8c0dee0ad3f03f3f605e30611aa41590a6fdb5f4091bc860946f79ca1013a6e873e54487d409764a7a674a635f559ed5ad590bba087f89735a5dc3fd84e51096606ccc2266fa43ef4c521d920799667a369cc47f2ebb3e4f8765232b05edb1bdabcf4b5a590ce1a6a8dc9fb4bff1d0a98d0f608ae5178ebeaf9e2d60de1d58db46cc8f2612bb766aa042e8ac36e549f100c71aedddb739d27a7f0f871e88d8f02346e4d100bb8523ef097d8a9767112fb817a60e8df6f7371af697ec22a8f329b70c79b4e48bb593ede08498e50053f621b3e3f7aa860ab71b5ab833ff9991ab96e4a57026a746aa69acf6f643d8b1bca416121d8ed9099103c92b7d9b345881c2b76a49702a1d4d38f938a3b0b6be8ef8523744e1d8abef1e9b4d7cde2c60b355b6b9e98eec8aae3d8132abe1bc4d5d3fe8d19e61714d5b6cf161f2cef6bcf7da9e4d96761793546890e35cd110e19e882451d6c05ac7bed88de14227867c47eb89cceeb39f4e1a917937b7127284709d45734bccd35cf5f5d23976ff328ab0f8a3cf84c6ad8e18c9abe4e6ede4da66f05dc3846daff0c610d3516395789d51706b62380713a8a7c87e7f6471d921083b1a893f3b5d27263852dc58288f5822b97c4bc315ad60bb7fbc4b40fa07b0b1eafd85415f6e94122715530e8b853d25da2f360f42209df7ab1e683faff98902f47ca04abcb3047ccb6bf5bbd035bfb29048f4737dec2fa86f2e2bf9fa215fb33d232be326aa5d7f698e73e44bac1df3a7ae4aad135b7ffc5e974ad68ae133d74bac13fbafee955c19ab8fae94b22236dfba2bbf624c5fba945233d19303a087087c40603313fe6fb74b5f15dbefdd94bf624c5f5d96b66a0cdfb85366dd187dba596ad5987c70a79cb5b1eb036eb9556a9598fec303cdb53f19035bc476fbebf022386e4c0dfbb941fee259e346f6d9af2140c4147f42bf893c9dbe3af30e8e15bc7a05b7710f58fbdc08e81f03509d2c6bd2c16a6b1b54e12a50e689a305765310ef00e4a7c0310e6019023c6327f519f178538c25c0671e89b2c0605f96217dc6213303367a0e8c0c66e7d9791619cbaf509717a412f2a35484d71f5b97679eb9b633874e188cb9c786dd64f0f2b8ae99f725873f41be36c33f7c612be1087ebef86fa1861b466d8d7aaa7366e2c8fdf098fb99bf475261ac6e29a37f6a8de5faf5e311e1a45268995fd9fc8dab8f53ca786bed9c0bcc2f433bcaeb5e7659e93dd01ea5d37fb0cfb559d3f614f34de100627da93512f2545f0571f078f435cff55133b400c03b90e11ea4c485d5b19d93063c466cd4463519c412cb5e5cc0eaa77c80560de469d2ed32e6ad0d629dcf7e846e1fd52747fe63cc3a7ce3fb43e0a1171daeb447950ce06f5c82a8dc3e467d7abc552471c5f7a8a059f4e0564694ae8087963d181b5ed0a91e797220c3ff72488c485c02ec3c3f5c093de4cb02d9a3154f58ed3c0cff14600d12d0da544e71d0c4c578faf1e14dc3a5b6a4464a97a9d93f939d5c7553174b22675d75e0f2342c0c814637bb5a99085a0956a72bd69df405b814988611e7b5d8bae62081960dcbe4b0c913b2c2a5c42c9f3cd85d1940eaeda05b98c064f8638dcc6e113a60353beb6711f3b8d94f22090dec8f692f1728665a3550182ac65b248ab59590a19124e9544002a4650d5343e432aa8a9e8f924d2fef7387eefaccd14f338454fc613f6ce4519cf4c9f41841bd103b25c097c69ef6eed6e30c0431dd8f4fa97705debdf2d83cfea0959c344f7d3a66409be299ac7cbfc243d660adbd325d29c9b8044fa87fdb0f6df593b34cb5e75efcdc4ffaee947d2cd7a70d7f32478c0b93937ad08a0ae2dd54ef83ed414c97775b9ef7d30ee8ac891a0a0f38cab7516c1115c0efdc15138f0dd17e10251a1e63de8787c27f570f3d5e63c4039e9235a7e1207951d8b8bb1ff701694be4f2983d73636fe41362db95e52221869198d30af74ac66aa6c5b37a4ce844ff7723de6388f43465cfb16caacb4e8f8e86b718afe4d0e13289273542ce31d10276e61a60fe6ad9c84e01a4ce8314c51300325ecf3495a9d1136297c6dd283741a6e5055d47e530d5cdd65391cd3e860632621201e30fbae9e472d65ecf57ba977a2f413cd41623083af575aea73a916fb77457d3148b1f543cbdc1953fc45bf7750ac04493465d9c6e752150d6f249ae1c070590119688027a3e7e911e5d13cbdadb40406e50d074d72e8f5012422413185e6ab4781dc3ff7179b1d4ba67e925e2febbae18bcd4ccfc3dc998455f29db5485bdc8283b92942bc01919ad0e13578343b5c5d321d0241b199a2af3933522250925d142373c1ca269d3c2e48ac60a93ee12e576f0d4ba5b5c190e560cd2150d9809a521d030d9c3cc5c41820207d40a06b87029e61acbb4d7b9661ce6d3218efa26eaa50a0b310c3630c7a206de630a0c62888b4a75888728a1c7a5334ce9f85c87a9d9c72fbda2e3cd98b1b8ab22d383b1bac7b0f65b1f55405cfd4550cff9496322fe1cc18bc4b4160d1846f4555437c18eb2f737a6a1fa38687cd64f3a8a8dc0870a31f7fda62f268dcf6780ffd3a369a1fd94a20064ccf9f0f3b3e47d509fa49af84426dee9a284283838600f68c370d3b40bba5944cd182d2c864ed913dcfd37355f1e2a4ccdda29078558dc4135f5b11121424010ccbda0e3556263ee6798bcfe3303cd4b86176fffddf761d867ce659625e341f1a2ba01734148ceb19c3cde04e0c5afb6e1fab3049751972be53091fdb97c522b1244260f230fd9f13d0b818431824b2a7f14c5efd45da59aa8adadd1e8b11c5f728a4a6c0b62955e0cfb17eb8e358f5dff6004644f33218e974d1921048ce1b48ab35a52ebbab70d6a8aa3fd9baf89cd909642074b4f3a81cda8db1578c7aaebef3745bc231a7ab6d0e6b9cdd6d21cb1e3ebb612140a0f97cfc0501d257f62846744a995e00a16d691699060497785716035e225f51f9164331be10bf12956e51095c63966506ade705abcb121e4da4dcf66a17bb5985531cb16c46e92ca31eb483fbc901ad39b2f5a841025e52c9c6c00fdbf7cca7e62c254d4fb45ebb11da667d21c5699ef4bfc695e98a3d2561a1fc16f8621f032b0c31f05637354061aa4100a809b9bb65272925909969953e17765266016c7eda3962233c8405a7cd8ed754d0da054b672f1b3056b60d9dbd7832e431faa86bd11b88ed8dae93b631d5f35ca9cec3b8a773b75058d2e90042250f477719b3cc380abe07201cc1d331271da40f7138c08f69b44f4639f37e9c8462fda31ad550c5c254af6afec4774a243df952584db5742ff40ed9b6839758acce2ccc6fd25cabf39b588d7b834d88bca21f62045c033eb880b9f70f8f00f66c7d3bea6218b2d539827c67759912d301668961932e27a50904e369ce66c4dc2cb685a07f551d41837616833b681c36b08c1ca562042cf7f0706f7292e12c9f304b49e280194b496bec9669e69cc88dc80bbf674be0d16c69c4d211097498936810d050f258b1d602eb7c1965556c497bf1538a9e444d993fbb769e3ac95b0d578a8c2c839bbbeec370a98b32274f4f3923d0a08adc30ed2707d949d5b57ad86966ef5ca3974bbb23d4359e6dc596d7e7e814dd1f7f2fce56583b63497be631849b1d0d5428f601d48f06e7b1c6888b9cf01971731d0a49a5d5cc5241bc5f245445c4bc48ba889235c4758049d6e1ac326270e012ec88f6bc1b9f17dffec24218ec09f5bac317a1a8eb6bb0907486b8aaef2c4900cc7b9b919f6adbc9f42064e05aead815edd01d062c604375e0e7045d0634813f09a1b6c1995254fe34ef697ad8a918993f3b1fe40a2cfe044d34d4e9dab3a82beaef79e93e91cb326602a9366180e645bfda1672e7b3e3616633c537d076d7fd63e1adaf0b3249cb69c2edd3e91395238e0b61553be423cb19d373407837a3cce748b92df49d90d8763bed5d81a0c9841fa35ece6d7fe3dfc2bab392e713ece91aa3ef180e628cae7e94b0175d70c81fa82cf7ce7decd64e1ddb3523685719e7c29e1c8537f71e0f2a8d27525be8dbfdb5d5fd91c2299107eae6b0f8819f7ed39c07feed61589ad8a951b96fae0f1dd040916cfb85ab429038377f0c54dda99e55e4f4d967bc1351dd6ae8b22d0443084ae05839d2d4c1c96fe585c51012f8d495a0160e9f7719a7ea5997d39fd00f420be8b3c427dc21e7f157aa2a4c78b71a7d981ad069236df7cd3d96aa4d85a0bf3d84f2c90343c1d18dc78d4cc250cc785a5cc5446fa70e6195254d99133a713729ebb6ee54172a1fbba519170d765b8b79579e790f16c320d0e8acbee3f1347f1edc06c04f647f2364344072a67cda062b4848d366f21b82c966e5f563f28d988de975d416714be612b5ee208dcafb668dfb1fc5f15bf2ae9d24426d00b3be4305f438de6b15ad30df3b2f6b1c68de66b551e47eabcc9c5f30c5d09a1a9da4f67889e0b3f18edf65c6d2f7d69ddf98934d5d50d55b7a111c83538708a8513e491526503c9710dd644a5b62448beaa41583ef18e69efaff70305a70bdceae1c332251fe5878f7265f69ca90835815aa5c87eeb6a4823a351989b4ff8209f181df0d705c29ff558bf27d078fa62f039eb4b6a1edb98f5d238b6fe146ab86c5c66aabc88f2c0c7529f45ff597d265fb8de6b33bf048c89aa8c95938b0a081b29a2c3f6f83c1c65b4b20d356501201446b890c80295ef3ff3fa9fbc598f0c7f6138b35d727f310f28cd4f8747ffa31de7a2991794c011e4285026fc4149936b8e0a1c023c921008658293a7f27dc503e8b9e06007ce319cf9e4ab9390a5e5004f524716e959e86a5dbb19c1e5bc78568d32578a939300d6703047e7792e234d786396683cf660a61bc82cc43016a53d16caabab84612c83113f84195650679c82122bf8262e21bc1f40bb5c72df60f202da233a548ee6f0ea1820ba4ead746e5698fc6fcba6532223b2c52db51fbea53eeed78d58ca47cf8ab6a5d67ac6b98774b863127d3f359662755b43086e520b8f0046a63e11e949c33c34862e3d71ba6d3807161d724d05f15eb06b1529e532445e00ef5cc9d664800bad17bb58cdedff14e06c781a0631ae64e614bf0bf5d8ae1c51d8c8a5a82cb49cb5206a88aafb4c70f99026a5c60a4bee9c3a6894ae40c11a31d1dba2b08ff66a7be907bbefa101ef10a2668fb96aa6b135d15e1b211b8a46bc6f539e89f098461e0db47f1866cc511ed8cacf07f2886c28d6ba899656f773368791f8219dc94e7aa7b606458c3abbb1bd0c153dd7b4d47cd13fd23f25e80bfaa39770f19a90d01cb75554ce6c13916420942b9c6ca4ebe85e358c4b4092d59bc4360a600a97b2e8b42737580d40935bdda7039bcc2f5d62a54dcb2cbaebb552d9553c7644719683e4b6271783555ec38c2806615953f9f70645410141a085ffc0770b892cfea643156e774137e30ac39a74cd8b597f1d5746cc9ecc4bc8a45256edc8ea86997622846ca450577b91d8eab2bf6b6aa35fc6a9d7911373f6d536091f1366a13312efc08a82324d108a7012daddb446abb0ab3fa8ed4cc4321d5cf576ccb4c7ae0ef22b8cd2d3274919e301687a4235503590058c4c2c6c5c674d4808a0d78ff158970ab59b9f9a373dbd84187094631dc0cfcbc6555fe90946015e4f25c2ec1ac516d4e030efea0c2eefe832ebf1a034ce480823fbd9e70e9f765754adcfc9e1d4363be63564e8154d648760a43c859e45214076733402a06b153d87332d25890fd61eb2eae13413d6bdcdbc8595b1cca907e556fd27820673514bf936bf4932b773605dc71d0cb995115f37aa6d44b76be7fea0921644cc9447709308c1a06845f9d9da75a2acc3e251169b113627aa20b896314b0479ad0fb59b4b113c9dc30cde95f281865dfa09d90a5a3a0467ae21d87e47ca5b396cd3b6e633e5178c32ea584e7481930bb311805e9ae09a26ebe9e2aab9e43cf3a7f5040f5894a9e9d1f9216f8deacfa316e2171e4fe3b40526b86cc233150d8b5e7a1383faacefb2f3eba0c996cfb8dc408d267c96bc14cabb492fba4cde5611101cb655477dc42f6921bdaa78b6ee826724ebbb327462a334a9e3b7c47ad4e9c538c85ffc1656aeaa94651b7083e04c140c41c2089ae1b0b2a14e7a00e3f222de7bd461ab724b408b8fc9f7669fd593526f85785e8bddbe9ed4db19cd67bf4c1054b338ade741fc049510dbb2ae49196c828226c0191b1fa7f59b3d648a5171e14e1628434f4150bedc83eaa705855c749c8902f992ccdc245045964ed1a03acc2aaba36b76d5f0048b43016eb1f14bceba21ec6504ad14ced29ffeaf68aae5686543407e411981441d5965397be1b7754e3bdeb9c75b1dd4536b0c0fc1b18ca413f3394441d0044fc50aa50d10221ffa5c11492d6ba195ce138b7b30231b8d40e4f770dc768b5851a1758181f533b965b401165112013a5f9a1d4d4470487bd7d90bed65ee98bc190dc750ed06e057cf82c69247f844a6915e6e830cbabedd1d473b3b909462fec75f58d9c78d4896230d38d2ee09a546de1b0c80ed8ff6ec7d30c6258f595e92552c4c749745b0baea87be42dff7fc7c2c1548c019227bfea601580cec516d73ff233ae6143b61a852f094a8840e7dc4428b2f362a9227d26df06950bb8716717d691e36ad92b371c67587073a8d0d0442c2076ba4cbe23c66fbfda0f402c3a40e94d9d82ed39b3893d6d90a21b9d435f05fe928cfe744118780c2fc7e29c725731be2f9a24d7c79ee6cb6aa53a34df571085e5783f69365ce046bfec883099a73a88d38cd04d20478b80cce24630f4499870a69fa25b77957b13fd024c9df3dcfb108a861d9e6e0911e3ce2f45aeb5aac3870bf2f3794a9d5d2b40ceca179a3d9b10a1cc91c64bb92573714c48e04a86e56091f0e45ba996277d2f7fff00aa22aaa015f764b19eae853b27e68084720138590e5529dcb99f2add14617fe84c28f850d86aee353168753e80b91588ba68ea8dd6c5e81270e82d44a05b375cc29fe33886bc3fdcd41ef848249d3aa708ca3190f2ac4079221fc7d5bf32587175eecd55100838fe3e0b9ea3d187fc79f8f263187d5a14abf32be6e3ec3d41a33f6de77bbcb5c5e8094c47a3b05a5f6a79a8d360a968ee60b5086adca526fd99ddbafb1b0b235a94ae236c533026f4a4230e7db36965757854b091f5e139925fe9f5b1d00f2282de4dfd77aed16da35d78e6990b11cc68a84ef12a29cbc508f08b1dff8248ebd3c0393ea10435e53a99a5d46f3c4c4cf8305740c72141fc90e166201b014b05023f2a6e5c8ea372b0bc689d9173e872e903848924aa818f81c3681d6a2df87a63ff0b1f3abafedc11f186f7c9b66a27ae9e5d9101705be1f1c7460b204f09db5e09dcab7fdbbd456d70309d491041d6ea5b2975843aafbc5ac85efd3f655faf552d5506c52bf1ebac6055073ae83e305035e1b22b9502e8acce528d81b5f1ff2859055e581c0ac7e67aafee29861966e80b41d11058d07f7fc82e3060049a39b1e157b52a60a29faa601e5120b27eebc2d94b4c7b4dd64564cca81392502294f307938f94a9eb55165ea54460562c202a71f49af2e4b46d7bf8781f56c19b9a13b4fb2a5c63b6a381bd02695d505015f337c1bed7383704b49b198c1ae331dfd796c650924d1287935e684c2966bfad43fbc6fa2d8ffcfe031e47a99648d79053277136404375adfa46720339ff76ae958a06dc48406d1c8b3733d1fe093d036cf2eac11603f0d727cde689c2884e65b214ebbbd027d1c5840d3e2c67c2c872b5150b29aaa22a9bebbacec179369c08124467ba68af279d0cc10ae5691f8ba46880d2091cac2cba4719c878ac78b54f730c4e189dc17841f48d4bb0f801a6bdc622c53f8c6ea090deb4e809e9c1645fc0c91254b81cf7af476b3a9c4144d99c553eb0186744739aa015286c3cc9bd86c935cbb2fac4685369285dcd2d71f2403768a0c65d1e0df6f9f19335b5253a87a04a542584948cfa186cd8b7bf7de75b5e1ad334cd7a8d3b435cfd163507f45a8749ac148a834b43e2594976ba8b865e3f8db1f6da145689a993ae1412c62476ea7957bb9ef3036e582a9cf5faea52e72763f37e455bab76952805dd83a8e9af83c55612f4895a7f56a841bd12c66db37d1651e0e2c45cee45affc0da404a2cf0230b1a363ace89a6eef8ab615fbc30335c768dac4f8303b143e4d2a8cdaef1ed5a34f2d569619dafba33e631f5b15277e0bec9392415806470f5eebda02fb8c49419933ae8340fd092170c383d1e6660f52eeb09ba05344238eb2165646654c2b223c51170b9ff12ef595342d3a184064b5255129fdc7ac141de0a87933b0b6fc9a6511967fb78640fb58596d1a3910840afe287d31d3ca096370cfe66378602b0b5f0ec3563b4b302238dd0e8b6606d12d461ee0887f7674ff0b32c679bbe1bd1f8a9c92d6b3cc78f65dc88272e58593e6be3f21c1e8bc9c9c770d704cbe3607f60a7c0f2d7435b4e4a93492c3a7c72a0fed019953fdc22c967f53e89a8afdc7a15535c9435a10b3bdb6ca94a5c88235de82cb6ee9744c1b5961625ea92b5744d694cd2971055afe8a156556c1d06c3b54c6f357202ca2551c2cca7fc335da37faa88e0f2c7ad19eaa46ea1a8dc6c2842e1a8fab84ec179caa99b74cbf8c06ff9129bb5114a18e6aeaaf211a1c89fe0374bb0082bd47404bf8784a521a8d3a3924c1a702380bbd9d54f1da74d89091505f5c4ee7b714d8408cb505fb21f082ab8ea2e63038c2df8f2aac6d463fa531215bdbdad03d9f071d8c129efe106847522e7d778cdde8d33c46b35c264cafbf32465844faf4eb38d1b8fb26c8ab7524dc848d8a31144823b85f07b700e17c531c604cdb19a71528e374c762654281b362dcc0eec6f5b322170efa7c3d9f732b5e056456f8aff3ee577885d28432265b10ff8a287e212e4cf148bc7c4d88ba2834dd98671d721ec89919d4e8123cf9b676190e7589f59563d43f958210e52f42b56aadd880ca9196cdb45829553f2ffac011d39025150cd14843fb6602cf299e59f4b65e11ffe17267e4bf80085eeb82dce1b927b21b21229d36c633d9c3482e22dd2a7fc91c06f074396f80d7097bc48523c94de6a1570f1272db863c86d85e4b61463a8163c4009bb27dd730f1ad7acbd4bd4ed45e00e04f3ad14d6e40f1af5f61a2bfd721809afa77c59d06513af30467c1b3ab7f0e5dfc46fcb49acf8511dfc0caf9c669db03e2ec507bfea2d21aa22dda15538fbad3c9fcd9fc977d1905cfd5939f20ad65ca71e60ffdf82e4ae432723271874ccc50ad807ae0612e1d15c33a7fc049832d62401af033b472e630875e994724ffc85d141bccc66a9ff4c3d4377cb152147d379f97e6fd3209cb9f77aea014cfb80666d761d539c5f5bf104106dd936370188b56b1b08cc3f0f835c79af04f0670b6d9f4e77cb27e8fd6cd0aa76cff7a8e1949751eb9f2e1cdca083b8f946a8109352f5e4013f632198088e3084360c0ae4ef7fa4206b70092a1d410112941d1552cd13f29efc77c9a26aa41149160a2ee7a5c445d1045537f4a693620e522138c90f521b3683970ae70b3a44b3b492e0e023b2823caf0b11058c7f2cd4d447e6dbb3d2c1d07c1d3e42c1f4ccc0bd899ed88cdde905e53105cb32cff8958cb49a50347e393cff2d581f5d0034c12a57b509b37ee3c5dd42f4156734494cb8930e10b1b640b7e542742b2234c27c1143d3c25339b9069c45cdcad226aed206edb1cd5e5f8ffb70a516a2e189b10ae6269d70e4825be695703e03be0d5b50deb2c93033e044bdac3723f9fe101d4a8ee8fc04acaead51aa3ffd3308f10ac7512e478293ef36b3468d22d221065c197622e3deee958149c217c2320c8e63e85886f8b46f5af01e2389171999e3c5505105bd12164013ad5b9c96c2cb21a6b207a4f18da76c3aaef9e30a57e6211061068c70b3b4c4f8c4c4dcdc0c69b7d0da842361b8c0bb1f924ed8dde8a4ffbd7c4fd821e67981ca3399a8c0918a259cebc63e21ba71f07e0a126c4c324b2e205812813b38070379b47884fc5cf9ba0cf9d7e54410db70d24daaa8d5fe99d7e402b65ca25d17665ecee4c4d9f12b3c376783ed652027a99405c3bd2d74b75c5e7ea685046a8af12ee60ec67de53e267e057b2887dd26810ac94e616b43081ab40b2bc0117ee08585be082e9cb6c0c284c08f5a53cb4181e7e104b84ace1e8fc03e1550efec803c180e99439715ffbd1b43806018fe5d35e59f264ff40ecdb307621f754389d8caa1241b44d2fac1038a5b609ee49521f9d266ee0400cc6e465349213483d8317f12b6c280dbf2098596cb5db78c03b41ee36802cf6f417d0f554700054ea06d2c1b383fed0011326bb797f8be91101a0e8038663e53e480293f14d40a4a543013a38727e295b84f2b67a7b403540050a404ee6e8f91b2f8303aee92eb21252dd9d0d1535439672932e1a886b3095f6746e88d057209581acc106c50d219fa426e2800c6a4b29fbaa3f1153d74b6c8fd91f988084f789232fa93624d364c635aedc371cca480b2d9049698783ebc97e8eb5335cb66930bdbb174a950a4f1d530eb91361b3d02e98fb5a6d81ccc66d3d6e1351b0782d9f8b3c605b7d09acd2af79bcd52550f37462668b69e13fc20118ea0aae51a11cdfee4210e419ee13c5797f8ac136f36fccfc7bf36abcde6e32658ae50e92af987f3736e369bc697ad7f4360055039dc7d060d1e15dc41ebf6f51d1eb6b1dda4066870956597e726bc2f2693cbdf376d8fd76f9626d1faa3be803b0d3f37cc04ff93af265d9ac04a29c8fd35febc1369a2f6db7c4613d8629bc8f167f045a425ed678b8025ae3d70a894f8d103952e4284c1f2755dcf308977fa8e7412a6d6e1db8124d940de98a4f48f13192b817363eb6760df81e3c639eb2307d094df5b5d1beaa5d22802ef2c961624016ffcbb869092a3d1f936534175a7a99aecd1fb09a4347b0513cb12ed411d7de850bd8744f3f45c5262fba871c88b6d9e4eb324c4953950143e0ff0463cb86e75515463d141bd93ac3d458555adaf11db9c7e17a225f8db1807a4599afa54d4b7a62fe71ff67bffaaecfbbc93be08e80c67373a77a049b3227441f7aafafe442fea2ba4db6a3449ba7430d6b343db1f64575a182ef869d362ae37089db2fa44e6c591ce7b4a4d50503a62c046a5e851f27f51c85760de9ba77531d9ffbc84972b669ffe6ef0f8107c8893f5a20f87f3839d2bf1b6739c3ad8cd26cb1f65a8db767e7ffa00b7ad1c9fb401d7dbf3fe6942ae6d727d52c2bbdee7fba00b73dbccf5a11decbe9de18b2ee47637cb377dd035ee7db6af1d693bde59888c0b0bad9f43dfa812b2ba0ecdaff289487490d261c715fbca43b32957f2917f2cac123efe87d24aede3e88357bb4207321735f07b24a02a3e70e086bce2502a094761e2d392a5442f283fa8be91448fa504bbdf66f6410972db9be9471dec7e3fc78f2ac0a56e2efb2a97b613f050f6323ea9065c6fe77da708b9dae4f5490b77bd9fef8712e6b233d38f3ad8f57e8e1f1d05bdab3ecd2e1d37775668847b33267e2bfda53341f6d21fdeb8febd4bd423bc91b07aa53ac77cd887d70f7ffb905750ee6034a4a04d931c5cb6bd4f78881f182e53fa3e99e44342f6e0805afbcb611a67416bbd22310abc191fb8e04df88004dc3c0e24e8a67080026f86072e70133e20c137cf033afb5532515b3953bdaca40e5237f383355e88cc7decb01e780dc25abec5978d3466b0dcd7ddcc67c19865f72b3daa8aac0ba4d05e6035ff94b4732225e71e0c232ef60efb6a289b0c8a3f50e0a56fedbd7eeeb08b88f861ec84e1d1648f1b1137c7a45fe4008ab3e1bfc933d44b037a08c41178533c088137e28312bc413e24c80d21fb9f88e1dc3f2d43278dc7115d4cf750c66e1139e10cc72a7c372624590abe218efefec079e84010d7ec1edeb8cfb5293821d547bd6cb88e75dd1d018955e5980d8febc282c1a22c98528314aad0de217300e2d06baa5396c4ebbd2f56a2d88cad429670fb7255ac8e955fb830ac40213f9b92ea334089419b98a6d5675c5dd760beb122964ad4b1ba041579ebfee64a1952cf951badd05919e2ef0f2b2aba9f2b95b27f43c44a7db30be60e53f60299188ff9804f91129a32e339e4d88461b34fac42256a75c633e2df91e6e707d7175f608c4df377a39e833089f7d12473e043d939a62893f8a4dda52711be4eba3aa1efc48d5d03b9c14956e10ece6acec1190dc416a612ebd44dfff8e638d5b9462af2982c5673420becc06a31f51e08a8deda28f0c35d30c51037a3646012ef43d6015c306e6c09dc6f0de58b5c8062a5a6a9cb4d4a3996e463274601b22ebcbf10829b1b50c85a0480dce5125a670658c1a9d938039f110304e94f8a496d72c4074ff1095ae06da4c8cf38a0161d1a87455680230e22c0867c03bcd34657523d306ac68ab80d44e9e23b62b5ae0caf431776c88c2f88156ce514f77c76bfabc6eb322b7b0afa11a39a23af9e9e37ee67284cfdfede14a2b3bf33f6237edf1bc2b488a9e5472143007dcc15aa36093a85c857d20df3cc3b65012f573a70a9ea6d1dd096e221d04472453849e12bf39e15152b033304d48ceba57a7fdb531411f4f25fc6f66236749cac2a2f1e926ba55bbbcd12cda371e0500e035d352bbc1094aff8f7f70797c6aa3cc8e6e7e2fd0979418ae74b31df931434d1a54c85a142a76a7e11fbff510603e5d2932cbde622ceab2ff92b1908b37df2f382449a9962a8eb7b48431a37ba1984bbe8edfe3d94e70877b6bd5f61612a1be74b0f70188d7722ce3bc65c3b1cb1f3395e391e0ab0b0f8ba66a1cc60627dbec79cf704d5c09d0273bea815feb3391c96f8e68d10829a357f194dcd1671749dd2d66c14acc71ce01c3136030b1422b422472555331b259bc342133ab3017b0104717715c751fc4daee8ba68f8943fba1d639396dc3c6ff4f0d4626426c0ff07ace30644ada97295d3b41ac0c992ce10276a2bc1becedae5c4d35c540640fbea0fc3930b838223eb462895e726f5744e04443a0a31ade008d7647e68df9278d95764d12c3eb0f923e406c49bcb1d01a5ed97803c06f1e152f64614f9fc598f546c5586c286239008c4fd879200b87ab10edc04b5bcb7250b3f4d8dbd3ef25e233c3bfe05e75df2b8ee52e6aa538cbf021f1d3011c3a43061f367553c3ffe811306da0ed29014d7d907f3eee64f6bc19ebb1a38d520d67c546b22400792e5edca978907e3a39e2e47c29080e6cbe1dd88b35377b468fd00e7648f55b45115285925fdc6b396c5c2abcac539072e9453abc947c5202850d1dc6b4330391279a3412f5eeba5734961a22a7139eba3962595111735dbb1efceb0e40cf436f52686da4f82679afa85d023bb593d5c8636994813f859c33d4ad449e5a95d22271b034cb3a43eeb5d9fff6174a30d93f0112f108e8640c61c7d1318ca9a4fa1cb17ff1d495865aceef1184fdbb399366f8f8c07e3f43b283e20018b706a21612e2578201411b98a06f3b35012853419adc6f1759272693951bc24e52ba06fa56c05b17a13a821615b1596b36aa2818bd11261040833b5536e1f7347278f1259a9446b1656fd0712a80edb6a5bfb564fd41ed3e3fd8d867019d03cc1be22818573d933ab4cab0d69408d449a5cffb952c2388f67c9a60d835a805835ee93f278aae34b6f21722f4d492e11f6536fd2c697ec6dd2aa3d1a99c170f5e7c1416a0fd6a5ba7104f95b2628c14c876b015328e10eeab682503d7533c3630793426cfae0c5d2224113714170c482ed4357250e276fdd301306d5166d48cefdc4108f8cd321035dc3f60e0722eb0d6870cbfa7d0dc7012c9f6dc68950ce67f9e2d5d3f9e6b1a2625e7056c6ef467041386bb0626640b60bac962841074739c15c0ffc019b80781d7d27ea7387216c1ce4cac00a726a0328c8229a2eb40f9893848b25662547b716decf25133e5f204938d6399cb23523c87f7741fbf52d4d67dd0d8198f547108c8315ba5867635178f003c6a42000f307406aefa2693a1d1126874afee580727fa93ddda0202f9706d8b6e77fff7821ebbe0e0fbfe181a9acbf708a1f4dbf99e8dc9f4347e6c560886786f9e0e4c6a7c6adb1b6c5c269f87b9d58da9a6324ea8f720a94525e4851c497566d2e777e71769b2de42fee04c05e1229277b6b836c71039533da0a1cfa272a63925153a2d35877069ec740ef965820b1ac1bf564b42a4a1e83287b9dcbe3b9a64ad92c50fbc1654399bf0557d9544282afcba4aa4b8875f3dd42b2a56456efad34d60367c759705578976874c22aef4a56822596037dc23b2762414c94ff135ee18f2386165d344578542846997ae3d781788967aa594fc5220868193149f72b45b0cd560b89707e14def8a8853e7417b8f8147c2f6f79871fab3892e23b3f731fe5e73d56f1ea367f55febc9df7875e594b3c87cb657ffdb397a8a4dc9bfac8c624068b3e25ada94248aa51fc1522c444cd6a6aecf62b1f69f8e82c6911b47d8e987868b77da93b68cb980b46130ec88c50bae44bcef5b121cb2e4742525e838708b9c4dcdf6edfc3839e969947c321ec315a8c85afa4cd545528371b644e3639d4d4937680a20067132c2c8d5f6de1cc9b5a8c780371dabe68f1a34c7d731296f5374cf18053f6a6a6f58a94b2a921f0c0d493ead596c87a4aa8ca46a971ac97ff8f9099f089afebdcaa414c0f17c073fe348888858251dcd72d233b2a99b4f3fba5ed5d9bb09d3d2f8cdc984aa624bfb1210e445d6b6e4599f7a20d99bd3541f808dd477b181ff1feca495451722228c4b29cb046c00e149e7f0086518a210e4450797609d1f01674465a000061dee26bb8d8b4751eca1b147eb018165b0c5c1ea63b19e8e50b6c168e80b17f6e6467d4ca9129e89b0e12c0cf6358e13f5d8232735467b9004304331c5ff362cb692b1d226294497aa811dd1912dcae125e222381fe0d76bb5e616e501713c5556da5917023441f26fff94b888de61d747c873f79d0734d07fe3d7c3399ccea4c81746babc4add8319b3f6d789774b43687591928070a87566acd7080fc43da04e45a989d8e3184a00032b4d2f2694dba9e58234a54dc186941c36f0870212ef751ac2ade745450f8e69fda9e9706c9bc8423c775b8db6e293aadf118bb0c86005de324cf423d113b9f742e380ab0b711ff9d7712cd705cc4765715ba43f454a89e31388475fce38b763724c5f0cba26dee0e12532022640e0c87ee0bda38397200963463882abdd607264ea31f0c083f357a7c6e1783f5a79a70d603eef8b1c4b01d6390be0e61871f27a94d4c4ded05968dd89e8ad135cec8983f2321038067ac679ddcb2329a721bcffa191e01e3230a5785ff826d1be4d646b8cf07da3b701fe599e742f584144b2356fbd29f1bfdcf31260f7771384bc221a27023c5841b9a82cc0cb8edd91f320f24721cf4c4a84102cd4da0d7aa5afedcfe0551ab076367db305191446ec47d2fc5d6b2f99ce767734b4f8e1e998f4744131636fef28a02df505cfa0e1277176cee9fa93d7cf7700d50ca31b5565e205a7a36981738e420374ade9a0d2563b8ef22502dd59aaf1a3d50a922f8dac48093ad8ff09165d766d5627343e558f9153e21c0c47034f85d8775e7e902cd029696414648ae9294b5096de4fa5bc6826706a64c52dd3f922462f6bfee81c1e26efcc7d9e51b009c27411bfafe154c2c915a0fc014f83d0d0784ff90edcca89e53a75b436131f80f64c37fc465e23f9961fcf715f0f11fe7801bd42ce52b665831d3b8875df49f8dfba17c6f9d4eaaa91330eb51fda74fd38e98f178687dfaaf9c020283d6d4f1576773fefcd69bfbab7455984a77157bbdf5a62844bb2089634aca501d0d61e95822b6ebbb0c6bce3049d6b0614ed835547d138d5a2df39a7fbe9456acdc9a155b658f599c51dd13fa0ff2182faad26162a2de4204fe2702ac40b5f6081e8b96ce901a449e484abf855ed28c2a162dfdfcb23724f9e5462f7f312a6eafb44836f32659da04a31347db29f08637511e12ac82a0947159c80dcd5740e31ea71e63899e0ee37705f4d11b90dcb930a63001b72894ee65060d60e728da4ffd92de3d149f865261d572b7860622dadd35859506e896aaf71a30457d861e99d042f51e38dadfa25d5e5aa8ea3df24492fa87201a388896b0e52b30086af5daeffed383918b257479f9db862ebdc81df1c0c726edd27d95897919f53d3d848309dbf7605b083c2ecde489ff120684fbc881aeee7b761fbf3755fe43b5d68b9e45a889cbb693e749a17fc0a03e74d2ebac05cc3e68f2f7c66748a8ef2819fead65fbbabb3b9eda880dcd5f3e50eec467f3fddb2ecd75a322e010325b091d09c7e5de9614ddf7e8ef50051f5130ac937920dad73ca1a21f2ac99d324b7f7c3d15330a0d0a553ee9dc2c31a93767bf042953a3c958127a077fe37ba70f92eaa81fc5fef9483208dc8ffc09201e6ef66f8a3d7a2aa72e54f4b8b8dbde21fe48303ed3dec0246a01999c4ce0106a65e13644264b679a6643cd3cb6271e562be9c2cbd82e700ea98875974a14a5450e1fec197248e0769fd86b0f83f21da7f9b3de58fbe7597d752fa9bdad78406b5dc386fffef76b78187fdf038949f75d28f722491cf97f981e445ef1173f4514c7dca61aa359b6acad43a86b31177345ac389f6af6a83ccf425e048cadcde33a38efa2f35e95b8b3c2a863d32b7718466196a6da9d614ee30f011d1362a0832396a8be0b013c3f7c9bfddd72025badb136b057e991f04032907c2dc0012ae8016f68e2fe40fc4e0b9c0e40d1ad270614b82b0c3b83939634e0da9ba7596442da70140bd63a566cf53a7d9c929706e96b0e7243e4290d2141852880986f28bb7dcd928fff92923226a99e4cbb2ef682398316e7eaa019a824ebb21a381a03503408b650298dcab16f1a3d046eca71e8b0fae56d393e1f63f83e85163c8b00aabdeda68d204c5f1652d22ad8d12fa404fceb94227eaf87df7c68ae8234241f42848833980ae07f20588080686f83f61b40728eba9a6230e7b13a41607540035712f4d12738704586c19040b427f7382db871b814d50c45f6ca417d49a4164523f9681a2e0f54371a04443609c8955d418006efa6a9be694590d5a6cd67ed95fb685437c828c79a30f0b8aa66c0dc914ac3b79c98c6dcc9c3f72ab029a4cca52450e2343b587aed6dddd84098611a606c33b18846a1efd5e6f534f8ebe85015750749a62072827894fa07a139d0f8e138afa27916528f71ed8c7112314ba4191bc44e0ca1ace32bcaa84743628a2cecf7b0108af7049863a1adde3c1ac2f8afb8617d4b238467b4942c454e959aa4a08a743c4a7afcbd374f855cdb4d1f363652940f5c36fd77ee6e4318832084f33b61d857d96f4633bf8d3488f331ecc7e9d81d3ad7993c7373fc017062ce50ce9ccf1ced7eb35bd17fbd192b48bf09e8f6ec230a583bcf32d16d519a80596916247a1bc7c7c6b9909ba8d4f9f0ccf3d56a81a4a43aa4385100413fb4ca4eab0d012ac6a98aed8cf5408611f11fa9c3858b398ec6e5be51b209d47e222d1f11490d41891186873dd2cdb6889353dfc22088ebcca6449a25846b1d2ba99ccadd449615d714f2fa038308a75d356af3cf80b221ca5067351a3e06dff6d658e40f3deba83cb4b4d14b60facbbb9ca5bcc0cab9487170297a26d96ce9d5be52a063f76e1c339b54c457ae33195089417a4f38a1f2bfb15da942bdff4fb6cbc33655a54cdcb5b18040eacddd06b0b5c69d98c39b70efd08b3fbacfbd57c9e2ff0fb6469cf4b48f80592f572d60f481116671ae04bc2f1f541489ce46c3c9438efdd26b531914ef4e522bcebc46053e079c8601ae99b6835240fa7a83f9f23cd3750c9e3a9a40c3d7dd5851873d55dad963e5941b35a478d6cf28bc7a73f9e9e2c7942191c45748452fc7dfe6c1b87d03daf6d0f8c032e2507ec9613ee40413826dfa3377b70488525362e6d7e1fad24031d437fe14e86131503e19a64758a73f81e5c82aa07d38111a69d310aebff7664607ef38d915394259d0fa65d3e054d6442b182245d489a52db9832f84be521f7ea7ec66450238dfbf7b0b5b84c18b03a3c8832e849642dbc4330654931ac831d27b8992e7647e0c700c81147c8be0f64a328ed3748f6328e4e551b061f849025e19844e5f24cead20a252089d7a66780fe7a588347cb176ae3a888ff9b1d202de38d6e065d0f846865a06ad3669cda8f03a73b95610da3c7bd7d17ce45bec4276b3084c641f2f5fd11313b63b0a517438183590f62b7a56c39ce04bbcafe04857b97216de26caf36ec1d7816436c0a138ab7539e7dd20beb08755331b1da060a08b44d86255d676acc6b2bbbfb32ac0e3d25b8e23bafb5d7e6ba5193f740436c2412d3e872c429ea56915ac15c087f533ab616a6b87b360d748c3e80a770da049e5c96b4d86483c4368e2c5ffaf6aaa0a6682e788743f666fedccba8fa7d530a492db9b6502a43cbe2313ec9b657d864d560844578da39568f141730a8c92b0233ae4d3d398a180b94ab60e70c3235a78bafc373886f0ce8ed513ac2b638ec512354138470c00308b80f790ca98677f91ae09cb6d70040d768494f1ae42c7d9dbd72cf7b535d931df9a4111e911d07c2d08d4643b8a11bd9604a53942ee3fea4e4c8434395b154376e4cb0897abf00bf4c4fb05eafe9cda0ec7998d42ad708bd4c6f285abc2f68c33179218a7efa91902c4405a2d2619de28963c556e3a0188d24a6b2b379e2a40fe4599408428601a45cb26bbd0f64d5222d6aaa4a3e4e6c1bb28f8ea57e8d1c823140e2940c69ae92da3133a28730af5aa1265c5301bfa1dc56ea01f9650def9b95e4a4c0d0c69e10e9b80784a216b4f55492c9bc5ee63f493bcac5b1246f5d349155d19083dbc72b4b3907fca86405a316de29ecdc2dfdf48ad24f698312db5c2d82a70c3af2a27d7a4a75e996989e28ecdf01ebe5aa7f8d5822651e807cf1ccb9633c5787e22a829f467bf9e0bd0acbb343a1a5ee8e53ce084dd924d562d656b1a46d36620ade153cc8b9f60fb45c42d03341685bb7ac6467ae01e2f01feb70421ea318ae993a6e022a8d8ce658e52a67cac9b28752652d2a19ca11f2e1186f92655bd80e36b7f7adeef78c8be65caa20663bfd96d19b27bc964f2fd20e0b39a4050e48a08f785ba25ea7abf2acbf65d26bf0d312be3b554bb59350f08dc7571cbd72e4829e2bb910722eb776ed0b27c0c403906eda4b864e19041d47139eed622bff41daec472331edd1fe2d72c2c2c219875fb0fc1a43892606128984f7ca3821369f2637b6ecb1c2ec139da12929dc0b34a3fd9461593ce7d3ccf81ef1916935c03a2b5c465d25079f685ef31c252081e7d304712df1061b0718f990f36adab11b028aee1be52b0b22bff02d0bb1079f931c29397632585e987a8195114f8edb2b0980439cbea66457572d8d3db7c914c1be5a80bf42fe026c381f94879e4f0f5817b703e2398625c429e8e28582cf02d48d9074bb6dda0b40adfeab7cdbdcdc9faa163fe725203d78e34026d3285cfefb3925614ef85195e0a28d3d5610af996dc018f2fca3459aa0dc54d7c58c49139512f48f8e887757c6d81aa932f48183e0ec5f1bc62c1e019ad4a9840b80d30a96736e25b369c22d0afdb3db01d3853d0ea1178e34f636f286262ae41b515ad3b7469ea7942bb01c74358e4d520e8ab76a9c157d9cd599e473438d2e3709ce5ab2ed94edfd772f8ebc74fa56d95a5e81c3f5507560c1006a413466b6537375452a5c703a3e504038b49126ad9e2b2d14103d4ad8ec6541c3b2b080f34da046f94c544301f9bf9708b7a1ee87d04b0d9120a0d27b4420b58c768a31a4f31d21ef782b97319378adc462cf0387121049a7aa09238aa7d616de36d4f4779121aef4b980d7c1d3ddb86410f42dcd2d19673003dd062d4d9a712883210fb1c3adccf043ea72367dd715431f61ca7ecdbecdff8e8a8cc350f29917e5d088d9b0ca42c236c27641174b4bce80863ed97cce4bcf3d091e6db0af9283f1873cf1f617c8914363b0522c2fae6ae7d5607cdd0d876409765c0c749b8447b44ceb7a43ffd1afd387df1931037d566d201eb727a920220eafc8802fdb0d09ce573dc5bcc9bf608297f97cb94fa2f2c3002be5dbfff74b2a1f7556d80607a05e6a4c7a4ee971d8b35c6b9d9ab921986298dab9a9e4d5eff2de275d9c59de48bc601cf5473fa4649075fad269b306f2f399ca1782e5254e663dff4d266753932ffe4e7143864dce5b12a082762ec57165245d4e9e0b8cc30e78599399cfcd09f4a2ed8a14a642531aa935916ca75a91462b58277952ec51cd473fec743123c753210ff9846e69586996faa80451b0c537689d5d61328d0c421eb747ae478f473fa90ce20613502887ec8a1b2a057c217f09c6f63fc6c59c53fddc96be8a77acb513a3fa242a5a589d3d0fcbc446d4acc74123414f8f84895f919ebfa4e7de96113a3a090f11bb6afd45bd38c4505ce75f01cc6718367434bb57bdd8da016b3a3472b2a176c9197b5a3aa7d52fd77ac88f4565774171989e7e17cf61aac7566256369f72fcb18d95b8ff47c442c1a7a90beaaa4a657fea1d39e2bb4ddc19fd6c493187e732d532dd9950b72305404a3920726fb10a7c6c35367f7b13718f752c689dcb582ad55512110ccb58179c589f71cdaa672004f966fe6c2ba842f07890b263e7ea543363d7d851b201233b800bd87551426507421c57e1955d2bdee93010730fb8c6afcb07d6edb7c67c5d5082ba8d63f5a55cf55e6b512f6f07fc094cb287eb8b70062ea18a79e043917e7fe5c065961e6994d5fcad6c665acb2a78422fca2985785bf6a359ec4392c321fbe46d364e8eed2663a151711694d198a61496d48095c5dd2978ad009458c6baf9ca801d10253dfb90560063cb27b7013d34a769af988e8d90a09b586d4aa88e45d79d2cb26a5949efdb5469c749bc2c6f48af3a74c624379409863b14dcee98b115245fe94d3210abfe51deb8266f6aa6218d9cbd7d94f395e44a106ac3fc361c414454db080b7c273c0651e494fd318e1bf868f4129231942f25af6e4e0c44e4e11e85612ada7bce7caf156618c1266cc7a73af22e3ed94e58e4cced01410c8645b50d6d1d14a41c32f5027ccecf38ce8334a19a8b780f46a5b6d7ad3e6571e028bb47ceac837de589cf238b48256d5bb9517a866b67a0eb26a095f6dca7b4fe32bbab31db01713c5a032cdf7910a5295adfc92316eb15225971f6c5a58b6bdeef9667df7ba5f3db5087caefa8cdb78da3793368422bae786240c15db63457d9131632a29b3ba64c3606fec8c8cb0fda815df57339e96b48421492f8e21b14eb6b5567d4605a23d152ef582bd31251b7eaf3a39719063f0ced74fa79c6453292967daeaa557d27496a4bfdb869fcdf665f686a2441510fb915f4795a570264fadf481f6d4f6c2306f54057439ca5d7ed6476c7b1511d0540528b7c202c8a0cc378d53a6c7bc6ffc7c75410e78bfbd2501357e5ef4a1d15d331daacf7a848e5f6fa86f1c8c52bcdc7567428cab32da33b070f324addf9108cca3aa5ba2208d9d5fdc8984a952ba1097d262ff4d9e1929955f053f0ea93bd33add0b96255618f4e809b86010ca7f02c1eaca67ca1d4478667272eb2248e7765412669ffd66186a59a4be30a5ace978c404f9d30ee53c24005051f97ebdcf8d06ba45f35556892b23ee11c070a59c1dd8586b5617fecf62ed5b3401cdae35bbe871701348046aca71e28bdbaee517ba21ef5ae2a2b2ba05fec303cc85180cbdd61e6ab378c1b4025be23ff49360cbd0935b7d84e07c936e44503932937fbdc622684d8ba22e93646c99385d6d5d2f64db10ce3e88892e4b4d14bf740c185bcecd69b2254c8c9b2dc9fe76475b8acbac2565617f5fddc2bc03fd7762383a26149a1c0d96c2954da9be05b7adcb8b426135cbc2f0d0f28b2727727a58d46e3e54cf654c1f3027f784faddbd38fa22e26cf9f69c1b7144a651a211e90deb0f352399b37f707239f25ff41a2eb634e2707c2f7f988cccae11122c4ccd782f345f62cac8b094169d2143ee56874086db44f9f518156bc767fef583d331be496dec5aff468605da0563e527f2cd86fb314a9c222bf3718b492ff0bbf53d4c8efc960c911ab9089b29e3c006598f9cc41838f9a08092363db32c7990d98cd87c72c1705d7b8880edda038777d71e70ee04afb56bef8ccabbf6a8e6d65da575d624f8e7618b4e1c4330ce6cc4d928c110ca18ab3fbee3fdfb8382c676ad19f06cbc78375092ad170edfb47faee8be38a40953ca94d75362e640199ad0272c5da7bda4c0048d1715087802eb0eaf15f6782a3ee123e421f570867e7e349039e447147b2aec2b7e1549fb520c65378ef50a3b1d457ad9f45155386242d334faf00a654152f08aea3a55b0ba6e446cd6a56b6f1192b8ef9d5c6b8a2cd91e0780575e08769639dad1a9790d9be8e9e9eaab4a1a6451ae4ab3318100e9c30469cad30c21835e1aea05c0c2ba879f84d32e5bf4295d29f5399bdf5b27585e9df384b18944464d2b4574a3f0197f321acb19e59de250b01d4df3f5f7d7b867957a7efe2e73b33f218bb10817b09fa516f59bbad7c143107313300befc7be205d37b0b3618191736b6ebb4360d8c662bca9f1fc987399e59b1433b71c64e0a3d5364ad9b1fd805815b5143c91d2d561bbf1d8181268158258be0bc9ebf3c20e5b04da7023fd56985c1755feafa1484221879a9adb390c036c94065ef747a91c331010b7a603c000030ca83bea020924411a2dd977b5dd1d77f4896ceb1db263f97a2d703846b700cf28cde96b7caa818d6c9952331e351ec11a6a5e6eb9a51d78f29a7b29136a93e797008ac1f29270a6b0662cc8e68642c605d62638838e28b713e297d11eddf15c03da3c9431262e8b8696af0bd43eb2c8f615d208f8865e61ee670ad1bbc491f21e0a98f81b259ce85d1290ef5811c639c559fc6b4e4346914489dfb291c8ff8230bf8a5caf7710c14d46908152d6c522e70a6c767c2de9e3a253a6c81112d3f479136f5ea1808403d0bd0c7d4247984a7c0d231a322415a2fe0412f7011b2638a84f1d900001fe87d592ac40038cbf24860a4a6b150e9ff3e3475e6443e82e28f6015f643d1958717e5322b2cf14e6f80100d97e03209fbce107ad1fab02081583e2f1b90e6ccf3e85af642250f08c88363b388313a413014dee0b71048d650485f335f9fa042222fd8ea59bf79d88df0a4a052d3467c4f50c9fe81c2d407f084f855f432ac72b17b5426b7cd80f662b8063a093e95395c565079360390d54a15018507abcbbc283d37203f718dee6a065786cca717f62c2156c2e3c815b71b94609bb9c6aa90a4dffda8703064490541e42af6a38e86f89e9bdfa48fb0503610e254d25cf6323e97b20c8cb6433fe38964716fec98e070f634bf138a8a2bc083b477222384ffc969f21b981d3cca71ced381d4a3ddc2d28222b797df9023ce2a0b476adcc400d9b0b4dc19245d9f024448436f84e0dfc04d5a8c8e536da25da3460ea99e8e0e31bf294f2360f10e425241b9e474a5c062545cf69408a936f6d12f165c244795b9433a7813aca5a34309f0aad17d9c7fa7c61a939f7f009ca07c9922b935203e4a5e488f3a22830f05806600413413193d9f67ea0346067a655a60d4a6863e22d99094065e428f3686a2082171a99f246a9f6b21c114abc40a78caa5d0ae4a53c4441c9bc297e215685b2a363f6209252a17c30103d95988867602a84ebfa50e3077149e04eea72bc1375e26f0be7f3a4c8f5a622204009b105fe89f242361bc3cbc1406ac1d68fa2fc54b641bf7619caa0025541dbbc21fa239866e401676ab80799bee2cccfef396a70f7f28f5a48e46410f97876ec5286d2e0edc928bacb8e826872351f22d0464e56bd0f3c4f77559df939b6b11c820b2687e5e7f3971ded104e09c8b212b83946e5866e5235e35b3318d0066d9857b5c6c83f3281fa4780778491c26294835f0df44dd0e4757dd06fc045dd6b9a1203e560a3f8a6b0d840435889f545f2ca9eb963f8ae2952bc99c8c067b943f69672cdf929b712bf8455173f55a702956509f0c384128086b823e51f1c88e34c8a8c418bd0c510aeb961f494d22010e23871e23fac49820a0ac0b31304a350393f92de8f9d5942164d524e229612b440a72f97a4f6e0670c5f79a856d4672823c0c930b9cb7a0558385a006e6812e7ac0f400900f4d800ee3b401a93c55cd0e09f3c4042632a781e049a826ca091036fd208c2d7580de403b99a5fa99f1a1fc34d84b017a9426f2624530e80c5523e632242109101005e0a9515e5810bc9afca05e2bb9831e0980a304179f038e4798a19baff86c7f2a19609b05a3f7943901ff9d8f8a52d2bdf28f3c739d41185266132f85a6fd27800541efeddd3e69026249d88a3131a438e90ef7a43e3cb06995359c31c14dde2e6168af796264c6501c8d3197ba19e24bd4045dc2913ba90a0c551f06184eef204e74350ec79ad3cb07f9a3b6f6316c0a58820e55264d8782f7440503e2f4277e28a8817cfb47dfb635606d537e66f2b61de38387ca54317d0d591064713c6979b170ce461a316aee48fc43f47b1a12a8b2b972ad3230801020494108932c10e6810e43e63ccbe5026f5dd6480f07206e8f8b653031c42ab06af5a1ae58e1ab87da81c8050ef50e8952bcc3c0d154457d46b422e44e6809741f3278f5181e85d448a8316b973e57441caa045f66cf14a31cea0e88a2b4fc74a54d00c2348a8de4e802a181ec957f640fabad02bc8f30154234fc28528d7b88b83c6430eb98a252034c700316e65125866eb7b7d4c5912af90a4f8a1f2b8e8ac3f0caee20b88dc84469d4fcb84e48da408f47cd680f8e7a300ffe2cd1fca74c4c341f429e284cad479519d76a1b73804ca0b000f7c1d4e61fe8d9510041147ca8bccacf13e3a603df2511bf4c873146a648e5d50c29383a321a3822a68c5e5edd49cc9ef0ab1671b5e70382c2d47d2e702857407c02b20e49731d04971426aaa97426aed0f4529e28a2a917dae4b84d05405db2baa6bd120aa5a3ca4560bd02020887913c8135ca1800ec5133614666814f864a8ecaf0f6aa932a94ec69fc16a2d0f11b410e66549f52670bd2f4318eb7704a26f458e8c171154cb38fc567819248e9ff5b8de438011fe2470f8a428797a3335c63c0a10a4be696bed1538b7e41b3d40f99c8f0028280c145cc4ac54ff68920374273a137421638007ea3125478a90246b58e1263b7ac3c61ba16011bcd376e707bd59cbc421a9bc6ecf0c8a2c71c027d160f54524269cd65e1f4f56dbcfdde1fa0e75905e480b5c680a4b8e2f51f5e3ec88f57ffc28b93351194f60e0f8b430a8f93260303982a11edfa5860a1a3786f893c2e04047e57943d94089bf206458b306282cd058411aa07a4ce07c6d5064211ba36808d2c835e43d6051d12396d6b89d14c1974063e443321cf92017824e4b0c172a42f9c9bf5ab5e567a6275e8413af2c42931de790b4f3a8ca4479347d88a0498c855c54dc97952c18f3016f14fddd8f3068b3e921c7b260012d710a47f00c1f4be8812c31bed8d441c973e6843da10790503d4064fe11ead1337814e713a489de2e862b74ca84201f430906f44c73c7a71aeeb2a10e4abcd52c2a2826277d0e77c50efd7b85e80f55b18472aa91fa12971114802581bc49813354cf87ecae966f9ccc98895c22478f4ff5c6e6020402f039384a641db44a051318d1f5751a5009f3b69d8fb00a8f7b7aa5fa9f3a2c5eeb4971669c77180ef69ed6667b1492f47ca9190672830a9a7c950a2c3ee892d32795f8843af221eb572558fa174f65de8e4da21cc503a08bb1e2221be215801bc396642c4f315fe20805ac0b831e0f8b4d8aa09a3010baa6e24cf06f33ca5bc4b828a44c91f298571dbe5ce0899dce150cf78320cc57e23403f50124f8ac7849f8473b029dd103279fcbecd3a3af5aa06d862eef1677c2c3eef01ecd09e67e560d5f2045f05dbca05e0086323fe5c272b85815f2a537bcb287bb25afb668d51fc9f32657901bf5b650d1124212e52453c8a300550b3223775a14036d6068e8bcc09cf89d5a06fc409aecb96811f9288eda7cca2b446f6690d137ece11bd98ad03a0290ee814923749907e838aa78723a4a52fc1b1dc08f9228c7eb200504b5e362c04fa251c20b5ca2e2345841f83f2620650e86c2845f5c2c5d57a139b490163c0f26025dc6c4a382e3c915ca811a2e7c1b6726ef43c6ef955fdcfc8913554f81d62537b24ce2cd1e8b9cce84acbf1006f04719d0f21ad68c64a2021d7f8baed363b843c10749f8828af528e501fa6aa1708ed851a00450374283f200373282074c457a15c998af352630bc112ef94b4460861c440509636912959d4553e8a5b835cf07c78aa27540e463f87470498f967c032c951c8e3d3e998e23d905c3cb43e002e4a6c88c0ea7d519aaa03df391b2a0ca0efee8adfe9678100b1937dbe5c16d603a7e221c72fc481e02ffca4c2cf4af419cf3c037721c034f7217638860082b7bbe5697e46b8c449037b087c43fc59db9845596b3f934c49b38e980f65910f4646ca4c8812261faaf34927cae0c259f850606da83ec8193ad19404d04d6bd08213032982d3a1e0a9f34347829002f6368d7470853be9a93250a4002532fc5cc9fe0d91f367302bb822a52d3e757d12015d45e32e4662e228cb048efc1743d08ce3a92e777910a80de0ac0c097b964e717b4c8f0d743f737146972566fd2fdd64a3ca1331c0f16ead2e7d204e4fbf814b9065b9a7c4e17e0eb671c34431bfb4a6c08c938e0c8f92c5990dee352003e6cf3f496ccf05ecf822830363f790c3d4c0427657a9011c10244e52cb1cb03ae04006bbbe2e06b85d9426d0452e33c48b0ca44248d7050ac1ea18ceaacf8cae1c823e115cadd8405cafad3fb1e6628748d82e22bd00422ab5a133f901c4a72a93d4b7e935188ab2121f4a3228d713e379afec68c014f60ce972cd667c2979550637cd2260de89d2850cfc6b1c995c436fd1b5e8982343eb8703d926e78913c429ec0864a3953ec7e832d6cd018524c78a9508050b7b7baa71375e317c8c5705978af7ec801c88fb895e563c5720fa639227fb291ca91663dbc01012e9f44e904cd70474cce14d7e639fde9fb5ba04205a5bc35c95f21008373680df2a11139be78ddb8931df0e911367ab6f00153e0bc140a10bc445a0bcd16047c5c0908198c2fcee732e0e6997d6cde0f823b594032f957d248425f3da037583be5c328a49c48af256f0b004fafb667643f1402de0093b5bfa5424316d1e84bf644b97ecd76661d02546f74e72e588557a207a522280c33c026d7783423a8c5cf926f11a28313e104bede1a879ca54920076c26331b2faefcc02d28ff84afe9a802281f02ccc731280af5058ab0f22a5582bc31cd7e5b9752a04f6284f2a4ab3a289c80c2b37739505468673e0d13289440d3c1b3aee4be5cec7182eed84106a583240ebae3c4f005b47cb2d8183a8e490df319985b5e958146bf2ac6913fd5c5d4ffa85b739e1452be8f945e289f1b75cf248d25941504e283e93df131304c3fd5bcf3e08f11cee44d5bae3404f36a54a1c814e0767906133ffe0bd0d7e7a961bee00cb1321e031a4134f72c4bb11587b2d02423e788734728e9c8ad37f5e2c7c72250c4a7ac6540856f889cc99bc1f58821f3af2018df01a0166e96a1ef1d6d1bef42c89e4704293f5fa11d8fc9d42b7fce419dc223018f000039ef8355f6b47e0c415b04a0e0055c046e0349e68b621a05d73a71c82a48c865446fdebc8e2fa0d040b00ca04cb40c6f168b49c6d0e64c56f47ebcd5985a4e52a3ccfb01b428e30222e7b3a0a9fa1812e27c0907c257a924c5bf9a1e321e3044efa0022fe73f59de8081b2cce444a1a7d302e8aeebc5018d207f0e1702ae37b7278ba5cd411dece96008097c5fc243941c6bca5ac6e5e6210b7961e859a469409fb1aaa01a0a6509de4961c20380ab95218d4ae008163dc87b1c947d5992448631e685bb5181e0fb70d2f5510ec47813400878a00782e6b50cbc45215dff66009ed70570e2736b881ccb2e1a1fc31004f7b0470365e062785da7ce08d1581281225327c10f635664383f1b82acd098e5206c7d4124a644e55496cc7cd140f53cc211b52ff1009527d936e52985d4ef2b7afaa48ce3ff8531843ad080c3d1427e32dfdbe9ff30b442ab8cc9e4b056a42ea0eece53ca9506f5022a959789c8f04ef20d7f428750e61fca355a29859ab44cf8515b76804df832ce27e6ebebd91c722d9bde5026a0a563e8e382ee01b0eb3dbc39f33d1f5dfe6c4b5d264297e3d9204b3829b3579f46468b3732cbc0df7af100bd8428c8478aa1e87f9cbd1f7361f3075db9fe31cd4033310dbc21bc1e6e8589198f35400d0dec04c49b8a2c6531641cb44f8c12f4c9ac0a4fe7aa086a83178c1c08c010ef83a7cc33ffd6086bdd98f585f8debca4fde99bece5fda4ba3c97a301466180b9f35c13dea09deed4bd1eb323baa6857048a0c278701223872267885fe0e3c0cf34c2f1440e195ecfd09a7c60509e7bd9cb85d62a20e7dd60d9220452e491732971038b90cc83aeb97183bcd85078303776a06d8edacc258f906c61737233c4b4aca49586e795230c7a6057ab57a373ca974531cfa689a157d5e28dd70983e3a1f098e1a7d624f12e4070bc314dee9561801c0482be677f40fa167133ab2fe5c922993d022f30f2df2fc95efe126435592aa1828ce04187d8f084c6b295eb8bd8ddc8b90601ca6ba22440f7ccb0f23e494dafa18894cf73e1e8640665f9f58cd04fb1adbd0d41ed73a9d3c90f15817dc0970d9ef708499e03c5e9ec15073f29c2170fd5e2cbeb41d07345a160a0500ec078043488bec5c9eb59271a2a482dd2f3dd59be280fb3f2a166a3601b3d21de092e3b6016f6e0bd99661934492bb14f5b350b9d13bce3ad9c48749698adcf353c945b0da1fc1a8ca2535c497213a61e782060271fb0e6cc53bd047f605687dfd0baf84f70621403a235cf28d4286fe224961b68e3902d65da832a98532b58e6e82187a97227d81c0423179261251807f9baaa6614e1df260d7907a51dc137457f1ee08c2e9fe18be5977a98ca785074f829a94cb898036d1e11af164ea699f6001448e5665096ee8459239f7985f600089af06f85446f04a1bd5409549ec465f16629127d9003f2170870f13f08cd0961dc0a937d4c72852ff4d87392352b48a507a31c65c02d21810dcf5754602c884519c7996d2a500521b4785631c41574c8f1c658553ef0959c0ba34cf2274707df85548c8e9071e778428efc95259c07c975e257d43ae0808a08e510905eff34620fad622bd04bb88182a6526425b3500505c98014c82889643ec3e73fd72150420a5a1c3d860c2ff2ad43aadb7054ea8b5583e8ff0b0fbd94698c1b0071c7db40e0f03332f4fd1c2af7430c95f287b48a270af1221f6915e7dd3a7441fbae88700e6f543d9c19966f8581c9ef018af82b7a4cbca9668e0f41bbe11d0c70ca5b26e1fa321508062d6e99826a29d2e8a5384a132403e3efb7706981ea9923249f6863f2156ce2cecbc18a571a6afaa7a981a201e17c4282dea081e200bf19e08b1b39d3cb717c129205c1749c6ec11757f506cb4332f6423dd9b13910517a2ee5c6ac1f63d0ebd5509170bbb20befe7c30f87221728e8c14d09344c0122bfc34c9cdcc67627d8a21331dba96682884a14412f3cca4123830cfc892ff51ccea4f9a65887c3c9a0c03dcc8885d65924e7601ed9702b8460f819dddad74912e2ab5eccc823e8e4f848250051c05b6d7f6b519a8fb0e1f823b1d7bb7a3af00673d4721d9a5d7990a665b0481f08d725c2d2db19c992095ce112348417e6df075ff2d30b2f948c00853c29881067a0084e8e938881c3423f9731d1cac996951ed095559f06901354c82134de8a8d921c86bcf43f92917217b1487f684f558e612196af7a64f6352481f1568f0bc56596c1779dd8904951b8f20f8e2b8242fe00650b6b86d0584f0d99159c861effb099448f42c158adaeaceb1003548ea501cf46cd5b7e6526bf093d4f07a5d767a525c86b21dde3524544e1128c3c8409b35ce646a20f616ce2707bfe3cc38a5c28975377dc851f898c098c870b9ae3204b9063f3345b7d5f2550c2d75a52e6d334b4321e4c561e80520b5ed6193541471504652481496891b63bb9539136424601ccfcdba8f0bf39bdfe4b861ada86852db7c325cc6a14bc5fe39331878102e0b58462f22aba2cbd94a33d2011587ece9f304faa44f7003cf28496f083e14b25b1817eb882e77ad8247a2e74333e149b15e19a06267f088a913c474fc71bea14e52b964643954186044b84b0f3ac60050896c9e1790322653211648e1fcbb303156524888f4d09e08908319da5f1208709083e588e56b9001e125e008c2994948e4a4f01e9e127c0e1f174b25c40adf0eae45a880b9c462a0d6f66c4153f0285d21b2a532bf770c124c7259a82063192c057bbbba0a507a55c51063ce80fa7a117c0e7f98544cf06cfa7183d2837247c8fa55e282c22eab93488f90918c01cc9318c4f10a4e585141893ab08d5fc8f1e189caf81847f163bbd293d3cff179625bbe1a2e7789e5b1c561d2edec9910214cccc94cc434a9ce08b307ab90e8518411237b0fc872e82503e0601729e8e25425663e63c93158f6009b23a6fa88889cc46a8864b1255e33359a1e066fc022aab17156794074a36908197af21f4e889361c2ee453a88fb1c3e9677f5abc7194120fa0d50267f12694935dc8828a2ab4c65d40daa883312ed9c822c57b71150905e002110580d15aeee502003037587ade8f0585aa726326e3b956b29c2b1afe06eacdc7b724fe272a0e5af702c38fd540f11d8472bc0c112da817481ddc8f1a0714550f1e3fcc13cb746f2b9f15078086b0b2c59b04b17c0fbc1c8e24909f5f85e4cab381b2dd8ddd5e7e34b71f1615bb7764a6ca1771b9f575182441b12cd884c6f044050d2226081591828996a8a3e1d9fad0f1a11f1487c036f75f86b95e86902a8f66061f07891c548b22050f4219a3606aa81c83ab534e0870d2933a92068514c4f9a7ea04b99d1f1cbe4c953287c2a0ca675263807249b7e41e686efddd06284e49d0867ca6579b2b1dd1f2956c05e25ff485092ad8f1fa9a181742c003655c2ed3ab0caa1329dfd3c54d7ef3c4c681201982ae0578f352ac99a37ade797547981c8492a217056a150a4a439e37815b3f4c1028afeb8bc8c77f4e7778ce4f608f78a91513322d0e9e2129520456c08eaa7c83930674c489062fc28e155ae64bae7c264ef835084b8c4f92a54790d1934c2ff43225fb0d9ae22ab25cf10647d4fc4cae2bae67b9e547b1f1f047e0422f74a42bef61a2c091c425c873628df81d10a038963467ff02ce0f9ae74bee6f7432f4613a013a001878a131749b7c0980b08fd228d26f31442518d8a9495e568202c6e1009bbfa31705ad75c6e7cdcc8af171fa64f262fba271e25af984261732815b6efcc29439344cb1ecf5882df81f418e7c203c5228901921fc0eda0a34972614dfa38ced8720c0e57bca7041353d168f5f993d823b4e2f6b23e129bbea0d91b92e14f0e21165a09031457991ed8e93be866310d0b432bc501e53c6b8893a46ef0328c1ffe16105858348959fb9e2f111865e3c6dec0bca028825d73283cd139571ee51de9e101a246fc3d2195ff1c3ed097112e06d8a74f29721e4f10cf4f15b7a6265497c2cfc1c54a1be54dbf2d788caf4e55684ce1ff82a2434e561450914f1e44169543ed0d951c821098e9ce54326e18145b43e890807caeb09ebab0c17644212e65e061f822cea819ee7b3a989f642f3fe4ccc88cce602a29f43e255ee4587c5b379e39cc9ef82ffc882f4465b72784a8195a35232c217c528e30fe6bca07f5904a0a4d0e6328e195482694839af03d04390485c24540904535f44c09beb9cf10926c1f4fc704c60ae14689343dae186baeaa5eb9f8406b8ab96cdeb9a3187867113b8504d4bd6c48597b7487026e740f67035dac1c3c222e6e3370bda09cd2727e35ce50d0894f22e7c7950137d52e4362e367cf1a52af14eb9245a3661480e1b8429686613824741c6f8614bc01cd00754c1364e9e7c9d359a725a163c9f870c594e51ea9163f972c75bb0395fcff1c08b81fd7e4ca3422f8658c837754193c95cbae4a486ab7200853ebd2c09177229d79387188be237d4b870d511a457a304f7b92c444045f031fa2474347d9140220905808a26213a46175a42d51144630d7d9b1e13505045283d1f10419e888f93e7d2ca87b7a990c003d3c03cc0aa36bf23cd42e3a8e9f03136b95c050a994b51cfa08a0c3d9f1114351f44cde8751e1d71023ff87cdf9c235aab4a0e7fa1c92c87d004eb8d988a4321a0c0e1a250325f2e163c9d564be2cb842d4a1ea8571c301350ec6433211608498098f3547f17720d1e949cc9005d28a93a5b5fc599e616ac8687dd88731857247c9a10ee62f0b6bcabba2ae8dd9d04fe85d69ad7acb41e4814121fa6e5f8355f295f48c3e6fb5ab8f92e8698be630318b00c7c01fc992b2599968d03b9550859c2308204e5465ca804f58a588ee74e2e18c749e71dcd61f13d5b64bc6f9659468b44c89dacda816e42d3e1a9082081422ab57a9aa11b395048010ff2298c0b1ac2e6948cac4101a5c0f014a906a0585a197dd09402df276c86d7e9e2223f0539f8385acc5c925d8bfc6632198fa1befff4618e700a81bf0c1808011d8ad291f718a91192c8875e82273339ae65c3cdd01293fb48b9f92494366a218a82cf34de50324dba07b4a1c539a172e41954eb31d4f54b7851f5c726183e00427ea82706839e550b24da06d1d82b18a5e955dda9700cb88064464d54fc1a5d6650354e0b1982294fbf648ed817e992004c44051e7f65ef2c88a784f3150e48783d719c7e6748ce92a888fa388f2e391b0042be541840594f41146790e30bfdc1a2795b1b442d0851e548b7ba0765a4870b4b1541add04ae08df684ec200ef559d226f8143db25e52720dea44d8e1e32cf284f63176793727ccd03a280ce4555e62e19bdad1ffe24cfa62023bf049ada0bc664303e75465931b2909f14294623ca1218bdc1119b0ef25e08e2ff18444e76ad87a67c522837820e96925d1950fe4197a9d1f60681a1b6cfec386eb6e932ebd86c1e0b7cc58e6040e425837e1566662888296dab59d541f4e59889b7f2f3f6fd02f36aafe951a98e09f9b7b891e195043348ebea709d7c74863f8bbeb81b37103e764824372940f3afe6d4dd40fc304f04eda3b14b560c8e1bce57a5a554af85d980ee8040c09fc2bc1f25241f8cb24c9ce6500f1734939fe66132707dbecd041bcfa7e2bea82da0ab405dd03f2cfb1357c4e181aa18190923cda1b0a28a70040f82816213c86915d0e6b8a9667ebb5e51dc4c1944114a13c1df6cdbb3c11f2140da46436351ebd0126742831e6f178bca4a14237172e8088e103f029fa914d205048b5e06c824aa160abdff272042808dea5dae288722c834a44ad50518186c25799eebc885942d7b3e2eba99012e251f68878aa33217947020eae8405f45ca32c3d5bf3cc53b0521f24cd9eafc4a9fd222eea502adb8cbf0a50e76db5c571426b11b20d1405be0284b9bc804d89f2aab6b44f20c74aee10f379366229b4871e49b948a9c2870ad4e48f046af4858616790d2a2b5f6170f07c007fcee4460582785294a8bf6587872782534455bc11fe19bce23bed4afd4ad201baab03a20fe4030aba2a119987e0f0ea3dc5f5792854f8721b9fbb9c861368165683bbb6dc5c4df28acb49d4e067c92d7839b64fa6cbc1075583637d6dd8932813b592ac6a287439b87a7de600e5b78d214f03ef89cb2955c0595b99be541b060f44e2ce6be0b3f42047183c1adc1eb452a0309f3323563e112793ab72a2bd850faebe9802074aa384a71f53ab97a77625fe80ad3627a507cc8b9993275fe283226370f597232d793a263ccfdfb0bc92739c2995f31ff567456143319ca0f063a38ee4b2284abcc390491f664d95a3c95dcaa5ec3c71068094a002f2d9cf6508fb506656fc8b0d8be7030be56f9fe2d0be383c7eccf3b8f34cdd87e890067d4285957be25486a6da9be42a7065f94adbe3e3611e7d05533879935350c5e00431236ec941110c8591e40ccf5d199272d7c370ba792d5a769e879450998e92184fe428e9d1268df9a0602274c69e19ee3e20e3bc48bc57b121e76f6972398e0e2050960f82af15d6b890b51c6e454ed8c30a23e71b6615ca415a7fef069580a02d2b57d0b4e7956fd06ac34718a501ccc0582194840fbfa0aed7c377da6523bfb270c6af14e995ebf0d83887e4066754e2e95ae0acf13b14847e41d089cf87ae7c5df12e2b09f1c645dd49e56a98187943765f729db63aeee1c667b04c623cd2a6b36c2a048ed720d6960dcd6afb3875b0f0442d672ee2f90a867aa1e835717a95c1c4b9be392749d8ea54a9af020841def154dc872923ee46d6805f1a057823434c7e0f971317c2e1eb9f9034bc1405eebddeb4df47882b6f6b52c463c541e4955291c9676e257a204602332cb45cfe6ee89163087c1fc40c49a662a217ea0b84c23890f4e43103b4d02f1d90dea98e1a5a6a039077736052b0ce229d07042026380587096fb601f931c91c6ea453a54fd7155fc425fc170f9ac7d5e7c6ab3a61e51f209db98491849b5852cad33c947125485c78123338fc598a98ed68597b30719dbe92a25a7fa8121a975444f06a4b9a28a9164cf2010b69eee3d5e6b3f0e9126495a6c93f4a610b85c406c593505b43e758f8f42e98e93faac3e4625e16a073049c713181947c6ecaad8f158a0e6d5564c583e969fa025b013c05345db227daf1a43434794b206afd8c358b1c82a406ce836fd5db0a83c39f81fe3c52e7c85214c5c1bf2886fe8fa24228a63c6696d007fd3bcabf8c3c92a11a1824ca7a24c232a30b055e93ed40f72400f578b84cc9afb8f0f8519116b9925803fc996784fb2101e57d88d8f1bae6e070449c9ce83019c61fc5f9f0edae39afe6262bc70aae78a43d59fc6fd0d76f00bce01534a43d94275fc219bbaee4ba0020642a7e3c729aba48f8414aacdc44c188af577beaf2203531afa88c855fe0c3448988caf37cc0cca080ad3e7929b682e71580e2b8cc84ae2ac7fba4278c6ca80b990361f1e5aea4987d193e4fb2930f191e1000631e04ae1a5e2b4ad3efbcecf844970ee4c03f72f257290a289294a69cf2500ae1476be68517028dc0014cee80e5fd72dfda500832f8843960fd79369070fd9e3436de47ee0a3a25c51847a428ced77851e7effcea3c0c0987375224d6930aa2c4f58adc653d79909ed0922ee80301977e0024f8edeeca3ecd25f4c131245c09cac4fba0742a4f10b22af8a84a9b8713e04f30cfa83def59fcf210478afc400017e1969d08ddc31298a7a09af3412530b28723b8de2fcb12f40d160b5e6388f323c892731a4102eea6a9c613ed6540d5e6d079a10b362f4107e05034e178164c8e4e498573232342fe6b440754d187313f818f98710903f8456fec1eca061c4f68caac609a3197b29b003a5f7741146409850051240c86e41a739c6f850f1f571e69f26c0340fd26076e19cb972fef8c8097adec7d3d254c7b198c82abc730e1f90beaacf03d3c78b98f54633e55639129281af30149fa64b5504ca73375234f3152e5f7b214141088368f268895107ed244dbd2b840b5245843ff583c598ea822b9ed6028b8639428f4cde9f67507d62dc7a0a5f8bd908cdc068b30772e604f401400bfe5031cbfa0c6cb87b9c4fa1a4c6150252b1d1e27d033030234c0f3447af1492eb0ff45bfc887fe623d9951b4be4f499b8b0d43a16bb1f36bb141f1748534640bb98cb9c420e34b4a9040684657ea7bddd013ca7111f1bac858ca303ac4b53c4afb28b08e782b373ad04f75981fa61387acea479ebb52e52ab7e903eb8d384d65261025aec88cc8ab6d30f32b2e3193aaa4e76cc2f0798566dfc74d1ca14d6851780b53de9c8a12560f56020d5e2935c9edb89f50b2170f329b263a729e4f829c579b130c7650963f64e0f589de5e7745c8d6cf595fbd973b71fe78a6d31fd2cb858e2aa3c3e3f0155dd414e1fbf914fc07b19d2bfa4086362905e754e85ee5204b343c224b6a8e8621f033108284d212a1e8414060f42b74b1d90e2a2b5b22d2fa494a3ca1b022f4ca04405d00539442c81f19d22448cb8c8976c08226830193e42f244ab9efc9911713e2d6eb1064f6661410e5373621bec1ee45feb1a48c0b3b90ca07f262f88d4c5fd0e59ac03f81a69663548f9e490606e88426fa093824ca751a00f1263a02f887131cd0ba455afe1083b0ec84af44102f94838c40d7134c411630398386212c1b83e8e90cba15d461eb873180c69535b878163703be031ce72b99a3e57b3859f07ae638e5760e993f13742b4fe160e7b9d22cf11e6f021f9589bbec2a9cef47c986df0833f34036d96b2a03f3b3f4307f6d34229322d3e60bd7994adea88584600f3550a8daab26a8a20611be12830a42090900ddca90c6d7de0e11df646f0c5513b3f77dac8c7a48e8a63f7b800775c4458eaf40e202fd2d9d5e87dd8f976124923fdae8a9ecb9fd892991f2864b609e49a619fee343ad1790418b9ba194f70e221df3a1593c721117b9beccb0833b7a842aa8b7e9c96f69c225d8aa4cce8732100b2ff918f16ada3e0937e9d1e29a60d141c51ca37c8c439f9c54db1d475f1a6829b1c0cf9353e3afa82c703559e01e578d529fc668ec7905cae480e650f130a0e2fc98dc82c78241d40f7a05e8c348169e130068d03641a0de93063ec152913cbcdc1a43426283475f87c54af0510b0f9910a8178ef881eb57383a81325735de8ca0e347ddc0f4500424429d1428be6300f327ccceb8dd9d45a82c14645e098ea11ff50791df2901d12683164e0642847c43159d57c1da5e8a508e13d8acff0519f40a8060421b08d1850e79f48622298bf4488e685f1c6e2df23e548c04255c393a8f5463423f9234fcae3a7628a63903be4b8f1139c15a039fa28614da4bd10c173007eb9378d8e372137aa09f8c487a4d442728cc27c0b3893507d522a6f94ce4bc789222c29f83e5138a2ea2e43a9220bf0a960d4eeab8eb3b1dd083bed8414a284195f3624409097ea1925ecb92497088f02b63216540b87658663fb64842222a4dce20ae7d5aad78781eb13fe898b690137a91a8195905bec993b76c22cf8cdf8bbb9331e130f471c070f0b035d4c98c497fb1ca8dcbb17980ba1d49e06063213ec38ae14fb272c50ba1dd65538ff8a0efab2a285830131895076fde02435a30071be3ff14ea106c3343d557d99343c8c88d19870dec723537393f2bd2945c834d867705298de7fa837e6009a62fa973c9d9c4eca0c8317f1ccb22362723a095ef911020eb2138bea320355e98e3860329c6b98c3dbccf2556e9097cd0f36c20dcf83a910aee51e0b884f64104e84bf89012ba5dc4a0e8a83b605600d882b678f3e89bbc9f9c80840f685e1d279fa4c8a4c7646c7b49cf4b7907dc2c0f53620a45600b853399b3cc7446edb90a374d5097c8ddbf59aefaf682895fc0a8c06bf004e754eebaa0428ac0791f953aa044e0a8393680c479055094dd30bcf221d6cc43b2252ba3b9e1e69c7035408fa02a827e211af17a6210fdaa0c351c6c95d2f3947e0e80dc7f9c0326aa04439ba78228424e963ae57b1ee140d92b12dec19733de2a15a5675185cf07b8436f256a8cdbfac0e2d95645d03e77814f634c8eefa165d63fe2c3046537f8f728d6f93f3f5cd98095baa0914932a780e225f8e30bc59f9270083da2a893278295268b5aea706610b0e77bd4e1e920a57a0b475edea3019d5bda58dcee03a29c269ce56a4836e52300c87a3d6f47b4d58c340f4b811294570115cfa44f1d148f2941cf287e8246798a715453900421e4623307a186ef13a52dcf8231ca3f4079916f302211d4f3e9c42b92f3f2e52203227fb1d9a06e628479db853b345b28e05f30e4a1318e3b4f6a8cac2c36c3c44f5a5196b13c13bd9f06201e4e9d0fcf064192c7baa5e89fe8a0f1af702d780249e2f2010faa5ed41618ad628b0d3db3864401a7a0f8a422155f457c68fa3aabb2a0adde9019cfc5257cd162c7d341f39cc8568f0732b7e675edc9f021698838262b63efc58f2434003c421ed6a555a805378cff48cec85a5ad179900db3f2282179eff6c18a03b02175188711d40982836ff93428a73193e3bd5240e81041df9fe2a32b2799b0662f985465462802fd15251f82535474ca9f100141cdb695cfab500475e427c6e7809a92934cb8f15f7bd050256bc6b8153e84f2993855cfe0cc90ffbaa25d939c92df21abc933aac3e5415830f2258462e4af5134fe8e572dd454281a5e071bd1022dfcc8e111fdc02813dac34198276972ea03b0d14598c91384cc49f50236c749987ce40b543600b81f089a9cb0c411d6efc8bca339b3744546cabc19371f0f8021f5092c587b3f3161a898096a5cc533c4c1e2eede05d25106350ac29fba638492613b39a09a47994e1be7b8e698721dae9a5f01cfcc374860cc6aaa04a28ec282a00c2e541236e31c41d35e10f9520084fd5d6d9f60284660d9c957f61525102be7a384851af24be10a84b0a8942e333c061bb29fa4e8c15bd9f4741e752c3cdd092d2ec442e6197a1dcaa38ca4702d6400fc3395f61c6ace21e4cd3d12bd5e8ff6a7e709002272b935655fab06af3fbe35b2060913826f8de2fc4d9bcab97c84f12475c27c252a7524fbb9e2066c4a2227ff43ee44aee2248ff35981e78b504c3917bb0b3e22851f4f1f9dc9b326a53d1cb442a8816ff47b6268b294b5130fc05c2af740a1d4a76550f44c8a0bbe088148a88f18909f72d425c79e06e41577cc041d7c71f26972399cd30333fea900a12f148b40655263a2be52566deea32c1264b347e7537850e484746d7a3dea413e85e1cfd339e5cc2a6a20df4d1f11fdd0e7f8690c51fab9578ade2e10f337bd8af2481d47504281784f00fdcbb40257f85a1b5bcf225412972543110a4a45ac37f3e6107a19087733ea0b2c018ce7bdbc1a11540549cd3f1105ffb7d6fc4e0ed2be4a8582e5a444dce51a2dd24785a29fe9cb0da734e3550e3be5fc34b3bfcca58d90472b6e47b2f7e2ffe0721dd52b487f6a961c94012742af8b46a627953ce53b82ca8c87d6ac6fea50e0b14c48f93b54cc2cc3cf2cd4e8685136a235ca89e40009d25895c941791834396054eec00b07fa900afd2a3b7c9f0ab0c377205323cb3953f47a8034c8b7ba14f21b62343c13500307e1c3884a99b2e5d7fc24e51c9122b81881037955885b8f40410a9490134eff87cff089f0b9e57453c23e8a84cf66985209e7e0ea918f54b813821961e4b7bc6d79931ba16bc9230b75c2e9c33779337c180d27bc878036e8df51df541437682915c62793a0652977ebb7993d7a090c25d7f1e6004dc065ce6b9ae4042574a6c69382dbd01d7938b8708af6e7031afec88f924ce601145fb02bbc0c2c68df28d61ca193535f32db9b4f42595f7aa09340211d8fa037ce0ac909211f0e10500f9e26ec44658dfb3882e22da5a35e8c18541fc5079687f5e795fbd97be1678e78f9893d083e92983cb9012330ae6e39f2845050f00ab894e43c2ed03c8e74c9993068f4a1f4f07138c4210f23ca91ec778b929b82fb9113948142a19ce123ac900b92e7299002b5d18bcd3928b9134ad2b3fc30797ee80965eb59f27c643b5e267eca883be8a01b943ccb9d166f8080c70f1a3a3dd0578a477b3dff2fe9c8314892f3402d4ddec9408a7b7235c015b5317f439f1da795770a6524c2ec1df049d15153726540483a41130ed65c50033141292506e5b0740caa4ad283dcc2840a9682d4f1db02c0827e21113c9e4041aec18a9767c3101dd2a436deea2c763e1c567883176c9f26d6a9ef1340f967ae2dd7d0e52ce38912e09bbd2ee42c7ac41e8c0c096a64a41f0a8d36d938c7fcbbb83847d336c807cc706515219ee41cb1e0827482c4e546525a7d91f970e667556a20bcb226e74aa90204633969f5343206940227fd763ed86445ef25172206ce6bf9bbf273e2dc640765b2bc0e87a2076ad0c365b56abedac98cfb40a5078d7373fb5b4634f9d3a0112e8310226f7407ed6d25a0e057fa10e5a07249f02d97886c45ec181485844896726c2284eb24f9354333be6eecd9f1423838792335453c52ac4d9e622fc8abe291967f3402e2462d3b47b1fb7fb38a782f34b638001fa87c045485bc6c0a2427e243d2afa895cc8982d871b23e027e7c52c177813a9321f0aae49806b50e96c84c3eb5d2021b7ba37e1c77169c63b0e61b1d79fe1340837200169790430c4ff9479c0e610122549e499de5979902cb9b9c05c83e4878725476395053750bfe4ed128f41294364fe729ce3bafa0f0504d8d36672cf20a67f0b224314a3c0d1b001ecf30f12cc046e425632a38a82e301ec3802939804709be562502f42c1f12c2669c504f87d61958911553f2235f082623c0039e9a2124e5267252608c7e9492bbbf2137e96b0c5a73527279d0220ef22bf5fcbd2a56613ec34700fe9665efddae0c7a265f20f9d8aa20194d01acc7a343084ae7e4c0c3cdcdf9dbe3cf27e141c8671b02e5164c5cf0c80611fa95a54db62120041a6714f00504d19227d4c3d2674c68d9e837267f81d327458a15dae5928dcf1484912f1132e00f0869848a61537e0c4ab13ece9c19ee662f570692b7e3f3c8f8f14474ac725e6d427d16141dbe4d158a3298e5c659fca1f10dd8f6c5ea7ea09934289f7502277702d2f73b98b82826e6961c288d0034cf904c5e352248ee55654e46f4a1cd75c19dfe881b13f4d01e301f666c126a686e8ab33109cc56e6d0fa1510e872af0e39fec7ebe8e370387950330afc8a3f2c9c79c47334942db75565811f68a6f91a69604ee7d07894179c6f0c62f13bbea8429b0ca990fdb0a111be2ae0e0c19088f0a551a1fa3d96dad0b8b63857319504b5a24781d77207e4041284bf06080d77345fbe0a1546e8a909c7a712c6ddeeeffc923a2319ed0c93e3e913f55aac30bf012328af2e6bbc5f8b1caf01c9a437f5c72ae362e3f337f6b0fc020f26de489c2c21188ce4c722b0f7058412a80c220c9df047081deea11158908a1c148fc8c01ab4ce58fc4be42042d500a6f1200aeae4f539c2017d89e499063571b55d4437d1a3905f9ad5ba87bc0e9f47074416456ac1ab7195fc2a2492f891102e50046a2f8f350781735ad2f680c8c0a0c75ec13cc24e2921810c710e3801084a6acbc8625f02fc33409c8c8582535825cd939c7c7296ff467d702c0c2ebc98d2c247601d3894134a3e861b5cf9568d7f581bea729f0859df4ad65bb66b42e8d71d6f1c8808b3a70169c8474003e02f98117a104b503d8367a0233203f19e1e5dae9287bcab51895c66128b8e7da505ed9caccac12086847dae805c0555a7e05b07d0474992862a8a83e91baca9e515ea9a8fc5c12d9481273bbf400b19b4cb2a031fe9158f6c437371beafa78f9ae1c6c30cf9bdac2ece0795f4f14b2c64decb0bbbda8d421f27511155ebd3e4f528d985dab864095537ae4c6703d6a79b3605297029939b2b6a81d959d3269390154988a6c15056cb8e198b86404e6b1293cc6b0c8b9f92c9c5d760d1e273c582b30955947b391ba20eaa8c7a13724ae52214be7e1d53e385007c7050450c788d59937c2e7086c7a8f5c9e76cfd406bd992f595f21ee52b83e27e5180b24ca997816f6bf0e92bc127f43d48691356cab1e21b35f7c0d018d8411d5939f0f57720d6b74120cb253cdae56fa530fd940fa17c518a23fe2a117b331422dc0bfcc25dacf92ceb8e07f7e1a8960be2e2e68f9f16b801438e9cac8222f7742cf47ba494425ff150f52d9005329c3c81eeea3d0405bd1193952c16817dd9e1b92e0d8e1ca82b8317da2025370715fa1a042a6513970eb89624590e2186c3230921902b94c9f0b916ecf2e7a2e66e01096800f81fd2924968af4f8abc4eaa24cea2cd8edbe0a223bbd191d33982c8518d89e056d6a0ca1ec3f8438244fc5c862a996c51afaf1fc92e7e041717744f41a537a506d2d7083a96b29a2401b9c0a32d3903929030d514e4574a68994401a3e73557e44ba602bf559603282101a0be9486a73782d1e969f4e893bdc48bbe50d82b9f9587cd61c13a84fa29224f66c73b2a01adbe0f0007af20cfcf935176f156776db29e520bbe688c19929d2d48106d5d902bd8150aee4a82f656e464401bd819f27c3ebcc83a4a59f907b280bc9f2690bec02834cfb58b8f8fc244f43c1074bf6789a5cc078054deca881ed44595335e44f401ed7b30f65c8e2cc803d0147115c33b0e6ac40e0f0c85ebc100aae1615cbcb996527b1cd00f841cc9438c2c6b505ad04faa443f024d4a3691680dea622f0d866811ea71edf9e3b238bcef690497acaa898987d40b0d6d0be2e34951f1f2165819df40d8a49cc7b6f4e0931f6f478e967fe22940976390deda1d412321b0e434984d7c43a3302e806df89e68357a1575ee32233ea6be8f871dcf8e09448f7032f20456ada1246cb85febc9900c7ff9920da1621e2890dd178b0763bee68894cb02a3ba00154cd01281de385e8914afc54280972409057acb0e228f7bf5e287652dbe93203717b4c3ee634c71fb089b70f9030a69be69541737a56606f5802395f7fa479fc3c28f0f6468c1d7b093868a98f505f542c909ea85cfae6f65f43d51d7ad1ca3519cccc86d091a604edb3f0d5dfa427d3c3d874c790f81c6a75fd502e9474605e09a16a5c90122b072a31d012fa7d2ac6f96a8955914da73367b6d167285f92b8c9ca116dc4c7a15ef88ba29a1fb017d5fee680a33eb215a0ad74858c85fb2c0a06b28cabed60313a80f3ca9f2935a29be92b881f34e014e722d1d64bf640fc9dbb935e7af42c1f93714879f7254832eb25474549458e4313d2f2ea66dd13270ac3c90df59768229734518a0782e2e245e05b3801b59c15e2dccc6bfa1fdf917cd3a5445f0c38bdd51146cb117e2ff361761ab277196428289c221c00a7d90b64068640087ac1b0c419d6e2678b1cf1ff47920cf3f8400f2644e81f830ed9da70b1580870a409775d1c9e48130c4c8b69e043e7d530a85f0c0f8a85695784e5ee65c889d179f0a42f3785f5132192f6b5f2410139f2365441568f20b36dfd42b09d17d3d5806782170f87ca1163a9720b2cc4713a5f28a382c5f59e4387a3447b6b8a45d377e44a535cff288e01bd686cfe58fd3992c1280f28121f82780f4bc994f697ec9cca56fe31eb9112f9e9e05aa3cdf43c6077aa2e8c9d3a069b38328aafc0facc9c398183e8226a9b2998d08f9d3141c1f248e4f365375f6550981870c26c241b0c01448af44cd949b81c3f3ab0f0ba82911f1afc7670611d6cbe5c838fa5f1c3e9f25001334928e204f68cf150a00a6bf772087030d2349933358b5f82c3444ef8426514e2285c71789b1ea4d4c68e50184071c86d3ccd312120a5d5622850210eb12deeab4e2335522946f04811fcc2541412392163dcc2147b000843fcf655418b4145a8ec7f007882a480dbd0d429fd0bd22089e555e9cac6726c5434811cb29d0febc981356d02748d733bdd193997850e437c49ebc924c741c091fbcaca66891d735b0f1cf2194be565b18ca08c58d7c8008a4e0aa249cb2212db172a5528250031224e43d1a0b7ec30a35c8e68a7a06da4f5ea046e9cf30b2857ab82373039ef25ed613ee6df4e9a167b2949f60cd1c6aaa16251ff309963330ae3d1544b69c682995dfa2622753709ff812f9c8b188007ca31528f90bb920fb50cb848065ccbc9e4344614aa24e3e05f80445e2c38fe371a6023b618c3f44201da19db0e934d2533e1423e66f57843904183d0774c845af001a79516b94de5549fa346aa272de23197fe5c6decf1933e7bf3ef472222f27bfc549571e6096e67bc972952bf88637002757ae15ea154aa183a41ca90b857c634b93ccc0c85b96d3302a8b5101912db460856622eaca7bb4d8849e82b4fe2c5586f23978e2a9d4dca175ab80e7e4a6653f6be2fc441d537904a716cea252043401cbc377098564261188b8244195502477933ec68127d9b5c3e24d8d85c89c5238f058949c5fc1d09f2ca6d5a3208bb42d073a34e063f172f043943409a24a63f577d6d4a0b9b8986509a66e7d1969a4e42ff179f12a076e3d2aeb153a02d2966f73ebf55a9262ff2609c8dfc83af32b9e98a09292201d90813094ce30d33fb003849e49f3e299ace1bd95247b7c15142528284b467e6f090b457387d5a7cb24688f2343b21e34736043b6907ca1e921ebca35e8efd0a541438120e081f24a092985527b450b2ea021dc20f954b56abd1aa94deec648c19701dc09d598f26bf6bcf0593a6e7c19121f6e27868017e3ba5e4624356f4d91f8445b86643366239e860043a80d3a6a1ecf78d5ed6ed3e4d14def3fa3aaa647ad74913ad5714ca7897f2bacd9d4193b99ba5dd3b85d5326ac74b531deb051a76ed37d9b70aa8ded6ad4f0f118377789e4ca74e3d4ac75dbb23d4d8c37ecb66c99ab6a18261b030205c89abbb0dec8187632853efc71eb87991f793fd4dce177edd36a9bfa25573fc0dda67aff95ad3ef8f8d83ec2dc89f0330574dbb20da749bdfbd4ade3d44d13f7ebec5b977debb2af5ddbd6f9c2ab59ebb65b5d7b44e951a207ca630e8f1a47184e8d3b9a35dd185ed3659c128d80bb3d2add173cd01d7b76b0eeec9afeb14832e418593ab6b7c3818e473a803c57227c3caeecd15d021e55371d0d9e819eec532db053201377e207b54dcbcad4ddd7ae49f589d4ea51c3817581608082005de21186db2c72ed5b59b976ad3bc24f76c7cc55ab6aebbec11d89adabf7df8e33aaad8b5457236c84d7bf517f509e29f34e13e1e7f683ff9a4e5477bbba38fef0dcfec6f69c9e5af78974de515bf7cd090476f2c1764e106ece00aa9ac2f930bec3a6ce1c311227c67cf17ec6d16918316c0b06e30e7388dd387767e1435885bbbb861d6c967d3db9fb8b06702bdb1570b77803e1d796135bd6f9d7d2e936872327ee38cdc104dc763940b0b19b4c9b9b6d5da47e265375555b4097856b0a72984359d3d8ace02a3aae49fd4c99309bc6abfb743bb4badc8947381d3bdd0fed8a076fa613de79ed95d6d966703fee679beaa6fbaaef8e95291310930cd30853cd8fc423e06e61386daaac1bafef124e97ac2b22ac53ede2d5e5a9d0ad1bebc8897d2b7265b1b87abfec925d73bf544e84e17875f5fce8b8bbfb81c0110a47141caebb69a28bba0e4f76b32edce1c932e3183842e00840ec5b3db9af6556bdb58413e17823d5ddaee9db67b6db55a9f7ebd669e276e6489bae7ec6f14eba7bb9b7b4e5eec4a3881068c6a51ed8c9d480ae0a75c34ee3128a3b71f7a5cdbde51185bb1397dafbfe8ce9e3eb1ed5adbe69125e55ddc7c4fb3c285d99c5a98e57b7d56a9ba64a34c4764dfbda54c943895486b93b5165ddd86df1b6a5d8a9dc44886d9a546ea486e1ad5bb7cdb7b36ac9dd897dedfa7ce3fdc2fb8fdd309375cbd4d86d9749a75eeb548bfcbd1b7eb26bac572ceeedbeb4b9fbd26652963b9bc6b0ab755fb22ec986248524837c810c90c64ac1a442dc8964dac3d89d2ec26e72996cf7db463a8fda8cb8ae7af7a5cddd9736ffd6f74d35d37d57b575931a4ed5fdee655fda74dfe6ebbeaf7ebee9eb36997b8fe8feedb71907eeb6ad8dcdee75bac865dfba5be3534df7abb6bb2fc5db3a56388653b6ad6deb58f574d9d6b1ea35d3ad820d2ded851bb774ba6ccdd94cf772eb58f554b4edb1c55bef5846ac83e33b0a305a72b7514397b9463f46286ea38656574da306d1e9d6158b7b806e7ba3ce0d33376e086d88826283cd06811aaf6a84a9c1d66850233bf1186fd8f86e566dd3a5dec6d63d6abf342e16d535eea895ee987632cfb419d946c65b6fafbd3b8e699865d3e4b34dd3fdc6b0335d066e9dec6bd36572bf2960aaf79b26c2f1eed3f16a346a78d5dab85bd7ce68e3a8baebbbf1984ee6daae75c5e291c613a99bcc3486779a2ecb949a4e13dfdd7cb2eaf673ffda7533d7580f761af77e954cf755ba318d3334f8dc9d08c32eab63a7abdbbe762d938b9d48d85d02d2d03466388adb953983c7aaee3739234d86a7e63326b66e72c33a86dff58eebca802283cf9d28638d3894e180cf1291ec55f28139d21df9f88864afbbfea5cb8d845726df1a51dd80e932e60be0c418a6624071e45675d9f1b81783cc8dc7b4aa07c396ba5f3786f73a06030d8ca53b912c85b1e6ee0ef8014698fb6e1d69cceee10b435b555de60b30fe621998d6a99b99b62fc69c4de1f58de375b867cbcdf6db7cdb33e4c465dfbad42e8c3d247d7fda6d0f853bf1d8a6b2ae8a3d36e59dcabacbbd3077e2712e30ad3b6a75c35bc7deafd24eef90dba6a631bbd5bd5fa51170b7c5e29e5e300f519e9cbc1a44d55dc69b898165c64b225117e33605d44ef7a937738d4990f04b6dd048f5f2d65c787277625c06a781722e6eb818806708ef071e8aa453dd6ffb3a91c7b2cd22d7b45db75fcadc4c63fb3a91469d6ab77db1613655dbb4e97c9d6fee2ee7c3bb407756eef2ee84768e9cf8bac7639976590eafdaeefdce1d9771ba5523a0bb9d3956d68e8b5dd3897b7777793b894c5fd431aa0bacd3d0a2d1b0c59916802dfa5a3060e187451f8ba19b0f5738dace371ed3cdbdfdf48edbf44d9d7d819b6c2c4dea32385daaad53a9db7d64d9d478d43bddaceb9a1189c464bc75195c06bffbd9a64f6473bfcddd3add67d9eaa753d6ddd3c4175946b6ff56363536f7f63b8e69984dd7b8dd5add71ba8cb571b3c854eb778ddb3d5cd165c58de10a10ee721a03f198c6ecdfaad32712f94c01755f1bd3a5a2fbe3c463ecbaef51c36bdf7ee996740e5404a0e28b0a212a94ee44b2f6752e935ae9ae802ecbb66becb6acde31c6b40610673a76226338ddac8e53ad5cffd614d05daafb45deeb97745becfd2adbadc37d95705fca2a53b8ca4be188a89beb12e6e0c314605cbb144b7855ed52387027c271ba265d188639c4ab76615db6ff5676c3fab959cce59953e740c89d9283e34498e92637324edd8847f8b9fdf4e4c8e2300de316c5a189db83db0587062e106ece89ea0e5c951a5ef5916c0c5657e373fb158bf073b32816f78e5a2bdda49b26eae7f6233b1bbb3b6ab367bc06c2690c1888313c46f6a66dba9963f07e5535d53087383abdae6e7223771cb85b768d5ba78e935ba9dc2f3cf6dc7ecf36cd63d33d954e5d5d65bb1affb8178f6f60dcdf80345340b7e11b9ebbbbd6addbdb98bbbbdb5b7be76629a9e114d0cd2d70bfadabe1d56c8d592753bbb939d828fef4bdcea6fb6e1d66ed1e0a28481478eeed1ea208e0c41dafb059ebb61a4e975b5d93ab53ef84a8136098e9f00410d7cedddf7c7822c3b0ed943b5109e3e8eafdba702c9b265739629c4cdf38706eab6ed2ef7d6e166dcfcde2b9fddade611b1ff1f9eebfad9f480d471cb6a9b93b71d836c0449da189a6bb85e46e9aa5c9d6f9ead86d61e2117655d505dc6cbcd8e0b0b1ee4edce9eb4c26e1e7f6433a61d8f9ea1d4377e85094dbbbb3ebd08198b26cca46a044a11239862546144715a13851dd802ecba630cbba11b753ddcb24acddf8758ff1936d3653fd6455fd4c99cea43e6ed5858bb75e7b77d43087e68e23aa70ba6c9dedd62c5be697dc9ba8923ddfb45d91637af7a5cc75bf4dbca20aa51b6fbd6151bb3b91b9e395655716ee4ee64312a6e295b9fdde94b95f6dd60e497069a67ba9610efac922991b86dd903bc6ee4b9b5ae9ea916023e16b6ad6f4d6ea46cc8a5d378f658dc70d3b3593e926f71ba7cc56277713669bcc34703fe3ad4ce1d8e92653b6992ee1b498c28ece2ecf2d06f1dd71caaa7b659b4d277c3c3a63a7dbde56dde486d365b36dafe9c672f04eb66e9bc6695c1aa72afc2a775efacaed64ebda158b7b6d719baaed4ec25b6db6c1719bae6f0a83e9b48bdb55852e8bdb5545dcae4ba35f3245b26caa642603dbd8921bc6fe5bfb8cf18a634560ca346ebfe41ac76d0ab855170ef94ceb0253a6daae2cd476f5331a0353a671b34ed565be2e8e9499e48b6195ceceef7501e3ddb691e932b43435114e777d77dcd2c96d16e974e35c654be72adbd518c32ed318a7466632f0ddafdbae4ca3b15d99739b99b66cbac6acb38e4d2dc41f1b33c9572ca6fda95bed84bbcab6a9ac9ba6cb9d48166f78b7ae56ae637bc5e25e1a1e7722cc3ae1b440a2dad4700ab8977b69786e69617eae1beb1876e2d064c5e2980d3835baaa13a6a1ddd04cb91355279a1f27eabd8cb79ebb040c74df58364db6edb129ef5a00ee168d0e6dac4307e26e5dd5ac7512ff5c66dcee3665be1befec0c095175ea01b26c9a4cf3e159da1906108edc8946239bea810874f763ecba79c73d04910451c089cfed07b85bb223e06e8f635aa5738b9fdb4fbbaa13d671bb97b1d36d09a77131bcfb563576369770aa42c5bbd5742fdb02b7dada404bb301026d4874d5d7aecfb4d9668c6137b9845315cc249fba1a9949bed77ddf2d22049a8a259c2ee1bd95ea6a5c73b26c9abc2b1637d34dc64ed70c4b9a37349b61162c83e3c423992e53e974d9d8f12f5d3ad51247964de18e3addc8d8ddbd0ccd8328772233b9c629d38d9d699b2efb5675b937f400c543b18329d609c7bb4f757670d3818ff86459a712867732a96e385dea0eee44586d37594ca606b85bfd0ec73e8d61216b5f1739a6e3d56dddc6da3898727722ec26351cafadbbb6ab1b315eb5bb0484d3a5051f72b8c3741b7218c281b8c1921363a7abd5cd5ce3f8757519db74aa3a8d575df6eebfdd32d374b8a1cc06bc65bca67f2e53832db22333c9a7b65befa877ac74c75a78efb9a1064b4e8cdb0dbb6920e34e4c0135c01a2438d16de155efd7b8fdd2f8e897c6f0aad53675916153862319d43088c21005031b11e9be4d0dafedfe7b77dca6edbbffdc3ecda6ce36add3c4bd8c61a7fbeebe3655c9f4d38df5ebae6f534df79bea76d563ad93f86461a7bbfeedb7f944ea0b8d2e04fa1e5e9031bc10e6441876c24d37869d39f6bb630c2d64b260c40288a6d38dcb74d9cb74d5fdb7eee47edfedcc21a7796934aefbaa1a4e0153ada64bb7a16eba13db3499b24dbda15edbc96105576b0530cea58e57bd93ed0a9ff9b0c2b102bc47018cc3aa2e1b525812fd9870bae4e0430a6b4e7c77ccaeca099e62a76b369c506842d3dd95ae7ea6801a5ecbe01450ddefba379ca089ea8ef7db6491c73d09b69cc8c5dd7809af80fa49c6b2e9986e01dda1043e0901dcdfad543a91c9b4096ba5abfd9229ab530d37d3e5bbf188edaac9fada3576baafab6a37266ee23aa6b71386570da7807b11e0b83b3165935bd56ebc4cb6a9d97ee12204c21cf6223870f74bbaac66d93586f57ed358dd3b9974c27b102cbdfbaf5d8f47073e840007c29148a6becdc0bd12fb887b6c08618db8dfe1034fafab6cd3bde103241eefcd7cdd78d55b5dd3e6bbf7e0e84e7cc08098c6e9f64bbaac5b1b33c9d7d6c6b2295cb1d8a6e154efb1b131937c6c81ee5b9b4a8796e66c6b231b636326f96278ab6d6dbbf9dc630b74dfdae040f78d01df8250c3056d860bbc2c68e144f8a8cd885bd57dedba911a5e95eeda3add58c1588248eecec28709900c13d4481060281689879886a1d870a867981c0ef37a85b1198601091b1b227885208cbbd7f910c11e023d3676c6473686c6076badb526c26e93b96a7865ae659b45a62b2099934d06ee314d7684e154bbf17ef54eb67b39a689f00135076a10e178d56eacd5367dd7bd8cddd80f761b1ad03534c0c6c08ba10116056c1510e4c4ada64cb7f54b63cd7432d7c0148637abe175d5ed7a3cba76c427cba66bfca6cdd7d54f76c79b6d32dde4b10f661ef71250f7b56abbead68d58a6cb525d07c747800a01b601a2063c19c02660d55040230181eeaeb51bab6dfaba65ecbb06d0132099c28701246cbf3466d9b4ac753ae1bd95c40e1d886aba8f46a3ba8f4575c76972bfcddda1c3106cd0100c89bb138fbaccf9c6475d3cc26e9cc6b0ee8b37dc3af5ebea78eb0dc1845f9d865f48dcdd830fbf6c7c057027aa7b23f55e2e013f3c6378c780f00b4ddcef064ca6819b65d3e46edd67ebd6baaf53fd7363e56661679adc48dd6ca66f0c33d794851b0a9ffc50881c0a0bb83b51d56edcd7aeac33556e95990c3c6a33225973a7c9346e7772bf3a865de6baf546d6c1f1ed653cb69529ac531d6fbd61d0390c5e1806030c515043b4c9100d1ca27a98150d3312e68e8968692a9ddb46bebbdd7d5ae9c26eba68467463dd74eab2639cdc7f5b4d991a5ef5de734c171ee6b2e16f1abe99e15b197e9c3b71bf2bbc557823d73709239db07eb2806eac8fda8cd8ae4cd54d3f91ba4de13a383efd6cd537eddbaf869dfaf9eebed665b5dbbe29eb4cae695eaf1cbd22f01ac40be6e56197a6b05d6a76eded6ae0ee771ea6cb90ae66982e0eb936e58a92cb442e0a61b83ab93b9e87e17a826b04aeb05b7e6ed9b995de12606b8ebbabf0305b7eb61884d5d2e4ee2e3cacd6925aca5a4377e7f3305a78682569bda99a65256cd68e5963b22485c9cae2ee303c4c169ccb228b25c99db8e174997c9dcd3a38beb2679b6ae5aacbb4bac266664418deedca7c77bc55edc26c1ac329abc27b2bf7deed9d2e9a118fc73a383e98ecc9225718769b5a6dd3b1add47a2fe38d2c9a11dde47663ad530dc3ee9b4c35191991a8cbc888c431d809b71b6e5d383645ba6c8a315d86a68bf0987e5d5da6b61bb64146248ee9321a47bd91b166d93586262ee3c0ad8b66c43a383eddd7aa6daa749b69b24e178f476d467cf7327e9d4addeebfadfaadac4eaeb11bb8e3cd74e1b223998d1e5a9791918da93b6e9d2e1ccbba8da9ec1a4317e11d71342c24f7df1833c977d4ba08a71ad670ea849d9ad8dc31acd9b45d953ad570daba7ab7eebab66b1ab76ef2ddf166a66fda34b62ed38d616772b7aeaae155c3eb724f13f7327e265bf78dd325a07e26f55eee118fc77719c3fbdd30d10f5e5f1da72dcbae803ad6656d0aafafcbd44a3a4d3c3ed3a67663a2d28de195d5edfe5bfbd4bd2ad7e46ec27a2ffb9c6ebbf57e9db0de7e691df1a8aec755abfbddfae944ba31bcea63ebae724fe7db5197c14d77a99f6fbaaa9b09a79a6537a086535dd6de7dd07b48a70a1d6f1876d3f0ba6357379f7bba2d73d373d3fb7399da8d8f65646379ccbd8cb556db14e600af80e9ab2ee315506b3766dbd7898c231e8f5aab1b4e9166f10abbcdadc6edcad46eacebe0f8f4aa5c63f54d015f572bdd64aadbbe75bffbcf85b51b178f6c9a745b148bbbf9dc3b6a335dd4afabdc48edc6fa787c37cba6709a788ce1ad1eb51beb8d7c5dadf566a6f0f14884f7566ab54d75bc2657b619b8dd98e9be4a0debbd35b43367dc3a5d66da0607a675ba8c6c0dedcca9cbdaadd2c1a95b6d9dee1bfc6ea6136edde4bbfd922efbee16d0cd53374cb6e6d4656bce31b696755de4fe5be3646a84d777abaddb84f7dbf6eef5651a37f299325ba83b76ba9bb9c64a6ebc6a056be9eeb0fb6e1d9b55d3cd6a37d670bc22f5aa543a95eb128e93674411c43433b367bcbe69b38ded950c7757d93bb57583e3ddf7a67b71bbdfd709f784dfbd2ad7d8b5db7a7bf7a5b15edf5a07e3410057585cf5703526808fbb3f0935345d9e34b5bad48a88003c6abbe1353557ad32b03214204dab0923ced044b1b2c12a40802bccf4ed73dfa691048933344babd0aceab16a0c2cc42a2fabba04eeb875939b990c34ba46554d43a829520565c219da1f5520242970f75745b693ebdb443b5ba3932a4e250101883534a888800949704195c1dd3578d8a959a7c07cc972f7470581990c04b106e5d45898a955a6b0e83975e1d402786fe56e3e636632300d6d0411536361a684a5e07cedc5afdbdcec8e41a08928a50696622b3524b56783d15547846049b1858d7a348a8750082934529ad40352426632d0b86397b95f7535c27b2b77f3191bdbbd8c8d6a9b1a77f3191b8d20ced48ea0c2440949a4ed896222ca86a800c20beefe61a274b8bb91b9a66c52ed2c4d05965072eefec2c340b90aee72f70f0ba524148fbf507ea1b6bb91b9e3d5b8b7f2f9a66b7255ee76235d38de309c1adfad1c8176c60605540c4abfebee0f2a490c6f556d373c424418a800eefe619f7c7c623dcc932067e00044d8a71aeeeec0c33ead857912b5e6ee1ff609cf18983277ec4ceec06d642603d1ced28acc64a0d9076632f0838edbfdb73ded7177203edcbd070f341871bbd764eb7606236e37f399368d1b4e37bbf33a5d7277ba4e48c23a159d18c3bbafcf0933f56e3ee3742fe3b2bd8cdbcd74f6bda9decb78ab7ba9e174a935e0b6d303dc76619dc0dc95ae663adbad8f47bd977b30bc614ecb35b433e7a64e3b6ebf6b5cdc6e660c3b71a86e705fcacea56f1c28c7b26e4978addb7b0edecd675c2cc248b875e174e735376cc67455249bea36a9b9bafbda74996cba7a3bdb356edde4fac6dae9ca8812a66993f7a5ac52efa91b766aa72bc379bc4be30d4d0edc1d8d088278f627f77697b7a7777c7f340fbfc48d74df180431cdac5dd9773303cdc23251815fe2da4c8d3b4effd6b76934a211d58820ccfa5c36138afd3ae3742bf5f1cfefb8d7d7ecb9fd9cee1ebbfba7c214e8ee16f6ec5edcc119e3ec5edce519e78c2cdce0e0e458a8add37db51b0833bf3499dc7e011e089020400600710702c433104781781220be6489fb0017e0eeee4a80b8002040820001b204883b10254084bcfb844b63208820cce2dd87c2c32c79b260018677cb74d5367db586f7bb3a73ecf719af6cba61a77663ad6eb7bdb637867559728dd318e6c006e8c26d66dac6c9b4c974e18ac5d65de177ffa1a539e1678ab7b7d2083fd3661b0ca76cd2f8ee6660ca7c0353661b5b60cadcc60da7c836b43427dbbbf10253a6dbee312b59707757d9d26d357dfb9a2ff262386db1c66b4ba76365d3769d4bae70bbbe71a0dc936d36dd369c2ef15c654b17b7fbefdd78305c2cb6783a93f668e5ba9b815bc3abdecb3d5de2687c5de351dd4b786d57a57eb7caaece37f825c2f1ca74ff3d4017ce00a4490afe4848e2e11ec3bb35be3b5e8dc9dd843f24f79fa4a3a43bb5758645022052185d3c1e759c6aadee40104b385d46a2e1eef1eb2e61edba7171c3effedbaf6ee9e097b884d36572ab2e9cda3addb9d8b553375decdac146c0bdfe158b90b01021391ddef375e3546dd33a367d77f38e4d99af6b07c3290b073f533c362dbe4436fd50c3c31c292212891ce2cd96c5ae9d26c29a4dfbda15d065954576ff6dd65874ede02dc3ac58dccc356e9d2ffc123f84390ae0ee823cac519cbbeb62992e0a1020408080014475bf6edbb7c271bb5bb7c97493cd149ac8a6ce3899c629738de1fd4c991a4f13f7db7c779ceeb74fc3abd63a865d3ca5ebbecdcd5c63a372bf49f70079f1ca5c5bf825d3584f65f72a03f0dd7f77ea6e5fc44de7fbba70736afaf6baef2b87a7eebf77c33b6fef772e09afcc62116eb79f1b178b70b118bf6eb3e98461679cc67a3bd9a66cfa66634da59b03dc2b8cc055a974c236449ce9126b4e1a81ab72bfcd188be02c727048d7213a87742ba76e1699c26b5cebae70bbe3c06d4ce3544de3cd346e66fa2ab7ead619620915a2434857a12184541f74e69fe464f01ab87a3d95374b6fc2502f7f4b2872bc87cff3402290634422e1277080711b28509de813f70f26d87a0fa2c0bc2353684fe60a1ed48dd89aefb085283fd1e474516a61d9d09bd2e72af17825718a1c4d0f593f37c7cb0dd991a1bdf41cbdc99511e80c34c6675803e907a9117d2ff221fce107282bd0748786b243ea57a95191cf9aa37e0f006cd0af01abcc0a14949cc6a9cbb92089f26285383ddb960032991310fe6990870fc0ae800b1f80f95064f2bc58012f689549706e36ebcfcd04a0e0093c18cb194e317923aacc77c2f67c970b6c9ccd542007a42af0f64bf7369cf754ae4f35cd8bdbad37e443102dee6e743e8d6a0b84eca9a63b0fcf2fe9b620c22c9bc26922ac74351350c3aff38984e9f0dc88fbddcbed7c63edc67a471a75707c9a48c6b269bc6ae5aacfde753bc98e47fd2722049a7e6e169a08bfa926c24e17d06dfd5aa8ef8e5bb434e7511301ddd64fbbf1068489af6be3c84cf2e5bdee4eb6e956e10d3b59367dae7f6a4a87e7a699691d1cdf9d26aa4f7619bbc8310dd7c1f1c51be6a059d64d1f5fb7eca8eef645b178dc03dce37d6fba8413c0470c104b99003c1b00f7dcfd8a18c030f7d8696cd36480347efa68e1a3678fd81f91bd95da8df50b054cfecadc75d1e90a81173d4e2c75707c6013f20c91c5044fbef2b5979d34118bd1c07b2bc14288c1aedc5d0c76e4626e0a1773db5ccc25ba983b26e0abc25780353623d6885013228d1a9ab4336866cef8dc739977ab8899c9c0d7d5e1ee0132993cc6ddbf101c6f18966ba6efdedbc531937cef869def6e3a5b28deaa65ad7617c11425c6e4a28bafab341a8bafab64eead365340bd15622e64b6fc200c736c4f0033e8ba9877979727a72d58b0808200831af8e28505e37d3053ef4c17f6987bd46209f8a9725d8459f9d171f7c445ccafe9f7ba804e18e984e156ced1161ca298abdbd46efbb6af3376955f7db4e040e3eecf378efb1a94050b8e16ce4c06ea77b7edaa2f88e108e0444a57d63f1ec68ad81ab8dccab45585fb1eb15582bb6b87ca115ba6cb2488d7d5ea8eab524745583665a94296946501679d4a345514b13e45fe098a581f1567d934890a7a1214ebdb739febd3ee300ead7e6de1a5d4e4baf8ad9c4865d3dd37396922a674f0e6574c966c474c942409eed8dbf5dd0344b2c7dc3d3b5145a9705ce5e12ea68e89a90674516d573f5da68bf04b3c9264a2ee04468a8825d7dcfddd33912141a42a779753258684826cf680e1140f2d4ddd6d5fb16807bb1d15ac9e851815b9fbeb6d6564cf94dd79c5a291990c2c16e162910ddeba8c2d5d61c0baac0d2d4da5638b37bc5f3c986e8c2d5d61148b46f71c04c80f77311bb1ee6be1dc86580d53647d4ea4bae33d07bb35f6d4c0e22e5663cfddc29199e42b16b7ea64f7f1c84cf22d6b48388ad1884543902e96c910a3c1c3ddcbcceac4664872f8159bf1466c861866922f18434c86ab19cf197cae8b3a4ec9b6f3b9fdc6c464f8d171aafd8c71e06e65a8c16232823b6e37b3e9b2fb6fabf16e6378c74654c781007e2f5b222d3c221828e0c5071188034b56eee2e860946208811f5f6b4f6cc005037525986240d23822a296870b2c3681c9c1a3bf1604d022a46a2d28f952840d042c308c75ca2864127238a48703a4a4a6365c3a471a8db72e10a0a10f0fa20cc3ccde6820abd3e90d0d6586299f20bd3881414230d0461d1e47719457452b432f8394b0629ada3c25589d5dc941c252afba2029c06ccd78a5f7e17881c78f0b85e2bc3a9ad260e441295ba21ca41a93624d03f6209784c0321e637c7aa44ac242112f302a23c0281c303269af0cdf0718c611775a917adb82c76948a40c9823ad05955204dbf4c8b1791921f10120286900015ea91c849961eaed0d9b9763a0974077794488769e0b32d9e8c3c3551958737700592c024ce73068a547c09683b6b337481ccd68c60dd08333e323c1aed39ea73492a0e481b974c55301e39703625ad51399e01e5e5336314186392383945674e102db8f488b3eec01a4e471e78e1608034404b313345df804f72658b0d007e202af9d455580a111aa362231c6a0e1a2296dce0812521188a03a14af35f41a00a0a8c0018b4a0a351be470812276688a88f4489e2e0d3ec2f03ab421091f61b020f8c6490f31cc32a588c0d0126a518b227c45ca8450fa9226c80782825442a45d0b0a4d092129038c35f06bec5b952b9c0c341ab73285d5d6451a5d65abaec6dc7cff9c7113cef1e668baadbbffe312d323c34a2946195f676b53f94546ec6bdd1750c7ed06d4d34418e98497c9367ddfbed024402b04675960ba67162cc6b34d5537869d2bdcb39f7bc6b1bae7a5c711cb6393ee1770db91c96b6ea41fb13c07c4ed7c4ae9cf996157e7327e63572399ce37093b9b9a4927987d539dbe2edd565dbbb7b8bdbe7b5a8de16211c974be7087d835551e6327f3b84cc65bb9ff386cc02362786a2e245462777bc4ec5ce53ef7ac14b353f376cfea18b13a3cbbb908ee9b55dbddae6cbb7e9aeb780602fe3963f8cdd1745ba61f8e75d93743065f0c182ff6f4f25ce0d9d5b560b142458a39b938b837b70f44b3b25e1e3a908d71d8a02103860b167af5ea15a0d7d7106361ea871fd68b178bb8659ce2319df05a08582f99bead85d870faa6a66f03ceacc82046c7e3ed2055c8f034556ddd377855e9c452807287d1e0e766d1ba2dfcdc7ecfede79ed300622984b8fbd6677a2b53381fddfd8deefe29c65c17d3e6f434d9bd34fabd2ea07663edc6da3ddfc8365c590359a3468d0b35be0c04c0100084985c0c07a104b588c5794a3b2382209e99b1627171f04b8c9d4ca49a845766125e991fe0d0c08d89bd0d719675baff8ea57b7ee19ef7f4f2dcf3844ccc2e3cb9673c663230df65bb170bd678b3acf36dbf2edc9bba1a994eb9186ed24dba796abb6378c7489929ec64f16ea4dfebce3d9f6f752d9e918895459b2ef7f6ebd6b94df7c58be174b788dd986ebb55a6dbbe73f0bb91cc5db793ab0b23afa05331e7968c5d3bf79c62ceb57bdfd477e3b9766cbae35cbb40399575ba3196c93865c26bdd66a676309bcebd5f3350ce75f7e0bde7fadad52e30ad73ba6ffb227edda68e552f30ad83e554d655b15964cab2ceb9376e5fa8bb7d91cd101d90631097e1127da1fcf691dc509c5057386692cf3db799602be1ee45f74c22afe51159c39dbb1d734d59b82cc24ebbaa88b71ebcf7dc33c50bd146adcc5a86239606452c2d0642a9558a4a780007e572f78c5c4db8af424d41e5eea88c66de9a490a7ac572f7201a3169f012e83134c2ddff84141a77509274d9e3eebf245505b257c8b6c6dd730bb913a396705852cbddd1054f1cb1ba82650f2477ffd252c5d64b2af242e1ee8f288b212b494e9714b97b16352b0a0f5d57428d7077e19623589665221c9ddc3d6f03885e3196f85442a20daad124c7a6d7cc2c4c98471eff59e251b8bb87a38ba151593b2382308b5df715be12432bb0e33598a54d37d3a41170b741466efe7962662372b1582cb62e8cc3b8d577c319dc1dcc3d868b815805bfc4f4dd1ff2874ccc66f19b365f278be79ecb3c2ce19e6c7b97c6a9fadc2c58f7dc814ddf649bc6f073fb81407b6e16996c551311b8d5d60f2d6dccdd0378e69037640d6e6244179e33640ccfd709a7fbdd6bdd75dd716cba2657d5b962ffad71cac26bdf6eb14cee3db9c0addad97e6b1b2a5edb17696774172cb87b30eb0aee1ecc13d8f7954bba59c21ada99138cce0033310fa67208310f78390284070e1a64069c7ed382ace03125101b8621c8079e8481029980518cec455fabe9c4c6ca78897655d33778f7a578f0bbd7a7728de124df117f2237c4361470171b730e96dc5b772d8a71e0db3a563d3c95ce4da55b22b681c8861af07e1f621a72e8d9ddd1edc1d9bd5861e473ab735b6d74cf03dc3dc087107f1f922ffc6a8c0f5f75f1e12b2c5f7f22832577955d63b8ffa9b55d953bcefd4d9572f757deb1ac9bfb9372434b7ba6efeb26e26cd49a28b567fa860adc6a4bd7be7095a03e7972ff4e9c8c3b4edf4deeafe933b93f26f7bff4b7f6b9bfa54a94dc7f9224f78f94beee0fc9fd1fc1c1d6b573ff46eecfc8a95457f75fa4282349bab97fa278bfc9d685737f442becfe870cb9fbbbca96cefd0b111ae4fe820278bf40ee1e60335d3df70764e72a5bbad76dd7cd4cdbffe3c7fdfbc44a57ef4d55c070dad2bd3b4ea66fba84e3c31a5ff77db71b1b9b4ea3fbef69fb5636dd3a56f8f5e4717f3caeb2a583ddffcedb71ff3aee0f00cb3aedc426c070b2b131b0e64166d465f0d8061ebaccf8441a97c937ddb091180465c2847e9dc9e011a10831097beeeeb6c20262120a0479894588e4ee71bbf5e2dcc4204031aaed86c5200c95ecd6232ee315308eee848ea189afee6bd798dd2fd3d59b4d35318e371cafcb954ddfcddccbe65e99da7d9bda060cc06d77a4c174f58e1a5e59785ddf38deb08de391065edd0bad2a93add36d01db15769380bb0ddc36e4e2eee08a4523cb6ec062b109d3b0416303ea326de6f6c1fb6fed73d3441b473fd755e1c6b0faba80ea865b68e2aacd9c3936dcbac978c3c7a331dec723bc91b19b26a6ab2e2b7b77ba99ec4e89eafabefbcfd5f01ae72a372060bab5d2d5e96693c4f74d931a56f75faaa62e8b749ddb9943d544386ed734b99bf0869b7bfbb93f9d39bd8e47651aa7eaaaa69b07013ede8a116033132350c1bd697477132e36008fbb85136dfab7d99da78fb033de7d47bdbfa46ef797e3fe6b44dd6edde7b29af86e75bf6a9bc2f186ebd435c5db7b4e000222ecc6cd75659bcc74031e7593e944ead4d5d34478095882cc832ef1ee956dee39dd417bd07b2b8d63da846eaeb131de6c09b2e61a8f25d9346934a175bcd90f1f74590c3bdfe3f1a889485d46d65c63edb663daecc9be29bb3257e76b16b769f2c8a6cc176eddb5b9c63a4d91c7bfe3335e5f777d9b47d8752f34d7f85dff2ee81d3b9b4cf7787cf7ba95da4d8b09f1dc77ebf68909337851dd4f1d698be02c4b64cc241f9c8edd764cbb6f5c104db1e9dc255634fba0188a462c8841175dd469375677da5fb108bf4431948818caa7e13e98a9cbd63a50626816cb74b429b1acc0ddcdc4fe95d81f2ad345751301dd56976d55ec577ff76ab684d3a59998cf71d76d26986bb11808027edd393fd77d5bc2a90a186e9d73ea66e177b78077cfcd0276e19774d93775bf2e9cb678dd3899ceed3df77cf7dfcaee38f8b959c481db0e6ef79f5c2f43537afde8c5e7baf8a2f5e2d00b2dd3c5325d74228b45f8451aa7717e49f7c9ebe8ee696ef22a83d35db360a6b3d5264c309dad71d71d5ddcb5a6e3f46dea12ea7e775fdffac64ae556758a9ad065cbe3e474ed41eec1e9e2e1eaa12174e95ca1ecf4dc9cc562722d169bb0badb17ef2e1699c940f825bedb8c990cc4a5cb75115677e03a87ebcdb840a45b75e5fee1965dbb6a5d6c1118338b45d856135b0e6c052003a6969a612d28ba08ef358b052ab478b97be0364b5f676a41b3e986759ae774d36d6a54d7b4d9be80d395754bae4d37b936ddbd78eb6dd5ad83f79e8bb7de6691e98e5d3bbfa4dbe275d9147ef7dfdabe789ded8b66e0ea166f3d155b0f76b2cdd7a9a7b64ee5ce735504cae5c5a59b8563e1e2e64e26ddf2daddbc03dc764de6ab62c7b16c0aa7f6c74cf2a9c6cd229dae5a2cc6e2134b0e3319c84c061afbdab52f8d61a359aca0bba3716079c1d1aecc116969672bfc849770aa2270cf2fb997f1ebd66dd54d3eb79f99591c8b38156ddf0ac7b18853e1c6f17e6378cd7b5fb75d26f5f6e276c34837f78fe3eeef26a7ca9ce7b2491d18375d37868001f0ca26f59c8001708a44b64acda6ee9f23c3007491a9fea6bb7f1e8e87d0e01507f7efe0f6b7fc83990ca5a2f3b26baa9433356405e2371f83fd369fc87c60b82a4671992c3ed3dd83feecfbe568ba690f3f65a0bbcbf0a1aab33870178bc626bcd737865f621cb85321711daf8fc3fd5707dfe7feca571fe9fe69d8d1fd8d68dcffc68b19a2ba936c370c6f63c6427c5d6599baff5c669bbe3de37755efb45b9e3bc58408afe91b576b80bf8247a0cb94228ff787a451dd4f3786050c685dddbae50d4b79c28174370e4bc5b92f936972880b09a2c4dd591f92c202bfc477388ac890946e77f3ceb51b6a22e4434d787ca8298d0f3579f1a1a4593ed424c5879a8cf850930e1f6a6a7da8e986bb83857d15f8ba84cb879736f9f0520097def8f01297a125a50f2dc1f0a1a5371f5a42f3a1a5073eb454c087955af9b092241f56ea53e98d0f2b71f16125243eacc4c38795581f567ae1c34a716161062234081b4e08a374c98794f6f890921b1f52f2e2434a50084c5ae5c349a07c3809910f27ddf1e124393e9c24c68793b2f870d2141f4e42e2ee391f2060e0d09a0f0f69f0e1a1063e3c44e090fbd0d0291f1ad2e44343887c68c88e0f0d89f1a1212afed5c0900e1f1a8a7d68a8cf8786f07c68286e5820010442507c48e8870f09a93e24c4e74342743e2424c287841ef870502f1f0e72e5433e9b7cc887910ff9c0f1211f2b3ee413c5877c8af890cf0e1ff259fa904f0d1ff2c9f3211f361ff2f1e0433e137cc847cc877c02f8704f2e1fee61e5c33d9e7cb827930ff704e0c33d717cb8278d0ff778f1e19e29eeee808230c18021010307c4083868c060c1d7707f1aee3fc3fd65b83f5f8b329e22050a982ed1d49324875fa21b379f6fd2bdcbd0d371ff89209e9925f7dfb35de3bf4ebae097d8898bbb4e6ed54deef58d97f1deeaeb02c2708a97becb8f31e561bc70f7773fd316aedd9a327ec174df39f7dfdbab9eba63d72e76ddbcd65dd52dc7a6ee9f975ce3cd5cc6ebebe6fe2efcdc3df7c7835dbb3b770fa66fee6fb7ebdcbfcedd832d822c3635dd7d93dea63877bd69eca8a9972b7787ddf6756ad2a46991bb1f8f7a65aa7bb3ae9dcaba2a005d76bf3dd9f6ae7d01abad738e6553a69eebeebd0d3361196aaab0c782d0d010932b13bfc2dd1fcf2bfa47efc8dd6df810d357ecdac1c5b0abc22d76ed9e6feac683fbdab5d94cd977ffdd89bab4e6452e05708fdd56afc9dd6e3d87a53f778793305debbe01ba2d5c778fe9be7331bcb670f7e862d70e70cfb9ee9e084a9dccde5c770f4e55d3b70c9440b87b93990cfc007fa873184ee6ee30d40daf71fb6f855f6772e7e1bd78b2ab8ae7daedbe14cfb5cb8b5dbb1893c6ccd49d7cddb9bdb9f685bafd926e0b75abed9a84771e9d9af756a7ee259cb27a31d4386dee3c35de31ecb68861679cba015db5959364e61e6997bb1323994997fa4fa770747b2c9bc2451a1269873bfcb755621c9ddecb3da2565977f9a6effe73894a1d98d6115b57c71676ebfaa55ac96ed88dd3c5ddaeac66ba71ecbe69e2aa5f67bcfb9e291356ba709ad473e3f4ebe2683a75bb9b6eb1057cea38d5effedb80ae0a4d54b7d17db70ee37e9dc90db7eb51b769b2cc7db70edde1c9b2e97e3b28e9b485bb3cb919dace4dc59ece93db7393cb4ba1e5def49ede8b3a4d6c77d3158ad1bd0aa1844fc1c475acd5b4510dd7c5776d04c275117ed32618234cee0ea7fad863c7516fb5c78eec8c94309dad26a6311c3b5dad74fdf65b86d47bb66e9aa8894fb6758f3a3dba71dcbac9bed665d3e351c34aa5bbd5f4ddeb9b261e8f4e57863e1e8fba87d6699cc6e9b2b758d4656ccc75a9d74cebb409adb5dea1b576dbe3f1a83551e91e3f9c85208176f681659dcd6572c74c3749443a97f1daf7e143116ec6f1f2a8f7d6d344a7fb972a75bb6aa5ebda69221cafad736f7888c921377722070ebaa8aec63258b95fedbe7b461ab33b2e0e8655d655a1a63b4eafaf5d53b5ddcd40b9962eafc513d70e7e6e16aedd73b350e3543a37d78ec2a0163e2c64a5901077f7013b868472b9c3ef934dd926bcc6e9d4fdd3dcfd5fcefde3da17aa6b7707d7ad31ebac53b7fbee19ad6b07d7ba49778fcedd83d5bd93bba9b799a95d7237f5d0bf4156868202697f098236b24836e6e7f6d06463c5621c91a8cb7668adb576978063c5e27edd58afc78e0f1f3e7cc81df2c4015c717762bb6a5775eacd05a0e6aeea8403d00eef55a57b129f3131b6717401f78e34f4869d71aabe29e0ebceb57febcab22bb3ac751a5bf748d4046869c19d935b605a572ceee9d8fde1dc3df84714d16dfbe8d2d7990effb8f9c3c43dd93adf58973d94a11f41ee7e8c8339a4afd32d6d32d7adbaedebdc7e2b7b647e328f2677e790adb87bea433f201c8d28c2ccec99be6fea4f867dd8f856cd867da20cfb48e853c09d08036e3b5d06ca1757742f36fca2a5f34bba2de25d17bb76f0de737a31ec97745b00ba2d62e79d9e9b9e6b97bea56fcf36ad73ddbd9df78c9b4c39bad8b58b639169fb42ddfb75b26b3aa7b65bef858e15deefbfbd5b2ea047937bfb3a9146d8c8b269faa6af331de6f1a35fb7081750398085b33c1767c28fdbfd37c443004f1000037776dd5165a7c9f00ea63b90ee0cba53e70e1c7766922fbdc3e7b1b3797c616797efd62d9bb3b3c7ce14788d53a56eddb64c279bafab3ad3d799066e63fa3a536632d055b6743bcf559d7a6ee9eb748b03e5d2d7e9060284fb7f70fff475a61f8875f0f1a8e3d4a8b556db55a9dd58db38c27a471aebdf91b85f178ea877dcaf0bb712b7ea32f5fed3c4b5e9c6b2291cf1b8f79cbb77d4ce66ecdc5be92a895b59e686b7b7d2e8c646e3de4aa3ab6c371b073ad7a61b712ff7884a57ef1470ae91d8ba2b9c26beae521fd7a69bde8bd865f58e3a3d1eb5ab8b6830b4992ec2705ae9aecb3e97f54b96c5afbb84d574272f5cd0ef9abe4e373a3cb7964ed3e1b9b56ed3696cd3640cbb4ca61386535da6f66d56c96e385efb5a97d570aad3b2639c6a1326f45197e9189a086f7575ffd2be16deb033b9f6b96cecb27099199cbeae723bb7d3c59ebafbfad23da226eee7aab6eb66beaef2ddcd657c3cc2ed53b9befb4fbb313376bac854abba7dd3cdba6e53b7ee1a18bfc9d48d892fbcbea9db6a259d8d63b1f8ee238dd818ef3e7d3cb67bb9379988b5b41149e53ba6d5ddf76e66ba84b58e358edf356d6a32fd64dde618bcbe4da69b241b53baf0f1a8d5bd4c3a61ad5c8fea1aaf6631bb3a91f00ab85f753daaeb51abab516557a7daa6cf368ddd36855576af2d8ba789ec9a6ab58563a7dd9dde8a142cab6365d3f5ddf056e5eadcf2e6744aa789ad0be3589b6ee9eb7423a6af336dae4bd885e19ddc2d11de6b6c8c5d1626a6afd34dbfae53d5b1cbc2ea869d2b1ca7db5906a7897e4976d56b33d5c7230c07139f6ffa479cd3444d8cdd165ee13685e9f0dc341170af7f5ac7ce66bbae4db71877c4b599ea77fbbd2ea052e912b51f9cc64aa59e869f9b05716da67a9a18a7891e3460fac2cfed67dc3151dd1b7637ac53bde3149ad8946be106a7d7ee384dc2799ad8d7ae6f0cebe39a32761ef546ea74fd0bdcfab9fdd4bde11e20865b8e432c0e86577c68c5cf3d6ef75fdceebfd8081b5dd509b7ed38659bccbd07c74cf2359949beada73af56057d9d2b5e9323db6d79d63d9148e4de18ac5014623bc5563bb55755d1ad7666a6cc2c5a292dd70b1d8965c59a413afd97473f78ac50c1a4e75fa3addd8d2d7991a7330d5b6259caa60e2493341e34ed4ba65a2c25de19449d812476cb3b9040a71095f0cbb4b2560d6a5fb36951cdd89ea938557d74e895b1257c4d6f96a375e01e155e3f5bd29ab912e8bd4ecda4c02a6d9d7ae499aeeda25a1806c9d6f1aa77148a020518144c1115847c41c11e2ee1a4e976fd37d9bcd5485dd8ec718b075d736a451ddb0b34d45faa6cd3635dd4b373785514df73235ba7dc6adba755b75997a46d81881e1c427b26c6fa53e36d7f85876dc5b7974db5b69dc5bb9b7d2986eb6b9c66d6d6c7bcfb5eede4a63ebae30b2081a77a24e35a0fb328bc01159e54e74e3cdf6b52bacd3b86d8fed75e7888021c270bb37ecd43b0691a6bbffad71737d9330910e44a633e9aa9a752a9bec5ebac8214a868c10124ac8122121829c0a2225085b900040f638f1b88cd767bb06a52da8547108f7c19e854c211a01040080820ec31000303824180e488462d170446f0b0014000161c4d848a53095875996c31432c418030000000000604066300c00851be8903c5653febe17452f432bc2628981141d5394901b58fbf31d21b18f9f306c111e56d26b4747361019499a02f5c15968194d87a2bda47baab470fb115de9ffc229f67005f338684b3f4e6e8aa743b6cf592b46a482cd33672fffd90a7eb60887219f8d77aa5f2d68d782f167cb07839bc569c267ba096cd21b49f9b42efa4e5c7afe9c74837780df68c3340f5911f262d41c30faa794deaf59207360471dbae14d3343b4e44275e22e1e300db1d03d0b95d29268799f5923cc460bf9a0c490c407ab2bc7920e586890f34f1c47194fc43bd008cf367af8d27ad275bfd8c16f553c429bcbad9e922520260ed2d956d4ee3ac2e814cb6b849ea185af92bedf0d1107a90ae243c4c69a123ab61b14e165b8f2b499a8c8037b391eedb1ab5bc5446024285ed346506352b772a9c779af344c524a83698ca428b310f43645c3cbdb262f71f804e451980e2cbdc5a4f029e287c5216827e62c8d31ba5f3fa0fd0a378974d73e99bccb1315be00ce422bf69a2c27a39a473a92bc61ed03b7b0d1f414eac2504677960228d20e7561dabba8d52da260b4b9552694ebbfeec2037db8f24e6096405589269c5c80cee3532d0d0ddf2a8c6965c039ccb295c551201b18d8c0af55eb5b01469fa0ac18281fe5c2306d59cc130e286ffd638e4b2895e22e30ae522b25be0d610c21b70b305981f9e1aa9b329109538018dc3832a1e8d3fbded954f6399f1229af003a9ea4ece8db50dd3e1af1d3cfa544e073aa4264a8139d96e51bcfc107916771728ab15405d0bd984eb228dec106a2556b451403cdc1f00daafd43a305d93c3bb1b7b6b210db26c5c33b53a45ea77278005ea4ccb8125f536ca7a26f5ed738225129c05f504f1542a888c21df3dd24a680fd0b4307a020ee2908827cd8be33dee9c911958984dc0e996f208b394e7965a88e9ae22fe6d126ab612bdda7e9762b494f4924e504d4c9f0db896a2b3df95621b03ca0e545d6c42d2650dbe1b34c9643f437b1cc0776e6a2565f91a99a55916d9a56bccd2dcedeebea70f2d03375ffcbc729ca3bc7f3e4a30f504bec97923f8856307e5eed7bc76c4cb7d794a4e685963f1958ec04e1f3b709a83dd2084c3516b3dafb4cfc56dd346f81d9db7d1a8d647391687873161b81c16b8674ca33c44e0ece8f165b8ec14fb70be1f50db568946d10d2b61b5b15dccfa5b23a595caf93d096fe975a5344f7a10f3e1c87a698ef7c90560fec1c3a6a21990378749da30b33572fdd3a6fce3b372e330761f0227166843bac1565d39cecc91c1b2a6321c3005f0a232c5fe068799536a228f50c1807897423d763b06c603c34ab97573c0068741d18a9c93f0346ac6560c40a068e58c500106b1810621d0343ac63c074c0f6b624d9a6b983cece53290466303bbc4cf8b94cc37e601d84ac9fbed0bdb6dacdd3f9eef6fbeff9ada89aa951a712b2bb5138d3c440f1d287ae86c2785ee9f0ea70f1e4b74a0fdf6ff13bf12bb04911fce5619b51178522100977526c8125562fca9952f7dcfe003998825f0cb215240910c703676e23b7cc1c60ad8bdae496448e6522b282e4421cd6e8de9ff893189b50ca9faa836d9c04e1bb96c4d6dd6359b332b3f420860f32e7f113e16c22678a62867013451537b71c8e5eb56faa68873f84f849f0dd0c7e0b227086eea336cb2ee01212ed147f8b8a3282e0f3bf64f0e277be32d2ebcb548ec917df4c9bb03c0f3d5a8b790bc907885d8a39a3ec19e534ff7f4aa264ac374b11ba044cef8fd50f5b90ce584e96be29646b0887d08185f5a8843e0301ed680caaa45c72c44be2c5b783a53cea5effb0d4383c85648c9c2d704db763a3eb25b2fc36be0b3a974e024316007a822fb4c4aa52564a29f0e447db128c93afaaba1dddb5de8d7f2a6ac9bf37b9eeaf8f0ffa6e1a2c23fa2db84d5a3c80540524bdbe19f8d5323bb7eceab6733301d480f4b79d6f22e8f07e88b666ffc09b850a16ab7b104cfd768c69e0028df714f9ef48164b73c2fe0460027f478319f8f9cf4bab7aa9124ce508600ebeb24f14da05e1a59c82e63ee972ee94c686fb93e0c36986a3d5c065fed500e056e81c83436ef2b48e51ec3462ac6d172fc7fdda48dd8dcc82dff2bf3ffd4d1d9e032e11034a18378a9df73044feb2bbcd73b0a0a7c473db5da3b4e5c137831d06c35ff398a0f5399a63ecd8cc87dca8e772605bb57d11fc7066c5914cb09deacf2a6e8e19c1bade2fd3661215e04b8cfd2dfc753120a3feb333cf57cdf841a77135ab989c7578581d89bd5492fa88396f88bc0165b6ff64f0fe6c81c7b3813ae549e5cc0fffd5917689568f546fed3b3d748f4d88fd343a8006bcda7c67c88dd80a53262ac11bf28289bd1886557fc8358b8cf65cf0208eb1ce5e52c0495cfd22609eda8d3dd62ae607f4dfffae9af73368cbc9ea9473fe974f656edda0cbffe74d744f6c62e3bf70b57ceb479e3801c1aedaeb82d238363643aedeec3a93a1f2636a7cfd8233e60cf77a64b1bda5876fd53adb303d99f8fe0021e7930c656fe8f60a4de6de887daaff697f45425e7fe69ad574ee77ac5dc2cd7f387fd95664982ce6826ffe04b4b8d3152762fc74e1f92748eaf337de890a4906bf414a3c118a8d8ba08aeecfd8800bd5f22bfc108ab65f27349da524aaf62859f94b2579cfeefbaddadf3dbc7fe9b3486d0bca9d3affd981c20621cf3e7034504434d2076c193b0fb24e5e57dc61dd68833d929fdb94920fb35ae11009556663419e44b1a7462a8ce35fc9b6f4e5b136f7940eeb2703abbc95f81502261871a163b9379e3313d68604f7f5a4a732619301b7701f3e5a90eb53aa082bf240f9509d25c855c937b092f9ac47a9f521731ac3657d6897d5cb28711a003238efd15f13231891215cacdefee46831e93b7468ef63b2803984e36cc78503bdcfc467acd3dcd2d4256bd11e724064e983e83a5ce157f64e7dc0dcaebed8fc647e5f40b3cc9898fdf6fcbfac97ac12d5531cdb6e345bbbcc9ec490091834acfce548c2f2e52a7707141e570d0a394baaa28cda09198dba2dadc9e5a7f8e0fd2969653db9b1da61db9826f82da57013c7e8f2e031d4bdfda27d4fa6223fc14272832154fd863a06e9636e3555bb53119be3ee07446e5b1eb9ef497f75c59a6131c90e02604c1c0e805fd7a4f6120aaf182a8f3833fc22b58cf1c110b820c18340bf397789b882bef8c30a828c5990735468c8ec82ee9bae74f606411e3dc79f5d13122eabbd3783d1f5f6a375d3b0abbd8ef507664152f603ebd9174bdc8b77992462e022004733608d1a311673f5ec4bfff4398552fc2ffede63f90dade02190bf1b12c226042c35c2d806168d7dd266050f6c983f8b23e70bfcc8fd4207ffff1e2a5f3c226e80aed96e6bdf7bb594f3f7e7887c5bda478a463e372c230ced57883e3730e570a49b893578f565761c4055e958a8d317226f826b34abbc6ac426aad58885e0e95e1325fbc6c9bcc091fe4e33e9999563e4fa33a9000ad23580879eed49942f87afbe077e5cbee705eb99fcfe8dc860186593c5e68a90f4c1bada217a020387eae5b2763684773587432e373692b9c07938a1ebbc86e82469da2e16df4d860b260726da2cb72b9fd0dde154bf9c0b7d96d37fdf0206add84ec54c250933a2b7a745e3ca3e369409b8c1b4950a87579d2e20cb1270253d6aa8df1db3d060e6bbe465a86bbfe578635e56c7212a68a0a0e24aac230d0cc4d7e40021ddaf57f3079f51d7962174e9cefcc066be3eb17a09448a7b1630acc9c3f1c2702e7bc7e6c1dec852a6d70710bcedf4e3e47fc5acb50eb827f4fe24b629d0824ab285280591afdf8d9bce91b3833ce7f7c19b103286bbf6c92a54e7d4fdebf89a3e7e86e87fc2772277099010f9d9767666e2ca66c8e02bfe6f2c13ebdd639d5de87ea26df861e9382a045ef4ea422bae87e86d8d63e716f4cc2267d5cab959121e2c0bfdf73eb201226dd29ea7e38fa689ae1334d1933e5ad399e82d90d21fe4c86fb224b1e4533344afaf4baf0b0cf1c8378d35fbc53ae1cda9fe8af8be00ed4f98038d43a69e15b9c503d490a67265e816237ce6e63196667fa663f78882935b5ca5efeae4c51623046f9667fbb9df70afb23539036939aee16178f2815b795994a676059635eeeedc7bf8e381e9ac6c99cdccca68d09906d5df0805189f9dee7d8985bfdbb749f1ef476141e0e69d0d39323afbe1cd92c472a4b0fe603c59f23b26edd73bc8095428c6fb6098e08228a029fdc7fd3b65a334526236690b2298645578a7c902431855862eeb330bfcfa9dc4cf137bce43ba35249822a6701138b33b299025ba8eaba27da05330b8f3d6e0164b945ee304612f690d3ff05bdc2fe9273e1d0cb13d2a2375f417cc10f26c2b1ddd156f13179eecabd95f175849dc7ab727dafd7d1e5ddffbff94cf5cfdb3f1d9822fe313a2c5c07a7a1c2cf970f347b9cf8f3e46b368be9af056d216b97f414c839db60317f2b705c5d011793827b84b4bdbf130a5b6bab6f0de3abda6cc673abb4f003db3bc316fe4f0865c623c5ee7cb1f47af7ebcaeee024eebbbe4a06acee74fbcf791b60afb4416c49ebf8ce28113323ff92b23a5b1e688bfe795763d37da91b98bb769d135fd24cde412daee4bffb985e7b0034697f684934f5fc81863c7db8a8d5fbd9efd068ac6718023b88e5ef1a86154e4704518c8653bff2e702a4256f40f43c0aca72e275e022be6e38f3b258a9cc08143f4bd12f8e175ef54596738f66a092337c1b65166ce9fcc8f7b4b1da5b06894fc780649b969fe6fb3b38308db5bcf10ed25957dbcb10a46d7dc0131c6888b4092f733fad4452a5dfa737d43f0179a156ed4f6743dd2bff67359dbad331b6f73f69ac481fa472c066fca7f80c08c6f5ac3fc63fc3bccc6efcc4204aa18bfbad792f92b7679a467fa9e8fe354e07b697e59c9aa1ed6ff991d15119eccab84b6eb0561d01e2719d6e6ad5aec1b295003655e62cf1772b973106e74e2938e713fd56e26166f67e14af969dce72a9120bb2229a1daa94f603c311555375abba6c3b3e5474e1ee005b0a54b616ee741c21e51f331cdb441cff81dc2df5c0e1f9be768deb07ff6687df863c3378ee72f75b03de4d3d40cba98025e081c780369fd1989a3c673cf9a75d8e6af286a68b36ee75098235de4afcab83f725c95be1a5df3c6bf1a88b1af0868c86d8117f69f4deb0c9c68687e3276083851a295fd9d9cdeeac92a166f58eb171c50fd25697a74a4806b41b1d429bb1d05b08af7730ab9f0db396145f476439781caf257f976ac07ea95c21f1db5553eb79594d91a133ce983fc6a0d462bdeae1d84b9731281c69398b52ee4cf688d30e618bea0b72023e1cbaed7f57613ea8d7f572aa6f1c2bf8b1646d49f8e8446f6191168468a38dc797967057845f9c9b1bae67a664cd37e51ac7732f9526bbc2c5301bacdfce3f8e363808efc6c5df7f357a7e14356d499aa57e5f5ba8f771fd6ed6470a730fa1b72591e0c22e7531d0cc9f3a7f1824ae96e6bbc0be69842232ec9fc0169db234849aa244e5fff67e39f65c6190c784f1ff1e097129d46aca9c5c9db614154cf178773dfac841b44bdff02371392b43ba2e7119f2334987f6cedefac187a62e5eafd31401ec08c72bc92e9e0624b091906f9d9f5534f54ae72a2e2bf74347d1c78de23bac435c0678c6367e78425e6e716963c6dded5973d794395e885229b7c0cf397624070b36d060aab06e3a1998ab5881d7c5bfba360ffdd66dd1bcb3b6194549fa8cd883028cabdf32f45c341c8fb830eeb74a0f9eafaa3a94f95c8ecd3fca8704fde12b6aead84cab3615fe62cb5e06d1f82a5fe5eef77081b68a8b060466d8147554d60aa48417a6507845525145684a0be32c0e9aa0e948d9d3634b1652b9d1c1b6fa94d39fe5efc5bc8a8e6b5a7629e51f374176cb0465bdef61453115b7abc708d2991b1f8fe6353c096a444b7ccf9e2bdda7dd8279106d24040c0c3a11458b614e58dd5ce3c556ea60089c6ba0ed74b46fd1dce80ed4807cc343f9aa075737a18e17f07488d2e29c57740e46708ac708770f971df5047d4da80517cb4d034a83105ca48e96538e2b130320dd24c7b58797e5541e448b5ec9508be3393ddc437628ee4f516a77cdefb06be8ddda3d3e8179f43cf784fa2e4af99d687448befc0665736fd559728f81d622e23bc129ab0c876c9a9d4a791b3f1b088be06b1c3f00d28bb0eac796d9ddc86709f03469099c124a635bb5b700bf795fbdc389e72abc8d189d9de0b45651d0413bf8b3d1a5b8b233dca351deeb7ab27e61ac5c0641f0731afd62d6133fa2eac15eb10b711897afab55786c239e76f90cd63f0a4ad123d1bd9f58bcc4055a4b8cfef162bd9deff6bd43cf1d86f03306e4a9907f7c989c88e90c9b699c7ef7dc305ddccc3830a7384e0c388d6dd8e2a6f4a672e43d15e026fc3ded8913d6866d733be6af0193614026ccb737c5d1d081ad296a8ec34c85effc2b6650364ca0f7d964e5873e930bd17b5fa2eed9b1f6ca87c9e75bd1c371c01d8b8cd560f3d8149f5c415f9d77376a5b0f6cab4267524bfb3f180b82b19980aa28c42701be615eae9d9752274dd15cad22c17019a41307e8cfd0ae8c7623993ec770a23f5bb6128f6f99fc979f0ebed1bc74817465b31e891e1342e66d39f9c4503953d2f463dee1ff255c056b1e3b5fdd3aaf3f2defd07a9fd9bddfeb4232e029a980874fba3c71cbcff0386d27f07de8731d3960274dbd1e54f325d8fb12a73d662ef2128540f4b78467ffe71e91e3be68c37f618e8f1105e77c95ae2bc4e134ebb43e0f58c8ce0b602b2cbedacd1985dbdd1c4bfeb901d1d3f875718ea3115b025a694cb3b41b631a09918dc27bc3fa972f7a023ad2f28077cadcf89a8515f4077f07fe813f773c975f90eb264247fe7cfff8e221eb034ac2db4093e60d4ab80bec3ec9ea308d27f29a242bfb4912cc94c1846d462d20e2d65bb049095e19978cae3bc46ff36bd985667410d80a68c8f818595d2be4b828cff190984c2fa082259974682a5f174a4a16e5a9b01f3c139b74a244f6e06e0c1a5a6386ec010ba66a9b2bf60ca67d7fcfd6aa122eb245a53993c89243bff5f81c6bd4547d0445f17728932315a68958c542a8f2f3682af43bc08707395a74f337878f8b579406c2f8a7efd3890b850c3301a328d13d6d81de016a0125b3dc356b83aec3e4a81970100c872a52a812a31c0f71af56a9b39bd0faf43bcb5105b71e7dab2d1a152a54077403d543338f45464dc7612674091540cbd76e4ad680a5cbc06f9271805d46de84ae8453012063bbc4cafee223dd3e99246b0c8951d3d789304789e00c5e10cbad74d24ef456c9ef4b64449c405ad16665498c4c2ede94c57f89383c44961f4474bb74c96ec04c361d2e8179a2131cda1df88cd1389c8cf4e2673ce2a3511dffc06b81e9408ada00d264adef82946f1548a15f1a6595924e78bf2ba9fa837e8ba2ae8b9089bb8a19c2c9d7c5e6f64471b963c40a2b78fc976ae53096aa0ae6a9bc819cb3fe52539583184894ffadfb8710cf10cbf5cb0a0b9017f97a7b814330d96c61184c48fd641205b7961af7a669b3b76187cef638fbaa7f8f6b582c70c5b292f7c8cfec712c3697365035082df34d6047495091ba30a8d3fb686552615c21a24d48a2a54e72e66ca0ecf4e311958d9c07a790f2133b14e1508ee83d2a7419161081c400bc0a06d065ff873aa8d75d59b73970ad4d3e9ef8fa1053add4d9ddc70f8efc4547b4fa32ee361a93511399ee85d34ea18048275f7af969a4cf7c1f933865f34c20d1a12736f5a41a2b38d55caff5ad9882109d15c451dac85d11c4b37c9f26855a39b9cd20c54db0b4f2180ce5fe4648fd63f1d1e04c6cfef3c1ef2e3e5af2ca243515a66b4556455f1a406d0db8c6cef33f19937a7e0c49fdc67a5cdad7f0678f1d6fa70562cce761b1ab192d53a4c016515a96eb073c5d4ee222518ecdc55af6174e5c69e5cf499c5fc7d83ab145b11b63eb7331e0beb9e7c1b56d7eea3c561a173cede4e5422ca126faf717d08bdb87d81ac05855bac2fb185a5bab1f6ebc5ee5c9461939c4f50788c7cea702247e88857e5fcc09bc1362e3ed2da1f3497392d71cc3e4075239814694d88b75c58cd67d27728c2da8b13e24c3ea3de3b955ac55122e60e9adccf5b7cab2c983d7195858ac2cfa7482f57e0df96867931acb47ee12993b0cb2cd02883e3c800f3a48506a3380e306528d07f6cb4659840b476f45733d858656cee48b62a38be03f8b0fc1d03100e596ed5afb51cec811e222db5cdc415307550b52fb45b08bc90f01b0d03cc084da90629c022b72a828e0f71276584b85af53057d182afaa17c429b8bdc03562195d99cd023e1428c5defe554d9abeef06e3d3078ebefdd288b86b0253cd44c3af1458a3f3156a96173e31d97541e326ef9e8f01684f5016079326547567451f72b04e225c44353f610ef6770fe7e976c8577838054be7d370edc45f5df6d8243277f321cc5c6616ad9f5f99e6c4c066a2e753926e09ecc928a4efe5081b1fc0fb532d4c028d45e398e8085fbb69a30bc54018eca3ac6c3c7240bd2fb0446e0f06a9419b38961aac9bc2c7af7246bbe60e7ea34fdacc397905762a6f6c225f262a2eae78c74c797089e03564d866411f86778b51dfc4770ed60c470cf4c5e79d4dcef34039be1ab6b1c65fe7a344b69a5379fd10f7f9615e53234e7ddbe15398dd93831cc6c216799bb0802c903ffebf20ab2ca74d135bb13d22aab4c3dfd4acf131f49cb459680f06a46e429c71b40d071db842b9871bcc79149c3b93b047638e1c6e1d8a6b1433f1f1829a8d8c3600da2d14b67f9bdb70761fc48934f63ff29ec807b21b624f8719ff56cc4b40fd3bb04ad7049d6f9d0c848b06b39294d90d815dc7263ed92f166948625b8b736361540b4f6988857d87551838ae919b4a4e6ad6c7a0a425ad94cd62f1eab25f92bc76bbda9f55f119240d6e5e5a82c07027f2fade8497dd6c06131f0f3a9b1457a2f01e718d075161ae83f98f889a8b696f12361e63df332f58555e48685615b839e45a7ca9b8009c86df1977263644fc68547c1fcef493c66665b088af98c2bf974464a6a8bf045fbc16d6b10e862b34569d23ab135967589ed5d0b382ffe15c62ec20bf5b6fc2e15e71faf991fecbff08d58b8c7d7d381cd766a913008e63d8afc1122093ffaa3df15ceac9a94e41befd0691332536618e7bed5b7ae91e184e5fded683f7ba59f5759c059a9d3e3363443d0b61f4dc8a4eb44133e374ec349cb77a556ab7aae59f27fa8b07eaf8470914638e3ee85f2ade6ab23d73a99f23da6a1f58e71662cc778cbdf56921f640d7b2a89b39d5b688b82b833963f17c1b808c21a53b9bfe32e1efac68c19cd81793f2024303d0e77f8224227ac877bc80647f68515fbd59bd0aebfdc91240ea692f5c5231edcf47e551e72f7a174f20838de8164ed9398c65193493ba6fa8e731d7a4bf5ce8af43dbb10cb3bc3b671a64741366373e24839b92cc20123680db8ab109ee245739f92c59a1a3a0d83cd032854472051902e0e5c981a9b786f0475c6c516be562b6cdb1d4d27f60ded8928bc49d0ff7bbf325750635b9198ea1fc633de0482f2ef798c28d9742f50588e3e2632bda49181da69a97488cb7d80eda65a3732889ec2f4d55dfb90ddb4f35521d6a22dc377ff9a1c03dcfa412ebdd5b3532c3eafca2f93dea437903eadc477cacc1633bef5ff68d1e63a8e344fa45a220e0ee2897d12bb8988008e0f412bf501206ea277ef5a7922a64d39c185e9979d4788df85ec65af6598c510aa070cc057a1d0e86e83f1b33c01f4e077ed9bfc1abfdc49b63c5840afae13bd484da61f7fbd61c89b4e57222158f46a3177b8923d564f54d44ecd2513ec0b14fd83a0e30adcf5751aa70a2de4f0dc13c2866c002aeee8d4e02a6aa74fdedda2b18512f583b0386fc12846bfb7751e91927706a73c0adc4d0ccac44cdcf473fd6bcc4729ae069c495f75a3103155bb3b5f0a5d5c0b395daa85b566872166d88894063256ee19943624e98820414bea4523341ec65a447d0747eced86e4a18a9efddd5743681b0179f4b84b44411de20201edc1541072f6310d77c0b8251c88d982073d946aa582b357bc4381871a4260fd631f221cb0a3e2bfc6702eeacb7f8a6fbeb7dbffe2f48d73cf0e7418c47bf59478515603b56f3a6829009bc7e3df8f16e8417dc70e80ba049a86a4e0778417bb4d287388697257138a8c67f007284a0861ae6022c4bcd70dbabcd537c5767c624e864ca9c0625b5a45dba62bf836d81091180d914e0c31b69d63f59d6f14d09f150216a450da6557d66438ddafaa2fdbdf535d1c46c67246953dc1fb459faecca6418ebe40ef81e8174ca81697b1b9ed552d049d084cfd77596ba42367409ed688826f51f77a09735f27b7b5f6cf22945f3ebefa174fa09fb7601f644395378192b73f03561131cc242f12973d302777acf2b40b7147b2ffacfe3de4758d6eefb36696afc10733ecb4960bf5ebc0def216da9df5b23702a9a39cce55de6db71c26619dc5e4cad2527ce2f7e2dec77a7b2b00a51a5f32f9c1052b7842f1f12ae743266d7523436050709147d568785bdd47f2bd323a30680ebff651b2e875b7ca77d813b8c903d2b9002219c249ae178783099037563a40764ba74be385addf44683fc46e945ff95229bed62705b3425153d2992e450d5162a85d71b5cd2c935dba1efca1ec7f58eb17bfdd11996be8b4b4a84865fc0bce63ef7057f2b3c52eed713d80c57ff5ee1eebe34349e06348d2f451d4c642c71c002f9fe533e6672f8d19776cf5301ab2d7f73132896b894975fc9ff21372858d39e1e3f0349a3c1bef8c4de23264c16a832acbcbeaba7fa637fe3e00eaebe6b5e9b4d14aaaa064e500a325bf4e438ff219d52a57ded04bc8dc597c75eed7be657eaaefde5d8559bec36ce2eeae0037403b9b7df73321ee8ba24b4032fc499fa57ce02c3dcf7036f3375258bc1b7940992cccba5fdc559f4fb58f0dfa1398c73ab6faa65b1203dbcb0506beaafa41bb8d7bbf3956d0ae6151aaea7e9754b8165bdc5603a024964a811148e83efa2eb3940ec891ea89b1617047fba520e369be47a71e6895d48575b82171d399f7bfcc114138c2b5b2c951f372e76a313b1aa4315e991d68dd8392cb1c59fb30b7d50dc2606415ba45d6d9c6d3fa6c0bef1a911dea65791cff545775d8b447dcbcbf6e7666f880b04ddec8fdbf286b3e6dadf206905fac4e89edd2936733669c677353605b741c0c0736ad2444d8ca1d00a26e0c754d19223fe7c22c490d0e8f522201151cb5899be1910af4f01e44746e2a08eed5232f6282dbf06f63a9d65966a6c01977d0cb5f5417f8505a1ebdd004b3637be98cc5ba69c03af5a865635abe079ed7b32a7d14a79baaa5a242ce4e12a410e93904cb5ec11dd527df0f30170db9a068f8d8c5067c2d41fbac6cf764459b30b8c1090d6a9df87ad7417ac2519f86cc7923bb67f9dc726aaa9af80bf2070899a7be488e5569a69e59d71bc4bb8a39b22b572300a2c4db7e6c64af41ec705e8900e53a7083dbbf32d6e1589ddcc84a18665bf8939878f3aa92eb04dac854f187de5e4f1c7a9f01e14d58682d9ee5ad00436ba83a7712f0b04bf9305ddba1e59b3190fddc9d9836845c0edf68f782747043ed13c59300f786c2c955d00bd8ff84cca13bbe7534db7097c81ffff3c572afc7b921dbb04fb881bdd2f645e11adfc39f0ed834fc70fc1f7bf9786fe029985fc87ff2cbb44e5677b8f8f39b3ad58b586d188fedace7f1458750a0693cdb370916e4959db7a9eef9760fdf6bda5cda17b6fd189f2ba05fe66243257f9b2b3ecdd577f0b3e1657dd95c1d92f94875ff11bd21a13e0ee27b7d3f46b5970e2eb0165488f23120a5c3fa809c71013ba6e6384f4d37709717c88db5aba93b83784321bb184895b5f14ae714c0406a8dbe03167f31ff0d8e2aafec04c69f5c3a11c84984ba2cb2f3ce732678030932159997e5b74a84da16f89891dbd83cd515738c6f4c06ea1db4ca38ee98829eee990c538164188830b97e66da023dcd73719033b3ae8091053e2bb3f6adce308dc3376d63f04c7bc732a83ad1c0ddd007ecaa265967f75df4bb58fcb820f166655a9ad192ff32925656ae4f0a6b67eab207ce156c3537f7b33efa3bef2055f9f86cc580e0a503f6df899dbc2bcb9bd7ea0efc4e10fe185c2e44ebad3f16eefd31af894f1bb8711f6b8d19b11c8b107d0449b678ad93212c759f3e628ea0d1e397f1e1ee53d671a13830eccd6fff880df5897bbe5df03f38e8deaa39b7e11c209c49b2892117797bf7f5409e6429498b5735c93e99dd551bc6a7406c5e6765bf44543bc619b67d205d9f813f7dd38a13fcf693e322dda7d6f80da4277bd6fe9f3d8b4e3693b26a545ad677847b77c5a2da9f3b77b0242f408a1ab201cfe3afab049f7f64556e74146fc3b15716deebe00bb4b07f68c3edbae60c55c88f2a29fd33760263ed58ac82ea0ac279d3d12ad3ebb918a046e3b6ce4513064eb7903d558398bf4a6ad4b5bdd510735e7df137bccd4611e84ceb88a6e356f1eb80f3b92a09e9888e5caba07b6ee652818041d74a81e1ba9164bc848d94108bc9b5c31e8609b513c2b81e3317842ab601034d6f0cd4a53f916d2bc21af606ffe66b9192e2ede85b2bd1e753bc95025408f85c1716c74da79cf9a079e3e6297b79e8bfafa5f04b603013f027a57f91e3917821b2bd1b906c197dd03f3467bdc46dea9826f77a7b35092c3bd169a8ffc5c2268cb7ae12a50847a382129803ce5de32a7b2fe9621befc68a0195eba7e5f6230ae0b3321f7e9aef4c55fd5f22fa319dbc8f0fcd28c89811ba49b790035c83e523eeeadf304a8de0400e191f42ffed820a530fc75e7f06080b24bedbb1f13058b943a5f50a3fc98463b9f3e916688af7a2986c36de6a970524f714a6a26a291513fb485c377e3cce3249c3216f70dec764cc389039ddb3a180b7b419482b9d1c1952a7f75996e16632654db0cd0067b78a94349e4edd674bd54055b6857b0e566535fbcc43513a001ef18c06c213c1fd992f35dbbd0287fa4e3673ee0fe0f1626dbf804ac5d952cea8a9cb3567ba78c00c4978a509a43b58356fc058de4ecd263a3acd5e41f20cad556bda361895ce3a4da12dbcffb41750305b7038104188c080ae3bfaa923d243904fc083b2c3fbc7ee199751863eb43c2a2f853afe7fdb69b94d02425d15be01da155a09184caef3ee7da45e1f3174a3262fbd3d71557ab508f16e4236b7de16b8d4d5c5d3fe10ff79220570cbb644bd50b85d492f0b1615e27e3c3180ef4394fdc95a4439825fdc86777de8308a75c6dc0f4d7b5e68c9766089167773cd28bc6b5a6ee4a6f0b4ea3041940de16e00918128616eded810804008cdccd09bf5c76bbcb4ecfa6f660daee46a73d1db9887fd4ab6cd0aabd7699ee466edd5f339cca2c11cb47da265c145578198f2183552fb6b74473ee69ec9e3dabddf7a11b9af7be455bd9a306b8dd6738fb070e75198d34b597603c21f239b2b76e2ddaa5d51cf8811d6df72633dbe005dd435cf00d07690462b296fcd7b8606951610e88d257eea3152a3d09df80abdb72a0a87d25b1a411159773ef8d555221f30c9f51bfb5c99632d730615b02c3624d490f4738343d27c8f6d1ff33eb212852421555840fa602a8c3cd41e30b637ad1a3f85dcf54d2832a5e221a6e5608880326674f0da122165238b233e07b058e69839e8d810db4191ec8bf9efcfb49411f7fbb8e9096360d421f755901c2ab00f071a6a44cde886bf31a88415988d088eca3ae8b6f9ef6bea99006d6565eaba684a51d3dc876648579348f283f069a11b2d5341a28605828c4fc3a477e3ffd8214af81dacb59c5717af722873ca2e3a64e23743a5c1311e1cdb538cf8272759af9df0f7efa0023efe440cb950522858ee0606281d33a2623a785b2b4b610193cdd9c59374724adf23c17ba90fd75faf4c5167a03900fa8cc0910a9753f6f575c66f88162aa89f33991ce0998847cfedb4209037742c154ab6a70ea718a174dc8b597d1b8f864be108e834596ebfb8c97b0cf641b333680d2f1821f17824ea0be3ac32e171002039785cd8dd931b960c0ea04d9e7761f350f7cd0cc21fd441a80cc3ad56a081fb3993ae052a2a4ddfd3e3f2ea3118205fd59dd6dd8fcbc499fdaaa4e8624c4add9bcbd071061061d4d608f8c88a946232a6f46bea0802f48f55cbb35c063a18fa3f953e421ae25aa9d7b101df3055c9231b07dd4a563bbb489cf8a5bc0a93d3697583e4f3968b4aa9ab81e434c4a900303804c7e1fd9aec6769845a47c2ca657a02bef0edd3c8b143e70e273772e09c57ada18eb7b5d3adfc2891f00c97108035e14562f7957a0cbeb99e1dcf3558f0bfae90a4ff3063543d91bb9bc15f6eb85f2022671727ec4f6bf14e516559272bec5a59609422018720c9aa3a597c1ebcfa5ad882a0f944f214f58a7e1139ddaa43513429822e1ff77f176df32778ef6ef92df30fcd4c2dc760e14042a36a872213a5e68b5d1eafed20e58cb65bc46a211302c8ec2fed6b417405f73461042c8b1427fe17df383b0e50139b12329c864064b24714f557da11f2262ac917ad045317faf97cc26c79e354d89c7e88bf43cf51349968d72cbd5c0d887176174b54c6314ff02ed6a3989f4ff183ddf13d4f62f79b7ed1b82fdb480aae21bd32e141f6e102da179399c2e1b51b57284b9469545de8f3d598fa71d3f822b90cd5504455c10e5e243e9e4206b13b4f42d5f0e2bc569dfbed332961a912dfee73fd1bbf60c66e8915573dcd32efe86c8dad8c7914f0146dceca1b1a264454ca3f160aaef92132786c85734c57eb5b44216e08f8633a1c0e1143471a4589842879d02975190db128461d04109137a55b30bebee828e965dd52383f49aaef495da896739aacfb38d301246bf63220fbb47b10e74acbbdf1b23bb57bf80fb9d38d82a94250430a9e020399a166486019d4be8b6d985fca370e2b8412ed5d5e50998ef6a5ec8b7e0a27c47843a739b7b592de5c1d4ce5892c64b7388c5d387acdc6dadaf9342ce366c837a2d193fde18418e766042bf63296a1d20e88178b50544294d9e7b49a683a220bf0d69fe54a7e45260c90b3b1f4b2f17e86d74768316773fd5e37572ff93eebce607e9ab96eac004a1ef64446da7ee39ffa883126ee6fae5d5bcd29dbade4bbabb23efa76ea07b38f883b3969360881089bce3cc9c8df0c75747f663636ccf76d35535cf4671729fdcd1240e0a9d7a37f862283df0899273face7f4b9bdf2a21d388abbe90d9beb188e72cf8b2b3ededffe0bfae9bda0edc732884fd0106058e833c3b6c51f2f28c7484c48c53e0908a1e191f7955423af85a1426ce7619d6c56b74742e08f8b67398af0143e189ca926d72c8c714106528d2e4524acd5f046428fe9997f845189c3fffc43491d39ed5557cb0856a52e3f156188ba859630e1112a3458bc0679e1416b2afb664bd4b0f7bdee6ed48ab0aa8488a0e31c49a69c5be6b2bfed48ad5c28de319355ff155f8fa251811114cff35708b30e0599f9b1358c84a7c04307d62d8c355f67de63c6a9e323d21bac18931382cf6a344238a554a4d5e75d742cea01d1f9dd1ff57e40b24c2eebf1daba8ac70e2e9340ae340f642c6ce5b2528b2c6153be962a231eee90c359d1febf54f6030b0a7ca942e58d60bc99fa495324f41c10530c6a4ca9b166ac83680086f7f66223708b6d15eccc8313dbab5cd6e4d9f7100ad7f35a9ce0c44eb577a682b5331051c648ef89e42d9e9d79246086a2a9a9dc5e2b9502ebd51da8a375fc2111624d50e641d7e9f238aba8178c30919417c2b1e6a2002c0fb4dbdf9ec2129f5fe4ebea26952a8aba46d91a67bec1f33bdec36cd20a792f565c1108d24ccbed694f8941994dfee635be540899f1bc7a1a989bd9f7908b19150dbf1597072fc662cfb0442acced2366f7b60939b395afcb12027373121c391c2e17ea03a538651e4e4e22f3b89e9e500291619b7194413282410c6ec139298b3ad4e5838a5429d7c7d9100c94bc6067a36b08b2dc78904158cdcd4fa1ec05efdb7bae121b58a89ec17c2fb2dcece12e4b1b833f76f01f4ad24c9dc92c46ec3c7337689b97e11f0e70cff7ddd3ffa06fb783243a32f10f1dc54de2ec72c139d4c16ae65d798190033ee0c96e5c0e0985cbfbbecb357db28ac04b00f6aa5ab8749156fd2b0f878b65d4ef94d6fc4c3fa6341bd38a2f7e236651516d24a772e2d42f50b9b92147aaf19fd997a742427b79df27babae916d6b848572ebc717adc29dbafa2d4f9f44228e3ea67878334205b808dda1c0e46f47270475cda73852f857683f390e931528b7ac13c62c4f4492693834c0b33f0cee612b5285e043fd43ce7d2d111aab4064c159b7a848ab5abb596681d3519810f89b901a6b0d5af6b09f532b36663f7a99622457741bec61e71a0132e17a6b27991f7c57fcbab6e23fb016bac21010c6e873fbf06f98bc895e83105c8e7f763912d140d1eac0a66366ea3dd649acf26a3f897ff1b550ae61a60a919633c4ed02f10f883743373c89b346a52b17aaccdfffec0420d808618a4f98035f60e0081ef560733f0658f41f90333fe29793350a296318103937f140732f48695bc63575284fbdff9e2ab8f0eb734751a76d7f54a2747d0d1119da326f1e7c65a6856c878f9ab99f35d5afc90bebf646c7b17156ab08e9213bf23a6cb6e4eb37803a69f689798f11e100db10805e6f7c6a292db6c206a547282e64668365801a4067c790866a64a106dd1ad5ec2270e143e1a13ee228afa28a973ec49806d3715678df3e870a81865fd700b84673c3c888d13fde37652330c9b59dbea3add3c481134dad76f621322df8b1de9574515d26c223e8a0a96ac8a0970748cc5827f2eb1d53e23029f2cc5e895b03492a551dcb705bd38c0a06b8b864c68d8d8ff1dce21a1c8954ec508a0dc097fe3d181730c2599b54cec5a3a56485e3831f19050ac13f56d8a8b5484ce1f845521a46f627cc339437bb4e033435cb3234070e1ad0a5b4d351f5ce09fc42f6b8dd1a0d811c42baf9a71c3a98fdce7693cd48980094ee03c5ad83d2bcf6b63c5ac604c0dafe5ecc4aa9cb7c40492916f6f5e228d240ae565e2ff4e4c41a7abcaf2bb167b248963799eb5374c02793d865383c2eff342cb6ec17e13598294240b96e1014a78a9721fd4b9b007ceb08b5559843bba82e4cda9e8716cbaa5de5471096d0283a759841eb9e41b0c082f29f2bdc1e341b9ba6d5ca93aad7e0524b71a4a6c5a82478afd992e0b3a2101d2eafd9483a21432db7efbd1c895137602aeaf08d4d869b1b5ee5360b0504753b08744a1e3c51858e3a97bd87381fa09bcc5bad5d8464366e8ad485d7d785178cc7e2eaa4490af52d3a0dd6292b5d7520b4d9b1c0263641f3f2855a31f8b496f31c8224723747cb211a460620028b66bb8d42aba96297addf740535e497ec01bf0212db196dfcc0caefd70b42016c8015140a204edc14075826a4026b49361f380162a5ec36fd5ab6dfb2a001b524434dc62b0525e982790b023ed1e46a902110f20bca4b02c53a51ae1f7f113b987f3e4a0781822112aae7f9d1f0f0e017245708367532569eed0c2ee88380401ecbf36cdbaffc452f4f8eeab00d223c9a5a5236f92df4684128aef8d3c6d5981eda8e6ccd30af2aa79a1eef3f604dca069ee04c9e630c43a78853cab92c2a4f4889f34bbba657213c991442a06f017e378c4b837fbd9bbfe98806cf0cfeb9e0b6d0839c1fcc8804ace5857651822c7982d61fa4c63027f651c782f348f829a9680b2a70ea33fba1f3a54b1252f971e4a3cb322f9aa21706c5da7822620eb3099c03bb53c932bec11bef1b2bec430393a4203b02023a371cc363b17b2734f0e05a259e86e545c1c376ddd022dc37d4e60ece69f750968282c3041488a800df636a61242daef4d5ab2b990c031561759fca2c2e32aede4954953090827e1148c61f5b21b156f20ed6bb787f747da58101fc849bb3f497e5b58db7cb18eebd955d01f8f6a8d62e1e245eb5c71581a071903a5d8a660c81e953a4df67e67c22366754be4e6323c15f18e2393ae4541e4c43fc1667553826e254050c55dc1fb18403441cd0e5625c908a60631d64cbd6eadeefb3d41bb0e158d58f4ae78191d4bd3cc7c9af1f679ee12466cf0cffa1271af8ac25c233a70bf2938f8bc6f5609b1840d66a3e2260c4006071f596fd01a9523f4e144598cdb8b479a548a8451219239d710596599bf9f815563af8d349ed9f3a4c64956e9dd65954c564e33edd70a684017c518bcaec07480b7a798fc5e14422ca13b6d1493c6da7c5199ad2ecdc73e07b77641e33db869600dd20c6ad0b483208457e592c4b1ca998a3a5c693227eb13a2427f1466cee8e0c71eb0bc36c49988b38b2bef7024e0567fb0851a7de2a43f542e01bddd0df021041d704ff54adbbc91c7a786fd4ccd92c93ea91fef2aa2a0acaf1f193e44bbe67ccaef4b91760fee22287cc8743153ca2fc73bb8da649e06ef4ac7fbc4152084b95895244145fc1a3030e5598a9b9bb508aeedc78ecfd1e592966c4ff94debc3d8f1d29edc2f504a3c615bb3b2da24b21658853a8ef3d85891882fdad012c017e21d4a048b4d465aec105b4ff1049bb011a367bccf3f0cdac3b87ed2214235acc9e79085f63412d1b77b6c24fc4b8ed996e58a9e569db467aa4cdf0c452107df29e48c1423ece6479e25b59b374aaccdc0851beb1af9657e9f8fe84ccda5037230910e61655561b7d7681dd5f9bd9577de2ef49975768857e70c33396cfa440911ba38b96ce2b631ba699d78d4136da79a35cb0060366a56472c6063677f7de1def6d3b719bde9f3a46e2089c6b17d4b12b7c646c83b9fddb6cca63ef133202262b51efbf8f77e84419e1a91cbb5b5bf5f7696d40857c5f59a68b9bf02711fb7cd2fd96e72df65b4394afa2185930b3a6008a07514d1e49d30f5c963b1c5580da321796091b96350bf4c3456158baf4e4fe07d7a4e2053bb459e2b2a2acc25db64638f13af2c301282c803f0ae1767221e61f6b4082dd48d2338724301ec77f2e70347d2ab07e625d01c902722bd1c7a3addb77c96ff522c84e902d08a5318b7933ffc7597f0ba22d160c045fb23d68fa1a1276dfa756630de43134ef5606192e3cd8e554860aa254b5ff762a75936ae9e8b54332f66d0db3b84bf42ce112c449e193cd6228ce52237e9d2bd97bb0338e5c01bbae8476494769587666c1b464f7362749cefee9cc52e88546c60212837966a90e538cd33d6f1203765042a83f220ec3437937720eda0805630cddd0f39d2b75a14d653e7f0b9ce159ebe9111c13b2494968d61f7f2371fcfe73906790095b65d69080095c2e9cbeba469b57b0cb1184d71f74d59ca1fb85c555ce7e65c7b29dd7bc8cf1460e33c0ad64f9ff3afde228fe2848221483aa894a3f73b8347172c8a1419413dc43e17bf897f702e4e496a1148bd22f292dc99ad7af882ff89369347290907811e843e8815269cb4486b844260327b869c9724ce37a0def02df3faa488a7c350f42f723053647b1300399de78a948b21e935dba703c873c8961b9cd468c0253cf1324650070efda0149b5c1614f2007a3e9236118a8aa416eba7fee29ef0b0589143e2d14d0e34d7010e110eed63273919aa68bea30da711a89c9e36d3e6e18a48d105a9bf094fbbfa30cee8dc7794ed6e8c57c39962bc26e8bdc5b6b735c83c5209bfc11830e92ea8a04703a4ed70038fec71e953f556816f0e8e30ba5bfa09d5af80a00c1af37d4ffc26cae5e2b00e0c026086cc089ff6f92e08037001d91540ab87bf2b15cf3e8fbe04c2fb352ffe41112ad184625091855ed0c602fd7489dae585d2a1aae8ad0600240da4a8c65e716e665d6150be607002853877cb4e230a66b41ff6eb12be3b0aca0174de4a73945cb1fd3ab19deccd0ab6830f3e1b744509ef6bcc55f8ee27dd277119e0b108f614c64ac19c69ad7ddf526db9d51fa37855b1126270b641daba39dd27b4c5d96020a8a71ff9f6b18380f938bb40c17ad685c67f6c2f8f108f0179c118bc5741fb3418d8e1f85f831bfff95eecfc7425f3df64af5d64535b9f6203b3771c905c9f8db77025cdc4d8d22acc5c30a6e765a00f8954df36f060dd22cff9285ee11b975fb2a2f137b8bf09d58f947e8e79ceb671116f3000ad97b64568da12f3f54d566a668d35db4f97aa3909c9ef215f3522a8499d5b60ff97b924cbf14acfbcec26bf6bad1c6efe60d0fd8f3c26fb097fd3453151ac3a9228b9e26721a556c90c9be3b8deee681eb5598ba610e26c95d6c9c1fa309e3653474231f04f908681c527b6619877cc469ad72cc3b4702619034528e38131e038c71022f6ee766fae037ec493e34e70e8f86754ebdad6f3499f76dab1f2163f9f5fd87f33aecab95be45e193afc07b69a77ad9991a644b48d4d075961af4d5e505fa606b7e83f0fe95c19410f8547526d247294a21ac1f1cc12c851329cb59c2d0223e267ec5b8779ddb1f0e2991fa2969ec8eb8c949495358ae642543de9959c301c8c0d1a771b17d3d443060906721175da92d1ab20edec4af500a244c24666f40ea524d70ce4ec24793f9865f536789417fd055e3ea53844e958f55c98361fdf667f133d09c3f8e201849e60f6cbce4bb339e81e9ee9389be58185599d8447c4f27228e2fe900792d3b925a184abad9c33d7c31123cbd48141ed608ede0e1dfe1c033a61ef0cbd06e66a220dc30807e5f5e372bb57695b59830937ab4675758ae24d9539679dfb3c8356a8ce67dcd1f7ee00971d0c26a1ce7896841e2ef46805f41dfde99df53c27c999406729a6f801dae0a4c05b0ca00329cec69edc09a09566b534fba809e538f9522f54f167fa5bb497cff88187bad67fd581fca1e448f495b9fc846afbb41a43ca19e0d8f8fe1ee34f7e83c508d1f22d6e5d350b5c2ce90cfa74e59821f8f67b13a36fb2f983fc86cfbf5159d628d23eb98926554d89b18a238d3729666f37dbe42cc5ab4b56b6c195e567a95d59b9e53cae0836de93b4280f0d5a0cac23c60027b2e28d78b0e8fedeef2979e627440553fe0a22ee0f4815e202aa48e19cb3863b8dffe28b1ef056f39d8b446a8726f02c04cf28da56b9a52978b9138fb4deafba00869e5ae6fb9ebf593f95506d1a7ed5c86d051c108e57469f04d555da20c8a6f745229a7016412abce3e8b933eb1d7ef9f2428f39d98d58bbd83be2110c6251a7ac23564971ecd8084bc8a5d1a0a1e51a9aadb82ea04a79c364880a5309e0647d84edead25bd051c744c213266abbbb6058d63102b61549e6b2b6c56f1b9fca59d3a26dcdd1323d660196e9851a0313305410b76e0515a9ec519032f821af46749295fe9c4ca12c1c5974a66cb64e010a5ca8a4522a86a965ff4474bb640bd48170983e242e9fe2c79a80379394322000cd199254d946deba1d61a3e80db37b0cd9c482b463bca01fe1fb22fcd4685e2c35a38c5e954f9925a8079f488afe83417f104c70c079015508cac8a65f546ae00d375822b3fd245d4ea677654ddba98189b566a68502c4e349026a53c5b321f2bd7bce9802ff2b96ebd808ec62f709c3aa2d971c62ac29320c4ecf4d25161636efa009537cd7e424d92252dce1d1c4260b2b7e132f885b0a4a60a7dd1a939e10fb528214a458b190e2f4c33a273d1c89d05098ec9a9e8cd52658f76f14afb9cd59110209b8997dcc59893f852a6c7480153fbeb0004801ed98569e6f6e46ef3c1a9114c9f6af8ab266773ee3d6b666356d1ec7351484c84897c4a6c4d0ed50f79c655fe9d04938aaac492323467c6a8d9f7e670cb5244d114739c1d2bd1273276d5023826340ed0c75696cff2827808d6bb1cc0c0791fead5fd5f1bf5201ac64ce85ab37a16dcf80ce12d1c44079a5d1291686916875d6aed158f2550aa6b1067fec21a96aaccee1a520728d72ce5cc3eb350bd7165973af664e367c294af0e7597105d0f28090a212c4bff467601f98342d36de1281aa6884d76f98bb1ffe942b30fff0d6257f56276dd086d886c832987b0a556bd18b324770c54672d679633afbe14c6f1b5817ab6ad11a8f7f25860ff1d15ec63086eb935692f0651d74d0cb48ad5b94c6e767832836426e84e717606dc238e9f162d67237b2508c0f1e8e24cee0813647ec2300cf49157b63e7f26041cf7ec2ad3871cf556211c8d2e62730f353a4b3e4841b17bf4e01a2b05c37528bb1553206cac4f4a6950be3d608aacebe75083797aaef9d115c41afbab647fdc416291bb706b93b5ad261e74e4f1bdc79a17ec7561314f9954c4d2ee604b77ce02212112eb580c155b3d4a9c2aa7ae356e7c3887b52d9b738f054a974a196cbbcf5e82e28380f3bf93d3b99f2893eea2622617bdd90b9285cbbd12cfe6732345925bdc068a951ec60652c3b275aa36b5e1481f68bec32e7aaafa0f6fec091c070de3b5d92cf9bca28296b706fb1c5c20908e42a594d518f28503b5ad47d82a4df58e4f6c35cb45017ed999009183cf41dfc6acab7be3baedd2e51e152efa2da627ac568ef59a98b3ded35e2a84537c6be4ebe22195784c3025a6b26729242aa181bae895574eedbe8c39a2a3a82b1d50586e6004af5855c65286dcc6179fd346e5e7e84004c3900bb71ffe8282a9c0587f547d218ab1d09b93ce870ddd329e934043be66a7fb42f36a947b430286ecbf358ae642ae45736551cd338680b19fef13faace055c6104a487737d5822c9a039fdd959f4289f3ae8fccac214cafb37036eabd3539747df9edb1086a9c1516fe379aabc29e0ee411ed0a44186d2ff25731410d1b70be8426ae27dc450b4a310a22e1cc8bd3cce361bd8f37d6d9d4a7b0117ec03c2e1bc64710fa54701b3b45c0ea4760622ea0eb498f95f200657a31a8f9bf905f5274fadf0f876e5052411c98feaeab91665480720a429e80b9934723d87758612cac0bc1d62d8cbd1368429a7c94283181080fde0bf525501d8c204a15d296b617a31249d62e7f7db0468d9d77055a94d0004618866ca90dde253abef55b01d3d950d260b9c2bec211bb1818a91e5bcb4010df70379ed5e0e8d789bd45eb7d696922d913725542db386fe52c107942f65c316a3c7d62b9ec2d6a10c902bf70018890174eaee27c9138ea3c81f90624b713f0c35715ee6a5706b01b976dc6e9e9816905ef26ae65ba8611fa433c58a7dfca5b8977a1ae07bf20701f0c4d89918af11142be6978b575b1a2c1a909628037c6dd1eab6a02029d1545d49e627ee50e00d2c83ab005e0cdd0d6ae8bda4b9098dd66aef9a95c2aef2946173ee029696eaf0141491ca7c1a6a3d823bb12f5b35cf1b8aee78f28f0a2331123e9f3edc708fcaed175a85a86716fef1295c4c09acd293056cd4f62265680c42129dbd6b63f76ba867999435109e1d727f92650d8a5eadb23acd58c2b1ed44b7520f5323e8bc2b8e35b1fc92e7949cce8605b08b12a3a83f0234dbbac2734130d9e90a6b834003abf271a752c6c2e6526dfd56b435b98518900ec4a4fd6c4a713583fa91edbde6def74041e7538e21660c5bdd1abc08dee01c04bdc25f7ebe0a622fb3ec5cb32919589a089aec904dd045c7b5c9f8d58c4a4c93f4a01eb3cd7cd10f88a685ce4eb8ab619bbc9a22b8338521c8765433c53daca0416b8932b169b57d018d7149f9e86d6c15a3e57e24c00950260f8856275ccc2763aff590c9c57b6aeb7ac90468feabf3e094a7a0082028b4ef9befc1f582a3d2e0663a3826b2d652be35a5bdc4d57f2139947dc321d5564ab1052ce5bc4e66a908efd238a13cd263d47b1f31041ed9b7e1ea5be1d0b9f0fefb0a1ae2ad57c70d534ac2aeb3ce1fcfce4fc0e2f8ed1bc46e6747d028ad5334dc434b6e079a2a18f632cf21e5b0fe314f2d45b0c400d98b30044b99c32cda8cfaed2c13a210b730d6691e46ba27700addab607d5c3b8780133f1513b6767028dd60bcb6ccfdf0ffef355e56a592f2a9a47410e8c75761687d71be0e3714e57f2e281986213cdd11c53c4da1d5e92cb9f086fe71d0c016c1e153ea04c22d534d21ec4b25e185064940c8ae6bd2a68018382d407d820f2f9e37e4b65551f2f97724597500aa8e3f612b4355cc8ed82713dcf9de5f0fe8008715d00bc5d1e2b7f59c0bf987bb50213164e9f8a5f6f368a329311a6dfc195749b2f45415602b533316d53f7a5267e4d1e7b8eb5139d3951dcf3b82a381adfadc9d082ecca9588a078f28006d8205b0bfcf70785a38de1c20e474b48e21c40c215f326ae32483788eba7442f973b8d8c09552b242d1e15fd719f67bf2e715e93c1ecec90ecf2ec95977514088d0e82879de6a97ca13d4425d25d3415bd17c5b5c00734e98050891b59b17605a90241cfa364c0fd340e741def9b586089d1a08086237e79c44e6585f7018505c770fde75a2f245f66e24d7d3760e3f3d5ec9b17801325452a273e89303ce5ea402948b38310ec8c921a2dd73c95d45da6dbba9f80b0372097b972b1d3b2205b2b977ebf5747e832c44741c86381e801eb31c42c0b18a024f01615c0b155ac41f3aada0360519a5208ae6787885a0406e047dff5dd2a593a4b30ec06fd39715bb7ba1ace952019d96122c7d8c6257389994f533c9bc9f675495eeb7bb8f4205c295c414f3fdbca23ea73bab917f823c08fda70863722fe3181b8a44e742ad16a4705da7729022861d5f7557d6b045498294bf8c4051a1cd8475deed8da1b383f48ab66055873170d5ac85587c5ad0e091f67f1c8e64b98bac3fa0bffc850a65edf3f0732b63d1e9c475d00180a57a9aa78d2301be6bf8aa936afd2e45e4d1e4047000898d80500d81699427e31098235f44ea5539f602e4ef225f51061be585478c9c424bfe2a1a80c73280293bea6ab299b03ff2273091c157f556d8e25154e071c93dcd4fc87e337bca5172612a412ac791caee2a5cdb464ff6652cd0c0674728ed0b05cd477b0aa66f2f2725408cdb58165135f9ea259f0199bd19e5cd552f6771f5a0822460dee1b765cc63676cfaaf005c39b124beffafeb814eb0af78bd6913eed166d140944f022cb06fb44e270631c9c841a1962e73c02e6b9ef3942a2be63fea8e9fccccc80e571c663b0039b1fe8cbf57c9af3af133ee03da30946cf7b5c5a0f3518bc492fee07938de7992587e69219f7f6f45daaba4a67a861d1664988d4cece444dab0487de3fc360d2cbb6d9a6d8a3007510c1612cbc490e140c09043b9a8043145d8a92e8220598c061df048ed64726b2b6942e966a2c8f812185861b611fd536cd979023e308299a9e6414a2d7173925930f9e3859143d16691d6c413d80d08f108ba1ffae88aba651e323aa1591b281d26b5c95f2101a98b647b1b6afa7f0b356254db76d4ad4381081403bfe445fbdaef10ed0e31253d4934f6707ee7baad8a9eae74462bc42229fcf6b932acdcd129c3f29e6d561c7f2f88df859d73503b368af5140a0b3de0ae96fe1ecbadd8e07fb1ac7868ea144120ccd005f64007ccef7b0abc6cc3e9cc021b4cbdcf237feafc3dffd6c007d236d48faeba32a9df69c7beb7b3d516aba316196c93bc3702841daa7b0793694fa4d30721823e0ca0c33088df17b04e6053e90ecff1f5e89e90f6b8de38b1e8c94058daa92a327b06720502436289897cb2ff5b304a10c2e32893a8d5844b16413abc2c2a34568555757b8927103219eeed12c15d498e8ed62200ee2b0de71ecdfe3741daea4e749ca89a21307e35db9dde1b732372828765929add7ac245014681e433fd6dc208f19a5e4580ac6b49b01e3e3ee0acd2bb1dff6b93b08535c8fa6108ab1a1a88410dff1a53b54efbdeca1eb57211109bf592380c41cf1d78b8a853e0afa78539d827f923678b33126ab3f9987874bc59d11672532f6ef00ba7f2271655b2da0243b2aadcc5bd1d9daf0646c436f81b70a20102425f87ae079fdfb0f238fffdb7497058f6316b19c357f9f149e465d5ad8edb2fb304458a4b09ca0d19925fb6406d1f7d95b7d0c7c9c9c5be1dff6bc51c916c5554c9a100bea9d59219707e2130e976104db37fe69ff6d7f1bfece45e9cf343734089caf6708d522a876a237a28b7b7ed85781597b13f0ce836fdfe1dab9dcb23b7b146a4f77cdafd93c8bab4e6206cff6ab403c7dc2ce43f96e50e7c3ce6d260c0d4e10bf098b5504ac0ea977b8fef19cc52ef0508dc787172147c9fd5f31c327a326e5e3d6995af50bdbfda45c7cfe559ca8ff4ae6b9298abc82744a6c82ebae545838e48e0c9e6815e9654b1e2edecdc509e01f73f1b1691cb8a9043e7abe3af0003848acde906024b94a8deeb7e52155081f57e7454475260e5504c6d19ba6291a6559c010a733890d0bc5c873d24affe49fab3eff2f42606022f33c3ff023a48edefdd8466019ae2c926c2b6a60c4780ed163e790aaa7e3545f823bbc8979455c861645f021e01a29fca9fe1ebe5f60d86e2589b6bc83a4cd8ad531ce12f9b4689a0f1d51dd6e59f141760a01f490744c547c86618a637db477ec8b122e8fa4952b4d174d03bc7112039b0d394074f1a50a2f3c9c9bbc8522a5e88c9e9ceff28b07981d27356548f5a65a16a2d18c3842abbe2db9f3389d1107e4876d54a315b314f559f4bf2de8772ae2a614167d13c2ca99e9809b19e25999c7fafc934a7024340ee8e9854251cdf621c123aaa84653131a4849f4958c46a3f32fddd3ddd37d849c6425e8bdc36052e0da887272221b9401d0e18b73444ca37e145659676dd13a98fdeabbeec9f5b52f76572cc246e37f401283a149206f7afc15bfc6ad0f39d5c3c2f8815010b5b5c5d1f8a78e1864662bee2d52d80519e1f04ac19c4b5b14d6c89f901dc0d617be5433185edeb3e59f3e05bd57da0198ab79794cd2fd241cee624e58a80fc086e9d7362fa21a1e7b29e080ae847a1e37b74ca1e17bf81a67446a6d307494a52c9d43d57e7504f43b903bf612bcb9467747bdf6a5c73c34fe761048238db1b88bdde08ec1c0d7288d299f6c0ac23aa14f6c11d5706eb8331c15ef6da96da7e9d589d7becd758e324c440f8cfa6fcb0cc347373255e1c488ee0c09a76e8ccfbdccbb99e465ea1af4284a03e151a13d380c28abb7da0a9f9de64d3511e8fbb54ac51991a9e8a3832d73ac84fe491724c3d5c981684b8109fa3398653b6be36800d0d9062634b1fe229d4b1cc8b428a9644c4963ae6549f2d84aa7f6cf743cc5b56c847578282c0d347bae1482fec4ced8bc79957f86ead59a526f362da7534f8cdb50cbd54b5acd3a71bb9a8d46061b640f50b4a06adaa0134467baab9d1bcfcf05194653d91cdd2799895d08b419a74839f87e3f58067cfe89da295b471719482a6bdca2535662819dc1d9b778dc1d80fe8c9f4f7eebfd043cd0ec2c47781910ae77856614a38889a5ef4dc057ef8a674498a408a0457f3b6348b71d968bf0af44815f479d5885991d70e5ba0577d67c3f17a93a69b40ed316fa9fce8b16036482ae6d4b91ce15c0083d915328e4fadab2e27ff78ec9b9a6726895fac739606e08b3823dc2e4d1c9a153dd83c4e04ce457ab46a46f76a92d5d87f227ce2732119d423ad40c595d4704a094a5e6a01a4f8f6f01fe8cb39cfe3b583f77a66919be63f519baf94b6ce700f9545f6e1d8442d66e3ae65e8e2bf7117c134aaea52311595cd433ccc538bfbfb6f91946bf95a15c6ab26d93a765961fdabc2b5b9d504f320087852cfd4e57afe9a79e93176fbecaad9db090cf2dd3c6275578cd67a2733634f7d48939f57b370aabc343a3766423cc3b2fedddf0801c157876c421822929e276383aab6d83d12e3b3768d01857552f21e8bdce9c9e547bac7d68381a887a933e75594c07763379947642cdbe19b8f6efb122e8aa533e691801a9633743365ae07732b1d67954dde0d8287b74f38857d2bc1fe28272c4b0f51ead1a6bd6cd981b9c03f5ce8900afb49811cada8b1695d697a4dfa2738427518be4ea60d2656a50870811848e447b9b3caaed3edaaeceb13a5e9e950d19e4f4797e132b79f1a8cd811de8003a33f3053700eb8b44b2aae68072ddf92d18ed5ccd815f857715c3199ced20d7b85689f10794b741e5d42ff25a22107e8d0a0718ef83d8d3456a48b620bff5be9fca225d81d8217d92c20c015368111d62ed07348c12f330c64cea58ab0b89b6d5004d6071aba750410984b67257b58f832f4b0f38c155bbca962e1b65a86426c053c4b37c75f3a5e176fd740e4360a4aa12c9203cea663f281626f374a5997349f342731c0f82e63b256c036808735d805613023173a39e618ab6dac2cd1b489756e1a61c3a6c988dbf6d9fe4686b019057624b7618eafe90c40b4f89faaf1e10826a0695e01372b367370ad82b8f26c0f88d6553870d002e46a583d61fad3bd9beb4568028c57e4f23fc4fda5a19983d6c906ca00f0eb83d336b4c4231f47f28a8bcc9bcc6317eb1dd95c1ed9fc9850f02bdc60556fec8dbba7c19ab0e925e678209f8c7654df9b119a476a7da5d7f8ca90fd5ff92eb879d6023c9488024da59e202158fb9aee723895e404112e76efc95e1ebd86902a3b13f7afda78f870fb6ec9dae12f98e7184ae5dcd8348512a3c056ba9d16c02ce11604b38d222fb389d523da9cd5f5406d983e5a93ab99b33186f83cb2531d2dfc0fc6c513a8ca0cad169eaa125ab7cb0ac6718d02f5c98f1e33e93fa217c931ffcc59cad8c53e3e59da8e06653de634fc504c6be4be1eb43ef414a11ba2b6cb522b3064a912a7bb24ffa3fe31fdb0dfb01830de749152a50a23fd3c881bcd5995d3506383e385dec95c4e6601e92be08c38bebd0e32fb58479e0783fb2aed76a8b552bdac149b4976fb867f79952683ccadee7202daa94408bc19e1017cd4a5a5007843710e44921a8e25f6355a0307ac320a9b5722d2586a00b261643ca471207d50434296866cd360177d5330e3f1d59dea1979abf96b4fb63102456660ff397888e64e1274286f0e9568dea69a1551920ed64c2c81b5c70301329dd0c08b512f0ea0e0a4f81a9b719ea3716a30b419fafb8e9fa1e47edd3bf169ec062521630a0038bdfb725022cc5d0f7575863607e5cda95ac645e85ec3500053d2ddfb735e505150903f88149e35578523f3446cd39c4caf34c1b77590c7f295949e091a2bdb2a75e5f043f2f22b925d9508d5563d3e485827956304f3a26699381df3551a5e46e63c1943758e4d4e363ddd0f747ca21b2408d6c1d215d0fc915fce3335b38db0949155a2768324ff97cfee4c18bb90690147978a1579ea947fc7cb65c57f0b2fbeaaeb5fec88528f660a27e8c701dfdbe2ecf8282d3f8b8e9513764911baa3340965c52fcbd8c0242ace489a45c1016220ce01e08fa895984dbcffd8df4d4c73d74eaf74d0553dba2a040c3765ba12ca2ec0f01a311184cfb50f5bc7aade6af3da0e22eb9c2163d28ff475d279f7170bd9d01aee0425c93c154dedf0e20e1b7ce8223fa363079cdb83c8778c405b42bb2ceb8723796acf94ca9985d1b31d94d3e4a03f4c0c7e40dcedcd6d080b7227647435c8d01723be09b4fd7b930d584f95dd346edc6e8ccbce2c3ad8bab4b67273ee1f74ac820146ba6784b902b40c5d3e1d5846e16624d9c3aa54eee90c9b667e8adad3209e94846a694386fdc5a9a775f79dbade7570364237ea8859aa23b926ce39965d5427bbeba79a5ffe1fd6d23c64c014ae6a30cd88c19be662885cdeaa3a227f4ca6380bc7715fdce8bc969418149e93d5030f29266f4a23855021a84f14e42076b9f4b1b48232094223267c9aca11326dcd0e40be85930bb0bd30506c59e52919ce9e0ae97b765a34537a7f25699668fed400c41ed0b7689ea1856213ff0c8223e7db57032125e01ca3947e39804189f035cd018e7ba6f33467b424a31a5d27ee6e31049948b385ab01adca069b1416ff0ea1824abe9646c48855d0ce873dfad17b8372e71efcd30542957c1d41590210dd6f2062b8e74e466733f6ded9ef9d3d8776021236af2d2c0bf853716986c60c877298f9fe8fd407ecf70405c9d3ce2cc0032aa134f42168f20b8e29d2ec58e8e7f8ef32884e8511d9f20a091a5c0666696601003032a34ce99914a65eb94a7566ee1228e19867ef1b2b3aa658b0dcef94937dd046e686b753858b896704e8c11c9f20bf143f418a49479977c4b8c7d07d23cd348c51fe6e48f356fd88f54fe888e7bd139073b3799b9b7da97b2927a94a542d79ab28db439f11d4bd1fc75378a325c715ef10c16a6827e181e25f6c6aa0b0316d26190ba203cf5ed056fbd0a49e7926ba35f315d4f64fccd0d17aecf001bdac42507443ef74f889555625f2d7447c3fbe4c026d2c339097988a0421cd016f09832288b0edf5c14a2ae4ba0d8ebc6d1ff2d2e90daf72556cf83c48425eb2501e144f072c33da3e351bc620975adb5f5c53d07ebc2ef510c5fc4a28d427bad1f29e1b467cb58e1ebdf29c32e2ee70eefc937af93fa31ffefcd6492144fb367ff10c036e78c1bcd2e24014950204293f16d80ed2370a2753c3e466a5e6d7a9948e4127c1349699057a07caccb79fcdc13035531e14d8d97ef4d7de308adb07f0ac9f6e6162b64b82b3a3fd44bb46b3c60186999f02c5e216c0e26d7717098e48e8e2de90438a2858a1fa67f0601189b5b937b005706c3cab877531f8b7c7520fd6ff6005a60ba3f82a6e9693e9e15040df5281a346dba42081b0ebe215485ae4f1da44a1db01b7653f9329410e0ec8a76f13958583f188858e28aceab89f3bae91d397a61eeeaf69fbcc6218093a3b9cb1a7fcc89ff7b4cf67a00223c796e91ece71c87265eb4810ec0653fe6495132b406ff803d40445da6fc500b9e4e15739527820a2bd205fd5792ee1f16d8471889088bacabda07898790dbd9ec2e6497c8a271856108e3fb221ff989397ce55397c11ef2fbe31e74fb0e953fd90e5d06fe19f2496350e3ea1b8c3129ccc4cef34507e07e7889efca36d851ef3e2ac7738de2d6da02dafc11b9aa1bc1374c158f3cd343e2863857709bc76923ccf4716540dd39cb86814fbc2323972a55430cec8147d360aeb25bd49c933747a8d80e05472085ca592db07e1cb9d784a9f0fc72f9250cfcd00602a62a0edb211f3083de0ab49a7999404653f5d138af7c2c58fea391f4800159dd564dcba1e126e3df701afa228ab9c87c18283b19d1afc2d7e0e864a6d290ed17a60bb3b712e2ed1f31c5cce9bc0990e4336b30e40d39cc8b935c23e71860db8e606820f522607db13843f7ba6722b4b8113ff4c84ac4cd8e928a97ae1c43f620e9fab48c1c4077794cedf45bfe3d2518054c4ac8d3ba38913601b451de40c7f6f141de2175736b10c6b23394ae945da3a892d35691fc855a2a3f27d3a2f5b6d6c14a47013fa86b1da7cd2eb08e4081de371d24dc385b2fc170c4a7d68a5b6f42e2a0b90535f5b5ed72e6278b1f17fae63cfee3dc380ae02c31965e18e1ebbcc48970cdb0c5ad0614f0f63da4376daecc82d704e91eccb60de252ea455c3fad417c90badba32d591462c05c1b55ccd3b39a0ba60eb7b9c2d78a50456409839ff8691892f5d69ef6d076e700dd23e9c4a03c61ee35557b3b04d46b914f182d56baf19aa28d494327333c50f276ac3cbc54e3dea02f3c0ce24a573e42dcefe880a9fc3f2a108469d4f6f42810c7c5b710cee10e408afa8d71c7c8c3cfa257fc723aae5f194b2ccfc3a293e3ff2e033300fb333237d00dd8ec78a7238f4908829b122516c1def706ea41dd477f58da3202d50e8a99028d475c19a3b823d7a2e3056d89a9f167e002d8f8d790360dcdc41c59ca8103252b563544946d06f8c642b3a75f0f7a4931b432afc7a30f4d245f3dbf30cb1ded2161eb5502ba32e43a08a3453390df7c476a0ed4cc0978bc93a19a0d375b704870f2a1fc159a53500b6f391d8db4e82c23e2dcf68996161e36f489f3b14a6ea0f77b0d809ad35947cd543462985fb0b05af542491ba5504408ce7c69681a9e05cf5ce939acaa0d5e2917e0eb5e4dd0debc5ef9ed969b8a0397e4c10051c901c010f0f4eacaacfb914cc1b72024b8691f36752060d59554a68f1df98817d9bb93afa0e7fa7557cf6de6929b1d0e9a794a06afed0a6e157dc5606c33ac2357880619e3fd8ad2d013d2728a077e924c400e4a42222872cc7ce325cf10499ff351c8dbfe6fcde1be7a9b7cba2b321b064e0e5ca52b44bd12fb56d623f6a685a771330ed91f6f5fb188fad32eb7c64540ef46ec9f8ba84f455658439d564a5377e073941796b9d006ba24c5f1fe80daee7def3b461d6f6520df8da957b732f27a37e182bae2337e6e2c3792939905bd2a01d1dff4c8c2471c747f85bb9a72fab70efcb03b69ea6528eb2c8b67d43e8c008335e8bc1b1b8d9167b46e7d9d2bf80957afbd0c9fe94defa8e0f8a32e184d2b0d33c05834cb046b41e3c8e97e55007c38b385870f052d55fd2d4cc6769ab791bc6571a1b27293a9f5e5910b1e6585789adaef9aa2f19e95dec4ee873334dfd1bbcbf63baad0ea3e6e82f18d95fb199fae5dd8cee28b01014dea241aac787877cb59a1b61b4798d3f562218070b55b3b2f64640efc6f9b7f8ae0eef0291a3a9b67acbe52c4ddea2b92a203b97c7f1439e0847775b8f162eeaeb54da58f90f9dcf1bcbe1e0cc494450219677c5577887337efba34b6c822050ce17218a7dae0fdcaf0afca553ef652fb576d36198d553994a41f28bb919c4d4f39c901e7648da377e58203a26ee340ad3afd00dfe07a739ffa49739775e0bfa79e444c2281321950006adcffe85e1441bbb9ddeb55caa59343fe2235fafa0cf3e0e947610071dd05ff0741ea7a0bda3008b3feb1688f443f7ce174f61090645cfc6f7721a329c6bb9b8cea45645fa91ee1e3edc3914f469bc198e2705b46bab3c3a96caefabb56b0f268a63b3018cd6d81c9ef67891936861b050668347253aaf424d07b46995dc78f83cb5d228772831d43979644269fe8746790c09726187fa09d017980f362651334e80baae8c898be7e450519acbad8c894d688e910decde71c78bc91b4fbf2e014e157a8e4bc83fd946ceb38f5d110b5f58a77365a2bc5b74263cd9d90ce28c01d30c7f49fdd2448411ed67dc324ce4c6117447359ea5cee82963e05baf307afefd29a97cd814ce45835f99014fb875638cdca985bd369632df1481596b8551eff29e9ac8d89bad110213699a4b872caf9a4f70df76a3e1feb2b04a84c03d79338995abe50f4314b5137ec55f451db9e93b885323cee4896efa3837ce208a12c07ce56c60ce193a9d5857c87bd59087a055b5f5c7f3a4c7a0fd331fa541dc632d19b549f8af428818e5bd547f9019114909bb6b7741f0f9db96262c71ad1f936f1df055070f2390a094a024b19d1cc81e6f68159913a644f6e42fe2ad5b93c3dc8984ac76c07c3ff92623665a39e8ec17ed9514644dfbb49c0e9c29d1a4b5e747202b85d4308aed5251c5238ae4723d6a24891b01d08924dfdd035bc4a0729a63b2789be9b5e3300271266ece585033b46aaca3c1bf8acbe06a12607ff7b7a8d1aa7e23472ca639c8b2869213f9549f04a9e0c036f748aefa7ee44537f499d3dc7a1f91c476f0e614baabc416644d9fd1eff8d4f52c7c1076b6e70e55e84e1c66e386abc841c8de64e0610b4ad64534699267f5b6ed6d1f3bc6e52866347f212b3f83d464349397011654eac222f2e72e8055f53dd6c2e99160521cdb6bb2ff285701c1fe5c308e228b2941c6a20f94221ad258ceea17c91b78b83f59322a69722a30fe8026d7d31cc1b05566e29acbe1cc3264185206d43520ef747d12eb6ea23e83a4c7bfd5e9716dd7640a5878ab220c4395921e539192e9627ad291330f479104b1a14a20e52722ed6bd52e5777ab019e60a2942db6dfe8fec7f62026ecb6d6bbed248dbdec652e1cb7f5766b30a087770908abfe97e7945e6c4038f505627d6aa5c4697949bb9d8b3180d52dac3de9efc35933c9f882782bc2e44ff53ef61aa7537873c84d8fa82369b303284fa20f37d4d78e6bf2cfe45929873aeca3a0f863de2a8445fa8f137007cc148e5a89253313813cc373a4fe2911123c5302461f3083d1e8ef81ad3ec0de5366fd29b9b3efbc94c7f2177e5e0d6f91b1a14ed6206ddaf48cec998ce905df4d63d37a57128f0a7429cd0b380846604d045ba607df9377cec823026c9bdc5cc71330ffbbbe937d91c2496774aaff4b9ad2430878e0c808e37452f2392e5381ae280fa08e89dd4edf04485dbc361e27c51f2a6adb237f9bd514a83b94f419d7e2c55ece68bacef2cabf0a06709fc7e0411d7d7edd3e7451710c3ef0758c1e71bd20ffcfa05ae4a87ec1a351010f6e6ff5ff55ff5ffffffbf59ff67212444a6e46592625b122149e40ab27e3eedcf13de13915eff46dfa9eadfcba481f1b596020817f618d61e3b6b75b73cdd3addeaeeca68536db3d2bfcddfdf66b4f7b7a957b5bfcddfbecd6867b66f53d55d6ddf66e7ecdb6cb6997d9b9af936956fb3bfbcb9eacf9bdff3a6e74ded3b6f76de3b6fb69d37b5cb9b2ae7cda86e7953b3bcd98c6675afbca957de5457de8c6a67ca9b51a59237a3baefa6bb9bbfddcd75ddcd26733779d7cd5637dd5537bf6657dde4ebaa9b4d266f6aa6aa9bd167b3f9d7ac9b6ad64db5e7c4dc744273533f73533f7b6e367dcf4db5e766e7ca9e9b51d7cd4db5cdcdaebf6773b36b96cdcde59a9b7de7e6dfcadc64a3ccf665f6fcf7cbfceb7e99deeb97a9f6fc327ffb76269477a6fbf2ce8c769df2cefcbb33977a77a6ba3bb3d5ba33a37f3f73677a9f3b53bbb9337f9b3b53a7b93395b9335b2867badb7bce5cb5eb3933afebee9ca93de74c9573a6ba72a6f75a5539f367ced4efca84f295a99f7c65463b5f992ce72b532bf9cad4de65f7cad4ea5e99dee795a97b5e994c35af4cfddcccb56fa66632f5ca646ee65f6ee66ff3667ecf9b5e3375bbdf5633f5fa5bcdd4bdd54cffee5633579d98999af9662653ffcc747d66faccfcad667b66a67bed99d96a55d933533373cf4c3733359b9951661431af99d9eeccfc9aa96666b4bf4b9de6b6bfcb68dbbecbf65daefa5dfefdf6650be57df93defcbdff2be64f2bed4cc76f7a5daeadd974daffbf2b7cb7533735f22f265d7dff3e5babde74bf6ed7ca9dbf777be7476befc9ad9f9f2fbb4f3e5e77ca972be84f275e54b75e5cb75f325932ffd9bf2259bf932ba2e9bfe5d97ea7ed765d79caf4b67cad7a5bbd7e552eb75d9f933afcb9fd765d3e775a9d9bc2e99795d22eee55efebd6cfabd5c73eaf792ed7ba9fb5e76cd6cf752b77ba9b67bc9ae7ba9d7bdd4fd65eee55e76addc4ba85e76fdd4cb353ff7f77aa9d3562ff59a59bd5cb55eaa5a2fb55eaeb96b552fa33dbf5da997faefce9f79f932f7cfcbae9b3f2f7f5ee625dbf332eaf36ff3329ab679d9e6a57f399b97d175b379a9d9bc5cd7bc6cfe9d97bfdd79a9d5bc8cfef54df352a77999eeaecc4b28ef4a1dd53aaa73ff8888edceab8ba875df2ea2da661751ff8da8f5ba1111b5f63bed1a51fb3745d45ad57fa7885a7baf5344ad9f2b7f6aede44fbdeea7d669abd5fdd43eddcdafb5d669347bafb59b53afbffb76ddf2ed79d75ae55d6b9fbbce5dbbfb6da1b5cafd76b56e75b4ff56eb5637d3dd5bdd64be7c6d7594b368b54edbdc6cb56e37b3d59a9999add65166d7ad8eb2bad5da77aeb6ba4d73aba3df6575d750eeb23aca5797d52ddf9fb35aeb347725aba32a57b2dad9b392d5daaf5affbdeace7f7e365dbdeadf66a65e75ba7bd7eaaaa15cb96a2653ffce974bad7f4e5f55ffad6acd547534d5bc99eaa8cffafbaca3ebf659377fcfbaed5947d79eb55e995977cdcc7ad933548dfe576da6ff55bf7f55ddbeaa927d5567faaad1aeb26f575dde557777d5d9eeaeaeebeeea5feeaeb25977159abb9aeeef7357339bbbfa97b9abfac955edb9da39573b6fb91ad5ce9673aeb6bbe9ae5c5d57ae32b9daf94fb91a4d4cdccfadeadff573ab7aabaadfaaf79bf55b6dfaedb7aafaadfebed5fe66cfdbadaa9965f5bad5e8df2d73ab6bfe7aababf67aab3addaada72366f75cd5b657367e6adeacf9f5ad5e97e6a35cafbf75aed3bbb5eab4eafd596b9bd56bf5646ffeb6ab5f95dadfe9e5dad465bad7ebfe6dd6a55fbcd6a556d33abd5685eb5aa75676a35bad4ba6bdd79aa55ddee75a75a4db5aad59c6ad5efaed4aafe59a9d5356b359ad5169ad5aed5a6cf2ab3dd3dab3a6db3eab259d5cccc6655cdaafe6fdaf46faa9ffd7d53fff2dddfd47d53f74d757ffffaa65af9a66bfe3edad3684f9bfeed69336ddf9eea55fbfdf674d56f4fd7bcd3b7a72a94f79ebabca7e9febba7aedf3dd5ecee694fa1baa74ead7bca66ddd36862eee90acd3dedfae79e367deea96e734fd9dcd3bfcc3dd5ab9a7bea4c734ff5e7519eb6dbbf3cd5bebf3cd5abfbf234da9be9cbd396ffcfd3ef79cad335779e465d9e76edba3c5d394f9d9ca73a6df7b3e569d7eaf6ba6d79daf294ed3f7dd596a7bfebb4e569b4cd9c65799a6e96a7bff325cbd3762b599eb6ecbbf2b4f395a7ede6e9ba79aaf572c9ffdbf294a7df679e36d3ffae69d7dfbf6beab2ef9a2adf356da17c4dd597af69f3f33565f23575a67c4dddbda6e96ef79a2ad9bda6cbe55e5367bad7347576bda66dd66b1acd6b0acd6b1a5dee9ed7d4cd6bbaeee74ea37fa7ad4edc7fa77a4dfb4e5bcee6b6dd69cfcc9d3adbb799ead599becd34dd2defcd547bce9ba94e376fa651ddb2bb992ef56ea6ad76a6bb997eaf9b69b477dd4c97ba996aaf75337573336da69ee766cab7cbe666ea5c7333ed3b37bb4ed7acbb4ea3fdfdad4ed334daf5aa539dea674e5bbeff9bd3df64be394da39d33f5cf6933fd3965f235ff9cfe9caef9f539d5ebf739e5edf6396dfa9c6a9fd3df731aed3da75fbb3da79cd973aaf69cb65cd973da73daeefcdd9caef96f37a72d8fb639f5f9d9e654f336a76d546d73baeab4cde99adb9cb63975d99ce6aed99cb26b4e9da97f7f9ad3762b73aa9959a9cc6962e2abec3afabecaa87f95deeb76fb57e95fe5f7ccfe2a5badf657d9b5b37d957a55db57a974aeaf52b9be4abee6e5f2554655f555ea55a97c954dff76650be55dd9952ce75da9135bde95ed5e799af2ae74fadd95caa5de5de94c77572ad5acbb523f73577a9fbb526d7357b63b77e55746b912912b954aefb992d9eece954a27e74affb65ca95bae54b25cb96eae8caa5cf93357aa3d7365d3bfabb2bfab52bfab52fb97af4a967bcf57a5caf9aa54dbbd2abdd7abd299f5aafc3eafcaaf9d6d5e959acdab52ab79553ad3bc6e65f3f7ad54fb5646997ce55ba9b65ba99d5ba96ea55ed368ba956acba35ad9f5ff5a19fd5e2bbff2af5a09e5ab56eaa7deab56ea676e6ae5526ba58efe376b659bb5b29966add4ebff59f9b5d36765bab372d5bd6765bb33b3676574d53d2b7b5676ddb65999dbdc6625e74a362bd7352ba32d4fd7ac6466a566aa59d9f2342b3b5f7533cdcaa8322bfd46ccd0bcbe4b68d62cf71a9aa3199ab53343335773ca9f39b7ecfbdfccff9bdffcfdcb7cf3dfea9b7fd6eafbf7ff5975a6f967fdf5dafc39b3cdeff3f7dbfbfcd7377b9fb3d36767e7d0fd7bfe695eeadff3ef19ca7bcfdfebdeb366b6b9f79ca36ccf9db33dab9aed99ed59bfcc9e73ab7bcebae774ffb4e766daf3babb9bf553afae9b7bd6ae9ba34cdeb39ba36d8e7ebd11dbacdf16fbb739b7ad86fa36aff96ddb9cf5ea6cf39ad9dde66867b659afcc3677cd6c73e7cde89adbac6affb2f9b72f6733b3dd8999cdfdd53fb3b9ebbf66eed79c9bee9a75cbd7fc3d67d71cd5eb9ad735b77aaff977bde6953779ba66f655ae99ed79cd7af5bbefdc776677d6ba33f36f35336b665677eecbac76be5ce6bef37299d3ade45d679deea79a75dae6a79afffaaaf96f56cd3fddaa9a5535aff9d5fda7b9f39fe69f669fe6747ffff234ab3bcdfaa977334d739a66ed5f6556fbeb95f9a759d9b95766bd2a3357dbaccc18630b4a7cbc6007afa5b5a1617073b7120df0f35590b360d62c0f473324cecbd22e929c19e5ca96e297ac1e188bc0470a3370f28cfbd93852202b3a384e408297ed9e53b0e57750ed07d57eaaaa55d50eaafd22fc7deea67137b96a10c94167ba45f0265477419dfcc9b4bdcf01d354c0e4f181176edf9eccb0218998d9b47d1655267de64ba6a9d1f5f02cfa2b6465f430e93b4f93693fd5bdab384c6aa59a6cc004c8b1c10cac9de9cf875a2f331ceac3c3438cb3781c1934c2f8bb0c661c19b0ea5e5a52c0b10cd5806359deb16c08c67e8386761fcbd030c666f858a6853184e4cfc996d5de67324a473248f848f6a6ede5ed257dd2ee42f250ddd36e7430aa451ca645b533b787862d3ff45f3393febbda99eae792ef253d05bf9b3add2c6f79aa8f6289f8f37e0cab8347c2cdba49d775cb5b9ca5e018f68631f609bc7401e0c83578049372040b00e3a876ea96e7793baebe82aa7e6a11512d42ddea2b08a67704fbe2ea1bd54e9fb5e7eaeb8f5f4370daba2a335a32ede86505fba876260fbb66e636f71d26a34a3f3f0a48618c8b5c0c8f48bfe351d1f1b807ff56ffac57fd7d3634fcdafbaf7dd72760609c05654b514b8d245aadb27e841d8d671a43310b16adad07c7ae21185f39726df13dadb347052ac6f828400a3e0a30828f0270e0a300447c1490e2a3003e7c1450878f02d4f05100047c1410868f020ee0e3162a7cdcba848f5b8730c6061080194072d999a2848da6a860a3a98c96014f00c360ea02369672858da5306163a929d8586a898da5406063a9326c24750a1b4925c2465273b09114136c2495b191941d56b3d6cb3d03628c05c483cb763d44adeeb96cd753b30e8cf6df7a50f31123c5224486e0a29020181781dcfd28faf05a7fc0c3b8d803e3228fac44c51d451d7fc51c02e0b851b451ac21018b515791467146514631461146f105560c175966128bd12c0788d0e7fb7d6f313804c39d3812a87b7bf2c3432c178d0c183a0ed8f1219d2b215722ae045c89b7126e25da4a605c748b0738c67800c6b8d816d9e2eafc9c0706367dd6d32af7d3229a3eeb691176793fffe356db710b99a4d3ff2c4957410b1eb7b28e5a9cb059857c4747c76cf7aab659afc8626775c0388bc352f3619cf5e0f35570c0da11179b788a4c2c404b8de59c847151c5b898625c54160f312e1a625c5c81715105c6c514181751605c3c8171d104c6c51218170b312e12625c2481717110e3a220c6c5408c8b23302e02625cfcc3b8e857e4c3b82802e362088c8b7b1817f5302e82287ac0b8988771110fe3e21dc6453b8c8b1ddc04628c0f613ebb41bfbf137b817f7a490e1b30215758877d24fc0c3d80b01314f4d067981768570848c2b0845ddf61b14e03c6b885282fad2838480e0ac67dbe625ccc80a783d50b561a303eab4b9ed17dbe7a12acb2566532ae1253f74caafa8caee76592f3af61951ec6be1bae7ab00a638ceb3e5f9367759fafde50d5745eed19fae46854595133aa1af01609624c35a8539da5a9ea6a974a0ba7a14a843146eb1a1515544a30c6c9a49a37a2023ba50ae3e48664928ed91ab229a2e1a97caaf0d41ec60e92746c8aa8e108df08dd084f859d4280d914b1f0e9db176f50d5ccedd3d40c693e6b655e933e43ed9abfb739d92acda05eeb65bbd7bb07e79f87c1513b4609c0388df5199ae6259a3153036ccc04868d99120cc012c5152a124ed2851293a4fb3849670c35879374a1b492747e9274a08c24e940a5c0384907ea0c27e93ea1c23849f7494e92eed30d8c93749f009374c64fc848493a4f5a9274de93068cb1a701493a63273f1827e93a1d76aa90a4e36487d30fcca904c649ba4da430de84d4844a931d9ca4d39402638c85f11f360ec00afb9ee6b79b073092e65b3a35df618c55a24fd142d1ec4c8534450a5885269c88deb57cfbfddc794509118a10301d5e52b325869b3e3793b967774b42f22c435dafb6f94cc5218a64d287a537bc00634c021b2b0dc1bfd52cc6c50768954a64a84496e6fc4b7ede56e2c2d8c995464a408c94c230a6b485f124b54911268d4d2a60947407639c96a44bd2b57a354cd2b5685ae57e819a99013d441a00779db805d3dcac9b6a9a99019351ddfcebbbd49e4432ed50afeade88b94fafeaded7fed0eb948ece27d7756b9fa3eb66ea55ed7c196d7372b92b24f59abf2062ee4b5375f42cddcdfe977c53b3254f5371b8fc6b35df5ef3e69c99b44ba6b15b33cd2af0cffc3969644486f1a24a182f128371daa21dbb75061a17fdad99d9ed13144191208cf1e1a1222618af4daffb0745878ad654ba44611249c0181121acf574ba9f5d0baadaeb764f55f7548e17edfac953bff3365f05a35a849a96f07f2e9bf711b59fcb763d5fe8b25deffbcde75bb079df673e28f7d3abbbfb60548b68359f67d312f9e7bc3cc1ae558ef7b5a0baf3dadc48f04115af6b403bcdf46ad67a698bbecce75d362d416768e8f7b72718e881d0d00308bbc0bf41414343ba414228065d1a7468d084a6cf7a776b6d6d6ed01ca8ee216ab5cdfbaf6f9f9a022400602392ac23a3b0f188266c3cc20a1be97c6ca4b3c4463a84d84847cfa8e40d1bf7f8c1c63d6eb0710f9a2cacacd4306b0302247e64e9cf20a018d82f49176d312e86618c0714c130c658c52f8c8b5e078a488c8b478c8b468c8b5d1817b9302e2ac0b89800e32202ac48587db23a140f140d64218b050864a91507f02902501450dcd22aaa7a10e36216c658ce2216c65879b214bdcaa4ea3c8f31562557adb2587d3d6dbea7a175ed4c731fd433b4cb53288f198c931a92c934bdaadb7079294f8b31e6cb764feb0f86dabf3935e42a9e6dc4d365bcd3c678478937f864febc6dd37c7ff0339bf4ba39f857651654b51d503ddb01b4f360039ada66b40d2bfb9b69fdfface6794f336bb801c2cafea6a1617f7954cd6b75bf4c359f72d5d0a97ac3aebfcf2cdf691a2818b67cff560bd22162a453068898fbd2fabbbb7ef2d527fdd6be73289ada73745df3d7bef3e59a1173dfcfc968764124d35c420ee8f3ca53fe7977932bf79ad9f23376ab38e4cb760f4fd5cd6852ed88b92f2df9551c0a2e971c4dab19a2d9c9d7d6d6d82a2479132f99a6d3fd79fb35d3affee5bacd7f7dd9ed93695de7338db6e49c1f26b99af91acd6efecbbd72ae4c6ab4cc33e896277f4e26d33c9c1b1c5c1c947766d2b36f6132edf03079e8fc3bccbdcd2987fe25f73e99a1e966731b5579ffad1a448cf1bae60c6ade30c64cffa76640318d9f24ff8ed2cc30a6e1c3382d430634a430c619d0e44123268dd9ee0cebfaa24944b3867186649ba44373468ff73ba30493309e69be5ec9d73be3990a388336038a847e7131006392349cd66a27ef19b0d1cc205fb6db0c19c6182db99389dc58e6115e961153c608c6becc0b0764566132713026e480c9dcfd86faa4867eddf34ee6a4d7cfae05936959c5a1a1a6a38bfe9df255131ea248b63b6737f9b537a4a3fb5a700d0d2d0cab308992dae5a94fb65b30d54f4367d65067d6855ffbb4c1649a6ff959e71fdacea1daf3669aec2f37914cf3fefdb967d7cd162cf8ed5d27e7cd64bb974c2a5f9fe49fcfcb9b83e48b17495527eb36bc789134abe0779ad67da966f43200a72d754f667615c659aa30ce4a8571162a8cb34e619c650ae3ac522d76fbaa3a5084df2bd8650f639cc6e5eddd031708696669cbdb0a499d7fce4b76ae77ffba1fee31db6dd6a69d79bd33e3cc35379b8369c94366bb9b3eeb1d66aff31c9ca020776656999369d1071fe6e0bc7f90d4cd3f0727c84c53e6a5e594e3357dd6fbbeef57ab2bafe0d9645f322dcdd3f909c9249bdbc334dfee34b3ef29b015927ac9b4eff9cadb36ddeee1e1d986410d9d7fa870e8f5926fd6ef363753ed35533ff5ba26bd9aeeef77ba5dbb3579b861c3a0060d8779b0423299fb9267eb9a0fb51b6d7ebe4ccbdb7b0f059369aa9b4c3b34e4ed61b2dd49bf53dd5ddd7499fc27ffeb26bd59bb2b24d35835ebde72cd72bfe4684c447e974c8b76ce6a16addd49420e985cb67b2fd95f3a0f837fc9b46f5621994c3b7cfb60d2638cf7b03100236c9ee4c44f9c375c9c3c7182c4091027884e9e4e5e9727cd2454504b9a494826cf2424e95c9e3c9390ac903c4baa40318893744ee430363a393649857192ceac427679ffad36ecbfdd7474742ac71bf4b0c50415969b514903254823922e4624714826783ceeb7aeef87233b30c6132868c018ab18678daa33e266cdcddfb3fbab86ebba9dffe55ae586ae1f8231de81f156872c37ac0046618cab608c054be0ad0e18e341820201fae3a70f1f8cb1d61e3d09f2609c85e70cc67880aafd9b27eb0ea41476b0e684000aa98031360ae162859374bc095583040a820827e9bed7ea199e9bd56cb834061100c4159048493afe936749bab3249d211e8980d07003c287b1f85fe25e0febec39c428ab8e215d268c99add6bd93d1c70feceadf6eaf0e629c452799db923a717bf7fdc9dca3510f277bde8ed9ee75e73e48011b7b04628cb9f070c2e3070fdfb5cb7bf22c49e7cf366c98d3d0e646e2fb96e3d1d119aafa4c37ff2ec473e6c10dbeff217ac89183531fceaa31e7869c1d3910ed8c3908b01a58de3f00aefaa9f95c3e4847e795461c5f461c026e74c27e6740aff5879644605f77fea0ea01a0a5f51328dc4c49a46303b661ecc89534a812138012d5654fa23dcd2708b89ee828b28a6f8f30499715146048525640da1900caa6010a2f7548e0c6a830c1868c9829080268c9d296846f559d323362cc0cb9301cd23c9a32a00c2933216a88273146483d11ae36d18992e32d82180e67262550ecc40a5758ca8060ce416be423eb0f603610630a0ee0a198dd98a8e0973a5d05661c01318913a541c19e049b0cf12dd1846548189d0e76c0f439b609c4b2c7508e067c63204a50a945301271a100e8228d981856ec8e857496680992854589227d8180fe266c09432bd3c14866449e273491b2d098044a9001862417d80a4b482ca84a06295178691a29992990a0c91f8c453120d57014153107ccc9940345ee20a818c120496a041194316536f6fca121e4e5edcab24e4322821c2a8c5dc52042785da46032bce4c18f9e570596a0d4870f8690f07020070911871343529111229324110f3717360e447f14b0c1c9198b61a06022f46ae2601496486631e6e07ddd689263ca8526589adc214adc1eb508804c029de6de93061d7dc00c9c0e8710a0ea4ab284069aa62e3119144099ca84434f1baf56322445d523868f42757aa392854ed382179014217ac326cd21304d1a7d4610b0d2956620d3844346c85c42c31ad1c0880500af6890496b3f30408aa2c6eeca12d1df8e3144a298b809a357a8034b6002394020b0e0c2734aca994e40e2cce419b5375722ee0112d5991d949aa06ee454a016e468f1ba8cc54dda448677762511717dd02460080997b28f50a82dab30ad3ef08ed01010e11132511208305e624b9630494a191407d7a66788b876e528e56d73d7502ded5e2d1fa570e563941f4728a48e5016613a3a160268696a03c507c505d5cdfad0c685a8425e75877d0e394a6c5287a954073946a058d210c44b2f9029ce933b5c06d8f924a3efc0a24f70466d08f4431ad575253f4ea5493967ee1e1b1ee0f032b50562ff85507a26f200b8e3e56cb5381b23a694985c591d16202677b03829e4d0f6a8f18aef10cd0ba5a8215ba9963937c72557524841c0624303432636e252cd31d40051ae543848550012ce12b848aeb51c961a052aca4896aaf3cc7b64a9eeef559044667dd424685860644aa2dd043f8e028b5dd2deac1968f1e777aeb46b55a5dddc5303d303dea56dd4db7996d9eeb48dfa0ce5eaca796a68e8b2bdd9b56bc8bead5e0da33d1baabacded3564b208b7b9bdea9e5639de71c92a8df70563ecc4c7251f67111e976861259d8e4afc608c93751a9249bac3efb39b4c7edeb665c8ecbba8cbefd4ce0bdb97e3a99d17aaf90ee3e2183efff297b995ac1dc64531591cc264fd65eda5bbe5ac6ed9ac423a810e196ac16ed5f04461e188bebd3c0e74856e6916242417801d15141a28dc2ac4ac4a85ea84899223448502f5b943070e1b3463be60a1f2648911213e72d89081e857ad4441628408420f84771b3010bead9d4970403846f845c8756000a1d6ab55a5426daa1489d1a1417ef0cc79a3664c172b4f961801924346b4afcd8ca2305084070e736e24d4485480504662cc8b84820224b65ea512d5e952a4468a0c09ea8367ce9b3462b85879a2a4880f1b32a2dda90d5110fe85c0ab1b84631bb4306110c22083c1b1412f058304068baf528dfa34c0a4478c0e0de273678e9b3361ba6491d20409911f3b6cc8887eb799aa201cc1b7e7a1039d5b9aa005c107820bbe04b90c080e102cbe4225cad3a5488c0408fcc3a70e9c3464be64a112a54912224076dc8801ed2c33501988a230d06f0f8f035d1c1b9a9904070b02bd028d090a046e0562ad32258a53a64a91161d2af4470f9d3768c474b922c54992224076dc9081d882859a62c4e09f5e5e9d5cdb19851111188c181b711c9160c0882c57a7426daa042951213f76e0a821c3e58a94264884f4c031c3c5db826da6862748008af0d021c35b1ae004c00662805f5c800500b700b1589d02b5e952a4468806f9c133c74d1a315db044617264488f1c346044bfbbeabfc3bf12827f7c20f038648053bb40e1c11f0331e45f02027f5aaf54950ad509132547890af9c953270e9b3363bc6ca902854992213d70d078f1e45b3d3c4138824f2fafce8fcecfcd2fcdaf0204bf055f46047e04fcb45ca92a054a13a5478b0400b4a70e9c3565bc5c8992a4c80f1c345c7c775555148ee8eb03d167d7b701831b5a853e080bfa8e7d0704f4e155a43e6dba440952a2427eeecc699366cc172d549e2c391264078e198950cfe7aecb9ca230904f2f6f031d9f1b1a85076562483e057c04f8b65ead3a25aa53264a9018211a2402901e3a6ed084d942c509922039662076a75e5122904f0faf4e8e4d841904110d448889308a40200200115815294f992431320448cf9c3666c26cb922a54908250100e18163868bd75d99ca15274800f2e985b00b9121ae2d445a08b3100ec68e07426cedbdda63856a14a74b8f14190aa4a74e9cbd3666c064a1d2c4c80f1d33a27dd52b0a034578d8ab9b633bdba3901c3bee1dd813f02a55284e9720252204080f9c3462bc68b10285c991213f76d48811f5ec56551406f6e9dd6d90734bd3b31041cf811e999e979e02bd027a59ac4e89fa3400a5468704f1a923670d19305aaa385112c08f1c325c3c3bcb4c5514068210f1c14ec35c5b9a8508c9055e2014802800020010c557ab48791a6092a34382f4d079f3e18c982d56a02829e223478d1888de5d9b39850912817d20ee3e70f890e14ded830508655f1f1410f8507cc52a15294f982a41524408509e3a70d490e982658a13254686f8b801c343e2b3855355e181c488be3dbcbab9b6b30a101a7808337a38e0618087e2aa529f305172a4c890a03e75e0a821c3a54a14264888f4b80103fadb9da628cc1becdbc3ab8b5bbb102199b7200f99c79537202f8bd529509c304d7294c8d09f3c73dea421f3e5ca14264886fcc02123fab24de58a1378817c1f3a64805bb300018f011e58175e02bc01785aaf569d1ad529d39da5478908fdd143a70d9a315fb25471a2c448101e386644df164e66565128f817e2c35d1d06b8340a49b23bb0ae3b03775a775895a9509a2a416a9468909f3c75deac31f3650b162a4d9010f9a183865df46dc132952a4e10da8db0e3d3cbdb40e7b67626c181dd8230a45d975d01017659aa4c89e2746992a3440200e283a70e9c3566be74d8d2018b14264788fcc021c3c56f9b1dd414847f7a771ae2d42c7478d0a10cac435707031db45a9d0aa5a952a34380f6cc696346cc162a4e900ce15103c693af4b25871384817f7b771b30b8a9717850c601cc988083010e023864b54a158ad3a5498f160930a88f1d396ed08ce182a54a9426498800e99163868b7703db4c559810fc13a167a761ae0d6d83d98607641bc23620372838b081c086a2ab54a43e69ba2469d1a1417ff4d4719386cc172d55a234392284470d18d1b765b154aa2821e807e2ae6eae2dcdc284ba066275c73a0505eab65c9d0ac5e91224468704f9d173078e1a325dae5081928408101d34603c5bb42cb4e10912801af83e74d09041835b1a050d111a8869381ed0008006ccca14a84d982839522400a13f7bf0cc7183668c972c559e2c0940480f1c346240bfcb4267158523faf6f236d06588cbb0762143840619c8c08c190a64d87ab5ea14a94e961e1d1ac4c74e1c3767c670b942c50992224078dc90e1e2bb2c52ba431424fcf4ec32c0a9d199d14948d22d40d221a0db72852ad4264a8e0e0dea8307031d3666be6491d2e4c8101f37646048c400ed2c862586152604fdf4ee34c4ad5d88c0200c431706031804bc42550a94264b8f120dea63078e1a3361b2445142648ec70d19d13fd7c2a91ea620e117e2c39d0639b734b30873656173c8390506e6b6e6b05aa53225cad3009622313a34c88f9e396ed08cf992a54a14264682eca001432eb1af72ccc313837c1eeae2dae42e40582007d6254740aec8aa94a74c951e2d1200109f3a6fd288e162e50992223f72c440ececf2f004e1df1e5e5d5c1cdb050a710ee2c6e2be12c40978952ad4264b90182532e4470f1d3769ca7ce172654a13234276d04884ebbca9aa803b41e24fefae2e8eedc28407706460704638037000c065b13a25aa13a6498e141902b4a70e1c3564bc5c91c20489101f3a6ac440fc6e339b087c0b81a7012ead0204b2b7b0b7ae37036f025ead3a15aad325498d0e05e283678e9b3464c06cb91285c911213d6ec8487c762753a9c2cd44a01b9f5b1e073ab8340a0edc162015b815702bba4245cad3009522311200d09e3a6dd08ce162e54912223e6ecc688bb6fdb6b6add97688627084080f1c32c8b9a5b5556883d0d6a04daced4bc18036ac55a54069b2046911a2427ff6dc99f3260d992f58a83c4912800fb61d3660405b38756653516284880f1d32c4b1a95988c080edabeb009b0036ac55a6406dba24a91122417ff8d881c3c60c182d55a230415224488f1c345e20fe96a9545142d00fc45ddd5cdb1a9ad903066b636b605c6b05d68aad4e8de28489d2234483fae091e3064d982d57a4303122c4078e18882fdf6aa96189116a7e7b796a1ae6ded02a38502b0b533baa2500400dab32058ad325498b0af5b913a78d19305aa83c413204485a8eb4196988afcb42555128e8b7f7c14ec35c5b5a9ad983b23430ae34036903d2b0548dea74092d125aa2427ff4d48193660c172b509614f181036d06da8bd775ea43142504fd40dcd5cda1b1a55d98e0800c4d0c0d9960005ad6aa529e06a8f408d120407beab84933e60c8c96294b8e04d94123eadbe6f1ecf0c4f16cf0ef2cc4f1ec0387e3d91ce78989b92b7562f3bf3cca6c5f1e7d7914cad755477bd651b5e7e8f7bb43f5fabdee5067aa3bd4cd1ddafc9d43a3bd73a8ba760e75760e553b87ae9c4355cea1d036b31cba5c3914daf41baafd86b25cf51baafb8642a1ce764399ed86ea7643a15c6d37b4ddd075dd5075dd50bddcd0e6573754ab1bdab5eb7713eaee26b4d54de8aa7513fa7313aad7dc847ea86679ba6aa8dab786aaad766a0dd550a5866ae8aa7dd6d09e35b4e56ed650683443f53343bbfe19aabfcf50d76768d36768e7bbf70c65f3b267e86f33f4bfed9aa1eb9aa1ce3543ffced09643353347f9937d57fee46d4e57fe54377fea74f3e79a53fe54f7733fd7fcf773cdafdfcfbffd7e66bf9ffeedfbd9ee95efa766e6dfeea77e42f57e463bffe94ef7f3b7b92bf7f3d9e6aebfd7cf68d7cf9647955d3ff5fbfcfab9eea67efef5cdcfeff3b373373f9b7eb7f9d9e6a77eaef9f9d42f333fd9f74df3f3b739cdcfefbd5eb57f5fff6a667fdbacecefd7de7dbb76ddb7e5eeabaebce9beebd6cff66d5ffdfeddbe6ce7cbddbeedabae7cd9be7de765fb72b57d5fbda6eddbbe6f5e57dd95ec1b5d99af76a39f43fff71bfadb0dfd3addd01ffdad867efd5c35f4ebf5f7f7b7fdfd51edecef5f75dbbe3fb7ef7fbf56be3fda7ff3bffd7fedb26fffd1f5ed5fbffd3bd3b7fffea34d97f7efeefed9ddbf33ddfd6be5ee7fcdbb7fb5d53d9afb5ff533f7dff4b97f37f7cfccfda77bb9ccfd47f96fa1fcab3d43f9ff7ef797ff357ffebde75ffbcd7fe79fabb9edfcebd575f977f96f7eceffcaf9e75fbfcc967fddf2cff2cf5bede4ffeb75f3aff9ef7a5555fea359e59fa76956f2ff7de65faf7fffafeabebfbb7fb4dd7fffbfeedf35737fadeedffc4af66d7e28efcdaf9fbb37ff6f325fdefc7e37bf6e7edd75f3473bd74dcdeae6ffb9f99d6d6efe8fa8fff7fab7adfebfcd7f5df567b3fecd34ebbf11f3e7fcfffcf5f7f93b7dfedacddfd9e6ef5cf3ffad5ef35f77feccfcf5ea4cf377df1ef52cff2e1bf52b57b251cf6c37d4b31beaff7243fdd71aea7bd650cff60cf56e867a97cd50a87ffd4fa3fad95fdfdffe7acdecaf7fbdeeafd7aceeeeeba35dbbaff7d1b67d7dfbfaae59f6f57fbfbe67e6ebbbd6aafafa66fafa0c55befebf5eafd1efbf5f2edfef7fabd5f77bbd32996fff9ed93ab7eedf47995a3ff9f72be7dfeb967fdf4c33cbbf77a6fb7baebbfeded5dfb3fa7b67d6df47f3f76a9bbff77de7ef35337fbf5ce6efd977abf9fb55f7bedf165e276afdb6f0bae7b7858fba9ed9eeee7a35ebeefa68eeaeffdcf59cbbbef37573d7ffed7aeddcaeef5addaed7e96eba7e5db5eb55ad5dbf6667d6ae6fa1d9f56bde3fbb5ef7ecfae67fb9775feed5f6e57e7db9ff9dfb68efdcb79c7b66cbfdcabdba57eebbdeeaca7dcf2bf77fc97d56b977a6dcaf79a7dc779da6dcbb997b286ffd72b95befe6d66b676ebd33cdad6f7ece59af9d9cf57addacff3db3bee9dfd543f9ea3f5f7d9b997cf5ec5ebd56f7ea57ef6abd7a36af5e9957bfaeafd3ffbe9dbedd4ebfaedbe9b7d37bfdb3d3ebc4ed11b7d73fbf7ffbaefbf6cc767bbf6e1f5dd7ed9debf6bfd5ebf62d737bcdd4db6b757b67ba7db4e9f5ba5cbe4dcf7c7bd3bbecee4daf9f2e6ffacf79d36bdef4ce94377dd7cfddf4ee6e7addeea6ffcbdd6cfae57277ddf4ebaa9b5ed54daffb5fe6a687723537bdfb7eedf5fabff6adf69def56fb9edbcd6abfaeda3bb5f6aad63efa37ffbaa7fa67edb3f6cab7a7bed5baa7decd3df5ffe5a96ff9763b4fbdefdcfb9d7a9db67aa77ee5bc997acdea66ea75ab539f7add73eadb9cfa68f6fa99dfec75fa66bf9b9effeca34bbf7ff66a9bbdd76cf6fabf6bf67fcdbee5ec9abd9ad7ecd79dbd5e66efbd6ed5ecbd9afd9afbdba319dabebd7dbb5edfce7cbb56dfdeb552f9f63547d5f6e55d6bcf3bcb79d7dbc9795f72de79ffda99f2fefdabe4fdf3ccbb9a79effab9fb9adfbfbbd3efae57be3bb3dd5dddccdd7f93b9bb5e97bb6b75f766babb4e776fb952b9bb7277b6f9a3cdaef60cd51daaf7f3d9bebaffacfbfeba7bddf5aa64dfd4ebfeb37675efad76b9eebfd51daa5bddbbda6e5677dddb9d59dda3abee4bbd57dd7547ccabee5f77a6ee2df7ef5277f6a77a5deade55dd755fb552f7967bdd3b4fcc1d9a7bab9fb9eb9ebbbadddc9b699ba3eb9a7bbb735f77ee7cabb93bd3dc759a7bcb799ae6feb75299bbfefc6d91b8df167fbf2d5abebbfe3dbf2dd8f7b7f96df1b650379b7bd4d56b62e2ebfed76dfad7d5bebfaef6dcedaf1bfdbbbf6ed4755f77ddeeeb36d3f675dbed74d9d775d7d75dd7d765b65b555f577d3fef6ed7aee7dd8deacf59dedd9f6a16bcbb6cfe7bc9bbcbea55c9bbab137777dddfeeee467b667777b5babbfbdbaed3adeaee6abf737775ea76ad42b91bfd5d3fb9ebf29f3f77bfe76ecbf7efafcbdd957337da72576db9abd3bd7257afdced79e5eed7dc65357735b37d5797f9aeae337d57573355bdbad1bcbaabfb759b573727266eb799feedaefcfbed6a77bb5deb966fd7d96ef7f375bbebbadd966be67699dbd5a9deee76d3dda6dbe56ddeee9ad3eda34d57fbdc9b2effbce9ea9637ddafdd96fbaeddbfd9aedd9fea65d76ed7aeab5dbdba5cbbeb4e5bed46ff9a5bedb6da6d73ba57edfe36fbacdd9eb5fbdf366b57a759bbfa99ddd65d79fffb67b7f9b3ebb31bfd3dbb9ff79e5d67cfee6f75eed9eddacd6ed7cddf6677d56d76b3da66975db3abd3bc66b7efecaeaa9add9f6657b73c91f35633a388bc85f2fee46b7e72ad6eff5fdef57f79e75cfd2f6ff23637ddced7dceadd799b999dab9dabfc6f65e75c7beebadbe5ad7679746d396ff96eb96eb94e5bfe37cbd3edb2d195ebe75eb9baf26876f275739deee59277bd5cf2e59277aef2ae95fca7bccd3ae5fd4d53aee4babfa95772cddcab92ff54b350f2a8567267e6ff6db5ef6f9bbe2d94b7ab7ef2b6d59fb7bcd59eb7cddf79ab57957396b7da6fdeea55c95b9deef623ead64375bbe6fe5fddb650dd7475dbfe54af4cdd3275ab6add3ad3b68d7e9fdbb6dd4e37b79acdad7eeedc367f948d76fd7d945daeda47d9ef5f36ddfe6559ce7bd3bf2cfb6affb27a4dfdcb465757af2fdbeee5f2659be9cbeafde4ac7f39fb7296e57fbf2d3c6739ab3b67d7dc39db72ce367fcbd9aebf6f39cb76fe77cb5996e56c74d52a67f5ba959cd5fdfd889b5535e2661137ab9df9fbcd7abfd968d77eb37a4d73dfacfe6fbb59b5dd6cbad9cdb6dcb9ee56ddac5e5575b32acf5fb34dafd968ef9afdbb6b369a76cdbefbb79afdab66a32a5f35bb6655b3e9cf9ad56c9b350be56ad6ac4ecceccf2ce2ee3fb3cd9fd966fa33eb7d669d7ef79ed9af9d3db3badd3db3ed662a7b66f5ea66b6e5dbb799e5cc36b39a6d33bb6696cdac76e6766776dd99557766bf6e99994d3733b36a667dba7b748df617f15d9b69fbae3db7efba6a666632df35ea4cdf75cd51beea275f35b37df9aabe7c8d76fd3f5f5dce5766cbd7e8aa5bbea69bafebf74abeb699af6ae6abda73e25ed7fff7fafd5e5bbe5767bb5725bbff72af7ab957ed5b9dee35fabb56eeb5e7bdae2defd9e57af5ad5e9b9fd9ae2d67fdd6abcad4eb5fea55f7f7a77a5d66bd76ad66bd4613f3da7534af7fbf1e9ad7169a57685ef333afd1aeb66f5e9bcc37afedfe79edfae7d5e5dfcdab66e697d9e6d565f3aa9d798daa79ed5a55f3dab9322bf30ae5add399f2d6a997bb756add3a37743b5bfdff76eabf9dad6ea67f3bff767abf9d2c5799ed76aaed764675ab6ea7ba9dce743ba3dae9becdf46ba7abb5b3d5dac979cfcc363bbf7f5938db9745e7bb7d59e895d9be2c5cf665a1d3fdb2d04cf56511e52ca2baed2f67a19d9c45bb390b2567b16aa866115d57cdc2b759b3f02f5fb36691989859f4cca2e79799597ced4c338b68e7cfcdeabff5cf2bf75b6df3ea77cbfb6eb7fefbd96efedbfd7dbbd7357fdf6eddb7ebdbbdbf6eb36f77b4efb745bb7fab53deb6bbeb966d77b4bf2cdafdb75e73b3dd3fddebb2ddbfcd4bffaaedee9cabedd63f6b9f35cbd376b7bb99b65bfbf575d9cdeebd75fbb2ecd6bed52cbbb5f7ba5dd7bdee75dd7a55777419af2a19d2107201ce0112298b2c986905b6c30f1a32800e3c1882a94b19496deab432163a844a88010d993c271e29cc20895319348073220662f69cbe68313208a1075d9898f6624b854908a81e9df09e350cad3a82b8c1452a0f273f41801e4e5604e2dac3205121bf417fdcd482049700f854c2a425eccb9b084f08de83395d24f006a469c0e6f8e654a4b803706798765d59ac219f9106484c2cdd4422f1c940133f167a4a127588794006ae95818ae2615a7892125d15052987f747d1c183e2c70f1412fad29497b8cee04e9935a184a952e54519a2127f0cc4221196b8ebd0ca12a12867ac7cc88991045906f1431326db0d2d320ad7f89f36239790009c6170cc89ebd4e665421c4428eec664047ab04405101cbd11c7166da22e3cf16ad322a729d3152d20cb9d9c52417884e02a2568f829790390508326931506a60c58f080c12b4bb890191bfa5b583336e9e065c6d2921b788b0a384d750647dd79fde95271235110d601c34e9b405033ac2e0516e82974aacc9b01566c2a11a118c13d827ed1e19d09497128f581760885979d31a9baf4c0bde10003f18f8a8fae495041410ec93c8fb43eab469179d2e54f501c3360585f740c49e0ace8940af1c923589a79c132c23d6f984892a542801f290aa87140c82c7b50485721d413e5a70fa9b8c8812b3400e6e7254d0785310b4445497be0a6029206e315421f5102497da120e3c34f480cbeb532010a3df449c3095491341e42c8588b62027304c949c010949cd790c59457265635388259fa445786025661c913a6572ed4f818fca812a662530b266a87441ce8834ac49730b746b4929b1392e23ca2e25641235078040297068824ccd82b4b7e726af4602135d023f185a9300691256d25a61cdea4576202b820ae31f6c9f2451460601127679420b748a01d323ad4000e0affde7d9dfac2a59517a1ef45173e257b66169a7828124a4c0a2b6052362227307ab950f1113490330ae7ce8cfd469b26d94110c00fbb37aea517341560ea50fa94c909a22d75f8d4585d24bd2395d628973aa812a52537898074d527e01120e1a5117f8e04e93436c906571f9790088fa8c6ae455e2fd43b133706694c9331f0849ce6193a401f5976107ac9d06b63c7c8c59fe490559e0a27d6d8d526e508a03d35447d1df698fd41e8f12eb8f1f68092163e1f600025d012230a9ea7af628a4c6892751a7c2432b0c695a540a1ba9c8410b47329495ae5a8c1489f4d07e690a1e1adc950c007212838d0d8407a9418e8ab8713236a19aa24b02457a8a74c98928371000cbc12ac6a74c0544701a5be2cd0648b945b28d09ed83033478d8107608a6800f35a20f722428cac5358870332f9d0b26684eaa55a2b636b82eacf2536c7a1e484321f594a89e9f93324f5a2caa416844b108151e164072985830c537cc8ce5040747134667ab3b988f9591a0ef83a1588474f2306766a0a9e42beb84a0e84f291c6ca0f20ec4dc215543dd48448054e1c3ab331e43da6d0b409ad829c4d97da305d6fe2105c60b0aa0b51cfeecd4b954a22fe8e40d0cb0bd3b3088f94370b10d0006ae0c0a58614b963a1497333ccdafcdd39c0ea559b26650c1bacd9a4f0dd1dbed6459a46958a812bb1ec6008866351c5c7113869541d5a5282ec33e3dd54781a4003b40f9e8c89c1916b8359293a637c74da938a0fc2c4294c81582b059f9e648234a9111d3e1b07bc8ce243f2f113c03ac9c824a689db3c048a4e15ae29a5d41c232c05e5bc30d109514e1334634edc9850435717f827803a5e41702a085e21d640e031d28a11a22dcd4706dc54d5e81a30210a21ae3e5f1f1c24c75011b2aac9820e757e6cf875bda9c3fa3380965891225e7e5cd5c1254ab0d6aa8981a420e47bd7e5f6512f1c3700491246c358072e15801660ea520891019f17122c9d99f27389158cafc04f8d0ec3a6b0da54f6a6481d0e247cba188dfa2af30153ab1d9592686193eb220059000c7aa869e1d5ecd8389e86282f3bbe1a85b5a948a590f0279436851504146bdcfb22c1489d179b0c50b861079081513dcaeec050d111252defd1952974943e0442c19a3ece60e09350b434a24fcf99418c8a18d9105091c72d7392e66fa0bb9060efaeccd4ab4c544669a4c49a56668f60dc15c150a9c8f425859fa3639e566dc2d4b7404734b04e85300c545250884d191da08e2206607e801195bd48111b91e9899046ab90301f55e254f0835006c4670386650f543f521940af494426645591bde000605490064e0504cc4ce41111e9c8460e38a0a692d883ceb2018381c00ca80e3c0c55f2942117048193162a0fdd9fb3152e0f9ab94a5c5f06fa9498b3aa15e001ea82800b8768c4dc40ea32072e5ac9d196197987bafc01854c2246f866218fa6109eb09c1182010a5c8892baea9058dbf0087e5031fad3d0600c05169a2d128977624c0141aa48d8619b971713545a794a39253404a8b0fb223687eb915700714f16187e79db0263be01f336c6ead30850ab56bc7291a3f5a1480d46d22b89044614d464b4ed992bc12389e233a3cb439a4938e22829c5e2f932a14fc880e5022a710409f00ac583bd3a498726c5f088be16f8c9d2b5c4eb0c00aa992e99b459b42bcc214e09905d2aa2d8a8e3668d261d46c8f87c1cf7d69c512a2144288f104757d87c55a1f21a324264c197f75d3d581a3d46321aa71ce165d92b2462e14d0548783090a9da3f8e6030a0e5c702e891046d87e880a5b139e4288f861c875e18726941c743d3e8434f974a51d2285dadc4485000f4a4539997ff814e4914750023a5481c80b1c705d81bb3417a12c5ca747051e1a84a12434a63ab360930ac02118290a73131c8a2cf330c9476280941d5bb46c0c8b4274f85379f8e7deb58e6216038457bc0092054996e50f65e719d8c8d494cd1b5c6c9ccaa43619556948d12e37542cf5e961384a7d41e1d07a85489cea83c3d29749cf43c14f941a641a329ad961ad60eaff8b06880a644346230fa423d392c64bac588822ce4494f11a4bae144a53ea39a52ae2c71c193c0da7101b24d02acd312c0a9570c1c041a11e16d4c6c001662ac3a708ae30a899318993074424ad2b103b9e74f0fb736e3571f4eab227099595747ed8601154831f2c041e9d134c60604f2088c350409068b0c2833c688cb2b137a3a6a25a7400b47765284e885e9d0b520c19d18ea9229a4c660f571604de0052b620ce0432764eba0d1044c9f4915b09725362953f4743684007d49e09992b8eb06853266a4a0d0a3c5caa31b2672ccc06402ae701a74c38360d1145540292b187f39d380c24b01a5850b33805b440031eefa84c74420182280b01ad241eb77c0988ccc2153617a1029a1955922850dc6f8ab14a29d48520ecfc0310351468f0a55726362974ef519c490420ac6b82c350b55278595385dd694ca603574907212a26cf9609505334640852c7c4d19c3a08672c710303578857b815a14b468863155a06872129aed27dde59ea7afc6051d42323110d44453a21745c444973a8461a1f4e0c31e27875f701cd59c39b3d57e9581a3d500c8a71d03c44408dc236583090c527e0cc0c8d00cb648aa2e2172f0820b054c6a0d8c34d67688296a51c9d50d2c4c1d905f48a5692bbeadf161e1ac42d6102363887851454fcc24d1b2f2480a616a0617a84002fa04283256e9d0a44f805e61ca10cffce850a2d22191ba057358a69f9eb7421c89a474d589ca459a41e62c35e1edcb8d1d0643d69c58ea3066848ade3393518a61b2ec8f064374c328e8c60c16c71d1db01846628c31c618638c31c6c62e5f3feaac5ee21028914ac4db0d2553c048345223050291a73e61e4a0605d81c3a7ec8260865026fe688ad1640b470d05692f8c19905bcf4449324292947c8b3d1809bef6281260284805486d039001f635693482ecc59f1e8f3165be5e5549d59c554877fd1903845081024f867818307033c54e832fbb32505d8a141ae0549a2b589c7ce0282c18a4d743d01d95de2b42b804b8a1d3a24b09491550e04c903d3aa22cb4e052e9f06a93a40e00204a512e0628b483030f9a6981051807f6dc3661c6287d3983c50889495caa8250f872e9ed7301f111d94176068c1706b6314b0e8d52fe60413aa3090225b1311d31ca5ea901dbc3778555542f8c2071190143284ea10440a4983df130e044c0895cb34807cf43886d809b2128962c06f088651a6126620d9e37213aec39320410901a2eb6b6358106c9e2fc9a305a25b6d17043d6c968e29941c09b94f5e445a2380e6688f141ba131cb52217d9c86b94c0d300901a48013366020562ac2bc2d7d1c8c54ae1d14e02e72024676e083440fa6ce282254dd819a3803babd2fc50a1b26db8740450653089700734f10aff6fea8248a1b302e3d8f7f40ae1258bd662ea433442042c80c29285983c291cc4e1e896088c4513548381d9001a795fee0449840195e945f3a818155d01e4c3a94914049e41a84f049f4b604312586995854ea1123953044482f2264ad937fad57591e91403d41e3d25785801c6a60ff7d205058638218c3f862fb422806581e96b70a6d01e1f67651dd2a0d84223ab632212b38a5e9b4ea7220cb1c48607b14b55d859073c08decfe6b948080732035f8850e4004f0d213468002411b7049412907dddb92301ee0520476ae28c0c424d067505c9d044ce6e4728e32aac8b539a927a85e25363abab0e1ba91514af3e8d78b859d0d63dc841f8b667a26eabc986425e2e7445b8041740a9485f10e1814003803c114dbcda0674508d2aa1a82f8d97bce7b582c6d89e2c65d2aca92998222149b4c909340fb8e00c101418a36cdb4913c30b56d81801909d7c6831cbacd881b3b4a2106bc5a31063153add9961094129bc156738cd4173c4119709234d5c2115d68458c0562695b18c0b92a7a2c34746142627535c254f115ef112f381aa0d12a430536cf081b105eeccef44034fa6382441d48447a53765c71ad00cea58ca04263897e6c4a5996a3b63ebf1242e4c94980c464a0b1b6ccac04953d729cf4603b51489637a402a6d3904a311348f5839c258e207902d01668046ebab0a59858e30159883ba03cc222b823b36888a9ac9c4e077f8abe3b288485f93855f98b0070f8e03b4b0e5e8a18789a07cd7028d7b1182f1215497092d71ce8d68000810f92cea52f626c71fe59ca21696929c1274a81511422392df4145aa03935a0c559372ac483c04a6a10bf0bbd99156ad58d3848229311f6506bcac10d974c3045d5c132bd4a8289e8c133ae560e4d696c68e120b4b6e0eafd497182d9988bc7aa5cf24d2b0c321605014598a420fd0c878c5e1812207442e81d094d6c5a6588a8c82573ade3c6656a97112a5e2abc28d510c0278b5053150c1b02a531aa90564b0a85d9a7b85a76540013d8993e8c674fd6571f48952941e7b5b02def0fd51c37855212280b3918e95d107bd550a7eb368c18167083c85b6e819c116e9d0833b8de0c2b4c7939bbcbd3f06fc321971848d087a3970c3c249224507bf0754d8203bac618eb1b8804380853280b98b88e612404c73b86aa07083b0488cb1ce80020786848628425209f58ad3a0145f7efa080d90260f9c02b13e606464da2a43262383b022614d562057833e05a18a42420572e2074f9200a67c2485a460a73cef09cfc62b5475883c0689ad656a663a32640043ea2b537c87bc786800e3818d076c4a45d88bc16154a4038584473070444a995114f7c51326542b006890842da163ca3f5070c3048b29a67410b09281811c37330a3405a0f99d10bf821f04218e7349401ea29c34d08cfc762c91b1c32f4c4005d50bc7a3c021f08185389058281900400606221fc7500a267039c311e5a932da0914040b1a4ecf2d8816c6e84b3ec8c09ec50ea866312278084e459c43344a658237fc2ac118146df6a173466d0e430ae360db183f405436499261624c9d0d088bbe06e0a0824a0d115814415a2bfb41899320b22a42e00c3c7834640821ab08a0c83269755dc2406342a93e6327e25424f9327615bf0cf34872cbd445025587142b46488ee02d38b546919f48084c9c9112a5c1f882ce4857a2a10ac903030add8881691f40ac3cf152c4a3ad8282026c97062a36786a81c0ce82bf4d31c818ff10f0c2f416840b82116f5d5da3d4d444c891f045cc0c4516f402e778117255ab18885113239ba2e02f62b618f36220d59a4b29e820a57b0403bbb0fab8bae87881544b65a50f1415868e21a408421eda28c432a042e00a47a9bdb0b23dadb103c531907a98ea8a41a1375911a189072e1035fe2ea051c4c753a22c53c60e493a8034a19c64caca903a2e4106f1c83f96f889f1364dccf499e9f36ac3b169cda738541af4e152634a767078420685a51667981e47482188586964a6d19c10442966787d68c21095c525384e3a7e2843a8c7cd8883080d0e54b24144c92225618767891da266ecb1998010ddab1d51146858e0a729624da5b03b638e3d7158e02964e0419c1a2bb4a8601098a4c20b350f883afe6ce24a5381df380a4ab4ef890fe760a432129e281ac5034c4c0eb0295a9e3e580883f4690bd0759639c9f284c707334466a28069c263e5470e238d4c74de3e8b2608a2d48a7233019121b007ca51c70d82c4e0200b11c6b906440f99a655611225b8d1084baa0285075663e88c46477d98081c0960723566c2c01b4f77be92189972d8a7d04f6e25e593df17164fb2bae81e35aed0e224c22070e141893bc72e2c2b8323944649bc0491c0a614d4c5d91717001294e408e04d923161ccc80860e2d40223033cb9d232e7a5159431520d7a8879bb34e0386268066165504350a200d080d9f3f28145159a512b88091070245063c504a3314f43d6a8624094f8e46519b8fce306720930e61f793a4b72a44f9c51333a2cddbc0a64ae435bd2bc71b1210ca843401972c6f85291383028c1cba204283821aa51c470b90b04a06026c98f017aa97c9f0d9400217f3ce0d362ca1b5e00859c2038099cd0110b7301468202677cfc88dab2d3a9089e282e042ed22ae041e14a0e185e13a40b16502497a254644e8972e59621692862e2c14bcc8b0bb1c1994f700e44304105101f3ad1e0c420120a559c5f84a0b9052a6119087554f21d25c203812ffa622900d08c2cd0b01845bcfc4e79699084918c1d359283061940896342e54c120a300819b2a0b2656bcbf1c1a4e495313110c1547141e5ca962a3dc03631d112a8ecd1d722be133efe9007d6b24b3404b32c91703204528bb4078a14e8308ae12a242910091a8b7c607123409e2d67c052780d58846761d288b421ab010c461e94b98d89e02a548a89a5c4371d09004865c1c80154abe9467446a0f5d050d3ce2a365f8138f5b8222189a4228828811aa6e8b690d9c0f4c5af6da5284fac5004a5327b04bb08b97e466cadc8c247c821212da00a435f200ebcd21fd08c78e3e6c76dafd2bbb72091200e1b94a497ce66c4e940a6a248932e660d0a3a1a6ce08c04417774b17131c56b8e724c1353020384ec1c61f16536c663015b1b1575928382e479d9d86952265fe07ae535b684548d541ab61861230990ac8dd78645b9438b2a697c144a35c0122b10348d0519926a489003575a3da8548ce0ac12d792b126aa4ae4c1a4eb9a6c9831408302649c7c87ca532a491b8064254816107114fb8421803416d49808b2764744cb014788b8e06cb00a4c2c2387ea91591302030a6441de555ac5143bdc3ae56506ab4f080480628250e83a405203c067e4206b03d9102b0db4e0d033080c0b81c0ae01eefe5431f3e7b847f0490d3079ee1412c1b6474e8e1138ac8d961b944e44d3e895b9d2b096c55207069a8a6021630b93302601461f0d831e0d390636c932084a18b0b5c2368a80e285b1300a7744f00838d188151be2431e1ba52431603bc6c9e9086524c30e2789a2ea2813c6475eb0269931c5ea0a9c12001190c2c2c0901466a150beb50154830d0f06871e9595b9e0444714dd1c4d7420ec0bcb1f47ae18599f0a91baa66d0da183364930473ac0060842d557874906b30b17b34c65860620ebb3157708241bda21316246292104842e5794ec589548c168872b32506f0afd08bf623831ba68bfd15967e58cd317079bc818e0818d85e802138000c11c85442c965d4506f0e4b621c0a47a2ae08561ba9be175ca0a8b033c1c9960c5a64d1092836372c10be486102f83625c648293e9d0008599bacc10bba23e663cf5b5808ec831e250282f7f48c8900d54cc22fd114002a64b7c5fc604f971fb7e21cc98c00ac133244889b8e8c89052418c273169a400c2f1e4c2264cc8510d76b439b290c2128f2c0a5acf4b92c6d430b1e060e49362b0e94ecc1d23529670a9004585e9664f58008204c0b87851e910f9ae7db0baac5aa186829fb1b11465886245f2b4a2f3a52a6ec9162729655484430d4e455bb5395153e7159cb44c7bd43c1938aaf2b281c3945189320e391a01e30da93c61a90afb02f5704d34f063e48a23b416a91ac87d7180c71ee0cc386b020d2202821e6bf879e31381c21d29880c3930d2874681b054861dab2f6c690820d86396ca55ee63f0c2d0e822518c087d4664f888305249392268e304c2f43bf4ca78a7421f3f375a60832c7c70e73cf80107d1b3bb7ae0dc2abbf3131d08e554f3046450c19b2e5b788c4d360003be26b52a1536c8e3500f4a4ec0eef0f4f8903579d3576c2f7c684e6c94190d8db1aa42c70b20535a6086188a558c17ec0c7174c984172c13748234b141e5c3179a3367bc0c41816189716bbb537b242253d30727d27022a343c6c115a1565f8274c179530a91cc2822a946647985f7e847f42b8ded8720897942b174bd421e524bb280cd80403f923831e22504498c4506dabce81af44023cda3398d8044e128d0034122cd6b0be1240987baa0984468018c99b0105d70f4c2240c5f824c4f12cc9d8af4e905e3e22422d217213c46282b5062c2e9c816352f0a2b12251ae5bcc2a60c198d2c6d8e89632de2842858fb20c4cc901295ae2d894c70e5a023b6639c89451979f220a2008539a4961ea58ea3340d12050e70e8899f3102c408090161468008980031adf079e0e008041784253f066dc97149c278c27401a1890f792603d4d6871b0288754085028958254862725138095032a1802191b8ee42ca0ab0063874601ab041edc7a9f78682b11def9363990f4a4f70a4666c4be7e11ed9ab112625f02c867b648203c14017fcb0694289819e651a2807d8f02d5ae8988a33c01da3635d87363a7948e1e04320ba482ed49e3d61078670f0d1505934f8480478c793860c0c1498f9032cd176190003483db5fb8430ee1134a6885c1e9f2c7d1d5e8d51699000ec459e235377bc5a8d4812d92029041642652808bdfe13c58b2bcd3341963c01cc6134e1f5a7b927151aa6dc229acc0a1cfcfa84a2031d56d068c6f0075133ebd200645ddab846b53952b866875ddf5d514a952e4daf422821514758a85405417b7779cb2f1da76c038b1f5e7688f25a288a083063c1abb44a41b6d41075515370a7437b40ea9201c32f519dba4b7c5a6d46cc1e68fc78414a41250829048730dcd809b46355190b0addfab48de152f3e442a9e5203d6fa0747dcd58f10a0c17afcc103dc42b7bdaf04a917cc66142828b8e4fa11ac14a86228c95a96084cfd034b8f7a21396e62302675c6152a5b823a6c8ffe209b903abc71d374846a7ca9c224bd3a5682fe182d5097a61cc584a0a294a950efdd9c1c81a4d43a5b84428bab12401df0ab568c6814134708c215704b21427b0409e7644926b4bd2a543b1a70d486a138044f72c3591009c3044d5c0508443aa40ad2172b2828e1881b553a68e959208487188418e396d30fc5d81c34455982337794819c052a15b00a08a90343b350dbc2ea40a95400899206678fce8a9084d38b2195ec46d110bb4644d8053791a412811a6d703459ee0219e0c1806de3585ced2189cf022caab39376898c24fb0028853188ca8bc80f565086f6d96881995ea4cd50d303488ca926b562c4d33cad64e2162905066e547a526a63c593a1901061c2188d69823518239431a65196f5f80ec4870ba02562188b145a963141216198d415d9880c8448d4992a09728413827a5f2e1cb6e8e110c8cab0d00542e6eee9107e79f01c4be9e308153dc23b155cce37508cf9cd490cc03167b6301970f796a18f121b67023d7d52559a91309e1d4348a87823e20bca87c790d502604ee89004b629c8270c2181958d024554715b5f4a290e5a8f0254ad79f2e3b060dc0244dfa92b628a468b5e14c7a11d1581c2d4251c28d9f5ea03c563c641a2b1587eb08a0a8b44d9951710d90422597a2242c540426512158566192202a42285e0a5ae591ca52f796a5921fcb646af53026c80a09dba0033406391222a9ca1b00845c1f8623480fb20c826021da4900be810449e40909c24d23ee384b853541ccb8d2460c8d16172f5826c4e111b5a28689c34016b8bae868ea8209d1240d852ebaa08d68b8407eb95d2194f467511fd6840002149aa2486c819c205e98d88d88a127468408bd1e7f0d9462c814ca1974c5d1a2462b188c79a1747c02863f13d900808b963d6c0809f292200cc79881c12055f61c096465a6e306a22e06580e839891e16ba32a4b1bb70196070e1d29b02ab148012ff5428b00b805243d02c042ade25c018810c5a850810e410ad90050e629318421350c3e15c9e347d0984e5a7818cf1c68ed8c3a9268e32652167fe34108a6fcebf1544b74c18297b0a201ac2e5dcae828b1c73680e04a153228fea1f375c4980728c2198943496b083b9dc3257e0cbe0e617d9163b1668c8217051d559c2957c87cd408c3e181793826c9f10fcda71e09ba10b1fd098a3874d2ba5abb089140b3f7c5d7aa4a050673757ac001e0ebc326088c1644aa33204a021e522cbb8351a22b9c0875ad1328400b9d94b0a3be3c984c3345af3c6a6348a0d9684bc128b2698edd14ad0573ab9e7041ac14824ca35358c61421e0a1abf8e4ae878f2060c2f019d393b6ca431fafbc1b01586f9036007d4f5b859135f870dae1211d9d77c07c95c99c66075effedd735e31d2673520b49c3909bee3c4563b63bcdfd6fbd6db561bcc586f1d69a1ac65b69186fa161bc75b66501e32d338cb72a60bc45618284321a6418d72531de8a80f116048cb71e60bce500e3ad24c65b0d30de6280f156d916d982b12db130308cf180ad2f8cf1d671cbb8d5b5c5b5a5e0d45602045b07b60c6c1548b54580d5d6802d008c44f9102fc1d891a8bf18dc6ea2ae0eee12893adfe0ee90a8bf0dee0a893a59540f323ab891883f10558c44e4c35f655c886f8808a02ad8a26ae0d6e0dad8b60460bcb585318e7100898886480131893156dbeda4dbd2da2a6e656d616de157ae5ab15aa52a15aa53a64a911a55a6f5267affa9b70f769b9343857c0d7c3318638cf52627c7c6e9ff79549130c658da997f5c24afc577c002eef824decdcd10a8be034e87d40dd5b836393d7dae3768a1a709c618cb90ab6c18e2dcb4705b8070414d797b13e34a71cfb6fa5c22ae0decb55ecac1b9b159e185f88badbcb9373736253c02c6980246b6ab5a2b5b6e74746e6e6c3fda1410fc6c9db51b30c62d8fbe4ac3761bd2d175fed6e6c636837dc1a260b5b4f858bfb6c6c6f6572b6b07ad076b9239b82628e78e2229a41392dae636b635b614ce39168936219d6a7cd96eb7b5353640163b58ac4972c380812c6f27daffd0e6d33637b72334f5d8d90cd635a76f7167cd3537701892482620262256dc1b063224b30233811ac339b739b201cbe41adb1c2b2d4743d17a45049a4b37649b9303a56652f9a8582a224338b94a2a19c6b80c235357a99620fcd3d175fe0697282d912a61a41d7e9ba186726e717e945fc98531d6c2522e0de3e6e4643d7950c3028ccc5c30c6be4dce8c9bb8b838382d87eae181b343a58e837362c7b0c403433038ee6d8821d70a2bc815aa7034bb86fc1bbadd58a161c5980a3b590456b0ada0b002825639bbd4dd50eba5d77ac9d686a8e2858a08586b6c706b8a46296e7cc21863c161384c1101c52514431ca540a610904ad572726f8328e690274c9d908231c658282c205120d9ddead550fb9c1a7edf39d4b36f9b53c3b837bd131d4e3c30e127cb090c27d24e5c607ad6aded4d8389d5c4801f2656c461705b2ba1a5445b220c638cb190259094108231e6c2c81232d69c1a1a7ecf5d39b708c8423d852bc6186315d281930b2bd422f4220787244c22090f2c388024c189042124891718638c8524f128cead8dae52223b3f8379828730ee430a222205f93052f00d7f8dc911d40a74830c2481b1908375584ece3014c65aa030c63158890acc840c6c840c3c840c0c845dbfe3e846c4c9d36e7410d00da016a00fe4df21d20f0dc65f7bff6908d28f02365c73d7f2a4d529ebab4f0392cf08728f0fa9f78604110573daa469804c982e59c2186bb5b911d2aa4409bf059a24492b92d62148186b09f2f3c851238cb5046064b844e60941e6bd48d22d529408d121010c152234485020406abb45b8b9d961b04bd3e2b3474f1e3c5a6ff48e9d3a8874e6782d3971e00c40d6fdc1588b4917367b1bc0361c78e3a68daac5668d86a5061468ce982983b116190c4430e46053448cb55ead315a4f315a62c280f9e2a50b97b737b854c8b8191863382c57ac54a132454a1455afab1614ad274e9a6095c9123aba36b7a79612ad245a3f2a3898eae76fb71ee1babe7e705a3fe030d6f2e1a6d583c78e57abc50601342860e8c3240babcd8c32890608a0430549095174824376407072470efa6880bae16ed431ebcdabd5d99f39715c9a657e50000d3a32e1122a539900bd14e744e149c258abd3d1bd69e9d0caa18543eb86960dad1a5a34b466c03de9e8b46468c5a0a37bd382a1f542cb8556a256540b510baaf5747bd2d121d1da906814b0d6abf58d480b0830d6f25a5dab85f7704f3abab7271d9d1bdcdb938ece0deeeda9eed1d1b93d55ccc9c5c1bdb9b56d50c196cc804243daed36a87b1bf8928e6e43abf936b49a4fb3d92fb75e5d77e1060da9267c97aaf7762ae67ecf805195dffd9e5d752faaf2bbb936b677ee55b1d616d54e756f50f7dadc5e156fea367c8b7b37486083f5df1daa66dd956f716fdbd3d0bb1e29e10f29c10e2961cd2c495721021b8cf1dc9b6a42bf5d3bbfddcc6cb766736bb8baec464258e3fa4128c7434210e07a9c95857cb0438f03f2c15103c6b80f83403aa081311efc5a10991485f18c17d845b2c2cfdf37180209069b537d68665841b35cf0f0a9bb8b5480550059a60649a6862c89910b1260ad382d38ad372d37e458581429e60763ec22c5de9061a43046545ba4971724321312d98731b36dfaace7ff8e836be3d041ad368cb5d830d65ac31863a961ac958686113dac39e57c7b827ffb9604f763f7f4cfed5e57f39d9aef7cf3f77d67a7e63bbde62fa8fbfbdf0feb9af1a27f0fc002b672d7b97b808383838383837b7b7b7b7b7b7b7b7b7b737373737373737373736b6b6b6b6b6b6b6b6b6b636363636363636363635b6b5b6b5b6b5b6b5b6b5b6b5b6b5b6b5b6b5b6bc3800103060c183060c080616e6e6e6e6e6e6e6e6e4e4e4e4e4e4e4e4e4e4e2e2e2e2e2e2e2e2e2e2e0e0e0e0e0e0e0e0e0e0eeeedededededededededcdcdcdcdcdcdcdcdcdcdadadadadadadadadadad8d8d8d8d8d8d8d8d6d6d6d6d6d6d6d6d6d6d8d0d03060c183060c080010386b9b9b9b9b9b9b9b9b939393939393939393939b9b8b8b8b8b8b8b8b8b838383838383838383838b8b7b7b7b7b7b7b7b7b737373737373737373737b7b6b6b6b6b6b6b6b6b6363636363636363636b635360c737271706f6e6d6c7d6bfe9db3ec9e09e40016186375cd5a5077401523b75260e49619466e7561a416278cd48283915a433052cb89915a2030524b024616556164f1104616a56064f189914540ec2601a7e10817701c322b094666cdc0c8ac6618466681c0c82c328cc4ba849158713012eb0a4662e1c048ac1523b1e030120b8991f8d5050a18e33131073ebab67f5ae57d7af7c1ecd5d483a087b4e6a067fd6ea65dabbc4d6aaf5b6d97a66a34fda34abbb4e667f5df7669eeab0355dd42b3eb936b6eed5a3bbf33ebf7dfab545365f61b516ff5e7e66fdfa4eef983f74be63b2d338cb52a60ac45416b82de7d70cd2a3c9cd81334ccf390f787e7e7c130f02f30d083a1073e12797f7d8625ecfab257534d47a7f23d3730f3a0865413cebd1b58fdf7987c55f774bb99ad07575e481d5db938b64a91caf7343838438f971c5905beb13d37da1b1b61f2b8ca489954667c4f534b9534ab8057dd0f18c058ab8016012da8c89486de6737b79bdd9d7d5bcdfa0c4d723d8cb5f2cf79dec93724cf34e49fd55308bcebf3cf79104c6d66bbf977a35d377fba574196f70fd14b968ea5a6605cac44e94fb35c50337a4b4b4b537b6e9222310a51a422245c7ce408e36223466d6eaa73cdd0e4dfcb6452a7b92793edcedf99d764542b79523f7757932cff9f2b45013a8af263969696562189b33c04a6088504e3e2a1232827388c9a9a1a90232807bbbf866f71efe7abe0a71dd8d07573f79ed6e03f4f737f2be7dad80c7dd7eeaa9b6f27311880438cb1097cec8401e33409cc7637bf61d72e89016c38fd618ce9e8929d2f396d3174bd218c8b8508618c19609c05e6b8a9a96548f2330ac7263d52647871d1408397ef26e3a9c7121f0843cc64dcd18d686b2862230381850595b4840c898168901299a0be2806152e7f213aa09814837524820b0ea01843ae92861df87512a348d60ac3925362600032a22785d90f3e184aa002c438a82b00232de294339624030c35402fcb21a150bd488580508d2795e7859d025df0d4b130f762c8001ece4083aa5e98c872f7214c87a917117000829228c0d00528a78131abe6f85cb0c98364e302900f2e70142f65f1a823e40230d02638ba248c5c8c5df2e0e0948915899670682d38032123718c5cdc0b08ab4e74e1a3c7e1dc179ef88140861968853f12bba4b05af6f0e2461bbde529004dec8b6219122543113d75d18e804f4d8b14b6a886494719dfad46148005777e5298c24224f402ce0db18289f824801d65b8ac5d41646ea1331b1ca506b1ad931e075c7452415ded7578c3042505540fdd923a9c62888106a0443a79d336016a581c445b65c3855608f4f4a1e6e4c47394a20b547ec0f07ac699038945626ef3e4c1b4e4498f9fda7350904109291b7e3c937731bef0b93af46a2ab69a84e413ea3513c8951f74809c7706166da008cb7c4354310409308c81d7ebcf910c1f47c39774604c1b9d57e9ef028286a6414aa0fc971020123f31ecdbbd2d1c99d283fc063e912129c492c31f2a41a94b3450cb4f8984e6419e2fc8af4cde68f5411a3e6ed29a2014cf3f3ecb0f887f6168a0ff09e162932ab62e3d49bb878711523cba320e0053f04c19ea68ae7a9328a1045b9c7245e74b0c48a31675dade1e2522a2d422081a36ad889870b62851448dcd0e49d80282160973b0a32ef793e74dde8c0ce0ae319be05587cba07b23b929cfc90e3c17d015abe366869e143278252748feb05f7eb818181e5a4430d6f144e58033026c18e11e16d059703a7972ae49463cb98171d632d27200435586d45e718229c92a1a32da16210221b1622e69337061e086d685b4021c8ca1d383ce017690cb3a19fc6a5384d22576b9a5cb9ebbbf4d6c9b0342ba261ec2da2a0bc210546ae4d63c78d62243d83099cb3368556146459d20076aac14eac488335007e71c95d56705572d38e138779090c1d6e66ce314842a21558170cdc922d326ac391c400ab028f3e90d4dceca0016322c25f54c08f02cf6582037983b3d840776a4411f4d29798736972424047fe842ed8f290c1122e589dd414d242f5efcc2ec027398895f428c690ac0c4b1ea8d00279a531a4051bacad36b3a9b709b069cf13182a889b5a350e100e891e92701835059226c62226941e604a7321ecc4c2a481808210c31cfd8c0b0b4959763696a55124d2c9ecc2de92821796a2326d512088b57950c69085916eef083860ca003cb07850ea11262a04e7b6a00e7440cc4acd588692fb65499b40d1037b848e5e1a4fd1215f21bf4481df6e54d8427044fa5f4e654a4b803716a182426966e2211aa510fc8c0b532886a9eca750677caac1925551489b0c45d0757a99532881f9a30db52574800ce3038e6a47432023d58a21228dd6ad322a729d315a5206593070c5e59c28694da8ca52537f016255b5ea5a7d0a9326f07321e3abc3321290e65227ae0de708081985390ca13e81892c059d5391405f7bc612249d6e19b431d7e5ed274501873187885d047944052876502147ae893a693212647909c040c43199601b3f489ae0c05c3183faa84a9d8d40df5dc1ad14a6e5018ae80a447e20b53a18c155b0470415c63f4b3e26f91403b64746845871504a4b0022665a30a43330ae7ce8cbd2aa42cbda0a9006347058bba487a472ab12ade0a55e03e2e21113e9a820fa4314dc64014298ec8d06b63c7e8458adc26e508a0bdb51417fa50982aa6c884265987628e931082762e2541f1030d6f4d86023f5010a2787082d322e5160a342827d2782d907b1121c6891a6d27fa4e8051e16407298583894926c09840348137c74402b812894a5429c14b607096d0fa5428e847e1924885ea8cc2354255847742ac81c063c415211142144642097e5cd5c1254a402294db47bd70e440a20d891c819f1a1d8651213182d1a8af321f329118bcd428ac4d452ac52099bd2f128cd4813108631044d3c7190c7c12068d6c08a8c8e332107464ea55262a930a66f913f407043780f9014654fe2238204260a1b2c028813bf02d108fd89338c2889e1187ec080b28b0d06c917001580a500e600f434012800e96fc6dfa43f3f547e38fefcf6f929f97037ed03abf3bd50f411fa23e2a7d6ddfdc5f71000ea94af515fbd6b1cc44f80295bd575c270bf894f0a57c6a225289b0731431648b8813762222000a012a049b1038428c5890e04e0c9549883d4b7e6f4c8abd177b1ff6f8f41a45f5b064bd8e49afee8a1e002008818002a2490984db07571ff47c0800ec83e107334d1e487990e38147968741380f491f16ce2a6411c9d39477266f469e883c3c49785df09e78767807ee0edd51b963c78c50c118dfc9e93d33618cefb2a4182631c6767ffe68bb24886ed8a54641766937667440c5a2439d1d1d8474e860a243040ea0700afc00e3b72fdff62bdfa5565365c6a070242c08cbc162b09421780676f12106c41df01a4e622e8cb1029c0023c007b0015c0013c00330005800dec25ab888b33016c659cd2cc22c025945ac57184bd518c6585fea30c6ba8225859198ac7b9602035959ab4e1d17b1f23dad5d546991218cf1e1719119bc08c971d10e8cb11bfd8bd445270217f1618ccd92746749bab30a8bcc162593c99f932d7f7d66599e263fa26e3275cb57b365bbd1d42e243b4ffa65bfe4e7cc0ac9a44f46b5d3ec03dbdada9b026d6d6d6ded4d5121c96cf37bf800868ab343bac364fbfd5ef5ba9bd0e4873f0f52b6e460b3b6425469d8733335f43b6db9eaa38006871a1d0f150e2a0ac2b81808e322a03f18630278898f02c8c07c2fdb8db66c779bdbbb968631c66786f8066c3a16ea83d537b6b6b4b5343634ad76fddbbc3bfbb6dacd2c54b7ef6edf42793859a8023e4ca685061c32dbcd09637c98ec9aa97fbb09313a1222747818cdbde78c71310fc6453c1817ef600229f09110068c315c5a1b9a5ebff2f5581817dfa088f447ec18c341b4810d455d56d9bd7136d96afeb8b0616d302241a08c2f976a0cbaf2578aceb02c2e94867654776504d585364c30386ef0c9928105814bcc516ef60cc0bc75fadd6ed647b508410f827d430635713f71143409fb9ed6fcd9558bfec064f36737e90663ac45478771b14d2043c7401630c610fa11907bfc93081ffd7c7cecc308a7ad859929e0c709ef4520a224b6f6d08a0dae639d0c9dd049faa2cd2055a20fb0b9a801943b36dee4d9daa10748508e8b328b4c89891814c7b66ab1001878ba213173810aa921cb0a20a08a3d56021752203a5053c5b586c3d206134e5a37861e88391cfba1470c938629ad52a0c150d549ab6f39445207a49a567eeade1b57cac2382b81086860ae005a2502a473a51720a2b2f11131598ee5508e2a4324c9800ba4e4101afc61a1ce6beecf2cc5472c44a88299800b81362a57aa449d280d39dcd25529b03b98a244b3c00cc5d71c26ac0436046802840ba455e8c5264c9eaa40e68640736dfc0a0e715eba941204e9b1e3d4c6e1f048a94aaf56805a2048038d0e3b3ac02bfce993a13e7dc6be3aac31976cf278d24c4cfce0a2818a8b2e3fa3706cd2132594264992ea065bf9ed2173d1408397ef46d6a588b5aa4d5aa5ffa5c7121f08432a507293c56475244e990523dd88b68622367f7b9ae448b9bc0ab1a3ccc2824a5a4286c8d0820ad1d6239d87006c901299a0aee8159b432f5a6334394164e4f217a2030a494bf22550c5393b6044cb1c89e08203c81252342016c509822341c02a69d881df26579c0c90c4f70211974447b25618969c0a93460c00635592183f1d1918d193c2ec079f09312ba7d6089bc21a84410588715047209224c03ba0ca7644123b1671ca194b9261ac6f91dca810852e253600f4b21c120a95852fb3510c1e354064410c01a11a4f0acf8eae36152cc59001691059a00b9e3a16e6d645ac9269942cf9f0b806f070061a4c052accdad85974931b2796e5ee43980e537d96c4ea24a6e872e90d1207202889025658490322d091af4f9bf870390d8c593527024d2a011cb820c6f924c0581e241b1780780815c4d58e80bcbaf4c0ab78298b47dda0200680300881e8d5263fae409be0e8922c4a44a06e8c00d1253c0c8c5df2e0e0948915135eb51a9f2a94d262f4c2a1b5e00c440c1c167e34e3089e5aa3a54b2eee058455cb91a84b2e51902a0b2ef0d1e370ee4b0bc7939eb70a6242b21a7c11c83003add0471f5118ea0882b8d284af4b0aab650f2ffc108abc15ac375ed491bde529004de4eb71215002194800d0d2be8644c950444f5d06420e1bfc706dbd816344c0a7a645ca1aabbc57da3d3048554236e928e3bbd108608a122a7c92fe003801b6e0ce4f0a53587798bef855c1d4573de30b3837c40a66734d61275b5381504a59003bca7059bbf251c421533567510437b02d746683a3d20cd9d362f434410e50c7d8498f032e3aa93ad0a59123e505579b2c067b1dde304141b1e4d40f26f30c13912761744bea708a11068c61151c9c2070fa318e4aa493376d132488fd4121b4016188daa03888b6ca869b01051924a006119a31252cd0d3879a13137bbe2a20cac9c288c9d851d1052a3f6020a53cca9107e7d8d3f36a3007128bc4cc86492b2b2d98b86f8707624c4b9ef4f8a54d526d04f19a60c7cd0f29c8a084940d3e3201ee0dd0c038212db8ee627ce1737548d0ebd06776773804192bb69a84e4030a078e2bed97b8015a0c32902b3fe800392c068d9050b8826530810b8b3650845db659946584710ca84a9bc6aa18820418a6001e0b57fc6efc6132e4c5ebcf910c1f27c3a036697ad1377044d875604c1b9d576902b53ba40209e11b635c008286a6414aa0c010d3c0c61219a49f0d2f428048fcc43015b976e44690e795b8aeb78523537a8e36f04e74c5255aa189c8824f64480ab1e08042c8ec4c04202a971a5f25287589066ac948a0c34e599da607595d91d03cc8f305e92b18b618578399b0c898bcd1ea8333a84c29f5626a3588657f4d5a1384e2f9c70fd3292239543c3583463f20fe8561812b390cb34041e32480675908179b54b171a1e22e39c016014dcd1bb0760f0f23a476d018f5a5ca091b85785c19e3003005cf54a12666856726657989c256e6aa3789122a9008a3383cf69348aed080b9a2f3250684519649afa6381031a6571cdbde1e25229ac4e9cc923e331abcca2c3140c3a61511134e24093a5e9dce3c21c91056448dcd0e4962cba3b747858512f2581db54898831d750d8ea963c9e8a54cd09e069e3779339249478d4203ca22a999798a994df0aac345304a93460262f08932650799dc94e764c7dda5af3d287d5c3a8645ae311282606008c40091ce1207d2e42b8ad57133434f8a184926d8a1c2e7e5bd0c423a41f287fdeae3a541f10c012e744065e182e1a14504a3061e64b68a29249a72728c29079c1160c388021b8cf6643db07b2be0b580ce82d3c9b307a204c05ba637b3295c938c787203e382900367a2a8c831c481df022d07305465482240ec70c5aac00cb83d2f279892aca22183afac923d54b085295d210221b1622e9100aaf04bbbc08d44df022e0cdcd07a902a631226eddd61e089d2978331747ad0317006cc8d330008b2e42353979920701900713b3e9ea888b26884063664835f6d8a50ba0480073d47fc0ca1a1aaced7962e7beefe3661d092023db408ebc8363a20a46be21f18299609c0a887953758960561082a357282181a8c40a3a889941c606f0374c093ea4e23343259ee244eba44c838840d93b93c835e8442b186859e3338de32332aea04395023d73843f108c1a70c9ec0eac48833500737068807a5300312f6f83866f559c1550b2e12b57f1ff888960003168f5ac910c0c5508e981888c26aec6909232183adcdd946c61f13af8c895886721ca14a485520545bd202e927811eac27a10612e6e4c0028aaf82194fc7108a9a84020cdb84358703080136164a28e0c81773101c3fbda1c95901408f8348074a385a63e236b094d43321a02b0ae4275290343316fcc46e88154a740a4162a99bd1028ea91d1b901bcc9d1ec2035c375ce113af2e4869e31af4d1949277c83f5182f5fc3cb814642c0909c11f3a506a584d582e8a248728041253182244ca1368487034f09a71e62503979a485ebcf881e9f14890252e7e40f1d833368799f8258498476c7e1af25c8c3d13783171ac7a23c0091127acb42a1e016327515703284a57797a1af46cb472028d538cb440f3916b458700ad4321b5c3384a04b8796d1a70c6c708a242a60213636d91b44c75ed285438006af412d8bf801122f68408590206a1b244d0f40530cd8b103184286b7cb520738253d98e1e5852ad6550d2cfc075910a1206428842541aa0c951fb5261c8293236302c6de5e110c436e98f9817023371be5625d1c4e2899ca23935eabe7069a1421b95903cb51193ca05d69bab083b4e8c6150c622a272a8640cb55735cb31848c31333023180d0228e312009078481e8b054291684c90363b1480014e96187d361407b3240a520a19438c01c000000800001098a1997500bd28bac420ef847fa3f4f7f3c5b2f11ba37f12539efae84678a637c9c5ccf4bebac18e4925c8d80bac55c8dedd8ab31746b11c2dc2639c21e57ed8cb8c2ce42f58a24d617aaa91507028809b7b84044acaf08313db06c8840ac539d78241450df355a7a47c4bcdb5275078710f0b318816138e70a9099161445be560b15a0acef40f0a3d61e0eac47facf66fda3c20ca18233f43fc4f780ff5bafa1306fb3bd0fca690f7023b4ec140edb82dfad542a5ebfcf99dacf9612b2277283fde3af98e3e31e5ead2e409571ffa9b95a6a4fd76a2dcff6a0d6f9c972765f303dea1440dbfb1b3039d5f9538b6fb3cf55d9fa2671beb275f0efef6ffc7ad3ff6c5f8f269ba6e07998b5e66e60e9b661bd92bbe260c61272673373838edf7a03cae1fb5b2d9203a2fffc90bfd40a0669415a85eca1d382f650c9487b205b2453905f64d790275a48c81f251bec0bba4cc80a21b501c2c5bf970fe878b5d4f5258d19146788bd5f73be7056211079b8f4c0dafed0f1edd56ef7f419e9af13e2e6b6f242cff992b7d1df4bc09125335e073a34818ae2d21c8c0bb13f37f65911e650455d9e71cd4757581d8e4e1d27e59438ccb8090520d281dd6413a88e3345e771a6a3f65f85d78ff04ce6bc6bf20bd3f9f10c286a73cc3705ab009da452fcff76b6c9e3afb65c84b35efb69493f8b3ba4ae0092c6eade80df4c5ef7bdf49b4efa663dff70e2f4737254abc977dcd2f0adc55b7c2d279efc57728eeed493bdbbdbb49ef64971f1ffd222eb953503e77552d95aa41dc7566ef6ed252f097755d33406f1926265320344138933cd3d113a18f787ac3137af9bfe08998dd8f2464b974aedbee13fbb0fdb3f47234e091766619b9ab307c55c6e1d326cfaefa6f1dfbfff0c324c60ccea43ee98705da6f20f7cc9ae9c2739eeae5ec71950198878f0bf3fea0bdc0ac35fc091760c9f49a7fa7c92fdd76c319bd240974064718b260a1ceac4f3b1eda21153a75e92a7be583976bd3927b2b1e9b29ecf464677011fe15280d8cebdabab7457d92e363fd2681373bd3f05de37fbff20610208cd73f85db5099632762254f6f74e80604c085373842b1ecbde0fad6c5c70af909e2b1628d06cc30ed577272c59311ca8f05330ff2acc2d44eee72f4a7ce49fdbb901e411b8332f0f34c766691fd377d2d6eece4c14cfa3cff7e62e8bae174984fa89915b137b1ae407076ccff798a736479a143b46d0c14a45daa58d3a959fec0e561c083feffb7bb3d8c6de04abee6c443557799400f106b7113ee2c9c970db741db1b85940d3d1cfa797dc6ff5bfbe38c30036ddc868bbcdd30054ede3a95cfb8a6b98e870f4d174bf4efcf8329d67f7abc5b484d42505196a967fd77b32a292fbe6569465ec1ef1c60f7de6a2f53ed1f6b24f4c1f5ac84e797f1ad04f12083f7dd52dfc33468d5b765723bbf8f1594811207b4b106c325e8571103ced1efe98fffbfca7778460ea4b44058b28c0c15ab6467175aa6586fe1ca6a5a21ae22851a163da91b43bec514aef15f329e9c1d2b372a710681434e0ce1922c6c2dcdfcb94122c8f198667e5d9e42b7b0f919225d27008b2d45bc3af0b7a8001bb4ce417140086b3de0b5e3e939f313cf4fdbc652226854132ad65bc6fdb8ccc01cd5136288b88c6ce1bb2c594ceb128cd1dbde4742bfef437373adca1c770e99e5570e71b44b9e6feb3dd7fc8d0f7a2d4dc688f541a0f9b1f6ea6bb17abe7ed8da8b829314fbd5cff122e1051de21f05bea3bcb63d357af20ccda8549af60461b4c36d43408c3e378de59dcde38c27c806ed8b5cf87db8d08cfb0a66f2c17efa8f773493da3e968c3c0a4c7a4c608b6c3b28a423764ca12c5c767ff1e6710e6873e8d83cddfffbde78621a239f6c917ed31e42f6e54dbc3b23763c90555b0fbc5ec6df2849dc7ce15bf4441df3b8f5bd3004c06cf8c9317543191011da1df176c5de8f65620d905a165248ccccadcbd25a718336373313475fc3b7fbfef6e27a9cdf0b6d85cfaa2db58bcded75e2efdbfed5961e0db3fb23e9962a3e6833532f953e993e0caa02f2b0e9a90339608a6cbe42a55d72ee06bf97ef1fe776ffa25c22137cc4cb7449171b3ddc9121ad5c344605e1a70f92eb47154ff23618eb01fb0a8f750578bcc68676c8c53025ee598add56c7ed5d69adf166ba39ebad8332ff5476447b1119c9c70f5b0a7809a1b229aa6236a163b7df90040207ee716f67c91d309f1d10d8bb19b4d46f92c1489f62c7253bc77215cc805c5890f52487ffb1baca49843570358248cd3fa98d723c0c66f0f6dbbb22bce1748316b48a7750c905b48a654789ea061df7cda00c3883989b5a166be73918f1d90b0d87a2f611bac4f2028a147786cf9b38d4273824a003be3f27fde6363a7208c5dff2f8e5d4719b1e3df0a2f0ce841f40082ce6212804c84aee400e8899cb5037e1f74ed48eb231222ebfb641ac8dae95ca1d7999b38e351ad57f5dc13022b0caea90ecf6d285d031c2f88833ae3d53933e301d7f8b70b453d41b9ef11ee7b0dd4d176723c922c53a0f1043c1de9b58674bbe25f700920c3ad81b21e87c6f0b23af6835b81b1adb5d8d59d7ce46c2a2eed9cbb81ea4e55644b8ddbedc4a3d7e17e1a1a25341f9e36bbf7fb1477811270e1ee96296dde6d8dcfce4d746ac0708b2ae2ddbb913eb57ef9cc3d2584aabe5c1afc7c49d73548f77457e5dec2ad752ad9f045e575a8bc465b07ff703f88c29147555b5c9e84db11441356a57b09485962f6fd58ff9de451d40d99809061b221e7aafcae75dfc2d8a57814220fb04fe0d7b340310fd1a5606fdf5bd75fbbe6944601ae50b3a3cc7862e431e1eb67e57561b3547f8624b3930210377250639dc956888b88bb67c15dc190a43f9d344763692d6953c6e6317272364713cf8e635ca9cb4398933759c2c3eefe6a12fa5153b3ad59f77c5a9ae69725b6e00cacde0aeffedf8356e1f0ca3ed34e389959f1c32885dd9f8c14818b9bac411004bcfd2ad0ca7f582b767a2e408924eb49aaddb952690c0839f81a38d312f62c8695f77d6166a7866bdeba785fcc7eccbc80ea6207e88d5e258ce2314780f61c51a5026be00138197867b964875490edd027585831edee15030731032c621208508cf28fc2d2030b4b0dc1c3f6315ede8957b8e806f5d493afc82d36d62e464b0ec05a653e3b046791dac8ea77e1953fcce3f1c6b7d3f730c7af61b60e28fd31b9ca0c39fc16f0a423098a53f660e4cedeed41a63395486db9ec0f0be48c8bee8942f29c6acdfb4e233ff1a0f4a692466fb9718f67336bdf7387636578010a37d49dfa096b542f33b982d74400cd5c6cd15a6d25f9622bea63e750b18d4f73b7fef875b8fa8fec5e084e027b1bdcc95f709e702ecdf5d68d02e356477d2f8a0e9775c9730f69b0fe32c0ada450520a4c27bb06e6854288274f22306ee14f668661c7082a4674228658a7614b2470f709fdb06c38bc1adb078f106472c2de9265a741fd4b1a73d3c9468a10daa6fa44918c50251cca32052fec5cad30f9abd72e206aa935e1e9952bec60a3ee3180a4c73f5777d3a591dacbb04ddd6393f5447eddc560afca75dc881b752fa22065b91b4e2343e8b28fddb67ff5185b36b2009a48a64214423ca9d26a89da638208d8861d90c8306e1f718fb006e108df3a9acfc1840fc57d2b6316ba79f528774c43c809ed5f7d7eb7a5523ee550eccd3af2c0aa12d3299203344ed253454979012520ec5a1fc9773b25d5ad64d9ab81711ddc4063169260946f6e6823c724ba9f902e005ca90d7639c65d475c39ce76dce160860eeb4f10ee5a3f7a1ec9a686c2f5df90cf6b96393697dcb824bca8d37f9b9753a2f34e333ba531112a1d589705de900be045b54bef557ea919f806f434fcb2fb476d975aab3dded7d857445fd507effd3c4c4a40e45fa764b8e94bc0bad1160287c12c03f0dd236b908593f42e25a31ade3828098fcf8ed06e9488ff197d391aebfd66b56c37fe6a9ccbfe06c5d879edcb152312480669b92da0c07da4f5e9c35c5213a546d2d08a2fef4873fe95faa5330c8aeb5935f5fb9b1c6538af87c41ac670db9c119fc40210556e58840dee16d82a5428169c3a7df1b5ea49864f082adb6a319c92b70236159dd2931542098ef0701483db31a0999586ed7161afce8e2d07bc46b94d595dc568ebb8886676cec02bd15a9d58a17a8f63e44ec9791b832e5ad58bd790f3b78ebf302fdd2b83d887934413afb01a2a4623443d8ea85ee0c18c59e990861a429eae6409e9b036d89833853173ea1bb082f30747a95b4d26f6131ef1879ed84575651f6f9f69e6201d0bf7fe76048b8e056b1f533433506ab4d7353a0b496cee29200e000de190994a3545bfacbdb451b0bb8f0a832797cbed4c9bbed9d585d592297aaa8fac1f7c0195fd97fa1a2d6c8b52e1bf63e3ce887c76c45d1587775b0d88ea7d0ec5a4576d71a50abecbed633024a1f1147ac1d420a19e09b7a936c31a13ec8bbe38bf0a37814a6eac7a6b232a692c2e29c4c32bfa3658efaf9edd13316c91b3108340c5527422eab50099eb6fdf4a82489802e8f26ad9a3fd7c1c4e38c938dce58fb99c3af86dde89f1b7819b34b0adedf1b75f0b213be6e684a065f1d6ec6afe72f5167af01f1dce8cf9fa18b2d847c60b4b16663a8db344a6dd98839e19244a8b402dad55c85ce2f87bc81303438a1f92e0409980371b02db44ed4f78919a09d7ea7419d47244fc3973b7df740eb4f54d0e7841a744b2ed4771e5e51ce378a03ea283aaf4f9dcb881fafdd8eff15f6ab753e853cb97b0f12363dca5da68cf06bc1d1c15fa15a0f1db3e21541989dfb6e3ef738985e6aad1c6f0c70689c10826f99caa4943b0944b88baeca31a1c0a48ebac1d50f6a2e83fe14069cd60abf07334061dc492e8b870558de7c8a3363247015a663c6dba56f020708d30bc7a077a69bf5c074ea96e1dc9f986efa667b9c52df9b56fe46882c9a254fb88b05949899b27c77c8f5ea90e700bde57ecd654dc47c3c252d6d683544b9b8452910735f5b563e88b36507475da93151a6c0fdeae09fb526683c610ce0eab03b20dae7f87e5153d19b749ce8dc279e36a09817c9ae757a5d490f69f4be591029dec0fd0b904177d8b3a9145f8c5b49e37623cf19e4999670bbf342b9fd62e744b875923b07a14cb6b032d87e436600eed1ddab4375cc3ae4ef1ab39efc04cb76b9fe94baf8b03515dbbf8f572293b0f5f1564131222e7879f8ee2822eeb8409d662ab838d0d57b7da032999b1e6d1492e20ed06621256c6c54d17c964ca34a1cd4ef75f51233bcd322674b938142d19fd7f791c2916d5dd471468b0c09dc7ebf279699b22d323731192e0a797ddcbe9c0c6eadc61aa635b041cce7757751b1dc8b2e733211e1e2a0bc0e3d9782b48c8f1b4adbdcd5467fb6f5b089772dbe35c4aa39961a596b4ba07b4861b2b95f0ba1f692c663e97e6a94eaa66d4f20731a089a8bd78d80ca75d6ab036c4d0eea76ae360e56b4291e07a9aa5aa8a4d974da2413a7b41ce942d80fdc716978997dd1f6c0abacd141425379a773490efc0f6df07a3be0b5dac3b1e91409a429f244af09863261078cb24e0adf2f98eff876bb71756115c70d8bf444ed87c3907685357654f93e582b75e401b562a2e58bb841308fefe281bc8c701bd62ce25f6f8038ff765777efe6a9ec60422a994fe51f5b398742f73d2a7af773910a1ee31aee8d8af527e3d416ba274e095e0790bdb0d924e5f8137789eadaa0e30328a8b44d5cdc8672192cd2005fbc612e272c9ad8998594d2a076ab04490d6a8c7294f7c6290ec7ee3b93dc42ae5008c8414d4530a6c4884653ef3ee3ffe26177eb8faa407710f44d462e06a0f960a5b839a59f2408fc18278f1a6c0a5ef0264ee2f207cef81e68b49da6ff517d845fd0cba52b7d10676e381c9356a5ba006757b6319212d14e81be430024db8a54d574e56ae25e71c1563e17e511534fc81c632acce87c488ee772417e9bee504f941dd837603f2c1bc34a260c4803d0b9f35d9941a4d133b6bc2f4a3894c7d2bf19093243527d4e29f18de3a55ad7a0bc85da485cea924739c8c7968030e93404bd6f2fdcd87b5aa2fbef9ec6c6e8e44309732a9e9d4ecc2024284988be368c212bb48fd1e061c65a4533489c59829c43293953a822ef2904c06a5188ed1e3f33d1ad29d622ee1827c84f73c5aea2bf645cdc54175239e6eede58983108e36a7a06d4398ed36d79131dbad82e4e9ee8d7e45168d57d897c3d1e22299a65190306e8eddf04736d03050e8f44af7e01045d60dba449c4dddd581f5f4e4e6640e9b6e5ca09ef85b07c6077195260d17ce2a0c14d143ec37b233f00b4c0bd9bcac23ef3ae72311906e44400555518276a8d933ce939c729bcf2f91bf253149447cc3b34e631dd8bf597ed5c670b885e84391c2988bb36f0230aba2284aba621c4f7393257fef4165228f748a2bf3267e56fb284d64440513d0e5d59c6217955613dd64fef4be597b8f4668bfacdd95f2b9f8d35ee88f3a049a586e9638baf9fd396ad320e34a97e2fb9dc69b88eabbe735dc828991d0c665519f52a8d3acd901bdd677bf6415cf11c16ba0992dca74727035cd12d9a76f646da7eddccd48c553c6b21b3fa8175e30fdecde9c3662c93347f6a770df8bd9b8ad7687f70f474f200b615b164db4db33730e212ce946ff1bd8a2b02570cf68e0b524c721571e2d05d73782da6e024144e6544c4b57a9672c8a5ce35b27c6e98ac8f877ff1b99718397fd6715638f99a2b48d6d72f6e8272afdb4ba119c98834431641e2a423f2b7dc4c2c67c9aa18f60cb72c4cc27fdef8e8e466770ede9e6a96563a8a9a7b6178937b711751b1007170f71e1fd674fc30aa8fdc5aa977fb2c98b6104dc635d26dd91a565af61c8d921f2c225270b653dd2951ed7c1b46571ce0cce800b82dd95bc1a9e3cb81367fe56ead676082879d74ca43ac8a18403b9c2f7a6e18f6e89efb0f2da6c5ceb727353cf8d545c300731ace93800f0316ac320638decf307684c6d0850a9cff8556ab4f572642abf3983d743c823a082d702729f471ec3dddabda875fc297cf157f36d5aa7bdbae4cecd45fc24cca09dd80c3f42f20b9cb526a3fb69e4d75e93f541faa9f7dad625fe7a395fedd305bca7b5b2553579a31cc83db634b4bd5e159eb3ece772a48a13ff17f1e686a146f8811dadcb4f06c3a09af7f99730b1f9f0ee3c1934e934a326ade03e3e6397d5025b962769d3bac1d8e685fdc4742f9e36739d5b40e8e52f48124dd1f844674f25c27fe288ff3f6a5887e0ce3c50e69116fff0603835ab5117898e107dc544deb59fc4bb0c097ba9d4ac7aa618120ce0c7dfdcf86cb47c38486220ba48ddcd40ef5cc33e7df970d30c9106f25c341631c30530a34ae38a67088811e4467ea44f0ef0085ddd96dc079fb84e3cc9c8c88ea3c1810a979ba12820c82bbac5f1d7c7c36901408fe81c57dfa78536975e118831a8f40f721537fe9c98598414cb5e4ee65f935e1d1e49f08397a532211bd7244165391a8630baa84c95f234fdcfd2259de5eca2550aa7811b91530aa52a96158af5ac6ef263d73dc4cd4c46f5636a2d58d3e92bc611585e3a191389722277a9523b0cc513d9dc30aa1e3a3d2b9247522d03ac2247654523b6c2b77fc51effc153cc1563c7202c9a3a2e8e19e573d7e69e1f33f689f58a9f247e2124869d6401ca5829c5a06fdd4419184901c4a481f29c47a5ac81d31f419aba1b8f490848248218a881949e4b09ae890288a912a924d16e9eb229e849197cae88c340a5d6d24cde2483175c4451ef9af8ffe600552c822491a95a45e2631ac935c58283dab94e22695a4502be9279678514bce532e7d08a6c0544c62249954d24c2ca2c91daae9bbb22992759338c2496d94131fd2c957ed742c9ec24c3d49239fb4d64ffc0594bb29a83b122af635943811a5888ae25f19e5a0d151f74a2a30292597965211531cd5942772ea909e8a475089a4a8b490546c3495e319a26a09ea21af21c250d84427693b062157c9ae477ffc518fafac4c5220feba4fd2e61ef57618b7f63fc0fcc6e960bd45e9e90037ddbf1d6c230788eef78de782e4242ed7c630d0c2edf012a7b97428b63fcb45a73b3fcf8d20af9e439ee38a8d6b4b8c4099147863a5d700714cb842da7d45dd2333beda659fd5769d33bb96aecb02d105eccb7b6a7693319e391f26401375fa217b9e7a80d0ea32084ef9c167ef277095436a59f8db26f22870531d3ffcf407cfaa524d69bbea5e3ec43ef6a37e031031e9484223c58070fea39cb1f73f27f002b16c8425e8a1d79cd348659ec29ae2aa8d716e2192cde138a7b1a845f028dece6f420f6107410de51503c851aa10e4eced86f1ad7371c7f58fdf6744981fed2fc6eed85dcd3142daf06834acbd3e43af10721c9905db86f8b56458d8453eb7ae035e1a510970723fc2f6460704d6ec29217fefdfa3185b3c5d3ae27a33244cc86e3b7d46c5fd45b07eb2075a25dc341ee5076ca63adaa48ea58c233261457691f721191897ea91c084b7af1e0bbf3a784da704ec829235a7af07b48d751cbdbb0aee7fc1874f23d8e568d548458c0751c88f1ce91d70b72f95db603de11defba01b748d8514d2bda2f5aae35797aa1e9345aed328d43e756e7353f60c65031edd77c2a7b9ecc8965b69fca69838c00a8dfe2474d0000e38cd1acfd5fe81965b77d20a4458e9a776c2a9e3adab95a1361a0bca40a2d71dbc2de6fe75fda39096df8a7c1878d27fdac24d905acb8df7ce863f257b2e90b35915928177a0350db0b56fe74cbb10ce9e7720a327693235190dfcd278b40826ef462c55f533fd5ad68f27f856ffae9cda503ff151da5d75006537fef34426874856fb52de763d93baf4ce1eda54462ac25fc04ebe2a152215cd70b69008134886e016d0e3e8ddc69fc9e04ba4e6f1a38e359f19fb9aee00ddbe10e7d37a2e61f416ae9f7ee192db6effafcae2678c66f5383f35d5d05e9d0deb015eec9e86a93a925ea33af6a59d9fd185cd2f03fbff01d38393ac8ac44673335ae64c7c6d2c189b3f74e8128d7bcb525ed0b8abbe9a2e2f737c3c511b4154174a57e7bdfec85ee0e0a8afdc15dc7df05f359a7fa3b14cb216806dd9566600814957ca00be4c0e63332b4cefbe43d8e136f656c9be614d29423fc9dfdc7e9e57f97d02e41dfa5ed3f64ac72730ed41c8ac17012828256df8aa224f7196f0cb28140049f1299da1f0fd59086f6f4401340384e3c7fdea509d9a61528c0cd3289586563e5b2b6fc339701c51e2e79723016a5a67e68c21fac76b13568a13978dcc8116e57642ce702e3ffe579fd39d3f579d328f694a5a72fcf82386afc0629cb51b8c9864da0e5c3c8f907580bf7e2d307066e51402b3f02ca6a0d38922d79ddbaeba464cac5cf67ee22632afaba2d3f74d8e30497080900144c8c4f5ca4b8927d5084f2f00bcaea67fc3a137c1938f96af884bc9ac4d4b4d37b5bd5b5351e38391a1696cd63fa62a93dc884e4d53db09a2858cf05c25ba077bbb4440029dd1f64f2d3e963dee7d4c1b4cbb391efcc50f48d8a035e9e1cedca2ae094a97fe6d4c7ffc95c82728750eb06e5f126c79ec6c4d118976c2ec38852f07a4d88bfa389fceeb89b7acea75c579b0f6bdcb25b988832ec6a91b2e0ddd5cc7fd2ff047763c121bacefeef91c58495639a9f9dfecc38c9aabf32abfcdfb974c30c87463b44d6560db53b8d93456cc5367f36c3acff8aaa132bb439faeaf232eff50230df1d6f53c61ec918520db3a55c61f209d776f30f5832396e7db7d91af84ad4b0c06ec9572f51d8d958dfeefef2e33038b4d3f46c4ed141b2043e4c15e06f58ab86f35634fbb436cee6a94e8b710b1393e54f83d04dce6064b773d7f063b1e71263ecf3b795eb9d9649a92eb0a85e20680446f3748634def5deef6c66aa412d396ade80893cc8c80a59fe207b31025373d03df50df8e62399ad2b7730c78ce1c2b74bb6c5c6f384657fc91d575df9946d60ee067b1eb3e0a76f39afbb607c568ccf66e003596a73b1a7601e74cff6e6988d32a8691c59a547bdac3546b6f4922c88d966c06dcfc7f647c663b7371afb1f4c636a902cc34bbd5e8f43c5b08d8d0318dd08a336ddb553c39a3866de91f81ad8068e159d50d67cec757accf9d84fde8c0fb4215d86b9fa37c85d3a6ec46789145cf8ccbabc6b42b6fdb6f3dcdcf206b33cf3382e592c6c148f64746ecba86f2597990496b9db208bc48ef442ddc68fb8135db19388ec6e72442fd8b581c108f2d6c63b4503fc0864316b8432987a97ac60a35ed03b3ea08c8f0fd49e5266c015835ef5cd66caf53af1ad4d1bc48eabe98dfba66a4897e04262bb69c0bd85d5b8a08d2c63c888c5d3da101f6b9c8ff979c05acb9de6c7cabd174fbf73cc04e31ce250b451dae3bd31933bb1d20666aa47c5f9529e86b1876222ddf1f35397c552b0dc9acdaef2716bc3d59baff52e3c1d7c0c322743571e22ac419a615e10d6dea8c33dded4c41904971d577b4bfa630f7419b1328c2eb09e384b5b8435a22cd89df9e001184abb5ad4a71dd34ed6958431fc3cf11b6c718ab16657465cbbf800561671b3cc4f12bc51968af0447483c779fc2653c9a27393d88d70ee201a2a76b34f3005eef406e9f0947678199b786983d9cb4ea06c1134fba78caf5dcec142e3239fcd56a9e35a979b1e61b9e6bd0ae7293c52ab6ba54ee6dcf2ceb4313bc009639be37a3aa7db0a5f7e922d75dbcc8dd73ebd8f73c918318a5cd849c56374a1f6f6f8e7e780dcb761544764271f92a94358ea266671452f7bd8cf2933dc40d355d6393f06fe0c5712988b2f3188583e9997ec2baf8bbefb393d085c819eeadb50be956d03ac05134fa901dfe67831f16d92890f23b3be9156c4f497605447bcdaa7710898365e8bbe46cb7409d643f1c2ec4eae502cd9eda2bfc5c735e4159b2d4f938c3b4f8d3f84a3c606cc42f62226d3ee9dd300b2ec6de136483bf48872333feae6c447431435d3adcd465db35efb3c216bcd5be0eb6d2c39e31a8d498bfd73ad055b1522d9e13defedcb4f9e9e5c82515bdc3657178c610f7273c3d22799e7d56ded2dbb882d33a847367e296cbac24b5d841dafe9410d59c8f7b3155e4ca12ca096ebe6b7b3ad4d984c924df2d0f99eee79b39c663e9dbec7f929367a2a360631c64c3aa22e6309e69d62da53f914fbbae1fe9cad90d9dbca25d9fe71b746716895acb8bb77e645dcc11a2d7353f10e23279767d19d0e324016f4ed8d611d8d73de797fa02b11385447e7b619c9dcee353ea507b235e636023d358c468c9a577615ed4696f5cea067b633fac05bc6b8924d7bda46e046c6a6bb70abcc8efda79c658de8403dadd123df80a544a7ab1bd88515caa4731b7c8bd04b67e311da88295dd07955f7f4767e6e56239969c117335e6d2367907bba434d293748e6165724e286ab74a958a90636e46d9c57d60235bdb6769ec7eb580cb0c3fdf5c8c06c659e4527b4b6887677d03f7b0cfda7c53544d631c98caa98f90526ba0486d152bfd35963a06b961fe497993473619bed0a7bf5b92926ca2d31f075dce34fe81886cb8d0cd591cccd69a68c998dc04f44d5dc8163d1ecbaa73b6e287b89d92651d38fa7899dcd09615d590afc90ccf5bb9b6d63e24e63be0fcf4b9b7b641be4f44bda8fd730f67c3dbc3e796b1ab34643b385cfac0293f3b2ede2927193a7b0adf5a23bbb69efd7e9d358c7db54b903ff54d181de02ebe6a398d7f434395476bf6bdcb6c5189637f48664e5a361069fca67287bec5b80999e86b042333bef9ae3b2d0e6f8643fdd0e5dfe22d7781d9d9d812d2fca89a0f60b2ee4838ecc4506b125db307aa24b669ef6566589d59e1dfc903cc81450ebe8658d416110fa4d7537b543744a167e2906f508bd01037ae7ce6e049dda08ddf5c03da826eabe0b5ca94279cd1b7105d2867de35dc1f27dbc255b0a36199a01c2142fee17bde1251ac8a9d80b0ffc0ee29e3035722fa1f0bec6400b34db1db820ac3951461eb0b365ce1bcc9631867d4366505ff3f032d4513e90bf1e305ad3dec6578063f9a538d11c70080185bb1fc6e806ef1aaff93762d8bab1b81fd3813fc0c5b84cdf785f88cfdc535a816c1aa1f15df7ec8107cc8a38ee72382ba6cac4651068d1ec95ab4e8a8d2fb18199fa5e35fab548b21cb7d6c955fbae119e352bb99ab79105cff0d16946ee8df90672256175d0bde3cd6abc793af63aa2a39ebb2226e859b111507b578fb51d8fb86cdcb38df0237c22eeab1eb41935f1d1af89c3c886fd43ea60b7ae2833c725ce5a397c17b79be3a00297cab1f037bc5bc097dda4963919c3b52edc836ca01cd0001db093b4373d70d4eab50e98db01cbe412778f6bdcb6dab033870fb24a1a97e3d8d8e33c55732c6dc28ddee0acca8db7cad9dbf14b0fd6189da2690dcedc6a6f67b66387baebd8e20c3d3d97b672f3ddc6b436f837daf5a61b3f6eec92da2c68b099061363406f30471caa76b2ea6de82d2bf24183bfb0d1dea7d55eae2ceae6b39bcd6bb5702e7e105cb779842e0293f17958edaa1bade89283f8b216bbc616ec4c0db6a29a6eb793116623ef4623a6bd54c78a89f62013d425601c35642665281fdd4090d6cbb1c31bfd16d711b3b863a7ecd9afdded79806ff54a3cc63e767253603dc678340c3599311fee19c85ff3669ecbc822ea721ad83ec6970e30f77670c7cc96d284f281cdc45b7021f15532100ded899b17238e291ef762cdb571980cfa1cd1c2da03729fe62b7af941b0c83ce288eab12ef799ec38d6db72b57cf8c4b6cc40d3c8193d61d77e0dc7315c3424e21433b761fb1826bf656dafce7e8b8c3bdddfe028e34dbe9baac12ee7b6818f81bfd0721c010ea3cde28eeb4b6fcb1d70316fbf76ad813e2fb389ec18b6755da77b1d1b7f9e16d271104bc51fafbd2d60b23b82c984596583a96212ecb89fee78bfdface11addeacf2db77e1d10c335b7b3311f4bccb52d6ab8e55a0cf7fedc6d4c1e641c9e908f31c41be9b55ad30979c7283e400ddfb18d375cad5ce54d6b293794721a6eb1318b4e0d8ca276bd3de32ee7c8002d18d31f300cdab3d9a8d80e3c133ce04ffff5bc1213836bfc4be4e438324eed081c7eedd23943a7b2cd7bc50d3403c7ac7035dbf92c873b58a7c2eb23c94efb326fbb9b8ce298f02933bc91a5c2197f29467516eff2916f34830cb81d7b3a0bb63b59f5eb1a176bd96061772c63ab858539450db476f2ccabb0b6771d1a6b6857d12e46edd7cf2723d57da1b319cf386acca5e56df70d34d28ddab6e159b3bebe706e899eed5bd426249fecf8eacb4f024b2fd28e3278d861cbd352aab1c9c83a9df15e18663b1583fa826da8096365c84e3ff8347a7ac428f366bec2a6ba62fa41af5e7ede6819dc9147ce75604bc41dc3384e7c771631677813465b4fc09818225858bd864e04bf9c074ac7a25773535db6b93af2ec81d546970e71b9ae64b86369057e2c7c098bb89c5e092b333b7fe365dfc008733a69d46c7e543c2db44201f675e3ade7e9aa91d0e54d0b66cfa91c912a8bb9766ce35bef115bdd6d3a1c83411708df151b9a4b36ea9460fe9cc12bb1cbb4d99f62806a90df54c7ebdab5f07a2463c4d829b007718a6d5a89d19c898d3ae4b7f4c107b25563457316b15b58af6b38d612acc5036920b66a4f771eb9d137223befac3bc4ed5f4b0d6b3771b294419f1c755db5d5bee75a4e10ccbe139969e4c881c16f779b5ed57361e5f313dbc0c41be752879ed9fae3375362d7c685784a160adb0b03d1142f32642c5a66102764c97c8e3f72f11a1bd52cee18b6e632e6ed2df39e9379f106dc4696887ddcf3864c865a7760b49cc6b0cf6c83876f168a010e988dc9d217ed4068d6581ff46e1dbe826c3442033bcded37c60626dec1f5e64000170ae25b73657e13761e08c7d1d6e10e50abb5355b87a6b95e6c9ff107aece0c7b81f96e1887df83719fd258beb85433e6cb2e721d2ae83a0c344108ae4ddaeb3c268678e0f2155a4e01bbfeb26f32b38f023b11a38fb59596b8b3a48755aaf56bdf084c24a4ff67026b7ef4be3ac59c032d4fa0ae1e0f1f84de8e753d030f085fd43dbefa2343c401fc2dabc495e5dd60ac9665b1704fafe022fb97046f5fe4e69b2e794d6c5051ffa7fbc53c0597d15276328508f94d31d6f38e075379f1335254cac4902183ffd0966f324cc9abf076532b0b00417022e1b03c9ece3c1b63af78fe9262015ffe602b372cfe936c2344f0266d13fed721ef7a6066946fab3ff571c43b08c1a28d61a5b51be1629d909012106740bd0f8198d8faa55c14a198f489cbd27358ff40fb9e590117a25053cb27ef886c123f8e1b174e630890fe4c703af191e386ddfcf86cdd8dce7de0a5a7cddc42ef2288352583e50d99d1714960689206fd16071b4b21f67117e6ecb95196512e292bc5816811a5232ba16264456e11df47ff0f45b0f230ab4519db2ce9deb057b4021a65bd0e368392fe1b40cdbe1085ddc7e8793152ce799997113f0cd992ebd38887a9f48366ee735a00120853964027dee1c679e57f36d2f1371aa9300ed18b4e46beb1b3d1caf3e8bb94119381c1391fc920af83cd151567320fbc7414f25a8b40d50a14d3eb1b0ee09f061954bc03030ba5a8bb1fad3be8ea1c7c30b32704dbcbee69403ae7dc7c6e4ca47e562c9e1a28d0008b8e651da48024f7b2b51c6d0e484a110ddeddce65d928e4d1fb2cddbd8bc6448dd2aa966d29fd68e7a7f68df33e0cff7938d4f52ff4c1722d94f3ab7dab10e7a1181b2c9d3e40aa9e9e48306729cd3e0524f01436c069dc2d24f3b514b2364a7f35439f51da3644a79a260419dd69685c9b400b4db34ea62c1f5c345503c9c44e943f10c5b58fbf8d61c94a4de76b59ba317009f5a425f6bdd020c4e1f7f2899cb5a612f3b7aaf3110ab355facc0d011a1ffda12871f8dfd07af315b1306abe2dfef8ef4fe2797262eff1976b61508952bafde29f314d13e12587794017877b5e3cefb7aa75cbb98ddd2b2ad742b215a4320f0063f5235aedaeefa094e82283935e68dd9f7a414b93671dff27f0409fc86c2ffac8cfdf50e56ec6a51282ab8011d4f997b91504718a61affec7668bf3ce0018a363857a9bd827fc3c71b490d6482e700b1abe709a72dfdc8f7ff6f00c61daa2a65e733ba2eb0ffafef9b95f6f5e80401d21760e8cfed2fc8bf697c8db2688e087a6b3fabb156d26f5b9bae770903c9ba07ca14b27bec582f7921d3d73414483bed35977272bd6e88e332df7dc973acb31b6e206f7c37fd38bbe96a7e6bcfb0210fea48f725b3882cfa159ad7b9e35199e9c9d3549f7a91f7f458e2411f52a74baea0e4cd12561e3687cf158cee3798662ebfeea509ba434ab3df7528424e95723a8cb9959710e77ae2781de96f6ca5ffa2fd48571c697626d64beff6d4127ac590a6edb3821ffc735b6ed8355ffc7fab0a3517a343f144a25bfa1e31ec8bbd5a3884d09721612f5fdef17b476234ea45c08efdd447632812c8cc59647572d4e9c5268b0773293ec6569c07b83f9be8cfbcb859ce2566fc7f87a90118323ac4ed3d747efd8bef5ada6acf7a0b4219b86063615979e884d499f0d07aed49112120b238c9128114107e3de3c186d45c08af8f68cbcbd8bf8493801d6e44d2a88279cd4b80e97d6dee8901b4bfa2ff7dab977837871fae1a0530a362cc2bfc08452304ab19115672aff38d35bbd04eaf78fa13e9cd8a963e8e31faf5007a0fdb2fcb99240803ea542dc3c28a4277be9a73fe303c907a477c6f81cf0668e45e0b57c9e45b0917b189b9baaf9b95e3ac02d8e2db2c484edbcdf309744fe677e44dd89cd0d9e59834de7c0477622540165ccff9b7d01fd616a6adde3c26bfc822e1c25e9bc1194c070663c123cd0f6bfd3d87c1760ecf3b1eb8fde68cfc0707438b190bd6432cb79cb44bf8918d6db28b70d5921300739b350b83aedc4423ad1d8b47f791d6b91e76eceafa4a46f4b52f05dd3b81adcd72d172e8b007997ce4971b3b01bdd4d2793822b28e2d0570ad49dc092eb2447fd597d70fe19c91738fd94fe4cf40423a07f73a495f7e5b332b391f0d187b05508190a188ddc7ec0cc627225869e9ec99e271a4b41b82394a66ff671bb01928501844d7ee31799a9ccb905205760243078dc94f42152ee2a2384cb5d2b86a47329e7fd58b1694960fa5341c4427b3602e3ac14e55a0e9a8380724fc16d9294993b546f05c018ea855d2ba18a40472dd341f6e5a053383a37e7a658e19eb53fd531943fe20c0a7008ae685641699a967f2fb39dddca1288ff48669341d70daf140d4292143ecc6ff6b46b3fc238d747dfc91f73c2c4ba532eee03ecfe150a19742b04e12326c44f3f6b68b9b171ba7b138353fa012c977da889cc40fe9dc4af2f924953787f21c6f31a5a23ba224fbc89faa96f192ba8318c36f8612d31e849a7bd06b8a8d3bd4d98a0cf57a211d1bbd53f33aef421bf3bed4601f415a6be4cef5d15105fd708ad4b7ac69eb3313738868a2adf6eaa515f6684b7c6256c12d2ac7eab60f80b677df4863ef6904feeb56565f37253bc5c3f1675062a24819ee9bb5d170c637a65f3d2ef95b2f6f44868584246738b08420654829129c16aacad0093fa3a6285c1fdb62c0a507195e8d5cc0f24298efefdde77a85f0161be4c8cc2295daf63a9829bde72c0c180f7eddf36baae3934d761b1ddacc7e9c90c506c615f3e6666bc1fef97846f1d28b42f466b052a03ff1e71cce1b84d5ccb93b1c46d80616d42d15f3f5b258b0320c1071b033fe5ee45b048db60dee82e6c1d6496a0aaf8be495c37152d6ac0f79eebedc8a2ac4fbf9133e73cfeb6a980107dc832471a0d75e9f5d362f7b98ba121418ce3e3271afd67ccb28e0cff7645f13c90836ff31be276d9802bb4e9fdb68e0f4c8c5e9fc00c88649e383fbc1e25e01ea17d6a35328ae03ded8882d102c1096546293a5cb9bbb7d9ffff52739e359d292e985e66233e5f3285fdf024b40e59c0ab1c408c99e8055ea72facf52397a20ef67b35d25f2af8678936c079f1b689119085b3045d1ae500a12547cf44d42e6b09fe41960d015e0fec451d02c56503b11e2e15da13103cbad7002ee3f9033ca91375d6cd60af03eb7655e4b70985c4f0fac45ffb0370be4ba9e3160f5d34134c5013c08f2a3d9a6cd93b983c945f584580f9174d1a7f7cad9922f67ad3778e40301451d77ecde3a629d39409d23982585e98b1465cd2deaadae1a1e327a1942fa6d0325aa6745d84b54b7fc072e5d071458770ed6f35c09fc20abbc0ed82a89e39a5c4d3612b24a63a5c776b043f4c625c9a9b80b1396e83eba6b3523f451cd36c225bb96c622fcaedf0a45521d778af8c82364f4e90b0087035d798c850c172ee5308bf5cdfe82d3d813138096a9ae4b242cc642061419423daae0701750e13308fb7225f93d7071d59189defaa3b1baed434ac1d6df3c51c14028b11a9d9304dc541042d04b56be878160704b0155a26d76b1c3c0336a8f4311cd07d1e547f4805b655652b3480a4bb2d438e98e9cef6413572d8a698482252c861699ee8a16fed33745db7534179fa793be8f783983dd9ca9e7a080bb6d3f444307e8dcf56b301fe92b5e77f92a7d8208c7790611318357ef721bc0031a667d0cc4f4f187aaab3df3c9c22f212a26a666795ad52954fc1c6d8aba3165ac68b2a7310b99d245a17ae8dbb1b3b86a13e4c02f74dd324fae44c4d048b68d7211f8c5426648259e63a23f841e725b46fd51549a9a4cd1ec79d2e4e755a98d7d0b904257cd3db2e658cbbf59eafff2cf69f0ec8440648524ec1357ce356359bfe8d6ed4ce74c620501e95723117b6dbd66b39b6ca271c29c7a287012e83ed97f269aba9a4d900985d1b9bf1c6ea505c4e839eb35cdf9de52d05fefd0e7675a325c4ebd35cdd78d889c32bd438c2ef7cb22c95920c70be9e2f7379c5d42f17f08847ac6725d6649e7190802b187f585b2e793b7352ef81d26ca9e1d4829a02d992a984712ff93b8284a2dab17d515516368af6f0424763b2af8ee603b736209fec12daf6a0ad39422a9e1dc044b30e2e89e36dfc8edc976884a37e1d924059926a735dfee736e74a76e2a1942562999c59830dac77df6e7976cf08f58ec7325e7700e1b812949ad33c9059a625d0d76ee400975f54e77fec1c5a8ee0118f87f62a0e90258938b6e2525f2fe24a4d0e952b43ad62b071905065fcd0025792d36e0aaf0b0de1ee6ea60ca506710226f903c3f31f9a3a3c3bdbb2736ba9b383de3e13ee0445512be6be3ece59c412ea6f58035d7f642e1a0b46c578f3d2214c570f478bb78327317023dbc23f8a9ccb558c6584022919f162b702ff57c538ca51d3826fa031c73d0e780a3760357a8b29b8f2c8d9785890160e3ff72d67ee1f2560e1537fc28d2aace3576f8486f0e8a0571316b9a26cceae7ecf7281eb25cdf5015c873a86e18741259d1fbd86c60d4475a39e77b079b67297d24b7a699e273f9b69df025f89b2f33cede766a79f6e3082ca03fc9d8b3d8ad7fa8898655eba2aaa49423fe2303c866cff3ab5e6dc725c44237bc8a42c7a72635f84a74786712f8fd908221d7f74aee82aa59aa58a5afabaec027645c6ed10f11d39d05d4d4a13bdbde4e6b19a7dc5d33f1ff50cf1ecab6e6af4c4b84bb4dcbcec83b921deef9c2a612ecb9a5f82a72ecb0b5de249d4fe538891a52e94dd4c309aafe2f250f3a74fb8db252f457cbc3bc51a12ca599e80e496808ec6ca7418f92833d2d414cb39edb38cb1dec5c0b45772f9f819bb9397bb01e9d0853105106434cc1b3260ba9080dfc745256d8f9e7170f3fbd93f1df6dfb4836a90e5abe0555de0e947c2365d2e670a16ff27cc3accc1c0b6db08df3a1bfd646cd2b5a1724cc364ca1bea2a4922220506abf76da1dfc5f398d2bbc30beee8ea838e1cb7c75292a30eb42015c6a5d54cd48b13db9f4371df599fe2886663686921fb05c0552cbc6169bf572377bfeb4114a413c79c6d0c8879bc9ccf4a54cb63751df4770615430518ddab4a24301f626fe1d611bea097a52c22dfbce87230c57499e3d459cf591a1c28c2419eacc395a84b95df1fd4da6d3805bc56f9f4e82ede88d0eb926eee43a83d195fe4382d46dc6cdcc3bc78d07daab54e9a81a267149d334b4c73bea8118720c1a8f695ccd7cee2c482fe6c732abba2760097fef22a31ce46de8f62ce9cf00ec1f214910ce97c06e555cbec9195b8b885c8450b16436a21ac65b1d1fab15466d0ecbe4f2dc7169c5518fa8a5780bb5814528dbaefc2ddf217ad9dc98291d621bde90a7333aad993b0d54d7c06f95512f3609a2a953ed4bccd18460113100302480109b00dfd396e91b2b8c86a987a334275eae3e2932d3dc550c950d237b1de8644e185ad0a6b5196dca97bf1965e503ed9630f9538160b5f0896b667bd534c770ba4559b46f42410316e094fe0190fd9eb06e9584d0b30c9ea2dfcf1aa474b4f7c56e28fe6f6de0600beca20e7f6ab13776ad2a8a3e2386e2b797b87805df3646c489df83f64b0f8f9f31b711cbbe67c162cf3d0e8dfebbba7499538a43e15ff35d0f378cdec75b19f4338fc555b6ea9d671ce814ae4c626a03eca162a3c4212adb98eff79348bc8bec47203e726a2798e2af63916402fa96f2d01db72c17ef2c3ac68d15b9fdfe4843a68ab28f940366da316fbe0028efaf2e0cb9fe0d28756703256d4244b9b8330048b7027e5bfde3ea48612cd857d8906cff2fba8858a8e6c0c7fd5dadb12ff5ed4a1a6b624bd47258feec503133d503a3d0cecde8f2f8a0d7aa7787949a28a3913f2b471d7035e4686d6d7cfc24b7babaf817ef5f049275c272238f9ed0c399f1b301d208757600c3823bd8027f1c14cd13396acf1c8d38ebe9172a6eef03755cefe0d6002826fb0cfb6de351d4671680caba6f4bd1721e7c866bcbf7ec7b90b83ab82cf7cdf9a4c9affc85b2120bff827d221cc247d251a81a5cba60eaca8d1e09fb9757b5500975b4f04b188e3e12754aaef70add1ebb5ceccebf33645aa3d1a3ba0bd088caec61e6e3ecf616e179ba212dc186e0b3d48b94b2efbaf1a92cf5e4ef489c5524b468d1e3c2500a5eae245de07ef53ca60b3ff5141d7443885cb6a25dd57958357b7223b3f687467319e15240f53cea1bd1a6809d068f398e55a79db623785d00627fcc55984d852ee2c1f50ce9891a59f2735727bd5727729db6b435838437a13c1896e0ff0b9ed1817e6531eeb21aeefe54e75f5fb2162678d819ea6c41dacec793ec4826eee0faa5e85701bfa002647a16595d8ba6b6f587c26dfe3deb6416f93d812ffa2408f7fef610bcdf788451ab72eae25e5422b755a9abc6e12d23f2e0af671b2ee1b0815113c59984673adf513493f04dcb8fe6c795bc5ac5ce7bf882d8ce994b1ef7d29346b0afffd0f9a52b0f817bd62311096c8a31f6bc190fc4610f10264bc4198b2682680409a783bf62bdfb0deebaa0a0d6d6827a5a553772d27e3c11c43630289f8e9ebbba09f85fafe7c9c1f8a2566e4de7ddcefb0ef47c81aa88e1ec99d25e4bfdca7f218577c361fd3a93940f8d13379146464039aa01be4b295ca7fc812fc728f960d779dd764dc1488b2aa5cc6a88677f72d4822772c7ab70e0573bda0f5c1ce94c20432fc5ed78f640a3806e8a76e196dfaa715e2da15ad58a3528c956baa61ed7782875fcf2fc2bf1bb289c65a05fcdf0d0553b8417877edaa1f1c837a7ce836a39dc6f8763e0af58473d6b1641f31afd72e377c82d2201cdfd16151538057e1fa7c420c7e7954475711a8dac81f6d6e5706b0469ef06b7a7dc77d2ea4c2c18f2c21832132b44a79b42e2c95923187a846b852e8a9aa9b6ac39440a0dc80ca4330aa6eba272034d65f5dcace0acaef59db6d5d5774ef1d3947db8d5db611a560b323e6024e4784b4df4511f2388b22768cf8a28f196fe7e1e94aceb963602276f54c4a2ac51def36998625b2f9f2ee20da9472895efe7ffc0d0815eb31eb4da944a7ffb3c10648a452b7ca0b00191abe4f1409a8aec72bf3528012e59de2ed55d1210035a2079eb25de624fe4355d4462b07ffd328d106f397923a5d9c5de7fb2815d28ea5572e6aac045980ad30b7396adcba2c364c443e392ff95be0213b11acc5a0e676ce398af659bd5d7cadb089e39a444f50ba9ffec29937daf4bb5330f994b1ab3b5ae2538a77c0ffadfd13906745b9f175ebcd7bff9f46c21e39bfa073be6f488661eadae85adf6ceb2e283ee8ac2f3c6b578a5e8dbef80c91ce2f7162fa928127de0533fb75ff33d3deee4199edb7e9d0075379cd0e6fb7c2d93d6639afc6a888788ee61a9557243cdf245b3d7880eb12b3e4ff6c06aa31b963121ae72d563b2aa6eebe3b3b747baede9ab931387af650c9df9da8cfae3e93ea3f261299d1236f007080f71ba4ed175a71a8ef601ed1b82ac21d74e33478c619b873f8cfb9ee1d868c2b22cfab66214bd65cec76a9ef10b1fd6a915abad2fd73c92bbbabcfce7d84c0589e566b8b9793a09adbc22ee526565406b4d606ca3f9dc1470a91585770427b08f966e4f44892becc0e990f904d945010b8c00850b5848b44bf8758eeae7bf5128580db7ea029b8ade9bbcc2bbc4cab5f6a2215822337d15b77b7ff20d15f8a3162a7eca0e6e7af0b125ee5a196dde48459b4b9797b1f964194cb208215841fca863a66dbae824616346fc162a83dd5592ffb442425d3738d432c58c309a9ac5bce3468865a1a5bbca3a38c9c3fc7a36da77a3f976b06d89e90d5ac435fe942a7be18e51a54595f728d9ad7bf327944e60a45b37798b1e320d3ce003c2625c80cdc4d3f038e64e64607b8c9d0b1d156422fc8828ae5b99fc4c9c6e98bd10ef56b6a2b2d36dfb37dc3fcedf7ef7661621aef2b895964e08e77311a7b29488c03701ec8eac385ec35ac1e2f292fe6c1900e80d1f92149597720509c8f5cf5097c82a4228bd8a288afa4b3c485f6fc3cc08225ca2da31d246aaca0580376fe2a76fb4052544cc480255ce2b0288728e77f4edb7572e152d7044691fa78d6f0aeafbfae5bce4c5a5e5d8628d25f83b91c395097fad4f12f6529fb134b7d335a96a650512dedbb456af093f7ce351952319d43daa8572c5cf2bb199da165758bef0dcbd52b6066686582788fc988dc8452c371552ae13b7bf8491b7d0a9dd86a1fd44b169e85d6c701ddd0150753f893555dc0cabe618e76c8955dbe86a2140b339daa4774119f1571fd2f42ce46566837843d36f34f8644beb30e357908a24cf3d196f898d0a2dd72644c867ead1745c159c7ce52049e9cacdada092a3a6500dfad8f11791b1179af027cf4a8644dc69398a38a262e8ebdfc6f961529949b79b4c3d68ff1079def7cdca42d5a456c1645c4b4e0d7d33d3bc117bbdde04ca64a7fcec9702638604b9731946e6b70fc45e1b2a59b0b989bcd2cbb061268ba0081b473d5d4674eb027166989f6fd82cde425bbb3b9b2ff246b964ed119613769890836916dfb8d2ce9125965ae443cb71869b4a59aaba597a69f3a994bdd52acefaeba69862c9232ca169e119f1e100937c0f1c666a84ad48d69835371cc984dcfe404b71d2fd4af020ad12f1a3f0ab1c01eeac83f4e7d4deb4278afcb522aee08449b6ccfc998b91da74a1050e193f19884931d4ec81507c330b09f995a31c97edb9caf83108302944fe063b9869873682858ac2d52fdba71aabe1edd9ff34f27e31b952c565daefd36f42e02f1918ca06774f03b2627b589567f125ed9319ad02b19d62b06557f3dc34b02d7579b4d6158ad5caba705c5a522f85a03f41430e521166e894ba673e916b95c0e29f67c1acfc0b44f309fd9426d915a9bc63939d7cc1c18a33de355af713b16d9dbf2240489321c0bea05f5f36910cb2215e2969e314196a3f454c3a0e6a0313f9f3af3b9489822db4a5b2f77027d1152b3caf5b5a17600a3109076cf0c60e8ea2a07362c09ab2b8f972c20b1ef341ce10b808b37a0df7607457595113bbae00ca2000d39c4c0aad83db67252d925061ec67a721b0d5f1905b9b3af42d44f5f7cd862a3027a0e9e3b5ce7c571136f74fe302d7031dd0cfc80566a1c4dcaa63f9c371aec25306b406c245a29a943735169ffb0fb9be8b77ba5a50168be3cbbeac5bcc68a87b718ca5e1f11edbd6b8e8efecd1bf7f93754aa31878d1fe64fc1b7a8836dda05d336a7d299cc0d5eb66e137e6c14cf390f337a4282dc03ac63f5a076f70b84c04e31426f814bdf0bfd185aac69915e6ac13c1db5f71c39e30471abc48b1ccc18b2d276a1770db53d89e3b2c9f3fc3ee3d2451894f717decebf51c4a45d050536f10e6e6de58ef14d8af5e2ea9b524cde14b9f93a408b5c6bdf5bdbf37e964ec1a2effc8b72330d7ede3c7a836c1648155845284c745cc6829a4c9464be48db0328f236725c2ea623061ae22822630cca7f2ca9d92d97692f8b44f344fb573d42ef56baadce99ce26a4531d1f325864c193784524075f75aed40bdde6da4fade9716eafeaa004f6f7cafa26f42757f0be9a6a167598c7a9958417ba21b4c19845860fde349997d5989a394038d64d557e6921b0f8c3ce431494650c705a21fdfa8f30cd99a7687aafae5b0f664a9437d9d8836b35bdc0adc50de67ca9bf87ce506d62836559f102f19850e3ea9fc5ef6cb7732ee00be0e2f1ddfc42dc1c5f332e237fdfc9730489e9e8a28ef817651fc7c33c8270a053769b32cf8db225426e135e8637a350604c53b417b5f6ed209ff53c1d1887f0c536eec8e0333b8ad4573a2b6a15be3c1291a36233e7ecae79e311cdadb64197830536f1ce5b52d67fd3ef1df400e17719eb7d979eea86284bef34a2632ae5bba9cdfd31490775a0970566f6aea618a51fbe1688ed3304ada78cf9992fc69c2dc2c4367f9ee0722f1382bf45e4ec1f8585ba3f86aa9efa66267696b7cd2252aee2272470b64111a6eddcce64d28ad41cd83f4895251733ab7b16e96356018fa9d902c544221021bbc5a8872002a0e7da7fb2f15dcb42dee017fde32427aed959e8c54f1278829f0bb1b868beba7ca8a30adcc16464023b5747f38ed04715006f446d4b6aad0caf8dd04a3186baa8ed3d4ae735fe478a9bb56e055d5e4a575ef8897d6aca4932d32bc1a602f083d2a253107070c8a529a7a13e11968a613c14d4f59d82d497f9714751ed749ef2353c3cadacf55ecc9b5ac36171f709e7f26fabfbad4d57affb4b9a3e2eac8bf2f3ee9759fef763afd6156a2294f973ed81845f31fe698c2b5d20c7788dacc884215a18c48a90681fbf07b94bc92ce361ee8e5c5327488541280f21cdea5afc3b0a59fc05f5c18ed8f1a5ccb396d8b8b58b0fd762ea59578a0dbc029109ad2bbbe38b90d95f1bf02b5aecea69e223f58d4060be80a91ccbe21e09080af8ca13995cd779472bb73f8a146c027c85229516267f8657d7408f36eadbf8fb72f74802735407c17f80ab582202256f5989fc72ba986318f23f456fa2b36b39a5ec90b727aad90ea5b6cff9bcce06ba3ceafd46c87295ac390b41936eaaa1e432b6af157eae71fcf6ddee7ad53b63c43d637d0630f99393bd155279e7078156371af2c94f2c24176cab731f73a5f39d97ea5e4e4e146b464b650527b80827860e6b401ff1291024746550ec6c3d7e1a0d2cc10f141bad465c2b7e0c7abe84053a47b68d5d5caf15799e24bad1f6cea89b51168419b86990c4b52f1c95abbd97acdbc5c20f0a6e9047f99b92e2351964a08416ba809149a4af4dfe4adf4e83a79872846088134a05e8fa660e58e4a4f2b55dc6ce6702f0b794e47fcc10bf3ee52c2237a3bfa26959c3f3a209a7ebe2649155e1c8e461f8d5621c8da12f0ee29aea56e4a81b066c772aa41d5c02c2c36c397904e07b8011e4107b12a68462b605accbec13a4513bdcb08062fc2e22360186609356ec8af05ff16b665ba2390e33f50d35fca71dfa6f33420d0251a721c0355379add263ba5502ff966db23c2c4b3810202aad506aa1867a830ac902b838b6875f54a2ed60c926cd60c3df59eaf870aa953155ad526835c463777508ceb4374fe65e207dadfe43e341f1b3f0fd40847b44a7dd3a2efad167fb13c32fdb837731ebcdbbc47a458ecaf998d9a2fe81bce2ee19ff8ae617e872f85c2b01d7f41c1f5a8045ae9bc5488176c1c8b1414750a2f579cbf90da4f978ed82252279559f423a9589ed064a1112e56e42a02fee438e656d077974e9a19483d44aa52b1a27b73a0e2deeb3b7a77f1aae8f5fe796de110aae6cda31189a2cfda1ef293f07c7ba5d99948a6b5f0a0fd884259cb4a28024b2e5ed2c853915342926718b50bc355b650fc462566c6b4e8c8060e0b9f6aece0378f24ab2e6e14fa692c623ec94e1565440d0832b50bb2b464df3b4d2c1acab0cf7e4b60cb4fec359553246dfb805042805d44e49064cc100a64eb3f891cc65b220a59be90327b84874729a2baa28288afd398f1eed0f42d22e7267e5ef853850d7ac42341009306bedaa51abc109739bbe22a48be3dce6e503c95f3feff930f108de30dfc082fcd56c4b56486c412631e020235c58fb6fb0904db67c0d657689a6610381ba8d20c408d4546b3b91f69efb50ade24d85c85fa4d56ff8159373285c1e726cb11422d22738554cf8b48eb8faadc1471dc238a42ba5a67b581089e24fe9a94477d32ac0478c22d3fd761b89fb6d3917d3f1030d275f0f59f90d10b2b0bbd56d4aa21a7f68125415473bc31326457b46ce5786e7fd98e4bd911b177d6f115757c1b1ec19c6d0818760464108c19a975942b727c44f7964d9a191781421574e051d2346a83d5dd8661747f742cb5d7d23b3c4d83f13b77b22e1a255f8c8199d1af242fbc6e7c143df1a1d4b00dde8deff6714d5979c2e2844cd315105fbd7b252d6852746000a76876db76a216e04f08294cc16b7bc8ca5f5240a194cf978216fb5dd3a9d80dd0e3e950c25579438e55a7c1c1f7b8ee265bc9ffdd1734940c52482e8ebc6b736e05e7e8d96e79497a065d56157502c276d3de1bb96463971a672bf67cae246b185072ef29c2848787875835553cc7b142602f5e726af35c24d77014947bcdda2a706d5b62ea04eb994425f800fe0e4d8c3db3aef792ab3103f702dfc415dbb47bbf87f125bad5fa632c85b2feb68a21bef2903d5d6a2a42c104ac8c40f652c8231c2ce435ad9d8a0d836c6c01d3eb41f5929efe0146d379572c28e64777edf347658993035bd10c222584351559bf43a0ed278539156753fac9d59f3ba14489b57220da0f23ecd54f9ba9e97fe50561d4a6112edcc5181b80ed62153867598e564dfa8d858551d7a3eeeec37c696a78e43bb37cd6e895d23c7cedbb94904b5da043adc1d868980aeefe1a33803b58e1a5596e8f87d836fe2c3b6c8feff27897d78885a1c336151ebfdcbd37a1c68ddf07931200e7170cda294e56f908168e595a69b197536b5859f3163ebdf4e54288f831100aaab9ecf12a59ea6143648b4358e3a7ec92ecba01dfb5f7073f1811f67b46b364b70384c950bb4237868e99502f60cd7d86dad670b1612529298d5eb2a95d94a1ae4aa0ba26af15a4dfbd9b82275b267abaab0b4bfbe45cfa8bc2f1f06186039b3e55edf47db039dd6eb2dd4effa131cc1b049d41f8c7823416e50cfdb307c511a3dced393b448c4bde575dd8106dc1098117889c1b115ae49004cc54f3b7cb7a3893306975436ec30a410402500e264295e94045a8a58f491816d37ee5d477ee4bff661c3b812d0b62c3cbe31f4c0ba71658217745236152a820314e87015b8b5c1d7206ba6e8a56e457ff2da966d7ad7fe455e7eb62dcf41a0669ccc6580387c80dd08e0174c3bbd11f7bbc38810ea9efd3fad0088b15b75bdbe39e840bf44dcc803a8d0c8719fce300b9c1fd29a3ebdcd1963dd17ba4a8ea661bf5568952c61b2ccf49e51fe098dd5db2fafd08580294e407a4cd29f5698e49cdf86b687b1a604ba76caee4590b461f12a9ab85c46a0bf82003ae5cd5634c6c9d7a091025227f5e9045a1c9479b51927f0cd0f918d02f971430450afe2ba2fc68d848e0382d99a8a4068c826e34766ca9808668cc04882eae2c2b4842e6db94747057540bd29bd95cbba1d6548d1c8c4a7691413641d8a0f6cf9769ba6036a391b49161aac2c3a77260e436b6fe307886741ff7e5562d1bec181ef6bc178b6f7533c978b7564b9f8b0353370887cf53858bba5fc49eccb6b776fe45f139f9e8be1572257447b68b41833bb9b543a69c1fe2a0a0371d181d2e6cb5b4cead2c5ea8bde6bb81e93a5aca1261853d062260ae1e127c4906ca2b6c161b149baddc6e6292322a5cba95076db712745d97cda82766aba171dd514f2f1040979cb9ac0bb54d6e095e8e27d33b525d706a9fd077dbec35e14eb5c91ea60fc234e33cbf32c4f97f00af9d57988197984d171583765d79078a163596ac84877396f7fea9f3715e5b2ba3303b1484333ac0827c4416a4c02ad6e8196ad818d40693e8949d7325e0ec93be62a3581e585e0cf29036e40c5bc58e5d080087058fa94f21695340b1c24432c7aab9e2b84525f95c8470a4901a10aeede02f1f693f87bf9803ccaaf15ede001c17b78fd619e543edaa439655266f55d8d6f0fbc48490528a0b274eaa67a93efca34a82816e38d044198455f304204252f04adbd28821e26b33302fd24eed8df1e7e4d6d988c8a8757a3efb37c346f6e56b140a772719392fde3234ba9cfb09d753db360266bd2ba60c4d1b0b1af229cc5af01c85aac129417c88c042c77f25dd3d9e4e789826b002c5b852cc50b518121362ed7fe3898df7b3db054a3808d7fe53a4236bab0a873bcefea4d2f9dffc4fd9ef751ab504ca0670493f25d38083e13601a3865b26d244865a25d4e0a16deb0c529f0a905468283e8e614f2e54517f0190c8f1029348cfc8d016172fdb2114745812eeea41536317e6eacb45aa7308cb9a002c9307a6cb990640f9a2aa682c90491c60c620a1b4b5b77ef9c11e79ccbc223df6de3a45b6ad03c2d877cb79872714c8351b7618c7789112334785bebeb1d7c67ccd6c447096b2350333731707f484625f5cbb8b0308c7b8e02645c47e22f8bbd944744d6653ab08b12969d22c69fdb5f014268aa2b448db0fbe9d1cc6c0c1609d6cf53e56b0eccb8402a53f488a38f59b8686943b9cc3c469409ccfb40d4945884abbd0864bd693f59754398b4e8a53a52e2ded1d55b2216a20ce7df0de77b0898723e225c01569dc65259f1d4011cb59fc2329820f33ddcf1f132f4b62cec987bbeaf295b94ce698af182de68fe93eba11a4948025e3cf03b427f23d53a17c93d5a1cd690612a3871dd4d73d70cadad397a0ce7be90834cce935a41aab7d76cf4f016b70125580926b6c6d9beba1b9de6fabf9d4dcc12611f2b778e5f6835bb1dcfd6af1c968483fc76f97dc09aaba75f2a0eaf68f42c471f0beadd3ee3308211151d2b17c565719fd98d9c4c106ecb279bf5120fc5c8ca02d0d60b0da2cb192a0f348f0366c1149dbe3474b3f6be3ba8f110c32e45b13f2ef82cc161af4a1474014e9f6a1d9d12df8add3a41d4d2ce51175a67d897586947e7d678fd76cc71d844504c68bc07a77cdebee8eedfa87db17e0e584733cc86bdccfc86f97fca2ff7a3077e5c7135becaa5436dc51e7de48129135f457a08de6b3badd8c20593f6f9f00cdad3ff433bb012ed8cac348f84a80b0e26c319fb02153833203bb3925904168049578f412fe1743bf627a7681c1734f1987182595b552d98bbd14d1cd8d08a5801f57877493d0be262b7cdf3246f4d482f44f4566c36bec2f97c2ee7912b24f4e0833f889459989ea7a92a77ba1406a89eb4d32b69ad646bee412a26dd01aa27b101e0669e81982eb97edc1741539e89915d046ae27c013d51139f885b22a08a5f2d6842bd0029f1c65c7378f89e1ef08c47d62f4fd2c4ea0bee1dc5831fd5f578215be4cf158e3b23aad9058d759b06754b0d61fce9c281f22f807c29bd1bab9fbd051031e800740e25ebeded9461a547308e2cb1bc3bc97775d0e410e7a4e5e46d27c38f25f2b9e0a97862df8583091d0f29613071266a574f24c5b35d25b259a08aa38247ef383db17a7f4d63dcf57904c9fba7eba103d1f346ccbb47bf9978c970f075051b5bcb0dec9bc319a277f97df0546188e44d6ffc8e7c7f36864f948b43c4b682c2db9a2fe8089ffae2d2161c8a72f9fecdbede28f1d4d4b31b6d0ee6067ae720d9ff3b2246ee88d2d7d18d013667288d5c491007bbe29f87a5e1b06c4b5cf2fed48caaa97c5eec529714991fe3c2569765bfaef164e93efedb07e12e0e1b5d8596c134d20053adb464de4ca3a7c88a4aeb40f86ffd83b16b58b0f84dabb3c3134debc97cd93914bd1bd9bfd2e5ab00f142c1252253abdff619c4d9d36f8679637e776888086d24d4b0a82e3143a93b4033ef331a13198fc103ce996b6ba6b030dd8e08b3a7f65ea573f09f00803632f8e2a4fc579d477c757c24ead803ef8824aa91b407401c94c4776b744158caf9a00c7299a3f7f0704b4b787fe06673a6d7a136c9e6ae431d8df4a85b5a94b3fe99fbcc90f8923c83ff8864a83055e7a4fc2f2398221207505947f1bb9f5ecf2815b564404c467c2ea50d30ed003606316e87fc50f49dc04162f890cea0dca499632658be10d96cd2328b26c19feaa042989708d219bcc7e695d0806a4913ad95dd7d688a424acc330ced1e55d84abb8e3568f70f0cede3e3e886d652449e5e793d79be7fdabba0eb1289b7207b352eaf7820a6048d0ea1db9c2514494ad06189d5e9a0fcfd70fc14e0e9d28fdf695b62fd5c674b94078ef94df6989175da14a64fcbfbfa0ab82b0f6844b955a82d7cdda9f6b739921ac2f447c0e41f24eb622ea125442b57d6b939b11f361335de13921641bc13848adcb818efd14a6f0bdde7f1187c376690c58611280ca6070e11100d2f4110805695e1db36e92642c064b1b615a8aaaaaaaaaaaaaaaaaa5a96686408000360dbbd8e03a22ce0302000f3f07ddff753e6856892802392c47662dbb6ad255ba6982d8c2dcb2b0f215dbe00f821dead19f14c2addd9054f95c2adddf04c7a7069743ca788b833209eaa8d1babf349dc9d3fa529f19c627365543e397c7efcaf6e6d80e7d423972fa21ffa5d5a04cfa9db735a7d4d825b23e199a4e0b26fbe732e5f3efcd0075736c027a95c1a13cfa936cfd6222ff4c5b3bce2851478c224f9a1472e5d08bc909c6739e6855e972fa51fc2e039a59eb6e5d923bec91b53e493b3cbd6d40b957165c24f66f07c85ce7e782a369e73496bafe7d4d3a5ed9e53f349c8ad49f04c06f08c1dfd9313eeece8a9969e2f307ee8cdb3437c2379c684f8dc085796f554095c19119f1ce3d602798af19c92e1d6983ca71479c2d8f8a13d2e2d83e7d4015746c327a7b8a4e1ae1c0fae6ce993383c5fe3db7bc6e60f25af0ceba90a78c266f821302e6dcb73aac9b3a4fdce0477d6e4a9b03c5f52fc1008cf1803ff04844b171a3f647b965bbc5094a7d3ddf93da95ecf98ed9d287065749e0ae8ce5078aa2aee4e01cfa4245716c853fd7c353021794e559aef39e57a964bde46c195297db2862b7be1934e5c19139f5ce3d9387eee5c1a17cf29169e650d2fc4e419e3e173213cbbc68419f1436d3caff3bde0595af04caa3cdb436b563c9326dcda13cfe49be7bd7fceb37cf23633972eac1f4ae0ce644fd5bbb2003e09bc7c35f1434ab736c73339c4add9f04c22dd599f0acab3d4e3851c78f681ee049f54b1cbd7cf0fed9e312e3e57c673aa99f3c997355c5a9be7d4d1a56df19c5ae1cea2782aa84b97113f543e5d55fc50ec5936f142055cd99c4f665d19934f2ef09c5cbe55bbb50f9ec9056eede7d41d4f57103fd4a78be885e878ce1c4a23e23995e6caae9e8a80cbd69c17dae2d66acfa9a8e78c8caf32ba744d79a13d2e5f3b3f647467569e0a842bdbe29379dc5a966752805b1be499d4e2ced63c1511cfd94567003c15954b13e43995c5a56bf7424dcf17153fb4746b5e3c932e5cba2c78a13faecc824f2a5d99eb93454f9aedca41ba331e9e2a8d4bab7a4ec971d922f34222dc5ad63369c7f338b3ace28512b8b3e153d57065607c528f67ec827f52c5ad099f49d9b34ce06d6f9e31399f8b7ace375e26e6d2a63ca770b726c23339c17366c5570d5ddad5738a8ebba3c03359756b413c931f5cda22cfa931deb8b53f9ec92aee0e044f2adba5b9f19cf2e1ce86782a38ee8c89a7c2e3d99eaff1d215c80f053de7224f9be0d696782699ae4cf6c9039e65062f545e99244fb5e4592ef0b702eeec81a732f38cd1f039102e69095c3966dcd9064ff5c22d18013f14c4a5d9f19c32e2c61cf9a4ed72fabebce2d68a9e53903c678d7c150537c6c8276b97ad065ea8ccad4df24cbaf1ec0f5f472e4d86e7d406cf79c3b70cb92c9a6f1f9796f49cda5dda15cfa9139e313b3ec7c765d9c50b4979c680de4915cf7bfe382e2dcb734a804b5a942be78ce716fc8d5c99204fd5e7cc8cafca5dba98f821d7a5413da79cb834129e5314dc5ad53329c795a5f1c9406e6d826792c9b3e5e585966e4d86677283e74b8c1f82f39c167c6be7d67ccfa4ebc6684ff49525f149349e7de367edd208794e6d71676e9e4a892b03e4935877a6e4a9a65cd9fca4934bd33da7fa8455fd9024cf58977f32c573b6f1320d9eb1103e17e6d6da3c9347cf52cadb74b8b2dc272bb8b5a1e754239796c5732a853be3f254223c6170fc501fb726e6994ce0d686cfa4eeee103d938e3c9bc1b7e9198bf24fb2dcda22cfe418cfb9c5bf08b874055fe8e9ee487926b1aeac804f1e3ddfe10bc0952df14935ae8c834f8a70e92ae387782e6be6cbc79539f1c936ee0ecf33f9c79d45f054672e5b422fc4c1a54b8f1f5af28c397d0e92bb93c03349f58475f143729e4d63b69a7821216ebde4f8a114eeac82a71ae11963e173c667e7b4467b4ef5716b4d9e538bdc19eea91a784ea5b2043e99e559ae79219e5b9b7a26dfb83bc22795ecd62bf94335dc98205fc453c9f18c51f04f5eb86c81f1424e5cd2965c39c4e75395edf1c9a95b13e2993cf374e3d9265f34b76008fc9010cf18169f0be339f3e3abaa5cb6782f647cc660f89c993c9ebf50da99e714035716c127912e0dcb730a801b43e493b11b1be493f3ce2478aa36b7867b4e0572490bba728ab796c63399c37372f0ad2fcf73f82ab934109e53539ee5102fe4e4d982e485c6b8321f3ed9c5f332be526e8d8d679287e79c62cefaf8aa2997d6c873ca8ce7924c9792177ae3d6e43c9348dcda18cfe40c9716e739a5e5b204e3858c2e6d8ae7d408cf99c4b7ea3c630afc132c5736fb240297af187ec8f82c6778a125cf12f94256aeec8a4fdaf16cc579a1159e319f7722c4738e304b3e5ee88167a57cdb3ccb235e68804b13e23975e6d90af3424ccfb2e985187836f88d7367463cd51c77f6e5a94eb833354f25c4b37ce18502b88445f043483c5d2fbc509de77f7caf3c67687c95eeb21d7456c3538971770078260db9b5439e277cd288cbe25099d5533d79c296f8a1379e93909f89b9359fe7d4209785e4670297f6c373aaccad571f3fd4c225ade8ca21e3d6e6730a8f671df979c0952df9a4f0d2e43ca79078cea8970172e9da792136ee6c89a7927369569e533f77563e95944b437a4e193d5d3dbc50f2f2a5c10f517069833ca7b4b8b43a9e53455c59d3271f791efc0579b62c7821109ef3e965733c678a7cd504cff27c895706c3279fb87c2df9a1de73e2beb4726b383c93c3278c871f42e3cea23c5506cf560b2f14c3adb5f14cf670d9e3778f3beb792a076ec18c3f24c5ad95f04c72b933314fe5c2b384f236146ec1603f94c3f3c5c10f597065c44fa670655d7cd2e9d9bae1856cb8b2a24f56b9353c9ec9246e8de739f5c7a50bf6426a5c59ec93063ccb355ea8f79c4bdfc2e3ce664fe5bbb3119e0a8a2b0be3937b3ccb435ee8e8d6889e538e5c59119f24e31933e09f4c794e09bed53b53e2a9ee7876f61dde5ad43339c5b3bdef9b6719c50b1df05ce89773e982f24278dc5ad233b97bc65cf81c99e7ac90af92e0f235c00f016fbde8fcd00c57567ef2c98d497d72e7cac47c12ce95c1f9e40f97b6c0736a7665653ee9c2ad81f14cc2707724785205706b4c3c936d6e4d9167528c670c8dcfdd7169bfe7d4ebd6f67826a1b8b3a1a7d27263897c52766b42cf29a9e7297c6bcfd60c2f44c39585f0c91e9e33a7af6ae0f914df012ead89e7949b4b4be43915c6ad29794e21af2cce2781b82c8d2f24bb339ea7123e63b11fb27a2ef5ed726b679e49062e4d92e7541bcf56d10b8db934119e53135cd9d3272379c6c4f81c1b7726c553e97177187852d12eadf89cea3da7244f8be3d6087926b77896caf7884b979b175ae479f1b77a4e3d5e1675652d7c92894b2be139c5e5d6a8782649b8b535cf6404b760b61fdae1b29ce38582b7267b4eed7165853c55ebd62c7826899ec7f0ed79b6a4bc10f1d225c70ff93c2bc1f78ae7af5f8d4b83e33905c4650bf9425ddc5aec39a5c7b375e585d05c59964f96b9b5029e53923ccbf9b5376eed80e7d4d4a5453da7a6b83b4b9ec944aeac8d4f1672e962f3428adc58209ffc59255f33cfd6132f74c43396e59fac7067c4a7bae1ca14f8a496cbd67c210b6eccea934c9ea5232f94e5d612784e51ddd90a4f85c595493dd5ce738ef916067796c353997165757c92914b4bf39c72e0caccf8e41fb746e79944e3f275c30f9179b68678211e2e5db3175ae339949f8f5b4bf34c3a7067063c95974bbbe33975c4e50bcd0f8579f6e75be6d939e65f7c15b8b5359ec91d2e5b83bc101797f6c673ea873bf3e0a96878beb8fc5096e75a4a98d30f097265489f2ce11973e3734dcf18189f4be3caf2f8649dcb5e95d6c673aa872b6b7d72804b1a00574ed273e497824b333ea77cb7b67b26e7ad2df04cce2ecd88e794d213d6c40fc17169333ca738784ea1093be4871279c650f89c075786fb64eed9627a2114eeceee49356f8d80e7542497d6c073aa76652e7cb2893b3be0a9bedc5a19cf640d97167c4ec59e9de1abc865a9c30b05dd98249f04ba330a9e2acea5f5f19c92e2b9c73326c7e7a02e5fc21f82e01983e09fb4b9342acfa99e4b43e23905c2b32ce06d6d2ecdcb73eac933e6fb276aee6ce9a98c78963fbcd0d0b3077c979e93ca6c7df042235c19974fa679ce2b9d4df1547b3ccba7176ae0ca10f8a404cf92cb33997265597c52ce73d6f1b20eee2ce9a96cb8b31d9e0a8dcb57023fb4c09d85f0544bdc8281f04355dc199ca76ae2f235c80fbd7063b527eaa541f09cb25dbe68f8a1e33366f44f3cb8b52ecfa49367ac837f22c88d4df24925cf980d9f63f32c237826b3e76f7c7f57f6e5934bb756c53359c29575f9e49a2b43e393732ead8be7540bb7a6f44c42f08cb57e88ead9327ec29ef7f00de0b2f4f91d3f2e5b5abc1013cf991a5fb57bdef475e0eedc9ec939776782271593e7cb841f1a3e0fe2bbe45972f042ae5bd3f24c2e79cee2b7c63c63797cce8f4bd3e13945bc33364f75c48d657d52e8162ccd0f5171f95ae18788cf82f9e2f16c2dbdd009b7d6c33379bcb5289ec9385776c853c12ecd8fe7141597ad345e288a5beb794e0972778c9ec9ace71ce35f793ccb375ee8777766cf241f4fd70c2f04c99d15f0545daecc90a77a3d5b3d2f14e6ca609f2ce0caa8f8e41c97b0337e08ead2b4784ea9706b743c93443c6716ff2aba6cc55ec8cbad9df14cde7065833cd5bc7499f0428d5cc25cf8212f9e3bd29ddc93eacb8af00de4eef43c93825c599da752f29c405fb270697c3ca7a2b86c21f2425e3cfbc74f00ae8c844f0e7165519facbab43f9e53553ca76ec634f827739e4dcfd6082fc4c225ac3f74c3ad69f14caa7077809ec9422e0d8de7140e77c7ca93eae71923e273243c7fe02fe4f922e387e23c634cde891dcf97193f24c2f319be3ecfb9c4b71eb93b474f2aa0bb037c52c1ae4c8c4ff271e7edcb2acfd804ff84856719f542103c6793dc9b1477c7f7a4725dba6e2fd4c6ad019f49d895553d15d173eef02d45ae6c864f4a716bbd67b27567b7a762e0ce7c78aa35ae2c834f86f08c417d6e92cbd6182ff4c465ab8b176ae2d666782639789649bc50d1b3f3dbc19579f1c9a7bbe3f34c0e7267183cd50ab736c233b9e5d2cc784ed970e9e2e08504b932db27a55c76929f0a5c19199f8c7ace05be94e31286c40fb9f1ec183f5f57f6c327bdb833dd53717069639e5352eeec89a772bab3254f75f49c71bc6c833b73f2545b6ebdae7ec886e7497c852ecb1b5ea8c9b384fc5c72698e3ca7ceb8b4de73aaf53cccffc8b377fcbc3d637b7c6eeab9983f923b3b3e950ecf191b5fc57b966f5ea8e7ca763e09e5d906be233c7bc5cf9faff996972ea317cae3598279a1dedad53349c79d3c5f467065523e49c19559f924f1d235c90f19f09c517c6bea59eede96c433a6c3e7dc3c6fe3eb7b9ec637f79c67bc4c7777b03ca900b8342f9e532edc5a9c6752cb9d79792a139eb0457e6891670c837f62c573d67ef22e0dcc73aae8ce3e782a1f9e13fd783c5bfb263d6137fc901897ae342f84c8f385c50f315db69a5ee88a2b9b7aaa264f97d50f21f06cad7921132e6d8de7d40e9706e73995e5e9dae185a62e5bbf173a5e5a0ecfa9a45b6be099ac3dcb392f34e5d6f87826a3b8b5169ec93057f6e6933e3c4ba617badd8231f9211f6ebd22f9211aaeccc92723b8b2313ed9c79595f049222ecd90e7941797f6c573ea852b83e4a902b8b32a4fb5e6ee50f0a40a7abe967e48833bc3f2544cb760b41fd2e1ce9e3c1505cfe9c8d338b8b5139e490b9e338c7fa571f962faa10d2eed85e75406cfd9f43239eeccf554b94b1be139b5e539a79e26c71316c30f7d7169813ca7b0b83436cfa92acf86f1d375e9c2f2427d5cbafa42683ccb255e88804b5be13905e6caaaf8241d9796c273cacba52df19c62ba330e9e0a86a72b87179ae4ca783e19e5d92ae1855ab8843df24375eeac89a7cae3ca24f824995b73e099dcb93bae67d2e93963e8ccf6540bdc9dde93aa7569793ca794b8340a9e534197b6c1734a812bebe39354cfd6092fe4c23366c2e7c63c635a7c6e8ca7ebe98704b835db730a902b33fa2497e754a0ac5263857cb275d9e2e385b2b8b2de27bf5cda19cfa91b9e2d475e288c1ba3faa400cf32f836306eadca33e97365683e29c3dda9f2a4f2b9b4189e53626eed886772cdadc5f14c06f16c025f3657a6fba4054fd792178ae3d21e794ea97167c0a74a7acee09771dc99efa93c78ce395ec6c125ecea8726b935dd33d93b3bf3543fdcdaef997c3d19b934329e53345c19d32775b8351f9e4932b760587e48893b7bf3544c3ce70cdf2ae4f255e587aa3c6364fe0923cff28f178ae0d660cf29a84babe13935e6e93abe10f2ca7c3eb9bbb539cfe415cf19d4573d70638b7c927639fbe2aba23cfbfbc2b933089eea83cb3285175272f93afe10985bc3e29944e1d6829e538cdc9a9a67f2814b17d20b0d72eb65c70fa970e9cae28766b7d6c533d9c29531f254b5274d7681c4784ea2f205fba128b706c933b9c6ada179261b78965eca529217da72f93ae287d25c5a07cfa928b716c23389e5e96af242723c6179fc502057e6c1274db83b3fcf2421cf32cc0bcdcb2e7dffb8323f3e697567083c159867abc90b6df08c19f1b91d2e4dcd73ea8167f9c10bd16ecd83673277f9baf243569e0b32636c3ee7e5d215e685e65cba52782147aeacca27936e0d846772ca93b673e58cb9847df143783c4b372f84bbb53ea7e43c6122fc1016cfd28317825d9af039257b4e2b8d11f2c9f25996f142ba2b43e193475c19149f7ce3d29a9e534bdc99f1a972783691b275c50b2d7161757ea891274cea8718b935de33595eba5878213a57d6c897304b352fb473a7edcb29cfd923f716c4f3f215e5871878ce18f9aa2d77d6c153c570673f4f05c1a5a9f09cfa726b523c9322dc99134fd5746b609ec9a2e7342a5d14bc901fb7e6c23389c1f365c50fb1b9b39f4a812b9be0931f5c59984fb6b93b113ca96ecff9c47ce9dbba33219eea8d670bcd0b9170696e9e5357ee6c86a702e3cac67c9284e78c8aaf0aba341f9e53649ead1e5e2887274c8d1fd2e3ceba3c5509b7767b4ecd79968bbc1096674c8dcfc9797ec317e8d2f6784e41f12c1e3f7177678127d5ecce983cd595672b83176af3fc90ce4078aa222e8d85e7d405cf191d5f157cc67cf81c9c3b1bf354323c0779f6d2e9d235c20b493de72d58053fc4c49529f254b32bebe1935c3c67707c95efd95af242622e5b7ebc9016cff128610efcd0114fd8143f34c795013f19e6591ef03637cfd8d03f91dd9996a70ae1d6007926adb874d1f921026ec1743f44c4b34fad3df24caaf17cce84e3197bfd50d5a569f09c42e0d67878268d4f17213f44f47c15f043c1cb56d50b99f1dccdf775f942e18792ee0e02cf64f2ce1278aa0b6e8dea998ce3d28e9e53404fd7153f24bbb3d753e99e3331be4acaa595f19caae1cee65345b9b52b9ec913ae6c91a7a25d962cbc100057f6c853017067473c151d972ea91f2a7a4e00ca17ef871cb8b50d9e49059ebd4d180b3fd4c5254c8c1fcae3d952f342253ca7976ff13c6944578e189796c6732a87e7cc90afca7263559f5cf2a495f7678c6749f4360e9e31323ee7c6b315c50b21716bc16732f68c01ff89d2958df04921ae8ccd2773b83b539e54b8672b86179ae1ee64795209f03c8e2ff03943e4abb4dc9994a7d2e016cce78778b8b40a9e5343cf1800ef848e5b333e93bee755942dac173ae3d26e784e79f02c2578260cdc9a00cf29449e13ccb704b8b52fcfe40097b380394f9813cdb7d278b60a7821a4e76ce15b825c59d0271bb8b430cfa902ae4c804f06af4c864f46f16c6d7921a56799c60bf19e7bf0535d99964f9ab9b5d673aae9f995cae47cd2916779c60bed2e5f667ee8824b33f39c12de599ba74ae25942f24213dc9a1bcfa40f7756f454155c96afafc9710b36c10f2df16c1d2dd8971f6ae2ce04782a2b97303d7e68904be33da7ca67a3f85e3d5b09bcd0f0ee3cf0a4e2797e46693c3ca78c97d6c373ea7869603ca76078cedcf8aade8d35f2499e2bfbe09330dcd8d42701789641bc10d1659368cd89673284678c89cf55716b46cfa9ac2bc3e193573c63227c4ecc7366c757099fa5ec77b45cbac4f8a19d674ce9735c6eed8d67f287cb16d40b617167424f95e5d6a67896cf641e97f6e53935c0a5493da7cab83b023c93883cbfe3cbc0e52b881f3af38c11ff8922b7b6c533b9c2ad613d9375dc1a0acf64976753f8229f7f40ebfd11e3d22e784e11f02c85de86c1b37afcfc79b6a8bcd007cf12cd0bd59e5de02bc253ea49a35d0182cf19e65bc22b53f249df9dc1f0545d3c6355fe099c5b63e199bce0e9a2faa1039e31de3f49f32c736f23e2398768bdf2f8a1156e2dcc3359c07342f2b41d9e30383f74c5f3317ff21953e1734977a6c3539df1ace3ce909e6a865bfbe1992c7367404f15c1ad99f04c5670657a7c72925be3e29964e1ce5c78aa2d9e2f2f7e288467dbf8124a9b7a4ebd71691e3ca7729716c5732ace9d9df05454dc9d019ec947ae8ce89310dcdad333d9c4a595794e052f5d87fcd0933b1be0a9b85c1a0dcfa90e9e2d282f9474091bf343505c191e9fa473e9aae3877e9ee5182f94bbb2a44fa2f09c085476c027b15c599b4feef0fc886fd0ad95792683cf72e9856c7786c35395716b3b3c93c5674bc90b65f0845df14375dc99d153897996715ec8e7d915268c8e1ffae3d600784e1972672d3c9516cfd800ffa4e8d927be56b796c13379c0ad21f14c82f08cc1f95c0677b6e5a9e03c637d7c2ef99c893c4d824b3b3ea77ecfe7e84e9f4939cfd2ca33e179967fcd8de735cc3ea96c884f8a7167413c951b7706e6a95078ce0fbe85c6a599f09caae0ee507952f53cbb65768bca0879aaf2e9faa1b4079e533c77278067f29067d9c03379ddd9efa986b75e80fc900bcfd7ed87729756e73995c6b3e5e68552b8331a9e2a8c4b17173f44bbb1d90f5d5dda18cfa919ae0cf954aebb339f493c6ec17c3f54c465a97e42b934149e535d2e5b6fbcd014cf5a306315fc13189e311c3ec774f962e3874e7896b6dfe1e3e97af24275dc9d27cf649d4b83e23905e7d6247926db7896549e49edd2a8784e91f064e339a3f3555cae0c824f8eb96c0ddf452e4bacac894fb2f19c7166cc8fcf515d96492f14bbb2359fb4e1d66a7826c73ce9784e3c5e86746b539e49dca50df19c4273099bfa21489e30e40f21726bc767f277674c4f85c495f57c52f78495f1434f4f57d20b1172658e3c55cfdde13da9ca678c807f52c073327d2b8f3bcb3dd5067756c25349f18411f24387dc5a18cf640ccf99c6cb7acf394bd7971702e41296c20f6d7165407cf28b2b33e29365dc9a93e7149d5bebe39994e2f215c20f7570e9eae38798dc9ad43359c63306c4e7e2dc9ad333c9c4ad01f14c9a791ec617ca95e9f0c92c9eb1349fdbf22c9bbccdcb3386f44f06793e4267493c951db7e6e699bc7265537c528e6729f542123c5d452f64c71396c50fd9f19c49dfeae0d2b83ca7849e65222f74e5d6a43ca7b09ead1a5ea886e7907cc33c6180fc10f2cacc7cf2855b6be29974736b4bcf24953b43f35440dc82097fc888a71cb7f6e69994e0d95d673d3c951a4f581f3f44c8dda13d937d5cc248f8a12c2e5d4ffcd0ebca8e9f64e1ca3af8e4087707f74c06f26cbdf042323ce7a3b3009eaaca9dc9f0545f3c5b29bcd00b9756c8738a8bbbb3e549d5e4d210794e81f16c163ffb74b5f143b81b7be4933d9765a20533f343535c19224f15bb32de27bd3c5b40653c7c728b4ba3f39c42e3d60a7926b9b8b5d9738a8fe71997b00d7ee889e7aceae28c9ea5202f44e5d29e9e534ddc1a9967127865737c52915be3f24c0addd90d4f45c695c5f049289e8de05bc28df1bc93042e5f6ffc100a9716c473ea834bb37a4ecd71650f7cb283e7517c9fdc5a16cf640acf18099fe3e0d2c2784ec57065c14f62f09cc9f155bf2bc3f2c9e3a5bd794e49f09c7cbccc8f3b2b3e150e97c6c0738af634e439fff819efc6ae3ed9e4d692cf241c9776c273ca824bd79a174ae45916f1424fee6cca53a1b9b3099eeacd95d13e99c0654bce0b597165677c12905b0be03975c8add9f14c1af174155fa890272c911f52e4f9daf243123ccb275ec880e71cfc92dc9999a7eae1c6b03e197469383ca786b786e59904e019fbf24fa8784e31dfeaf29c4d5446c72717b9b23f397469553ca74ab832289f9ce0d2f0784e2571657c7c32796baee794d3b325f542605c9a0bcf290c6eec904fc2ae6cf8c913ee8cca53a5b935ab67728e674cf84fd63c5bf45d737708782623b9b23b3ed9c89d0294332ebe0acaf32bbe043c5d35bc50244fd8163f74c7731e51b6862f04278de7fca1322c3e79c7adddf14c1ef16c15f1423ddc98991f0081a72b801782e3d6187826697727ca337975e9d2f242517746c453c571e97ae085f4b8322d3e89c79ded9eaa832bcbe193585cdad2738acab324e485aa3cdbfa8eb9b3d653195dbe827ec877d9aae385aab8b4239e536b2e4b3b5e487865429f74e0d6bc3c934f9e738d9765f06c00736af9567967649e6a874bdacf9533bc3bad67b2e959e4ac50395b9579f9240877b6c05319efceeb997cbab42ecf2927b726c83399c5b3f5c30be970eb05f5432c5c593f49f47c8b2f02cfc6f04de4d99ae2859278c682fe49eb593ef04c6277d67b2aa45b4be199f472650d7c7283670bcc0bb1b935449e49309e31293eb7c59dd9f054635cda24cf29372e613efc501ab706c73309c42d58951f4ae2396ba84c8a4fc671e92ae085eeb82c4d7821a06759f43636b7b6f39cf2e3ca6e9f34ba330d9eaa855bcbe1994c7ace06f92a2ccfb28d17f23dfbea8e01cfe4245746f5544277c67baa3177e6f3540f3c67d19736dc1a94e794d5a5119f53bce76bcc0f75b96c99f142505cd9059f64bab52f9ec9172e4d82e754007746f454133ccfe27bc0a5613da7eab833119eea89cb17113f84e6b2557ca138cfd7013f24bc33069eeaf8ec95af15cfd6f989c0b3257c0579ce154a58eb8770b833284f85c19591f9640bcfd194f6c1736a81674b921722e3caae7cd2f82cf178a105ae0c8e4f1e7263c84fba9e37f125ba7ccd7e48ca3306c5e7b2b834209e53669e33886f49cd65b3e572bd5aae5787cddbd355b66ecbf59aaed70ce66a7973edb45c2f99ec962b2673b526cce59ae5abf3c0e6ab7cbddad6ab352b4fec75eb268bf5f25b9d00f0c8666cf684cd56ab31dbb2b65e65ac4967f91dd627ed393b97d5663ff6baaf12567bc564b198abbc1300db973bb4dbb6d9b342f317adb3e8d9a5102c00da54d2b66c6fc0adafdddaf9f5dc29e7ce38209edaad79ab8c7d2b5f414a5e3cf7f028d9c925bad57fee6ded9a560500d90db68bc9e504c462d37edd66c973edd6b97b004aa02cbbb25809746d5c00d37e80390141c78c76d1be577ee03e73b8e2b203e0f28e98714f3a00b7803ab9e79f5d2b31c005a0c7b811a0d43fb84d2ec70de53a6e0d3c96ffe71f9bccafbfffff4eb9f8ba9e47f1bf9311b9f5eca35978fe799482772ac320fce544bf66bbe5d7cf133ea087fc84a025e67f9e5a1545440bec1718e44be220b7a5805c4687ecd815b27248889ac810e44bba881ad68bea1c0490f50101b9ab0a422a881472a245a28e1582bc1c20ea268a406ef3450d830079501c519da30479f925ea28be4076ce0b398c1164e5bc80bcd4459d8bf2476d2920875989fa894290479105f2a026646d1644f5cc0ff91388208f05809c491dd9b04790bb8a40ee0202d93945c8615a909744e455424b8e9244be2480a8977c1175901ec8792438734eca9c9b0061fdc0915ed2903f6108f2d713f2a04490bb9c88fa8939c8ce99212f0b88bafc00b96b0de4371aa27e4121e77923ce2505513741761714c883e440564e0c51c3ea445dfaba6b07e46512222d43401e0409f2271a4156ce09515d0284ec5820c8637c205f6242d42f31c8a1d002f60b10e4305cd13c59ce748e1364f1a8821cab083911b29d03849c278e38334113f51239900300249b8915d9a551d43128c883ec886a0907399614e4af1fe4510e41ee422380e28a3c2644d44c1e91fd1a24ea12871c068cba49212d218c1cf28b0fe4310090f3c01167980451976690cbba202f8dc87340c40e2a04b9cb0ae431395195c302f2a03be2380a3490db5440ee5a22aae51be43127c8cb1bb24abc801d7b82bc0c206a2239c80ae080ec2687b47300401e1409f27281a84b17f2979727d71a800d3b426e0346dd8490fee222b48b89a86774c83a270064f1b0826c000bc03ac706e44bea40dec408c8cb600f92833ce607b23713642de3207bc687bce41275ac09d9393ec8f26045dd8491a88304418e45843c17446c011640d68702d9b13990334983bc54421e4b46fdc421c86341441d940772ac27c85f1b202fa5440dbb8a9a678233ed4944366c11e4a598a883d440d63641d4e59338de8943f6122ea27a889ca8ca990279933e90971c20521b0b516d0281ecd82051053a03765014b26314d15d3f202f2340eefaa2a781f090c79a206fad803ce80d6481cc90758e0b39ec81a88306415e6e80ec07747a0926aa7850415690469025649143266224ea7286dc164054cff490c7f6400e4594a85f872067b20679145a206ff214b5eb09e4650bd93937e4a5065125a411647d1a801da408721905b279e488d3393cc8a344823c8685bc49536fa247546f61c06eb1801c4625ead20af2a027e4651964e70c80ec9c16f2520db23d3ed93720ec256a441d9b425e0e1379091bc8ca39eaf1eb0bb23361779901c0512441fe52823c0a2f909740875c3689aa208b203bc700e42e1f90c31c410e6b0479c983ec214e51c54de4417490bba8f8e3a039c85f84202b870ae44fbc64bbbcc01d8b421e7384c93128e4390508b9dc414ec447cf25c0c74f3082bc4c20aa33086437f106f91230a25e4246d42f0ea2260a04f9eb82a883e848e4970ff25811c8cb2ec86384200f42225f4207f21700c861749003e007725816e44dd041b6e707bbc412752c0a7222457a0901f2202c6403d921e7f9c2cd5126419e8372c84bd040bec48ca84b0f1279c91cc8a3904456396bf4282257903f3108f29228eaa03590c7fa405e4a10751346202b0706e4416c208f89899a0908c8634420e7099239080a594118411efb01796c11e42f0b888e5921272aa49d53431e3302d95921c85d51441d3445c84bb240ce4409b9cf18646736e4313990133982ac6d0bf29720c883da40bec40df2b286bc0926e4650c79cc09b98b07e4ae23909707c4b1ec0bf2257144550e0a51bbb4d899e809799429e44db841ee0ae28f5d6300dd840fe4514c905dbb00ccaf3e9043f145d63941c8ce89218f314176a70839960151632910755914755023c8ce91218f2982dc8504f292177513222087e20cd92519e451ae90c786404ea340769021c86d02443500a1acb39da8229205f9120f649543a6956342d4415951973ec8da54883a2684bcc91e51f5610076ac00e4b01db27246887ad600acbd8a3aa60479ec8ea85d642839080ee4343a6447b145d4322c647708405e1e91bfd60c70c940d4e504c8975c81ec0790f4724c22379183bc89217d491bc8fa1c91c710893a281975d01ec89ed9218f19827cc908c89b0801794c92a84b2fc8ca51a3c74bbc883aa88ea7ced9415e0a450d5b00d9212ab2a3d4410e93425e8ebc4442649b0bc8da5640de041ce4511241cea407fba507b2362dc883f040568e0bc8a32091133512b54da847057840362c02e4510441ce440ad9a50d59394a7a1c250bd9d20d72ac01909759a22e09889a47cb99ce1942fe5204591e2990f521837c0900c84b2ac85f40c883d288ba740059dcc86359c89b5042fe0a40e8f282a80a5005f66b0eb2725a4016112bc8cb226f22487f2d213a0644d4b02b51c3aa206fe214752c08d9591039ec873ca641d4302cc8650dc08ed509ba4420ea181dc89ee1218f82853cf607b2737e90bf90a286e59097326479a6405e2a10f50b03e45102411e8b0379944690bb72405e4689ba4687ac3b0620e71192794908c87d3a4016c7931da510647dd0200f000a422e7f90f559421e0512e46550d4418e203ba7444e84472f99e871d9eb3103909d53e42e21a2266a426e3b2185cb5f8b3b43561c1bd8502810751445902f7903b96b0a647d9890c31a88ea214d51c720415ea641dee48fa86d22a4709441909dd383bc16668383184136101fb2738490132182ac1ca31e07f9811ca608f21855d4310490973dc861baa8992061c7f288fa26945d0e456d2321854b0b90134521bb5300b23f5760c5f5642f7983ac0d4bd42e36a2765d31eb9c913359421edb20aa87e011f5922d902f0923aa415460bb8640feea41ee72a3a71fd4e931a9a8a32c82dc1586cf4f3882dcd544d4a593387e19823cc80de4b531606319212f3b48649803c8fe8c411e450ad91f2ab25f37e4b63829ec83843c8647d44dfc88ba0920511349451d4b0059253aaf83aa909d21a37611819cd600ac87e411f512319003f0233bc64854e7d890ef3020bb8412f51389206bcb821c4a23c8ca59d2e327a0c86aab20aa730e40eeea21ea582351bb9488bac920ad120864f52983ec1c26c87346736ec211e46589ec4f1ab22272847ca701d900e021fb4541d05118411e2485bc0c13f58b91a8f26445cd240ad94fac216b9015d92e1ca20e420379ab0564837c901dc50a79d024841c7408b27370c85d5ddc8a8804c889f6e8651564e714803ca60772266a90c7e6208f3d216f9244fe1a83bc3c839c070c375d8245f62b0a79d01cc8daae44dd0409c8831e411e1b00391450a27a5b23bb4954d451e6208709a38ef208b2002820ab1c19a27681e1731466205fb246d4e5441eb323ea2886207f0582fc9501f2d79626c7004136901f725b1b519d33912f7103b98b0b5b05a902f96b1164e54881fc894590074972c8e5146403e9218f21a3667206d9db15596d12200f3a037969401cdb5a40568e08512f4903b96d2985fa98418e9540d44479745830ea72c92147a9428ee504b92b8bdab12ae44f1082accf07c86d23a4f06c0cd850e82067c206b94b0ae42f0d900bc040d451e8202f8f1c59e625ea204290bfc2445d0a1075998bfad5c5c9250c79133c90bbb0a05da241de5201790940d46511b96d05d94da690632110358c87ac9223af0a30477689017201847fec3202d94072c8122215553951206f220ef22563207b0343f6123890ef50203b1609f25705431341212b2785a84b25510705825c0a4664131d12751020c8ce69823c3684ec929eac724a882acf55d4301fb26774c889fa401e4b04799339c8b1a044f5903ba27ac853d4e51564e594e9361050b87c003951227dc91951ed4104561f36c84b608fe208f2720bb272ccb472d208b26b0b9e83fa400e404f764c01647dce200fe203791022c86563c0fac123ed991cf29800c8899c90970d44fd8414f2267720ebb306f9122c90b75c405e6670c83006a2be2d206b203a64670b44dd042a6a288e208b8b03d6a129b2a31082bc7c218f1d823c46843c8a3290bf70c86304206ba320ea28ae404ea447c73a20aa7368c89f1004796c12e4b147902fd10279144490cbc020e7594076d022c82ae942f66b0fe4af0998744e02c879c290bda40db28860418e4500f2a0aba89fa083ec1c22e4313a4d7e75807c091c647fd480fd1260e82790c86d4c2bbc4404e4b13a900739217789f1f31381200ffa0379501de45851a22a07043d864d415ea34076b98bfa094590b57189ba8936c85f8944ed4a4380061dc9c62a00b92b89a89b4082ec9c13b54b07e44477209f51203bc80a914b61d441547c1c850a79a90539cb7298acd5ba6ceb58ebd99ad35596afba62ad7296aeeedcde9a97afd9b0d8af56e9dab5cc157b5df6ca5a7bcdf9ea9cb5fb2a61af5fdf5eb15fafd695fdb4d1eeb72f7305f0ebcb69e39ebbbaec29afcb612bb9dc855b76f9edec00deb975f9edf57ace13ab3d6f496b2d9bf6acdb9eb76db300cad73fd7f699c99317f6c89ecb9eb776b97c25d0dde582833b3667fbbce5b7860dbbad0118379626033c5f6025e5f3f7221fdd33d0cefdcacf7ea1b5d2dfaa0fb3e85a71014b0926fc820c51c7b4c880c1310462908381bf45fc102e48c082044c4b9ba180ca0cec880820526344932372c009911a231adf0f0c2d072481642aacd03d1037d8f0612c80c085263f2e70f06a648ebf5265848f9271c7f869a1890a6fbc6b0197d01504b6607db8a649f12f267e56b0f2b382011397a6a00973dc272797dba030b8b829b7c984abc4c9ad137471656e53154e9edc1b029f85c2ed59ba4e6e5c9fa80bc5bb3d6edca726f747c9854a736d607c16ee39abe2ad9a3c6bb6b75ae3197be179445cca8ccf8be47276c15741727deab850045c1f3e2e94ee964a6fa4e4deb4b8b0289eb1369e97c56d91f0baa5fb53c28582ba38016e1306f73e3e088baa236e8fd47daa72950c6f1524f7f5e6778f3c6933bc150bcf09c117a9b92e177e67e596c4379a5ddc21d7e9776f3f5c980df71a3e88f73cf8a573b933c05f6970cb37de48e9f240f2581fdc1f182e9420b764e08bfeb8b7d9672545717b2eb84e515c1cd675fa727bc8b84f3d974a22b87522b8372f9f15c5250ce979be8b63e33ae1ee8f1c770e984b989ae7092f81cab8749e5c96fda22bae4ff24259708bf44438dc9edd7572e1964fbe888d6bfbe3b37e97b4dd5b8db93d2e5ca7a8db1a7aa3362e6e8adb14c925ccea79c527ade7adb8dc9f5ea80caead8ecf2ae0f664719f60f756c76da25d9b028f45c365cf782760ae0b91dfbd707d32b84f56dc9e45eed394672c86e715717dd8dca738ae8dcd6339dd5bd46d12e03efbb9b83248be4a86dbfae07548b72790fbf4bb3829b709cdbd0d3f0b8c272d87b77ae1ba62f81d96db0f9e68887b6bf3594db785c4eb80b83d51f7497779d678ac052e5f433ccf756f395c180cf747810b95c2a5cbc9ef9edc09f44ee05c253eb7ceed199be4796f5c4e39bea888e74bcaefccb8383aaed392672c91e7a9717f16b952b10b94e54acd706fc6cf22e3febc70a10279d69efe8a80cb5812cf73e2b6749f0b5ea0452e1d07aecf0af7a98f67ad8ebf72725fc6dfcdb93d62dca7dbc57d719d5ad80dd7078d0b15c03336e779665c7e559f35f7c98d612e9edf055ddb94c752e2e2dedca633eecf09176a8ffb6af33b479eafa2df85716d551e8b89fb83c895723d6d3e8f85c22dd3782333b795e67549b765c3eb56b8b8046e5399fbe2f91d15f796759b1ab840185ca9209e322fbeaa82fb63c59d13bc8de089906e477827b07b6bba4db88b43ba4d45dc95f8a02cd76789fb54757f8ab850935cc2b63c4f777b22b84e3c5c9cf1364531c7caf549739fd6b8b71e2e8c867b4bfaac30ae0f97fba4c4d3e6c463593d65aee7d9715fb2df3dc143ba3d7fdc27debd41dda69fcbd87cdef1966abcd10717f7c875aa72715e6ed30d5537dcdb1517e6c4fda1e0422d717bc65c272d6e19c91b0d716f325c180acf5a0b6f75757b8eae5310f7a78b3b07828bd3e236595dd6e99d6c707de0b85044d7a78a0be5bacbf920279e33e45b052fd007576a8b5b2e4f64c2edf9e03a997181c05c291fb6bae0fa48709f88b865086f24747d78b84f8b5c5b9cc78aba9c607cd10fd727ca7d4ae1fe34dd391ddc1f3717ca8e6bbbf2584f3c6bc6b7927abe82bf5be3f648719fbe3c673cd6effa08709fd45ccec67cd524cf99d45b35707d9cb84f5877193e28f79c7df1564e9eb0029e67801325973b1cfc159a5b66bd5113d7d6c667093d6773bc9502f727830b65c553c9ebd2f9e0b6dabcee83fbc374a1e4b83c553c16eefa9871a1945c02b971e91050180ef7e7893b47777b72b84e863c61903c6f786d8d7c1696eba3c07d3ae1493be1ad4cb836423eab812a022e79ba782c019e3443deea8a0ba4bb524a1717c77502e01236c0f30ab8dde08966b8dcc1fdd597eb83bc500edc1f29178a85dba3bb4e2ddcc9e49d8c707ffcb8738e17c8904b27787d62f7a983cb1d0bfeaaccfd29ba50223c5d69fc6ee9e278b70984cb39f545543c6b73fe2a81cbc3c66331f07c2df91d174f18d4f32eb84de29dfc6eeb84d7b5a98a737df6b850b95baef9bb25b74b9e08767d52b84f7bdcd7fc1d124f190f5fd54b25596e9d2a97078dc702de56f0442754bd79bac2f89d9a4b5af0ad3cb8b63c3e4b816b9bfa2c0b9a8ccf99edab98b8383fae93024fdacf5b557009d4c4a5b3e49684bc910c4fa0dc1695d7012f5d45bf1be0b68327aae1becafc6e90ebd3c17ddaa2ea850b24e64a2571b9a3e5af8eb735c2eb4078cec278ab271708e84a01efcf940bf5c3b353efe483fb63c79d93c1ed91e03a1151c5c7fd5173a1d8b83c5c3c560017e7c06d12614e95cb1d287fc5c1b591f05880dc1bedb388f7e6c385d570c9b3c15fa9c18b736f3a5c580cf72d3e6883cb9d37fe2a87db93bb4e2c5ccaca3c4f92db13c37502e4f2c8f15853ae4d85c72ae4be3cf85d1ff765c2efa86e0b88d7d57039d50fd55125c4bd8df9ac2e2e8b7c2749b744e08be6f80583e07952aa8cb84a18b87580d7467c2c362eee759baadc528637da5d1c0ab7298e5bba79a3a0fb93bb502eec723dfd6e84db23749dd83c67586f65e5599bfaabdf33567c1e0df787ce95dab9b7356e53ab9cdcb2ea8d9278d69cbc151d973c0efc1518cf5a157f85db313d6b55deea8ffba3c3855ae4b68a785d0ff786fb2c33cf5a107f05bbe499e1af92b75a54bf0be0f96af2bb2eeecf9a0be5c6f5a1e13e11722bc6c4f39e78d60678ab3aee6dce6d0aba47f0338bfb23c59dd3bbe5166fb4c1c555b94d285c1f2a2e54eb3963f25557dc93f820092e79c8fc951b556c2eae87db04c82df778a3139e35aabf025e96b02fcae2e2c8dca6296e4fec3a75706d478fe5c42dfb78a3149e32e1f30ab93d3ed7a9cc7d75f03b3dae6d90cf62e08efca0316e39f54646dc1e3eee93d1ed795da70d6e0f16f7e9752903e179c95b4af246443c6925bc55094f9a226f95c5fdc9e3cee1e07ec307f96e857827512ed0982be5c473b6c65b19704b21de88ca2df57823139e343ade4a89e72ce8abb078d6d6b3c275dae33eeced81cfeae1da58782c439e3227be0ae8f6a0719f945c1f25ee13d5f335c1efe6b865f18d68f7b6f459765c9f26f709847ba3f259415cdb1c9f557471716e531ab76788eb4487c78fcb1795dfc1717dbeb850b6db62e17571eeedf65965ae8fd38582727d08b84f71ee8de8b3dedc5b23b709cafd61e24261ddb290379ae1f61caf9318cf5a056f35c8edb1729d8078d278de6acb73e6f0452fdc9f072e140fcfbbd4678b0b457bc6f4789e18464e5489b9f502e3793bd726e5b16eb85472c1ad83858880dbf3c57ddab94a12b8750ab83f245ca8a78b0be13699717d58b84f51b72cbc93db254f047f15c6f591729f54e03171811cb974a65c9c98dbf4c3bd1df059275c9f30f7898a7babe1c256e0b9b92da2377283478b67ad84b74a12495025c865accdf376b838056e9399adc25c1b94c7aa61f7e5fa4471a1faa4c9792b262e6ee9367d717f04b8506bee6cf24e48b84058ae140c974a7ae970b915f344323c6b4cde2a8e6b13e1b1fc78d2d4bc959b5b5af92243ee4f7c500597b0ace7199fae287e87747bde5c273a2e90cf95f2dd7a25f2bc00ee8bccef04b994213def9167cf3cd113b7f57a232aae4d82c78ae2daeef8ac036e09fc223e9ec5e19d105dcab03c4f91dbe3c77ddaf1c4dc9b049f75c425d011974e001708924be7e856ebe977b6db83e63aa1716fbccf92e192e783bf72e4b6d8bcae4c910c97af1d9e57de9f30178a8afb1afe2eea2a71e0d611de56ed8db4b83e5a5ca8d925ed81b74a7a4e03fe89d1bd95f059825c5ced366579d28278ab199eb1169e37c4254f93bfaae2f63cdd2705ee4f0c176a907b131fb4e5599be1afbeae2c7e77bc3d4cd7098edb93c87d82e0691be0b16070327cc6d6781e16cf1a066f65c873b6c85b31707d86b84f8f3c6775bc1594fbf3c69dd3e5fad871a10ab8b6338f45c793b6c25ba1707d50b84f7a5c9f1eee13234f19f079845c1f412e94b06cdcf7f8202b9e3c588fe5e66988cb53c663f5ae0f10f7c991bb0f1fe4c0f5e97d0af30ae1fab8709ffeb84a84b78eefdeeeb84d3bb705e67559aa08799ee5e71e9730219e777429037aded37575f1bb0f2e6d463c56f272e7cc5f81707112dca6162ed0ec4a29707b1eb84e3adc1e18aed31fd776f55917dc1fa20b15c2bdc5f05952b7cc7d511e17c8e84aa5b92d105e77bc37153e0b79cb04be888efbdaf9dd14b745e6751c5c5c23d7e981fb99fa10dda736d72787fb84c8c5595d270b2e0f1c8f05c1650b8bdf95cfdad05bcd715b635ef7e5f2b8f1580e5c2003aed4f09671bc11089773d0e279e1afa6ae8feb3e89b9aeacdf15f13c809ec307012f816ab8747a2e5d1dfcee7729a33d0f8fdb1fde49d1c54d5da72dcf58d4f3c8b817f241625c9befb17cb82d0f5e77c1fd09e0422955a1b93d7ddca79c14666e8f9cfb54c02d7dbea88bdb03e63a41717b7ca21faa72b8e451e0afb4b89c137c11d3c5d96ed396aa0f2e8f208f85c1bdcdcf12737d94dca733cfda127f55bb3d255ca73c2e50ef4a2d5d5b0e8f05c92d795ff474818c57ca8afb3af33be4b376c65f2db9e5246f54c47d61f03b3c6e2b88d7e5707b64b84e73ae6bea773e3c6b7d2b322e7700f8ab0beecf16778e03b7c786eb44c80512ba52155c9c96dbf4c2f569e03ee1706f80dca626978791c74a7ad2cc78ab21ae2d90cf123e69596f35c64e84db2adec9d1b3f6c65f093d6769bc5501f736c385a57071775c27a1ebe3c68512baa5d41bf17009cbf2bcdcf559ba4f705cdc93dbe4c1b5f51eab87e7ac8cb72aba408c5c3a0f5c1f00ee139a5b2c4ff4e6d2b9b8f23645706f78dc26dba5922ab7ce946ba3fa2c2f976de39d84b9e401fe9517d726f55957aa80b837073e8b875b9e79a39e7b03e1b3eab83d41d769e94953f256163c6919bcd599fb83c69da3e5fa645da830cfd807cfbbe1def6b84d4a2ea7165fd4c3bdc93e6b787dbab8503b972f0a7e47c7b3b6c15b217271addb34e52a09ba7504b8b7003e6bcde54ce38b84b8adbed113b75e323caff7a78c3b07cbf5d9e13e29727ba05c27142e6b6bdeea91db83bb4ec75b72f046e5a5ebcdef20f8f5927a9e0017e82bd5e4f220f258632ecf1d8f25c16dd1f0ba142e8e87dbf4c7b366f557c1fb83c0853ae172b6c15749f2b4b51e0bceedd9e23ec9ee4fd69562f29419f155ae6b0be3b37a2e8e88db84bc3fc10b65c3f529de27312e6344cf5b73b963c35f91707dcedca734ae0b8cdfa579f2e4f1585a2e5d25fc6ecaed61e23a51dd9fda85225e5cec361ddd0af044afeb43c17d4ae2022972e934707f962e141cbc05ee567e76717f7017aacc9336e6add4549df0ac11f056765c5c14b7e9913b1f1f74c56d59799df05993fa2bddc5156f1314b7657c9d98db7af2467054215d5b97c7d2e27246e6aba82e6ec96dcae002f9ae14d3251014970e933b83de4909b7602a3cef817b0f1fd4c0f569dd270d2e0bc73bc1e0d2d5c0ef14b8ad37af4b734b39de68e992e782bf42e39ee6cbe465ab8ddfcd6e29c61b253d6753bc1593678d81b7e2e3491be4adaab8b70b3e8b8aeb23c37d12e4bed0fcce904b99d0f3f6b83d66ae531917f7c16dbae2fee070a112b93f298f218fc5c1ed51ba4e6b5c17d5ef80b8370a3e8b897b63e1b310b938186e131e4f5a156fd5c3fd79e44ad92e6e83db04c4bd9971615edc1e04ae530997878ac7badd5b9ddb6474712adca6399e32089e77c8a50d88c79ae47267f757636e8f98eb64c5f559e03ed97023b9b8a7eb54746f8edca628d78781fb74c325cfce5f41716d733e2b787b40b84e6d5c1f32f7a98c5b1edf68e7bae8fcee061e0997b42ede0a886b3b3ed61bb7bce0a1907059c6750df2bb14ee8dea3601ef4f03174a87a792d9a583e6debeb8302baa78b837252e2c88cb1d30fe4a86670debaf84f7478b3ba7812a1b6ecfd47da2e0fa405d2829973b75feea881d16b754f24560dc1b009fa5745b0dbc4e77499bf256c4674d8fbf2ae0dab4f82c5a1508f7b6c1676971818eae940bbb366ecbe78dc2b8823c63783cef8b5b16f146474f1e491e6bcd93167bab2ccfdaf0ad16b92f31bf73ba3d61dc27db555274eb10dd57f9bb246e8f21f7a9818b1b739b86b865932f32c30948ee2d8d0b0be396486ff47ad6746fe574ebc23be9b9adf2444cb7a7759d34b83e4ddca7ab8bcb729b5c78d65e782bac8bb3e2364ddd263dd10eb70ce08bc478d2e0782b246ee9c71badf0741df13b314fdb7cac37d7c78a0bf5ba3c623c96eebaeafc0e87db63c67dfab9e429fe551b97ae097e97bbe5116f84e539abe1ad6a9731299e17c56d65f03a0aeecff14291717f16b850385cd2ae782b1f6ecf0fd78991fbe3c69d63c12d054f54c2c51d709b8e4f5a98b7fae0bed8fc4eeaf20cf25819dc928c372a3e6784bc15f0f694d72983fb73c79da3c1254c80e70d706b96f0452adc1b019f45c2bd35f92ca6fba3e54221717dc6b8503e4fdaecadb4dc928f3742e1f650b94e3edc89f8a02af736c76d92ddd707bf2be49624bc51d105f272a578b83f3b17aaf88c4df0bc149eb535feaac99d7d276b9eb325de0a80a72c80e7413d6b3dfc95ebfa10ef5318cf89e58b962e2e779bd43c6743bc95cf7d89f03b49aecd85c742e4faccfb84c1fd69e242655dba7ebf43e0d265c0ef8aee8f1e77cef05ec7072d717f3ab8505bdcdbcf67a1b925e29de4ae4f9cfb24e7f6e4719f0eb84052ae149a8bb3e036d5706d193c5618773c3ee889eb53c8856ae0e28eb84d88dc62f14e24b805f3442c5cdc05b749875b3c2bfcd5244241dc1b98cf9ae2fecc71e75cf094193d6fceed31e23a415265c2f345f4bb2faecdcd63e9718126b852353c6b27bc15d5ad697b2721dc5b1eb7e9763973e0ab16b92d215ea7c3c535719b1ab9add91b61717f7e2ed4996bb3e2b360973b42fc150af7a7ca850ae216ecf73c28cfe9c017a5b93e775c2803aaaad8056bf33c06b2b8dc51f3574b9767ce635d707f7a2e949927cd8db73ae2de1eb94db9db73c3752ac4556bc16aafb684c1dad7f3e92a5b2e5b8fb5e67c8e6b5dd784b99e65ecf27f95b0d7ac35b3b55c6dcb36ebeaaed23a6b77c562a54cd67abada92c566c9e38af93c67f97a1536cbf2354d49ab371aedd63fe525cd45fbf5edf9b3d9df7a9fede05ecf723669ad363b7d6065135965d3359bed2a5b36da3c5f96df7a32733dabcdd76cdd1f5950cbf5c5cd9dda3200ca966d468483f1cc68ed6bf77cc25ab3b857eca755cec3533493a25a397bebc9b7ce5b321f5aac9c890f6cb6ecb6af125602edfa5956c6b6b5f6eb27f673ebe6aacf2572b5fe1680135c90c9b30004b8769be727c79e6798ec17930f609b8d5636067bb662bf5bfb02ae5dd92c95005dbe7a0a70d52682b98c8649d935eda0611ff07cdcabc9b592c0014fa0dc1a81930692bd6ac121db43025cb3a2645b5f9daf9fd7e56de7de5c2b317ac57aacbcc9b01fdaad097099acf673076eb5f69c31294047c0a5030fb0d036a20778905759fb23013f0fdb011a00c38629141df1cead8dde55f03c6984d96176b26d1a7888f31d5d1098f60d2d01760d0b6020ee13c3f096856eb0ed824179847976fdbb9ffba8955dc7de6819f717ec3366b86351fb25c1af01784b778359805f3b974f2da66f286d37ceea8d2f1fe3393fadfbf1e370ebcbc27f8dfbf06c35324fd1dcdeff800cb062b324850d9ad9c46f04036f849237c2f646b8be08ac2f22f91484f922c4782681c333099e2712aedf32f53ca28e2782cc6f61e4b7d4f1435cfd10114c21723f411d0f04d60391c603e1c40381c04fc0fb1f0479f2d0c5ff80c0ff409b3bf4f05ab278ee307b1fe6bc1637af45cd3387254f1c8ede8701be832cbe07353e0bf2494308cf83179f8587e74186a70c54bf03d0eb90fc1c46f81cf4f81ca03e87e0e3c0e4e98294c701f737d0f91b7678b2c0c893053c6a687ac6fe781a1c791ac6781ae478c65a4f138c9e86109e06263f031a3f8314cf119ef8192e78196238e2afb8f157ca78c2393edf54f13d31fe05aabfe2fb17fef817a09e6ec8fc0bc47fc1833f4afe0b7d1702f923a877a18577e1ccbb70400b82bc0b3cdfc20bdf0214df82996f818c057f74e6b9068fa712167f34fca30e9e4a509e85e2934d1ccf82925fe1915f81ce1f29f044e3f44c73e689e6f72a44bd0a73bc0a71bc0a5f5430e45520e35518e055a0e25520be0a41f34c039f02f25320e353d0e253c0e2bd68f12910f129c8f029e0f056cebc0d457c0a2dde104f9e0e4f325c3cc938f162b878141e782bb447a1fc13b2f82a4e4f1ed29fb0e6697ce24ff0e0691ce059e483ea4de0e1497ce04d88f34cdae3ab68f04cc2f24c3ae0abf4be84a32f613e096e7c953e09c427520b4fc23fc2203fc2214fe5881f018f2707273c15035e04385e84369e1b48f154e6c79112e3c45383113e4e051f47cb14a387a3c80cc3c6334c100f27cc334c011fc120ff668e375c9e60823e821e3e822b1f820c216819fa10849e5d78cf2e023c2da8f3b4e09108620f81d5d3022bcf0abe785680c4bbb93d9d1831b7e4f06d1e786ef97d9ba28780c933c5f14c2c3071f04c581ef8e2d930f10f4cf16c647836719e12fc3cb1f87e89875f3ae17925f64b162c1df0ac22c58330c4930af141387aba08f83554fc9a107e0d09bf46cb3bd0c3af61b246f84a6d3c21a8e109c1985752f36992cf07e4bc1a371ce0bd1a35afc6e8d3f49e0e087d1a163ecd9b4f63e6d34c49f3c0a751f268c83c1a3a1e8d19cf06c678345c9e0b503d8368cf0568f8336218f16796be012e7f06cc33e8c49f71f20d04f01ff4f1fc29f11f3cf1661279334abc192a9bf9f932435fa686672f4d192f4f86852743f50c6479f2d478325f9ecc9827e3a4ca1e7f02157f1ce22e3c7c971c7e01429e81180302fc31cb1fa7de38c833377b239a05d07c31842f12f1c512be68e61790f244289ec8c6179f3c15a0f344429ea8c213cb7c92d5131d782a507ba2059fd4f449587c52079fc4e4936e3f94e48f1f5af1c3257e98459c1f6e196ef9a104ef811bcf029a844d5eb8c07b80c223251f09ea91e878a4203e38c8239d79a4a4e7908fe7ee8b0fba81f4e453e81c40f763b09e4ae430a68b1fa3c58fb9e283233c9da8f0c1a41f63e6c738f0630ef80eae3e68f41d08f21d04f21d8cf01d9cf90ed43c8390df4195671021cf010dcfc1191e3c1085e7e0c9237d790e5ebf41d6934900bfc1231be8f11ba8f114e08d077e83d8ffacfe27f5628eaf811e2fc68017c3e43558e4a92491a792275e83a4d7e0c96bb0e435787d06937c06759e3f847c06537c06bacf60f718c8f019ec3c06903c06757c065261983e4c97c700000c94fc0569fc055afc0552fc0540acf01710ff822f7fc1edc148f260927830651e8c040f26f8608a7830afff42e7bf28f2a411ff0b20ff258e5fb3e6398362c27f21e1bfb0f92f62be64f9f2fa2faef742e5037a2f21bc97a5f772e5bd30f03d40de4bf95d2279e2004897299ecb1cdf6589efe2c3d335c177a1e1bb90f91e185d42f82ec5ef02e6bb50f07c2df0bd22de023b2c00e22d88f316ccaf408c0a3ce032e5b9049f8b03578e92921a35608401c695b304c21a2535195c39c62b07832b40ee0ae003e302597181beb83f645cf113c6fd01e3fa60e0f3c0f5c1b2bb38032e4ec78410f716c6bd01f12e33cc30038c77392582c821862009192490397f44f5c1c71e7a3c3935e581879c778df1c5bbeeb8638c31d240e35d88bccb8b77d579d716efdae38da8e18da8f22c218f2707773cbd64f908841f4100cf00114f9ed3f3002bcf03b408d1f303cd873ede87303d8cf039b8791c80f81b96de86a00c31c4c0c8c78015831c3198d1c2c330e55d80f32a34f22a787980840d7e0411b0f837737c08117c085ade0d24efa60f3743ef26e8db30f06d5ecf04c29215bfe4fb109c582324c7abe9e3d34c3903e7c98479324c9e0c00c6305ff4f2c5264f5ce3937a1ec47ec8e53dd0e391a87824333f668f1f83c76f70c08b497a0dc0bc06563e032d04f90b80f80b2ef042f55edcf82e277c97a3afe084ef52e6bb70f15c0af814027852917a0fdafc0f0cbc0f59dfc3203674f134c47e863c5e06e1cbd087a18787e1f62b6090029c4781913fc1f5262c7d0953be049908677c1c143e4e040fa7868743c3c3e9e0e1847938163c1c091e4e9687f3c0bfc1e1999efc92020f829a577af26a967c9a10be0c0b7fc4e18d82bcb1821fd6f9610d3f2cf31eecf01ca8790e8a9fc1139f41041fa6cc8779fd0544fc972eef8590f702c777a1e02d30e42ba8e27bf0e26ff8e389d8e28138e07fb0fa1f1af91baefe86e0c730f52df4bc0964fc0865bc0f611e8e0d0fc7f870c63c9c06de4d1ccf2681eff2c71f993e03317fc119df25821f93c7c320c3f740c1bfb0e56d60e08f5b7c1aa1df80851fe1e993f2f8314dbc17d87b59e055f83d97335e860c7e0d10bf74c68f90c38b40f471e478140ef934723c191fbe08237e080cbe07259e05aa67fae141b8e3c104bd9a30fe0b04df83208fc31cff4220ff821d6f029c6f23c833bd1e4d215fe68927c3e58f3ecf81f1c1d8de0b02df430b6500f8a1954792e16d48e0d324f21d08f01628f03dbcf92429df25cdff30e649b8fd9b33df46836792bd9a213ecd9427f3c89311e1bdc0f03d48f9e30b6f040d7fc308bf82d5bba1f220d46104e23980e037907a0bf8782e2dbc07817c0f5f3c0e5b3c9c2abe0219fe8700de0709be07493e87de9f70e54d08e299cc3c9b2cde8326df41186192cf859067d3e64778e0cf54f144111e29921f03c70b69fc9a371e0c19ef4589f702c0eba0e56f18e057907a1b0af813949e04481e4e1ccf04c38390e59506f862100f6ff8314c6f43d29f09e18f6dbc1721be883abe081f3e880f9e072a1e4e02af84f546367ecc22af019b0743e5bd44f238d8f131e0f12928fd08867c1914be0b1cdfc5cc73a9e2db189f78c4a750c827613d9a17de862bfe4c181f4314bf42960fa19fc198ffa2c693f0e48d6f1ecd1ccf65e791a0f80accf83755ff05806fb3e6d9b8f01ef4fc06863c17e1c7809564c7cb70c2f7d0e655a0f32494f1719a7c9739be4bd49f20c37bc1e37b98e04b003e0946af64fb347cfc073ecf41d267a0c7f730c9cf90c6bf89e39792fe84127e040f1ea9f51900f2313c7d1126bc0ead57018e27e1888763c2bf99e189a07a2194de87ddd3d0c8b7c0c1b7f0fa13fa6e0cf9a5db7f90c717d7782f7f7c172fbe8216fe863a7ec9ead37cf06400f83171fc0b438f821e9f04c7c3507c16e8782545be030bbe08a16f21ca2f31f933adffd2e6b9a4f040d0791c3ef8151c78367ffc9a3d3e0d93ff60fe0d36fc0b53ef4218df02046f020befc6cc0f25790d24f80b5c781ce4bc065d8c18e2bf14f25c76af46cecff0c6d710c71f21f91924b8aa43c791469ae8430fa7cf0581c7e782b0e38d36d640c30c32c400c30b2eb4c0c20a2aa420e28a086fda7c2e88a5cf05a154e6581c2275b08106185cf0a54b05147c0e88cf4d90801f9f937d2ec6c5165a6491030e248c2005144f24e1420b2aa420429c10dcb059323e293e7003143c19ee800447551a2060005aec498947d31d3be4f065f09ddcf00444e513cd7f0b28a080c20823e0383ada83722498608209264a36d040830d36d860030b0b0b08208088c55aaf213386cc1832e3cba3cb83175e78e185173f71d45b2f2a548a0516504001051c70c0e1830f3e78e18517473f3f474770c0c1061b6698f1170b28a080020e38e0f8924affa142850d36d860830d368c30c208238c30c20c33cc30c30c3380000208208000020c30c000030c2a547cf0c1071f7ca042c50b2fbc98071eb8e0820b1c70c0e1c7a73e3f58c0d1008e06707e8052d686499b0bda5c30400515944c983061528152054a152855a054814ca9023359cc6439321acb52261b6080d7ebf57abd5eafd7947280b294c97e4e91fd5386536ac297b3994ea71b608039616f3278f325ec72800160b1f6077013a6559651a2e4724545ff054c6098c030816102c3e60b9b2f6507180006d3e95aad010680c15ef365cbc6ca364a149d6e00186c800160b034147c19258a4ed76a6d41b3e5cc046726383381995c4e8a94586c800160b056eb78a5342097331e95adb21525ca6fa568a568a568a568c500dd4f25894a1295e1142a103cd0c002b81d9a0cf64c7ccfc4f537297f23e006299a4062881c40d0e26d27bc2d8bb7312dbd0d84b771f1b6083608d365cbdbbc781b95df01c48e387e678fdfc100cbef3cf03b57bee694c6531b5f73fa9a195f0bf3b52b4f8372e369653cad8da7413d2d87274f6be0694e9e86c103b4304fc3a240130094047fd6c0cf765624f1b2315e86c4cba0ca78991b460a3c71d204002540bcdccb1a78d90178a0e1a4e55f1748f02f30af2fff32600205b01850a535409501aa0c404114440e79402818402bd80a0008c04fc91ee50b2896bbfd94b4dab498aa041708f365cb982f18406b800096bc5a3e2da081f080830d33d800830d30bce0020b268000030a268c00c2071e7e2f70f8b233f0138cd267381ac06030585941cc0018ac562ba080020ac0b5b960c9cb9217a50a942a3093c54c16e391f168f894e153a6f440b651ce2683e50f660ef5e2800a942a383301192cc8368653a67cc1051794b15aad56abd5983061c2a40683b5bc8ccd7939cb030ea0d166b3d7abd52acbb25633a034e0b25633c080397b7959ab196040cb9634daebd56ad56a0618d0d66a68b6a0f9f2cc041f68c962268b992c66b298c95246023258c8602183850c16e391f1c878643c3a2a5ed66a30d89ced0107bc5ead169c364a6abe8ccd5ec666bf34e072162b67bf6c199bbd8c95b35f9697b12c5fc6662f0db89cc5cad9b2b22f3e097563867cf275f972e1878acf18ee9d0471e96abd501ab796c83319c6a549f19c12e11913e09dd4716b913c936c5cd9d0271f789653bc1002cf3280b755b96c3979a10e6e8d8c679286e72d7c799eb387d61c7926cfb833da53fd6e8dca33d9f38455f143745c99061f353fa1b19d7752c073aef9969ce765feac670c817f62e519b3e2735f3ca707dfe2e0ce4878aa282e8d8de7140fcf9ef1337665693e39c3ddb13d957826d95c19179f6cbab2e22755b82c4778a19fcb17f187be5c4ed84fdd95ed3ed9e5b9951f914b6be13915e6d9e2f2426b9e8d9af3cd2cc5bc50ebce829e4a8227cc8e1f02e41973f24f6acf79c7cbc6dc9a1fcf2415cf52cb3371e0d2a89e53715cba187821a82b43e293673c6353fec99ba7abcc0b1972e9f2bd90d39d85792a156ecdca33f9f37c41f1436bee0eec99847aba903fe4e4ca1cf8240797afdf0f3d7069913ca7d8783ec637caa589794e2570d91af3426f9e6599179a5dbe723fd4c0b3dcf99d2dcf96981772f37c882f934b737a4e31f12c5165bf4f5e7077849e49a94b1b3ea774cf2ef2b380a71f972e487ea880cb32eb852a789e3467587c550277e767f28e67c3942e0d5e28902b53e29369dc1af199e45d19984fb2b9b3324fc5c3f3375fd895bdf14943ee2c83a762e1cee23c9513cf19416b669e49e1b3acf3425a9e85f2657ac636f827815c59ed930adc5a1dcf6411cfd9c097733c6715ff7af29cedf155115c190b9f5ce23953285bae17ea726b433c93689e9d62f6852f22cfd83f3475694e3ca74278b68b5966f14250aecc8e4f4a5dd9244fc5e4ce624fc57bc2a2f82139ee0c8aa77a7ab68278a11deecc84a79ae2f2e5c10f79b93b073c93539786e639d5c095c5f149449e31193eb7e6d6387826a1dc19014f65c193f6e4ca19e3ee407926ad2e2d89e7d4d26569f5425c9e312cff048567ebf64217dc5a11cfa49a2bfbf924efd6c63c93529e31383ef7f48c21f1b9226eedc973aace730af2330d9e2f357e88844b979517e2e3a9c8737ef1af33ee2c85a7b2e2d272abf9cee72c335d4d3f14c0ad41f04cda9e651c2f047c36882f2497ae377ea8e739dd74d6c05391b93536cf649567abce0b8971e992e28760cf19a5b3e053112f0d83e7940197a6c6734a87e77a7cabdc1dd933b9c79d5d792a36cfd964c29ef8a1386e0d8d6717df049e3f7d1fb835359e491d9e13525ad673ca8e5b83e109c3734a83bb73e549a5e4d2e5f3426e3c5f0ffcd0945b33e03935c9ada9f04c7eb9b39da70a5ebafef8a126b75e88fc500c97b0273f04c4dda93d9351b726c63329c3b395c40bfd706b4b9e5389dc1ddd93aa9776c873ea8b270d7681c2b8840df1436b5c59944f6e79c61cf8274ccfadbe62ee0c89a7aae3ca22792a016e2c924ffe5c999a4fd2706bc8e7ef0fe4f2d5fa2128b7d6c13319e559c6f04202dcdacf738a904b53e43925c625cd802ba78c3b53e0a9c25cd80e3f54c67376757d26b8b2053ea9c1a53df19c7a7377869ec946ee2ccd5305f11ccc5fe7f9135f27b716e53975f59c45b426c73329c4738e67ebe78530b88405f243865cb620782133cf16f19dbab2269f64e0d26c784e215d1af039057bc2fcf8a1429e2d2b2f74e689c62dd8f087a2b8b3179e8a8b4babf29cf2b934a6e794952b5be393835c991b9f445e59059f54736b663c93365cbe2cf8212d9716c2730acb73523d6d8e2b73fa2424cfb2f736279e2f511a23cf29329eb0207e488da72b86177ae439b1be76c6ad55f04c0e3d63673e81a83b7d26ac861f0ae33993f3550bdc99d2530df1ec213f859e312f3e77c69541fdeb9304dc9a0ecf24f1d9d8d7835bb0363f64c5a54bce0f015d99109f0ce3d9aae28594b835a867d2895b23e2994cf37c71f1436eee0cf654bb4bd7103f349f33836f5970672c3c551677c78127d5ce8d7df00324706b0f3c933ccf96042f94e6ca8c9f5ce1f2f5e58726b8b4389e53413ce7213f1b7365007cf2f79cc89f6d706b709ec92c57b6c127e33c4fe45bc17316c9bd0d7165727c3291bb13f44c327269803ca7acb833e15315efcece33e9c7a569794e2d79ceb2aecf964bc3e23985c2ade5f14c2af174ddf042923ce7966fc16e0d81e754f2d6989e492bcf2ef99eb9b5179ec90c9e2ea1179ae3f285fc21189e73cecf7e77c7c93349e739cbe3ab18b8b3189eca8bcb97123fa4e6d9e27921305796c2279178c21cf921a9674c89cf4d7169649e53c05bc3e09934e0d21c784eeddc18249ff47996bfb74d7165147c12cd93e6ba3f653c5b01bc90069766c573ca84bb53f44c42726b113c93b767abf8665d59224f25bbb22d9f3c736b863c935e3c6139fcd018cf970e3f54e6ca40f8e40dcf98139fbbe2d6b63c934d2e5d5ffc50edd205e78518b9322b3e59c7b354f23b7f5cba14f9a101ae4c8d77f3b39fbb671fb760517e68885ba3e0990cba3bb167528f1ba3f3c9db256ce8877eb832363e49c8b3b5c30be1f06cd3cf9e67b9e599447069579e534aee2ccb53b9b9b2339f8ce1ca18f8a49867cc8ccfc1f18cb1f1b93c9e6d61c640f89c0557a6c22793b8b21d3ea9c533a6fb2749b75e8cfc900c5756c627fd785690ca8e3e59bcb53acf641a57967caaa02b23e09356eecc82a722e1d9ee34f0a4aa3d636d3e07e6ca0cf8e495e73f7c05b8b2283e09c773acef06b7d6f44c2ef19ce9ebba6cc9f142545cd9119f34e3592d731e2b7be2936e3c67817cd5952b33e193453c6be58bc4ade9f14c3e716b313c93622e4d8fe7d41397967c4ec1716b8d3c93663cf7f2d379dee4b7e3395f983de13bc81376c20f697165417c128c676b851782e1d290cfa92e9e30397ec88f4b9be039c5e4d68e9e49a0274cce0fcd79ceb4f82a052e5bb9172ade1d26cfa42257f6c727af9ee59567d2f36c1df0421edc9a02cfa9aa2bbbe19356dc58f29301dc8201f0433d3c3fa02c932f44c1ad95cfa93c9edde12b756b343c931d5cbe22f8212acfb2f5b5382e5d1fbcd02197f5e00b7565533ee9c1ddd1f2a45a726b493c934b972dda0b7d79bed0f8a1112e5f597ee8e8d238784e4179c2dcf8213e2ecd82e714d1ad213d9346cf57cf0fe92e6d87e754f1ee28792691972d365e488a67735f37b7c6c83349c6b37ccc59e7691d3c67c98b93f26c69792135cf79c5bf0678be48f8210fee4e9367729167ebcd0ba97069739e53575c9a1ccf29219eb38c972170652b7c52895b2b3e93bd2b7bf2c92997af303fb4e53979ad013da70ab9321b3e59c5b3ece185846e6d856712ccad41f14cc2b97cf587147856eaa7019736c7736a88676cf84f12b933159eea8a2b03fa64efce6a4f057cb63878a110aeac864f52f17cf1f043669e312a3ed7c53306c8e7b06e2d5799ef93609ead235ec8874b83e439b5c6d3b5c60fdd9ed7f15de07911df26cf19205f65e5b26dbe80dc8261f0434e5cba92f8a1d6ad69f04c22706b579e4925cf7a99ad255e0888e78b9456c4734acd9561f0493797a6f49c82e059e27e27eaf9d2e287da3c5b39bcd00dcff940696b9e5311dc99034f55e6d62e78260978463dfbc5cfd63366fc278b5c99089f0ce219a3e3737b5cb6842f44e6f215e7b74991eb8ae4773b3c5d77fc0ece7336f556532e61593c6f82276dbed595fbf3e442c1b96c13ef84818b63729b34b837486e93eefa4071a1beb7e067dd706f4a3e4bcd9dc1beaa88db5a7a1d99ebf3c885d272713db7a982a78de7b14a78c6f878de18972e097e67f4ac75792b426ecfbc4e185cdcf13649717d0cb84f235cf254f92b316e4f9aeb94c6e5ce187f35c3c505709bc2dc9e05ae930dcf1a046f15756fc8db34c0bd99f9ac352e8eea3a71b940205c2931eecd8fdbb4e4dab03c16141727749b3878d26e782b176ec1e23caf810b84c8a5b34015f1d95ae07359cfd9156f157471546ed30997404a5c3a02dc9fab2b25c0bd61f92c232e63bce7bdb93f005c2835d786c16381f1a43579ab2ff755fc1d20cf5ad35f153d5d80fcae84e7ac8bb722ba3e17dca7296e977827c1e752be6f5c1f2af7c987db5ae17570eecfd1851ae2be54f81dd65552c0adf3e49649bc519636a5b9addde7844fd822cfebe0f600afd30cf7e78c3b27cb7539f23b1bee8d880bdbe1960f7c5120b76787eb84c8f599e24295d766c163655185c13356c7f3bab836399f85c0fd81ba733c78c27171df2607ae8d82c7b2e2b6cb13a570d9577159d709ccb376c15b219f35376f15c95366c0f3fcb89c65f92a472e4e87db145585756f92dc26debd61f05956dc3de84f1f774ef139abf3560f3c6968bc1511973b61feea835b2f349e67bb3e695c2801aa5ab8b833aed3ecf638719dac9e405597ce0497f38d2f22e2e266b709cba52bf73b032e77d8f82b1b6e993c51ecf690709df078d66af8ab5e9fda7d1ade8a219f97c6f5b1e03e31710b16c6f328b84049576a8a0b14bc52215ccaac3c2f91db13c0754a737db2b850b27bc3ba4d0cdcdbefb36ab8b7063e6b87cb9da9bf4ae2e2a0ae13011727bc4d215c5b9dcfd2f26c20ef04e9fe7cb95051dc9e29ee536f4f94eb94c22dab78a30bae4f96fb54c46d956f14c5ed044f34c2c5395da701ae2de9b1d6b853f64e98ee0df65948973b72fe8a87fbd3e442b1b93839d769e8de8e3e8b88eb13c685c2dd1e2dee53ec72a7cc5fadb93e33dca741ae2deab37a97340ade8acc6dcdf03a142e2e799d28b8e4a9e0afccb82d0b5e77745f20fc6e91fb33bc505fdc5ff8202897402f5c3ab7ebb3e53e2171cb14de0881276d88b7a2e1fe4c72a57cee6d91db84c0b376c55ff55cce0ebe28cea54be9770ddc9e2ad7e987677b4ff4c0c50d6f5312cf9aecadd0b8dc99e1af4678da6a8f45c2eda1ba4f15dc9a357c910b1747c16d92e172c789bf62e1d2d6c36349726f3b5c980c9787ce631d6fcd14be6885cbd8cff3d0dc928e37627aba9ef8dd985f2f39cff3b93f712e541eb77cf3464317e8822bf5c393d6c25ba5f0bcf865d32dcf7823321788832bc5c4bd11729b9c5c968c77f2e54953e3ad8ab83831ae53ebf6a0709d9eee8fd39d33e6aec6077d70b9c3f4574c17c8832b05c5b3d5fb9c10b74cf3463fb714e18d9e5cb6c2f8ddebb6e61b41717f18b850395c1c20d729cafde1e142495d96ad2fc2e2590b7a2b399e53f0b38f8bf3b94d16dc1697d755b92f127e3775714dd7e9c97336c65b0d7071815c27a36bfbe0b1e678d672f8abf2de5c9fd5c15d880f9a727d9a2e94029740445c3a005cc270781e95db8ae075be3b0c1f14e5be987ed7c8b531f2594797878fc7e2726bbaf922146e8f17f7a976790a792c31bb600b3c2fcab3867b2b362e6e8feb64405512cf5702bf23e37ec70735f16cfd3e37c47535f2bb1a2e502497ce95672d8abfb2dd1ee47d62a02a8f5b12f146569eb31fde0a7781f6b87414f8f502e4794aee6d82cf52e2b67ede488c5b0af045635cbac4fcce77791e792c33f765fb5d15f7f6c167b1716d273c9620d787e93ec9716d907cd616de09973b3cfc95094eda5c168f7722e6b60c78a33a9e3304beca8fdb12e1756b6e8fed3a15ef557e7271e95ae17755aafab8b6473e6b828b0bba4d1b3c69c5b702e1b676781d0cb7e7e73a99a942e19635bc91ef9680bc510bcf5af95665dc9f142e541fd767920bc5e5fe1071a124b93e585ca8d8f521e13e355d1e421e4b830b34c8a5d3bb3e1edc272f9eb52efe0ae8b245c6ef60b7193c110cf736c6856d71cb3bde28847beb7dd60cd7d6e6b1a0ae0f1917eae7b6f8443d5cee44f1572d3c698cbc9516b7078efb24f4ac01f0566fdc1e36eed3928b43739bb2b82e417e87c22d1179a31b6e0f05d72989cb1806cf7be1e2a4b84d90dc35ee4dcb672571b9d3c25fc5b9c573c25f495295741fe38388f7a78a3b077839bb7c919b67ed88bf9add9e2ed7a989db0af3ba09ee0dcd67b97181a42e1d08ee6b7cd09beb3375a12ab840055c29a4a7cd80c792e1968677b264170c8fe781b93f53dc39be6ba3f2584bdcc3fc1ce4eec5078db93e805ca85f95154f9ea9c702e1e208b84dc4fb03e64249716bc43be1dd9e0cae1315d786c8674db94bf1415e9eb3a6b732bab6181e6b91cb57781b9c5b0b9e08857b73e336b56eb9c21b29708fb8404fae14069732129e777565617c5597fb63c18572e21216e579095cee68f057672ac7abcd2dd992e7e9718b078abfb2ba40015c292ad7a78d0b157439037e552255599775f34e5c973b4bfe2acc2d5b78a328f7c6f45979dc9b171756c5e51c7a27303c6b0abc151eb715e58d9a6ec176785e959d18f705e77790fc7a41f2bc25973b08fcd50617a876a5a25ca006aed408f705fb5d131787bc4ebd7b2be0b34ab88c01f0bc34b705e7756aae92076e9d056e4fd275f2e2ba26f95d0ff7a7800b45c2bd217d96175580dc72c917915115e672caf9a2236e09c61b79703fe383c83c654e9ec7c7c5b9b94d653c6b53deca8feb63bb4fc57babe0b39cb833255f25c5fd01e242d5b987f141c3cb599cb72a9f404b97cecf92f04e64cf1a217f05e5fe045d28a6cb9811cf6be20ec14f2c6e8f24f76982cb961dbfdbb93fba0bf5c2f549e4424db936413e6b815b2af1465a6e89c31b056f0f93ebb4e6ce02f82a2a6e0f18f789e7dabef8acdb53c6c457fd5c9f01eed39bfb5af33b452ed0cf95fadd9b22b7e9808b9b739da43c6b7cfc95011788e74a19dd9e2bee93eb960b7c911f973b497fa5e6593bf356746e0fd1756a739530b9750078d6e2f8aba14ba0a74b27815b2d4f24c2ed71e03ae5706f623e2b8bdbe27d6e81aa036e0f1df7e9c9fda172a180b87425f03b02ee4d84cf8aaa7ae2d225c2ef22681c1787c36de2e302295d29306e8f1df7a9e8e222b94e572eeeea3a79b92f33bf238428cb6df9f0ba19ee627c50d2c5eddc262db75f9e6885eb43e74249707f782e94f129d3e1abbe8c41f23c376e4faf5398278d8db732e2021172e9f8ae4f9bfb34c705eab952bdeb73bc4f645cf264f92b322e0ece6d42e3de26b94dbdcb5815cf93e2cedf89d22d1579a31c9eb3396fe5bb8401f23c0caeab90dfad5055fcf5dae37940f716c96ddadd9ee47de2727b945ca7334e40b836071ecb887b1c1f74c425d01d97ce01cfda1f7f85c0e54b82dfc971718c5ca706eecf11172af9a4f5f056313c638b3c6f8dfb23bb501edcd6ed8dbcb8e4d9f257655ca030570a88dbab7782e6493be2ad6c78be7e7e97c5f3f5fb9d1ad7e7e83e055145c47559fd4e886bb3e1b1e8dc9bcf679db93d5faed313f716c86d12ba8c293d2f875b2f3a9ed7736d323c1623bc31b795c2eb42b840ad2be5e47222f04f72d7278f0b95c065ab8adfcdcb961abf935dce45be088a4b9905cf93ba3dbcebf4c205e2e3d281f2a44df1563c5c025971e90455b9b93eb0fbc4c12d58eb7942771d3e28786f465c580ff7f5ef8cb83e3fdca7469e36041e6b864b1704bf83726f643e2b8ddbda79a32d2e790ef8ab2c2ed0bc5242f787850bf5c7e5ce037f95745b50de288f8b2be23619f2ac99792b476e79e58b10b9ad9e3702e302c9ae54021737c875d2dddb0a9f75c825accf0bba3d75dca701ee0ff24ab50a81fb03c59db3bb8c25f03ca68b5be33addee84f2451e5c1c98db94c3bd417161473c6357cf93e3f60c729f82b775f4ba052e65437c55ebde0ab94d4f6eabf83a0d2e77687fd5e5594be1adaaeecf07170a8debf3c27d02e4d225c3ef2cb8b7043e2b855b3abdd108cfd90d6fb573950c70eb0cdd1e9eeb44bc3f6f2e949ccb43c76355b9b6328f15c7f559e44255b93c583cd6cff5f9e03ea171e942e17754aeec8eaf22736d557cd6ebfa1872a11eb8ad00dec88ceb6375a1be5cc2889e47c05522c0ad03747bacee5397cb19096fd57ace66782bdabd79f0595f3c5fb9df9d71ab25c8ef7aaecd8dcf1abae5076f84bbad38af53ba3f40170acd05ea72a576b8b4e9f05891dc8df8a0a3a7ab88df69706d5e7c96edf6a4709da0aecf13f729ebf610709de2dc5ef14eb05c1f34f7498dfb979f739e34a8b77ae212a6e4794f2e63b4e799b96c9af268f1584a6e99f446b26b33f35872dc5b161706c5f5d9e03e65715b469ffbfe4c70a192b836a8cf32ba40875c3ac2eb63c37d423e676fbc1502cfa9e49dc479d628782b41ee4de8b3dc5c1c04b78984db63bc4e615cca1078de1fcf1aecadce78ca74cf0be4f9af6c024fd4bb949df03cac5b9af046055c9b078f95c6254c92e7255d9f2ef7e9897be3e0b3b6b83f855ca9ef8fd5950ae0fa10719f20b9addce77ef706f45969ee0f0d170a79ebf323e7ce117359a327025e250bdc3abf7b6be1b312b925952f2ae402d9ae54eef6d0ae9307b727bc13da25ec87e759b940115ca91476c16acf23ba9c7c7c911297319ee77df09c9df056aedbc3c3754ae4964c6fc4e4b252efe4787de8b85045b7ece18d1cb8ad2faf93e0b23abc1327d786f559616ecf00d7e9cdad992712e25983e4af7a170876a50cb807f14111dc9f3aee1c0c9eae337e07c2ed81e03aed707db4dc2723aad65c1cd06df27267942f1a5edc0bb749cec5e1719d88aa58b83d135ca7236eb9fb22a75b7af046b0fbd3c28502e4d72b89e7c1ee4de9b3e6b83e6eee131df74778a16eb83d71ae931dcf97d0efbc78d202792b2aae12086e1d062edbc53be972711ddc26216e8f02d7e9042792f7a7bc50629eb52f6f55c8eda9e13a0d724b336f74bb2d1c5ed7c2fdf1e142397227ef8bc83c6950de6a83cb189ae7e170c933fbab27ee4f990b65c6f539e13e41dd1f2717ea4dd51eb7639ee886fb211f54c6b5051f2b88fb7afd8e89ebc3c47db2aa32f37c59f0bb3a2e0e88db24c83336c2f37cb86c6df1bbd6e5c9e2b1809eb400deaa4b1f79c60479de19b795f43a0c2e5d667eb7c0e50ed65f2d71cba73722e1fe4072a56ef7078e3bc7cbbd357161445c4ee2178d707d20b95013dc570abfbbbab6308ff5c5b346e6ad1ad9052be1790e3c67516fc5bbf5f2442a3ccbf44ecafba374a1dab83eb2fb34e6e2a0b84d759e36268fc5c2fd99e14215e2c4231787c46d4ae4e230b84d3c3c6965de8acded29e33ef95cf2a4f92b3ad7d6f459506e0bf64655dc12cc4319e19675bc519bfb72fd6e89cb9d2f7f65e6492be4adacb81513f33c18ae0b8bdf19ef0f9b0b15c7bdc1f0598c3c1fe179a22e5f47bf8be3fee470a11479da6e8f65c22d677823debd817161575c9c92dbf4e5966ade08e8ba08f99d0ab751bc13076ec18e9e6774390be1ade633d6f43c30eead880be3e1bab6f85d997b3be2c27cb853f14160eecf960ba5c4258f97bf3ae356897702bcec9a77d2db73c87d72e0b273bc930cae0f04f769873b3be0aba29e40c94b47cb3d900ff2e256c178275eae8f09f7e9e972f6c157555d5b9ac7b2e3da748fa5c3f549e03e99706d1a3c961817a8572ae89683bc510cd746c567b92efbc73b19735b4edee88d6b7be1b112b92d9e37e2e23977f822186ebdc8781ecf7555f1bba46bebe3b378b7cce28d34b87475f9ddeebe967ec7c82d1979a31d2ecb9d2fdae2de14f82c156e157927c5678df7564fb728bc93da6db5de488afbc3c59df3c07de17e77c5b3f6c35fbd9e3541fe4a81672ce97933dc17d2eff8788ee5a71ef775c2efaaee8f21576a5e1ee4636df0a431bd159c302e67235f14c5bd6df9ac25eeadea36052f5dc4df05ef147a27265c5c1ed7c9c96d39f13a232e771af92b232e2e85db24c793e6e6ade2dc1e44eed303b7c787ebb448d5139e0a97678ec7a2f2742df13b0e6e0f11d7a9ceed09739da4b8b6373e8be849e3e0add254353d8bfb21acaa26aecf98fbc4c5f529739fccb83c873c56075786c34b81746f88dca602ae4c8caff2b20bc6c5f3b6fc82e59ea740559aebe3e53e41716d927c1697cb58ec7965eecfd39d8374fbc23bf1a91ae4b6bcbc0e4b951ed7c6e5b1aeb8a45979abe2edf1e03a71716f56b749787b64d769cc7571f13b33d7a6e6b1eeb8b8a4dbc4c4fd815da831770c7e12f254c273eb7cf9f2f23b3b9e716ef9c71bb1f0a4e5f1564d3c63393c0f89eb73c07d22e1dac63cd6194f25b75ba7b743bc13a35b1e7dd12177325f3e5dc68278de12b7acf346405c1f392ed493dbf3c475ba7ac6de3c8f877b5be0b372b8383bae5393e7ac8db73ae096ebf53b264fd71cbf0be1fa14719f22b93c8b3cd6f072b6c05729f2a43df2565d58715b4caf33738190aed413f7393e28895ba5f34ec8dc1f252e94d5f5e9dd27189e32069e87bc3e47dca7492e8fd463119faf087ef74621b836333e0b808beb729b6cf8059be2795a9eb320deaae759abf357bcdb7ae075bc2aa8dbb3c175bae2022970a5ca5c9b1e9f95bb9c6c7cd110f7f6749b7c7ec12a78deee9650bec88e6b83e3b39cecd8dc1b9ccfe2e38bfb13c59dc3bb3d5eae9313973b467fd5c1c595719d6217b7c46d62e4f658719f5ab7b5e48dd0b83e4eee939b672ceb79735cc28a78de955b76f1461d5ca0d89542e0faac71a1985c0ec90fa1719508dd3a4b2ed0962b65c3755dfd6e885b7af146636e8f0ad7498feb73c58582dddb9f95c1b315fc9c11b735c1eb2278d6846fb5c7c521729d80972d2f7ee7bab6358f85c7ed81e43e65b938116e931af746c26705727d84ee139b8bfbdd26a6bb211f44c633967c1e1cd755f5bb20ae6df8586a5c591a5fa5c1731e7d11085709945be7808babe036d15085c413a88f4b274a959aa21b6e49c31bf59eb427de4a877be3e2c2a6b83e57ee9310f775fc5d20f707ce85c2e3fe142f9418cf5ad45f1d705f49bff3e39618bc14232e67175fe4c3edd1729d8cb84a80b70eef9668dec8e739a77c91d2c545709b4ab83edfa70b2ecb2e9f809b5bc6f046ba2a039eb327de4a80db127a2336eecf2157aabc36a7cf8a724b1dde688127d008978eebe212b94ec16b43e3b304b86c3d316b92fc95effe6070a1aab8ad2baf63e0fa04dda7a50bc4e44a4d7067e28326b8b7309f55c505ba5d29dd6d21bd0ecce50e0c7f25c26d69791d0417e7bb4d6cae92e0add37bce0479abdffd81dec8b8302eee0f9a0ba5c62dd807cf0b5ea001ae9406972e2ebfd35d16ce3b79dd71f8a0dff519ba4f4cf796e5b390b8b6151e0b5935c0bdd9719b6ad736c16351c12be3e21cb94e115cceaa7c95d4ebcdb5597d16980b94e64a79f1ac3df1573cb70780eb84e6b688781d0f1788cea543e5b296e6adea5c9c99db64c56d497923a7db73bb4ec6e717f747840bd55435c32d1ea6bf7ae4fe8c71e71cdd9e32d7898c6b637aaca77bd30745715935dec9059740385c3a3ed7e7759f3678be02f8dd16cfe9fb22334f599f47c77dc5f95d24d747920b45c1b58df1593ff7c6f359c7cbf3c6633d7067ef8bca3c6b08bc959c5bb2f046509e40295c3ab1eba3bb4f2ddc1b049fe5c3d355c7efde5ceed4f1573b5cce22f82a469eb545fe2a775d5afc8ecc05c25da9ddbdbdf92ca8db93c0753281a7c1c57db94d38dc9b9bcf72ba3e11dc271eae0dcc6375f1a4c3b5d1f15904dcdbd06785704ba8372aa12a8aeb83bb4fc7fbcae077795c1ccf6d9ae0da36782c322e4f1c8f15c1b3ace01368734be68980b838a9ebe4c06dd013cd6e4f93eb04c2c5f9709be6dc9b9cdbc4739bc23bd9b904cae3d241e0e232b84d3d3c69c7b75ada0543e279586e09c21b05706f523eab85fb73c08532e156eb8fdfe1ae4ff03ed1707d22b9505b9c9cb9353ff8a212aecf1c176a800b44c195bae16ec6071dafcdca633571cb2fde08e9de9cb8b022ee6d7cd010bc126ecfd57df27219733d8fccae5721cf03e00291b952585cdb149fd57acef0782b29f767850be5c7bdd93e8bccbdb1719be6b336c75f113d5d6ffcaecd6d25f1ba209eb4376f25c2659f36001e4b855b3c6bfeaace258feeafb8b8b836b7898c7b8bf2592cf038b83f355c28432e679d2f92e2ba14f95d0c578907b7ea91cb9d25fe6a85cbd996afa273290be1795517f7c675fa09d2e22ae1e0d6e9727f7eb85074ee485fde71190b7a9ed2e54e0e7f55c2c529719b16b93c693c56f0dac4f82c9fdbeae0755eeecbcdefe85c1cec365979d25e782b15ee8fd1856ae1194be379575c2001ae1496db72e17523dc1e28ae13d6d3d5c4ef3ab83832ae136c170c86e745708bc113bd707126dca637eecf980bc5c5f5f9dd2719ae2d8ecf7a72bfe28330b83d6dae531cb7ece08d5a97b3e1574ddd66f14eb25c4e3fbe6889fb93bc5240b7a780eb24c2656b8edfd52ece86dba4c753767b5ed3e51ce48b9ab8e4b9f257635c1f21ee539ddba32772737f38b8505ab85cb85472e5d6a1726f675cd8179793cb17b5b9383dae53019713cc1785707b80aed307b7a4f3463fdca33e288b8b9be136395d20402e9ddc5389925bc7e7fe98b95067dc1e3dee53947b137e160ed7278e0be5e4568b8fdfddee3b7c90f0fe1072e7a4b93d155ca725ae0d8bcf925dee50f057642e2e86db94c79316c55bed70952870eb1870bbe58948b8a5156f1406a643d598fbe3e54241714b43dea886aa1e6e4d7827b32aa78b23dea6269eb1149e17c4b5293d969c6b033e1610d7478c0bd5735bc7d76d707d8aee139ce74c8fb7d23d67566f55e5ba92bffbe1de92b7e9776f1a7c1616f7233ee8cabd0df059225c2504dc3a4e2e4e86dbd47471bddbb4745fb3df4171e912fe2e813b2bbf2a885b6af046f3da5cee44f257485ca0e395bae2494be2ad6e78ca60cfbbe3faccb950c027accef33cb865d117b9f1a4d5de6a824bd7d1efa45471200507f7c7912b55bb4068ae5417570902b70e0117e8812b75c2e5ce097ff5e6026970a590b83e46f769859d1bcfda107f15bb949d79de24554f4f5af2adc0784ee0177d70e7e28338b8ae457e27c3bd6171614f5c1c15b749922ae42dd778a333d7f6f45952eecfef42d1f0e4717aac092ecf158fe5f3a439bd95134f9a076fa5f49429f1553ef7a6c66dfa2a5972eb28b93eb4fbe4c1c50ddda60eae8f08f7098ffb93c8957a5d5b0a8f4548d510972790c70a73cb32dec8f8042ae1d2793d6739bc154f950b4fda086f45c26d4d79ddeff6f4ae130cf766c58535715b03bc511cb704e28d22d805c33dcfc955b2c1ad63c1ad9624bf03e0594be3af98dc3288379a727b5ab84e7d5c2546b78e02b76cf3464d2e79c6fcd51ad716e5b16c78d29a78ab1c765d9eb52ffe4ac92d7f5fb4c7fdf9e2ce99f2a445f2565edc8235795ed1bd41f9ac158a6cd8b171cb02be088e5b1ef246365ca03a974e955b26dfe888fb93e642ad717b60d78983272d86b75ae1f6e756c58531715b14bc8eca5306c55729b9e5983772fd7201fd4ee8964b6f24c0b5a1f058835c1cd16d1a736baaf922136e83782750ee0f1e77ce06b734fa223c9e34346fd5e629e33d4f90aaa5db324f14c4bdd970612c5cdb0c8f2575393df82211ee8d91db94c06dddf03a166e697ca3daed39e33e01dd0e9f4887eb23c5859ad767779f5cb83d70ae531db72abc139ee715fc8cba404457cacbe51ce38b80b8d5c2fa9d00b7c427e2e192a7f7575d1ce341e2afaaae0ff03ecd707bd85ca737aeeb8bdfa179bacaf8dd9ae7ceebaf1cb8408f5c3a566e859e08777f20b8503d5c9f9efb44e6591be1ada6ae8f23170acbe5c4e08bde5ca0a22bb5c1a58ce97954cfd9d35be5ee5f7c10d2ed29e23a3d727b7ed74986cb1de35f29f15ab83c6a3c96f0da1a78ac22aeed8acf8a5da039978eeeca16f92a152e63333ccf88fb13c995c23d6b02bc151cb767cb7542e2b276f456805c2540b74ecf2df1782338f756c685757177e38388b83f642e54195736c33b31756d2d3cd621d7c6c16395716be589da5c1b209f05bc363a9f95e5dedeb84daeabe4805ba7e8fe0472e77cf08cadf03c21eeadf659c5db22de89eec963f5584c973b66fc150db7539e68cd6d85f03a34f7f6e5b3a4b8363e3e6b775b456f2447d5998b43e33aed5c1fe17daae19652bc91975b3af9a2356e4f23f7c9cab571f1593bb747789d6ab838236ed321f707ca8552e1f6b8b94e72dc1f0d2ed415b7c780eb34c22d83bee80cde0a973cc3bf62e3964dbc1105cf27f8c94793d2edd1e03a55718184570aceb5657d1606f7c6e5b39ab89cb577e2e6de8a3e6b840bb4c19552e2ca607827eadc9fdd858281b7c1c535b94d626e0ff13a7d717fd2b87326b83d58f7e9cb9307eab1b65c5beeb172b83e56ee13101727c975d2f2ac35f1573bf727880bf5c8b5f53cd609b71a3c510ccf5a127f457362cd05aae04ae570195b7a9e0ed767769f90ee597c900617e7c46d72e4b60a78233a2e6ede26086e8b87d7c570b943c55fb970d93ede490717c7c06d8273b943c25f85707da82e5497e7f479276f2e7790f82b156e8fef3ac5f094c99e27e73ec5077db9404dae1405d7e7900b05c1e508b485c1ebb6dc560baf13e129f3e1abe6e5ac82afaa735bc3d785b9057be3795d6e8fd1755ae1deaa7c9610d765c5ef88970790c702f3047273e9cccbd995af6ae4fec3073d705d81fcee84fb075fd6b93e18dca72a6ee9c41b71b93f155ca8266ecf08d749cec581709bbcb84a76b78e945b46f045833c65043c2feafa7cb94f51dc9e25d749e97ec2db6a1788812b25c225cdf75648cf9a237fb5bb3841ae53eebab07e47c4c55db94d2b5cdb028f35c46d6d79dd94fb9c0feae2e2a2dca633d7f6e5b1b8b83e30dca739f78776a1929eb6d8638970711cdca6202e77acfc55f1f6ccae13d27376c45b01dd32ce1b39b97481f91deff244f258676ecf01d78984cb43c663f1ae0f93fbb4e649cbbd5507f747860b45c8bdcc978e5c20de9502e17206c25b7dcb30de68f8dc997fc5c0e5f9e3b1bc5c2543b70e9327509c4ba77567e38384b805abe3795fae9227b78ed0c511729d769740685c3a035cee04ffca835bc2f046b95b2af045755cca80f8aaf22ae9dd3ab9db13c2759ae3966bde0880eb32e4772ddca9fcdce22a49ba5591dc57eb774adcf2843732e0963cbc510397b0e4f3884fdad25bbdb92e2a7e37bc47f1415dee747c9012f746c385a9707d9edca710ae0f08f7e98d4b181bcfb3a00a876b8be0b19278ce8a78ab9f4b1a96b7325e9b098f15c8b5a9f1594cee727c1012b7b5c4eb8678ca90f8aad72d074f44c3f551ba4f6d5cce28be4887676de7add4b8b7103eebe9e226b84d305cee40fd950ff715e677722e0e8ceb342f633e3c4f89272d85b73ae1e2bcb84edf1e13ae53d36d297923322e5bb6b0bcae81fb93c08542e1b60878a3392e50d095e2727da42ed4d1b391bc9332f7c775a138a8cae0395be1ad6055355c9e461eab787f46b8504ecf9792df69717b84b84e8e3c95d42e9d1bee4fd595020036c4c595709bdca8b2e0da0ef9ac089eb131cf8be1022570a5c85c5c1dd789c9b3b6c55ffd5cd2c6782b219eb6d9638d708b6784bf8ae4b67a789d0c973b417f85c1ed295e27306e4f13d7a96a888c67a33cd1ef0241b95266ee6dea36f99e343a6fc5c5ed29e43e2d70691be2b1a62ecb2d9f00d395b5f04d0cf1ac11df8a912bf3e3ab986e817827075c1f362e5493eb63bc4f633c677fbc55efe20ab84dc57b2b3f6b838bdbe136f9717b9cee5302b7a7ea3e59707bb85c27252e8f198fe5bbb62d8f55c52d1bf82240ee8fed421def501f44c5b5d9f15906dcb5f820314e96eeadcb6741715fb1df39716dbfc7fae159337aaba6a21a2e77627f65c1a5eccbf31ab93f465ca8a967acea79715cf2b4feaa89fb03c89d53e65246c1f318b93e08dca7126e4fcf7522737127dc26382e817cb874802e100157aa837b8b7d9607cf1ad05bb9717d62b84f815c5c18d7a9bc36363e2be8de889f25c6b525f25954ae92dcad03e5feccb973cc5c1f0deed315b767ca75eae1de22f8ac1f2e67d51755715b2fbc8e84eb3ae4772e3c5d43fc2e835b26de89f05236e579885c202e570a87aa36f78777a162b8ae177e77746d373c569d3b141f64c1fd41e242513d6d4c3c56d5b5f9f159beebf3739fccdc9bd167b9704b00be288ce7620a24c9a583e5da901e0b8dfb94f9dafd0e8ddb8abd9115b7acf245c88bfbe33a41b9b830b76987dbb3c4754a3e61733ccfcb2da778a32f4fa037974e5955e6defeb84d4ca4e8e096405ff4c5bd8b0feae0394be2ad945c5bf2b3ba5cc6963c4fcd3d3c36fc15d5f529ef5306d7d6c16399714b28dec882eb5375a1bc54897095106f9524d735c5ef3cb815abf23c13ae4f0bf7c98fdb52e27542dc9b1eb709e8de04b94d439740625c3a4e9e1d7a22009e402d5c3ab3dbfae175345c1f38f7e98eeb93749fc078ce76be6a896bf3f2585b5c1f3c2e1402d716c9675170b9d3c55fc5707f18b952b2dbe2e0755daa7eb83e66eed319b7628e3caf8de70c92b782e09662dea8973c3e7f25c5fdb95d2832f7c777a166b8a5166f24e63961ef84cdc5555da70a2ece8debe4f3a415f156355c9c1ad7c976b933c85f097181ac5ca916eeed890b33e2020daf9414cfda0d7f352f7718f8abe12d1f79a320ee4f1c77ce97fba3c2858aba045ae3d229ba9c577c110fd706e7b1fa78025d5d3a5b9eb343de4a78cb46dea8872688b83fbd0b25c3f5f1e342f52eae8bdb94757fa2ee1ce3ad16f2773e771e3e68814b17ef7707dc96ec8dae78d284de0accc5adb94d5ddc1f2b174a88ebf374a1a25cba967ee7c06dad799df1da0cf92c082ed0d095ea726751be6ace6d99f03aa6fbf3c79d43e67296c157457281ca5ca92c6e69f5464a5c5b098f35e7966cde68c905225e292a6ecf09d7c9e90215af5415f775c1efeeb88ce19e77e67efcd2e936cb13c5d961706f71dc26d8e54ed35ff570c923e5afb6b8554af009d4ae0b86df5db93c6d3c560377e6bea878b943f457193c6baeb732e3f6f4709d14b9a481f15641cca1726f1d7c1617973228cf03e472367d1112f7213e88ca2519d707e93e75717fb2b87318b8cd7a276a6ecda52f3ae1e2b8b84d5855055c2000ae1403b7c5c4eb88b82d33af1b7327e3838acf9dff6a81fb63c0852ae196be2fd2e3dee8b84db35b1af146579e34296fc5c1e52b8be7d12e81e8b8740cb89c667c5110f7e6749b7a6e0f9dfb74e5be42f85d9d27ade8ad3078bac6f89dd2f5a9e03e2d710bc013b52e6700ef44844b1907cfab736d6b7c56937b63f2596c2eeee836a9707fdab8732ab84053ae940ad72784fb54c7bd1d729b08b83f3d5ca8462e5d18fcae779534b97502b8b7259fb5747b80b84e52f7e6c26729f2dc91fe102f54181737c9759ae0e256b84d74dc3290377ae19665dec8766d353c9623f7478d3b67cb9387eab196ee6b84df4d727fe8b873c2dc1f2e178a89db23de49ef02bdae54d1c501709bc0dc1e16ae131fb78781eb74c33316e7793ddc1e32d7698c5b06bfa88f5b4af92239b7a5f4bae2bd65f05957dc9a71be288567ece979615c1c9bdb04c6fd695da80d9eb61f2b846b93e3b30620c2725b00bc5119f7678f3b27e90299b9525adc128d372a737f84b850905cdc0fb72990db53bb4ec367ad88bf925da02857ea83db13c77d1abab6101e6b8feb53e53efd7007e3833cb82d145ee7e6f6b4719f98dcb27927f3f6ec5ca7a4cb89c8173d714b47dec8870bd4c1956ae2e282b84d83dc12893792e0fadc709f0cb9b6111eeb8f8b53ba4d5c5ceeccf9ab20ae4f9d0b95e596037c511b5a54595d25636e159dcb89f54556dc579adf1d726f297c5621b735c4eb76b83ec3fbf445550acf5a9cb79ae4dad03c561d17d7c675eab97409fdcec9c541729dacdcd798dfed717f06b973d0dc56933752e3f658709d9878d23e782ba65bdaf046bf67ec84e701716f5d5c18151797e636697139e77c1113972e26bf23aaeae0fe74b9504f5c9f11ee531ed796e5b1a4782ed49e3bee1301cf191f6fb5ab0ae4f26cf15800dc5b9acf8ae3de78b8b0192eae8adb34c9b52df259562e656a9e377571855c27de2d0df8a2389eafdeefd2b8d54ae4773fcf581ccfdba26a8abb1e1f54c57366f92236972f239ef7bab6aacffaf2a42df156385cdc13b789ce13c88f4b47ca2d05792318aa8eb752bc93072e955470eb1c5dde6e8ceb92fa1d0d4f571cbf73735b1bbcce827b3bf3596ddc1f172ed49cdb8ae17526548df0a44df2565fdc9f3e688a678df65669dc1e35ee53004f9a1d6fb5c4f551e3422db925d51b21715bb637ea62172ce979bf8bab739da85cdc10b7a99027edf656145c5c0db709eaeec40751b0eb65c3f3e62d9778a309ae1229b74e02f7c7893b27777d02b950c1276d87b7826157cc8be755717b92b84e935ccab43c6f91aae1b545f159f34ea32f22de9f242e54d5252c8de755707f22b8503e5c9c19d749765b655ed7c1e5a4e28b76b8dc29e0afc4dc09f9a0307878b70790fbd4bbdc09e1afdadcd28c373ade1292371282a8816b03e1b1f2b837342e0c8cebf3c785f2dda9fb22e3ad96d4ef802e5d1efc0e78717d5c27049eb403de4a835b46f1465dee4d8c0bd3e2da0af92c076e3d78a21c6eb1de499a7ba3e2c29678029d70e9c0aa109923bc3ebefb14c3fdf1b9501f3c6771bc5502cf5a187f05c0ed41ba4e5b5c1f0eee93164f99ef79830c9d716b7c221feecfec420d9f3229be0a80fb83c285e2e3f644729fb43c5f6402655d3a14dcd605afd3f28c79f03c19ee6b83df3d5d5c0bb7c98eeb82e4773a5c9f412ed402f73c3e088a67accbf358b82ddc1b7d710924c3a583bb2d37af3b73ebc5c5f36a4f5a236fb5c525cf93bfbae2eec2dfac6e9d3c51d16d05bdd11a17c7c7753ae0e270b789cbbd45716148dc9befb368b8aa90fb93e5421d715b3abcee8567cdf75650f767880b15c9f559729f94ee0f01176a84db83c47592e4020572e9ec2e4f1d8f65e5fe0c70a1e2dc1b9ddb24e5de04f82c10ee687c5099a70b8fdfc5b93d6bae131bf7678d3b8782dbd3c075c2e1f670719f66b795e5750f5cc66c78de11f7b6f359c6fbd3e642d5717fccb87324b88c0df03c10ee8fd0856a737f24b850465ceef0fc9597db43c87d125e9c1cd729805bb6f146696e4fd67d027371735c27016e89e58b12a932e4e246b84d6cfc82edf1bc304d6bee0f1f770ef1deb6b83029aaae6e4f10d7a9912bb3fa2a1d9eb7b5e29d5cb93e3ef7a9cc93b6e6ad42b84a7eb7ceeec903c663e5aecf19170a80dbe3e43ab9b9382bb72985dbf3c87d92e0fa38709f72b840085ca9e2b388bc13e2c541b94d1f3c775a7fd540951317b7c56dbabaac1eef8483a7edf558712e6b6cde0a926bc3e1b11e79d690de4a91ebd3c885ba727f1ab952b45b36bd9108b7e7cc753ae3e268b84d4fb7678dfb24c0fd8d0f2ae2768a7702c16da179ddf072878fbffae10251b9522b5c1b99c782e3de50f82c426e4f487098cc2c0dd780d95254458a1426e2704d1a5dae8509c5519068d4e9927e43a3d0e72b027d66d4984142fa6d9942a5822d587ec7f9c4d1f108d4f57645dd2eb823e678b9a36f3aa12b0e7fc7638fa83bfa8c4d1cf17ebfdf5147cc158bc062afb71b32719424e4017dc06350771cf682bd9e6e89236312efd82bf68ec0e24fb7dbf58e65803a3468cc9c11f250984a1ce586c15ceec81bfe8841e12ee9a7dbc599491ce58e452350f8230e8fbe5f2f18ccb141e28818cc0187ba23914834260181c5e211473c61f0f74b12261d8f4561926f1734e26848d4098db9a22f17dc19733a1d9c59c4519270f70bea78c5a14fb7e3ed80c432401d4f8449c451f147fce578c09e30c8d30973bc37738823dfaf780cfa843a21ef5706a8d3ed94a6104749bb241f3129373c068b399d2eb80be2e8c8eb25f18c3c21af38e4e58845a16fc766027154d4f5927ac11eb1280c167f3b9e92d20f47c2dc8ff7f3118f3d5ef1d71b167965803ade0e84e9c351f13724fa843ae19108d405814134b38723ddae674cda1d75c71f0f481c0ad34c1e8e7a46a2b0573ce68c3be3af47cc19c9ec7094f44b0a1287c0e2ce374cf205733c36bf0fa60e4749395ef1c80b0293929276b9e210685c62a35406a83b337338fa019388c75d124f28d4e58cc79dae0c70d7d39d212aa149ea2d4d1c8e76c51dd0083cea7a3a1d4fc823faca0089c6a252156351898b30a76b60de7014d40d85baa36e38f4158d3d2151d7cb326d38fae982bc9fd107d4018dc420ef57ace128e9d8d3118947a250a733f682c1200d473ea24fa8db097dc0dd50981bfa8c40dd1d7386a3e0aed7dbe57c3a1e31373ce68c3e23d3b028458a0ea969ca70a4cbe58cc11e4f37cc019986c53517489192d3cd306338daed72ba1f9128e41d7b466331285c624a6ac326589c301ce588bca4dc3107cce974bfa3f0182cc3d3a96913d425cd178e8ec52271a7e3f174c59c6e9803f224f805b9884172335d3802fa7ebf5e52af28d4f188c6a12f8e19364b466351498d4e385b381a128949c59e4f07d409773ba290c8345c22b241c3b4a4c406090d9a611a363ade64e12898331e81493962522e09d833f28e65803a364841a62525363bdd5c2198ebf97e3e5e4ec8e3097b3a9eae07e4e97445e0709794e30979399d11785c42e2a9d1e99894dc9859e3db60aa70f40bfe8c475e30c9b8cbe97ec0a4229699c2516e984434f67ec09cef98dbe58440148e7c40dfef9734dcfd80436130b8fbcd138e7cc71f8f084c0a1e87c29f2e09c82b03d4f1b278c0e04e0714fe80bd5d52eff8d32d198b66dc282d59602c431c569122a5ca510ed86be550aca31f312908341e7bc02251e7f3ed7865803aa014295e8aaa1455a952f4a508cc96a2247a7544f41983c4e0af474cf2098bbfa1d0aaa71302733f234fc813ea8042a130a9d863a155bbdecf17cc0981be5c4ff8eb15893b1d91173cfa806580ba9f6f278114294560b6e8805447c36351b74bdafd8ec1e06e770ca2513a22c159620a1681c1529445ca95a22a455986144891b26698669783a1c9a3a1b078ec05893aa130c8cbe58452a404dd4891a2d321e9826e76c2a9a322f0a83b167dc6a45c6ec70b1681c12241193643098e4a4a4b16489122454a2fa8e3e9805cc42055aa931cf180bde390083c260977bb1cb177ac24473a616eb713ee7cbc635198148ce4c8c83bf69276c2232fc9d8eb018b49901cf574bc1def57ccf188c05d8f77d4f5911ff017d4f97440dd0e28e401733ce1eef733ee8849411d30f8f309854621b1758e74c0e150a81b26157fc6a42423d04886f7858ad1cc12182952a45c99a0a84a91044560b61451b1026749298d91022952928a48c29e16a57364240a8dc69c11c82bfa8a49c4dcd091a361aec70b167fc35e3008d41d83b932409d152952a448e12206494d1b3922f2883b602ea96704fe78c7df4f57a9239e91c7e3097fbede501714fe8c45468e80c35db027dcfd72461d4f674cd29501ea9498d464912265c9c864064989498d19304c59d2282d5d211ad77c912205c8d351d1458e80c65c2f670c0e9384bba051f82b0283458a14a2d18d0fc806cd9a34667c399d22473f1e3077fc0985c6a4e010d80b12bf5010dcf9d1448e7cbd9d0ee8fbf182c6df2ff7cb259501ead6c0619222458a14e31a38607a3a245d2245e44878040e89c71f709713f28ec2ddaf0c5087b4a4e3b1d0438e86bb5d7118d4f178c3a06f67e4f1ca0075c6e27089cc9a36c1146ac8d1ae4714f284bf609231e8cb0181c232401d8f84228f7e46a1b007ec119384c4249fd1082c03d42121097755a1851cf97ec7de30583c1275bc5cf097db1172a423127fc024a22fa9c81bf27243e220473c624f270c1a73b9e331a833ea74395d6e97c6c8c4060e1b1d4f9023dff1984b0aea883bddd1b83356692047459e30c947241a85bfe011c8fb0583693ae7c878d40975bedd4ef84b3aea8045e2990272d4ebf57cba5f2e98044c4adafd7e3c3443374845a39a1094908a4325343fdd1f47c5a4dc2fa9e70bee7abca24e7814fa7144e4118149c39dcf08cc057db9619271a90d1b253444a4e00ecd50cd92b10c71485cd306e98c92121ae0ae080c96a22e45558ab61481d95224d4fd928ac0a8239e90e7e31977c61f8f583cf28a8ac0364569cc946123c54d5112b04d9191a84609090d9a2131d73312d554a0e6ca4f4cfb38f2ed8a465d3027dcf57643e331082c03d4a9b9b20bb259a3a42b1f47c1e131c7eb198bb961af18fc018f7b1c0d893be051b8eb017bbc24a1f0a8c75170d8cb058d4062d2d097132625411d117b476392ef28041e7b43a1ef677c3af2ed8ac3245dcf58d4e986494947a7a35cf00724f28ac1e051683cea8a4d47c1e14e18240a77c49f8f281ce671d44beae988391f5127fcfd763d201e47ba24a090f83b1e7fbd5f5210a82bca39ca117b3f63d2ef2814127bc0dc2fe98ea3a49d71a8d30183c1df30f8230eed381afa72c32130980be67e435f52af8ea31e51d74b2aea8ebe5f50f71be684741ce5763e62b1d823128bbd24618f079ce38848f4198d3c5fd1083ce67a3ce14f8ea3a251f8db158139201018ecf19278711c25f58ac49e0f68e40979bf5f121c47c65c8ef7fbe974c4634f48dc15df384a2ae686c7235038cc0d87c41d6fe7c65170584c2aee7ec3e14f982b2615756d1c15853b1f300734fe86b9a4a4a0315706a82bc36426841e1ce304409d10cdd0c8d3b17124cce57249bca49e30283cf2726a8c6890ca3099090189687423d4f988c6a2121109090e9399a5e19aa06e8d239e3057040a8bb963d2af27041e87486ece047f7d548d23e0b1e7f3fd84c5e33078ece5784965803a3767908e43231aa49e6f4747d338daf58639de7148241e8db9a1d1e72b03d49561d3668db0080c96a50a8a463521541004ea7e95a4681cfd7a3c622f68cc0583bf1cafd7db9501ea90948ac13378c1638f5834ea78c0a1b00c50f733e3c86824f27a3b239127dc017d3a60ae0c5087666864628374064d9b249fae080c16305b8aaa90516346686c1947bce0af6814fe84bc233069184cf29171742c0e833d9eaf7814fa7cc1a463718c23203137dced74bc9d0e48ccf588c432405d9809d00cd5ec72a81847c75d90580c1a8549b9e06ff72bfeca007564d420e98c648a4743e3962a45618aaa144d5054a588a90d0552a42c1d8d5e8c45252e52a4188b4a6aa448912245829c6e672c2aa9e9198d4b4c493e9d6e0ed1308e7a493961716724fa72c0a4dece776c038671e7e309873dddae180c127dc0e01747bfa0b028e4fd7abc9d1038140a93cc7891d3f1823a5fb027d4e974bb1df0e70b1273bbddcef733fe82459eeed7eb75d02e8e803b5e4e973bee80bc9d3189084cda25958b23e03169270cfa84bfdeeec7231689be3569ccf086dde2a8c8331685c6a070670416793f1db00c50173c32b511b2092e31b1e1f1aac5d1d057e4f17cbbe1d0e71b1287405d19a00e898d999d2e8b20d09703ee7842a0b0c703fa84395d70f7ebf97a44234f27e40d873aa2cf88266928a4a0581cf57a3a9d6ff73bf272c7249ff1782c03d405bfa4515aba22450a1b2633c3252629529698d8fccaf48a23a38f38fc158b49bb1d2f9703ea92ca00753d9d19dd2e4d1b35b5e2c878e4250577bf602ea82bfa80456219a02eb74bd3464d1547c5e111380412753ce0aee8e3fd76bc1d1547475e501814068bb9a270270cfa8c45e31b33472425a6e01447c7249ed0a7fb0187bca16e28e41585521ce58e46a0f0c82be68cc61ed1772c2a31f9a238d21187451eb0986404ee7eb9e38fb8e68d118a23def1a83bf674c4a390684c12127740dd1347be9ecef80bf68cba1eb0e8fb018b68d820e974453546a6374624631a639935c325323edd90695844dae98016d489a362f1973b027949baddd0281412874c44e39a37c6268e7eb99eeed8db1187bb5eb0574c02ae51fa317194e41b068f459def37dc0d7d41e171d7258e72bc621290987414fa823a1e8f782c03d4f9744a1c25e57aba9e8fd72bfa8e4062afe82b03d4e574c25f9338f2f572bb1f1098ebed8a3c604f474412fa8ac4d130c74b2aee80bb220f580416753bdd12131bde1147c21daf284cf2f97ebc9df0274c4a12ea8c3802067b426230184cca2501d914d5b4514a2ae24808d4e58ac0e2f1e83b1e73c1e3b1a8c64c086ada28a9410aea16281147c0e24f18d4f172c62071f72bee923a4430f8ebf97cc05db0a7fbf17839a030f7031e7fc1241daf48d4e580c71fb0421c25f58abaa24fb723167dc39ff0582c03d4f9a03488a35ed2ef07ecf580c4e22f6957eced3c281047441d5198ebf580b9639118f4f98cbddf714c7f3812fa763b23d048ec1d938844df8f5806a80bc1a886b7642c435c1a1abf2c317dd1e9d42c199998866b804b4c6c7cf0f57a42a08ec70bfe74c09f6ff7f3ed8245a0ae583c1a75bcdc91f8dbe5b2b48723229097ebf188c5e0d0d81bea7e42354a6bde187fbcf27044f4f586ba245fafc7eb25198fc36319a06ec793a03b1ced84c0618f074c0a027b456091382c03d4a9514a93468988846698c60cd1584452624212ee98864a688ebeea70a4eb1581bae08f474c02e6843f1f131b335b84391c1d9386c763b1972b1681c65c6fb8cbe170d4e3ed78449d6ec713f67ab9a3cf6744b3a60d981c03bde168381c1e87c6a42351a7ebfd7ebadccf81da70c4f30973c0228f9823168149badeb00c50e76322b65962faa2d30599d21c6b38e2e576c21d2f1804261183c324e3d04c6938daf1883e214f07d40589bfa4de94e2d0022952d82c198b68ccb4490afeb8884122d3198e8c405d30d813e67a3ea2d0c8e309d70c974250d386a7fbed2ac35152d251971be67ac65c7097fb09896f8a59c8a8197a9122c54846cd70498a14366b9474402e62908a8d2189571c168bc16312d167d4e97abc223058a448515a32c651a3a4468a94346dd4f484c2b013fe78c21ff0a7cbe97a395fcf07ecf584c123b0784c020273c65cf0182cee7839377de1c8b7fb25e9863ee1ce373c0289bca21932668a4868daa4c9e91aa80b473d9e30e8e3ed8ac35fb09803ee826580ba5d084a6b90d0b44913ccf5deec7864cc5009fed2b451c36be168f8db157fbb23b048dc0577c263af0c50c70649a9d8d331a969a344f42d31b1e1fdcac291af181cfa928e3e9f7077ece58a39a5a39a2c44336a86164891a27454630609c8450cd2b12b1c0187bfa2ae18f42515773d239067449334646a9326c7ab0a47ba632fc917f4ed8ebedd7117cce9ca00754868d018893d6153380a0683b95f4fe7f3057fc29cae97f4e322068983a270744ce2f988bd2461ce9824450a1a3446e28f8b18240d7ac29130774c2a067f40628fb82316874724354634401d129c354a445f51d1d7a6084c5192af4d917067c25130482cea8449c79d4e181cee7e4965803a354a6698866894ccb8412a2e2921a951daed844c4b4a6c7a16947054d41d8b471f8fe8030e8741e0ef98c6b844c2d1f0f84bdaf97cc11d51c8eb057fbd32409dd292310e129c242437668a48bc1d131b354a44249d8e8c1a33c22d231c0189bba1eec7e31d8f44e35027f4ed2210e16838f4097b40e2ae9864f4057b46decf4a9ca363d20f98cbe98240a31138f4f18065803a354634453546a4dece67249a41c3c64705ce11af27dcf57e419d5167d4251d8bc232401d129c9e066f8e7841611118d40173401dd11814ee88c337c65f96108e7e441f31c8cb15938a493de0ce672c03d431ad5142626263645a522ac30649a86bc3c6cc12195f90682cee98d01c8169daa8d9e2e6282714f68cc1df6fd82bee72399faf97a5cdd10ea8cb1d733ca330c9a7db0d85c71d16a6a39f2fe9a823ee76439d4fe7eb0179608aae7829da6161730434f28c40623068fcf974ba2191c79360e9c8971bf68e461db017e4f5763b1f0847bc5e522fc82306773a637158fc2531b1395a73d4331287bb2423cf98644c021a8342344a4a4912281d1175432190c82bfe744261cf67d4f9d41ce574451eb14814f2928e49ba9defd84b73b43326ed8ebf9dcfa7db1189bf5e120fcd5170283c02794562f1084cd21979ba32401dd20ec988664d1b26a4a33347c7e24e0824ea8e3a5d2ef7fb1575badd940f8e7e419e4f97441c168739ddcfc8866969b806a96864422a0ed70875109839f2058b3d9e6fb83b02733ca3af385cc39352e648b7e3018b3d2030b7fbed7ec6a46019a06e7785cc518f27e4ed723b208fe8f31589466119a00ecd70898c91498d19a4e270cd4eb7a47445183c1e25f57abb9d2eb703fa823c9d50f8f37111839481f148084cca197d411def38cc117d446019a0ce5740f1e8e81b1e7749c2e06f67240e7bc6231ba08f8b18a430c4a3ddcfe8d3118d429f2ee8dbed82bf32401dd31b2312d26f695866c706b8342c43ec7d493a1af68c46a271c72b0a77c262d1987b639460c91882d29631c32360f1c823ee8444e19178e4e97e422a390e3c48121a8fc0de9147ece98cc75e2f5706a80bee746d9098d21c8358908e82c61d31294724127746e2cf97b40bee744863823b9f5097ebe584c1608f97d3f9743f9fce07e4ed7cc79d2f09e8e3f17abf364846364bc3353d1d970e8e74c45c30c998b4f3197fc2a4dc3077347a01fec8b4493216d77070f4cb11813b1d0f78e40173bf5f505806a8635a524a1a0eb041128fb84b12128f40e3afe703fa7459c4107fba6152cf08d4097dc41df097f4e3a2c16f27ccfd823ca26e07dce572c0e10419f492883be130670406773ce2f0679c008363b038d4fd7449b9a18f972b1293c21c058d3e210f7814ee7242ddb158245e7094e40bea74475e12efc8fb0d7f3aa23008e648183ce68cbedf3007241a814060eecb518eb7f3f57449bde170580c0e79c63245a505bc1c1d8f39634fd8131e7b46dfaf17dc158b4a5d8e7a3b616e08ec1581bdde51c7d31d733ba105473d9d30f8db25e57e44a06ef813eeca007568d6a43183c4d4260d921213523108ace08898a44bea197f40df5057d4e57c3b06b81c097f39e031182c0a8bc09f70e7dbed760c5070441c262505853c1f316908cced72ba326c80badf96a3e03068f41d937e40e270a8331a736a8c6e8c48699496d6e8760b4c90643ce672bedfaf573cf2927cc2a5a22e8b96df30a9b713fe78c31ff19833f6ca0075c636209851d306898d991f972c47493a9dd1f8db058fb95e11d8d3f9d2487014241a8bbade2fd733067bc76052521925269e0e8b8e982b260973c760d07724ee82423444a49d4ecb9523e010c8031e7f3e63d2ae282c168b6580ba20151f173148bba3242b3c2150b7cbfd82c05c4fb7db05753f212fd7f3197d3aa34e7804ea86c55ff15894dbb541b3268d999d2f4d1b353ca634c710aa1c058d47a04e28cc09854322f038249601ea9498d49841d2e97e411f9b242a47bbdd309823fa7a449f5028f4e5766580ba9f9169c8f4c5b79b725414e68843dd4e08fce58c3de2ce5706a85ba3a48406a9a75b525a13dce9b888417a2082a3dfee38040679ba22cf08ece978c432405dd0b8a45465691826894a4ff7e322060908c1d1700804f68443dd6ea84b3a16736dd6a831e32b0283e54817e4220669cd034749c79dd1f80326057f4160122f582c03d41991d2282d1d75ba223058cab0194a2045cacfb71b96612345ca19078e80c6612e97e3e9927640e0f168f49501ea823a6003b9200fb8130a75bd5eeef7db097b3c5d0f28dc25e98cbc5f90c8e31d85479d14294c6d94e00cd1489122fc71118324020347451ff097db018d49409eeed84b229601ea908a6a864a45dd6e0908664bd192518d9a2cb99d980582c09ed017fc117f419e30e938dc9501ea42505a228374d44d203c12fa74493c629038241a79416352b10c50b7e3058f8e40df8f5814fa783c2170d83b16cb007546354a4821282d91098630f422ac02ccf974416070d7cbed78c1dcefe7d301774163aee7d3118b3aa01098042c9601ea9088401dd1e8062984e112b0cbef4877fcf17ec0ded1b7f3f174c4a3ee785442623283660d1be116df51305814ea8041de5047ec0589c1a4a5de516ec813f28abb1d31580cf6743d5e19a00e89a7fb1581c15234a5a84a119822305b8a88c6303f1dd1e8260b0f69d7816e4beea8e7ebe5883a5eb157d40d85bf1ed1c794e69833fa158541602fa9a8cb0987399db10c50b7342c43cce9de48311e8143e3b1c84b020e8dc15c92af0c50b7c4c406c9c864662904a191c9cc120648411f1731486ea21c15813f5f70982bfa86be5cae07ec9501ea9076ba1f539a23cfc7450cd20f4a1a25252434c52524249902431dafa74b02167944a28ec72be6ca00754c698ebc3649462b6c8645b95d9ba225a5a5a523295298d21ca548312e29118bc06c2942e2f9b888413a934030b8fbed78c25e8ec7130a73bc1d50279492c60d1a34528e78c75daeb72326198bbb1eef37049601ea8ac06029fa22458a14294560b614198943346b90d498415aa3b454dcf59698d6f08c4b4ac41e173148460490d8b45942425a7240ef1764c01ba51098840af8f9764404ec744445486f86698606d02129a121a38446802769849c202d29310d9b1019302480d092a033c461121a344a093459c244688900023409c04c9a344a0700f04409132035c6356b864d7e887c7a744f70c123539ba09bce58060989c8c64c9a26b6a271c9585c524242329a59624a808787068d9933b91d3606d4764a4a4b07d07443e3d20133283226231903623a364c6cccbc312600dbbd3173342eadc9bd9686463444242426346d8647631101d76e80960e8980725734b26183645c421ab229128d48ba333fdf6e0dd1c80638e11ccd2c19dd2019919498d6c059222231bd310e501d921a25336c968c6e90de18792b00c801865c350d9b610852868836a619aa691d7088136d3dc4b862ca0f0a6ffe41618d7fab314618a101ab314610a101ab314688d3c09c363d26a62fd8bc2401082facb96211a506d414d3ccb0069acf48f0c10f8e98e99579c11132c1e39b39c658b1472c93b4c21dc31f0f469803298031c50e562084032b1b5820c6831f0d66c8e00d0cf4c0004a1834752e68c06a8c3feb07cc0872b49ca0418000005002f4e3d383bbd978765eae56396f16d695551555726a12492281e4913a741c291b29a51831e44fc091270e69c48ad40b8cbc71c8221628b243542256feac1b221efc59b74332f8b36e86acf9b36ec811feac5b210dfc59374296f8b36e83bcf167dd04b9e2cfba05f2c6ad8f03fe22d108a1ad8715734cf9d2a104800e7452825274518c71cc282d19e318e39861d38688cd90288329142cb080318e193666881c6880c818c74c90ca97461ec90723065efc700395f4650d181bc03043ee870c141c28f80bba68c37b323135273c98d8c789f37050f8a42f441897283768792e32e2059fc4c32bfd3c18e167e0c8cf00050954de4bd01baf409ae1bd50f046201e04277f247a2e4bc030c86bb0e4b9ccf0658edf00834f9a408b9c08bf162f56aa7cf9228195291878c901e57e16b30667300687f982c1fc652f77d9822b98cb14bce509d672962518cb573edaca55a672803008fcf97abc9d2e97d34141220c9f951f16a57f21a1269853a047650a6f676440135d5a48dfba00072d535a767ccb8a5606ad3dbe0918bec5a535c1b724685df9d6d1b7acb4a87c6b4a0b825603df62a0156cfdbee56bf1ca33daf8e2c97ca35ce34b35ce28e34b324a31be0ce38b2eb678022b9ff8d2892f9b58e24b259030e2cb22be24e2cb21be14e2cb207ee8e14b1ebedc6102bfba2a155039629942a580085d4066df34be68fc0f3f93f889c44f1b1e0a083f5ff8e9c44b41e66713f3849f25fc24e10212fb196786f0d34d0179fdace102e2faa9e69da8e102d27a4a3157f849e6e710538899f4b3f8138a9f637e66f04138fcc4602e21c5f1a7121388298700399e8023de890e4e7020603e11143f137f13444afc49e48278246765c8209f83820924aa3e57045a780458f84bf817c1830e3688e08106a020e0c48a962c1260b97264a50a95290b0883c09fafc7dbe9724652a240512001040e30e0827f19f072f22f2f5e7ea25704134d34d1041344e040030a3c809305a47470cef6399ecfed7cae96a37d6ef639dce76e9f03fadccf22203d91cf13fdfc5272007c4e0903b9f9b9fe50e6c03211948926f2f1b0082530fad7d101065831808a152d57b44081a285cad11194232d5ab268c992254b96a3232d50a064b142658a9605b21c09b5440166398a7204054a962329508e1298e05f0600b1e8743a5dafd7ebfd7e3e9f142950a04489d2ebf1780b2c20140281af085e11bc22d07264a5d7e3f114383a0283650d162950b060c17224250a142d5aae5cb972e5ca95a32c4756b25c39dae9ae1ced74578e76ba2b3b5d170b2ae042c1ab0b5116ddbfd6fc2bf72f2d5aa468d182050b162c57ae5cb972e54a162d598ea44481a225cb91957f55a952a54a152a54a850f997962c4752a64c596001a13008fcfdebc8f7af2329bc7f1d4581727414454b96230512f897962329ff3ae08003fea525cb5114287364b9e38d36dc90c0c9802c77c0c1861c6fb4e106157894e1244618586861051438fcf0420d33d0e0420b2aacd0c412704c8873420922bc407857d40a1cf22e3ffac8c325c8bbd294f0ae3346979b773131993133697829bc48017c270cf87ef91670c509a56f6df99616323c6110f8f30983c09fafc73316220c027fbe1e6fb7ee0950180cbeecc58235162899497a43060d1a260a263023019ca212992740452295344328fe33149c394d39869a3514840913260c9b720c35bb252c149cd93d01e2f1786976bb34c4d3a44183a61c030c160ace487086cc57aea0c142c104674e538ea1664d054b1ec986468c3ff26860c031ca1836ff05bc5d9a354ac32f78382cd3e3ed74c220f0e7ebf1d680b1068c3560ac01630d186bc05803c61a30d680f1e71e9963a588224028124820893c0288218f2862c71f4b30f287d5237dbc61a5c71a7ac841861e5620e2841a4a008188166f24b108106bd851471c8a7801c61b5e58716105175a2802061656562ca148238a044205228c58294245219fa3420e2aa478048844a450438a25e644f188951510563c01051a4b3cb28455128fe490f89c531256393bc0ccf05c08a1d3c8e718f9dc229f53e473897c0e91cf1df239e4e708f99c209f0be473733e07c8e7fef85c1f4e767cae8ecfd1f1b9393e27c7e7e2f8dc1b6b98f13932c0e0028bcf59f1392aa2f8dc139f6be2734b7c2e89df4a18324609c8c4c8c4c8c4c8c4c8c4c8c4c8c4c8c4c8c472c220f0e7eb9d1306813f0d9acce0869b4136f0e1bf30f05f1ef90e906788df05881f5c8fe690ffb2e6bb24f0379869037c387abc972d664002cc0e1999b1101ce4a0e9918971e9804bc9650735349c199c1732d7f4f5783b5d4e1804fe7c3dde4e041bc68cf01754f0080a8954808393e60b9819dca8a06e06d9e00866042e8378d9024e073320b10407cc0e9c07c8c8ca24602c0483211ce49039004d6fcd1932b12f53b874d0e50c97b24b1a2e3b84e9433603977ba4a8d16a3db89b8da74693c15eae728eebc1e170379c0dc783abe16838190e867be15c1f8041ee3540e0b9f4b908d066f75c68cf25ca73997d983e9e8becb9cc8043e271453c6e87c7e5f0381c1ef7c2e35878dc0a8fd3e071193c0e83c7d5791c9dc76d791c96c745f0b8dfe3768f337a9c94c745791c94c729f038041e67c0e30678dc93c7113d4ee871418f03e4717e3caec9e3f6781cd4e3f2785c1d8f9be3716f3cce8dc7013deee7711e3caecde3981ec7e6714b8f03e1716b1ea7f438358f4bf338348f3bf3b80f1e67e671651e47e671c7c7191f577c1cf171498f1b3eaee771b8c7dd1e677b1ccfe3761e577b1ced71b3c7c91ee7e471b1c7c11ef77adc92c771f1b82d1ea7c5e3b2781c168fbbe271aec7b51e573e8e8ac74df1b8f9b8281ed7736fc4f0b9173e17440e882f47ffc54aaec78823de88218cf0f24668217a237cde089e2fe2aa08395f041d5f841a17c144116d7e88425e08312f44032fc4ee85307a2108f82000f920f4f8209e7820a678208078207af81f00f91ffaf81f9ef81ffa3e3cf23e30f23ec8f13e98791f92de8731ef4397efe190ef018cefa18befa1c9f370c2f310c2e3200787361e872c7f030e6f031736085183144f83164fc39aa7a1f83310f133bc99e1cacf00fc187e18f080a1847f81f84204dfc2996f81824fe1cda7b0f429a8f914863e05269f42ed51b07a141e791412791406f91360f8134cf813787f42cf9f50fb136a420c6f429737e1f7234cfd086c3e4ef2e3c8f171981e4e190fe78b87b3c087f0c88720c887d0c7bb917a3766bc9b2ade0d09efc6cdb7c9e1dbc8f06d72dfe6806f33f46d027826e433453d1b189ecd0abf34c52f6df04b1afc12965f82e09718f8a5df2f25f06bce3c9adea3f97934b63fd3c79f69fa3372fc192dce24fd19a22773c09389fdd1913716f2c6396f04e38d4bbcd18737baf0c6de1b8d3e69824ffa7d52ec91d47824368f347c240b1ec9e791688f81e4c798f063e2fc98a5ef00eb3ba0f31d14f21df4f11c80f01ca8790e821cd87e83a9dfe084dfc0020d0c780d805e83d96b303f03451e83a10f03f55f06f92f6ffc972efe4b0affc5cc7fe1e0bf4cf92fc1ffb2e4bf00bd97e47b112292ef32e7bb48f15d7af82e297c9733dfc5f85d20782e613c97239ecb0ccf8585e7a2c17381e0b9fc9ecb014618f167e8f828c30f1688f39bddb00161a532c624311984f962654a1c386f4270d38689cd12086b94d4a44173e6033365c81c8d4562d2013b9d4ea7d3e9a4481106813f5f8fb7d3ed8441e0cfd7e3ed8441e0cfd743e0005d4e1804fef34979a240ae88c6cc1b3366dc98b1b2254b0659b284d1017d41dd4fd7e3f9743b222b3a21f009eecb23bed4e14b2da698c1e30e0a8eaa88a1600b98bf78e9c2054d961af0979180cc0d7f1b25e2157f95871bb1615a93e6ccd44069b84e8d03ffa427f8037b441038295d3fd14e7c44bb9fe8924774fb89fd50e913cd32fee1cc61de3067086a3261f84af15385f9e6679b9f4c3fd9cc35d3880f62e1679a9f447c90083f3f98c689f41f77e4e7053fb1e5001a66b6f8528b2002a6d20705cd1404c00729f909a6139cf9c9fce4e0e7063f35b8f8277dd0fcd9e5a7051878f92da880820924680d6fe5366e5120d09e0709209e478ae7c9e279e8789eddf350e0c6bf98985c29bccbf8a5123f7c99c697687c19c69767c498f8a26c79347998cd247e492b0f98c15e70260a3f45f809e70fca6c450d970ffe604b712b62d8cc31d07cb0967b13ad23222a5b43a29e23ae5324f7a6fb2c182e4e83dbe4c32de7782336557f3c5d3bfc0ecc9386c85b61717b5cd749cc3376c7f3bcb83e3cf789f88c95799e0d17c7c46d92ba3241be0acef3f5e477605c1723bf9be152a6c1f3e83c674dbc550097c791c732de9e3af709cbdd8a0f0af3a4bdde4a822a12ee807c1017d72788fb44e796586fc4c49356c35bb5705b2abceecdf521e44231708bc43bf1dd5bebb338b8ad1c5ee7c22d6f7823e0b336c55fdd9eb1379ea7c533767c5e0db75c7dfc8e84cb27c135709be25c9e3e1eab82eba3c78532ba1de49d7870a9c4cbad73e5fa5c5d283017a7e6366d717be4b84f44cf59e58bd65cdb058fe5052c8bcbd8ef7970ee0ff042d5705dc8dfb1707bae5c2721ee0f1b770e97cb9d1ffeea845b254f54de72ca1711f22b36c6f3acb82fdaefa2b8af127e97bc3f3b5c2846ae12dead6374810ab9747e1797c36deae3fa14709f44b8dc91e3af74b8405aae140d9727eab12cb837396e53ecf235c5f364b767ce7df2dd1e11aed31d97403b5c3a3fb7660b5fc4c26d55795df03ec307e92ecf188fb5bb38d76da2f28c39f0bc116ecf18f709778176576acded71e43e1d5dc676785e12d747910b45e5fe44b9502bdcf2e78bbcb83e50ee130acfa17cddb836a3c7c2e10295576ae8f6e8709d0e79d6caf82b019e343fde4a8aeb33e53ef570399df8a21cee8f2457aae7de92b830209e31289e07c5b541f058485cdb249f55c1c521709bc85cdc03b76984db12f3ba0aae0d8fcf4ae0da1e78ac232e10f2d2015e2ad972eb58b93d59ae5311170878a5dcdc9ea1ebc4745fc4dffd716f573eab885b42f045825ca00cae94101717759d12b8b62d3eabf6940df0bc3eeeadcc67a971c9b3c05f7df18c31f03c119eb344de6a81ab04e956d5b94a886e9d26d787910b65e5dac8f82ca0fb8374a1bab83d4fae53084f47dc12ce1b115ddccf6dea725b4dbcae88db16de09ee397be1ad64774af9a2a47b73f25970aeedcd63f1716f419fd5e6494be0adc43c6729bcd5ebdea4b8b0246e39c61b11ab76b83d185ca729ae4f0df7a990a7eb86df79b94a3ab8558e54d1702953e17959f767830b95c573d6c25bc5aecb8bdf9db99c4b7c110eb7d47d51d325edcb5b99b904e2e2d219bae5066f34ab94b8afdaefa4b825176fc4c1c561719ba86e09c71badb93d5ddc27da25d017970e1118f727840b75c7c56db94d315c2025574a787b04b84e6a9e359fb76ae392e7f657515cdc0db7698fcb9d2bfeea85ab4477eb44b92f0d7ed7f484b9f03c08eecfd495fab93f582e5411b70787eb847cba92f8dd069740415c3a4aaa88eecdca670d714b1fdee8815bad3abf537239915fe4c425ac86e74db9e4e95f31f1a4c579ab11ee2dce67f571c903fb2b276ebda89ec7e4de96b83021ee697c9099cb53e7b1cadc05f9a02fee407c1004cfda9bb792e4ba1ef95d0ed726c567954f1b018f15c36d69f03a2eb71ce18d0678d6eef8ab274fda1e6f05c5c5f5363d70ffe383b6b83fc60b35c6f541e44245706d507c562f777efe0acc6d29f04678dc8295f13c2e578901b7ce00cfd9196f45c00582e04aa1706575be0a860b34c9a523c1edd9e33e49b9ad1a5ea7c2a5920c6e1d092e8e84dbd4c6b396c55ff954295da0462e9d086e99c31b092f67245f34c5ed51e43e45706f6ddca6f299c7654d82b79a737d6ef7c9786bc6f0452d5ca0442e1d069eb1039ec7e6f6a8b94e6adc32ea8d54b87c613dafc9ed0def24e89664de88e79247c95f4d717b66b84e81dc9e34ee1300b7dac0136170817e57aacd2de7bc910bb77ce28d2ab8b6dd63ed705f28fcceeab275c6ef6217c8822ba5c395d5f155c6aa159e37133e6b90db224eda0f6f25c36dd1de288beb53c27d72baacec8718298ae139bbe3ada25c9bf1b1dcb83c563c56cf5349ebd2a9e0b680de688c5b32f9a23260393c81982e9d5e1c0bb7a98efba3c895825dca7a9ee7747bdeb84f41f706c76d7add928d3742736d4b8fd5745b47bcee875d2f1f9ed7ba3d8cdc272ab7ec7d11d4ed0cef44800bb4e44a65b99c31bd556f0f96eb34c42dc37c14a54b9a96b73a5ed2b478ab1f9e3440de6a8aeb53c68502ba85e19d005dee2cf25745dc5bf1b3c6b8b834ae13cf2d87be288de7147ed1997b43e2c27eb865226f84c37d71f03ba8cb1d2dfe0a865b2f389e87bb4067ae1417f776fcac322ed0972bd5c3a58bcaefa2dc52f14e22b83d2f5c273f2e10ed4a417162bcdbf041bd8b33e43af9ae0f12f769ea598be1adb2ae8f9c0b75c0c565719baaae8d86c76ae45216e7795617c7749bc4b8a5f244205ca09d2b25e5cae0f82a0f6e4f07d7298bdb1ade0993274d8eb74ae2dad2f8ac25973b20fc159bdba3c4759aba3f622e1416cf1794df95714b3bdec8cdb3d6c15b25726d153c16161748822b25c3258f007f45c5bda9f92c392ece85db74c76539fb222d2e8ecb6d9ae1b6cebcce035e08b74d9e48f6ec014fc47bd2aede4a8cdb33c97dda726dc5c76ae3faf8709fa4ae8f0ef72991fb201f04c6fda1e2cef9dd5605afb3720914c7a553c02f9806cfeb5d1b0c8fa5c8edc1e33e19707b82d78986cbdaf14e3478d60ef92b29f736e5b380b8b833b7098b4b5998e739727f985ca8a50be4ba524f9e36011e6b852b2be3ab2eb83f265c283d6e29fca2a8db49de89998b1be33ab99eb4d65b61b936473e4b8227edb73aba3f75ae14cfe5cb8ae7cdee8f17774e04b75a78fc8ee776857762bb36061e8b8827d00a978eecb25abc130baead8ccf5272b953c45fa570d992e277bd3838ae9392db3ae08decb82d235ee743d597674cea796cdc56026f24e70255b9522cdc928a3702736d677c5600d787779f5eb8380f6e9311cf9a036fd5c72daf78230c6e81da52f33ae22d9978a32d97e5ed8bb8b857f14117ec7ab550eea8f05770ae2b91dfc1706f167cd613b767789dbab82d01dee88c7bc3e1c25e78ce6278abd97326c95b45707d70b84f873c6d418fd5c2bdadf92c3a9e2ffdcbcd3376c1f35cb8b7dd67c5f09cedf056b65bb00b9ec7bb2e497ec7c3059aba74b25cc6b078de14b7d5e575572ed001572aa96a83674d83b73ae4fa04709fd25c9c93db845405c52d5813cf93e0fe605da925973bbebf42ba3f4b5ca8ab4b1a036f35bc4a7cb78eeef6145d273877eebee8786f3d9ff5c1b386fcab28172877a5d4dcb2843722e0bec40769b9afdbefaca82abaa50b6f24e5e9eae17717dc52ce1bbdb99c79f9aa47ae929e5b67de96eb8da678d2c4bc159a272de9add65c203557ea8b5b3af045736e29f44568dc9f2b178a887bcb7dd60bf7c7860b75c82d14efa4814b59d2f320b92d266f94c6e50ef2af86b83f672e541ab7e5c0eb76d707cc7d92e2c923e7b1b25cdc22d78981cbb3c76351707145b729e92a31deaaa97b33e436155dce3abec888cb1da4bf4a737bc113b570cb45de4887cb93c86321dd328397f2c8b386c75f0d706f57b7698127ad8fb78ae2d6802732baa51b6fa4e65933e0adee78c64a78de0fb725c1eb1cb83f52576a766f237cd69c676d85b7b29262cc2da37cd11df7223ec8cae54ed55f29716d597cd6ece216b84d6f6e4f15f7a97cd20a78ab0caeeb8adf156f8f20f7097879ec782c2cf747903be7cc055ae04ac579be56f85dd625d014974e93fb73c1859ae27207cb5f192f77fcf82b209e73882fa2e11246e679c0aa12aead8bcfe2b9406bae5418b73ce08be4b8bdf244215cee20f257443c6759bc95d0bd8c0f325e1f302ed4ed594be4af8cae4df85842dc9e28ae53d62db178a30c6e6d78274d9e32079e67c873a2b2454f54c02d89be488dfb43c69d73e52a8972eb20706d5a1e6b8a7bbbe1c25cb8383ad769caadd713cf8bdd1604afeb5d1fac0b75c17316c55b2d79ce7a78abdbbdf1719b00b83e5e5c289eebb3739f92ae0f1717aa760b167bded0b5f11e8b87dbc3c175c2e2b660785d09d747cc7dc2e2dac43cd61877a70f92e2f67c9d2eb82fa5df25727103dca6e1a52d89c7a2aa0ae1a92476e99cb94a7e6e1ddcfde8a71797b12d9e47c5fd5972a140b8dc99f257c4fbeaef8eb840825c3abc7b33e0b34cb8b73e6e5300771a3e6877c993c15fa5f13c5625c75b95bc3d52ae930ab755c2ebd8dc1bf0b36cb895e089e03c5f50cffbb937063e4b874b5794df15707ba0ee13947b7be1b316b93e2adc273e2e7986feca8a5beef0460c5c250ddc3ac14ba02c2e1da1db009ec875e93afe4e78950470ebfcdc1e1aae9320bc2c1747bb4d125cb6d672cd7ed7e4495bf2565e2eee769b28b82f35bf43e4025db9522f5c1f35f7898da70de8b152b8e50f6f04c17346f55654ee487c1096fbf3ba501ddc86792217ae4fee3eb170e942f33b062e67c5af4ade16026f74c7d336f4582e3c6b63fc5500cf99236fe5c0bd0d729b88ae4d91cfaa727f40b8506f3c6d4e1eeb85fbe3c085dae1928780bfc2e27216fd93281727c46d22a40accf5e9e342ed9eb509de2a904b5802cf43e09266c15b95b983f919c82d5578a3049e30419e97c1bdb1f92c3cee4fd28502e3199be3795c5c1f23ee9324d7e7cd7db2e3defa591a5c2027570acced69ba4f08dcdb93cf8ab30b737fa8ae94923b1c1f64c4fd19ba506eae0df9590fdc9ac72f22e139dbe2ad869eb536fe2ae89643bc51958bbbe236252f4e91eb246c9dfb13bb5048f7f6faac313c14ee0f1677ce02b71cbe51ecde12b94d06dc960caf3be18ec807997179fc78ac2e1707bc4d6dee4dea3629707d92b84fc95be6f146719e31429e87c6c5056f939b8bc3729b58b825015ff4c6e514f345709eb1029eb774cb17dec8a82a86fbe3c185f2e27214de16c253563eaf8eeb03749f3eb8f562e379b78b93dda62bcf5a94b7cae35903be951eb7bc7aa3252e5b70fc8e76b993c65fd51094c1e551e4b13cb83d54dca7f9841df0bc032e77e2fc959bfb73c38542e43919f8223497ae36bf7be059dbe1af5ad7b6c767e92e900357aa84aba478ab26b925f28d68b8b7292e4c895b3c6ffe0a92a78ce77979dcedf820268a66b8b3bfca877b0c1f24e549ab7aab30eecfbc501a5c4ea82f4ae2ce7c5f75c82d5178a303aecf1b176ae8e29208993fa8f42a98e9219683108662008661281453ca20536a0500f314608038201a0fc8246a1c2469d70314000d4d96da96309bd2520c858c3106104280310000000040404020006b8681a21b248473a4a0b7e247171ad57212a864049ef5783bb11980f8930fd81ba3e0aa1ff694b5c2bf8647f7696bc1602013df2d8798a0a57179be6fe0f1dee152da91fe8208fb0aadac8a09e453d315d03f147350c9d78942f5b90cf5e0217d3251a278b28da7a654740602a2bb04ee8df8db0db95414bf69dab2f56b6cf85c8a6d51e6954b2cda8fb6be2c62f5cb59f514d8ad4674f0388b2181ca81adc88cf834d1912fb11e4f2b12ec0897176121fb6a797e69b399131122e07f4bcb5b3676a60422628a698cc09129b0510b6049ecdf75019a4c6d81b02970b92b41b59d727364dc58c1910ce8574768d692a0a15eb60bcbe43c24566ab111ec96c165f6e5fad4bfd086e94d1b9258afb4efd3cb1a083edbb30240890df117f50ada2759d95011f58996343aee005dc82549650ea6ff67c005d31f99d0d854c3f85c3a620e3f04a9b32aa425a675893d0b042521615f10192dda53425b430af643dd6b4763bc28a15aaa11ee64b7ee762467c4a2e77b8639a32db9153d8aa276eecf911e6c9ca0407c00c93f1fae55d8ff306f0fe31b8d2959519e928333adb761e27dca664a81d122322141633c4bad8bf0606e68881cf6402fcb922ef658d32bbc981a9b05fd296cf55beceb078ab23ca855f046305f5ddb7eeadee0ea516b9e3829ace5b8338ca01f4e49b72e40ed23cb459330fe5222edb3357f3b806fd205fd8271f2e622697ea5f6505bff050475e2fffbc47eb65e6407f32bf9d02434f7eaa8af126039570dace33f2c63b295c075abe9cd43a260c49fc10f08b731d04fb36aaef7b14c11f4fa584d2c5d4f4d689745922503480c1dc93a9a85c26b158c125e4e8df20c024af22613ebe72b2192e92fc4df8940cc81e619b16f9d26d35d11901d41b9e1ebf21809e82241a2efba08aa34b95ce274c93e73f297f9cc636875b2724e0c805b0b2f52b4676e5e46ed62197476442f0459f038818de303d873715fc5a74449cba58249078698b3f04a197dd30172939f0ef40f8e9e220a5d4c7748eee0f8f9066fa175ba2a49889dc56ca00e421b691d9837993c85623fb3195cec6511f125e8472b99b57c55eb43e3e6887601e8f481eaaa5d9c9e951cfcf5c03ba465a6317ac1a89b60eb4c65a1c9c5828e5b19d27e041395730832e82e891c89dde6d0e435d5e37cc2e6f354e9d7fdbd577d68b2ef79f3c8f4221522c07060850ad26008811683886a0ca0158d4424bba3a98ed60e45b5a72bd6b18d1785901c9eca73bb57f5dc36147efee2ae2e987a02c999a8b7cabe16baa8a3fe651c2ae025407839b74c504284771ad9c1b01a71e7426fdbc40544f1df13971e45941b517454be0260f0dbe860c436568da41b01d713c56125210ee0a14e0a7ec2a8bb5fbd660d3ccfc685e77bff843864481be06108b68ae0710ffc60f7f605143b3466c85a5df62dd1a8a5c59203063c7481d19b1dbfcb10583056f4790c7ecc533582764481d9951c1a4633ccca8dcf57a10470703d981ab9854f7535200d295f347cfc0e00c22787cd982f4c8c8c9e50fc08d717fc32a9cf1d99da14f3f207c58b8d9bfcd24917dbeadce49f4e76b1c9913ce9bb1ba3dbbb58efeff61c1de66205dead32fa8c8b1d8ae54fe7ce39d0d5dac138aecfc01d0d2c3eb25d97b9d827cb8e301ae11d7f291e7e61d065660d39c6924a3e5015b8242882e4272fdd3426e0d59d5975e4f751a322f5e85061643fadcd7c5cb6dfdb473c2e584360db02afc9c01c3373931d7981b6a8bdbb98f6f40cf5f87ae717a565509341b69a30208aa68b0d2df08c91df12500fbe88002beb678dcc2e69a7194b293a3c7cd86d0eea912cee5038b28c3d194eb9ef04bcfbdf851cdc430efcf6959335758259728c34da24de073a028cadce2204e29dd95cddb18a88256a68caacdbcc2b32a40bd17b845e2a3a60b69b1d139e4a7339438f0dabba87113058967a21527713d5c30579d19b0010f582846bf1e81a57a5122475e23237e841bfa688bf2b714ef9f7818958bfa708b89f8742506d846638c37c8cf140d250f802322a6431a6a03b5e350e3569a8dd10d755f4b7e25cdda07419f3f4c7ee494d513e4f6b7e47ee4692ddf4f29b03f2bd3afaa59b59d0fe6885db7e0d5dff7f796012758e518c6cf92281c0c8db4ff84026aef5e704719f89dadc7f9a3c8e694ecb1d6f714d139c771e4ea3eda75e80d3a4b328d22aec077372070299fc0f07327bd0320959701e64f20bded634a504da8438403cac3b1c478447563701d9da670b3f0304991f3a97d02c7fa94238643af8913d6050c9ca3219241d371bbeefaaba1ecee00094614ca82f0026a13d63527647b8e92f70c4ed927fd8211e80baf241c93afc00d445a0f795a3bbd2529b265711c0d774c31481396132879c231a19c3d53bb94ca0113926b5c895c04428b50d8ad6ec4d0f79c427d8a5ad9a052164f2be5a001f3655a116ac738c60d1825da6e172d128438c3a7dc2b57d3e77b456392411f68ffbfca457127051a0b85b039c790e80baa165c0c94b3cc3aea0a7ecab5dca90b6689d2c96d6e8aa4163d6fe0d9fb833ef782601982dd47678943e11268e93ae3dce26d819994220c4168c99904c879cf24035daa7be4cc971fa3c4889c2067af4a5b46696028502013b8def26ebc0f2086d8e67209083f9b77a51143bf895e45a652552613660428897f351a08e59530227dc88570d3a5e9ead0f65e1ed13dc41b19b7617568455144c5833673c90038a2df9c83c044b09086cceb916b23656f6445d25c07679a6dcac3338428357ec929264cba0bce50a202a27f90e2453911650e0895dd8acf5351d9a02ee9ae588dd3a80e2da26e625663cc302e46a291896d45efc2f91f38d19b61175e0fbfe5891221dcbe06ea3d1c65a8ad7c3e9e24cc90bf8df91eff8cf7ea4ca18a65f9db490ae69d3895e65b5cdd5c1f8880bb63f629a223bb7365ea01f3580dc7d3406ea8f1646fac5831823b1b252f40a25fc71320f834fe0c3f03183fb28e242c35ca611863895c280568ebeb2a849905a764e32b33cab8c23b8ee974c424756b43ecd1db587e8d40b71f25f925bd87f292e16dedbcdf7e2efa68e28eff54dade456897fe420eba706e45166845d0cb6a5316459954a08efaf5ca246bde144aac41be222b0bd843881569a3033a2d9989c356e6ebb70a91e3855aacb42f66b4759fafbda97a0a5c4aec8697bf4ea17d2ba1cb5abb69378c14a4c2a8dfbde1f777e2763c15fb0d4b09d9e11f29d63062cbd1565e1e25416a0900d8e8469e089b2ee6cc21fc8d11ba3ee068a2b520c841a4ef967920b6c3d6044fcc7c17cee4288bb15e33dcb520a77d8bd894b42a5e665fcd3fe7f9b2e7382be70811ad960acf1c77e8b8d9c65ebdc93608643776f65c4bc02fc594c070d3a6e642bd068b87b973e9ae434fbdf85b7f6835d744e98532625ea5f84e5446213e3f6692afc80af4cd5dbe5148da0bcd65ec599670b1aac0cce394932e93109a9ea3eec9ab1bbc4c89cb12e2c2739b387d707810e481d8b60e2efafe609bad13b9ca3d67b72617bb4bfebf43879059e34fcef460e8b6b0b16f5a07676e0ffa13e47404cd414dfb5c77bf953eddb5aac62760174671af9da180ad684631652a86ef23a8eb642a8a1b1ae948d6a393e0d4b6ca7c8590ee5de5a2c9502a54fb1a8ccb1a7647cb579da9dc61ef04f37932cfe4b16ea6279a287a94840feb3e5be15257c3e48973e0c6c110f0b5373699270441259418cb10ec5df47e7f5da0da43f3dd3fd9c64cb504788e9d1c762b7b84ac7765a803d6b411cb89210695adb6dea1f2ecdbf1459be3ab35fd89f3ce0e3bb644d1b1c44065e4c5366b08c6da540caabb8e37ef268f966f624c3fdc43d0501756cdaf52c9eb84fbfe231d24361b2068bdbd354943226be9298f5dc08fce3505bf0f165ef653b90543e54a1eaa4054ea41aac629a844d22ebc6f1950567eb21e9cc30e1ae927bf93fedffe3a1c3c397b695387318321d80c8cedbe198ae8ca3e13e5b47b9d9a47161b792e15a60c0b3f03aa59c6ed2357bb9e7298bd0f19681716652df950beb945c2abc218356b77f1787197971a1fbc7af2d3a73d70d7a8f21184a8878b6e6f1c83b80f308a3e0b4bf0d0c317a675aba1683f4e4189b2079674c18820c4e2ac084b67ab8fe1884dfb5595ff454d0d96dbc458b0338d53e2194d5fd5ce5586051c8b6c58cc061640953ebc594ff8bc7e97f911939f26b2ff71cff52af3b6ecff7f7f4fe5f35fc59f796083582572a53157ef4237a20696f52fc3610f1e8c9909deb798c0a01a09a62707b1ad522f1ed5518507c33d8f27d1d0fd3dec563757de6f92c4ae67dc5fdd0b29ec929cfda2dc34886282dd1f6a9649aa690ad9c9f1d146e41d5a61504ea3c9379e4ba897eb6e248a3b6ccc82f697f5f99e357544869d408eb0a7d883098e98fc638ff3b33faad88c9122f1c9c3f346f347e1a4f588c811d9f127a61e36b3d53575272461252b9becbe04b1f7fa6e319d14dea55d1613c8b68caf8eb35ee9663ad28bbf628623d14bbf6289edc5c0032ff5293db401b915a656c61474fab61bdab4c44241d082ac054c8deeb863b0e6e6a8823a4e8d24d849a7b4ba9e38db9deeab6907aab183564daeffef0beb5e9cb4e90f908726620c9c35320978d02f922534b1e6535c9744eecee94eda269ddf656e9d963423b0150ee756050362044f6e324b10299c9179c4f4aba7a7476ec0c1b11a8f960d8a1a8c1c39764cd916b137cb4a7ae699a6560c4db855537b145a6063db3808a33dacaacc6db403e7031a7e6e6742634fb0bc3dcb1b8f98af36ff82ce36c5d4367b8eeac07dad7c3bfb5d1777dddd84a9730a4e740f6618ddef3585ad99f4570f2f8f6f6fe07af261229868703dbc94b223ad6c7fd36bccc315745706fdb85d815ce5774bedb5657e721a4fdf7af9dac39cf60f3bd38fbcfe06f6d79bff50e33799f04830bd8d0c493d2cc99d48f60761683490ef82026771379c34714b6c3d3c47ebd800313f3719bb8ded5cf04f4cc4ff04b5b13d0e4aa9eef7d7e684a9e95efbd1700a73794d4f9bcfebd7bfc318027fcc6dff861dcffe228bec4c4ca6adf0932aa4066b53fea81c97fab843ca4772e6d2875e08111ff5ef2a8d3463a8f77dabee519edf4f3d8d77cea537314db579db8de9726b8c3ffa4af3f909ee8c7c8fc3b533ae3c6ef8f4368b6f6d6d19e1ffc0ebdbf8390f7b060e9a377f2fd06f2ad7455e8d743d635a8f3cf206d51c666da915fd87b093cb9f7f6f12af5d971969abce786dfe0f7e7f0eb4590b8d7d5f8be9158f2356c43f42b3e66e86e996bd61f08c9a90377edad71a97df8cea2a7069ece5c2391ff8c29758dfba23dc4bdf6969925ded1b5c5f9ecbd4c3f0636d22bdbbf9fc1207bed8f2037304c9cd64df206eee7d9d38fa113777e4d1cf2df834af92818d7e2c0ba20fd5f8cee3f07c8b54e8217168986e625a11b4239f56159ce9142db12e3903ef01de99708af789a555e215c4fcc814e17a7fb9863e37ab64d5e9f73a4b526583722162ed9c29d71d73cddc001df2f240ebc0656ddcd2ea53c465167c365e9c7b0ed3cb84dd7521fa1e061c5b3c9687cee2d829c75c517eb76c6137f7cfa113f680d89f9bf3ceb956cfaa435a7f464491c7f12c45b18cf3eee65e4022e64ba58c562bcad3fa1d923ede95d22a0cf98c6df9773cce5e3c878ecec7e50cab35c741fff6ce0efec09e25fe7c9e60cd9416a4af6e7fa0b763b7b41e6c92a3a5eb1948fedf087bdcc7d18caf177ca9712a7436fd2510a3e1ce1903cb2f1716a415fd687ad2fa2b35527507a2c28fef996d67a9e900fb847b9e127cc7734d6e7e923a39c1a3efa5eb9be2d7af33c762efe17ff4406313ed8e194d6b3037117b6d6bb725d898f6858a7064702afd56ad31e36cfd974bb9fad5190b83443adf5851d6ff7fe4cfc63c8072adfb83f56b1264addc340e4743c330189b598222c37d8c7f2192d982ad247f9d23958ebe867753363fdcceaf3522efe6105dddcdc531b0e12e5223c095c1e8e3e17e4901cf8b81cc16f163127c29d2fee3cdf877757c046a6c4e2cfcfb2baaae3906b159408f366b95f8913f35bb8fc9c3b958955ad1ef97ad5dba6288e1295a754db26de6ffe76ebf22d0edc5fb123c74bb8bd64b54e7beb2eb51a50eb9d58ccc7bd7a0ff998d8027e355f24cdf86514ce49abfe6deb35a37539cf078e9ba91372a872bacc3622925d18fa0af36164f3038fb9ccbda3f581435f74175496e5e9a4b2aa1144e3dcc639a3e07c956949a36bbeb7ffc609b7f013bf3c679560b5cd111c20106e78d39c01f49eb0f4f0c6a07f0759e91f64df47a846a0b1bd84ec7f0aa1ff0b7535bd714dc7de333d9f6b3a2fd3eee126e49e46bf7f42cf9982c6ec56bb973fccb3bdb17fba978fdd9ed42875bafa86f1e31eb481ed8c0263448454f91e91c858e4c6d63ead295a39a9eecb91a5cb56f0af6794a7374febbabb92cff2bffa4c7af2dcc7ecbfe5f993f22d1b91b6017efeeb549093836b53f68826efc57c27c57fc963c60a705f06af4dc91bdc015b13b227975315afdaa603bedab28ce533711df071b18d97d92c82f4ca4c7bf26e9a999f86e7a970706cd29b6783f1b055f83f66f610dbc58648c2f7d4be3b65ff5ecb9930360383c773fbe0ee4f98ceaa357ae1c62d55f6df0a56cccaad24d6fb0ea3856ed142441f93b4dad7661467f0b8a337e8291ce050ef01ed1423bd9aee281dfd08bddbb1143b9a5e4f3922758786975a3c37ceb172bcf87c62e45f1993e10d20d15a91f1a207af95e22bf79d41fe5958533d21c3310959743463e1b33bc62827bed5fb5ea75f70bd08a48cb2e6c4a9bd64989ae0033b3e8b03fa7cd3ff3be7275975c9cdb621339c596eef6f02c0feec1a6b1ea3bce5118708a7f6662d5eb8f71d3f08f468b30d6ed9fab9fa930eac1f24b80480afbd6f4dcafc838ce79f44cb4b83abdbb5e37b275716dcf656a53ee2da9e766dce8cfbe9a96e46927be4e6da82b51e779eb7a9cac121a4f21887be70b8fc45cbbca27ae567be9058cffdecf7847f697c743c8b2fe3b62ef7171fdf9879a7644d001b1978501d342b60ff7510ba85702423991d8c05e4f94205e0c4dcdeecd11dfbceb64fde5c94f3e50ed6cca5b4b9a388641ef638b7cb367878a71eef9bdc421b0e68ec6c127b5ffdc4bf35e895df193549d62f09e5e6e852a58c2e746cc707f17056ef12ef96efb108139db2c7a836ed1b98f3f0f10f7fc7a63feab71a9cd5fd7dc701c30de78d75380e8bd07fe39aa97f43df66ef461b93df368ac573980d7320393392bca16df6de5ade7b3ec2601b6c591c2bb3ab3675d3196f338e231d4f717d439f2d191c1f716772f3f8e419feae8bc1bbed84373af2fbfe01de59ce60bba1ef917a8e5e5aaa3b7f374f2cf435374e5cf8b1b1f048f39928b7faddddf902a6bc4d121b9fc5cc05e25fcd5bef776afc62eee1394ffe69c12122931f620e46707b723d3cc0dae0f710be2c33ecbd2effecf2376471296b361ecd6efa11dd9771e2f81dc2ae1911c38971fb598e99cff377dcc3c9e9a7c1618dd9cd4f9e0c291d3bb51a024799191e1f11af0cef78aeccb3ffbdbdcbbc71c7f7b1dbe3b33f41e2439b33bb05a3e3342233bbfd090b3bf8cbc0c5de0d924dc7c06f2cdcf22878ef98580ae2cc9c0a6e3bc17845b31554692ce8f516e4ef8261599340f18fc114f732382d69432c3d233250d47b1beab9678f1bbb6b650f6aea7d38bef5feead1385cc856f8b63da17a2fa8e9b4625a2f1b37ea9a2f407a931afcd960e9338ee5c130b79f2d7cd1efcd84ffb9621ec5e978307a49b9ed0306e7da70427d0677ddf047dcb0e3d67ce856c330b1da6f92fe6478d4f4f4d955e8aff96777de4ebfcbf7d772f8f56390cb493f2f94c1b8398c6732eed9d81ec04d9adec61d79248a453c78ffa36e9ceaccf3a3e03455cfeeec73977295114be307cd689a91611e2ca8c6dc663233e0c5b22a4fd75096a11e59ac82895ab235cc53f5f38dd3e1b7978ff8409bf6bd0bf9b90472d78617698da6d2c9fc4aaa9145992d97c975791d50b0a6dccd302be08bb2291ff5ea84c8e35fb99dc76c7455bce860620e894d43793ab4771c0937717b700efe486b7cc4671a7c898f13d3f17e9836a59fda02b1c199439e6a24c0c02d4ab966ead5ac2c12955799d1926dc836da5a7d458d7b4f953e2baaac2a23333bd37487072866fc5915e30d1f30ebb281e5bec4e05ba5cfe0daf6b7d4903e17c4df1b01efa70dbdb19c19414fcf913e31fdc4ee2ad82aa567da8c326e4b4cc62fd29e5b6fdd82e9f644ed3899edaba3b434573b60c9c3548e7bc9ce5cf7cace42c7b96bbbcfcf1b7e31ad6c9e3163e7bbaf79990d071a77e7296426beadc48f53cae82103e56ea6af52e5d8a0373078bcb1a95e76cca55796788ae9d26e0d20f93ffb60ddf4cbe5113e6e91ac5dee7cc3407fad67c8e76e8f41a977f027bcaefe239ea7f1edd68a7c75c5f1975bef8a4ef079e2a5b37c12e0ffc8dbd71bdc3b5d31f18887e126b30319c8bc07daf8e40725ba0df8194d0a7268e097a13744a71f09bb50e46d3c68785e4cbf1b13e7553ce0bc2f0ef1feeb36ff7704b0e6820337fec0e9ddb789a7bbefb73dcfeab8e35eb34b0c3640e11fb6f827c47581a110665be8385479e9fe47fc6318ae61f312f617f8e64d071b687f8f4277e276cedc9d73cd0c5a46c9310d54afa6dce769c08e02b5f59d20a7aece23033a230558497a0f74436ea6c176ad3fa7b82fad78afc5b9e6eca6938e3d7cae141ffdab8764a2fe77d10dbbbd3c4f28ee4656d246d1d898ab12c047a642dd099d853d565b22f9595bc08db62d72d7f116388fbf19f5cb7ee3dc3a534e8bf7543bdafe7f5fe439bcdb6cf8e6953e7a7cb8d33e7f76fc861672d168c5fec56dacdea7a107c04c8f442eb5c6571c34c2cc58a5c62e72f65fb24c921b406fb90022f188bf903699f86c30707f1aab7fc5fef26fc924f26ff5e78d312c0de5535acf11c3515eb5dec584eeb7ffa8f59383c1ccaef2ccedbdc7a1ccfc4b6ec02619849fab56fbfa3bb08cf04ccfae47fed5de6f5cd09aaeca8ee4f77c34b18361a1f8bf6ef3126fb65d658ac26de465eaa0b0f01dd7c15b2d7fd0f367a28a935a3ec870ad0d0bd5900f0f7174a9ab8af02d58899a5e7b2080809c15a54bac9cab0eebab6fcd20a6f9aca756e6b6cc47f6a8d111d863146e9406d2692fc7f0663f7661db6ea3ee10155fba192c191986c474362d662f9f1d0e2bd52697a1de1939b7d61d7922f20996fa1973a24881f2c83a3a516c435f7acd223259ed69af49791deb8e58cd81e62e2f1399d8ca18af93ae5bc25c170c77eda8b4db5ea2d97240502c589b589b33c74d82ae1fc5161caddb7bdda07b5ba7d376a8943577c59a2bbcac1f9f617d66748b5d9f75ce7da830f31dfa3ae30a02795be99cacc458a04ede62254d32ab5dbf6a8bd43ffb22a9668b66a2ec4074441cca56a0b33cdfb9d6a1d42bc3bd1cd297b20ef13e9a04aab88a8cf6b487eab841737497d99451d12d6b3774cd89a35a32e8ed6961b09a35e29ad46629f7763b3df3096058bfe1c9b55dd77d3f4f695fbca52b5ac4d9b53ef69bbeba0b0b666a5ed4ed657c9a08d9dccbae57d22876ec8725592a4b25d75f56662c71429beac2a6ccb5d20e8ef22d49630339c26caddcd9214e478b14de906192490843cda1b16d0aea0a7a55ecbd7dd9a6a39e18d5ecc03cda984df1cd8cc80fb79e2d7a926fd655ffcd814b2ead1193d216bd2191af69f6584d2e43751f4e83a99b3b2eaeb093ccbe3b3af1323fe0216b61a519f641695db3f5d22dcadceb4bfe18b23866e31f52570dd4a2ab3254eab58889c2bac4311e0393ed27ebb528d09798fd84d66a59ad9824dae8328bdc691119cafba66738ee646bc9ac334acb7a490c17bd5e5d1ff156877e614659e06c90ba87da45d35c2685fed645d6d56f1b18ba6eb68ce30e7ba5682073861ae2aa35eae2be25b4b4fb1f9bae9ddf82d3cf1f22d79a66d4429fcddce0632265e42ec50cbab4d8182dd15a2d4a8b47225dd78f7922549b7e188a71fbe1ab4bcdc0f9f0d8c711f4dfd52d5ec5fb24a75e9eca5cd67ef510ec9d0237172e35ac7337df4d9b468596b0b430fc5675beff10ab0b19b545876ea9e2e74ae339efa33d9c23eb1b2fb2365781617d46ec038f1c16ff35c6a86e16f8de484cc91b35fe2dd30c8aee5ddbf9675a6ec4fe815d44a2480e12ad0e6cb7626630bb09b2ccddfecbc17b3def9aa89bfe80620eb261c31e92d11b7647231c9bd666524363ef2f014239c3287565b111e56a6487c0d53ff7dad7f8feeb9541fd81bac0a001d5054f767193146d68a3548dcb1beb98d00824af5503210b6ddf546cfa014e0838e7372367d8caace92d7c724136a96eb793aec8280cdca7516b88ae6fb6403c98bd33bad7e7a8698c4bcbccd949c4630c1a0b239a64528d7b3cb1ba7a209c2c9543b5462909575b2ca3762d1a48e8e9333d8d5707bde3158f141b73a6a2d30a2786737f500389c7fdf9cb2f8973d03cbea6c0d2f38cd89e1b3d1c85998a51e3ddebf8d6ccc2c11127b7096782159deb3d13b6d86b3f4d714e00dc20d92dfb81290a5bcef154ec0f77af40b1c246120dfe5aecc46ac5fa9dd1770cbe2e225373e86f6bd6b5a92564c1bf4667739f2bce7aab003872896b7f33111f8db1a03a71e4c2f0dac48ae9b2d88f25af344e9c3facd437fde79a77390d456ffc4c52288a20e02e2271595f2daf6d07469dc297a89fad063621c5a7395c0ed551273acb91efa7569c1950414e496b061feb50b57c81c3ceb6c87dcb9bc7cd7c960220a619e6241c8aa9d8fade929dafb5bb4b7de66b0e03b75b098b3779d6c243b92b94e1b60fc60fe9b3208b1280ab6601bfe88cf5bab1fd050190141702e1a07730726b291bbea55a22f1a6be54c670102ee968349694af1ac67359f96c0ecd63d6e451cd328e3cee2885db44d93f8ab8907800b7f5ca61ac04cc5488d2b54d94bd14a36bb871653a88d145f3ccd78cbee9bc03dfd8729b757227d9cfd7ad764010437b5cacc65b84a0ce818ed056fc40dddec1ebb156fc5af1d83d56ddb6b1b5b3d92ff1d20e670fea78588ced11cb9dc0f924d1ed3f1613bb7772be2cccbe3ab5edf4ffa16d3e33953a5ce703444c8eecb676cbb1deb84c6537e5036c0128af366eb6760967c3ae2323bab05589b50bccad46d6268b2b684ff8a3fdf2b06a8252f5020cd349140f13d667687384af1864ff3c725a301fe01f814dc64916f6c779be9fcdd74d3035e2aaae9752d426bfca89fd458c6d374e26aa946ff4320088edca68f76184e4d88e9052161c451dab42aa5f323188abf09beaa8218d42ca4552b13055ebee4248e286176b24b35b12b6f448cd433daa922c08bc89b1a5bc41d04ae9c007f775eaaa1e9dbb336c781797fcde05d859fc70cb7acdad3eeda8c6fca2f679fcfdaf11b399c42f95e51073ab683de634c552f1043dca8d6e1d90ef12f7e0e05354092b6698ef64cfcbf7f4e455bbe6599c6b3b64b82a93ec1d9a780522928bbc2392159da116e0e545d961fd5ec9eaa4240e1e83dc45aa14222d5332640572c981e1fa9046b4b2c7a7c1d3ad0c205f8acaaf2c4f1f04dbf99a62931575ee2e23db2b5d5be1dda39d2f21e98792158b63feb28c8792f752557a44cecb013d0c36b955e199b8080b59963df0c39eed71f09669620c8fdfb0c206ad549e787614197eaf70255f1ea2b0867fd5ab87a1e0b5e2f375bf61bf0b61bb0b6122c83843f27a327396c84d8360a466414f2c90a501fab8766250c09fa284d7f61e2e8eba3e0d3b56c4ad5b54b983c65e45f183f871915851c623bc45d33019d3de91b014d89945b580cc94231c9e70387cbc85823aafdf8294d8a54fb95dc2976b746fdebb84909b17a77d36a685a027735524aa38161fddc428c85629faf6f91f84a948052f88b9988a263a4d8d9bd513db7d045d401895fcfac62fbc391fe699688983631dc8a2bb4a0f7d912b92bfc52981c4a4202f0a314105fd841e12e9b080e155a5e58ac27871fa0899248ff6f7c3d076bb7fb0501fc639b1afabf0a8205ec9d7ebe5ecda36a0534c7e6bc62ec839722199a5723b70dd6da447c89f94e1f40beb9a96cfc26ec2b0e18c468dde7f2c64443c5e11a40da55865c2a1178530f03950ca02562525fe659b56970c6eebea8774086b3b218e80f87b9e18ac7d4778fd598e77a5980e2ca706165eef7a839c4b4a3d9372bb0be75cca351cf2c1cecd7c9437974a5858ca9502c49ee9bc18fd18b4b6d67882c2b7aacaaaab0c08bf8f109d4bd7fdfcaafc3e681ae632dfcf3ec1ca03a21555391b9f30e8ae31542e0d175e98bc21626e118a89d9bad87b38bcc5bdd75cc7a0b42fea714460f599e28aca5eebeb523b48c2d98ab28cfb6f6593767779c6a289fe4f56a3519bfc52d782ea6d42c40bd6f2c69831fb4dee793395bbfa243f1afeb1ab3696e016e9c86392ea0bd08d347ca77975930652642b502ce46e8a8c8824b02f53ea064a80fca2922043d1eca42466ff878178143f96a67d0217d746a4830979ceeb1282f72fa8020d88dffa0acedcfbc4d7413fe0223f1fca7b11e9d307ef7106a212c14eac575b03e6894a3721ec49d462fcd200d09185a20970047f8fd70b2981a4fd57caa3ff4f9f1a80af91442143e33211eb195072273055a1aa868078cef0af1e40f3217caad2ada40a44b5f0c0be0251787ec26b484b7a3061747a808f40ffd2bdd8df78c2526ec1b90b5f5251c7f21be7f9cdf960444ceebd11601d477af56fba1c18191cc557155e0708cadf3a13b73898b5ee7d5345a141b307415cddc8ce00b05f2c2584986af597f59c2d762782ceca8c7a81702e4ff29f89afe5c458c80dcbdba6f6630f9a7889e0535a45f9a308aff5dfbc27a2fc624cd7737e2861cd7147a7be96bf19e233d3af14545c275e9fb2ccd95f2fa313d5f68466fb0abf0e03b0da62696e505f2391603b36c49960f9bea73b01ee234c1c80b0af510682ebb9171290159fa57be8cbe0060d0f9e00d4ad21bc56703f14200ebf1bdb529acc5ec4364f94b3822a76fed97ffaf93bb4d187161d507d7126c115f65ca93c4693a0ecfb70754683beef2d550f37c71caee1f8dfb315aadec6fe3da30d350b6a09113a10b55c32f84bd0ca221070580a69c70f79eb0c06263feb854a5f347408f3bf50a10f7c2ffda86b13f6c250dc02ad69f1c84bb331fc510835a4a75f2334be114e2e31ed3b9e4fa13a8e85bc1700b3fb4fd3fbffbfd1084ff18da03381845a0a9e2b3cbfef499069f4b3a5e7160fa8a654c304d8ac5a15241486a837a5e639c19fe5f9a2c2ff2c47f47917faac0e8ee30ebea7da3386bbfd0501e6f0407a5af4fda01ac386fa74701cfec42d6ddf6cc1d5690f9931411e80b507e8b5aef3cf09fb37bcc4e7b7a71ed82732d0cf77def3376e05b48e5ac150e8732ea09027a37a562ba2f41802ed19fcc789035b1efee228d7c5f1d5aef31faa31643988ee64a8a3a040dfd671c6bca00b9947c84f559e6dfd1ab81b91e52f541839664cc098ebcc08ec8a56437a020274309d3b10d9a7e43a07567af7ea4017576d00bef44b63da10708710530bbd9b3dd7df1ca8e3dbfba266c0bc26d32244a9532ae7c2631dbcb62efde9e634c262ce3c253d2d1b775b75bae9570fda664bd9e33ac107b29309c1c394dff649d2396658dcb4f672b5d5eb030fa14e8fbd827c102c40b2d1e9b94f630f69519ca6d93d8756243d4b79c6694607739ee4f7129475e422b0eb836141fd61101b8a3bae51c8d0f23388bf3b68e96c98fba343bdd6f9322a1b725ed673d34ef3f9ca79682620e30cf4e5f2aca4cd99d35fe7da3d814bf059e715d7b121cc8c09c37ea1c21fd23c55dbfbe579f7ee6fde2f9bb5241ac51f7e9bee41337bceccdf4ad8ebfaa52353698bcf2db3ef097f6c4d687f0fa9006aeb0183e637fe89c788b5e6e6869237ad51feb99fcfc73b4e7a89f69937a4c1cc59fe0873796c0d4b1362b85ef47a69d397449bb39f2aaabb3e1edcf571eb164b3ff770f5056e1ff3ae89975b6c7afe16ebd11d5dd2406e7c1ea0b4c563ab05a3ecbfb076bfb0540e4ec4be96778674adb1585f26de53f8f92e6fb87fba75c3255f04f6e3069ff2e9bfc07ca725a119f6b87eb0f5f624fb824eb3c8303b8013e39717a505866387571dd71808fec545713f24fe5b0fe5ebebd367bc309fa36f568c7b783978f0a479557f54beb4381ccc1eb7d374e3e544391eccb0711b1adc91fe7693bb2d7cb8369831a58e8874f5aafd7c55beaff8c2866feb0078969a98a302cd18d86a9af1c9a4d711cd67704fb381f5817f742c7728e95e2bf6eabad2721ef70f5f36ac5fa2104a36e4d0ab34f27aaf1ba88b0f9e5d7befb03b01db2e48c6c46f67c1a7dacbd9c6c227f180e9d2e6ee7d671bbe11e14b1d641d59750ffab238242d28bc1a9b50cc1decf88857cf16375a3c5b6f5176dc0e5b1c6b3e9983c7987cbae9f1b624b28bc63580cdc46deaf99c79f54d999b7308d4f6033eefed2cf3126f07f02a9154e98ae290a103f5dc2b1af31b2d6b77ab579b507e05e818e04c38750bc06a598726356b2a928e700bc1bc6bcc919ba709bbbc0ab8f67717d95967745d8667b48f1b5ac6eb780fd198cadf2ea3a36765706e6cf668aef18cd9dc836e3f0c1c7c182c782838f890b37f1c1af31c59ec644ca479a498877ad90079a073c0f2c1b28103509949ccf849f140b2637ee8ceb279b5a33dd2cf259cddd6d83482d8ba8783f12a1f2b1797b047d8669c5ff7cc9a10785890d60e88c2e233331872cba5953b1d833ae1eb5e401758568edce9984837708b42e4f32fe323e4bda1a8941f748358a2ddb2abb96bb354aeb9d4f4bfed9fadbd433b7e1e5ad0d6075cb7adc5b177a5607c7c6f6e0a68f72ee6d9d2f5846a17896867fdfb86b6c3ebb99c85533c8c8f2aaca194216f3e7635852adf46710de8565b6fc86246c1e52df62eaedc3be7bbe4988d4e8c62fca35c911576366176c2b1b8610aa076c88dff5a2b65bf6f7c802aac80dc4723ee6f28a86e24cbb2fc37e47eb0b8b7921f90d748c8f54ec05e45500326a77bf530555aefbb40b648b15e319805c4bec368bc5adb0b8617558caf52dfcbe6e632703198b2236308991ded72111dca76bcdac1be872be603c09287ad9edfb7ad82f4dbda91586f5e607670b6fec90ef1ecb7343d6bf58dcbd8f9978d4dc81b8c250bef6eb30799eb113fd5a6bd0a3317f9a3cd7b9670bd87bd0a5adffa2164b5832f363af320db6d9898d8c3f93ebfd8e800ccfdf520751c952176eb76fc2398c659cc665d33c62ac6d1b2ac09dcbc13a70bff4eadebb3668f64f9dc665ef00a744e0b8b4412b8b328a3ba9d8bf6e067f31fff883c618fb32e8dbaf49ea1997f62d999710f0d6785e34e7950bc7ba266dcddca45fedabdd9b5e43c256b93a58d6309cbf09f4d4d0c3b4de65bfbd25678393abde7ba6cc58e0d0f7c06eb73fa819c7f7b980e757bb07fc63ffd77b982bed3c2f296c471ade6b1538bf7091a308c3f489c83e97656b6faa90c13f37e3c61b89ce5de7dc6338181be6769cb76c2ddb8dc1b9eb1afaf315165da23bde36088fdbacc3dcfa0c763ee6e3fb77eea3bdd7f8ba5108723c97b98a62eadab249d5bfe3e4ddc385861c10dbf0f451f7ac8309a0ce7339557d78417060f592ac6dcc59e18cd3ea05d51399428be71ba0749ac15dc98caedd79a6d3f5727b25cbe177e6a315a8c3178cbe1351c9ed6afb0075a2d85a66f844b7ab1263a773f7d36ce7c33af767f3f17fcad72c088a316de72abfb3a6a4c2bf0d997d2cd81db73c31bf1e89bef66961f366f70b3b088b85d67b7a676dc832bbf3a712b41dfa65be4d92f15cbbc4e3761d1cefe522cd375dda48b72964b6999affbe6fa7ac5b2e5f87945bcde8ccbec7009bf4df97020b450b08808f19bff39fadd7c35f54f68a540328bc7e8a2b1c6608e36b669c127e4cd112d58778f56c839405efd1779207dc8bc890eb1131cc7994773c1f34e9ddd53c65e9cd5fdce468f567a3b0cb8f26d3f8c770262e126b2e91738343e601e9ef8fc7c03a5d111faacdecb1be86da3bad4601da70705965edec371f4796add53f83b166a26ef3f230f9fda90d185bcaecab33442769de7d0005c2a6ece6cea53d29eb39f139b902bf3c16cc80a0167c82737e87dbf1bb03157032d6bc1369e45f65e16d8e87430f1c5ea192d0c07b93f752b67bfca151860bfe037635c51e5108d59ab09636456ab46dba5835701ad41e9dfa8f88353c142496c57e1aa714a7889fba3f3b41561135470d9fdb7254536deeef7153eb9ba36acce69cafdfa146091fde5647399c4be5bd50dfbba943f2ddddc61653ffc6d319d8a1ceed7fd043da94581fb71c76bedb18a7340dec0da4a7ab5eabb99ae1f0deb934d8e9acbfcb645eccec8c022d95f335f9c66b3db327ba01c9a663360e2f15417fc1b494ce3273796a3dfbe5b2d41845cdd6dcc72df864fe665735ccd553a09877a34c25fd0cb87fec77245bd1303e3ba4d62fae9f21ef080daa8a9c4b3b049aad45770fbbe3de371f8b359190d1b47fb237042698e3c6cc49a41f8fdf45e0c017a2e8618dbaa69836e6e3fe1f7f0d9dcd29d0fb2e7bfc51fd3d71de96fa03ee6e4a38939ba85aeeca8819bb6d7582eb7fbbc86d7fb9510c1f8b59ae71d1dff547ccc303aba6ec80305a740e85693f87a99f617317951572c1d8f069dfb49301ce7f98cbf19af2f446b3d3a53fdfbf913cadcaf9a6ef9ef8de7ad3ff90ac9a41fd810be8c49a2ecf16bf629a2e56e9052757cf1b94bd1ef6e3f617fcf3796fbdac4877515888738dff4785b4d3011eccf6010f1c01df0b6fb74806cd5043e8a67d76e1dc1cbff64533e630c83aabf5dbe73179b1b4dc46be7cdb8faf14c90548cc3da5393cbbf73dcf583573aee2f73e1e684c8d4e08e5ff6bccf0c67d3077dc5b4b42ae7fbff378dc344fdc8c61e74f213a33d275f2fa39a90fb32909e4753ed07c4ad33675bd0f22c272e56333731ad3b366f11f4866c6cfd67cbab4ec7ad95ebe75c5d819a9e8574e3f0de3e4dab70224a3b61298e18a615c64db9396e5ad9aae71f445de1fa346f9ff46572fdcd074660d13428fb68f7e2f9b3b66e7fa8b9e5f88b49c8fa9a241173d66ea99d9d17d7e78577121acbd8c904b2301c4743607ea223a17b1fc62436cebd6d597716e47e7a31e5ce558f9ce851a17f5a5c9f65086c9f960b7961e97b6eeb382bc8fcb8a97ac75d7caba0dcc516f095beeb547bdc4371584b9a3687d3a7d06d6bc98a722f51717178ac78190e9e39773a6733bfdd16b202f7076d96b90e9f94e808c7e03a1d82363f594779eb0c2f75b87baa7ebd555e6dc625b25980b24418fe917a4126bfbb8523be0692bcd4f6807fc301ff87b72e131919c3704fe934c32e2fc6b771df7e6d0c588eb77ac9857befe3bca4d1a6d2304d809be317df13b4b04e00f1f813b322a936e4c1431fce5197ac0eb6ecc8d9b79e37eafab7a9d6c7f5a2ba61b60e6b5f8dc680524102db5ae772afb134bf2108d753ed556ca41980669bec7caf45191e536088edfadfd5f67682bb5dfdf58e583407b6cf1e8f4ebef8de1e84f7c0b94a73ff5877431443b0da029aca6f6a2ebecd64dc137369ee937bcaef5acaf352ed2db102ffee81e63f414381cb794fb90e2d88d7f3278252ac7d606a968b6aedf49466c4671975b769592ebdcc8783825df5ae41ce3cf61c2851edaebd83732520550e35ef73633e8317a3b000b389893c01d646bd42af514d1f1ad013b7085c035783e30c4b52377e3395e47cdbe730e352f154cebebda3a955fcc5ef46c71a2370cec182b655de5e7acec85ef3f2c6a4bc21658ed42e4072afa4cc95aaf7fafcf5bab186ca851eca66538d4efbd0f708b89507df078017e64fac8edd443c3925b3d4bb890dfcc8d956be2d2396891984be09fb282961a8a6f4b3655ad16246c981ad313d9379fc39cd40c6f5ae2bc5ebf14f3e2b61bf52a7b5bc583ba4459b247171957e3bf56325f71bb35cfde32eebdd9aecc1f3678d1abed35f4ad0d2f37b8a8b3caf908c0df4667d3201b01c7c3eb59b12af4447cf2a946ae2cac92c232390b27766aa8bab7fcd76bfb43eae0eded311f6d914dc39a05a9632b38ffdaf5309c76946e674c6a786038473a992c39153f7a7baea2ecaf3dfab93b2cad20c9848eac31c458e01806c9300a7e65b94fd5624cfef25bb0611753b61cb9caaf9b59fda6b89f53dc2ecc7ecb3fabed06c0b0ec2d82ded997a7ad40ed61fe35503fd4b5b2aaa9421e288795cd779db7851f0c80fe28827eba6128163943aabeca22f2976f8a368ff88f4e0ebe5d57838da1066a0bad7d28893756b7bd52891bcf0dc50546a7510efada9d92a1ae32e32f5a6bf77c70cf26c0dea25b37cd2248b54df8606494962c6bd92f3285b8b3a27b9fed24bdc77fccb27218a0026666418754f32a8c60475b0822fe9b5dc6216d1c0b9919fc4bb5d1f2585dfebf702a6a28556e5d4734e67f5feb334ec411d35dff481fd2c681cff61335d31cf42e52126cfc2f1220994f88009446118a1a28884f6e78465cd084c625f01d79e80e7fd77846b08e1ade8c7497c37cac0bbca0d0a70a749a8058777d0c03c490cd3714462246c83f2a37cce0ce84c5e1ed6efec0d3f496369d71e16ad32ac8fb64da1629a4bba9975131cd65072a38b69c5f0459a6c9b76089ef0faac8adcb8f7e14e006e485f6be87984654bfafde16a2a5cd163711cdba4aa1616a12db8ff226fe5f4f7eed2c6300cf323607c642203886ae42e82644cfa795c0d8b6e18e3a0762ded23ea9cdb0a3e7f5f1aa720cbde48c49fdfa2250c0fdea78285aaabf1f84a3f0377eb313856ac4e40e34cc9b42f48f37659fc38030e9b82d66b30514557e063d0f0a7f14fdd3007e5bf0849827449b44d6721d04610aacacd5be917ee879067bf6482a45bf20a8c3dd6a5bc82c70b32b2c0e1815a01c49f26add5636fcff2a2296f1db4fdca213eeea539c4ad9fd094facdbcf15a83f12ec6d6ba0f619f9a71f78278d194d375ae3232d42491ffcd7f500cf46e01429f54dcb67ab9e275550f3077bd7ecbf7d383faff3d3f017f0d7895d28c46eacd4f2615c8d07ec992d5f3588714220dce7b17401c6c45a3bf9fb298f4bbfd1a6ed5b9dc3c2fb05b349341c4f1564b4e4b6d47efeca562d832fc9c13450e26817e1ca4ec105894ec388843ad3a0802bb28d6e7e305f85cbff422443445b5210133a4cf3d5c026af413f7dd40b4626a7fc61428a29e533867ea785292badab6cca8a9a71e0a9b1ee6688bd7b8c28f82eb1d9ba874d1e0766f3ecd8e078d208983aba0234fcae64213b1806b74cdc0dc7172f2f36b7c3768c42dc0186a943f6802365426ecf55effd1b6f617e21e4f2ddc74cddd928df3a94b039005ec9df0a2f675d89ad9bd076ea9c37c8eb38fd4abf3e2df7711b369257456ed987c30fb9de2ee07121320f8d5ac016b89dde34926d2947a9f0a1d63c59426a86dac6b48ff94f943c93bba47368fda7818bba2798dce256bd65e83ff2ab8d1e7c66294b422c1fad5458f1af3361eaa6aea6ac9ec7c17bf7b5fe8b465fd91f80a36a869d397624baf85559e3d1a1c2b04e47185b2f0d578f110be73a1f97fb16c73c636d28d4e3b2bb5124cac717a8949fad7c785b03117bddf4cc28884eb53c095b7073aef2bc109e3bef552781e045c39412ec60295391fb1dc2c278a1ac719df98e8cff75e6b71246e0b20e144fea1b7075971340336e252b315ddf1f501fb9e67334dfd3fa2656e748ee73d78429a3aeca37d645d33590ae5f1f8bb75eb110f09d0dc1d8c4e461cd16fcf1a3f9595acffbb1dc73247296d853e5c1d58710dd7eb8f878c049c7c3ba72b65939499e0d3b28b40ae8bd5d5752fe094f210a7c1ba205ba9c8c73720a43cdfd35df021f0e4b85df854f2184d58b0f99d4012d080ef9ff90ef15cc0e30b8a666d281b32b9d8bcda206153e89c14d2a919935fa1fe23eea07e6676e9edcfb94d25600b7c7f4b83f358e715cfac2bb37cbc3ebc5f12876ceb90c35c919ed2e6b17ed128c51cf026f84fc5dd8a9a13352078b9b8ef3f1556d7e163d8d573e4f1413d97c2713d443f426d19bb97ac48ca1f40ba53ef9c9ef8c3dff03fb3017a71a33d6af79011c4fc025ebe45cd0e3c60ae26e900c3300cc3300cc3300cc330bb91b1f6eded2bd436249394d30c64e4d85822726a4a29259952129c99f882d399894f6726cebbb791bc3f171f0f220ec70e5c7c244086153a4bd7952bb6422ec869f9b57cca56a9323fc81afa4037d86edcb091ca76e4c8a20b1c17f840387cc7052211195530bca9b20e796e27da944105d39d47b32cd1923105d3b9c98c4ab9726f2a52b0e282e54aeaa695b25ee5b9a13f668afa2f011951305ecc0b5a9573a8d82114cc61a34e52b164b93f51c6134c258d10ed1c4a9adc777c05229128c87082c1fdf5c4cfa3d47897c86882d1fe4d8f559dbc493a06c86082699414d936f1bae0f5e240c6120c6217eee67b4127e90e71900a44221ff6850c25982ec752793b87eb4992fc614930e51016a7242589a1afcbeb810c24986475127ac6cce43456828c239852e953fdd04b212bcb1f07041946307a484fa54aae4aa2a8777c059c20a308c6b00e7a2a49ab25c95c035a70f101228308c68baf13a5c49d92178e4422910f19433055ae5e12dea5df4207b2803e2118f7c7529f34bf3daa02b2c62167213c6c7861e3869e8c201854b4aeac5036104caa25a9a43ec55e77f307664f661f94b07213321b820c1f18ebcc6247fea3dcc9cae88141ef7aeda5cbf249e86c1103193c307c7992443e86695968063276601225fee2a72dbb1565c9d04151db42cb552cb8589866f6dd7eae20d44fab20dbe3866b20128944585d202307c6f0346a2b5decbc1c1c98e434d27277d02a662537306528a16289223e4f87326c609cfbd3f1439728251f3c7e471e1e17326a60faf7a046aba46c937290b51d393e787c17c5d8013268804e4a4c494196709e44c60cea3851b5ae78870c1918b3e6ff762e8a92a35e901103a3bfc7c8db7dfd5e2f12e90f2b26051930d0cd62d959998c978ac86e0537b5d1626f661264bcc0684a2aafd8be27d38427c8914524f221c305a6f750d94a273925bb6e85493d54e4e39a50f12d3158613839f75afa68b2ecd3315661b40f5667effbd9c74210f83055186caeedf394cee14a30c46f64418418a930ac2751cbb5c3fd49a22fbc02914824f2810aa376a536ddfb8a6232b4c37b3860c77fe11270418c53984f12ef5a25f79be183ac7d9c1b7ed872241c10e01192a3026a9c8118a6e84d2c5598318b96c2a5d092c249928e59e570aa0d442267828f482444b5e0e2e38b18a530ddc74b75d3f2f1eac72085b1c225eb60f2885117c7188529feb74aa9ace5b72986284ca6fde3cf35eb649f239150986cf553ac0e6ae34e3ea4070fe711899c101b5e44221f76426c785142703c0972f0500485418df0594f2eb2f42878906b8bc4f8842989aa51313244b63f9e30c71f258fd8be2456c7b44016c4e88441a67830bb4eeb75baa3c663470e1d3a7a84a071c2a8ee226ed28ace5b0c64ed8be4a3049fccbae379d82831366192a1377bc22be76c829a309eea9cb542fe993027115f26cae9dfec8d096387e5acf229dcb3242f81d7768d8c2515fb34f390ff114aeafc49cd124b18ccf2ae465ca83595af84c12e7b68515209036250c220c4824ae14992b6528c3109b3f8767b88f2b3be3c8624ccd94178b725931aa6132312c6cad1a34f783df94b180312a674f274f866cb28e989f10873e9b51242b8398148843fac2f86234c1fa65ff4c54f4a2c1ba31126a1e2692ba894b449d3c56084b124376db2f47de86c5984e9f52a760a192d56528a309a60fab642f782344f8c449852bbc29c85dc8eaa3110613025e992e4c54477862f887108d39b2779e54d46a6e90d6134313dab14c3c491b51086dfbe2455d9c8cfd26210c2a44b876bc5dc2d79840661989199622a95483d590b420c419873dacb3c8f779de44f204c524e427a788ccbd97640183d8a129772bc2df4fd07836c65f3934f9eb369ab0731fc60fa144a9ba8bdf7c1a0dcca3d6fdaff5a920f26619460f249a33bcf647b3048abf35492576af9510fe6cd90573b2bba56bf1879307ab5971cd4c959c9444b0c3c1864bb948bd795ec2b66dec164b631ca747c84f82aed608abb96f10aaf9637ae8349f8f0c1a356ac645a9499743065f1b6d2a6fee754b8ac10630ec613f14f3bd294604a50297230c96759bbc74afa1d2d250e863535b2441b5531662ca5c0c130e75143544b56fa74bec1943e4b0942c6a65aded20de64eff4949da3ce81343a50de67435a5ac434e3fc995c206f3e7bc56875aeb7f5bca1a0c4a09aeb27da35b7f296a309bfc297b38313d8d25d3609411bf1dccbb4c3498839e38a3f2f2372615e30cb8a5ec615ed1ba4e2ca7e68d5a52aac44f26df31cc6038d1828d76fcd821eb48a4ece30b1e5706d5f3e68556eb9c3abf43c733a0dc10830c26314c7b4e6396d3bd925b883106734e415e2a39cec7d329868518623068e792ab3b1e532146180c63f2a854efa4a4a4c46030efe55fcfb984da5bb19e10e30b0639b5fef7417c9435e9185e308cb0f5f1a4d473107eb1630731ba60ac92db83bff567e5919a06388b185c3057dffdc9f30c59bf5fc7175b20058821c6168cad61494e31fda3b5a35a70f1816268c1a0ba3da8242af64b45510e101e3f011b3a14c05e88910583ac67c7349bcb8a9947088e1c5928176260c19421abea930ebb9c5fcd046a26c02b1884e8122b7eff58de9b035630bd5a28b9e35920fb710b885185f73a57d8ec24c7983815b8b470aa96ed65b94eddac82ffbcdfe5243a8c31057366c9c12f27b9b2a58e2fb650420c29982ffd9e94b2bbaafa17a250881105f3c7c9c14f64c7978f2bf0058f0ffb82c7252106144cd182a5a8277c95fdf90493feaed4495059fc24158ce10483a86c22423b4bddc26103e4e3536023a43f8410a309065f4ff9a0b2a4bca004644d111083092655398e1c93c52bed1463098635fb924da758ea672598d25c9e94844a12cc6772a58b6ed9fe4d1a0906d56252f3748e4ab1c63882413bbea73eb92e097741d6d801318c606c4be1924ec252be528b6074b7f19c625ec72f8f08a624478b9fe36d67052dc6100ca7eec144ab9c361e435f818815bb420c21984e4eea77f35baab2280806f5b27d9f049d4f7f120806fd0f2f9635a4c9df3388f1035352f99d45b95c8790fac024d8485f93b561a6537a60924b8cea58955b922008947d6821060f8ca516dbd54dadfa2841f68b1d1588442291ce1d3c74c4d88139880ccd4abac7410c1d989230bf9582b5fdd92907e6b032e3514649f9390e4c59e747c7ca5d2242bf8179e374d014211fd4b581b9925c31abd3995cd2ad8141d7491d6ec467b7aad0c0f89b95b3081362329a81b1d54e8d8fce122586323049dfbf25e7e4cbc3873162604abad449b6a72559ea6160b8f015e7cced64a972e0f888f102f38add6c7d102572a2315c60181d4fa274b050d28d305a6112fdf9136592fd56b4470ea46f021b3cce8f20c78e0a640860b0c224d63ec996f28ece9041d67074612324c43f0e1b165b38e08b1b373c8b48240a3056613a1da12ea782e649eb7402305461d2c973a5a03de89c044bb11d9d0ad3c7e5d0f18392a29a2490b52e1ec76b910318a83065f71416c6f3b8c753d20303a730a5af583079b7a49a38c81a09ee043974a429ccfb29264ab4e24dad377a4c800901a314ca9778769c67bcd66dad25f12153a4c7297f87f72841c819294c5b26e50dd3c6c7078f1d2508b9488447611226defa43ba9b546388739e9e51519863ff5edc31754aec423cc1620b07fc8dc4b7f8105f40f9004628ccc994149dd749da8e90a389f0c061234705426ebc0d2d1e878d9414108920a480480484878d1d1e8984ac85dc7894c38b8fb353c00085f1452e973e25669fca85b8d9274a6e972e98665c685c2c1337cd5a2e08b5ea066078c2246bd5852929f5ff321b27f84810c0e884794466b95bccd8ec09b2c601189c30c8ee5c8c585393837a78f1f1c58ef72247173c70e4f0a2d807606cc214ecfff2936072a5f5206b498f10e4c31ea85b01189a30fbd88cce3987d5af5d471f06229148e4b0472472c36decf890dde137fc84e8875a268c36aa2441981c41d6423e5e8f8d47480e908fab010c4c18633b55921fee6a37be8451457b45bc8ad03aaa25cc1d2689a958a75ffaac84e9c4aee41c96eea53a25cc25daab2bc555d26e7e3c0fff62078f341893308d50e1f3d76225db7d3024617c4b9f54d755b0f92d12e6d7af1da15485d1ce4717386c84f4405348a4d57725b6c91727c47d80f188532c7b79d75d9be6664926557bbee3586c21012cf200c31126afafd80f75a59292fa681ca61166f30ba3cb4b859bec20596c990106238c7b5d4a523f19d2428d44cc3e6c510d301661d2aa94847a9247e73169715c80a1086307291e462eea8d25112625e7cf122d2caccd8b8854adecccbad66cb6e6b304f9fb59b5d3a73541028c4318a458e9e0f73b2608dd10e6913725e8a0af45695b08635a6e05cb516ad98795c3020c4298c4b9bdc5cce5adee0761ae7e93e3cf2caff42708538916fb9c4c287927e602188130ec49fb611efb54aadb5c04188030dae7b95f5075fab488c346173676502012e90fc373028c3f985364c5ade75a76be3f42fc60f84c592db1c43a4945b980d10793290fdb29ea2274ca07acc5e652d4b20a76f3d9a32add89a1ca72ae700fe6180fa2a2d9c90e27d783a9e7e26b8d92f53f878b6700230fe6f2bb3ce982dcffbcf1600a975f9424989c30a5045933c16e21012c4278e0701b3b5c036be8868d1e090360dcc124888d505667f75d4a7630570a9595242975285987518752fa0dfb50c93a118041078352b2bf5527a8f4299dc35eb315eccbd4a2b85867e88d39e9925c5268e5601274d4b59bca57be1b8c38982b4777e8c796a04789f37006602f01061c0c2656692849bc244bd437187e4d75bfe7d4e5a92c7383f1a48f7dba6b3ccf2b3c301089f487e569c1c507009200a30dc6fdad24fdc972e1c2dc03061b9267ecebb369e513ff02b0c8020b05605101096051940730d6d056bd5d6d451195b35953f6268cfcdb5e78aa06d3b59509af60492cd1d360fe4b4a8af19d92272da2c1781ff54ff65b3541c9e9c8b1830191482444478eee3314ceb2655d8a8baf57cdce496e6df8775fee3f0e5ae2c871238b48a4b5e0e2030055806106a3c812fd54eabc72a52d83f1e207b94ab96efdcc0a5ca00212c0028b2d24a0a8051864305d5eb8d7fdf9b97ce2280dc0228b0401141823c0188349a7a0e4fc925b1ecb9800430c66f5d6137e43bf938941d61ee5c081f6288716856184c15c577f427c4e9ece8372f0482b53000c30183f94362d5127ae98db3b14a076707c1152be50bc602ad9f9673516b4ff0764d512ec814524823605185d305f9dd66d4b9d56d302596336c0e082c12d9850bda735b74f0f5800034042fc0120210e927906185b308953b1ae947097441386168ca394abe82fdd9c9381ace1b0e15ef0483676a06207809105e3fe6f75b7e5a0049341d61a06168c273e09a1f3de9a782701e8d94e26cc29e7e748abd395dac18429644b2dbd3a97309738fb0b159fe43359c2304286cc31c943d75f09d35c90ab3627b898204a9867ac9258428b7cfe4cc27c792f66482d69c44712065372cfebac97ca7b240c9ab71e5dd6c4dd1b12c6ea4a6e55767a657e84e1bd724af73fee39eb08e358bc1a7df2567633698461dedae27d323d6a491861ac91af94adb4b28fc9220c96844a27a39412ea4b146110ff7b3a964b1261ea9c1ba7ef940ca58408e3b869cfbb24c54dff1046d335317555d97e6408b3bec9697a52eab250210c3a75672f25e484307f895db2760ae216f741184b12eb5354fd8a9d5d106657b1ac7aa29478b107c220f645875bb81b793a204c268fecaea0746596fe076389e97e7a5292924e713f18fd64dbae9ef176cffb602cfdb5d516733e982df9ad8e79bde8a43d187dc46951ad1f942ae9c17c9ed286c88a5d9ecf83e94a124ab54b3e49fdc683f1ee4b9616696572df7730e80e3fba2aade2446d07f38898a43a8eab099fae8331ff72aaa0ab4bfe93a683f9b264e5ace1ff3949cfc1248fd412223f769293b41ccc3d4a9f5221ba64973b0e0695a525e699ce59b40d07635ff2e8c12d8cd06ebfc16852b2bfca0a2a9fb61b4c95738afe97aa7694dd06c32739ca284f361b4c8225dfbf1ce40525d96b307ff8ca1f439ca5b1b41a0cfa8414e5165d948e9d0683d46b517d25f9bed768307a2925c99ea9bdbef519ccf239b467e724e54f3283b1e47d8e7faadf4a5f06b3e5fcd20c7d3aee93c1e81fda7b545610c21f83b97c2bbe28ffba14c46230ecb77cee51ead3e870180c32f2c97efe538687c160ea2d0b6da5cc92dce12f184d596cc66aec65097bc1143dc78f16cc6d33e72e984de76a11fabe5e3773c1741d26fe7249b97298b7600ad1eefb5a590b069343c88e39aef12a67c198a54f0c2d23848b92b160b2bcf4e4d1c584a9f0150c16768468974fed0b5bc19c2ae511f28452751e57c1ecad712d1fd7332ba682f1a44a9278b27fd4f53b0563c9597e45850d9573560ac6ce9f4d3cc97737cf46c19c2d7dea90256f4f928582499b8eab4fc9e4937c9f60529674b2b4db09064f2a69934c12ecb26e824992b9b21fff7d316682d12e9808759e25982441a9ebf8ed499da4124cd72e3a85d0fd279c49308f65f75be5143dcd4582314474cc513796abdc239882eafab45bb7a6746b0493ca7ed05bd626686f8b604eaa4a4c8a886072f9e8968329139e21985d4e10cf7f72dc122118c63e78a834ea84d982604ae2a50d5d5143476b8160ccf68ba6fe6eda493f30f898a0ecc2095d4a1f98e4ce499f60954f6e490f0ce3a792f60d65261e982c76cabcc87760924b92f4bfebc0244939caa8784265e9393066c97d49723cd929c78141ada49473aed45ef50dccc14288f818fa8312b681b92d8b4ed27c3cc1dd1a98f366842af7a89a2e0d8c15cc563ceb540aeb0ccca604594aca0e2596cac0b8f6fd96b4190373b6c921bd5f44c91718988349bea7bb5301bcc02494bc2394202b690d55002e30d8b597b857a9509ab6c26cf57db9d2efd35cca0aa35a5e972ead3cfbafc23817eda3ea49fb5f1526aba44599a05498e499101394945a57840ae39e38a32dec53baa05318bd43946ceaf226874c618a771a3a4aa7140669696c3fbd786e13529892603a875d1276497c1426750ba2d4299599bb284c32a27fa2dfb54aa1308768b6bd8505956e5018c7772cfd443fb1f4278c97a6f3c7a531796b4f18f32bc72cb1d776e74e18ac5b749a8e9d7c644e9884765f397dfbe3f1268c9676e45bb485725513a6caa104592f1354273361ca49ceaebc333161aa70b397eae9d5ccbc84495a4a6daa4efe4d9896308d9e0ae13b66254ceaa6d2a3aaf9df989430fd2549b2d05651f1e5244ce23bc9b564399dda5212461fa144c78f09775a46c270652589d793acdb4a4898c4156d4abd3ddb941e610eee6bead34a2b4f8e30a7124cf6984b9a6a6a8441eda73ce204d71e3d238c225a62728a4e117f11e6bcfb79f2f57fc9bd224c9278f97554be924b5022cc7f7955591ffe418408a38b8879b4136f54e810e6aad87039cb10060f6a7237d2bb4c924218648917b2fe3bc49e10c2a4e2b42949d2b9f24b0661927474d648b3a8ba0bc2a0a604cd912144aa1e0873e752d669fd04fb1c10e6b86aa9f3df4f12ef3f184d52e2414962c67cec07c347d176727a5d15ed83794e4cb6a4bb24c9493e182b558a6d41ab5c9a7b3048135e456a59f460909afa6effa54a8c250f26655792946ff184f90a1e0ca2b4749235bb47c5ca1d4c15cdbc044b955450153b18672f894b62af9760953a98947862e7a0273a984c7536b1552be3259c83c1825acad35b95043dcac1d4aba29dda5bf33dc6c19cd54e5b3f289f17211c0cbaa372b646a8a708df605032469b777ea677d00de6d7b1ea9383ae511d6c8351adca56ab529a2941361845e91ce425e9f3a104d7603093a4116a95aac704d560ea3d11e725edcfb49806f39b923dba49e96265110dc66e5bebdc3d29c5c53318ac52fa773f3f9d269ac1fcb7e69e716e7299580653ca4949a7ed178430910ce67415b52e8961b254700c066549ce509ec39f4941319845094ac57db0d41fc43098b4c96f8259147b11110cc6ccd310bf9ed6f6e1174c62de6ec3522a9d2cf482393d53c44413cd4aa90be67839be9a18af9a262e185ff6ec82b89ad6d2168cf1b9ef521269f7792d182b76f67f12d2bdfecb8251434d27513c4919a2c3824950f7f4ebd015cceba6f77efe46a89015cc974c4e3a4ecaa9ed5305c389142543eb93247ca8604ae1a345f9dcd53d9982499b78ca4cd44ee24ca46012fd4acdc9680fd3a36096b3d40f63fa25e55030ff9baaedeff0eff3130cea2e8b25f92cc3b34e30dcfebe456fcff36e13ccf2c14c5c13258d891e134c66df3143855c8feb2dc1a8d6574149a5c410ca53826147a9f43b295698ca25c154b1fe64eb4ba3267748305a6a93d3254165bbef8e604a7641bc7f581bf3ce088613ac4b7e72d519d515c1a44cd055827e5f78eb88600c2fb56c72ac1d791a82d16d546ce71196624908e67825da757f104cf2faf695bc4e933d100caa3a843cb94488e9fcc0144a4cef8e5d3af7f181d154766eb196f1ece98139d44e3c7a555532e181a944e372124ebe30fa0ecc9e83fa9cd35ab07cebc0acee27ef514be3ec00e4c0189674693dcf9fad0e000e8ceea57450232b8fce01b8816184c9516485505e73006c60fc60d96ff9b6d5b205a00626a5bae2df6fd69aac058006a60b7fe93c2b4bc5d702300393dc9d54d494588ed7022003b39e206fa163652fa9052006e69196c4c7b1a067570b000c4ca14ab345adfa62b500bcc02c9faddcc7a4b9162d002e30e90a712db9b379a1b5c2e497fe4e7492fcdd33569832ec3f889a55f4cb5661d09304cfa75f840a97a9c214d4e2e598969489a654183fcdea8230e129965061cea5a298db0825687f0a83cea74dfe1c599b23539857849e078b9f7246a530c8aed0d62a4b771f5218bd56a489f7a12e7a466154d327c998ab38da118549fc90b158e9e1a724148693843ba9cc0414e6d05f9793a5de31f5270cb6a12495a42c62b2f6844184ce17b5c2592a71274c17beaa62bb75729913069324b16c82c9e183bb09c37c4a4f7b2a437daa0953b9a82fcf177b2fcd84f94fd8df9cca9a254c98b3b7ed43b5764c2e6112bc043b1d6982492d610a66a529a3c4bb302b618c9363e6f6a484394dd8315dc242fb6512a6944ff623444918536d43a5ed64c9140973fe50525fb0fd2f3948188429b72c71d2499f4718e63b3ca51031ef3ac2dcb1947cf33c2267234c49c9592f96dcb28511c612849ed1257df6982dc2ec26caa72ca9528431de44356f556f174f4622cc2294929418a37310910c4498f44a12dbe328c91dc838843959e5d25b2a95126b640853c971d3928e5942b4955108d3c929c99e3b54b6d54408ece41c9d3fef9d1a8441c7688de8a45b53158461c4bfe9ac7549ef2b10a6ecdc93c4299d2d660c886d3dc6bb2cda6abc567cc99f7425e1f3ff97b44dc61f4c4ad52ceefd8b4a75d285f3c0407b715020c30f4693f2ff5bb68f8ba1c2620b07f008791e2e8195d107733255a32bc71ff1a606598b442291d6828b0f16c8e083494db074c289daadf2eec17492f0e4299e976441a607e3a8e7ce6f29d424b9e7c1602a551293d4fdb43f3c18c382fa850eb5965606594369cc1f27e30e2653e29892920ea5731f1212d253906107738cbcf7f9653b93269975309f18791f9477be924e24d891e3043c5e8b4c3a9883975ecea63a5665e1b1c32bd032e66052d29f3a4949f2cdd28c442211344124d21f236034c1591364c8c114d23c4cb6e742ce250e2631ac4efdd4cf699cc8808329d64ef7fb689e8afd87f89f8c3798aca2e5ad985ba754e406d377b949af2e5ad72c6d30c7a5def4ef94a48d4e24128968d1810c3698c4942497fc57423e08adc1240932d34e8d0aaf73cb5083a924b13ad6773fde0865a4c120f4a6aafd27b14a6d28781e3dbcf860fb1edfa304755a70f141011968308cf6fc2de3f12c372f8d0419673075c67687a94ea2e9bb0bbfd180fc810c33986266494948ef0eea4e70e408f1bf402412896448f2a123cb60782f314c5c2739f8bf64305f4c4f59c6e33b451c03b6952bc62ccdae5a2ccbf6989b98bbfb55ab188c2649727be479ccd1fe8b27c1ef28d7058e0b5c18cc2b57d29b0e26b99ae8bbc0f1376e38c849038329880a359363e77cdd01592bd600195f30e9d0a92b8ece6999d816653c74d8d871ca0a20c30ba6cd75d6a86775aac8052da382ec52d53f70d8e8e213e6330cf4273976f00851d5828b0f0bc8e882515f4d9fa9932184be29830ba6cb2666553ce1c42949646cc114e263ff28d1444c96bbc87183510b2e3e5086162e29a3041179137b6fa43c32b28074bfd8be666d72bac871035d06164c8f55b1145ad75637f2496ebdf42539449b43025d749143023a726811897491e3868c2b5869495c3cc4e4c25b8a3d536a1572b2d6d3206b3a3e98047ece9340b508ada531cf6d7d2755045375ca5013edbb0312e220667f209086011a443049ba43e58aea9c04250fc1a8aa55a5dccbbcd204595b21984e959b92c7e358183d24c446a2e72d6804c1d429a8f18ebe72222e3c70d8f00208264194eec5b9764f3941d670ece891b40668fcc06ce2892e392721f45ff44662638740c307e6fcbf646bd2fc746d206b1f38fc1c8ff33a427040a060f880460f4c97aa53fc78d1b3d32985e0f01d3cf879388f1e13d00cd0e08169d654326131bcd5723be04a1c932eb7f1e3321a165b3820128944eee3860e2f6ca0c1d8020d1d98574e4e1276a22d8e36075512b4ed874c8bab211c1928dbe1377a74f13bf66f2456010d1c1874f4147e7d96a3e5506781c60d4c9ebd445323f74f2a3130d0b08129d785d12e61974d379035ff30c1a38f37818d1d8fd89a03346a603c5ff94c9393ba94340dcc7d95fef336f354bb39508f10cb817a845c81c60c8cbb151eff47c7923f6c041a32581a313079e527ad1f22cf3b06b216c20387df0668c0c0346a9e83ae2da57342206b6aa9058d17984c6bdfc677ca2f21a6e102c39afd7d09fab7c1c3c65db6c2bc57a29d68971db9d500335861ea28faa4bf99f06422c81ac2612307088f1e0a40386c342012e9c28c55984d77123d7dab9b575615a61444051325d949e924322315e86823553eb8b74551e1a7f4c15b2c2fcc3885169e5454cc67e5a4067c64618629ec8e71b752f5b65ab5122bf19d37b43a099d97c21c7a6e623dae206b5e7cdcb8e11f49df0d05fc8e1ce9cd4861d26da6c4bc94fad2c94761923d744951fe2317735118fbb45d3ef59ad313b3c18c50183be712bc63c7e78f6fe16006280cb24428e94cf684d7ab0a333e61922f5d9e553f2170e3860b618627cc9e53cde53863f3fb75c2f83fe1e1a2aa050b333861d0a14bc92ad2c4c346880d1334165b3820070f1b213634f0f1118944222812f968cbc48c4d98e746df75102377b4af098368ee28151744c9c52b13a6b82294b0fbfc364b61c21c66bd4dca3627eb75f409332e614a59430869b27979de40d67e878e332cb67000166f09a399aafad1973ab71f78218a021389306146254cc153301da96bb29b30165b3820120921418e1c204609e3f9b989a36343295d4fc274b127679bd3d9b6ad240caa63c2c573b664ad72146644c2204e5525a1c5540e7a156106240ce2e3589af07ce18fe4e30e3d8e0c4c61c6238c6a26fd79f8d527153c24cc70842965f3ce57e5a4b49501614623cc39d4ac5a3e4bd2e9068a198c4058cb95e958a95a6288198b3076e8daf9b6a07ba305592b27f00bdc69c1c5070c17cc5084b962bfe7303154bdf638bab011a23998910883fc75db97502aa5f4951bcc4084495062c65aa4e8102625de5cabe3de095541d676fc8d1b7e3e4078d838810ddfb145243284198630f6259da54b1e7562e80b613a758b93bbb6adc604593325cc2084d92449fc8bcf36cb8d3b09330661d2bf5675aa61b18503426ee8f002021f3a42f4c8304310860df1c9745899a4c3fde0f15dbc0322911fcc0884299e1c437457ce31610159b3330d446ce8f0d4c20c4018ccec844fa596456715f82e763848167f70e4c031814824128984e0c861232412c9228b2cb0380af80247173630108960b18503b0d0c004221193814824b2e3913f4824726ca80676e4481f37cea3c8878e903ab5101b3abc10e00933fe60722bd59e4df6d4990e64cd2e0633fcf0c83039bd9c24447f206b3b6c7c986d32a30f6693622549593ee1f2fe203b830fc6feb2134a4f7ef4acf760764fb962566eeaa61e4c6269c993feba97a87930658f4ac2aac7b77d050f06b5579252f2e42c5abc8339d9c5ad91b5f5243b3b184c9dc92f27b4bf620359cb0de0e89143871739b298510773c9b2d8d6e7274b5db0a880040e0796bf98410783a90ca13c87ca2bcf41d642787c4888025090630191087a1494bd31630ef696aca52cfe206bba83870e14cc908326899d96e797e3aac32780814864c7876c8f1971284942289372c3c377120ec6ca1b61499267e2579004229148314124a2c9c58c3794d3bf43ad53504998c70c37fc7174c939b6e7d16302381a901798d106e38709a53dfc09f9a8b3c17015ee2bd726aa84c91a0c42eb04254c899d9c257a13893c8a441eedf890196ac0b2b668dca54adabea96fd2c712f3b70ecc488341f565afe479df9b0f1a4ca2e4c9ce7326c8757985196730ec456bb51cbd198c57d1dd2cc89b1c2c5706a3899e3d39d5f9f4c9608cf10d532d1d547efbc60dcf820a33b0d38b962cb784c460daebd8dd26e55ded78188ca52b27b94bb46030a62569f4577d3eecf205d3e69da4539277d6c2d2d5828b8f1d33bc6050ead77f65a2f8096aef076674c1ac7275764a5062d7aa8f195c30cda518edd1a1d4e9bc05c3af85c7fca084afa06ac1546926e8a0d232dbc41959308c9ae7b1f4dcce0a8f2f121e3d74e080402a6006164c16b76dc783e960e2e70a4651d7cb3997a9d7bb5630cf9f384a97a073d929ab603c93c684978965951c154cdb9e936c0ba7640faa19533088c929c6f4da981c2f29987594ac52334a5130058d3ff9454e758e13148c1dfb63bdce8f7a2c3dc16c2a8512cf9592af959c60baf4f9a0595513cca264ad5b959fca9e678251b343466a55f09cfc2598e2880893a49d9d6c7925186b47964515f9f9e327c1bcde26fd5e5ff0ac232498b3251d425ef797b8d1114c95e452f2749468bbc808e670315dd9df945f1615c15c2a493ad4e657720b2282e1cc4a3259a2996882ce104c6a7fb25b4afbad258910ccdfc173b69f83607a5172fecf259e7a4a020483eb869025ba7e899f1f18b3f3cc4baca865f281b94caa7d92391f75d203734ebfcd5262cad6e681b1243935a366926bbb03d3099df13a4154bc3a30df49de25c9d0a6a439309c641ec7ea54682f716032a1c53ac9b689aeddc0643ad77b423ccaa9dc0626b9733bb76a5f92700dcc1e4e454f42769a924203b3a553b5395b1f4cd733306dc50a5ec2c408ddcbc07c79e2e5b99a753906068b2579891fa2927860600a7e1e3c7f9424a8fc052649d0f28b6282255dcf708149466913d372e1b6c26495ecf2789c8faaac30882f354a1c934bcc5598a43273f7fc68fa52f6da326d23eb712a8c652a47d4bf56c76951611265c4bd9a243b8bc9294c4a9d070f42e7e8c93485b1933cd9a7925a0ad396f4f855f92485f1b4ea2f96c7bae7e4284c42b87ad0f1ef49a78b28ccd1f3dcccb2563d5c42612c556b49b494ba232da030a74a7b921e9de449c2f209935c96922c515c3b7cc51346917fa11fb54fc95ee984e1242b25cf2525446a8513a6646e62ac25996359d984b9f55487bd34ea721e3561fe8fa7da470966c2e0fda361a1443969829830fc6891d79973673b5ec21cb7c33a57958996444b18d634e5f474b0a0f3570983b68ab7f76f2be93e4a98a4fbcbe79d249970df244c5dd9a293f0e93cd49384d9f4f388086524ccf7299849f22861b51d240c3ae9ff27130fdfce230c3aadfb8892fa724c1c617efbd81dc3c3336d84d194143fe7fb52395c46982fc99ab1f254954d5b8449ceab272ab496be244598e4bd8d8a6ba3d2f289d893f0ce7f524e5d810873d4eaa8a25feaa43d1dc2249650c94c76106ff30d61303163f551941f66afe38b2d8a0160105714c2e4f2973c7b870a573b21cc1584964a2dcae24a4c1371c520ccc93cfc863899d61e0bc27c29ad83facaa74f12af088469457a1a55324cdc7c00612cc9d4292f49be49aae40fe6eaed2ce2ac74588e1f8c96c42c25acee7ac9bd0fa61f0b359f9fe6c493f96050499027c57d15937bf760be9cc5d2992c392a8c7a30075992c786eaf19c7479307fae52573d65e22c75051e8c722667cfbbfa1d4c5a4dac98ef4988fb0b08aeb08341a8f94b428c492728a983314bfd34fd83a7b9a9e90a3a1854f758d928b519e2640e663f9ddbd2d43d545b57c8c19ce65143776757ad7c1c0c37a2d3a7fed15272e0601cb592a627bbdf93fc06c3edac8eeefa6e309658d5ef9e1f7d63b7c194b2d54982acb0c1b426899dc22b286f4fafc16c2fb2a6543ea52587d46032bd8ebdb41a7249950693a44f8d7f978eddd74183292c7458f82cdabb04cf60127b5fafe63a873dcd60188bab5322adc485b70c26b96c77d6c449a2b42683793cc79c09e1b3ffd6184c8292f949bc7c9285c56230093ae7a4f4a3dcb7a361308adb688f6242bf0c067327b538b1d664bd8dbe603c95d6b62f84f6d0bd6012ed6269c99e704f72174c49122ba91b9d5fd45e2e185cd43b9727959474a32d98a475e91195236c4f540b067182569fbb8dcdc9b260f6d2d43f69e564c48905f357f6ca12bfaa42fc2bae60d8918b27b6886edbcb155630d668d5e6fece983e5d5105a3ddc750292f76c4285d41059324ee525227e9906da72ba660be5f915963ab2ee2748514cc15aec3c357e8ee9cae8882b18277c7d7473d49345d010593da1961a5827cb1325df104c39e8a5ede79841a957485130ca6b26ca57c41a568495734c1384a4ee79fd40963957405134cf2569a9650f91ebf74c5128c2a3a42a7281e75bc7485124c2a4bca2e79423cbc7445124c566264a4c51212cc29eba5e43693c37bfe0806dded6e82922b4cc7df08a6e09ec6929c3bb6c75f04c3488fb9f2f213b67d22984e52e22eaf2749d0d11f822589a526682a0473c593f583ca93e3413056556fa9307362974030fa5de519257498fe035352f23b74764e26161f18b6dec77ecd3234ec81d9db3c6b09aa4d2aef7960f0faf02d6f255b921d182e49514ab7b2cd9674608a9d264d29395fbc7360d0fe5993d7459ef871601072595249daf235ba81f1e4765f2831714a3630bcd7a59c743cf1646b608e2bba42dd07212a0d4c9e24252d444364766660122c3d259997e5a4b80cccd1754f67fb60fa1303c3be29d34963f7761898ae2eab9a2484ae788129456bf9bfd2ef29055de10283559e515393aa4d0eb5c224afe81cf79465ee87586138d35a1db95c95155a8531847853ba4d5a104aaa3049258fbcaf3b75a14f85412d65d126c7eb1c7d54185467087d39c9274ee714c679379b4b95f3e48e294ce3a342083129852985f14e91ef255d7e4861aa1d6d5ab29bb04fcf284c63b196843961649e4714a6927c6de5839cc679426134492c8f212f0579c9030aa3079573f410a2a197f309b3996ca73fa7389684c713e6d97e4fe1ba923cdde9846984a8d7bbd026d97738611e25e7c39589255cee6cc29c53c7bc374b166a3b9a30fa2571ec3c8e0178309e7b0a5fd96d722abf83e9ce749baea974a3543b98c4f7fd11a2b43a182d8fc9d7e1dea44e2a90357482d7f1c5163b5e870edfb18148e4e0f8220603a083a9e2b59d9b7ef45cd25b0c600ea6fda4a31c3cca06062007a349254f5ecac1b294201c363a0b121ce781811d0cd0fbc000e2605aff7b932daecae80315b3b7b1838701060007939cd25f32a9b5dfe4bdaa05171f2218c01b4cb253e4ee8d921b8c27b796a0f4e5596ba90dc6f6f4e94989d69794870de657b79416c4e2ee9eacc1e4a972ed2971abb5133598c32531a4cc577f7a93349873cea19ee97134184fd2b57b498ae71eef3398ea57d3bec48608bbcdd0dcb7ee65efcb50e5a6aa7dbcc992c1a4af779df3eae2e4760ca6d31f94bc68919b6b8ac19c4fce29b1a2439d5bc260fa601b4a3eb728295bc060361547ff5b89aed0f10b06cba646749a98242e7ac1fc16e42b8feccf7d5e170cb2a4a792c7afd4f45c30fb9e7482f0532a9df4160c27d4c5e4badcc9b25a308bcc654f79cde43c2d0ba69c42c5fd75d85cd3b060529f7dfda9a3c89eae602a39cc2595b38249bc247d0921f4eb8eaa6030c9e4123a9745ec1b00159242c996c38dccc8b1073005931c3b8a92933aade86c0052308b79e8cb4853314107d98f1d3c7494690e200ac693df72a69c129f4f080a862d9d53bc9221a48a4f30a7a024a9cdc7b35d2e7182c9f3fdabc91e3627f526182bbd2761214a9560612618e743783af9e49952b204837cae12549e2c9682aa04e3cfbaa69b7ffccb4930bb082d494a8d135e2b4830981c9683d24e825986473085395997c353fe5a33823929c9c40fa6670706500493ae55dfcaf324f9b84430d92779d9c372522649def0df6103d9487a02031882d15fde844a794cafc785600a52f4a7cadabb2d77104cddf72f100c1f5bfab3c9f10fccb615cd2d9514fbc0207b4aec2c7bd318931e98acd4d996380b964f9c07a69c5ae63e940525976469c00076600a953f7546f76e7b5a07e6e426e7f34787b6d202069003f3725c478fee1384120e922fca2cf6ffc916f71b68f97d4d2cbfcea5ab0d9695ad70295a83d3fcb49b7cbdf0a7a441fe29e5fc493350ccc45b3d399544adc8a00e7a2f4cde5ad4c518e429e6ece80b16d57330409c20bec7541e1db61730fac492f32b1b800bce6beabf1dcdaf82aa462b4ca1948d10a6bb7f920a2bcc266aa989ff255e52626829851aab3089a795adee6f257b09b28a871aaa3065ed9476fa63e3662f5da8910a835959e714de1f4eb041b6062a0ca3931464efb2b97dfe14a62eab9c2d9e09b71c99c2fcb7a162cc8d55e89352184f64b88e506369c38414a692ad135354c9cb568fc2dc27a5966acca230ffd95dd231bcf35a361426d99dec4f8cd9fa4a4161720b5a9e825754cb3f61b460821efbd913a670cae7dfeeff82969d30253dfa541279e184e932ecb54ac74d182cd79d3822ba82de4e1386536692f21b95de7d264c3a2b85d365ff9ee29830a8b7d793d3eaff49a91a9730b949ba97f3fe896cfd3b12115d50c31226e1972d962fa876fed40b352a61fe345274ea5f0b9e354a18e59356f667953a49576312c630fd58d2943cc89a22a08624ccd14ed2f1fe2f94e53b12267d61413ec70f97821212e68ff6497a4c5dd3336b3cc2a484ab74c184cad511a6e8b717f6fc4ad2ab7decf1e841810758266a34c2b02644fb8593e4beb618618eea399eea8fddb8d1232d6025506311a65d53134384f9052538fe83870d2f6cdcc853e38182474598527747ed7abb2d8f206b21396e1cbdbc15d44884e13d9e0e5d364aea199506b0d8420258e091a006224c829db4b2fd2fbeb6cda1c621cc31bf6b3ccfc5b41619c2dcf9e929cfbb9df0fa414e40012eeb3500c0a14621cc96437dc910a17da7a42750831026fb93a48a56eda7ad83ac7dc846a0c6200c4a093b6529bae8801a8230b89bf0df66daf37e88193453231026937b625216f1964e123bd4008441e445932b895126878e8e1e24c891e3465d8d3f184ecc180bbb59d1e1b5206af8c1b4257a15fe621d4f18e4781616881a7d30dedac829f95879bc54830fe65072b52b879a2433d6d883294d6de9243cc9fdf1c3c3bdb0c123e4edb0d8c20129b081812f6ee0a0c0a7c00606229188bda1861e0c7e4af6606ef2a78a150b35f2606a95efac7a2394e8c5ef156ae0c154b69e74d07bb1b27730bde853424def206b07a3e775ea9a3d7d17377c87c129d4a803d66319aa61419c20c7cfefc04b420d3ae0a1d74cdd9dc8b9581f6accc1601f4609a204255f12a72c6ac8c1e09ea428a56bbd03438d38984ad44f6a7cdb4f925370309cace141a469937e4d653c6abcc15cb226a9ffd0d1c412e6420d3718f49ee893748969fa758d3618c5242d6247cd897fef701dbf43c79ec02fc0f735d860b8513a855c25a9b1066309b2d4e7eaa5517602b27602dfc18d756a6a30e78cb338965f55eb83ac7df124c0a15aa89106d37f7a6eef701f94a03cb3420d3498db838c2f7d4b4a89a63398e2838a317a623f9b6e06e3f675f41d2db71cc232982e5405f529cf097fdd106a90c11cbea24e65fb3198cc726d9bded291fdd61083e994966e9fa4af1106d39732fda9ca573c4c3e0c7960c07ce80859000f14984884070a3e0a35c060929fbdbdf4f45f30a724b7d7dee9d710a7a2831a5e3055f0517b3b2509222219d4e88271f4a5f09f44f6a81971c120fab9c4dcdc4d7cb660d23d717d964abeac1ad4d082f1d74b5272aea4673fb360925f279d3cb1647e8405e38f74f35072a87555ae90a0996fa2a6e570ca628542d52ba96da95a2cfd2eea74ecff9c474915ccb194a9eaec9ebb2152c19c82f8afb8b5eff9bbbb418d299837bc4f750a7532239e410d2998db4d6fb7762e1289446250230a261d534328d9c5ac24512898c4b59dd97aca134c25f32b3e3b6343764e30e8582cd124534af8186a82e1945cea574fd892756182b1cf2c87c5d6e718d9124ca6f24c9452fa3fd2aaa104a3799eb892d2458f9b83ac9de0717ce0c85114900516f53774f4d8028b0a48008b16d44882499e0f6a3d5244c81382ac31124cd795eac4aaa56708877fd8f01da828e00bdfb143016be74dc0e74df0050e1b19a87104f38e9f20fa6faae55f24f21189740d2318ccc6e22e986f984741d67ad428827157548e3162fd24410e0edf91f0c891638717fe3b7860c0c60e1e65b5e0e2a304358860dc3293967fc264af538d21dcc155ab3cfc9f77821a42308d9fa51925e542502308a60bdaa45152accef7180435807056fde8ea61bf42fa03e3e91c6f2e9b5c25c831b7860fccfde757972a1e4b097781e36f7ce0b051b4460f923c8998360159f322078f901e47796090697b4a9c738bd1d3861759630726a8a10314d4c841e2257172a92555921489708624a905171f386ae0c0f06271728c35b1e54b3730deafcc7ea8127434d9c0641e773be324217daf81399630fe5942a99196a78141c687fc34dea924399a81e173ca6fdff1a28b922303b35c10a1aa46f64a6260ba3f494f4c47eb9361608af196725b496abcc098ad7aa28610f91f26355c60923fa9d6959b534bd2ad305dd75bf2dd1ab561b3c22047bda5945c4494205e85299a944ab8eb93e4dcab0a3c884e1ae2f5a6c2a0e3e85cdaa4b0258a1415e693ef84a7d4a1b39ca730c9d6b1d69ac294fb63a477054b61d03967c73ed391c220b4efeaca8be89f8cc628163d716ba22ffc9c70a028ec9c6dd4ccd3683d29a3110a838f36a1049344d597e80bdf408e136c516880c29c723ee1273efca76e41d62291cc0ed0f8c441ade492d25d6878e20a5e29fae7126e1ea5d109937cfae4e4943aa8ee39618a1d4d48fbdca94a841ad0c30b2c1a70012c22914824a46f40631305f15d2e7efe7b02011a9a30690d35e35da983484ba1910983b90925dada02593333770fa0810993b07a2f1e4bb0ddde8cc6250cffe7be629f2c942c59c220aa2b8e6f27952ef44a18e54d7dacf867a2589412061fb37092759de8dd933097748d592d4998285149984c924c50d70e2361504a3a29623e56d2ca6840c21426fab9ee1574f546e31106d525e85d0c5d72b5cf7fa0e108e3d567e7dc5797f4ed206b39d0122f7a6801011c14e037d06884f1549c149ef56584514db76c9a2433f662376e2cc2a4db94649a7bab97ba8ec339d0508441789630fac4da53070190061a893005a54d7c470e47c1231c10f022c78e06b4266820c294a2c8c5d67795d57f085349a652bd5d5798b91040c3108b8aa5738d95345a3ebad4828b8fa4510883a932514f7cac888a0961f0123d8e8ebc3ee19f92041a8330e99b8ef9a9a6210883cab1db4c3b3310e6681aea213c9cac5303c270497dfd49ebfc496e56a0f10783b8ca75ca47c70fe67295d9de0fd73957fb608a5e23f2eb7a2b8fa57c30daedec5d5e48b711efc168ef5e1dbfce29d0d083e1643561b2685a9bac3f0e138d3c98d32b439b7884f4401f5de0b0f19cd0c083f9734ff95c8ed9cf251f34ee60120b4f7d4189a1f4d5206b20213d743403f0fac34e0b2e3e3c40c30ea6a04ced57b8b351e2ebc2b738366e243d2a808148e4038b2d2480450e1e3abed891452412899cedefc871b640a30ec613ae72906172efc303058fa3580b2e3e7ad0a08349659c2407fda2d7953307930ca55faba411c85a8f8681041a7230c9148ba36bba8318330e26b15116e43bf6ed595c2012f91b899b60c787dc1707c7efd8d1e3c030020d3898ae2c54ac6879b577de1868bcc11c2eea97927962a852ea020d3718547949954af03bb194da60dcaf58a6be67835184f8b07adee1e4d01a8cfa26ac82923f772e490da6a4e2ff4972be37aa9406b3e6bfe5a4e64dba281a8c599fb39f4a2ea9df194c7732fc733829f97d6f0673502a76ceeb3d95d497c1a0cfcfedb285ccad10194c1da69f93cd08f79c3306737b9d758e7372257ec4600e3a292f415fc58ba23098db64cec4798a6d2660308bf8a092983af982d96eb7d3a991d52a265e30a8dd8a13cceb82b924adeca445875356c205934af2759c3429a272df8231d66f5e3de88cf95a30c93a27665aba743dea2c9844634b9acf3da524c182c1ee5f2cdc4cfe0aaf60929454a7af276a96c556308b89a7ddd3f572f65b059360a5bc3d27712e4b940a06e5a18450c976773f5330da6b87edfcea55594ac15c523a799475902de228183b5f52ae1d7fc9c2020583fc10fd2827a7cdf40453d01ef504e92658387182493ef1b3e3e7adb866134c2ab5859b240775bb21134cf254f69639a55ccf5b82392529d5eec7fe0f91124c6aa4ea9664e925894930895592872b4bbdcb0c09348e40c30846938d75a834ada543a240240c0603a15018100a276ebe02a31408002034208c06c32145d1b3a103140004404634502c2016241812101618120943a14018180a87c1804018100886c280c04070092b4c1d000a836cc8960acd7846621c8f5480dfb095a6f26690104c1ee29e83cd9a24d0cfc0e854421cb20099290935dc4093ae3c04fb733bd1a9f52e01cbb5b692235619f2e5e58748f5b0d7361725b7bc0e4690269ce133d882f2437c5844b82768038a6f0392dc7a43ae7d63babe5887953f5c3a30e2a0b4ca5d9a328b0f4a55a3e3bd5a81cb38d3011b0deb40d0fb5d227a39914406a211832cce7c29ca88f6526446891e29d53d095b892aa96c6898884e43cde53a2ee6d0bb2949ecfbffd65ce95be4fad9078fe4eabb513dbba111df7d700467d799c8fbbe37cfd43e3b01e0685814b46996a47cc849d8c9ce1f4a9470642ef49bf8fefcb53032a22a30e67a2369f2a6f1b6fbb3af8ae88e8c7a32a5ebef498a309027e3ad9fb17fa4ba2d890f3f8a325971fdb0ba5e357a8f6aa9eba383d917f78d5846c9b8f5c1370a0c4d0f1d053258aefbf951ba08b41fb3915d0c1d29c3fe986d2b40dc1ad561595ec00d8c89fa2b0a34ea7ca4a980fec60d6ec7d16e878ff968b8442ee4c0c4fa2f9f012723c7c21c7eb83af8d440a804bd8dc93ad963451a88251fc224ab74bf216020766440969b7990bdba9c8c059ef9c0211ad6b78654cd74e580079e2e14a56b9b0efb027ddf401f57d466fc8acf21ff75e5c52c9d59c9ef79a7e1a664c2f46a3a0e27a729a0fc1d37ec4dc679758ba506d84aa2639c5231b48f01b0d9d9f012230b67acfe6a54083ee0db64639849861587ba50f35cde5b25ab0ddb71a3dc0c314315f27779207c7952e44a32398a90cd1e6a6f1f45aa24ad3946702d7b55a3186d113a6c3c74539071d91039935bb268fef13df678fa49de0e11abd1040cb72f429de2d4ff5d486590d5189d73f4367d581280050af78f7841d4940aa30aed713e272a380a20cc2e2eab49857f50fdd6ad3ec84d3ffdc31ce2a7a579c4b93b19366478b48c7e438818e174e446fc622b269cd2fc36e6be3847dfd83e997bb57404a8847cb98056ecd457fe4d1c7bc9e9a9b4035a0e62c937987ce228cb0b6326b8c2d2a6dc0f1ff90cd02f1e805a9b22a36a61b5daf77ab96ffe55cf41e4d4df533d360da214c1ae4c6e6f04cd7a6ccf989b16e4aa7ffa2c37f1f9bddce0ad08b5f8118d92aaca10cd760e52c47fa4f27fdc915b9205f301e6a842ac96190486ebe5dc48b325edb3482e66b6a75a10ad2b2cd88f75644610b88d8781f73be0166209dd541e331a436a2c1b8d0969ff9d6c08b0230b9b78c427026669c653577317386fd90a342f17df9af04a40f38ee63cba60f1f84ff0880fc09aeb0a0bfa755d2d49d7b308ccec083563c6f2a758c0f8b5dca9c0388b4ab7783d50aae60bfa505c1caf11922817de06850d0c2cf068f98f88fc273dc51b75ac9e04c92c2cb2ed9b7a2519f42a5e0713fa262872811d9f27d9c927146d4cc0794d618780199598bf1a099c4e72ef6d94fa4fe1ff6fa889fd254f7b70ffea6d2ea9c77ed871276f45f11a07ef2d3a2a131432df97fd1c0c61d5055cc2f6408c1a4e7d9b781f206e40700714394e3e109064042e3540c5c2d22c45ed27017bd30b7947afeddf0435d0158c0264cb5a712e7fa6f0abf36d6eeb8a8c13c7e702b7bd023fab363e0c807e0f672037acd32db627b8c029df055ff232612089561553316053789195232c58b9aef83bb0478921c2a208c11d816397cd313d5096ba3968afe53ad2d8d968c108fa90c2178fe9edc12222708c07c2b08c657ee5ff7767eb7ef4a230ae4d5e5c884808d0071c3dc511f95197312c35ced5a3dea4622687acf36257f0c427124a495131cd424535ccfed0fef24596e2ccb56086c651e6b4e5f175d04942a7640525eb6323bf685c82874ee2a997213d180ed5c646cab45822a681afb5644fc56feed30f79e43703f6c9f24c9db391fc5ad059188209fa74a6b45e07a9f2f4ff279658941eb3205cc4c25b991a2421c35b32a61610ea5ad48c18e5c966b5d6f9e57cd1a2b096ccf5a7e2a7e623ce1d910102a25a572d88da9816a1ecb28b3146e4cb266421fdf7af734d01ebaae04432098fcaebb2e93ba746a5763af69e52c8c93a68f511c907d00b594da25154cce90d53440d2354bd613067da34201578b3a8d4fbb9f0b33ff2c5b48a41fd2d4905f884ee40b71f41c82aa34366f496e88d441eb0807fce725d1e9d9ddb007028d3f78bb30644325c14cf93cb0f49cc36eb223d281f8fca447e2501d3308f5c46cd9eb0a10bcb786d5e3ecd9fef7dee9f93a66d072f2b3164e1da1f82d11e2d639c7152c7647d64e2a8d1bf2e32794d9c49ed89d65233d91afd7e112a1ad184c3437c0a508b199da77675291ddf897b8991e589545b573b34e50388be0eeb067329d1887fa92c1bcd15d3099a617ed25a27486d308b3e7cdfcc8fc05eee44833c86a63a61dfcb4216c7a10e3077f88fb253153d94a012f46a940992baa800d68fe60c34600276423a717cc0aca0333a61901f34c7acaf42843c493d8781d49ed37a1940ced7b251fb490eab5559d160ebf277ea69305cc055f7245a3a06e17b57904469c4209296d6cbd75002fea671cd21c78724f15d75003e4f8f009f156c056d526b9d7f3c059920f3455f201be8056480139364640708e00d5958e39b26d8e0a50d6c0ec02a9beaed972117d807e6329fd0f1223b1e22b2b189f537c30ac4031e4129c8c25772dbf9a072fd15dceb4ff0f00ea2214585ad9f050012e0729a8d13598645ed4dd5add958d25fb609d262d68b32c0baed5e6e92892c9136ea5ab1a0d0d2c6541be1fbfb7fbe262a5dbebce2d13a006d427f99dd368bf33de53f1668078840aaebb5f982e616666be3c8ea6ea67b285ff3ad31e1f18325499d5e737021963016d018fae4526817f6786bbd10bfc331bc3a679948010bac8c0c12dc36ba471459c2ba6a90a475d73864bfe5b9af8391d75653d06a061b412389d34eb817f5a4e5999fe6e53f6e849bb8a15dc8490b7ebd08fd0284c5d6619ac57de2603eeea46bfc0dd3a6dccc9769db1ec593bd324e16f3b1c350e3f8e07c4e2bf0068f60d3a8badb66c7dc966cc84e289026ab7352f60d72c2dadb447271211a3b74781dbdc65bd6071305991b3c7b01a59d00e330081660d4958e35d03f0cf73ae967f93fe41c1ec3cec345506d421433aa8a82fa95f13825228bf0738ff10a3f15e4def37a0ebd6b1b6e5dfba8889d3c468998f51530d898a3becb0612f19e8fce398bdd5613409621ba43b2deb14f3bf6d077b6eb898f6121028410c2a8da412371840a43295c4c2bd7db3a7f2b9680d9639cfb2b5d685cc9f5c30d80e03a8b17726a17f366552e4296aeea1c57ab2a8e8219834583cf58d52cee4906f84d5e279f8cbdf0ed7302575789829ac262afe824dcf6ba5a59af71cda436bd548b369d36f2b2fc224e79f5c2f4b9938c2dedf2bdd0ecd625458ff3550ac4307ad445c60abad6083a96f679b7a5e21b6fad06aa2479824360cd2ca388ee7fe91595174e8c4adf41a1c7b23ddd9d640630dc96bfad6dd49eed06014355804bac532ace277d6b80fd565a3d56104fe94f2831fcf3c3289d0a631ede4b701faf601001e6661cec3c803ade8f8c427d21ee43a4cd5a25c76507245337227a7e0d79de0751dfbfce739a0102faf1951e8f6abdabfe27309ff98da3da08ebd0a0105acbb9c6da063556aeaf7d818748777179a627aacd53e02380ebb6eca8fc379edd2e7b6ec1beb5e400fc9285742e89f5d659114b4c85ecb588d8e08c22fe2e6e4132f9c8fb38492a6c054b4ae778808661fe840c6fbe24863427a0b0a694333318ce311da65665c06d7d0bb17519242d75a85a33436aacadff27dee9ea024b9511e4fb6b4a915b89606b99079a567a20b3a20169e10ce716378c5a3a03762b2d90adc8c069712f9881b2180906e2eb64c74718f6bc19ad717d63b9d591c257d32a6b73c3cbce5b6b18f70031fcdbeecc3db6abb9a3a11e2da4089c2ba39a966b53cf683c30639f48515b587aed13c971b36ae737cfc1f9e6b4266229a285f21b20805af85ab72fb0e983b8fa11fde3892dfa51c6abeb9c6d3076e073faa1f8c5ce00d6880227da91eb3765bc66745b6ca88562a7ab7568234b873deab6afb3607aa2f7bc82e22107b438234e00adbba1ad8172678719c50962059d68ab69d4a9dce88a024d2ffd9daa42cd6875ace29b681421f4b4fb4574fd4bb8d18b0f3500dc0b4b4a2f50313f4fe8058379acfa5cbb2f03313d51950d627d0eb97a02f95a8afbce6108d5ed99f13e67707511c2e55ccbddd9126a4c770cca1c7a024de3c984eab5c2243e2dbe83efd298af83ed723816d58f019e2a49e930ec84add2452f5b7e4bec0c0b9b07ec8a4a05f066eefcdb17d049dc8c0f5751142f9cc2df93942aa86482462b60cc9c82676347d6892c6c446802d79ccfe4d52d316f987dd1ef01f4da5ae600e9967962c70f8f579c3ed503a13e01edfbc632b18e04312b42eaa2937625867fd5b543129ca00efb9aec2de3e4668a92020990e601091701a4e05b3b356d5e4de572950ca7ee7cd878035c1d72a7bca9d4f1119deedabe2cf22a566473ac093f518765bce535eb1bf997f865a243fad86a02d81e2dbac14f04b0571fd0daceceaad00f54f4c233a200f692cf75297e429b7bec0e05af05133eabc96163c5715a63eaa365339531e7d0397950785d6b594e8ce612f47fd792a26fd406f16d2f05c0a31acaa96e087198aea8f3eee308c9ef27ab60bd45ad1f96314a8f6c2ba2148c14960c041bda1e898fc959bc48c0013d12a7c384dd87dab14803ec97bbe01b7819bc9de30809aca207e521c34e1f97fbf3d44abcb1b1bae72a17368df3a66b3b88a18e9170f6362ccb0bbe475e74aa2e3562f6a752f9b0734a45ede2e1e4d439eb321fb1f5ca697102775e39f647570a0b764394a465cd01362d08b416656c74cb89baab8a12f109d6e609b8a63f596a24d4039556fedde5638f97835831d4659915e243c6bdcdc9c89a2466bc38350aac54bd66a096faf002422b83145ddee3337edd406037ae9631a53217ae68f146db5f6c5ed6f1535ef7ce59b243dc9dec7e314e0739acbcf7890e208c520e6a66773504695b6018f596681b2abffaef5506f027e8aead7f3700a03edc443a7faf957e9438d5088b69594b6fdfaa26b543b9b973abcd8eb4f202fb644105810aa355b0694d1b761e435f8e283df854de68a5306c0d4d51566092e4ccdbad5c60f0a7f9b7614fdceacfaf63389ecb7c081fa1ed354b448218dbf266a5080d39e589ace79e998cfe32de121e4efa3c87b62c27957fb6e1e7c2ea4979c6c722a624a16d3c84b15f312e341c1869ee6d6c15947ffaf84b0329ddcd8397cfc47e9072d76a6993cdcb936e5cdb0b0138f648eb200cf39cae1a383f8e9bee5844f0d114901973d968ccece2330a3903839495ad29a73ad679953848ce2b5e343bc7792482d0989920702eaef6e061897fcdacc38bdf19ee3dc84ceb454a3134e3418cbaba5e924469984ec87b1c6df829eb8a28da9e91cb12d1810f5d113915b27e527f1989a92900746d9ea2eeb0e8722ef4f64c0ae9ff94d6fee2c6c31e8538d9b7ecf10d459a9886cb28924bb7db92227869afce4052bf604ade7d0e8dc763e4bf83050f89752245aac9c0c05d630bc21c1e8d3630c4c78b7c070f1d28a8d76affd728840e57cbbde078d3231c3d7af55535f09aa8292d29a386ff125546075892d3f3becc77a2238f0d69a705141bdfbe47dbc68553a9419d0a4f9b73d8657bf48f47e30c83a7c09347be996c9ccd2de3af712f1800caea5d5cd757304e04f2acca073c7ea0cdb7d28e9ad7841dc6e0dd75249c4beeca4d15786b6b4f432c3b0ff6e59a03f0168c4fec315f1d4852818ea4b3b4427db9ce795c1cfdd3e6f722920b3b456f33bbe04f59f7e973d065da6d1d6a9892adebca9fc8ec778b19c9d385112138c5368b8d20e5c15949e52a1fe99891eb1a64e76e0dfb66a0340c13f986ac43c9e6796e80af2d1561959b0d1158c3602ad8b30074b6fe13a9c37f6e6c0141397f3ef42f1c30dd601e1707779e606411bd4c11ba5711e5922619b6e584424e33a8882313cb7a3b4e6dbc344a1ffd29a264613b8c6e71ddecfdc4f13a63e575f211b9ed2850ab83c191208c44d821b0f918113d543ce6b72edaa1f8dbd08bb7c1bc757b916d749af2ce1f52a299f6bcc835804f87475864d609f12b3858d38bc36733a8b87e07b67249139b74aee3657fde874f781ea21a913d730d425182a4c6ba68f603ae7a66f5e9687f9971ef1cad825749c8294504999b00bd059d0f5ec3ddef09bd90561c8ba2506a13d227bd8810758b35048dc54191ada2b9f1a2c1ca435c09741dfc280bbeb410ae296011a3e58595c1ba74ed79256a39ab04a3215c126c3f208e59bdba89f6fe7fac36637789ab31429338a6c1c5085fd820d08014567b31a53459a83d5d82862b0080538654297864049669bc2929d1278580d18f604dc6c5ffdf6fdcc7efa06d4c93f3b4f5ecefdd890143aeeb631368ad3ea22cdfd0718516d1ad9fa5dacab86669f9db2755bfa3e0c98ed7da99f53853d6ba181a0dafc5408eb6281cd1f9869a57f50d020228e80bda43f5b2da09104700e7da623cdfe4529b752bed2f7d7213742b016001e9a5393f642a4a862b80b06328be9e88ea28ce5de4f7a686a10d390c2ed5e95f52ab83d712c19ca1444b54810cf710c0c5024dd14955ebb971c4102f31c0e7db5b5ea43cc6b88315fc518322b863043528c6610e6f63bc5aa64ec5f4acfa3db0291ba4ea2cd2bb1b558d14d99d06cda28ab4f28edf0285bc920eefdc41795fe082faf4bf466899c71b02d88e262b8996f0863e04e20a27d4c413f6b0442154732e21f45285051eb08b6b0ca08ac238424889d140598a5e27afedeb40ab745c26ee2065a8db64d3fdfd752a0bd2d6b18ff85f27722f4c8732ea8519c2cfe17c4ef7c9d4b659138c025d0a362ed5afb1465c4172a4a5784d5cde2889510c562bfdf6b178e95de2a1c2db3bce3bf42bc7ed3217e6bf95cda4fc8af2f2caca82721f7f41163227b4a210a56ac7d3a8824eb328b0629bd7811e8c1cf00962564da34cc74e73c0bd61c85b1d9083e4622d422c2cbd185085fa7707f46148af807bb7d03d01f558b0e703bc8f617d02f66cc15b02d46fe15e09e8b6867a0eb0370cde10b05e0b7b16e00d0bea15303d5bc8c18d00a3b742f1883c18e38ef430661df158cc38eb118c75c69be88c2929645194bc7447c98414f6c75993fed6bf37169cfd679877dace38d3a4e05bb780d8a0e0d4bf01aba002914a4bc74967da21d027ed2ad0f54ee069eec05d7997b72d640d9b6ce4250405492711da504c1a12a19d02a9f2271bec88b7b2dfe5fa5efbc49de6c65efbc44da771cad08093992b5f657916fe3bdccb2989db11d064a10d95d4412589494323942e340780ce2477557abf2e6f21294890768a9086c4b4a110ea2442da480131d6a5dd4e66ea209dc0a95902a773a3ae3721296890728a9086c47466b1d0215f4cade8401d521308351220150da92531d2910670c0fd2b3c7e60f4ab121cbcc77196f9d34e6152864850e056dc75dc214fee6c40255a24753585ac0ac85dd879e90485dbe84ac8dce1dcf17dbfc48b9cf229de22a4d1839bed8a25533e6772d7f14c40166bded2103f2ae9003ff205dcc8458979be284ada7c59cf75e34d9057aee8c6cf7266effae64e950c8b81518306892876170b13c36b57a00db2244c02ba52d3993dbb3b78951b3efb33b84bbcab9e90c7ee8d9ca59b9fc9d9dee9abbbc9d99ee9bb6ead3b18e4799726aa201311696a9303382f0a7906a89a4c74a0998cc8a0632ad1406632a283c66422039da988061993890e6b7ce6cf704756a789ac0e21588869f9361df7c5dde42cdff915bce50c9fdd0e349309597440251ac94a66ea72993d411ffc9ddcfa30eee7a24efe6ceef64adf265332d0b9e6311963cea632c3d8c6640e9a91850cd7e9cadeee0c9ee50edffe0cce24de55c9aa082d871ce5a33f829bdca133b713acc5e9f46e8b68dcfc341fa1d90e693c699dcb26a96bd6680e2f389c2a37a5b3e307b348a631380c42a4357f1ee4837b9a35ca09212656b000fceceb4492739f20545d8e8507dc18d79a9818906c2137c520cc15e7742434ba02a19076e4f58019192c7d399251ae233019be9b3aa2e5914e1c1db2664f550517414f57b6762737ab92d0688b44023640b06aebbb4b2062996472c14ca42d8d2e2955cb8ce7451b4a3d9368293ee228ac695f9d86cc10c5973b8ce30fa969c3c0b57e9ef440cae9aff9fc1d15146da359aa233b8fb82337f354585cb41a214181a62d5082cea06260cbb348433c2d532ad1a752df81304d2184dc26c9039be32df9a642a220198d6d2241c1cee79ec670553e9757702fd3ea1c454819a9b36a78aac3a6ade4461ea3ad85075d2ebcf6746b2afd09cc20b881d13d50cbb35236ed637f5ead7b2b4905549b620afc87c2068c675ffab073cb9b34e4b737df865612414988039398a2aa182f8525c6bc47474299adc6995009fabbc050e75db178377a3ca9f76280e80002a447342a777e065b5586951628d468efd61a68dcf67dd7247cc3b22788789ac412cb1bced283592609dba8593d41a9a724e0c134905125f11be279f04423bb94fd2b5c490d7dc29ef0ad1d70980d8818f13f8e40d3985d161f88da7572117da82febd79fb944a778142f28d8e24d3aec7356610d1b2753a42d20c26e72d51565cb8b8271d18ab8763e46f8114e155a45dc6cdb91cb5bf1f5e1f279b25e6fd6bede8a40f445e10f643ac60d1b3469e8d1cfac21119d9da8a13c3223a19a92bc2107a49c0edd4315c9c42c943dbfe69ee2d5f03f8f46dec179436ede637de7535c81ca4f90892c674a790687ada949e030c0491fbf0c27a3d6ae4518cf1e584e3eb97332eef4861251194c0b86e9ab49fc04d52e4d28ab79d24034fc50489592804238a5a96e8a3faac3cb4a8b22417c79b433593186eed6c69590835959157eea68360205854de82de7177273fc04475d7eebf11f4dd3c49626c5a700e890374abf6ce629b58f2841d748a829ce42a09220680887a3e640ca27a4edc866b1130f0377b6aadc3c007f89000cbb262d8d56ab0aeafdf4a64e3eca5aa0d99e37a2cb96b7ef26aaeb68f9f5f94803470eda6bb76455b0db72e4e5489240a32c784af46e7fa57d2534b3353465daef752d2a2b0b8272389b0b4710755b4256687ae1f1273b03af25838159a7ef18f5d5284058df41a6ffce688c73944b73a05befee820c414f3f958aa8c4cde481db1a58dc219af53d15734c910b66e1116b8d867bfd05e2b9af19f574efab944eacc0a171a93758597bc893402f26be309a7141ef342b274f4e48589a6ac5dee6af041a4bbebf87ee96833c59ea7408a0790000a18e16a13762e7781496184353e05624e798dbf0e4282b2f368431bbb1f1a597307358a7a22678ce64e5d5e2954be725e0c541f23c24c404b3e71938f61f48e0d033d480fecb12a4fc14270da21cd3531212df447344fd393517736bc53ab784b2ab622f21f732a66f6dab323f6509135bc72ca7c1af2474082ae68708974196722c719216cd700c54d559fc169f28befad0024edc43912f17794f549c95816946631a2d1825ce7c33f6b90ff2dceb3d1aced71c937385ee068c1f5653982ffb91bade57ff08702c72216628d2468d953e5f557a8d34619be9266d71fb8572b5f31f833dc6b118de4218d2c12f71d913da2e7f2c37176d2c1bcb1cb09ab3253ce30da3b0ac8d792bc30c309e40cf3cc58d9176720d8ebc2ba5454c1569953dec95cb4fdc86c38e820a056089374181379662906b06ecee0de81a32dc1df6ee173616008b60c8223024138c8078f029b0e584823aa184adf17000df0fc4695071c9866c33358574cb1052cf075094ed3f21f0bcae7c457a4984eff73677457e8eaa8a10bab2bc5c95c4dea434c1fa1ad8c9fa4bc9b28f5173d13b926b3ecdb8802785de77721b74d5ae9c79db32eba8c76b3e9c9b33ca4240d0f3a7f68e4240eb54261fbc7e7a020c3d2ec6fc3872112464fe0da1e85809a039c026ea9b67d89a88e19fbb3e3854a1e44e1c62a31c6c66e052a321e13781e6f2c128890a4d82d8443c8763cf3f2a36c777e27d376f31c7c3fc746f193d8c6a117df0012792eba2e0f0c3b1a935d0522bfa15b010103b8d3225b6a6eaf9dc079826e5184cd638c85a07213b3e4ae3e438d603e9527d2d028af2e6655f59c08195aeeb2dcdeee6c324203150cb61d36a3fbeabcc60b1ac0fbb789d605928b512a1af720448466910cac456edc90074ca31e01d727133d4182c4a09459339c4dadd52744059d431ef0a041444ced98b4e6a437f03287a255cbde5749be3b2d85ba3f0a52916d8127e0a067fa85f40b3638adaf30ad897d69b68df425bf46a1818e5f869e13ab743cf01b0c88b273ab0066270032eb467b1b636e1501e756375dc4e4224decf40374152d007d59ac7ecaa2b443a0e1150e060499a4508282d6a0bcdd74681451ab984fe4a72ef312181a68d5f448ad0244f69c7484714c4c34adbac2c0010a95aba58fa25c1e18675b0d694f1a83feb12136fd4b8505c6782c6a9905dbed6ac1ed0613920e2cb797e2d079d094eb3ad255752081096c8b7c9916879a3bf65e50e87384a011b6a71c81db95c760ea90a9e9467fedcfaab00ff00e5b1367635798daf6932aa77b4dc8f85c39b1a91bf1a468e8880d05ab2ba7351f2bb640d976cf79499cde39626beb8010cba4471b93aefb3098561723d9724ae8fc2243b54e15db737b92ba222a2ae1270ef31b500c80daa9d544f2543b6bb1922046ff8003f5f5cb64e2bfa2e36b98abd1b0f24bad71f8639162b9111a45a3f23fc2b8f0faaa11079f323af7e6fb85cb0a430151e65c707bd29234af3fc6566ed9f836368ddf77344c7cfa85eb1711e59356a4d662272d0f3a1793c0a69081cdde43930f420e86b5ebc3d1f60ca29705410cf21ed91abc7bfb2c664e9ab3b855f8d4a125faf40cb4325e0ab8c9d48cfed39c4519e65abb73073e5c9457419867a9594a103eca03242919fa12eae42bfa8111b66e5cd0cff222872038f8c458dd8fa093d82d6153e9151cf5ab5cd3e069700dd7c5851ba5a8d8c111cd24eba91fb9156163aaecef783eb07c45d460586050151f4c8d2acd3ac78d8275af7659ba2f65b9dc8aa97daa06141989bf2b363558669ab28e652232955ccd3ca4846e615632bede605814ef05f8ca1fde4fe7d93f7b44caf62fb215d64ee75e50440bdd97e103061f2d47d7ae84c56a885726dcb15a0f203df836d4153ca71a42d53cca444525fa67fb53e53c92c0781051d132d6835cb82f4a4e500c63d35aed22e37e06717974e6e09d1aeee9641440a29384770a8390dcc94d6563453b0994ec5bd15852f300b719ee46bbc332aec9c83ce8e6273b07a7916610cee880ce4ab38ea6e0e948f6b460a76d7a82c911db290d165da360b27b612f9a9a1b6e9177474f2395f19c2b75f5f26854d9ca318b18607b5ba23bbea21dd36b8c291bc8c458d397a72a5681501ce712bbd0a377e4f38fc7d3f2d8b7759fd9e1544a5eb2f312080706718a2b5bf77ca5fa9b7bce7ace0a2c199f4709f60965796bdc93f3dee55d998b62f781819a44c4ab800b6b401871f85d6e6a4e94a9c13aee331b2c03b56d826b27abef5effabb48038cd687e2e503b2f6c81dcd4e49373f5a4cb6685fe6fb5a16dda6770d03f0fee4abc61eba65cf7bfe54125a22f432b05dacfe6d6a4ba146a0d4d34c2c8f93cee87822f6c8957397a07ecf5ad0984f628c542730aa9f8561775218177c22b3e0bbea30d8c9eaa90c31aaaa3c05b0d7d41a6757519d35a2f3fdc9fa9ecbbf55d00c527989fee6f261a6f9e8e445dde20f92bb62ed25313c9b07b11eb44a3be9a4b890ab6a8b299576699eee3be54a73a7625ceb8e07da99092bbd04299d26786e77e25f389bf0545351327acceee54cc2d565dbe1452d66c89f830378d0bf50261c48e3d017ac712bb624aad415037f4016aed7a2bb90214e58b96b561c722349d2409192d95b4e05f5127b893317084dd508b6d792503a52e6d61182558140ddf7cbfd1f03d727d1e7bad52f0e2d7f8d333cc4cd128bca90e62863a85ac1993fcd406f9f2f1734eb877373020e647e9d268ff17b876f38c258f219221a27f55045df39ee55b93c91680fde0a6b0e445ecf7e57a3516c1fc4296def6e6727290ecc83cb26801a28b4336f7450436bc8e5b4c185a2ae5b9ff4db68147f101dc20b586b7855efadfddda7ad2cf2a378ee87526cd4ca4b224dae1863194a9237b490000b9cec6ffdbce29c2a0fd9094785d6f73f6cab85ae0f49d7f01dca96fbfb8d689a4ed7c0ff5bdd7cfc42e6352472ffe4ead6ebb8e584ac3a12604099602182f7a0d149cbb54af5c2929439a2da292900d801d09b82b144e7638898790d19a65f64413ddf0f4c44f7bf585dd297cc67a307ca4a42fa4aea4119a43159b7734166778b40e468d35c20904341bfb7793b9a1707080a2022cbc12c1272bea3c159ba0c6bd7f79a4b6e62da30f8f9583c5fec7e0748aef28f32e8670b3b096956be29851482970c0bddc4ce4e657dda992b4cfad70e1b885860a6a0ecb2021fb2e3a42c370ef36dc5e7578934413cf954195350549d7e3e30ce29e5ec18c764d7bc6377634bbc6e3e8b90d89cf867163efd7c3691ad0734fd0e15a65e47c10bf1098950f0f9bbcbe0bdc68f28f06d28c0f6d03f5fa605ea8a8b87034af17bd871631079364efe14c7bb2ea12c5b2a66685e2cc3735db02d9627db276c13bdd98ae8039be426dc76648e89772c5d10bbea03843c814fc8cdbc084edb240376f947c2c20b52a99df7919f95a7bd9e8fdd0a599dc11e098f4d6f755d6f127dae2293bdfe1fa4212f3bc26bec70b0ff3c5196ddf4c0d8ec706f01f41f02caf05fa03770f054723ccff33ccff33ccff33ccff37c8479ef8f65a31511c9eb113aafe33d6866ca9d9b442ac911d4488ee44866f55bb7f9e488e625e109420a160a66b5f9dd8dc92a4f7a144c172216ae7c53752328985e542e4a2f84d4e2138ce297ee225c886c95728251342b98fcc71563a9269843b75f9139896bdac10473a57b9c0b1133ef7396609a0ec9f9df03edf04c2518d24dc7a7aab861974c82b9dbc53a4caeeb9620124c9ea3e95eed3904cb1fc16c373965c4478d609090d3a3f26a76a45111cc26d3eaffe7b57e792298c523c793e821535f0fc1387bf1d244368560d20f75d9a2c58b4d3f08a6b2153df7e8b153e80082218b97655d13c9f1e7f88129b23c3ec7e71241253e3069aef999c5f868983d30c8df47e1912d0f4cd13d48138f33bb92b30363d9d74e5aa644f2301d984d2f050f42227a249e03d34f87ef1af93a9c7ce380120fd2d53b8cb3b88139e28bceb407cf7f4b163630aa85f0204290199b9890450d0ce241c418d7da724f6960b614c2f37cf43103f3a7fce9e413d5d3586460b208a72a51ef5e9f8d81794ea2c7922f9d050c4c22e369f139d6e32867f10243ac881f428acac1d49e850bccf18b887454eeb148a415e6ead4becb519ccadac10a73c78a3e69a973a54badc2fc196137162f7e6e5285b9a39c913df73879f8a6c290df53fc547d3ba5122a8c5e1d24455e8edffd9dc2d89bd7991212a53ec814c6e97c39d1ab97c23c1fce3adf4bbf7a278531626bb23b5946cc4761ac9f8b5ef51f5b6f89c260a3fb51fa38efa70787c2e4a19ec2c7e4c259060af3859ab4f393fc51487dc27c35f3eb16af27cc12522b9569db09f3e7b093ab12fa398ee484a12d8807ffb1dbc7dd4d982cb5e3c9b9947ee44313068b91be82f5ae7dd8910973b8c48e44a5720af3c084f12e4ab744b0f2387a2e610877ae21d93523e5b18471e3e3f83e35cc5afb4a98278f48c751e99430d59f840f753af609c94998a572f09b6fb7934224610e35d9ca21d4a7673d12e620eadfadcf871e390f0993440f4e44264887f41e61bc1cc4b22e91e838a48e306acda95e741ce7fc63234c3e15c9dbb5e27c0861846935528e2cb24598a3be9c430f6f73ab5684e12347a2589ee0c94312618c554bf520b8570ef28830f8cff6b45f586ecd0e61f458d6673b292adf6b08535d4a32294dec6eb910664952bbd517210c1d94b4d69ff6ac6410e614d73e2e2427a27a08c22817132d5db3c53e3210a6e491575ed2def01c018439374248083978cb1fc71f8c39a923f585bbe78e7e304ea4ce9ec53be5eafb604e1d25f3a032f3c110d299e7b0c6ff724aeec17c7d61f35e759fdcd6833165c53bbda7f360ccfa2877a4fdeb1dff78309be7be96f71c24e67607935cc833cb71303a5bdac11ce13bdef79cff091f75307ba7754709251d0cafb9f6e3fec1a6c539185fb3366a3b0c9df4cbc11c6e4739bfb3079d9d8b83e9e42d8d9a95af660f07835c96fac80a0b9f7e8339248beb131eabc7466e30c57bac4daf0e262d6d83493d72f638e5d0c147c40643e4ace5415b8ae8145a83a95e36423e259590623598fa222b27f4950673dd6ae4498bd0153b1a0cf39e537210d235619fc170d531c4424e9f3a4ecd60ce09da3bf739b649c132982d3ad7cec30e25e48b0c86f0c169c590d8d2af2613b01883e95af33b8e2689dd478bc15ce271a5ea1ce659c70983295b08d9c5838590ec0106938c5e6987967a68c7170c926a925fcecb8e72a4170cd1e55278c9d93bbf74c198e281b8e6ca5c30ea071db4e3e9f8f603b760e816b50e692d2d98a73f4ab17f46a2cf96058356eefabfacf2f8180bc6d1b9530fa26d2449af60a8b5afafbd76c9b16205c3575f841cb2a70aa6103572aeeca8e2c7492a182ea429cfd0ae09396a0ae61c29ddbcc3d50b714bc12cbebd67a59eece48b822152ef764facc7991c21600105c3f74c48f1e07ac62c4f30c75972b411392de5cee104f3668e67bbeeb485b909a6948d9ef34f71ad4626186b65fff4d3c7124c163cec3814177fb9cb19b05082397cf6524268a790104b02164930b4ea448796f6c17fae0b5820c13877eb39bfedc19b7c04534ec1242f4a8e85c508c676f1f0b142ac9426aa5ac0a20886289236f573902729342c604104636ba4fcdaa155ef42c810cc4118e9bc74a9100ce12cb77e78e1bc2c244130e5ddc8896fc94155428060d69193b8bd1cbd76ee07e6afbdce321db2bc7f8841c67831c4d82ec62058f8c09cf5e387b96e89fdb0a2aa0d60d10393548e53ee3855b8fdca860d1b368cb0e08139e5f3c383aa10967360b103a3955ce8785afe531e0b1d609103f358d08df4ab8fb4cc1b484751010b1c1c163730e4f824870ff452d84ee0c51721680216363024d1faf7403e6ea0186378310238605103b3cc7f7894fb30babc7741027402163430458ed84987207172dc0c8ce1956445f26cf7c7c909c2b00011b09081e1bfb6a673d4edc82558c4c01c26a7b9cbb77ad13a6e88b10af80216303064ad44d7fea9669667072c5e60ee94b2f55dfad8eee15c107103162e30987410c96346b8a0e4c315ad30871d84b98b1131c9498c830e57b0c2ac7329c7931e4b8ee8051820e8420c2e4ef01fe0c20f70d079f11f08238c107c71830157acc2142a694b3c8b20167e071c50b84215b66459597de49c194985b93e5ebef59c6b6c51e34910c68b41862b50619c4d4b1f8ee5befa6a6c51638b2d6a1400ad0c579ce28e5244891d87d241ca0e3ba8ba1ce58b96d6b080036ad8b06124302c5c610a43acc7dfd96a32c444245c510a93558e52ac89f01f2a4f0ad38d7dbc17631f84ca7370c5284cedeeb1f383290ac379bc1eeccaf275ec0985f17ddf239b74946a3b288c3a41fa438757e8fb9570c5270c9e72a656e5b497b055608c17c313e68da01133bc3e0eea25c153c0860d127c18d90943c48795332fe43fe570c2509e537aa2e5641dc89b304cce8ed2ef36d371900d1b10d800172bb8421306edf82ab775beac453750055764c2541b71dc527503e952700526ccf176cb3cca63c13630ba28819de08a4b18224e723b320b37122cc17ff14486708525ccaf76eeada2671b9204c2159530b707d18e42ee387b9c3e1f5c4109b368870d49d61eb9a39330e708965e23a4e794d237902461a8d4e1e5c548555bf806d28ff1c57aa0540fae8884f96e42b6d18b1f7d4e720109e37dca362529a683fc7570c5234c7dea7bafe31da7101be3c57084b1ff4222a794da0e3a47e1e08a461822d9c73be3f1a49c446f700523cc2f2178a4528f95155a84a795fac1aa3e4598cd4572c8962de590ff4418eab503e9dc915c7e50dae00a4498c35cd4efc0f643b50e61b6f011112c758a109234b8c2108689b2949c7ee79e6d21cc6d629667fca5edd326832b0861c8bd59c1ef5379580f3106614a23d1fe63d949f9713790046114cb2fa993e5f6f055175efc185ddc28011763bc070261fcca988a0895c2ae4f0810e6087ae6d942f66597fcc1a83b9a173e8c0e3bf57e304dba2cf6e14f7aee8baee883a9d347ca390a7b15ecbf8174900baee08339db47ee623adef7efc114b2d6a38adc0fe9e3e8c1a87b9d1fd654ff270f46ed2c39c871b77690e2030406931c65ea44f5f98bdd40f2c28bc50241170e00e3dd04325661f24e0fb276b7f77854615cffcb519ad6531d252315a6a4f6913f4a74b3d9322003156423659c826c7c21c31464c34a6188d6f2d2b14cf99ba430b4ef496ebd0a23df16440832466148d91df4659d7fc71635d2860d1b368880204314150ab2210314878c4f900d4f98c3e3402b4ad81620a3138674fdd0728a90ee3c9e13e634563ac9bd3bbbe89b304545c85126dc5422d7842164b4684487cedf3b138659b5f3d0e37414b3c684e92355434acae4277d09435754756fb598a35bc214fae921ca786c8f5c09e37bcef3fa78611f634a98ef4387d71ffa434a7812a68efe2e3c5efd258425615897c87e7ef1c15e1c0973be7b14dd23a92e624898438eee5b2bc8e494b38f30d7684a8a2fad234c97c2fbeaa7f81fd6d908b3dbbc87729dca5d4d4618b73fcaa1865afcecdf224c5f593dedc4a81cc5a708731c3f773afe4ffe798930f7a656b24e164498f73ee528e2f4740e2c8730e41c7988bcd6519a698630ac89eb471d3b3fec14c2b0ff71e5dde3a8e3342104e2dff6c147eb200caddb932cc27faa1484299fc713ad25dd6a8504c270dbaab37d9e254408200c97e5f93dd2d90895fa83f13a48955b55f9c1503d3f93f693791cda07e3e478653f8a79e58a64f0c114553da48bce7e313f64ecc13cb5923c947f946f3c64e8c1ec1326e490baed3c76c8c883e923c3a27b0e6be6918107534efe8bdbe1fd69f21b4885dcc11cddddea99c9b5e7cf0d242e46f02310c1174f481564d8c1709692aea6a76f2085f1639ce5a20ec60a0f268f854dd55c70f17c820581d2c1d0a659366fbed9fb71514a903107d34739f96b67ab4ea99220430ee6143d9ebd89de4ae83a071971308699bab8f9e5b85396830c38fc518cc7f5e1be6f305e9ce8b1c7fb606f4b37985646be5a6bd36c926d30590e7274ba90b342bf33830c369842fe78903fd696a9720d86ad0929c471ef0332d460f6f8d43a54f2ee30242c230da69af8ddc1752d8a9e9890810693779acb33d1f6fc2f19673047d1538ae997e3dfeb32cc6088dd0b9f83914a33393790f40832ca602813fdc8426224194c335d31a95722c5720f8cf109c8838c31182458fda78df197a81e04021be0020083902106534a513cef4f0729da85c1f471103d2a72bc83b26f201102be8880fe4106184c9363345ec2b9e720626990f10553f607cf392b8d4be60563d57fe49dd31d1132bd32c8e882213aa79c8f2cccc372704106174c2147313d4f587b8a9e23630ba67ca9ec43a647b9daa205b3f6f57f78163f8ea7bb81843b909105237c8e3817ff878b2e5390810593f4cf7858fb676df209c2f81188800632ae608ef1aaa5e76ef95bb981d405177f0214ac17571c906105838e8855647d105a1d30c8a882394894947bce6a850c2a9873c877eae421895a7e1532a6d0c64f082ed91553195230777ace1a1ea48bb66183a84821230ae6ac3ef72bd19d63f95030e48dc81f79db4f309ae5a062a4b34e30aae738f987af4716df26183a8ca5e0d629130c1f7e6c39858ea582049760de920f26a5f75d0b4125983f2a6ff8689d458f4b8241db2c87eeb821c190c348688434a9d21ec19483dea7dd930f6b2d23984d2fff7a4e043fab08664fdeb577edf91611110c5e51eedde3ca47e6100c2adbb1510d0b24400c13ec036a6c51e30463800102e35f74d1801a5bd438c137a0c61635c2f81b62ac026a6c51836408c11423071345e6263cf841307eea2064dbbd81609c0f725866ffcbf881a97294becee4a84a525c102141e91e64f8c0742527c983949f3fe981e1e24d79ab57b84847060fcaf1ef71a02b5e295c193b30cb4bad84378917242b327460f459091d786cd7b13222091939908103b3e57eb4c93367db08f8a01a1648401816f8220235b6a851630b5f408d2d6ad4b080036a887101cc47c8b881f94224427d509233721b98e3d749eae1d49faefa06193530254f1e454f2d12a45619343056597638f329ac72bc8174d41564ccc09cfa3cb8dcf0b9ae1429c890c1d6e569ddf3f2c2ef304610820a38002f212306faf8fbc54ca94423b844c880813987a129f5b177b11205192ff062ac5a8ae43977baf0020c30960b74830c1798a3a01eb332596ed112e30a91452b0c67fae5751d57ce7537908a14b2608549bf2bee74d53d7753c862155a5ccec92ae22bfb0da40f84200437b8782fbc0b2ebe084165a10af3e5a057f7e13064910a7377e78e438efe93df55811a5bd4b0809619b2408539bdd37a6c9992e5db82b238c52187f56e51c283843186185f74411e50638b1a5b1839c54116a630e4948bcb8d945a2f2e8521da476ce477becb9414c698ffd0952eef55f24761aa74cb1b15496d2e2f0ab3445f55d297cb71bfa130a7e0eda926697fb82e280c934ebe423cdc5b3b3f619c8923df6d9b27cc16da5196142365b1ab1366ef0b21eb6b0469f9e084e973768e4aef5352993751aaf873cf8ed2fb2097822c3461968b1feba17e0ab36f26cc1fcbbb637864d67d61c2d039ee28564fa4bc951642169730dd5fa7240f422764610953d24a11da546298442b610ec3fc7aefaf3ec50a75210b4a183afd8b618c7124008f90c524f4e852470739631e491c78c7e4c073f8ae23617c0c8f663a550c09b289da7e0ef982fa88536fae7b627927dd1168cb6cdae7e87536e238bcb156d1eae8b0c288b2e5bbaf9c1f7eb65a041d071d7cdc7badab2a22558f3e1f85ceebe5910872a53d48b29d3e7201c682a0c0d883c0581090304230c6ea09b2408421488c497c2cf65ed60d0c01a1304620c617a60e61f4fc97feb072eab8d42c0c6108c9bd2e913c07d31dad218b4218fb4ea62eba4f48168430448f2db23a780761b8f00e2a8764210853ded689142cfeadea241086b9e49583b433112a6401883f985bdc7290f02eb943dc0f86e8c9a6f2bc781cc7de0522b0c58d31bac880185e7851801a5bd4a8b1458d2d6a6c51a30224e8c20e2a50c8a20fc62ee9f22854cd69843e04e62a0b3e18a3b6ac3d18db529cd052a9c9fdc8420fa6d2cd8ccfee4a9e3e4a0959e4c13c973ebacbbbab49331e4c1df9e4b0b63e45ffe81d0cf1e2a72812fa3e4f720759d8c1e0514b9ef3d4f92aa47d90451d8cd6952b78c82bd1d7d2c1f4d9ce4672bfb4411673304978f7af0fbb1c0c963e8a1daeb974ac131e64110773449f78c9c625c4b8c0c110d2245c87b46215dc371827fc435535ff30567783f1fe2ae6c456ff8ecba20de6a0dfd7717fec51904b0eb26083c9437c46cce5b66cf50d242b618c0146166b307cec8a3cfe93d553450d465d5599d3cfb0ea2b0de61c2397dbe6a7ec154383f94bdb3d83d94f74c2757b18b29b19ccd117fe72eea7d8692983493edf7c1c6225ee6c32183e9e47a7472939b78dc1d02174cd87ebf87a2e6230cf99a70d0f56f2d11206d3c56b9605dbb78921180c75e6810793fa3eabfb0543f8e8c3c8e147ae7c1e5e30897e7d0ab13be5a8f25d30079d69e2e69fe3242e98e31c47ad221eebe3ba2d1892e9b64418cdd68e69c110cce3768e4424cbb62c98834f1e7c78ddf183f858306977f8c9abe3dc9a932b98e392a4cd07efb1d359c114214faec741ec3e4f553084f048d43f0e1d4b7450c15cef5b29448ec4cbe6291835b2879012cd33dfa41046c87b21dfb9341661ecb39d8a12f258ccaf08737ee8074b791333112fbac880076824c290239bbf4eef292cf68830c6793c1f0797dacbd38730e55f4b219697b6576c087307d21929c48747152d04f1c26e55a72c0961b4fa9e7ff397ee980dc2142c3ca7b987696bd30d3c41182d4bfd6e8e5fbfe76904020fe645cc3ae7a00188e3f27899109a1fb32d6cd8a0f107a3daccea76189ff871fc60ce27361e7c74f7c1b85f39f8c9ab7a9c663e1862bc8333533ff57cf7600e3bd8b6f5aceac1f05194f92c89b21cd33c9834a6d2257c100f869493a454faa1471729773085b8dc27ad6b372a7580861d0cb3a1a31626a6b4ee3a1842058b1c1eb359f1d2a083a9ff2d94a4c8e1f93f7330e767cf2152ba5a89090d39184e733cbfa974b07cd18883215aacfcf842cfbb5e5aa0010773764f977ed63372badc7044008d37982b3ef54ac67eb268042038880034dc600e2159db3b9d6d308590ae63cd5778888d0da6e8f92e64e450973ab20673677a645df7951021a32a3016048469a8a133c9714e1accd2518c4be1e1683049ce51a5b80e21fcd934ce8077a78bf4c0ce000d331842b078611117f6b7530673857c21f2ee64309b4afe927d9bc6184cebb16e5d5291e85fd11083d1276e072523a9f4ea3098e37ff865218f587a1c0cc68ea3ffc95b4a72e07d21fd0927f62929a2af6c010d2ff0a1911e773ad6f1edba5034b860be9c91e33857fc061610d0d842d9302d182c687c1caae38f46164a40030b4697b413ed627ebc3740e30ae6305a62a75b974916066858c1a86997626c5648b788512e40a30ac6bb4e8b6a392e34a84036684cc1102f44a28570412d461b36ca185f74a1802229d09082395cf52a7dce294b4e2a126844c1e4397a1cf8ee0405432aeb60d371789074a5f104ad67fde32e498b26818613cca95542b35752d424e908349a60dc3e999cf3b11b48c78e1cd06042d15882612556ba7924ad1eab7980aa03d05082d1b4fc32deb22ffc9f04537e6cb9e3b63c120c66d7922d44e8f6ef4730b484fb4072945348791bc154db29d5a3cf6ae1d245304998ed8ac729444b61221882b65bfb68bf9db84330975e7b66c867ebd80ac19c1d59a4f847b75e5f100cdd3329dcdd6472f001c15027e6f35174779eee07466b8b290fd337ce2c3e308c694cabb444fb20a50726f3a9aedfb2ef8a1b0fccf9ed29bae6faef5c3b30ed584a218711bda0950e8cdf925a72f4224948e5c0d4712a8bd1390ecc91a5bcb9e814bedb1b98830af9b1ce5c667b363074796a8ae9678f2b3530e4f02ffbe7f0175fa28131e53cb5cba9799c836660baeb4ac1e37842ca7164600a713d08b29155c53c68c4c01cef7c87912aa57e4f6160d0fecdbb8e6bcea3ed05a6378fda236277a45bd17081c9c3d653081f9f6e465574822f1ecc6885a9fd5362a36b3ebc42000617632c17fe6050ed0c56983ef98d4dc831b792640766acc2e416b4ee7390722cf22955187db5e31349a23bf901a38b0f88910a730edbe1ab5bba8e5ebc81f4817f300ec2c2c00c54982ee7afd2f372a730c9e58ddf3c914c61e8cafd61b66a844f9695c2e0111f4c924d5acb9f1a1670400d1b362a0a3348714dce7b48c7963c0a18fb0aa8b1458d4741171558099c61c6280cf239a59af3f1c456c6180118638c20020698210a73b8d7daebb03b5fbc4361fe3689d853ddf1d84bc00c509822e535543c48bacb0498f109b36a840e3c44ac572c9e3064a7dc7d9dd7c2544e270ce9cb54364b2478983961cef7f954ceb7d3c6b70943ad9a7c1cb4abc3a368c290f2a4d3babff49c639930b869ace4788f565c4c983cf22385766a39b30e0ad4d8a2c631811a1270400d2fc000411761fc175f7471543209332e614edd1e79e430d1c14b2c6196c97176d82557c2a46221968654a5850e250cd9425ce728052761b0eaf8230f4a26490ede40d201cc9084399aebfd8e933b87ff185dd07bb10025c38c48984ba693e4ae45f6f220618e9158bd1ea13f48fe11c6ce4df7d03ef071df1d61920a39fabb7ca61e0737c2e441cb6bbb64f67fc808e3e9eb071e85787cb9b3c28c4590443becc8425877686086220cf571855a0bddf14c1fd8312c11c69ebd60dbf157036a6c51831051cc7e5d310f3f8419c2b00f3bf8c8e1e328070bc1bd5d16eda8a42a8438caf51f5e9e1cf43d88737eb8756709628b36ebd032c7e32804c682e0a019813004f30f22a5741018fb802307cc00842157ee84ec39fe07837d4e89aa64d5b1e60763e4eff9c0b4d205c9cee883395b7e10f29ccb07b4fd721cc495d841760f86b49d3faad0e3b1f77a302749394dfcdc758c8bff22045479c0c286741cf5c58f276178002921b0012e2e30030f465389a615276fe87c3790fc0b10fc180b28807be1c582a002549871079357f768e5cb6e2011a51dcc15eb42b01c9f62de7fc28c3a18af42b80b1fa4b8161e3a98a3911413dc542ffe3207434c468a511d2b7230ad9ca7c75192e360bc0a13729ee7f83f7de060fc5c3fd12fe7cae7fa0d86fcc8573b6e428630c30d86383977c763151366b4c17cdd9223b31cf7925536186524bb4fe8e4eef1c3f82385196b30557dfa4fb58f472ba806a347aab38f9adb1129a52461461acc51a6d4dd65dea7f2d1608a965b0f165a6eaa9dc134b7163a4c4ffe51906cd82033cc608ef4b224e7d8a88b758131d60b04d8b0f1c58f31c67a718c6694c150f3eb1a95174b82b72e4010822f4ee0450824f08f802c04cc208321cbe3eec45fa63f06737eac9ce3245529f188c158aa26f791ec479ffe3018dbd67772f23418ccd6d1f653effd0543ea4bf1d2a7ff5039da0b064dcf3eb327a127ca5d3067fee7641d9a9d43980b865c39eaaecae6e191dd82417afeb3c6a35a305ceca81c771492efd62c1874f226e49c735830e7db7c8f2cc46ecfa15730a4ee5c0e5d54653dd40a86c873ba16caac429e5530458eb8fd4147a5f83815cc390e93dc762da246390543e5ccbcb60b8937a5608c903cab758982a9262287faa79c530605938b7bdc9de3c7bf049f609a8e573376a1134cf62ab3ff715744844d30c67aee9665cb91ef6382495e2676e7724b30e514aa563eb0b5cb5182f93b2de77039a4833109863a2fed50e9273e0a124c1269ce734276047320de2147bb2b131e2398535abc0e6ee616d5f605d4b080036a901a6614c19c9176a7a9b3155f11c11c3cced478b41f5c4a433065cb21e6a352857a2d0453b879fbed8cfdd0632e98110473fead6be40ab1b1901940c854c3a2a85448e5fe9c3ebdbd9a6504337e60ae73bd8e1f39a5fb1670800d1b337c60f61419fdf1c78c1ec898c103b3e565e458965a4c120231be0841135d290436c0050366ecc058f16bee36661d18472cf7e538b2dcc9590e0cd2718894f1ea916c8718360307e6baf9b7cea2f563aadec01ca57c858f3f56ae739860860d4cb94ebef6f2c757770dcc91bc7e3097c811622ec10c1a98afceb2e3a367600efe9e67c9b7e36371860c0c6ba713ab53fc5f5466c4c08d971fcb2a39c87b931a164800024ef00d98010393cfa7bd27950ab7b9175d64e08b192f304d9a3c5b9df258749be102534456742cd120b0012e5e462b8e1501753024cfb1c4879063217d7430b56fe57c1cb710ffccc17413c42207b3658a79103f8e3898375e27d8671f0e26151bf148ec7394b96f30c72f9bd1d21f4cd5ea06830519cbd408661faa3618772af56cccc50653e674d4921b9375c73598e5be26bff5538351f3a452eaed25d9320da69cd0c14f3cb173ffd060cad2f3d71bef35899cc1241f22a7f452663046278bd0089e1e3f2d833998cf16eb269364b2643045bcebb7b4a9165d1d83c13bfa94f09fe3bc290643fc8f50163fecc7bf309843b4742da7ae7335c160fad8642c725c295cc55f307eec9f1376ffdb342f186f2eb2eefb7a77f876c12cf2c93482b4fb7f447bb0a0d739fd6dc19c93e3a8c3a3a905530723f1c542c741763d0ba64e7121a84c1e0bc6aa2ab9a097bd8239fcb06392ec5630e7a87e5bfa91881f5f0543968e64b55be83c512a98034f1e67c7106f4bed140cbe9a1e8570f5cee8a560ce69d52c5eceed241f51307e79d4081a1f9f561f002898224bcf77a41d75d4ff04738ed292643f79492f4e30f84ffcdd7a7fb0916d826924bbc7a6b66b1979261824c5cd95ec5cb9944b30b77d7b8a1182fd875409c69a2c1245eda3a81693603a9b0f29497f3be810128c1223848931fd361a1fc16c152ddc4aca52026004937c787bd1938de420a7940014c1f4e755a175df4b265f841000229852b09cee6ec2c57a6508e6b80f3ffeac0ac11c77fc122126787a1c04534af3955fd53dd33e8060881fe2dcc7f9c93a487e60f4382ba7ddb35bf02825003e305d689f9891e308400fcc3ea14666a4c20343ee75103facff0901d881c1d6c3eb7dfae03c787560fab0233ad7f9633c9703b3e58fa17639c38121d64c749cf1f3207b035392df9e90c37dee686d600e69b23ada8646bc930901a88139f2e58f2d8807ddea03400353ccd4deb6a967608a8d946dad8fc5eb9581c957caffa388ded15125042006e69cd284761c84597d350a018081d1b6d73dc4f092e8fc05e618fbec732697722803e002a397ac758e1b65179113b46885f92c7bfef19c32397b56985c442784c0a0c52abea49792538731e1a30a3fce8a30b1efe6c3938a267e1cc748a697914705efd7f1a51099b4e99e020f92a6b073daaa1ce937b1ab14e710995deff1b091828f627cb64a4a368da20e3ef06822a78f28b8b1bd4bdbea930b0f7cd1c509fca052a1307a24b12335afa97c162b5a80c2b0366fe3db63c1430f085a7cc218f629dfca56c57ada80307e8c05100fb4f084715eb2e7529b8a9e3b61c871162b446c4d4b1d4e183466525dcc7b13e648277adb2d6bc22c96dc728a4755073513e6a0a24f9224398f33c58439c78fd3716b3dd9a59730cca77ca21f3e5e5fb4847127c865ffb29cb388953048ae746856fcfffb2861d4caf629aa9c84213aaaad07e98354d249c2349d1e7bdf63e7da23610e911c84d4f513333648987d7c46dc27a510fd23cca9d2d2e4fc1a51db11861c8711f9faab11a648de9e57aa6284a9bf3c5d45891ca4a74598537d7bf864531f5b11e61016b6dfb1a7dcedc844987fefc24ee4c882e6af05220ea7fe5397a2450e6197a99468e408969644d5a394424cac5c410b439873e94ee8a7458f258a000a1410685108d365cfeec1ff47ff7c3126684108936c7cdec91e663a920761d88df68d0ef6a25bec811682305f94f0f1915e9a873610e614ff8a97750784d9528e381da49e96f4f107c37d8af46fb93e8cddfd60a8f3e09278641deb651fcce6d9653e8a361f0cb9cb737967fbb2adecc1acff39769d547a3007794524f68510829f07b3c57ffa055ae0c16ca1b2654f9b96c643b4a0c51dcc3924e75817a3d70349075ad8c11c7df6b02664bdfa2d0c8216753095abd907f9b773b0590b3a18ba353bb8f43a767f72f109b061c3860d31ba085accc1e8dae975d66ee2455b4a0b391825e7085fa1a2e8557c030f52086c800b016811873cfaeef02b74e060ba50fde1fa6287f9df607a8f25da9e2f97c5e306a3e428224af4b4972ca70da6f538ff61a54abb1e870da6b42216b4625205f5d760fa1c4b16491f79fc385783495de643bf4acf4c9c067344558fa31c3fe5602f1a8c17fcd3728765e97f3d83492b5cbfd8cae59c543398eac3f29d859c36222c8359e7fb830fceca2e3c321872defd9b74bd464e1983d1cc23f1d891bea4b988214d51f574e795309872b47a3b42e4981f309852b382873b395f785f3047b2f7b1a945bc60b0249d3beebaba60c822293237d2852016174c9fa2e71ce94a5b30871d3dc78ddf4facb560ee9afd881fdc8b85b3608e3f3a8757791d72120bc6cfa1732348520fa32367a0c5154c15d2acbae50ff99f6305f355db87560749525a55305ac87af309be971ec70d24d5820a26c91e675e398eb52f9f8271d2c34fed714cca5b33400b2918db2ce7b230dbfd9c3e8116513046deb849c89fecc8a105144c59cc76e23d22b5659f60d0ad149276e8b2b838c1ac1ef5a96adddc363286164d305cc5bdb1d81d26986c65fae52453655f82e1e338f6fb599f8b1f7de4f51d55882d27c1a8a3a963c972a81e8804635bde4d0fb79489e9110ce1dc83f1c0f5fe7423183f165f2fb3e93884b208a68b27f2977d74ac430473e4b67276e7d146bc2198f5672bcdec84735d08a5c966294130a4fc502c471f08e6d5fc543662fdc0f4b322c952e6e44fe503934a7e4ba53d305ff20af9e5912b3c3c3045b8524fe9b37628a11d18bfb46226ab5bae551d983cac4811d39e723673606c13f5a0f56a9fc283055ae0c0943de4f85285d75b8db4b881d16522c807e115fdc70dc3d8b0b161bc185ad8c0fce15a23be45c929f562c3c611022d6a60e83055728494834dd0550b1a9872c797fa3fc79981e12ffd8594153bfcea65600e5fe2b785a7b5888139f0aaf6936c95dd560b1898aeafe338e6a7ecb7568b1718a2551eb1c9709d1cd5c205e6e84bae83f1bdedb4b6c2a43df18285ef67f5485698a36b0bbff27015e62e49d69fbe83aa045561b0ef97f91c4972cb49853947162a748c75906e5498b2ca07fbdbdd298c5216e2dcef875bc899c2503593dff196ff54570a7398aae768c4420ad3a507163f0ef633bb320af3587c5aca9ea25d554461bcad89a4b15296650b8539dacd55470f1feb1250183b2ad2b772a2590af904ea71ebe50953caa5881aefa86077c2a4e7d107f325151173c2386f951e153e5de5260c17ff41365c4aca221a9a30bd698ca554d2e651bc0b1a99d03de63ac5b2d0bb9fc2021a9830457b07fe51dc9bf8d60361ac05467009536e93fcd9372a479258c2bcf7a9fef7038f16f94a183dacfa751479e539a7c41de7d3db6de64918a48324661eb9f7579584b9836439f2f220e59f8b84b1e3d4269235ca7c8784a1b3cd7bbeeb38c8323dc214619d2c27f5bf8f2247184a3f9ed2f228e79bd908430e3c4bf228ce6449ac6930c21c87b2e90289c2a8e40de622c2481c0e0483016120140692f21e00631408001028248a8502b1501eecfb0e1480024d3420382a2a1e201c1410121612201204036130281c068401615020100a8301e240213c24a61f00a0a802051478ed45701f900e6441017b2721d4691095267b774b032fe43e099f3581622ea3fa1edce1650045ae503aa6872b940e0583a20205145e4671623a18c85b282a940b2ad7c19554030a1a0ad12894d40045a1a2c2f217d1d04482ea3be6843c54281a8c027a5241a30a3f0a7869e4e80b3c146df537625d925aa06450b7507941519e59427efccd70ace011cf1a868242d5433da0a450a55030541feade50c059b0f5211d6110933c6cc20bf79a14af66752adba084a3ee9da60197c52925a923d4234601ff6b48724374a166c99cc158ca226ebfdd906e6a7a1e91d4878a49fa852d29cb85a7741eb31b082fca776e87bc7aafc4cf37dcf86edee969904cc96e75d3b38d21c2d542d8252f5e9dc3ee1a25e111b9fcd386bce6f465a30f29a90e2f812da05b8cdc4292630a19eacba3d3e8b85a528930ed4746000dcbe1d42b0af23c2c749c0412aabb1116bad4c80c8d6e81ec563e0760c2dcad3f7d05a2c983efa11c8479bbde18280a3fbfaab38124e74a8743a8c25dd9866c0d2ad143df808e930641a6591c1e57587d0e8824a40f2867c3009a3c393ef1bc243cb4ef5021ad86b4fccc2d36274cf3ce3490703290eaf51f4d230d7b4680974f75eaca175f42a9f16931514c5cc63c255bca928cd97f608f81871149c25e9a4ed75faafec70ffd97ae087003614c0cf7265eae903a5ca36f39c2b9300d0a82a01b780427dd129c9da0de0529431046d92b4e850f6a421f8928144a8c2ea1ed28250a10a7390708ca42aa8a33c557ff94167d653154c647c6d55207f50490e34651e7a6cdaa0cea537eb7fc814c276bd3a5659fec951605f2a7e6aa8a9ff2573e6cf9f6ea74f30b6ef880d451cc2644c3f28a0877b4ce997a28893172e5b0e00ed088dba1f90ddc1ba5f614484451a64a9b78a497d39a453f90f5c65bdafebcf5e91c9f8f794b1b14514095056b83d0b4a64fc26de4e660c46699b8f18850f59ead36fd76da40e422103dc16eb03c8e8c15ad83f4c155b8462ea5d50c358c896a299baa8d13e6ca173370db5a2c905e194442543b8da4cca98d84f8a54090e7e432a509ceec02b927052c9ea09c3c6ec70bcddea9b93f4621b5e51c1995a4effcf451a74f584b1f8f96c205d973c2b2b9daa0b43e4c14d3bfb37ae623516c5e695709a9aefe7b1ecbfbe4aa533547cdd0c62882e647cfd03294210a4571a133941c3d53d4d320b61ab553d857134365e8ee9608d2442b6af86e4918eae64b4f002f085c3453c1ac835badab0ca05f2b0a582aaf8dde3dd8cfb2316874a40b66908063d6335a073cd91e363864133870f564bdbddd1adb6804142026559867b11839960ce79503a437b24620c68ef52fbf862501ca93aae7bc98248e75c44394d3249855beffc0f1228d86ee6b419c7e2505cc2ca904aa4eec9348cbd8311168ec3e93216a366b457c1a9e9dc96a3a67bd340267081a3b59aa1a0140eecf166a4130d13182e60493bd9e5630d46a400fc6c732446faf62edde9daaf61e439e9da311f4025709304d1c553cdc8f5d6f1095f39255a881df416de4c1084f157630b8b37a274c034a147cfa4238202a8277c103a7b89f56187c211567af8dd1f00c8cd595607d0d427da8c56702f242c9d86196d183d53d4c1b2a8dfa322fe57db9d3de0a9839818f71f95ff88ad537affa7e6bb455b2bca357e13e584301a74afab96938661ae3e05af0569c3ff918285d0705c46b564db3e5ef1dd876d174d0afaf67180ffef5acd5b024f4313d23bb82205246a6d69c13c37ab3c65feb82443bc42d2f02e12dd30a8e2f88d0f26cedc9b9ee9c7ba4f351bff47397ccb08d168dee41cd1ae35e105a8e2895f2c9afac4c58a435f18f7210133d9f0c319918a210e9177c16da1a4686d28732a05a513caf564ea64a29d60ce129290dc042cb60560439d276fc6ca8543c6e54a7c0285813bc2234ff2ea50cf0ed01e8fec5e52e886122edd67bdb2a29a8055111251332d3cf94cdc95fe65dee4e8d2fe27a759f6da8fffc46eac22bfb2e4c7139fda9c3241713b209bde01df2e3cfb154828b1e29e9fa001349e1e2184bf91d4cdb3119d9d87131ce34928902e5a24cc230ec449deec854b9d2660653a3ad213d187db68f9e50867c815bb0eda6aec3822e5a84cb0b2ba09a98cdc379cb7827a3dc03804c60440075e5d11af56b4f893a313262a99c101d813df199b4881ce3c5896a262f51db9a1641afffc22f0708926437fb72a20d98546e29094a89ebbc4b92e9dfab39902efbc502a54c2692e1f0adfed492a08cb65e7c37d1c44db04acc85a81b99c09ad1b4c571f14a7c873c7b754e5da9b5031cc8cbddd7c76959adeb8edc6dcdfc1914807ec68d59d301eb7678b6d5283bfda099de3be2198eba376dc4913700404a0de23b8993b7b2622038c2e26a1a9131397aed2afd900a45a7d49c4883c545ef5e8de9f50719f3fedbe85e85bd7f5b5510828faa65eb0452187bc85aa6d3fd958162521dd0c6af23b467aa82812f65d12dfb8295c4f7cc71605d5fc81025eb80581f61bd65453137820ba960c50d22cbc677e888ea1202305e737440af8c292fdc2a96e234ceba4c267a35dc73374e8d34d22240df4bd24b6e58e2101b987f7aa5b72cb282e4c74ebf2ae11d71ba900c3bd5fcd0f2537682f7860ab848f84986703b012f0dac92166d2c52e53ea54f71706f53f0e504664835739fe814103b8a786f83d7545017d749ca438ff495d6a81c959442d37605aa0b34a232ff3681021277b9d9de507b509fa8a330162d04b939b1dc7824fa747d9bf22bea8390f8534dc4ef1940fc76f4f1aaffbecfb507c894b9bdb82793bc3f8ec7b3a9a809097e61d37d7d5e198ff66ee0e4e5ac311bb920a3b49d4637c350f4d65a9136f33c6e289812189841463f1784bf4bb193c943c675b39a25fa9b5ca1831e4370b66e03c3f91614619a17c2b0e5f572e2870384050053ee5dd0e81e45940519c87215e395d7dd202655c11f1470425fd459ecf153dfa5e9baee2e1bbd92636f12d8f39365166c0e264972835001246e910da2f5a31d51aec9815b0ddec8a8a0a6c046f8dbf64fb970f120043f19ec4f9b71b42a7c968d75757bbd49641f3f4036dae2705bf47cb507c4504c286a14ac14b3579812444b24548af7fc5c815466bb4b269ac7aefe674207b1e3f22ec76bc29c8c1426f8d6bbd1a3e4a2b70fa53614f4d05cc3a9e3921e0d27dcee8a2ec0b2bf342711ae602a49a15ad51bf3e484b0cd010ad781fe5028bebf36392ab6394c5d862e5f17bb5d5ed085bdb329427fb5ca53d34ca4db46d82d594557e47dabb47e912499c90f5d0d41e6b37e25e57d90d7ec6782bb9acbc53e70a98d20a50fe155ff69188c62a48164551565fc5db219bfd035dc2c0e8cafc1f834e3a0ea430e39d47375608432ed263652a0cc512ad5b8b1537950de920487ca86550205490ff35c627229ce265ef02f28c1fad424cc542bd8a521decc502b536dc5164d2ea0fe3c66f4d7806fab86a0c31a2c3139bd3a34f0dc24186b47d165f38137ab2d84cb5f5ef9c222d53a072a0140b620c9993219b4e11e28408ceac594694e2067b0294f62d05e4b340b64300e659cf7e4d7d2f74d1004625744caae2b3891b39db0d366fc42bfc0d836c8dbb187f019ab01c6a48881df0c2ec780e08a3a5ceabbaffec53dd7460ea67fd44a1963022412dca7dcb9a4065e6d94203312f1ebd9966e729d974b366aa47893dce0827711ce18e1552070680a88a51829f56c0a731731d2b070d087beb0d6d61b575d822890b4a1a8a552618304dcfe32f42b04d6a24e1d1c27e9662056883c045693feb417eafdc1f3fe8340f17ce1b19d8f9c2824cd09eca08855352fedd97439af9f8be19c5d70b9b901626712bddf585e4ee8ee13e45e8b8248061810613de25d1d92aa3105ae8689fd286b7c89c67e89ae856106ec202af66cf53bcc469aa9fa7d97229a5f78c7a3f3dcbd52ef64fc2d78c4b36d92a7ccf1b60b72d4fdf02ecf8a37e06564b57fd33f553a7c94754a24a9422690a2e23d36171eac9207f598bfbf09ca3f9f12fe6b22bc46685bf00080b40ca9a7df012778b4da6bbf4059cdf55692159340b9ec800b6d41cfd80929ac576fb0eb65d2f827b9da83e45ffd08372dba850a288cb02c720593134f637a6b586e54750127315011fa00cffe0990b3623510c3bdf1efe8c6adf0c75481beda062ea817108835491dd39500a311b371aa97d833a928188ada652c2e59f0fa422d08e31e23e448a3c39af58e10a4c84da044164869b74314198df8cda0969b7ecc8a0f978add217b49126fe471bc0d1962ed314f4712b0451e8af4444531c2ebd07001c87305bd2319433089884a1ca399f44c7e1d9bb8b7f4ec2ebf0cbe8cb2941486100608afefad074db99a0ee19aeeb14fbdd030e94ada5d6ebcb3779144549526df204e68591bef793e34808aad896451f0d2ba36564bbb03d6be918147be1251e2f9a825b0d8d0eed27a19a56e6897ba1ddf46919e2df119189ea85479b25221f1018a5e0aab722281c06b734d785c2275b161bff33a6c80f48f3e377343287be0285e0515eda64926624a9585a158ce376ca751c211f0f3add859aa45503daaac675094b8c0dc8debda7599f1aca173059003bc27c3f19577a3b80da7a90aeeaa88d70983c5ef726085da908ac899a8f384d85b5f2679c529828aff2022d472aa625a7459ca1dd6ccad1dd8d1d0af783582e0faefaa45c89ab65ac43393757b453f72ce8c4a2dc622e518bb74d11854191e87167dd8fcdf517ae0390bdfd3fe69f8bc0aba0981caef535b317b182a1e4aa0974aab7ef6963114c55a81b4b042d2fd9aa3d05fac3ae9a2957e56724dabd8f4406e9d4529b2d8a87ae821d68a6ffbd6d53348d27d0d85b750a09e80f5225e0e9680b606e266714298f8920066b5e074d844cbaf9346944b3bc55f5106443ba20652b7260b4626f839554d90d4fc8dc320f4cb30d493aa2d69a9485afdf61518615fb67c7005a9426066a411a98a54198d18617a1c5844be272a26683b5486437803d0773ddbbe6966428701d30a665aa8c812fdf3512f4878bc0f1cca2c72f58e79d05893fd3930a4f6e4c9341f3207227e4261a237d7aaf63574b2442353715174257e3a3b17111debf576ad2a1f57a20290e6fe565626bbd66547b088e6f0062cf0aec293837f14e93885ab0708cccfc6c3047d2fdc82b3f8469350b8b515be93538a2b99df6bf40837366ca315e88815a34a8c3188072238bee5b9a99c26fd868c5cf4c56f3e2cc834f34aca7e6bab8ed7b42037fc3810a98fa2758ba8efd0805aebcd2461ccd186c3bdd4098a2b6e8b81b32725dadd5b431f03bb46755637d6b924ae1a8e03a223bbce04daaa0a1a554382da48f5306ffad94381294ea617b1f631c4752f14de0e511a410c846c821d63333fc59c74f778e1e45f779d81efa4168aae93720c71bac0ea8acc4db5a7731632c3cbb0613be44732d50d46caa4b64b3b8f85c3c35c886d53d74c03d385938fa27e3bb5784a446cae7ce602e19d0c81a7bbec4ea69b3b85ca20406861d244626d25b45d5a263244031628b15f9c45c9b1818403ed1d286da8fe1c476628bdbb1cd5dd439e7445b52353013f29d006a162b9ca453101752701fe8631e4957ffa48fdcbe82627d19adb7735dab0d139149ac6c8b1debdf2439d89d2fedb9139e8f9e23c4ef72b61ee64146833a494821e0bee27971fce313919629fd3b6b39a71a04a598503a1212afca6499d410b57a9b276b093c1efdbf32d9f807d2cb504e0d4abc63c4d93ecfadac7d205041d38a47c2200a46351b0774fae9ad4e04a64c029e2e8740e2d2d87b0c79b7e44fea5b567ba5576ff1b3dcea6e6524055bb4224397297fcc944f857cf24c0fd8bd1e0e100be3c96262d1387a23e55817eddad5f361e2a50b07b0eb5981d39baccb0bb9c8aed01c8751dba31ba4caefb9a240a3ccd6e17c24b673795f7f86e4278ebfd215b67a4138b828d23baf0659ceb62937d138901a8806c4e7865bc9e6c00f2902772628a92c1233d66a086609619791fd9ec78bca4539e0d8705e2eb3bc9a12afa75d4542a888a9588aec511753dd81140fa4a286383a06bfec22572ae0593292b42595f75f0c187c4e760dda8ea01b3f9c77c9da87383997cce57ea9cda6076499b5c0d53a4101843589f4df36e0b4ddc9ba3ad7f61ce4f4385a6c9dcadef1341804a0d45688d3eab6f0684dc405ef95fa6032d0ec521037ef818a97feb939f0fb120ce8128031c0bd7be0598767da5084e2849bf7a89ab6b470c9454df8cba8c03290a0bb7d50e0c49133edf25d3285f409bc949f5ac10d0629bc4f289fb2a7cba783fa754a2e937e643497782493ba046c2a4d8e58628bd44f61a94b5b1597fef8f4939c82d22161efbbeef2bf55991717b28d47a7902a12f46a082c690fced71a3eba5e619cce2f33860ccbb99669c01e5c8e924bac92837b7863c26a1fa911b34f2434c57f9d3364a4a6f8d838d92e2882cd2a61aec45bd25ef35c7d3921e036aa3d5570bf6fb0967500630837933e2abba54aec0c7c2485d76da4c2dd56ac8cc4fd2058db7f04971dec421eb5f421634cd830b422f81c90485144970e10cb7f0acfd9b976b0b21dcda246f5e08ac04df4adaf1aa38706a23e51e27392f1a68cd1763a3a5e2bca6971c2f8c192fb2a92969e8b900afeaf72681bf2d8bac41564b5d27b0c43bcf1cdeae6ceb340d88d67547ead9a5f9b74e5c1b7bf4e4e97ee2e1e884c1a30166b06c70b40c669c87a1c58f818a069b2bb7b59edec4f92083f5566102d894f9b566a99b61423e81615f7992322545b39cea67b0f15224174b6fd8c33113cc5d228b963e696fb62f5f0328f0e866f5e0331d88a9e4a72edbc867b46d7204bafd1641c2cada79be8c010ace0f44025c88def895581b052a7541002bb59bd4fc236c43f1c44f2d81fdc2ca1f2551330d8bb8f1c18d550c85582f7b687786ae6e2c9db93dd4040d0367f49a2ef016a381277af59b16483bc66d5f5393ba77b7a421d5ce10e1de008d44f6db81d2f42f8db2246d8c95451f73fc06b7fb6b8a4b92e4d4a21bda5b1195c7456000c9b0a9e2b1d3a048a8e1560a6dab091f99b521a2069023f0e241e4682064bda991bb0f77ed5f99d319504848d77ba2310aa691861ec106f11c858827639581f410475351e04f7081b800610aa29286b5a1b8506a2a5def0c776af28303c3b580af4b41d846bac9a2d3c540af9be660d208f9834ff4b1ac595f1097fb41e01f939fb7360e962da041330c92b8c32b2eae280784dd6af3f1bcc0693bc8192f15f7fe6ca05ec8973a4f6965ef9fb34b5db85c142c54e409bff0875ae03e7086ea8415753d1229d4cbbf716c40121bb033467df40a8b9e6aa1df784429164e485570241725bd8f85a74ea8af9304ac66cfa0a21749b1a2c3e0c458f54d7323ab6583743e8c62653172296cea19b751a9433ec87c1bd2fe51f2446831aaadc018b78b488d185bd8f4c9a57ff18cfb8a129573384b137f004e7945210d5e620b63fb453493913f597bb3df135287e9914fc287acecfd1f32bd62dcf701d0d4ef52714690680601d6c70232ffe623b4541aed4e8ff2d0b8314f4510bc932c975283c41f55f2d3828797dccf46c4cd85f4549f96c431baac3cbbc3a14efff159f6f703fe2c0e0e1eb918dc60ace3d52147f2b0c181e3d799b2b7bdb0a84c1a1669e5b7ef5b19a898d60302b50225e2a0849068d881bd785263a82b143bd40d85823a860a406187e241e1a09647414adda15a50d050042870a80f8a07b511aa0b8505058de262e28ca24bb540cda1cc50a1501e540fd406547e10752f06fe3c018a1f8a87aa4d40c571bebff180ca87b2404540e9507508ea9e89a570f5425d43bda09e43015f85fa1289c1dbbe0995935f7876273e762e4a47162fa6e75012a86d0805fcfafcd9fc14fd647972818a420950c150e741e9f8406d85ea2b2a21ae4de805288fa2f0525918941d39140d2a6651c052e3e3f71fa3144d4f8d0c09285ba8c728cace06ea01158342855a41996850a80ae700ab0f14695130a90ed41ea82c14050a1a0a5da06893f31a52195350297ca8099429a0fad8889ac529d94a3d2daed9a2e6521d2838c51d2aaf1a51c47214094de9686c795537d4114a200aa5230f699f8162871201d57700156f44f51fbef0fa0ef583c281ca855a150591da878a43b162104546a875216a2cd3ec21f48552825a439da00ca788222e94b5eb855c45fffe3982a67b6d13d6b60c63fcaac30c850a35427181da42e54a517d20ff4f61046a3aa168cf91b74f3c94078a06ea0b956628607bf7d7e00475cf032a07750df51beaf126eefe71b68444861f3a1f2a5dc7ef09ea01f586b28c5140487d37395040844683ba9622318010b4d79266e1475d9c48c825f8778940778aff5ab05fda1f6f9ac49961586cffe91d9697750941d1a9976d649e472f678f4b84957a9b82896d57e108f05343d0aa93072e0238fd264f65e46ae9418a6208af86cb2a2fd91d6454595e46b79505628b2899a36d2921a95eff60d85bbf102842fe34b34b1ce0928929b4ad7693299452f96537e327ae99ced74d378c09409acd35dc8e40f4bf04ba0aeea0ef707de8696be9a1b2747723f68c4e2fa95562ab932a0af82abf9ada5acd14508b52586524820fd858a9d58e77e2ceaa66bc02d7855f975ea138f33a50b59a7d9a0086502a589e6ce9313d98186c91ba4c013e0e9743de1278e9af606193ddc304b249769e81a4edca0668c939ee174e408c46e01f7b97f7f3861eb9b7ef96fdb332d7ac571adedf6569877a0b3feaab99ee6159d0d7bf205010ff8f601c0f4bbc2bf4c9d33941e15b9018b87f2aa897e633fe9a213e64a5672b3c96897f77fd7502113b27bc5e99633096c3b3bfc99faf7f026cfb96db0b70f91d62fe143d07d91fc552fa8365f301ff457af10c97ee7bd82ac23a17dacfb82ecc890ae0d3c78de83242e1c8ca5e53d69ef5427f8730acf22884d89fcfc150eb222c91d57bf934f279a765982ae158383aaf6aefcc3f9f1ce317747d881dc0336d9933ce6b987c0ab038a1895a5cc17d1930d47bf33ee9f2596c90f6c1bfdeaca7382cd93408bfe59436bb43fe2954b6004e255869b6e816edf594a94418ba2012b9425f60e8de90de2ff85c8bb3c7a05403f38b7e13d33649b0583a600818a822959c03232e4b5294c7cb76d4af4757b2814260cf5428f2a02b69dbeb02c7612dc175de7e193e761392bad70640d7263081c0efb9690de0cddcfdb678ac3cbd3f1eb59aaa29f1f14bf7c6ecf72ca749b57710aab8a2cb018f938d42811a5b632d7ef2ec59a5ed1617ec10754d0e75137694a7257717225ba586172c3e095e16e8779f01b6185de9efa075c54e390a0f62960882d1c317ad79a417172e2ba4123624e8a01c123aa9a1017c512509ccaad07031e3a9ed30e613ae36b836e4ada1f02d20d660796b365765b2e88c54d71c0b5a4e1372ad8723bd0a01053fe08e0f15fa6eb1b5c4cdd3018b196f8343e0d0eefe83e69f9b5b7af3b0db79cf4c39c545e2993b09ad506b2ff017e479a4b0b800780b38eb29147c65415caafd551509ad9cba0b8b8dfbe993baec586e8fb88c675e7ef8ec3bd0c4846a12887ef514734e29ba4a447cc4222567405c11908c2debc2bc2fb2a7ca6e33afe27111b3f31533d2a4d22a44e341edadc2073e1aa8ca1393da21127e803c04ba6e8339d6790ad1f857c8d0e9f8853f0e07c5ced64a2ce24082fd590475ec5fe1113f50286effd2da87f8454221e0f5a48d108a3861011e1155662ab3a172db82b7508958e7f2637d585028122cc590805074983b3221b8f6d4faf0bff275bbd7ae69f10cc615a382ce4b26bdc971a8c1ecd3e1335466022e24c4930a3760b26639ff000000000000000000d06c9488b54853324929e74650a18cfddc94924c29a5249c99f8e8e9cc046edb76c3ccc4a7339b51021e0a9c0adb0abc491273a5c4599a8782ec7a0b25e4538d2ef1a02955a5ba436133c4b25fcf9133b743b9423ef2fbadda895787a25ba607cf155284d6e8504a8f49ced65ba803c61ccad9f39384fc18b4f32f87525d6bc8d4d1c313e8408d13c08843f9740cb1c447bc7028b6e8da1233b53ffe9100c61b8ae739ff66caf451a27c6e301a5dc06883d1604341e9a8d0b96f65747c1bfb30d6500c21f8b58defd884b30d0c35145544a791596334f59886428a332dc9a36faa1d0c3494f2b344584999b97e232a80718642dee426f3f5c6b47dc2304331db8eba3491733c19170a3886518672273d39fba48e5c298e1ca9c68e2e6e7491fc23b0021678041a990cb62489c1226f0cc6180ae7e29666621743b174b6e887904fe792c350129a49f689f8a6f980a1ece9e6cd3f09612afe2f9425ccdbaf0619da23c80ba5fcd84d42881c74ca9c2e14247fbe2a353a17cadd1a9e435abb85f2c76d2ded202e7ea1164abf77afbee1e7ed3f0dc0c842314b58b9744f62a1a8293d29bff598d3d95728e6f8d1ad348f39e76e021da84101185628bc84d3389f92644e3a1a34180530aa50021854401853c01b30a45038f1faa5b3986044a10330a0501a9120c3336693a37e85f1847382d180d104a40102184c288c6bf8b8bdcf373d2da1a823f2b2d36492b59312ca49eaa60d9753128a29b5aef3269935730909259f5cb2fe51fbc4f54728260d5a6df544c81e232314726dd58fb236b31815a1383332b94bee640941442868bc9ae43bf135956808a5d4c97145844c61ea238462a56789be9a0f42f9365789f8246c42ea00a19cecfa77d7c5cd42e607255fcf0d370f31ab323e288c14df9c6127a4f7de8342f020c2b7ffe46cd779609dd62c42fedf41a9c524c7ff12b353eba0b879fa3b2e9b54b39d83b2dce74dd73e91356c1c1464aaf5dc5523a24e7c83424eda4e7a8dac9e866d500839fee910bd6a936e0d0a5a795da27ccdd75a1a943d7cc757c924c7a404c60c8aa7348e97dc198bbcc290417947fe4c883cbfe1652c8a22eb33ea8d6d27392c8a41abf72919a1e3e12b8a193cc7f1cdb9a268a9a1275bdf732d6c4559edd647a499f469b62c58513cdf78a52da2f6732a8b5594c3ca685a87bc2a0a62477c44648d888f5251bed6b66c3979d24a0715e51d21ee3a975e86ff9ca2d4d61a5314934e1d8d8ff3d1952945c9e3d5d8b9c60dfa71525c25223984cff5288a41e60ffbd9179a272c8a92d8bcb9769b5a4c23a1287c9e95565d89c1741414a5cc109e630cdfabf7270a5184cc264b989e28f65ca7d9a4c24e946b3ebb42e7f6905e3340169c28bfa8750e49e80c42fc4d14d3eb9ec97a79122fd244e9bfccfe6a53f5842613a512d371125cdde36931519e30fa93b80c71dec34b94737a9c488ca5254a9a23da7ac694da3366518962087a99bcde4409a3a193301a92b8cc2212472321514eaa376386679efb100b593ca298b6db3ee5d3e578fc2c0b4764d1887248fa2298ced942bd04af64c188e2bc68dbb4ab7532f22c165110f115329c0ef197794594738238b9699963049d4494ec3b843a1b53350b441444547864b7534f7a14421687287d6449273d87a4b199e6200b439435688ac86b6a7d924e21cab18377fed54f759005214aea5936aa758cabf70da21c25688fc7f72046ed82288f0c9e25c22410650d1a83682611219a0244b963d0b0758f5a5dea3f144e49191d459766bfcf0f4591a2b5456f63ceee9390451f0a427d967caade93930fe52c1384d89b4827f3288b3d943dc63eaa8d8e2bd7b3d043a98307fd2efaaf93b6180859e4a1986c24e64ea9de9e4d286481878248faab45043d9f9fdca110447ca38b90ed6034f40259d4a1b0317d5cd2e64a99946a167428e9cc93f3742a29f7df350cb298431672289e9f6e24a5ff42458d4341b4f58a8eaaf41a1b0ec5151946e30635318bec0de548117cf2e79f112b7143594cc635486a8de5216d28c920444b9ceaf0e1366c287889df660917df215d43292408992e9243d298aba1647245c4ca8fa7bd4a692826fd9b4ca5cbb798090d052577cf74f966c99c9f6111db9567aa4e6628c8e9904abb04891a94ca50ce93433ecfa5a6e57c32943654ef45cc6b2bd98fa1a4f3a68d31490cd378c550eecc49734eb2c2507e332bf1a9bdcc2c038692aa2c15753257a808fa4241097d4fa64afea9ec78a1987126ecbf886ab4ad0b258fd5892145c60f12e442612e3342f2286a79ed16ca153ad9de7c63f24cb5500e2743e690fa4f7c8c67a190f425a9512e39d6565828c88f5a428b9079e34d5728f9c71c926edf0a85319d519f3b56a1987a4fc6f2f5a850de1ccd36a64f5dcb3e85e28eb8d221b7494d6d49a198394c6a7fb8d4955c140a2ab943de9b8dfcd843a1d41d42769131aafced4f288a8ed2784f7273388d138a3e41db738636cb7c35a1fc22eb3fc9d0082e6226149450f7e76e72732991251443c7d072dab2676b29a1e8263248ccd7501d2649284bd07b2b3d17124a6a456c9fbed09e343a4239e4e8cc976f9935248d50cc744ded4c42c79a5884f255c69cb729e1d1448850d8b8fdd17a3b6ae8d8108a163361b55b4fe46c8450b2f0d3d9eefe84cc6a10caf1c35344497f9ff603a1b0f157d63b3f4eecfca0a4e4697ad81c7b9ba00fca1d35b96ecc7927badc8362ae493a44a4c49884cc83527796d24f2e1e3bce3b2869d2d4a17e5a62d76b63ad0959e8a05c9e2b7b649c503a623928556b4869ddb1daa68483d25d767e2a1d33ce3c3728e44e13ebcf446c50daab2ed5a0aca936fd6ae66dd5840685e0263d5c89998bfc3328b5fd9c6c0b6916322868a7c9254f9f1aeb3a1685bcf623940c2153d6091625c9a2ce474e664892bca224629ed730954152085d51ce5ef3281bfa37bd6e45c1d77dde5d74d0764256944cee4747521df57d15a5082262c99890cc25a58ac2b5c58ef6f0c9e429a5a23c216f509935ab8eca5051da9c43aeff4504dbcc298a29a9f632f727333d99a2fc12a2f87c90b949464b51106152e7954613f519294a573b2354cd9724111b4541ffe81227be24865914059d4f3a97fcc99fa60a4531ac761c892a395ee74051cce6b249f5e9d131689f286ca90c6ba3264f943f8912d2931a5d0b55270a5f56da971193e614e244794fbc73799ef81b929b289f9a50ff97254d1484b838f119b2c9ce7726ca32d741c6d8204c94b347f334959db4a6ed12059db5a4c7109b51b4b244216d7c99a86d53328695286e575a097925343d468962ba99301117a947ef93286d673ee5a13f9228291ff5d7a6ba3d794c248af1736a92ce6422368144e1346e5d98adaf9dfe11e511ba234a6a4a475bc94d23ca3bf955ff5b26e6931125a999e1b47e92a03db988629e7f1e15673288c915512c8dd5eaeb994daf29114509936f4e794c6f428b8842d0f812454e483ad37988b2b798c831e4a4b78a0d51127adb41e4d47da14b8528a7eb2cbe21fbdfb64688622e996e4e8812ea550ec290c3db1444495ca76b14f9a763300351d6b20fc936bec4681240147bc64f45b3d55b847f2868592ddbfffd5092a1c38f6bd57e76ba0fc5d8d1d7a35ac98752c9c875dccd6e2794f6508ea664e9646fa3a48a7a28b66dc91c54ee3902080b657b2f7d27f347a9a4af50d41b9df2ee4d55e268856204dd914a628e0732aa50ea68a5f93a04abcfee4006154a9731f6bcda484d1e7e3185724af3e07fa2661f495228e5c920665a5227cd4f144a923c888db5ad226203855279d5683c9321f5df36d64ef09a03194f38299d4445ef48eb7c1739b890e1848294bb4877ca356453ca6842d9e45e84f249a335694c28e48c915397a95fc4cf128af5d962af9fe2fa2e7270913b6428a1e0b6dbd7b175722f9384e2c8b1f60ba12e194828f8dfc4e4a7beeaba3d4231be22cc8aa88dcbdac69a110a616dbc5d4687a4b57e19452806d531a34a636ff42c110a3159e64b36e14908e5100a5afa7b261e620e0b6d044e08e53c9da29fe4534117a96504a114337fbf7b23201463149dd9fbd54ad62d64fc409b545a721c1d12761f94c4071755ef213abfef4171d6e366e76f25c051e38f97c08bcfb11590c1034308bbd33daae31d02193b2888f0702192449a48173528204307c41f7927d47f0c9d1cb83122f924a149c7d6c61a928183c258aa47cc29e36cc8868c1b9ce52149e8a727bd8f0d3a696ee9399e26b623a306056f3be951627e9798d0a018cc8485071152869c0864cca09ca3ad6ddef674b5be0c19946c73f2c9b7417752320862c4a25465f93bf294e7a4731bc74fc1a210d26812f2672c644caf28d649ec49df917e23c415253fb972ea1de2a64cb6a270c23efb236867693bbe3041b3a258d5326372e3ab285f4a38dd904ed64db4b1a6aa288d382ba5ef95ab2d4945e96436e547e43a881054143db3a751a2428431f9298a9333df670eda6935c914e593e9ff4f6af26ca32f45219ec753373a133e438a52c6a4f2a6b346c958e6c051231b106314a5fa17d9df41f3c4fecf700131449184798dbf9babdcc3afa78218a12824d90f134546e98018a0288611bf11649bae9604ff3a6adc781b3b6a5c8c4fa0262933410962780293325a5fa3a413450d9ae6262608ffcfa6e06f9c71a228e29e93e9d96cacd5c881a3460a3c87da26ca124d4a12125d3dc792043134516c1b21dff374f64ccf8dcff1e973383720ef0231325110d2d44ae874c244295d4daf5ef27dca2ac6250a961569e484740c4b947312eaa3cbd343bb3c41298177b1c30b139c4a14467b6fde87ff8ea31894288668e848e2f37a13639b4449575dff657a0f9b5312e5b534fd37969f35c8cce08201df450e2e341209b5937396dad4a5f718902867c94dbaafc37da7cf178f280975726b4db36dcbc811e594b65154dc89fe3160021c3b6eb88d0a34a2381e93ce8872d810232d3db5b1b688c286fd15cb24c75f551bbb2988a18892e5e66f889f1691451b6b2b78129ca17ff4c2253083188928e669e7188b74de4944442185fe9019646ac82e1e9a20c6210a3acde3f4fbea94766218a2b061155eaabd45e754888255cda98d19ee6e4b8428651031774cf5bc63fd204afe29a27a865c97a9114439c634914c67261005a55cad74abba66df8028ccdcb75e955758a7ff50d8b4d5fa4d6a1b72ed87827deefe303ee23768fb50b0d38ea2c583bc28113e94e7438e7b25267b284eccf6b0fe39e5f5aa07256d67d04927365675e8a88163871eab0e0c34f91c380e8a9187a208b1c137c4c4434925983c99ae73b0fe0ea54f325f8789663fb91d8a3539cb4a3e7d7ac2578772498fd3324a59f6c9e8b07ffa701b4fd99c72bc0eb4418c39944bf39b8c1b3b1a75399433d5f53f3d071349d9585b418e1d37fe0e10230ec5eb0922e8a0737ccc291c8af79ac5477be70dc5d9cb9fb4a7e3b33a3794553c7bcab61bef94b7a154424d4dd21ae6f3cd6c2877ad6fa6db19f5f81a4a3a5ae99470a64b925c0d253995bca756beeb256928ae4849a3f5263bc6d060effd0611a243bad5c65a0d1d6e8318fad75183068d4731ce509c1c9eb47a4b1b6b7fa643c79f8380133c06da0c05913b06cfce13fa4b6a630b10a30cc5dc13ae31cbdc5f572e2a108118644086ed4c11abc6b21863288fa46c913db235be46930231c450fca03cc9e43669b3c5f8851861301a376280a19875538b980ce79a598c2fe8fd39f7b61a236288e18542ce0d4a5eb44f7d73664388d1858208b25a973241a65e1a2813420c2e1426db8690848c636ca128c9f58450597923ae168a16314b2699fa6ee567a13c2288fad0113f9c90898185f2bfbc4f2edd1515150a625ca1b09f648a10913631c90ae54dea195572e7a4d7562106158a3f328acc632d7aa26e63f102b0831853284e2cf92047968bbcce31a45008563a9a8c613a8c56634461f920da39b27162f250c83ab87798f3f0fb13d07533bf9a4fb79a6a410c2714b28676fe992815e1d851c6f608c78d54408c26e03349e25e44b349dbd808b035006810830925d365bebe7fe2f1c55842396b9039da4448096553b15ba7caafe3ec2494df6373482dede82e120ac9f7e4863ccf755ec5384241a39b0e31fb4bbf270688618472262931d8b7c4f6d317a11cbaee733645d2483511ca9b95f619f37bfe1d630ca12841a6bb93e7997fea1a3abaa04183060dc2355875e878410c211464e7b1f68fa33bd544043182502a15d316b64167510db61840287a92c133a99097f5241b6b0681183f2896480d191bd3858ebfb143c7ef50d3b1e3757c0e2f6a7c20860fcaa5673f86ad6763adacc6dd0362f4a0583149bd395e076a0c1e14733e97a4252488bda8c60e37410e1c892dc7ebc001c4d841414f07d1efcb8fe6095e870e8ab7bba5d32a939f5ef8961839286690c9a34d37708cc0e0c0416163ec66ec8736d6748b1837b076fb74c861b3ae172bd8b15dc4b041319fd2522addf64444d4408c1a94d3876a95b8b341445f27108306456ffb9421878da9c8e5c07143045da40462cca0a4ce6b52efeda5e65d04377094802d104306c5511ff1a4f7e7b4e1894571fd33e7d3cb771980018bf2ad77850891bca2607ac7ac5435c8f52b877b9124a52b0a4adf6284e98e1ed367822ecea35694d364370d59ca6f4ec4c6da4100062b0a22d9e7f839264b3ae1f81a3970aca220fd3abe77fcd858c308c050455164aed8f89d23896ed4b8e147472a0c6e2efe5993f451176617b07b74305051fa91be159fc56b94b8c58c2d7805304e51b88ea16cf4887fce39a6280425731619bd96a290b77bfca4eaa4e06394361123c247cc618ca2e8a1333ea4cc31fee86088a2a03dc8f0ab1fe4861b8a620e412e736e444cf76172304081bb85d7665c9b5d842caa53a4494abd82874002140005189f2827ada39b753788d11c1b6b3780e189f28eb7c6b21746270a979bf944ecb01c1327d4fa1c61c2f9a69a0930365110df72da9b5f534ca489a2ade90be19bf1347c32519c24d6264ad660a258ffa52de3682e51ac7cf38eebce6e26b744e146a6bd9aaf1371e64a14d29989d226294c234c89f2c70cf1a9db2628a1348952e70857124513f1f6716277ac452251ce7bd993cf714d6220515cbd121f84e4cf74fa230aa3c53f269145e9fdd6c6c6008623b24f6bf12e21dd884ea49698194adeca086c3473f6349d2406631125191e3f6c5032c697204594c378ca20457f12510c4a83bc4a3d99736c44944fdcd8d698c89fb23d44b1e553d45f49b29c104394633a253f43ee879ab51005dff09adee266377884288415b1eb0927de4236886212d7f6b031e6fa93208a5723628eebe549ef42018c4014c4efb95b8f79a9520244612524159f793e7493fe50f24ca691f2ab2be6f74321473f91f373a89534ea43b97d7377b687f850fe9591f7e1a9b346cf1e4a11f4f6b2d3aef886f5509205ec87a067c1cde082016a042d965038d5baaad9f44f3e460b25a83741b79dfaa43a42c027b44802ca5ef34811b540c21de1adacd33e45455d36e951aa36beded512c42d687184c2891c5edaa565c3de21686184e25984a4f7361b6b29042d8a505897d4a6164428899c84579c690805997e12dddf94bbf942289b92d7a99e339de83e08e5eb5a370993eea4e900a1ec76124c65373f286f0cb934f1a635373e28c87cda6433c6f49c7b0fca1df7646afede9ce3e6813166fd13db58b5d841317ae8504daf6f1f550b1d14b3e93af3be8f98bcd32207c5eafcbb12454c8835c9a1050e4e8b1b944496e68c2ffa3636d3c206e59f139b1a1442ccdd13f2f593ea9d068510c457c8968c90443328ab8b7b8957a5869ab5904151f27bc6d071b102cf91c3d52316c5d6ffa02d5ef2b70550001648e315eae18a72794c3aba9e791e214a0778b4a25c9a62be37590991382b8ae9838dbe8f5651da7025b27b7f90a6af2a4afea75409a575b3d8968a82e9ec6f93e4fccce651519ea47744b8d96a49e25394752dd3e67df227774d51d0197fb54c644b518e297376cce1ae3179a428a9a912bb498daece3d46519acd6532fa9c9031aa1c3c44515ccd13f2a5a594b4cc161980227884a2bcd1f3d47d366da74636d64051d0b32fb279da2b3c3e5190232e25ebe8fe681a17681e9e28468d0f8dc95bf3fda613e58e1f324dc8acf3316d630de917330ef98b2d66cca8c00568d0a84004666c51810828c18313e7b18992ece93d7d0d414bdea01b2528018e1c3b6ee03880f0d044494e6e504da6bcaa461b5bc3231305ed31d96fd4b909cdd9583b868982521f264aec97288be7a89d37abbe5ea7ce12e5d276fb1d73dc7ecd4ae05189c255bd7a9c2c429feb9428468d159f597fafdb9e44f1c4cd9326cfa35466ec2189a2bee6897332ae492b12a5aa8f1eff93a7c63941a298912e4e8f8620db64f288b2698c66b5d5cecfb6230a22875cd5be1a9dcdf13b6e7c238a1db4268dd5bfa6abe4c18872081dd2444444519af65844f9b266b7d364918722caa7933788dce3790df4c123118538b2bfc93c6b723521a2e4aea7eb671a3d43f8100539d31f6915e9a4444be026f01c0ba041c33c0c51dca0b49d8c9a63bd29134043e7e0518852ca8810429e9c10051dc2455c714dcab4e83188d2cabc65c4706dd5bc0d1d5f7851a6a30551daac49134f468c7b3a1005c9a6af96c96ee35b53f0004421acc4e0264c646b2dfd81a433f56fa39d7e28072ddd11f6f37734a1471f4ab551e37aac63e88d657af0a1fc96ed3ea9bb4c8f3d981ecab249e6f9fe858ed1da584b54822f70d8c0000d1a51f0c883071e0a413f83a73253a2b3b32d78dca1d4a34798e89f18e48c76286649901233bca9ac93091e7528fdc40f26dfb36665448762eede71ab6c553de65052fa744edd105f82871c0adb22d2d274849c59138772fe84a441079d5623c3a1dc7299c464c43f177ddfa06e2875fab788695ad63e52f56883d1f06083aea178562e2aee7ef55eaf1aca41882ba17a7624dd260d85492be757276d2478a0a1f4df26449c1a91e52567288cb6199f6c72d649cc3ff030435184070f326fafbaac3294b48e121b6533965e0ac2830c85d3f17666e7226308a9c025d005d6c1630c25ffd898ec43cb4e88184af2eea5d4739ab4b2bbe01186f28695295991a39f3b184a223bd8969cca6c33d282c7178aa39d94b838950a1e5e288ff4db1ccee42e9447ca955e9e12170a9a5bcfedd23d56ad12f0d84249f7876852734e6212c35a28e609b24b4cfa10bef32911061e5928a709134cb743ace7cd081e58287836cf18827fd02b1e0a3cae50ccd8a983498cefb1fb17b9c3c30aa57c6bddf69c1f730e478d4e8547158a19325f37e9b2bad2d9584313c18d2e4870dec61633b6987176b804666c3163061711a0e10a0f2a94accf43b6beec24ae8effe2049fe32e87c7140a3133d6b5e677d5287b48a1d81e5ead2449da1c825128cdd658e97dcca489db58eb3d8107140a419f470c5a211b6b5f5e783ca118da84999cd1ae1d293c1d1e4e28bea88d2422487de0d18452aaa957e9f3df504a2614337a0ea2344b3a093922f058422167eaedb85022b8f736d6140c1e4a28a6e9ba3215b1a247bc4347e2173c9250526a4f5be78917a9791374e12538e7050f2490239426082d993f7e9e8d948711cea308c599347a5f92967e663c88801e43301aee2184244160208cc0e307e7e18382c8f13583b2eb2a6f5080068d1b387a503a21ebd48fd0216cbcc09143013468e8e082070f3c7690998abbd5a5676abaf6040f1d1474d94413795cec22bc1e392846d2259b748c26793a7ae020975be07183bce16103fc80470dce830609028f19947bedd497486ab664ef21839232a58334a9f1496f4e2c0af15469759e20af46038b82ba3211d66495f18a72d0d592faf92a167a571437c4df344eece821a815c56067a52fd4dad6ad793258518c9bb1df7f341d26381c58cb246315a5f1243336236ccba78ad2879c7e2382685ab570c84845d97645df7512a922fb892d200315a54d1b43d638aa84aed9c61a2209649ca2f0a7f936bad9bd7e96618a72965eab9ac9a5da2e4549fcee7c2c999e6c72a428668d2fd95fbd8db55114b34ec9929d4c9b5c43c78ed7a1c345a1872fd9214e0c45797545c5b2d53f54088a9267bb6b52bd938c4f944e4daa66c9caa4b4ee09a321a313c5ce26c4e9532fe7a3c38972eeeef89922ebfbe54d9464ae2ba5a125cedea78962b8c8d52e49467a0c2199284634f5516b3785f21c4c14e35be70d2345e289fe12a54f3a9834114a6bd5b484d1a84a9c0c4a94b755e36e273da22aeb4809c89844327acbbc35364914b3894e939d2a47c5b7912866bec7d4dff8749186c4c9784439baaf9c4c6a1c5ee8f81c8e288df875f11843cc71c24694ca94c584e841c817971145094a8448ea20c52a6c818c45180d13c85044e157eb7f84fe8f24fc2e769c2f3a1105eb7c9afff1076420a274a73e4a0e259aeff5808c43142657ea84cd31d8c6c91045b1eed0fde13986ae10c5091292ec943d218a699faab1d9454b35569063c76940c6208a2554bb36946ad5cbd858134459cc7a52bec9c6fb5c7121231025093a69aac7dc29f4cde1c50e1c3816f05ffc17165042c80084d190f187f26a8b694bef891a8240861fca21f663ada7c9c65a1a0764f4a1dcb71aea45547d436f636d6770c100bd3a3e94abcd3a7c3c899d473fd5309b848c3d94fbc647e418947a282439362a5329cfcd6f1e4a1e326a50fa4c7bcc1b1e0ad7b1219b38896145798752246942abd775104a6587828c58c27f44cc9219ae4339ac871af3accfe02202333a21830ee5e821d14499fa68d2cfa1ec1236bfe3477228891033ee4f5933b888c00c1971287dc7759a54f10abc04df9a900187429029d2fc4c5da3ee0d85d5f7f36042c2a43f2990e886a2e949d9c1c32aa30d2551624e248d314e6c52b798b185090e078e0a882164b0a11469628af3ecd958238f821b38bad0719632d650b6b8523236496b90a1063b8f4cd038a163b332d2503a9df89e99e2428f8865a0a1bce7d565e51f549f0ec080175fa057000d1ae8bdf8023dd2828c33a80c337c69ca940c165a837a5121a30c458fa69fefb236131c0e7c19198a41bc7cc39f79051963286a88fcd990c93677490cc5b08af15b93384979c2508ea7fe4244b88edc5a524106188adaab1512549e8cf47ee18a64e9692f17214950cf5c20c30be5f098180a7098e02fc0c5116474a13c3fea593d7f309d7c1b6b2c830be51824e8b8f9cfd25282822e4a70e331d0851738b8f82f4ed0c58d0cd8d8d1c50668d018828c2d943565e89dc811fbd6d742c17784d8c82a67a1bced2379342665f8804521c64a0dfa77938ac4a41b5de89f83001ce986037418e1e315259b2c26d63aa4f90ddec0b166666656d6bc448de0043a50430041f87045499efed2703a93898f5614945e9b709e4fbcc4a44a4b7cb0a23cab759621fb9d3c11243e5651f220b6d4c87eb24e6a121ccfc1050668d060c4872a2cf1f023547c37c7e7fb48c522f4c3072a8a31d29fe4ef13edf99cb1c51e3e4e51107983be975a26b50c3145d9278f18796bf24968d3f0518ad2f779ce1cc374ac7da428adcca9fc581a84241d4751ecb87e8b24e32db4268a52aa85e9ea1087a2bcd6260745416710719e5f9b4f5c9f28a713329b364fab54b9a30b1d1f9e28c4fdbe2a25b2a5e85127cae915bffbefab1ec25cf8e0443979383bd72bd5f0b109e684d8e40c1f9a287abab5a47ad1514e9289c25dbccecde8757fd70b1f982865bcedb80e0f3a87fd1f97280635df7ef9b9d0ad2d514e1efe22e75d4e5a6963cd8b1a3aba68f43abef00a182a3e2a513aad9d612abfcea48812e5c9dab21d71d45a4d466ef0318982124924d579bdccdc1b388839608b1b14d8517c48a2b061b486a0c3ccb751978bf8884451e62e7ed378fd6f0ac71d0ed0a0f1018962f87e76d5341e3c2c157c8d0e7c3ca210f38fd22de2c40419ae617b870f4794a38692a0da51d279da88b20961591a4d878f59c3000d1a3468106b46944c36e424f304cdee693c7c2ca298eeba337d045d4ac48a2887a44b076f092e32b28928efc8d8aafd183e9308220aaa6f3221ff5a664d8346e2243e0e5194286bd94147ee20794394a4e41043675613423f852066bde94d237cc70f421463470d91ae3e23c71b44b173dc50f5a59f93975bcca80accd862465160c616336a0233b698511298b1c58c8ac08c2d661404666c31a31e30a302119841870f41143ed427b1ec3e0251b68ebd1b47ab1ff80044c96f33c9bf139e35f23f9442cd579c8ddc973ed54037bcc68ef33972e03878372890010accd862060d1a1f7e288f9c70cf08610c7cf4a164d66726e5754e8ece87b279523e21886d112adad8b32f1af750fa4f4a378978be9b255eb80430d0f5a187825232adb3279ef79ef250d29d59c33bad3728f05e5060c61609a04183b7f08187e2ddc7907b21b6dd2259868f3b947428ffb0beff6116da5833a8860ed78180307cd8a1f4125285a8ee9ef05187a248d8bc1009a24331cdf77f64d9cca16032f1afaac23497520e050db24ddfddc3696de35092b1d4ac64cc44f5a48543e1b484b09622c435de50f06acfef644a6370d50d65f3ce3a1139c9a42d8ec2471b8a21ff87eb64b98fa61c6e82cf4114f0c18662f4705f93cbaff1b186d258eee9891bb136dc6a28092fd94fe99943888a031f6928780a4b8d19cf071a0a36ea375537547f9250e0e30ca58d7d8d13845fc6a0f4618662f8a07f23fcc4c61a8be0a30c2549a2f326b9c1b6737005381061c107194adda7c34aacc9d1da1c43c1d389e70b959a3bd41c5f811d1f62c08f3094b366747d7a3f19bb43c10718569d18e487904d6d44051f5f28fbc9ad4f6aca2697ea85d28953dbebd4a4692d4fc886fb39f2c607170a1e23b6c7ae1a4f63de78147c8d1dafe3736ca118d32799f05469fa8ed751820f2d1473734c63cee8230b05299ed9b428759b291bc107160a394993cfe923e85ee80a65f91cf44a18137aedb442b993ffa43e6121844e158aeb26ac740ab11e3752a1601b82688e58af0d6f0ae53cfa547c0e2a843e078e1d3af20220860f2914d3e8124f3bc283a63a078e1a7604f888423144d0b399f49efe708242c9b553ed22249d61351f7c3ca1a0f3348f0af121bfec74c3098514b2b341a7adbdce96195c4460c6058e091f4d2826137152ad7f8ef0c1844c7e0ce2b46b7cf9b184c29bbcd852d5fcb52325a88e8f24942edd3373428ae8a5b961761f482868f568391f1b1bbfd5b88f2394468706e1398c08a5d33770f061e1c308e51caf67a724092d6919e1a308255df2751a3e640e213d840f2294368abcb97f499a111e4239575494a75d0805e9b6baab5d06a1e07b2762789997bc4920944b46e3831a3b9ddbf483e28dd249ac97ec8382e7e01d3eed43fce84141d4da24d9ecc124695a081f3c28ab576a48a183c410bd1d943c66c73c956c78c950071f3a2868b2ce9fbad37ecfcf41615f630691cd4ab65ec40f1c94939daa12a5676a5343287cdca0d8a64d454e58c49f930d8ae136833eb12f9e2658838267fbd125c935f989113f685092a0749c41593be7bfc3ea7777f44306a5d15ee3c9e41e8b72a6534913cc65458605366f4ac8873e5f51b08f49e4f1d23a7ddb15e5b4a5744bae4cab39a71565eb33213b234b92e7ac2897ace6ff6bfeea6b5751acb26a097a661347a48ad27a944f239f6b438ba9287f48c87d276a34b88d8a62b69efb784f9da2fc4944cd1bb4653faba628445711ea5d6d434856298a3978ee9c2cc38faa9614653149666a6eaa1dff5114ebe49909e1c9dcda1345392965d23e84a4a3e52414c510474b5fab4af291014521e98e3a159e7d4ebe4f94aa37753cfff6f8163d513ebffd081e92fecd5f274ade2363f4fbd012838c13e5f694bf494db6f5ae9b28a40c5aef6e4687ec5213c5704244edc964a210264712f142041385bd4822c5cbcac6342f51d08acdb9ba334b14442ab91b46c754b9ac12e59c2eb463788f12857ca9d13d630841077b12c56c262b59ad9244d97f45e3c4903dbe6f244abb9ec1646c2051923199bde43812b7e34794b346335169ab238adea9d7b722d288c25e7ecc1d94850893644449889c203a434971ff1651d02a93abbf321f09514471b45e557bb529fb3b11e5984b5e8828b8cd9daceda7ac390f51ecfb98237e43befd18a2189f21448a4dae2a6121caf5227447d65d4fba2444c14f659ee6607d42bc4194b3d7451c139b31e51144e92c4ef828fddd285a20caa239c7d841ada7d90151ec0d3139bb6e4cbfed0fe5483aae4498f397acfba158ba3fb249c91145a9fa50f698a326e496f950dcdf7872abe3897b6a0f658fb8493c24481222d4434168eab0a7339f87d27dc69f796caf391d1e0ae27952a7d6a8a5ddb943594d5c4834d94cdab21d4adb1a3373c7881f295387928e41d37327e1bbf6a143495d93e6751ed9d8f91c8a177eaef56f1b5fa91c0a39c418c3774772962e0ea5307152d4247caa7f7028c58b48b32927d4b9f7866277958ec8759383ae6e28fce60f622d746c91671b4a651bec7d45d77785d850ceda21869329efa388d75018d16b9d9057437134644c4c235e94b6d250d219de3a57c4b7b10d1aca497ece20e44e3324a6cf501ed1417798cec1ef4e3394ae22c7647a75452775198a1ff393a91a9fdbd4c8505042f674c8eea6be640ce5a0428bf8f36b2d1bc550d8b862399b21f27285a17832b6a74d92038662aa0c6db3611ef5fc4221a7f8eb9cfd59829f5e2826d5fb1add35dd56ec42297f4c9d7a9a885a70a1709d940975de366262885a6ca11ca65eb649432d1484083295fc582a4245b2503a7dadd4dc2b416c140be57c96b6e919dffd3d57289e9a50abcb5135eab542b183cc9f317645d4a20a255ff5ced5daa7662e442da850d2eaea9b4ccd26b75d63c78d47c1db175a4ca1f04979b4f4de5d043f011a344cd0050d1a440b2914f26967ef912703b4884239cdc8a8595433e8b043a1386a999b4f3709711a2568f184c24bca10ab3d7a2a649c50dcb85113639e4836ea26146e9458c9bc2f6a25dc5a30a192418434310f8bb9a8040f46336124108642e16030100ac3a2bc47008313000000081c91c562b160349ce852f70114800359301e3e2e261e241a141418188885a25038180c05034140200c0c05828180403428c69358fe0a0e6bd954a7ce5417bfbeca42f5fb3d84469d6cea1e703eb4583edd96d4822b65dfaec839f06d360f09b8260b195605e452000f051bd3087f926965a015541550049e16b893a1634676c651372f086558d0d117c945671016e971bde5eb5c5c24f3353782fec51dd472a08013bdca0c8447d6c5639300343af29870a32c510338108aba5c0469f78b3da8b5c83bfaa27b083953b2c968be58d50c16563ed0268ac9f3aa85acbf0b5e1212b577914800e97b7f102a6a489b7e894d784d5b33b35de7f78c9c7e0415e65cd67895b28806d3d2e6f3c1c450da97a0b3123f30854ed67d94b06feaad0564413228b6eca0557ebc0022493c1ec110a381bcc833e1317cd74c51433a9917071fa0852643755218c21f7d513524e52736ed026b54e5058ded8481da8adcf8268a5b11942d605e71e591cb3fa071d0feacdd1b206bce45ead52b6ce35e9f24d0bbb59c42c9c24b12be5efd84742f98b2b882d1818d5d6de0f0be78f709553e9bdc8f7c575e48f63492a37e9febbf74a9965e06f052b1a33cbb5d167a4c1e9307043b46953ea5f8d126cc2717e529f40f096b0262f8f6736471ad1e8b702465510cfdd154656912216b473ad63c272bba29065a09607395b7b181a04001b8233a55dd8e88d3ea21241c83619bbb3eab939b5355519f2eb0d95254a34306d3f243fdd091f28b26f69c1a2dc9e626709712aea8ac129008c971888898f1ead2b7e1175013c41936045c331fe8688bd34508e5ac6f213f774cd9a5fb1111d4533fef6746060ca78df488970a81402915cc682b0033de8e8ee1e8f62e588156f124403894995c835e0829214f688e3c6865329cc591f58c9acbb9cfb97fa088ea428cd72b101797a2c19d709d69a3dceb447bb63c0061e6b46c48bf54bc7e47503858a27cf3188889d7ab06195d4f6d90ae82111ad6828efbd1a14971822fb57a67739c673fed00521a6f7748802cf6f8801b98835dc084401125d1eb28a382f47f08cf8f8536d1e3a8f4fbb2c04b712eadc492fe1e7aa34027ecdec9e7dbbc78e09c88f81897c72cb44d43fdf2da5b9103de1d5ef81f47c66995c92bb8045232b23a140f034650df1463d79db59d716423377a8e51535041cf4cf69444ff196015c773422d9177a72494c51ece7fba79e2371a37706e4e9bfe2acaf31339bf90eb41acc9e184767a24db627a7001a56124043c6151888f645b67ac3526288581e8fba8036a975ebf9bc2a39d6446ee5cf5610e23434e9545cf0e001cb747deb2f2eda805de58a088b98a4c63f1778b46cf27a88e91152eba1cb55914fb9ce5cf5325aba2bffca98259ac282870b7d47ba6820f37b15c9c15edc7b6b634a477108e5c405e2d2464773f42d3590fb09765f9deebdaaa7504c232c3db9a3ed62961d3d9f23d24dcf02f26630c8c471e55e59d63a37d63319e45ba1a43bd2a37a453f8f73d13bb58003563199afe85d3b77d8c7635b27d3a726e685c2a18d661d3fc288323a28a77551a72d50a315c03dc400082956fdf3ec4e0600b7ab75f26676fa4e3c809381abf09fd8a8888bd1321088cd24741228452b17016ee654f1276d0bc48137f6b06fa9bc0dc6931d0a0252617d3a6f3d9bbb0d60eca31602beb8de58ea330924339411b3be0844b84846b8469486b258b04267443ada8f67124511d5cd74d0057bae70780cb64135e6b8ca599984823807694ec804881ec41455b5d2f8e29e2669a9802370748b5883d65ca9d6850348b64346ce5c442cd5bdf7b553c94c2075a1b07786263a40d2213bdcd4523fa0982de86aaee6ccb65cd7fa742ed69ddf7ecb338cb18e2645d28c0e4d951d5dbffd134ae221600637aaaeeb94e54121cf067ac0262c51268b7129e8a1be3fa60847eb56667029a77672b738bd123a8f33c9cecaaef56b4cd82fcbb735cce28c3faa5ef4c7c20d25baa674139831323edf8acecabe5098f68ceba864f089b419dea5d0f3857f6782e71e299d0059cde6321cd91cefea50f7ad11ff722107bcdc7ef65fab871c1689bf1a11f94fbbaa6a9818b37342ec94833816e9f6e45e38185652b19ce031d4512337ef20fb19f9728db2ceaae3d681b7dc2d75e01617d76079a53c4a36747ce552bce6aee65e2306801da9286afa7ca665de69c2113378cd294cc3e74a2e5b3b2b726b5e5af7c676f405d6885572073f3f3aa06bcc97f0372ca02e015bbe2a0fcef98e0ef02b0bbe7f7390f1c127772e9001d836349146c5c484e183039515d200a6a0af9256b77ab4b8b58e94c2946dbad850b1d3b3d1ee33d947d15ae5baa57bd07dfc3c49c8f50a9520218c39ba96180db53f85f118bee1a29b055af205e94043bedde055baaf1edc4326cb806d8e9f459d8bfd30786a4091026972036e75222ea31c3f6c7c357c28c8a55c4d670e7e36de18bc990f0e6ec6bc594324581da7beedcdb30a79ceea15b25101fea5b589eeb95dd15af1d0fc85748ddf907b7e55329a7aaff840343c5f6e343a59ec55e71818b28e9d9e7144ea95c12449ce2bc7a5dfa46d1be4920691c6e1e0a8b894558b5cbafee23421e854c3d2ce32dd226be7fe73ac791cd356ea2189fabe9b798a8326825924aa5a74e4b06e2daeb400dd3124a1f1a161efc0d2a3d3d0159b6330f60514e7b910d52fa725c41494001411d838288fa41a1425d437951a062349a0c2d79a8165060a018a1ce00d0b8ae50d850eba0ec507ea04e82c24321813aaf2860a77c845c9692261995a99da0087e071aa77b05c81385f24aa3fa90a9ec5c02aa9b460103d8f78b405040f52beacb27a7031ab2c8863a43012d1c52232743595e600ab30b50ada520a230500f50d626ea16b8d4bed1ee03eb04c5d6a8a0525250fe50660240447aa8b68eda97ba0e4503c52fa2743039891d6f505ea1e077d4b4ace42ac301651cd4dc0008d42c283f941aa874a8a450c65010510328c8507b500a50ce1a940e8cdfd64441ca0c94ab5006011a436a1674cc19662a80ac0b4d2c4449e08a6fb1547b29a87d5011a034504aa18c21d4bd87e2056cf951a5523650891114f0d7681e017c790333710b95b946c2f1bfbf98451b0895875a02a50595b140015f81ed96202361b6f32d7f620b32e64778a4923aa9773ec7625a17bc23ae7c625b6cd1613939fd7aec29387afd9af88c88c6e5eb7683e0eb5c44885f45a753061803beaa2d451e96d00160963a344e0558afff29886b6566680cc6275cb59dfdece2dc65181a5e92c1ff4c2cc604c8ea100f842f103805ce400924bbe411a371292bf55ded7431e3241099151ef9153a9dab0bbc934109a80f8b0d6d0afbcfa39ffde84a01e71c0f398e4b15100d2c857b66a4d852faf24178a3fb82af6131e0507d9e06fd2cf676874924757560faccf5d124aca95534992f4d7ff1269d3d9ee1b8c5b7521baa557093217d23b384a811bb2eb1346fbc93338f8288450e7d8ff5a78a4632d769043b8b554c3ca172b413183d2c76854bd855d6178efce48f2446ff028dd1b0589cdb1216d9383fd07adc23cf723e4140328009709206d740ede8e23e05ce0bd7808304f84d95155ce853e2bfcca39442c281a461e686e85563561be79ea76bb0cfba3478d8899d62e7960580f1eb67e4e5ffdb50e98e863f7aea6c10e86ebff79acf54848f15d24f4d7b94e8cdbc75254d73b38a737eec348ff21498f09eb29aa7bc9e81ed15c9f791375e0f150330aa721393a17f440695605a03cd940c8c123a1f0e1b7af4aada06605551927a92b0e3c71bef85160520728f3b469b3b2823503ff683970b567857ad8a172c394dc645965ca1a50295317c661895917a9cbba47106a05326e8025450995f4e1dcac31774704a8f1fb29b7f0dbd0c4d0660df1b4624595fe888dbe495ef25726c83575dc5647019aec869b8e88e54c90e71cb89eb51536bf64c903e72fb341be2c419961d92a4af9a2ded8263a078263861009091e92e4536323ef669a4c1d2ff7e1a5f9a3ad37dd847e4242a6cb78139cc79bef8ceba461a78cbcf1205e45e7591809bf7c8df24de71c2c3e8bfaf26edd3d987e530070288a07ca432a9a3661908defba10a361c9191c87733fd28020615ba606fdf030da20dfa8e132eb13c6bbac7a5088ab66091f28bc7a1f509cdeec5f1930fd65283e09fd3497acb1011d3e76b2a5757f13e07445555c5f84a88e2ee3bf8a7ca2675313b76b5eef099d90a86e51c5e80e2d76eed4c7b9a09623c201437ea3fe9c06590e07ff5d4d31d133dc23ae75e5bb9353c57042da7b24b7f2ab172df8c3225218522f368a9a01203c3264cd0819cdcd1ee3e52fb78ea1d38e4e4c6ee5337ec8ecfb8d16ec670659c4928bfd77a5512a6ff826dfb9e2a0931e2ee71e110962ae7a7dfdf3bc514c99be1e199baa72455ce54422f4217b09c365060fb686501027cb6a7393322985059c5530d95675f637c75cf57ff8a542eaeb7250980ff60a9bf9e9ec99ee1ba175ad3a54a06753deebc9f5c90312cce96c11058f73e103eebc2ae9fed12199a3d8c837b0af8f09f52a7448441ecd0d6045af618d0afe28118ab11d913753c31ae2de644495c7a344adce28bdd844669896bf42763e9362989a0e435c99074a0acaaba3635afe0a0ab5b578d38d1727e4a84fb485d6f1a71dad4426ce2ad794b1135e5bc77dfaa10792006378af9d2702fa0453c2648849ad014605ccea5ec88644cf600b8ac869736c14bad69c92b6e52f50f02f4d015c54078c779e33ca92fb2ea01396255f1247c6d67b05efa64a65b6d1c75b1afdff02a95552612cdfa0f676ad2938a2e44a630b426916057d068ad012b5d2b0be4eeaeb51366f616414bb5629a7a7cb0a1061a0c937b88b137fc460aa4bcb901d0eead06d5153a678b1c7f7f1f48464c99410ed1ceae1fdc5e89c2c0e08ebae014afbbeea85e5c130df292597b97f32fb36b330150bdaeb7bff4d6c5bca42aa50bb2f7e41d6bb4474c5c602f9799c3662c5f08537b80622129e6b0c945d26c72522c0c75038ec359efaf705e994306d3d4024a2250ebf3470e64c5eabc134265c7253c44075c1bec4a4ba6c1a3334324655016efd55fd183a8c327139affc5e6bd8e8058c3d8fceaf62c10df9cb304e4ce68a91349da47e289c362ba3da24a44c8d4b90f7dcc757c3c62440ae80f3e42069148b48159421c6ff50c7346578e461e3ecd5e6f7952f58f0180ee010f066316dc089ad498c3fb3319744ad3f65d35dc1cff53bde42b338de8a2c97b778fc9341332b18d180df6b85bece3477ab33ad4760bc10f492aa13e690e96447327e9040f32f43a80880d6893ab5a809cb78750094b76f121d7cc796c80c04bc228543650c95d4b602779e73c495b7e7e1ca536d03a3f5c2b61502b0d68ce235ac095045f355027b9999e207e488410c9bc27c6cb4d969ab8758f82b777a07ef3cea46d7f3f74619c90eec8e5bb6138e04cfc60db301fa1e19d8d38ce9c71281621dafbacae048328bfe3b42fd929609d010886ca8e44448348a869921816d6c327902fe9ee47b77522e6d61055d68e47debaf8c49276ee7969b51657642c09ad2028437167bd12a7812cff9e84d4af42acf100269a9197f46876e2b60270eb08ac2cd2d4c9b5832b36bde7c8fdb84cbce153dcd8ccaa639cc1b827935110d8eeabb560e292f5f3fddd3a922262e036ee807c2a0ed551379be4572bbf2e1c366327c6f2a4bb1a718f093d1fe68a38199d80c5d86708167e744ddad475b4dcf8bc1abfa6b38732410413b33b1a127ca88443a2093651ede51877e5b1036d754389dd636138870837415f9e3144aa4a41673d10eb395a8c5a3dd4e5593e88552192737bf1431d9408b3eaafc24562481df46f3e28fdbcdbb260c447cd29cb41a11464b6cabd46c79a4af856311cb42c6579091744db858eed6f3dd92bf80ca91c89823bb6c9e0a69ccfbe05c1ce2abf3a7a20d9af28939c84da4717f267d44630315006a90df3eaab466d3ea3fc6af2aa3557990156851e27a84b81f5492d1b8c9473725ddc279389e4b3f3544af07f292b15a21848ecf071032caf0fda980d4c7452957be1b5ad1eead2accbf7af58fe78e8da4eec48d53443afa743a1a4e41931c83a8e943a358025445e7715358bfb1492d6126c699727abed14c1da2ffa2cb0be510aa749f3ffce16b987d3106e725a8985d1bd8117d42d462ee86bcc99f1f73221159027952c4ece39f16b20eb096a3ea63e9618a02ed4286f7648f70eb5d90dc3b1de37916d2eb1a9d37be25423d2bf7309a8486acff4cab00f8b8857935be19d50ad1ca6a45183a421a480322e75f9444ec1f91e8393fa414751c54a3ce317c6f6b35b7432889336f0c8eabe8429c0b710eaa81aa8a65378401ffa56223293212c6c92d14c4db184793b88f4d7aba1697446b812ddb363f1f2e6250c92026dd0413edfa6270e4af83b71ac130c0439139399f61c6deb279e03e5455ad5393b4b547a4ca17943e986da2ff6b9c48f25404596f8504dbb017cdd31a2e5b87119dd56bcc43576bf32c6cc146fb1bc167174bc9c8ba856e4aa34153148e6bc6ac81828899a0dc91144fe22003c5902dba024ae7d7c1604f42af4ea0c1e0eb7269cea720d9dccb4f5fa826a1d2d5e3b672540067db5d7ee85564cae115d5dc77755804e133a9debb60f04a5355594ec2987283f9689be5db77014c58b6192069faf1196240833d8724735d15752b84ff9e2e3781bf927670836f6c260c20f84dd13ce933585d15f38b884150030c453cb156b983123fd6119a510ac5f3dc7086313cee771e1bcfa66354277db48e7b79d06b160c8e367eb8c25a79d45b4e23ba2d702af64dce54a96da03f0df0d694cfb7983312746480ac2885dfbb418367620553b83b1a548edf72a3c4cc2165a7c5e42448fd8e8ad3823fa110f16eef554e2ad67bf34035c14b98697180eecb0509525c397cd943a9301925c30e01e312cd06b79ddbabf14f19212325e40359172e94a7dd4f741e848d4b51d7034dfab5c7afa5e5ea89e78a614fa49d6ea3c0eb765c8d0a4196fa4d0260dea12305ae88818664dfc664616b70d4fe4470fb75a1b6ed053ad6c812cea2849271fea2868f41bd8ab6bde0762a88ccd1995ba133a910c1a7265cec81fb5e1a470b86a2d4edf06a036f7ff7c033da7f5867042bedd6ab7287b12abcd45b2f365fc929579a857ccb063a813ebb848885d352a169ba1bd037d712c6cfd681d04d27e4c3bc772fab7cb163c627dbf4c5bb1f110334ed474e5c87530033ae6aa8403af5aa75969e17b0041d9b9499ef227380be2aca8787e9554af0febf0ad643f908fd937c89c67583972c7e4a6604c3df4cfd4ec70e59d6c40e4f0c462c4ab159771151cf9e7d4922f650d9f6e69ff5f3620f063de89fa3a8cfa8ba312d1a20ed89484303f42ae14281130d2b7e0b0dabd285d0cef4705e5d000d6d308cd7449aead3da19656444cfcc88a1f492a228310497d989aa8077155fc85254cb2eb5ef475991e8c9db0a1f17fe334143b6c3948a0ffbb22c0b5cab329e08dcd0e4e73929ef310eb3594222b812b32e68ed65d256453073391278df03e092c3dd7d8482ba109cc9828774ec42ce8e959cbf0d5d2b1a5c043d8a6181fe9feb454b37d75914d287549b610cc3b442f699f9b23fe0885e94db9152da204df2ccb95fffd39422aa2e0b371e2e5032becbaad22d464a7c6851749dd9a3c0afac02e61bdfb5b87984adda1f5e4b365c9596926e8c9843438b782792bc34840604c0d0e1bb4708d6280b4769b3b1bdcf1242829d2127a4f0f0663294f56a5fc17ca8b8dc9c2bd41983efbc8ebe7c384651a534689c0eae4462ff6a7c5cec033b8bb0c759d5aa36b7cd17f1aa80255832ff2a210b687ae35e56a5c5aea2e3ef7b438869b9b2f96183e1028541f84ee99891b1bb6f30623e0c27b71b54b06e2daa9d09996bd580b159200dfe1ba0ea76f8d529f9479c0a40babdb63c73a2bd93f57b1e871ba3d628fc6585340269b35741f5e453f3499fcd9eb3ed2da6ef5d8b8a527a2f915b5d93b4a3d8ab861c98482d30d2968066ff5f02045efef8fe493572c1305ec5032fb5d7ab516ef4e98b4bcafb7bda66afa812fd7f37dd82484b022dbdab027163dc896be1e4d5bba5b4685d6d45a1b9e826e06f9c0e68c9e3392c9835c84d95f747a060969c5c8e3fe1977e433be22d888f3c3e3f84c041db2062719cb88f28aeaca38f7eec24a0e6832c99d6293698f3909694d062771d4ad9696ed9bd7bff19f87e5ec27a8964334dba4147f861832dc4f163399797bece6657bf5cff648cc89c66549d9655c901d424d4732a646b9ec1f34c8fc09198c9e0b7798038fa53624e791476f1e04f697ec0b5369f9502030d6ac4e808b7a270840e5ed1dbe8126b3794dd0d011332ab2917ee0da7651001c8f349201e350921317b16a997afa2b20159be1351f6a871a06c70e03dd8a3e3552f030cea7d109f64147d540196fdca24923eac1097b1be5ea5320866f5c1d6af7b88736c5b2ef79b47634b0a3d8dd0c7a66e91648f27a9ea52ba3d1df118c8b91784aa439baf6b04e992ee9c53b694ecb98c59895344e92153453df42366dd06bf1dc4a81fcaa5970a9952b8007d828b3eb9d4f5c4a290922913077892a58eda569b817bc3083e20be56eea391311cb63786cd8e60ed35620ddae74a1f9d3898499b721256fbdc1c911716dbf8e8894024ca4acbf0bdd53a7100851b367176d9134212572f2b730808795f85dfff81edc43eedf73488eab888aa69b2c80fe09233ae611e8c98da9f4e5da05149f4235b1f0b9760a874dfa1c4dc845cafd58a124fed3ba6ee2056cd1e63e3bf1652da892f90c13cf6884b28824ed7c50993c7012a680c84f1678ca60207d266ce72e46d5777f6a3cbeea8e5929707cc9b374fa67763bea8cd5e2ea158db986f9b733abd0e0279d8d64a3e41ae6debc8276009e3d25451da7469838697610860d467de616f503eab8d1339cde5e9df1253ad9b39aedce5eacdd0c3f3748253f8fee99cf5cb8cbccabd2e4164287831acb53f47ca9fdce09d6f1132b661600d6ff664acc3059ff53dd7b108d3d35aa3dd12edb840b146b9fb3826957da4ea62f4a356a25b8a00b03bb300e4b9b3c240ce849a38484d59318f7fefa081e7cab8a7d49030bb9199d0be0a9689ca8dca67eb3acf5c78a29f4a89f41bb804b1ae6431fac5c38914242e27e2d1928c16a166771f702333626f586cd5c28dd586fe2893ac13a5dd3b39130f503f8b42e2f1b8f687a5203d529463a6ab24c11653b3758efcc1ca6ff9ec93298ac243e4c772e99e9a2ae9670d3eef1dd0508c2f7a57158da9cd2cd765882603aba304a56a897ecd3413f27651a6d6f031775f781b4e6b8a58443671455ae933ca6d366905a4132b74fd7281dece40a4f29ba023c425f63c66f1a9524ddf2a8d24c70000ae8046ebe14e8249781e09133459ff8d313de50f8c9bbe9d9461c6edc359b3ba5fca22311fca4f7b07e63cad75849b5d6f35441d87f65494ccb12b547d80eaa3d95a12c391103ab21878d4d3fb524d7c8b8319a04aa6a71083096aa28db68c389440c2446c79fef2574abdddf09fda5fb695aa089fa54e9fe543ae9205952235a8f43b943a9eb22ea5222fd412019e89dbe6f341b021f27b915b4c434097c2ad48e5800553df409fa70db6d68d7bdedb97f978181bde0f7eee4ff873f9d57b66366a35aabb866b0771142d45fa0b3d1a2084afd1cfd3e41407aa0b847a00357c8feb7753b18ccde19639815557fd855ba4e2f200c40029890e7c3bd4f583e1531d4b87ff1cf64d9dcbf95ecf4861cdf1f543e5dd332d7ecb571bc169a87f94ed5a2f2e6e64a7b3f0adfddbf4622c8552c1d064c2f8680839acb3c1dc14eec63ae274372f10833d012d0ecf3904695cc27a846360445e306f41efa13d54c97d643e58988b9afbfb473b37a34133109a5751aff0e61a6406bacce5948e14c939345fd73792305d10472f2f94c7500242183db8d351e883517febb3f87d1fdb62125b53ae78411da60d674a84eff693fb26da8a49343ca4e8430ee3f9735d960fd2024c316a8f8a0178c309b7ad2c46e1201522b80f755cff8990f7909e7686299bda0c0b9631fdc828c588e413228a6838a1b06af9d0e2ea8f3f0c1c41062c6150fc483c26503e4c9e37a85f2ef46c736b3e109b59e07819b4ecc2e04e98cdabb2e39c80743a23c9bc1a4725015538c3e4dc6c320d96731f260cac6ab7845793eeea877ceb25f6f048b81b07f72347e9ab4aab7f3b94ea9726206a116040ab589aea2e1004e6bb8924fcf0a23088441b36688e8e43532043192a808726a4ddd514b409f80a86486999d04c70497ca8cfaa240860d2268c57fcb4e1d4460252044708268916c4a2b5cda6940e46508b7a308dd9a611423d856dd358df5bc495d5c659f8d231359a162401f5ba821d73d2f3eca93f7925d5809204996276581d944b8227423049187885688612669a8f0645791bd579b58b82c0826a425214acb8744aaa9102be455484230edb00d8487211d86713b30548ea02330d690730514d929840ec846fc00d14a6a6b2f17b8e8d3471a4a46dbafb0747ef444fc38b29f06b8de2b5d6b5bcaa2f660d5d3c1bbadc760170570ee716a1b3d1aefe3e7ceab27d89c59b4a6879a062e75950cc32a040b2120b22d4a002ba240fe460fa9f893581077e4dd9a0e857f2c3aee4f758c6ce95f2a01e50740fcc210bac6bd2707beb5bc7ce992ea997b6102a0e6bca6090f45e64e8d1d0e94a8e68d144fd207a5c1121c89eabcf96e71d6d68b156b27c649c039390c64b54898cd9edb46723a9a99586bce57130ad7ef761da60a031d3c4712e54510a93a636b4d5763024bd7b9eb41da8ded64023211d0278c86286a6b3e7537a41ce2cc808d25ebec358e1a4a12720b995913a765803ab78c6a903e230416c919716977ed7c052be77943e036cb5a0ce87610510c30963c5cb03d1fcb967d671bd9e8de716c1aad22819d8846d909173177f489d220471e1f9651d0798c32e89a9e8254bc72c66280d2f06e7c950d34a25cc0ffe269f6da8c5676fa669c039349a303b1d7267bdc6d0c9a925e07ed36e7062922fdc6d766783649d023fa11b253d2c367365303d7b3d45d6fae0029193d0bd45f38d1f771ea5a3753c1fa1c85553b952f6a0061b7dd7873154c93d5d6aa510554b3327b669e159c6d39ec0b87e03bbd73c9d0c6356f8c4479a0e86e855805a5dbe4aa959497c9b2da443e5793e4fa216a82c94b5287c933bd2d71ba5fc12c6c1873d439ad388f93e32b548172907f5d9567faa074e87d691333a7aac150ecdec966861735ce3495a35295de2a1f0cc10fd0c2f21ba23e916ca574ef03d6750f481759fd8635229abc78a53e00512d6f8b19b4c14d52ff8a635771fefc9b1a5b4324a0197eea364c84ce80ee677d29b33c0b29c051a69a64c0159f4f6504e83642a944ca7cdf8b59b286d1b455216608e377001826b28809604c778ae67861c029b9ba29e3220b6fc933f8b61f2b42e609378be7c8881c634da6f0a94e4934e4f07c29103f210fbbfb0bf421bdef23aea2063bcac2130bb79aea770883ab59a31f5dc3853c46932e0a995008df33e442d412890bd7bb9f325e804bfee3f895316219b068bd2b9a98a48870571e8b280d559b98f65aa19dd3a420166da41dfa0919153b8083a1391a8420ecbc050e05be252d7969e234be3ef3b3d8bc656c9a491ea635ef145a3998bec370c6348a3557a5e77c90b158659f45e629eebb3c37cc04d53d9ba1b883ca432981d28232864a03150c250be507ca0c51b46f7eabc7045436940aa814a87c04aa6cc2ee286fa836503fa8aba170a048a16ea144403942a50d057caba0bea8030a502a7c1149c374433419477d234248bc6950e443f5a05440d941294285862a849208a505a50c95fc4089e0e31c39a04399827a830201c500b50be5024a071505a3eaa5cc0fa5230a1416d4978dca96a90231d40594c380020aaeb724d18ad281d5c23f016be3f8a1b0a138c628a007111df9131dd41128860418e1379494a284a4c287ea835285b28652840a0955084a9a516622d4025f00d597878291464d818ebc1929541dd4512818a7229260a29a9e00d53da8384e2f131631142f54e85039508a50d628d43d247d7917a09883aa4319a628604773f8a7d9035c010ad5e94363762baa27b51e2a1e5429943594289443a86441f5b1434d3f6a0a97180a83850d72b5a02650fea1ecc48a0aa30900090750e282d22121b8ad1005751e8a4ba174105cc63578bc8535fdacc5025eab84140c3540b0a6d0013c0c3c0c3c0c3c0cbcc6f05b5f6f81b59392dc721a74b7ed8a94924c292561435fe05d23ead62463f73bdf71c68110201e0cb80bfa0bc97fa79be1a42f8dc860b2d1ed2b5a86b3264fcd3e8b974d3e19ce369782eceacba7bf8fe16825e98d50fa6e449e2162485fa5bac6dd155b102161285abeddbfb9ad30184c269f5232af5f4857e5f6939b4d2c2f94c2dac4a86cf90d9d694248174ea28c1263922c29e9b3ee21840b0711bff2d2b6a5ba30846ce1a4ca72a689ae7922cf30d00d432b8468e1982989622af46757eb2c9c622c9d2566e577cd2a160ea2d4851c1367cd464342c81592a4512b292579ffd4e3878f045840040908e3478e629408b1c2419bb4194265fbabe6881052053042a87012b7d6d03e313aebc7a195f8248002092041c814701022853bf3a6eb9578400537524814ac98e5e11aab5b6367acaa58bd65a324f1fde4c7831028f8f019b48e1b31429e808010278084348101214c28214bf8e28ba680129210820405841ce1460e1e12100931828c9022d00821c248c8107ab80c7aecb0c1488810181012041f21401009f9418c101fdce8e121317ab18018bcf001126317213174418018b938400c5cc820d9f1052a408c5b0c20862d72f0904009ba07181250408c5a1820062d6ee4e02181ee0186040e10631647bbad5cb2ecd9fadeb238651a7162d63cc7e2a4d3c258c91963c0e26ce2a85dd4184e9e28478c579c644d759acee4d20a1d63b8e2787542dd89ca1373df569c362669c2ccce8a83ab858aab4c5ac531492ffdb9b157c53156bbc5743da7e22043f869bd1c15a7578d13b77c3fc5e954ac28fd2e99e26c2a66d5cde9371697e238278ec6f1b60b594a48716ead54423729e94aec519cf26aed9d8512511cd3e9cd1675d22aa81f8af3584a3e9e73725f30018541479a74820cb24f9c5d43a89a0df54c33f2c4e94c4c66269309a71a76e2284af40619cf2ac5b93971343516944c335dbbd9264ea997745965f7f14c6be2f8dfd597764f993856d6b5cc06cb73318c899345dd36179d26f478095b7dd3e86b7c2d718a2b61dab792124ee89538be89bdfb26b4a97f4b89633e5142c512f39b4ae7244ef96b848c3e394a968c248e966553d4204fda562812c7d3786d92ca42e2243e4e6fb691298ea53ce2204beeb5263994362d1d717eed50c285b71149e184d214e38411c79497517732b58893a4cedd546f58499122ce76f1aeab635252d29888630561ef279fb6681b1171d07dd2cd4f450f71b2cefd929f218e3164b0dc621b94743ec728c431c5ecaab132f680188438899c4b7e5d159a20c6208e594ae50ce5215fa617c4612f25bd52ea4b52720ac479fe0495c46c26409cbb7298505171d6c4f01fceae5942bacc96522aeb8793eed64c96d46aa850fb700c7629860fe750275b8a26e5d9d67b386e589c93517484c9a41e4e2a9c60a7c433d3da25461e0ee3ffa6577b6522d7dd430c3c1c4676952499b60b5dd522c61dce273f2ca9fba853326787834c52b42fc4a8c3319b6815aee45da9aabd10830ea7386aec92bc20da439ec3d1467583560995fa03a00d31e470de94ea2ee50bca9225d910230e470f93a127bb87c3c1a415a5b29a94ad4fe80da795bb64622ead777956371c4be3b987758f146dbf20461b4e3e2a53b37a5e75e513c460c3f92ae5acf39c57edae87d760c78d1d492d0931d6a08652afeff960359c8434fbfe531bb72b6ff0e805428c341c46259dddf9278ee3068f198081f40731d070fad4bb3452630c9bec1d5f84d13cce4a11629ce158f366c23365bc97fe7610c30c27db9069aa7b8e448c321cb3e799585f794cb8261331c8e0af066d0de78d1d694d8c319c046da2857a876edf3b0124b84002ce06001331c470b874b14b3ec19287186138552593a647e479bd976687186038c8d025fe626234a14e627ce128268516392969ceb9d010c30b87d33841975e4d196274e1a4498d88f4326f0b31b870d030cbce71530b31b67036f1f99aa6a74d430c2d9cd77c349f676d5a871e7018b48e8a91856312f57a7f2fc1c231a8a66416bee9fe5fe124948c68856ddbeb5638ca6617a159d7345d5c8573e5bf91bf6432c9cb5622061596cf12723f362b448c299c84675a9835bf4dfbc690c249849d9b1816339f92640d31a280d614ec4b5e06f1e9210614ce59ca4f58e62cd1fa7fc2498a124f480dd5a2bd13ceaa5d6b92b7dc750835e1a06dedb741c684e37d779fd85c9770aa24631096a4aa84532a1de369eac46f3c09a74db94db0cb7a75a341c229cca26d769897994738d655fef99fcd10151ae198d2a4cfb4d9d1722ac2d984d69215a32849c4478493a0ed94145eb5a4686c0827e95f2dc6f7c60c324238c85ef79d2649064d55108e1936be090b7217e3403826f1bd27c9f60f0e3265e46eeede9c148fe183ca5e3c77f9aab5799402082f4e729acc9736c9164ae9777152496ccdbfce33b3a78b5358d5b12433a836f15c1cd37b8392b44dd096797403082e8ebeb5e6961f2aa993bfc5f1f40926be456f8b539c3eb9c45a7e68cf6b71bc78d7bfdbfda3448816c71ca334bf8c7c9d209ac5512c9724bd085516272967d9f588b324f4589c32883349e7469fda0d8b63cdb5aae889d93df12b4e95f184678d1613d3bae2cef8d872d5d85a59aeebdbcfb7e76266405a710ad6fe75d29fb251a2ac48f6f3f452aeaee27cad954a529e497c9351c571dfa22649cc184f381527a1d552c508b159e3898ae3a7c656d2379792e814c73d395bcf32a3af5d60f030c5d9b64d10b17052c69e4a71de1df3d16eba72fa09290e2747baab998cc8dda338b8f56ce511252dc65f14c751e12767eaa138898cb14409c2773f934071526205b9a27c840e25c9270e5baeaf27d29497497be2604267d466131b4ddc4e1c542cc1cc349a8e4b27278ea3826a96d3d1e6336ee29c3199aa647a4426dd69e2681657b4786fbc90c9c461635cedef6224d02b8060e268635d7a4c1263b3e41b7a00b9c4f14b9c929672c5e8bdc401c41265032b71ae5831eebddbec2a6b6f00a1c4f1bff4d9aa6e8c26791287d98ebd91797d4b84247150666661b32363852f12270da122e52449302959402071be2f495e374994411e71d4f233a5e56a471cbe4756b0942985adb411892c0061c449459c57e650979466f0700a208b3865f0181d1126e8eeaf885338ad758d9a2d8971420790441c4d70f14b3f79a71d4a72f8d091a30706920d20883808bd5df3cb3fc8218e23e3c79a0ab3a7b3151e400c71f2db92e493d4840029c4d164fd7e67bc8a6b4a429c3745c989b831102083389790d77139d478be6b750710419c84be4aa6bd248daa012410a7d6d85751c28710d98100e2245f294d0d5d725394fc87a3b7a9abf7d869fcfc70f6df13ccf4d945bdf8dbbfe03e9c44598bfa7697f47c38add5c667d5c76b88f6700c6f7f299c708db1b21e0eea728c30f5b2b1b498879377f6cba6a9af4a1a1ece7beb279f92e3d3b45f209443c70d3602c81d8e16c25212f4891d0edb25a6bd82894100a9c3f976a3cd5e4c62c4bf7438892993924d9d26d994650ec7d4b5f946bc3a0091c3c9fe540a96a4f649d6e700240ec7932a645fc5b23fb9843f0081c3515bcb92e8f9fa746b3da0821b3b0079c3d94a3a719f11bae1381e2a6a87de32937d1b80b4e158e9424e1811b92909b2e114e37b9a6c25a625295c0390359cc4c57b11a7b34e124f7e80d10135eca6f2e4cb5269f20490341c4c8f9ed7bc98f66ddf00040d273942d8898ed228270d72066de3db9dc5cf2dd9042a903c691e2308c337a00410331c84c7bc8a9ecf3a35ef0029c349d29ab22973a9eb527fc1c3072064386e4c3d791ab3e5d77623b5f718c349dc52122b9e944426b5180eefa6ed301cedc4932d19e3fb26088663c9ebbba2fa4c73a69419902f7816fed6359cee85830927a5531f2ac48c8c43eb46fff8c25316902e5402e182816cc1d11b64cb584ab551440783065e81c44d50e660d0c0d38dc46bc03940b4808fda92b3842a1906c9c2a9e46bfca7664a25c6b1809fcc71a69604728593e0a519b4f2424eb641ac70709533cdbe79f4d703a9c2396d742931fa52695e3300a1c2397ee46e7f6f502a420399020552007b0091c2514de5a690a7329c64392880440141a060409e709c1f7dde279338e1e0a7cee6525ab7a46fc2b954fcf74dd9d43261c241b96b7d084f79d5d012cefb6f32bb353d474a3899b423df5a324cb2937012fdb891800e256e7884c349298949539794a5ad11ce76654289396611ce166efc4db60e8408e70d9592bbe8af30b54086704c5121b5dcd2a6280b88100e6f266727678bb4b08004e1e8699a4c5d5b5e250b0408e7329584d79eb3206f3b3380fce0a04d4fd8207bda47fa2b06101fd00001bd385c9cb8972c3de547f6e6b812451c5db64e5bf6e433f1449c479a8615257f051911228e3a5a53f3cc87f833ffbf8e3a0d71ec4bb12431d5f75bc58538989dce11258d96fb09713295cb729294549ecc200edf6ef194d8db4de30ae2941aff43a8a7e6d10371aa98de4369d025ff0c88739d74b751724913da3f68629d3a49bdaa7e2886d5a657cbf7e1342fdacbcce46eb10d1f8e2925e1f3196aa5fe3d1c4ea6c61e3131edaf87e3688ba25483998763cab76ab78887932475785aa6508289e21d4e62ee9e564ac45e06ed7012372aa8da8a52725f8753b95ad269321d0e9b64d51ce62735c8cce12493a4319f0e392da21c0ef795fd041f5d1c4e3197b525fe068753d41935694e2cf4b6371c2fb8c9b34135371cee82dbbc08f9734a6d386d0c1d42c492a706b1e1649ae7325ab3069364a574e58c51c349dc4ed1cda116734cc3418d0932a90d7ab91f1ace35b22f09d1a5ffac820118c875c6198ebba9f5ccb337c329df7f4b884a97e118c4f6f649db910dd7fc98418693fcc8df8653d2c8e833c6707093c41479f512934c22017f31430c872dd12fa47d29f35112868392849083e1706572c633e8d433f1174ef396c2d3d694a8fc7ae1bca2365b8c5d0b16db2e9cf2a9ab4b422c55902b170e6e972eff686c9b50b7704c8269ee93168e16fee40cbae6224a260bc7cb2dd6214c927a418985c3e593335e32c12b1c55533766fed878a1cdb0c2f14ec574976a6e4f4a8141034f4f727c318224c7173e24806346154e31fc44554aa3066650e1664c6186148e29cc25f78d8ac0868da4079a1185b20185b231e309c7a4abc12a2939e93489138e552233eda698269cc475be754be35e306fcc60c2d1334cf019bdafde2ce124376fc96a9e2be124eead28392b9b84d389595d7a47c324bd41c2d16445171944a7db664738da95cd6f9413e17de50c239ce4ff2e0dd7746bb22fc269fe74f8879c6710e1e4a7f263394ef8693386700adbd02a53ed3591cd10c2d12e2f6566bbc8309719cc08c229fb09af3cb9b30b6a201ced649254d0e6aba1a91b61f4f851b53ae3076dc6b4ada6cb4478337c702ea1deb4c9cef4b1931c327a71346da2867eff9c20c33090c18b4dc69e981e9f1dcf711785bf5cb770b151e2d01dc8d0c531a9660c2256ca44462e7420031746c62d8c0c5b9c8c5a60d2e250c62c5226e625597119b238858eee924d10df202316078bb2110519af281b26c31529a3152a831547d1cc71528f7e152725937057796230495a1507fdeda644349b12a9a7e27c52c51e2b99d4cf4942c5316d125de2c4985d3e39c5f1c24a4e97d027e90e99e2fc35325b55caa538dc76e90be51d26e94b8a9324f5c5dc33a32f532563146793929c3c5f2af5e4541447399dad8b86e2248c49298ee93f1d9501c5494f121372dffcc469c48d98913fca2fc913c7f0980b4254ca2515ecc4e9af644b5757d97a3a4e9cbe9454116d2a93691327155df45d4eae924913c7507af32f9864e2ac95ed7275895999990c4c1c6f446c3cc4c4a185a5f8031997389ed2ff291b543a51464947dff01e8dd22a09322c71d618476dc8d69b49171c5a3f7a64fde8b183c70d9c03322aa1051994388e4962853f2b41935c9ac4e13ff325f9e2a5d03a91c4a90495c932e990d192a0489ca410a1f1bf67489c9452578dbf5fbadf234ea2b22993a41819c7a28e38b59c1c952ac34daa1b71cc67a91b97648b6d9011e7101944a9ec4a614f16714a6542362e284910428a38bbfb693e593242454bc449989b5dea4d515d4abc06250719883806693adef24544e8ff10474db9e37653dc1087edaad07241fea6bf1027357fabe1cc4d893213e260a14b87c512467a9b83382541772788d3c66cd27f572aa36210901188a39ae41a535e5866d2017198f54cbf1a4b7f3805d9272a68f358bba81f4e524b6e58fff5ba12fb7050b294108bc9b23e3b3e1c4c12425cee893723af0bc8d8c3694399bc2a9333a3f87a38a696924fce8b537f277938a9db0a8def0c0fa75c67b6e57adfe1f8f67e9a5b254469db0ec7a89dfa9be2f11bd37538a79e5ce267291d4eb1194f12abbf94ace41c4e31eab59b698cf2262787a3ba995cb59652ba6d47461c50061c4e824ce71a9774df4b7ec331c9bea1728492a4d8991b8ed14c0a4a5e5fdb4b52340b32da8036d20532d870d25e524adab2bed69decf86204366cf8f8b1e30b1f3778a840c61a8eb92a251544e5f42c150e2d1d3b6ec860c70e1c377c80e14387fbd0b12399840c359cc258d9e6fd592979e330e8fa808c341cf44e973c272668a6ebd070ee102a46334b5972fc673848b14b16c2c424c9d99be164f28be9df6c327aef5886d36af2906b3227c359d6d45d478d9ed2f8184e6b1532ca26795f3a17c3e1f47fc99ff7cbc5a4301c4cbeec92d461d27d4e301ce47e59da52b96a495f38265db282ddafe8da0b276119e4a209b961f6eac241954aae29ed840b47b731e517cedec4bc6fe1985d56e4259d7a61624e0bc7d8f1dda64a948593943e7454a6b85cab61e17462f293929daf2961c62b9c7554efaebd6b676885f308cfd85eda648d96aec251535299d46bc68894a9709aeb6d0dba4e924ecf9bc231ae86d3545b0a27194fbf043db992dc71144e77e2d8bb26bde94350389a92b25a255fc2fbf484b359c8aea5efe7bc4e385aca373ac2849b707c53e97f847956d2960907a1922083bc25652ce1284226c164f4d2719570b2d4a7c418f1b414a449385ec7c9a1ff19241c63e6534a5ad125fc954738ee29691aee5b1d328c70eefd33496fbc5885b008a7169da765d46e8944388949afa4a45e1cc2e1e45d11b27df46a988470ac7539557f15a4ed1784b3bdfd2949e597328070ca3c61c359bff89bfce0985dfce4132a26c307a734aaa46f10ba92201bf6e27cb1f259acb14c6ae6c5c14cae6930fdaab6dd8d905d9c4cdc13970bca4bdcd2c5e1d4adeb069d35e9e72259d1543c0d42c4c541b6e4ac84b2d87ddfe2544adff908712d25a6cf16a754f2eacfb82585905a9ce40d268f494963c8b3d0c27fb714b6724284100ead1da97410328b624c28492a953be38d1da954b11c84c8e26c72536b8cdfb26bca589cc24bc95fe1f3f6bf344584c0e2244b4b98ed0a72ba24f942c82b4e552709524bace8ff12571cc65448d3d2f217c3a815c7cb52f2b76fcd0c61c549ccaa262adcc824a39219b28a739ec67f93bbcc4e5b9921aa38a9a0bee4528e35cd300e2d1dee63352415c7d438b732afd15031838a932555392ff3a8644a1e0b21a7b010539cd3b26bd29953d1245548294e5a5349766d416819178756a14059084248512a339527854771badabd51496b4f0811c5317ea549f1c2fbf7b9a1b044d5baecd5630801c5b93ceb6bf5d49229dd270edf77961574e589536c137599c5d489538956fc53279a6442ca89a3b6d8a7a816b5b0ea268e6a66caada47665dcef423471d0e7175a63a811777309219938fcc5322506952f5bd26500130725e88ba2366e54125726845ce2e4bb659ac184b3f091250e3289997c949efa7e4d48250edaaa4f977c499438569910359b439b0cf9240eb23646adcd9026b64512c79899652ec5ef955145e25871bd5a6b21deda42e2a84955cb44dd421e710ca7929f12375f100d0a71c4b124c9ad47a9346faf6821a411674b932e8e1e95c41425440823421671122a1a4b5b4af5214411e7adbc55d2b88969e14fc44169af495d51d25cf21171589d5359a93728fd0f714c3eeea5fcadb75437c4f9d72fe8bb90a352c60b7112e51973fc5eab4c27c4595d5390fdd1204ec2289d494f4a75b926419cc74d98d07da7c5bd241027252f3bf52f0810a79196ad77d2fd87530575b5184ed80fe7f76fb90f47113fa74bd2a499277c38c929b197f12fcfc5ba879358527cdd6e3e1199eae1142a2649de93bdd2a7260f271753a92441dbc53a251e8e9a19e3d5fdfb2ebb3b9c72494bc147ff0429dae1a44f87e9b2a4245183753886d99467635aef53293a9c32689d92db672b49a9399cfa4d89b09cdf9b22391cfbd2ef266d1ccead9a5469ca2428d7e070cedfd7b5b0142784bce1f45eba9b544c97e243881b4e82d62ec1d2a6d686639b924d5852ed26ad091b0e525499182fe9a438416b38e6d64d6ee2494a4cbeaae1dc2595c98c27e88cc6a4e1e0597ae9ef2fc96329888653aa39f155dbb476f567386d6712b62e0b6f05914e1ccd7c2e5c2c498416dd8df2c1893ac36c55860d63a94fb693566311d9c4b1d65489dcd17a38da0102535527a2895338b9cf8b31eef59c5420928993ca1c716d62161367d319d467cacb23c3e5126c65c8e68a19162aa7556dd2a6d9c9124b1cec4fce64492cc38445011b3652258e490ca7f72e99b0b8900825ce77b2fb42a725a5fb9fc431096a7179fdbf748924715216b56263fcd6201289a3cd997adb4a0b4a5e20711c79aa95d1ca45c99b720491471c6b2b5b9d6ec54ba3b76103dd487484e1a30f0f228e38c9ab5f3ae496cca87a3b0e09ecb840a98248238e61525ffeb9328f13144109b606960511469c2449d4bb933fa5164cb420b28873ec95d0d64c1763fc611051c4b1ba553657dcba1126151049c45934fbe64a7ea54e6d2c20828853e6492b49677583c8214e3b5ae285acf01c211331c429ddc9209377dc8de614d83d8814e2ec7be286d037a6760c941221c44950d56e620eed7731228338ba6f7f49aafb640c2311411c932513436a59d81f51200ed23de544c5cc934407045b61a52d17e3729689e3bdeba34933227f28beba6c6ce74609227e385da637adda76d5ab44fa70fa1e51e93474113e1cc6362bb28783e6d5a062f82da2877389de25624f588d9f2092877328b1fb6ab4365db33d7a8041011ffe238c0988e0e1a01f3bdfae5da20681c1e307181f10b983a3779390268678276207e35296c668bc752671574609e1e9e996481d2c5f20428783ae590927f3d75e12cde1f0a72797ef5ec92eaf1c4ee9cd3eb63e2e25492c0ea7144aca63a5750944e07078d7d217cbed1e3dfa46183c76f4f8612220f286b3ac25ed6f69f9d62ca9c70e1b140788b8e15c9782dedc7ba5b2323a7270253974ec9881ebe8c0f2f1c881acda70740b534acca14a7b8838b44c8e40840d27b1a0b2d724656b26470191351c4ee48fb89d520d65c3072269386c4a828db69ff9fb2893208286636c5812f742346f7f86a36c4c19d24d2c647d331c94fc6399f57b198e7a965f4e4e86835d9a25a9f263a804fdde8be1342336afcb9b84e118362c659aa4d45d9380e198ed929825e78299fe0b471116f3a88b5b5298c80b2739b3ef56564cf242d485834aaa7d440815e35c10170e72426feb890d426cbd8553ee8b15ed9fb5708ecfbea0794de63ecec2d9aa66849e60318ebd583846edbdd826c65ce1609b4f37c64726edad70d20e533209919ea7548593a024373bc9eead4ca870fa0ad2ef24dd14cef3169392243d37574ae19479a34bc5142d13330a0811c264b6781a14ce579ba54ef31282c8138efb654297249fcc31613078b4e330c3e1030c1ea82307094c9940c409e7abb85ad3133a4396dc40a40965224cc0945ce9c4af33e1b75b104496000511258824010e224838fe9fd4924da92247388cee0a7e3165a5988d88114e25ac6b30b12f7fa62852848368da28b123b3f97c224438e705a971d4ca6d6e26328493b97768e6b4cefb45847092826f0af55d99428804e15057494f4efd0008420408c778e9deae528ed0634283c80f4e7d79624c983b51fa7407111f9c2fa539d77eadec73eac579e3d2f6976cfe579817a77c9b2b31a8d40f25ba8b838a5bbf76caa28b735b66abf8a726f58cb93889fbee33b619cf81062eb8b1ed0d6255738b63d46b51aa81862d0e7b29f32fc5d5d6383b8d5a1c4c499746e74b7068dd585a1c3ca46d4cf174f6aa2da0318bea2efba6218ba357d4dca7a6624b5e38b46271382162297be9607110aa275d997768fe8d1568bce294d557d46778880d255a051aae385edfea6dedcce8f85a71d06f9a7e32bfc6c5c23458711619724f6d2fda896cd6061aab388bc56f984a17a67e0160113454714e3b29a7c40fcd82462a4ec25ecab198beed290a12408104742001141881bb0592177b050d541cfc2f883db595439da4536c592263929220ed030d539cddcdb2ff746fe8f94a021aa5389f9c10a1ae46a87b6b1240820b981d3448913446714cf37679936c553f12c5497e2d2fedf586109a509c36599bb809e5795296a7400314a79823456d18a9993727051a9f38988ccb6d6936186878e2d83f9e498456acd3249d38a9682253d85bbb40831327cd944569eeaf8fcb8b011a9b38888b266a1976f4d4a46968e22045f3b2ab48bbd584804626ce16ec357ebe9c65c5e0d0bac2b32a5ca08189537b49216b62c25bf6df40e312a796d5caa412c6173c78488002c8061a9638b6c91e27a54a57e224e8931694e53e49bb4f89938cde922e9dc885e627716ebf95134ca95152ee25718a17d7942c3312e790532657c6c40e1d1247dd5259a2660559a3479c5f56534cfe3b49aeee8836f4ac8d3849b99ac94b50aade74461c6553a9249c588289992fe278faaa64f4bbba542be23896ab25369a88c3d68ee90a27c7a69884889367300de2ea748893123b756fccf42d9718e2ec7f52bac8545288832cbdde259445d59c10671117b48d88d1208e29e98d26fbdb823849c2d41f88f3ceb82929693625981810c73f532658b75cdc10ffe19c7da546a858daf4cc7e38e6926485d50c2a73e63e1c4b7ddea859c698cc7c3889b9ca7f438c864e790fa7b393176652e4a48ef570122be97ca5c67938566fbe1326b53f2f8c87934cd9c43431ad294169ef70d81846ce6f543135ad1d8e9fc96383c595caded6e120e6fbdf3aefe29dd0e1a0324fb693678495c91c8ea74f2bb7e75653ad72389f2432c6cdbcff4d8dc3c94db69cbf673a9b53389c9409327359960a27fe86c3a95c255a7ed12dbb1b0eb24f86539994b03a9b361c2d9fec972c0d1bce27d67729d62788cbace1d89616a4c8d9aedba9869314c2ca7cdc4cc33157e85baabef954130d87cb7c0bd3d326b79867389768a5bc3a13d379698693a437c725e526a36f2cc339445a69855e0fad41329cb562700cc7f4dba1455cc9df11c5708ca94ea6129a477ec3309cd7acc25bdc92e4c9c170ca28aaa35d7fb6e9fbc261348fbe88fab9fbce0b4753539ea55a4b8eebba704c4b4a2b639c0ba7d85af146658c4187b670da12be722af246d5c229bdd7c9d4380b886860e12496b0f738d1a490cfae704c1f91f77bad70b014c49c9242e3e4b40ae7f4d1f535278fd09ba2c2490ca6d24f89214bdea7703051e28dcc5993cd2485479cb2a3700aa24d5226097a414942e16892dafab2f86592ece1d0da018d27200d279c4275c9d41099a5d484d39e74528ad6a299a92ffa3e408309878b9ee167f4a464a65fc239479dc6fd0be58d8086124e5a930aa116f65d2b1a8d241cd42951bb447b536a5fe3020d241c2c5c904189e9eb04a1be8e1c73a071847389d9d86cb5b3146ed6020d2324996e50f24b568453ae7759a04184f38fa818f51a76bff5211c4c4c9ac95e935a4cad10d0068d209c3fae2e05792a69c56c8170fe50fa951b542bd0f881d2f0c149da8d712566b393cbeec5b94c0c9769d3eb4c569b308317e7502264aab173d1a164176793bc33d98f9952717a60862e8efda5c47e66352317877d93999db79f3aef1a66e0e2f49bda5ee55b42cdab72c48c5b9cc346cd4e922ec9f861b80c6c711254903aa7c4511466d462062d8e63e9265bcc75799235631647ad9437c96ebf0e9d093364e15c8c6cd6120eadb2b21ecc88c541663e4197781345e76d8098018bb3c95ca7fd9cd8622f1e66bce2787d4a8e5e2ef7d363192566b8e214fd845dca26038719ad38e9d08b393356e9fb920c248002174800051260810450a0021478c20c569cff2bede688a8b8cbafe268977574989456c5b96413a5c22525726c4ec529c489913174892a4a507194135a6562b412ad36a738dca91242e7c446d7678af3baa612f35233e92dc549b2b02f49fc2e5e8c016106294ed2badfdf4be53f3ae5483a0831631495567c7a590575f50c519c4fd4ec19b494b878e342714cc29b985c33994a82491a6106284e1a4df6a4b45b25a22f333e714c27c3e74f9e24cf9e78624627ea8a99522ad36ce10c4e1c2d891964e9fd450e1c36b8f1c3878e1c37ca6c942dccd8c47184499eb39a63b356ca83199a385aba4c7237ce9fc8993896854a55c943835233073330712a154c87b849f266b57018332e713a61749ca0f5364949de12a7be38595182be12a7f9f250416cb08aef53e2705dea435bac5ca1fc499ce46613f67a2ce55b5e1227a5ff4f6b5bc921bf47e254635a6f846512cd3b24ce7d62ae53f1f48883561096b1b5e684d611c7943b679474a1bebed4889358512b31883e49c932e25832a69d1e8b27bfb988c3c60ce2a42447013aa8110903891a8fa8e188c25eab94891e9b84387402351ab1e6388b33370deba9d964c431541239eb954aec8b2fe2a8e1c5746525257fd28a38a5a4eee524f9c37abe2f78cc2003614cc0878f06810d2ed448c429255b8bb75063f3066a20e2f09a84598c252fd4fb30d091030630d8f1c5214e6b9e41cf48374bcfc018e2a0f4e57f5b8ec829698f472ec431c3e3445b4a4a053311e298417598ac27e4d4c63e06713c5139abfd7d622c95200e7add9a25ee2910e7ac122f4c8d0a204e23d45f57102daafcfcc329832e25dab3b6aec353c30fc753fa9af22e093a2add0794529b6b6b773e9cd4550af625842895d31e4e9f5682cc392a7a38961494247352b01274491e4ef79924d9f4d5783868bddc3a2a9ad224b61a77389efeb9f5971aed33d5b0c3e9448eb693bd7352ccd5e1bcf62ad294ae32d5930ea7249ca45345ba7bc8880835e6700c2d793cf3043b50430e0779c1355a8baa18f7c58ac3b954c6ec19aa44cbade4076ac0e19cfa1de24de57ee8d0408d371c84d05dd1dd844d36273e72cc0077e4b8c1030335dc7038d5b96f8d23ede42c478f1fd886f36d9a9cffd00fb31236e0277885ffafe7630de7927f67d46531498a26351c359f567d5e821a693845bf245c4c5b25a678a7a0061a8e194be56dc8523f6126418d331ccce392b658cba562d69ca086198ee75a294bc96a198e711ac4c9df6b5b4a8f43ab47fb17499699a006194e2966d324d6af75eb35c6703e7d73217bbaf25b16c331c6bfb56ee438b44c89a046184e15564a122e78a90618ce779abdf4b823c70d1e3ed2032ab801821a5f38a628623bb737c96abaf5c2a94d43af94d4e4f8c70c58c00233f0d136b06123e9ef6155a8d18544488d21d4a553971a5c782e54d43426a94a7276a8b1053559b07497d9ca9221ff4343877ea5530d2d1c43c52e196cc4accde80b307cb8087c18a146160e66da322c9c921884ae70cc642ba74fbacd096a2b1c7458dccec85d88ef6b54e11432bf84a967266da94185e39cf725b9f3d891f838b7408d29b0b9daa4134d504a56a570523297b8fe8e9d5c6314d4ae2cd364ea6261779498a5aa5ff4613250030ae74a917bc2ecfbfa48478d279c2c86975cb06c27aeafe184b3977052be3b599f6bd284b369686bb56e9b4929359870ccf4ffa6840b6b2ce16a28e120b7e54f9bdc24e1a4d64f161bd991df29120e62a6bf76d2f78db0d438c24196b4a6994dca1a646c831a463865c63a1993248643eb4672f7018218d428c2b13263be9ad0307aca1a4438e93a7994e8cd689f748d211cffcdbdc469b84abdd510c249d8c9d52f26dfc9bfd408c2c1fa4dad2ee636f92c37700cd8b0916ee038921a403809fb7fbdbf6992528fc47ddcc8a123c70c6edc483d1a470d6afce006357c70502d7ac562c6d0482fac8c2de39acd5466478dfa6db40d4ae4115e74994f124a54a423bb389b725162bd7d26d1c446747190b9bfbaa48faad3542e4eb2829f496b827071aa6849c96db5984349e98dbac539de2a67909a4749927810466c716eb9b4162c5932b14e72f428c1d5e2789a84ccacab7fa2295a9c2fc66432ba9f0a9e269b3e7cec8e1f3cc2e89198068ccce2b45956c5644daac0882cd6182dc7c6aa378391589c334e7c050dd9082c4e316e099a4eb538b432478f1294cad1038caa579cac34d9eeeae5bcdbb8e2a0aebd2faa7b53beba152729ec53b7b76585e29ab265cdaa99524ecb94e9346cd9ffebb58a9310ff71b97eaf52d8570923aa38e778e80c5b49c52e2537cac78f1d5ff8d84ac5794ebcc537e9c295d451c1c9dd33257fe736728aa39ad68abbdc7a82a6ba0718ad35628ae366d8c8f2ed36b1547230528a8352369b4de80b323525c569436a0893d447b855a3d862c5cc62148d37cb606521da5e3305b15814471531192cb67b7e9884e2f8a124415d2c061447dd3436f27e64d86a90235d0578ad183f711ab526260fb3dc0c9d27d26f72eeae67d490ed4827d4ba3cd912e5c499dadeb131a69cf15d83164d264ed8c84736714ce209b749d4ac49959a38e6b216e1d926ef043b13a78d35b599ef1dc1c44929cbe43dfa040b5f73a01e0e021b239738a65d32555e9a844d415718b1c4f975f358f0ebd3397b04366c8c54e2a464e89c49a6b561e30625ce26caa619319777b1f43b7ca055360e1fc61a870ff4800a6ed4c8244c121689b201896392fa43b79494c9c4fe11a7f7f11675c977c4c9b4dbc458b269f89f6f06a711672b49852e8d1bad4ab911461ce48b8aa24fccaf8a741147713f49ca206b192c56c4f9567448032389388eaedf37d9acec328f20c24af9ca6ef1221b634cedd0adb57164a608953074b4c131728893051d61a352d6cb340f43478f18e22cd723bc62ca264bda238538b768cda254ccbc1b5b11e29437459b2abf283b4aeee37464107c86d1bd0daffafadfc07108e2248b92f292db6fec132a550271b22db1b96d2ce6d2520c1027932fb4040d5979f7f8e14304366ca4f61e3946fe700a5a4d99c9bde8a54dd80fc9e8af9a2d89436bc70f5cc1481f8aa96aa16a1556bb1b2a5bc9ff3ffbefb821024f727c3102e6c36953baea06dbd125c5ab3d9cdaa424fe9a98a9e6be8e1d3e3430a2875392cdfdc48cb9551ac9c3c144c5a89ecccba067502af1605a4c51cdad552d7b575bf725717346eaf5c806237738889324597d64ae92e477c40ea7b0b14946ea706c9539b96f2a339a1aa143cda1e45036e2208211389cf2faee47936a1a69f2c81b0e6233c5d4e66e734ac9881b4e42a689325e623defde91c305236d38c9117132265fa8dced081b0e731a2633d69da9f846d66089c7a88a5bd81c27987e689e236a38a5d025dc995c295ede341c46be26d952759f5cd6172368388bde247b09736530728653cc5eb32284f64cf2d9c37d781a31c3c9ae6289936ee22921438691329c37998556c88993517becb0800c76ece080d508198e269b84c824063fe03a3e408291319c84af18bb4f3eb1af76311c4e49dd9ac4552b80e3478e138c84e1182764f6ba7c3bb629aea304291801c3a9e470d3263469991c8f7ce118b3f4578a51f6c2713479a8d19c49d5851918e9c2c92b99302ae54e3931c785c3ee2949d29a9298749243c70e1d9df4e8088c6ce158d285dd68add778a7fe1dc98d30d08d1b9e72d42047aaf3d1a33930a285938a3aa22fffa249311ac9c229c9af214b581b0ba7d24b1d939ff73d71327285837789a1ae376a4a36e6681e61f8066cd8f01186cbc0868d1eb1c2f9a45891d9a78ee67103373974e4e8c0e10346aa700c9f9a7e272f53ad04092354389924643441ac4952863f8563e91242090dd62b2a4ae17827f6eff72b460d8f44414bf175c4d658aa387e34086cd8c0f1a379d8b011c60f1c8c40e1a04f08b5b65fc92d4f607ce13d78e88e3ce16c41e84da2e491de297b8f1b36701da62630e28483a8a0dd4bdcedd3a282e347830071fc681e18c60fc391261c53f40ca5fddd8d1e3b6ee8e8e119d0eae1eb81914326ff8d7631b31d8c2ce12426493c49be8d49cfc71125246a262e1635662b7c653c39257f89b5ff175f309284b3851a71a54a5ff492e4c60c72f4f8b1653d7ef8b80d8c20e194a2ac4fa86cc24e8c39c2f94ff0ccfca67baf400d468c701ebdb5f2a5d265924dae44b0234538c9944ece247a34b72911e1d475992b5bd648bdecc8100e634a9652fd18bdee47847050f2b2a5f30c6f7e4123414063581655d1f6acdcf0da3713fa74be19f4d8618119f4d8f12340387a29d1cc92a969515312467e70b63c7ec9f29c2a9f99c7880f4ee326bc44f7b1d27f2f4e420525e58d954fca29e2c52934c5246227d6786fbb38e687aada12b6b1f53505862e0e234c5ed5cbba6d3bba1888e4e224e61273c927c5b3caf88b1d3b507e21828bb3c9957aae2bdfc4bb7c7cc16306396420728b73b9c5e88769bd92d2b638965231cba9b42eb9c95a2c321a6b31ba67ae4e1753154af01c4df79e312dce9bc4880b6a8e1b3f7c80d1e3868f1c5b3ebec8f1038c599cb28636a5629541e8b2389990dd68578ac5b9bcede4cf9ec0e274b289e59254c5a0ab7cc549255569d62c64bdd2ae3857b02053bd4b122686455a715a2d35355d41d85c4e841507213c4e1ad5da2a4e629960f199cec2e546441507d3dcd224369c8aa3659017d542c5296e8fb6cf5ed327faa7389bf5a87dcf9452c952c41407932b46b7694a2a6949a414274d1fba5a92201c5a689e0122a438c970f52ada2cc6ced53e7ce4f8a1a367b061fcf8e13d781830c2e871a338669149bcbd3349da538ae2944c5b8993d4289129138a32672e8b29dddb3b332e7a97d62f417112df6431b9c4a4cd3f0d887ce2e0dbb9d94b54ba49a727d47879934bda2216b534abbb942429098d93a8940f6552692c120ac3e1803810c5202173013313000000101a114662b150401ea8d2be03140003542c1e3e2c2e2a261e16181a1a89c6a17030140885036140280c0c03038160402c345192787e1fb88258bdb9d9d51e0788e5ac16b7da2acc537bd79ffbb4d115c78615e8ab53a37097904e53990a77a5f551d02cd219f5c7c397ee42c80c71a5b4e9f4b81acbe3d205306016d55ff3af84c6ac6894ac997b1b186cd0ab1600ef39a3a9301b3b422a33a72d2c20aa1790aea4671ec5d0fa9319e3738152888b4b8dbd01513c059d207a940ab256918e73644241f8e6d6e8d700e8860b718f9b7986b832b12d8308d72053846801a107a529cdf9190f2156595ba605532e75853742acbf9284c2c7a516ea1060225c16966a219d004be7c275229040125a332fbec6b1a9b2a1541d4327e165ef948d13d0b9162be87405be10d489a5e7efdb02b5afb1da35a68e731e86de11cad0721225e4e506e36661deb43c98966b2180ad47715db4d457364dd7f914f1b33ec53e70703afec8a628014555ea00f70607c727900cadb18639ea50554989097b0a463d01c2ea646e1650ed15dc969123d2810054f44838a58a6d85a8b57550acbe9b7c82ae5a819e4c90c6001e879bf5cfa874d163c5d32093c87bb17234ebe5eda2e9793732b51c5d8ca2d62aebc8231fe76ca8488368e537733be7d275cc429345674819a50a5ca082a970c17d85837ad2dec9dcefc218dea9c078eaf4ed3832903d2e2f9d0b499d9d0efbe44dc25cb2cdb517b68507fa2c0a9eca8e3b3310869df3eb0115a245c86285bb12f0fd48fc44d9532080d4e6557a2ac5c0f23e40cef93da0ea68b71cc1f27adfa3a059bd365f77c96dae245119d36987a1cde5a4c986ed8160280378536fe124a1b4b5894503d955885a4986835bd028cffae19646e6d72af0c04a4f4ebb6a0a532a5ba4881dcf40c2e6a6d58cc1bc8f27ebc32573e284c77f8231d91d2c8ca91b06e102f4b615b97460717a463cfa0da946a2015423bc263d8df7153808d2b535e2081502c3d9d0a87f150dabf5bd7903d524d26de03dda00797df10af4dd8ae761a377656b00ac9bc22f2ac1a467a47d03191f2476c5209980d23485b4b74d3967204ae469a55cbfb0e42ded4ea83c0fd18cc1d78d7c3ca63eab13c20afee096a4a0a80b71bc291b61192c4d6dcd3a63f758bef4c28eabce4e43bb3834e7d7cd07d148858739baeaebffa2a6dafc6c3e387d6a831c18416eae3e296034173441718a29808416bcd170bc2c267473c46177db2f205a99085e239666b8335553c1385bd67399515a30c527271b5b874f9e3b2b9e0d2050118545dd7a508dab10883d70216080717c6c141379cdf351e09a8cd5ac46c3295eec302cf2f1fe81c3ec1ec351eb754642e3de6bbfc8c9e92fbeb13a4c7d7919534c3fca013bf1177241f6b0c41680322b146481ec21b7063b25c1829bf906d67851bd3a9d70e835133dadd4fd4e62c1dcc0f20b3faff2d6e8c0e74e4259870f3af15d5ca21d7bc583acd37503e3efe1d2c688f5352a8c7330375279978372c611d076810e3f602405ba244a8153866d0236097c2f591dd325a30a8834a98328f01717c57af23284cfb0d0d7d86e524c0f93abb0e254ebfc78a95bbe16c38e597be489378ddb98467c24ab37b5fbac5ba5f779521755f10df615987643e9a204a7d4495cc471941d01615e81b93094b845f144965f55184a302f941c1cb57656920a33147ac9037b75ff53e2eb73e1fe2d1d68c1a661bbd8e81ed0e26f3ec07aee8bab02c54148c422f0528ac4e410affcae616052f918378ae424e1f5ee8c93ad12883a774179472a12cd11c5071cc44bc32053e5dbd5bc6d5b5613997b78a4e23d879a1a1e616768e197b705ed623ca6181ba98769d6627ed0f5e3e745147c0304bcf06e96098709c0cb05cba1656618f139308e48c21ac3c8565b2ff0517e9b104d4a10ff6452966d81b85e14e4996025489561a3498c3d8233d0f4a913b738321e48593857072d4f41775c0ab01be9dc2d1c5ad2a3b14cbb9b83fbffd51718d0ce419dab4d718b96a9c917d825199ce5dc29bbafb2251498182a287e45b2ee61aa2488f7bb97297beed00e091c6bcfa1d3fcf927f3085c13e06c4371db9b5e39a49c36dd92a23b502a5e6c291ff700d36ddaf1f1245a824307654817d15b3c7e8435bffc8386ba95099b8802c73622f0664b6cf946a56bc436d1115cab536e05d681e1f06c5d898f915dbdb4246e76df085bb7341907123df55fda13d1612343285ff48bd946acf458b2799225470d856dc63a2b1ee921cf273d5cd1a1702895e4dca292bd87071f0e2459892b59893392e4e325309b242a74f8e7fcb501f7dee3405a1b987dcc7101bb9eb0de138106f9bb35724ca56918b69f082de6dec9bf16b69b0cb8c6eb5e996824f251a4607771788ea2e60409dc8d0b29321f6f2e6a1597f776c3c981c6ac3fbfd9a20a94fd705c53f5109c1000b75b71ababfe400188d756b14aca320b5911492135419bd2dbef365e331047d20d64c1609f4e7a9f27fc388b69839a2881a73035d351f72ac70d7741f7c92a13297034beb044ab56180c9248deee58029995d428b5bbbe8d279bafcd331abb5c63c2076831836cdc310f059abc0f3c4bce1f85323f3da00b7dabcd2012307d71fdb40b97a996b867faef1ff375344b2d2db996468086b77d42122153e30a3576eb0de4af2c674aafab70b19c80aeb0cff6fec0e15d21cb2a8ff1b9737d3c9f098b78a0ff817e323531797e20370e629c370764dd10bd29a8fb3324872641170050270bbc00c29b9e94e2df334d20f0b5c31e342130d56c4a05f22868d41f54d0feff5a3b714f381578e3e02b60d48addc8306a83cd6ec0256e006d0812ab80e15c7179ae43a520e862c9acdf02829b68519c3a34d0c7a50b0a907d66e03ad5fa909611239b2711b5e76d24a1deff491a61c5ebfb209fb5cbf5f76730d6b4c423561e21c820477c78736687ad7c357f42eb5e5ebd52192e4e62f9d322cca060dc3cef84779a9d53d1f42631b45b83860cccc91f2f69c81d38a45f45182826fb80e00e17fdce3c4d4e79574bc7b3f25d9c4301a4e3ad208381126182bf568f06ad48fce90eb81790e0c07e2f5cb69c9b1980396f8774ad007bdb812434b880dea675b611344e1f67e3058364c98701d496c7b3dc8a267685e96dc1754c4597f3eaf91198b6fef5f404fc329468222d368b46a10b5110c0edf5b8cda082b93475c41eb14a416b060c199a592baffabed64697a84f2f70921284525a8f29582f175fad85878439e798fab6c621874c74de2965cb4b4e46077c7ed1957952eb7e6004e79cf011ee70bb4fb208f76bbd222cc44c0f8c1a9526766246403013a093589b321c36d436f4c3b92c524be9cf312d8d45313250130314b0c05299b0a69dc5c44cad3a19e8b50ae4d51a69f62a69e99f7fd2bf82d233a41427dd261722f8f049b1e9e6be2e9c246149202612ab31105a7183939f9de8bff4405173c8f507227af3454a8429333d4968a6093e51e62c83d8fb2db80160bef88db651f5e2b678dbd70b13c3cacde4851dfcef50c2ce4a617b1a3dafa949a650848c46d0d101aff21ba775eb51bbf7482ab0c3e9558a8dac958bfe8af96883cc3258160b30a7a29a6cfcd6797a6b1d86a7e4ae78561134042e314a9a1866ef91e0b80f0da8ea02a01be7ef68e005612c0397a09796f51795705e579bf5aee64e700da93125e1b92a23dd899476481981044116fda30c57a2fe2da9004a6c7f2f853e8ac688869104c295131cce11889dff4f6e1419acc41431cf8f2f3667a4ac8737407ac1428e7a39007ac10a9292f28e1d54d75adb6f46e934ade47f4f054e8fe48c2e2b2a01e90dcac7c18e158ba99b68f8c3c65b3ce544380e2a1a87b3473e4808da7d4249f53514b28e132a02d612f258f618144e22b74217c75bc05cb7980676d00e8b034dc21fcf102b3c6ef4f81afa023f0c29afadffc511f3fd4a0b186dd8cdf92fd6f323a7b26e4199f0b9c4e8bc71e91a62ec199d26f6fa1b26f3cc76fd373b4d60c20998a649b724b9bd4d23bf779455c86b8d085938de0af0a768879113ed7ce6039d2788c473b553f60fe6b125416196249666a946ac465ac779c15e0f8eaa2387c66a4f57ea8a1fed6a98c9b59f2b72f8716e88bde3671f86e2d5b18cc54ab66498b6db860f0c03adff7182ccfcb23b171ae94f9ff4def57bd3d8ad66c88f14078f4b9a6e6b1e4cd9c1e93ef644bad9a23dcd0389af7e52948f11f809000768a1aae3fce8274ea12bf0a99e93408918aa7d8847c8733e7d2e34f0a1151e434edb4662b37d86169b0f28d63a0367cff8e786c9562983afb726975ea176c6060979d3364ac2b68736cce99c600d637241cb3e31ef6766f3f718c3fd7998e16b946d5e885587d5992ec3198a209644f5133ec6e33353636e3b941ef99b62a49ade662dcd7eb67c478b3e39a2e0ee4a986fc208434eb0e208bb012e6b108df7a6191dee5a9a2c33b475bb3cb0a47c8e8c53e3bb00c74b4e2d433c7040bbb42fa687a35be4b2a6143819206597f3f35b2df7a7134c4abd50cea5908398b8136e80355ec804f3f301865375ec58eb32f5472e9ecdcc9854916396d324cbe73d18c96dc2b780c482fd861635006ada2907540d62634c954b5c8839e690a2a490359736c50adac4cad684e6c58b8b3d05a25ed85d2611edd4a8164aba8e6686291606dccc7c7b9c6100799ef6debd0e0dafb2828c75c1bbaca836404956c33c93b5378dc1192ad4da086d7ac0a04c4af2e3799dc08210ee508a8c9a36208fdcce3ed6d92ea0c715fc659197a88cd42019e37d249b19b8bf22c673fd53e316b62fd26cf0d33027220e100919ae32d4120888fde150183c7a580c88d701b790aa38a20277a0cf3807c24b5ed49bd5d01fdc9d18fb0adc291a759d8b5a1215166d2ed62b885113d645fc7ba15e0b74e1d0e3f200305055eecedd5d3eb2c96b86c5a90785cba4663a34e1cadc7cee76bafa9b0ecdbfe21cf1e0178a787072366d698ab34037815c474b9ab2422f371784e79755653817ba4be5b7e7d079952630f4eef1a19eb7ba446690cace5ae77515017d14b9997f8b233d748ba3232e6e19f116a72f03f288d80ab6315e40451a7831ce437cd3cb70d8dca3e8f00dce0f62e3685455c59404c757d2fb1b1ad79954601808a008d56ad252be78c8d49c00a48978e417a1310a36ce32d97d84619dcba3f4b8d20cbba9782ae9638415783c64b5540ab5cae068325726a86c5d2ec407852c6d5164e69893ea14ef0a10c4ba2a2f2112386dabada51b721ff360c128182f14e4ed670d6610ae1c309256166c978d80a155e0b1ec96a2ca7b2e251fa8c2e4922bfb7e6dacee54d2bc5ccc5bc9c005e31e1cc604abb0df40142509a96ce6114aa10eee9c7be54b781da8aab18ba35d248585b001f3416f21f1fc2ec5c76c74476f9171b476542292e26c1968af7bd1cdf5c7fb0c3cba9b6228304badf6b35e5ec2d78a0dfe10ec8320c67de160b98200e05e4e8c910acc82f48c1375195924181d955351323a4a6bd50c7dd3852d1a6191e8c0ee44ba24a8aadabb5edfdb9eb9f065b8c37b6d0c28a2f81f81177797caf3461682ff1148a51f4551de63b84aa264aa7c89292bee32f5a73a8341af9f10d58396b24c5da9a3372a9b976dfb01407d22bec6a5400a131562faf59079a5a72805c343a7e7c9e17c22b8fa5bdb1176c4ca4680445fce3b680e7540257d9dc4b46b5c3a6a53355a2721ea23608248914507f12fc3e51d3c1267d8425a630b59f1617202f759084d2abd94d04e58db5324b66166d6d48dd2201faca3dc32d940b4f822dcd8ae3571647b44d501e12da2c60b21569e4f76193d3a6b788032288635f5fd169a2823c6206325827b95eebec298ac95015a98c3a6bc4002770ebd5a080da986222d89995d87c0e9c2e2c714574913c9c53a20e298a3f494236ad47e1086085334a70809bb8c2dff9253703c832d193ae3a798ca219e09b81a36957fc27a2bbf5552c014c19a65736919de300d55a0ab580ed161e2befcd4223914bf0c99031842512f0fef4b8602c37f6095ead567ec763eff3f93460ce13978b17205464ef2ab58da49ead1f1bc1fbc3e32fd0737e8bdef60f93485f667d4a1653b98db5e11f970756788ab7889c948c55c2280995d01be04e504ba0bad7dcebd41526b8b4a5da013ec7a5a2442be1cf16d3d1db9cc466aab80e4b8c4dc677cbeb91492060e98444b697b4949187287d94ad95bc90674e6c100d3f696345bd55ea17575e95df110a06d16dd3c8ecc2e495c1a76dac732bf9877ad5d5abc549ff80836372a8f70f504050f1aa86a70afa7424c2491190bffcb556fa59f66f76f2501a8fdb25a2769b3dcf33941623c2a269419754a31a1cca8530ae7d8167eb7939b3a9d9d62a35be9ec5c6cecad78768aa56ecbce8ec68edf92e69b977e04ace529cfa1ef0e1681b72614940aad4aa7a05440ab4192002cfd020f64b0aa92aec64e8951d3157555d1bcfa3c155ebc2dcba3505f75ef28db93758d1f53c78d9281f8198d20d51623cbc09b7f4f137749bcf0d8b493e071691e6973855b6a59baeb9a2bfe0bdbd5f97730ff5b5795592ff119ea4e270122ad6307794b7389276334d9c2fd2931dfec7a59429c4858e0e1483428b9e8cff7fa1b79d5fc5e710b769d00812f1f906789c2f27c7022cbf71208947bac1b66e3bf8ece7adc9a4db7b13873970283204b38068a3328f97634a0985f262ca6c14ed54df2d62ba638a5322a39361493497f70f5649129b3534f637faff2e17326a81f54f4f0eaa8af2878b3db06c491eb289753a917ed840a184c72b7055271642c2b305212a931874fba7810b052769d214678033d66d0adb6259224d7b87db920a3ac658ec9caf6a99d6f310a187d86a29f21034e65381eb99b45f8b644d9104340e57087ca8d4791ff806558608ac44f7fac7dfbd2aee6b177bb0a7d2e15232ff015a30857d26368bcce4419edb66792fb7096788a7f7153ef81597add54a49a92a17c933be00ba64f485454bd00fe6afda9eb3db1baac71555bcc896a264c451d775f219c8b61eac757d1b85fdaa1d5f2530c6a9dbaf573726289b302b69bef240783c75035c086292674f4f888c3b1082f792c0807de4d56a0a83455259517bab2badfc816c10e774a78ef7657675d8957b4ba6ddcfe2cf665eb486fe0c6069a348cfdeb521bd28960f5c80d50925dfc3615d457766405268c41881291c7c21da0a28c7200e33dfd22310642c8de0064c941480bf2f46fd06ccfbb5ad0566aa062516cf1b9a9116326214bd6c8a25149165a89696de975aa9246eb9d760080dd394f9bdb4d4338485768c01def970671b68b2343489d547e56253505453b6b712389bf4c907d5caa0e0d9aef2e155eb1b6444ed90c88e179d06fc59f386f2ef229f5414ece899ccaf1ce87122b9e14e86329788a6918c990fd12f73dbe8b4c743dd99234c123288fe849905b0ad820041023275aa8d946afecb5fc35868f8000b6c175d00c40263b1fc6010d7bb238735112c1e107c0033684022c6e0a41c4d4ac3157a7e23e520cc9a2403e70bf3c681168b6913da63d7efd28a532a260769c8caf22f6b935238eda918b86305ef022ff6bf82e041d24e631494be65c21f65733467dada055e92daa5becc0f1769f3113f0181bc34f67830bc2d01f87f9e8abe2420d9c04601e9cfca3b217f57069e44d4ffff0906a1f719d7ed12cde40ea567f2418561f9c008fc0c59340473815203e8532dc5301197f80e7c9eed6892fb7700c828bda681b4c946fccea9a2d80e24051a200a5f0a0988e97e90f068d94da0d1c0c9e172b359830ac5a4c311067e9fb7211c938aa4c7fb6ac2c823398b020a911c3e0a985d68d3d1a48337df7f49bc554657d3aa7b0cbc66875591b46e8757a2d52e1354d9475d7050b064f654e05efcbd7307171028e066b53a166706afaaea686738ccbdde125274950eee34a1cc22a86792f60d69c77a67fb5cb3e696ae2f6a17f88a137e66f0682e9fb96abe4166252e2f55a63616420918cc93c7ddb9d9a4ed133143a069a29a82574aa41622e56ee0bba3a8377e5186937d4b376408d021704b61c809fe0707181aed36f63df5ac0ad052d3de44de8e83973b925c62620d887859b16eee6b74018801e002e801a609381586648cb89cf880de09400f7a5ddf7e509e0e5f39f311b39e58ae8bd8fdab3eb8b7b41e8fdc5924d1fc6fa43b57bad13f755047a01c9b45cdba15f85cb742d7afbad755ef9c9748c9118e8bcf95f68815be5529322f61058496090e07a42e4c55f93bbb97452f7b2cbed9cd5d433365781c3697d7e4fa34e16e48a10111f669a00a6d850b55879b229765af261973dc33454797449fd1463ee4dd2624124dba6a3a2da5a982bcf3d0857668dcdb63b6eaebaae534857413b3b5248f7346967ee4e559d6228b32704e7b7e7b5bef388b8387e073f05b64509b88e879d1ac85e3182b55ef980ef1c0ab8cc5af9b49d847d0bd2980446545ed6b369356a8c349c1dbbe819e88c009b01ba6b400f6af17ff19608d5b30216c50a5298fb737981232e98b1001b2173b34da66304a7546beb32faf0842ef01d3e8d0bcd1aa98fce695bd63b8254cf52159f56600d692282f081f97d676f542d361e62aa28b513266c6c126212b789eb37b79ca72d05301cf4dfb53c275fc31a35a89fc76c0f9f2f8050c9c369c4964696920ebe0f3ef7b32fabd1f8868a3ef341b41b401d7c13401bb65982e451588277f005ffcdc171edc027b5aafa6ad3f84b6f97a39dcc061427ca5e2d729b3f377e8f4c1b7a505b2570be194d9c67c58947bc4ed7d5bc5efca6f0f4875a36e9afc19e7b23cf32c4f929c3b4317efde2460fd097466e62096fe7b7076c3379749b038692c409042ffe857f00d50c524265eacb1a3f932a7abe3da99906879b041b126a204093432cc0e776279e7f0fcaf3d895ef3d5f26d367ab22275f2306db709b990db95fd9b62c50aafd5e95c72a246ab3871e3746030e27b7f327991f70ed12c21dcdd28d9a35c26e8e8603fe79814275743b92311c498f048b474494240d129838da49dc60f96cca0db72377cbfc975e044c7657ecc90892a14d0d7e96f77b09650b71ee0cbab49fe4b893c25015bab032fd222d02392a9eab5c918b6bb1e90a8e9091eca700f46e850b6d8a5caeab33846fdbcfdcd276c50be86f4bed6a4e9bd9cc70826d9f37ba1ce566d0b6af2d1de33373b68a0d41132ca79306f8649e60ccbfeced41d11e0ad1c2e62686ffe07dac37cca173284b617974f3d633eef760877d35650cd39431aca4b02abd3d3fb685bcb07fd0cb237d979f3198fe240517ee0515697931c75d4d32bddb19d3eb0efebf29ee4737462a194dd2025f4e23988cc55d984af13a2e044d661f3bcb924e4d861bb13b97055596aee2e2f32167df7968a6c2f94e92e1e93581024a8b48a7ccc73b87cc051e46bdc6e431ea008d1a98930787878c663f2b33d8c4795833cc7bb3abaff0b05f6d0d36870f7fbf7ce67707bd708c2426f0b471fba2c3fd00b84355768ce41e88076fe8e60691a38bb701ccceb8f7bc5388dfe69749f40992ddedecc0370da6d8d17372214b825b3b91253bae83fda9ccb8ae942b460ac9684feae16377061d029b7f91237d53e75d8b618bea8effb180656a9d3fbb8b83d18ac3e4c24e27ac705c5ae99250ceed90f8cd855ada03ad072cdcfdda3c5dcf8d2efae72d11393a809be035f2379bf53ce72e4132f89a972b066ce58188df87213e44b924a58fca0742b6543fcd760164ecaf7a3071cde6d64f8e7f8033c65aa03fd64859f2f7014d8fea11575189169a36a5b02345130d96c659eb1436b580ab9cf82c60481d831a766aa344bd8ddb90f8654e54f93a6f9de2d4696de815484984e954fdd7b1fd03204426a416d08cd34f540e9d7f32ace50580647f3500990d94ae590c2176a66e8014614589ae4061477e9446734f494a5b779881c588be52927715c034a47cd0624c6c23d89a4182e600543844faf83e81766b804271c51a1f2cd10710251362759c41c333fd01d70e38296a788fdbd94dfa71f1d42de145e2f4ae0f14848b5924beb88e8a9b88f65eb5a40b121645ac2e94c25bdb10c5173313216e415c8903eeca6ff31994bc6ebc00fee0f01085c47e489b6c1bec621d8a27a5ca61c22d340cd3fec85e101b6f72cd3601f767e5991819d74b0b42f7ae9d7f0335de0bc8064c5bddc9172b172aa0ec997e1fb4cb16fbfd19675189629cb62c0d4d9e381a25542fbe386712afbb24053c6501bf1661020a7c582106782eb0b29c21e7d4ed1bec170f00449fac6fe8ff3797a644801280bc3eb2f32f943b9a6fa2fc0b89a2fc37baf9177ae24c68f4ffbcc6374fb9c35b4932ebb700208a8f964fcf97e863c48f8c013601e0e6e3ecb71a012b413e9f0f020d081fc0a588ebdb56f020b432117c785878b4dea8e3d5292a8b077b35929de496476c02605c08bd358f0e39e27298c4106bcb4b4f975c3e004425f807272aa50c93c1fd98551823c305c9951ce3b78f10a62bdc1bdc261c5d1812cdce5031560864fa3be012b47e9a53cf565206316355c40839170efbc82f931d99558fc349b23f630de01bbbc689a769bd2fe36bb789cb9ce8dfc9ad3044131e9c334d0eae1483b5d5a495103414aafb0baf896517884063fd0c1568dea294ebc164601673ec462f34b6426953334e3a2ba0f929d156df86d916f8a61ea9dab7569999fd16ce51c63ec793f773f45a8c00c3c7a3bd50a6c68c25076f430afc0a4b27867ee4f89723753455963534b02fd9220ffb1a52c746b037a405aa17b527db39edd920aa088b7a7cac30f041f4bd4ece54b49fbc2af6b8302e7130577c15f4fb4f8c884a8755c33eeb64552cf1f069a1ca2dae4380d09c1cb2d7ed2baf751894b5c42d16f1ac8983ae9d4041bdff0f40ea2aada71f710b9305bb2e9252fcede8818930c731fe29c6802fb0cd208ba4f614bb6665daead705e5e0bb84944f8a9bf256b30908fc9f1edb42647142551c4c4f5eabd4d7403abffd046c8e6d803ed0b5726e46f699421cf10947bc3fb941ee4df9fca5903edddb7f7cc8a67b63153ad2b146eb15a83035224d1e97dd5548cf501fd12e429a4a2da7d2d40456ede5e260c5442779871affd6f116cfa029a8aa5dbb648c46baf8fd907e4bc9c6acb90452c7a46d5c75c8d6569ced0065ec97e7a0d7357acfd6946166e3468ed0ddc5c2bc6c14620a5cf02e9cc14c69451a5a5cbb943e5109df1d2d4ee6aa4dcfd5043a6201a0c111355495bb0e616dea16a20b79ad1da1d6f72cd49f65bb93507bd08a9deb4a579bf4a6408947bf89573bbc518faa3f02f8544fcf2b088658a26d5fcb509d214a5fe8be0ae3602857e85f2e3714d602e34ef35b08849dddd0559f102e4bd381ad46f994161500161f0850234ea9b98c003a23cf58eafa0015e181977f06a0632cc0e791061c38423aebb4dc8f213715e0799f0b1ac8d51c212c7e0e18a6a3f165f478350b4279c3a297ee2e1d8c430782363930acd2ddcbc4a3bc679ea9dc90692ee2363da52052dd18965386e26dfb7e33458286966c330002a0466fa7d546e8656a9f85781bea7ff952435a6d8d68b9c46100e0c090c7f300186c4cceaa04c049c9e434b482d047d679d9c9e464083fac846b111ab43a53e47fb3ed41cfdb85285d59f98f001de1bae20721992653bc2a74b5b01ae6dde94893d24306b593f35eb451a6bc35431431ee8baec4452875f6713c53f29f91b250db7078aa11ea352a2f1486585222116529e42e5579e177f3b9d17080cc1d40ffb0b411f560f2cf04ecb34499b4dbd768289faa66b15b160f2cf4654335f26b491290c56bc01a0dfa2b32e24183d3ddc28d7a795e7236ba7cdfd018be285c49c46d36bdbea79384c420a96d4212704385f875e1db7723e4af4a1c77070e7386256d6469948b46c6ae89940ed9d6253f5d78f30547da1dc5b2b729be3b322d1691ccde34d97496955dc1da0b98a78a7891199dd8ede30cfc63b0c3513bbf95f23e719d4c8542151c794d3500346131caadb323395582c40e616514ee97bc1cb2974468351d849c2254b314969c1c433055a25967d309341da899e0b85122d6e636d0a317b16cdda9fc57fb5d15977922f7680ce3b6e85f5ae5ce88b5d5c276ab0ec73400b2bf7663e905d979830ef67f426406798bfa348fbd1b3027ad1616f8ece455c53600f06b7a4310d9c5a1f0549a2df0a4bb79d2fa9efcc03d92cea4c7787b53986d03aea120cb43511ea5e836f1b573fff96afab0c61110fa54500fd7d6a48c8227a1e06e75faf982d2b9b92c3fcd4da8b6d6f44050470dee3103d04f4515de50d119b4a4c0add89f0256e65c4d63678244030e447493f17bff6e47c0900dff4b0d45874de15fa3ab3908912f4b27dab43809c0c8cc54220c23c22e4bd200c78a938d4fcd8aacda0b15aaeddabcce4071ac137e0b592482b01e6e93f384b7c98e6e2fbe029f8fc407ea83589fc029a04689f277b248daf3dcddc42e92b2c6e87fd4e008318c5ea18dd057c256487ebbec6f1e68a7e82b2cef181fe96b7bd581311bbc00e36f4f31bb0d785e94113300cadff0d4a08e83400d285f441ba6f50a010e96a1f701c7eb4f9ab5ff284fdde1a00dec5504a2e1c01ef42ba9f019a6686a5ce57cb7805032c4123c7886cb110b2875f4affa032111607a071bf1c22160e860c39cc5dd03e6c1a2943d779a330eb82310c241f911be787000c2780c387d7008c2b83ac0d384cd63a9f8669377f8e3e9cd3416e847ff6c008feb16907622d7aff9212336c53527008641e9d3965463c2860093b32f4c999eb5546cda654abd7df7102fea07e3b457442a9e40430c702568802e070d800de0480048e5802bf54313731f400e812e0018048021be80f98e556fb8d14e58e752e0f4a2576157a3568d0ca0638041103843801e0140054cda48002805c0c8bf38cee6d0b087ae320231ae501b49661040403c033117041010cf40cc050184113fc104a8769d3729dce48e5178c4676850bc2e799afc3c1223c8b121ce60f65b780886973ff22c9a00039f3d496d00864afb65b428c8587af6a037efc66be89573d46fb752d8cf36bb83d91c8317d12a4d75d35073df4a0607311a63a0f81ef4e2780e6b036b5d8882464f91670ad12928f03b52613da812bd7a202da5202201bd98f579182c4fef2ecd989cb8e560df0200a3ada656bd74e28dc021b408fb59e3051f445d934da36beb09eaf3141aa579efaf7b8f09e9c1086046a957330012c561451bcad7557ca635d799a0868e404fbd4ad724d2c0f5474653f3c9f86206bc6dd29e9fd4a07a4c5d801fc77ec8e23aeb551a3e850c6627251cf9445f9e3342b86afe3aa0b5a00c6b2288940878e7229da3a72f7945ad3d307035191282898035c973b337606e8cc81ce53b0560473452e6f0654a0e7a3d610208257873f8dcedf9fc1d4a9208d8265c7a3ebef3a96d4db2210e62dafda5b32f02e11a0b79f96c4419dfd2983d04c61a57858fee28b63733218937e909866657a95e0d42ea06b3869e8da44fc019e26822c196ef466041a18c438f740597967738a72ea1416cb7bb01171212bffd957f9a022d95b9fca2d6047f6cd03c91226cb94cf293bc1441e7b1aba171b9d65c0c5dd8fe3e2c8f88b40d32a4f47785bde47969f9928a2b51b962c861085af07b19ae65efc0529d04c9881ad2d3e0363a4b78ebf705177a61261b0770d305e369d1c3194be425debd92321373c3cebb9ef483507724404e9db0fe27b9c35ff71ff2fbb5aa837c354891d9a6b45782ea4d285abd89b7012d905881cc878d83b2fc798abb1acacf92c90a38b72183454262fa6c341992ffe55c12a687c9dfd6031116cb927c3fb8ac42bc9582eba699db631745ff99f52b81f192d0b0cf7f79ac9abca5c0aeaf4331c9e8b46fe4c3acaf6660a493f095e1731239dce510e197003fd96b8a171d02d9f06e16899f10044ec740c09511f82c092c09516c9744afb13627a146a7aceb8f309b97c836aacb830101b8654a24107486e7fd755b76161f023664ce359613bb25d4726310c39320b206b04c0a0e6e05ddd8b7a67d9d93b5cfc22ce93c25ee8f94762caa9369c0743983d564638b4ccdba2664d4ff3bebc63302d4ae7aa8f452d71307b13ce1365fea11717555593fc18ac8dbad8d7e0b8d7bd695406b4a14082b4fa85ef11e6a09b649b211cf873813d5135c7a46b61b7b2c05dc5ba7469e3a11446c82adac12bc6ebafed4adf3a35fd488cb954f74f1d107f8065c87f8fc12b43f65ec55e2bd9defe61f35a1f3e135e41abdf46a6040ce819d72fab6685308905527b4518e4d4a2ec94573bf7c981b3de215f8f0cd206aebe8a75bd2f32dead52a696d8945e8a8fee49b98eb0a5756a1eb02dbc18c64f00b775a35bcc001d94a9f44cc31a27cfb472fa943659502cec4042b0c3440b2a4d001ffffffffffffffff7fc136fb6d6b18d3be945b4a07a078418494524a29a5a43597904608620ccc39a37dce2bd00b25a50bfa0b040cae7ece890b9d9e22145faea4ea68f0ee3f885030957964ed663431c32897284109723d7e364f1825259dde991ea5e3c782710a2d61323b858051f0f4516e94857e517c35f154efc939b9c917c5ffdeb53c41bd28f8c669cdeaec3145bc2858c67913cfdecda15d14631237cc9a4717c55b3be1a1a6e4fc7f2e8aaf99d1344b65d2e2a25cbaed939ae616c5d8a5d24e90dba2247a9099c4b5a712f75a945fd469154d9aab755a1483c96baaa60fd1ed2c12c3f3c6666c135914630e75824ec295a4d52416a553ba7fceb246f699c0a274aede7dc2e7fd1126af28891621cd04197dfa4b5c51ea4fe26caaa91525e967639797bf65102b0a2a949c4cd62626f55945494cdbb7a1fb44f5af8ab2ae9fe6abb193f9a7a2b431658d6d8be6a44145e1344dd224f25314945f7f0cc22431bf3645d1639320e224753a5b8a4388870e3d3229ac30552709a35114b67edf3c9388131745f1f3861c9333acd31a8ab27679125e4b5014f379075b0d3f5192c49343680a3d51d4e89f4a9392fafd9d4e943daf3d7f3671a2249b3c97cda24d14e38a58b95875728f260af71eb29ae724f1f399287587babcfb13cb3798285d4972d2a1a3669ccd25caa2a964939e9127ba254a9d269e45875c8de14a943d35afc919bb049152a2183233573cac649f93288cb0d63d3125512c61f54dc8a0e368311225319e24fd707fa731489454d9a6939f3fcab47f444926e136861274d0d2de11e5749b324b8c8c275fdf8882fb7a69b5134614bbb3643b0dda4de61751d891a97afee43919a388c28b4c6a3637261105b57411ee49fd7d37114084ffa9551fbf3687288927d6b4b63686289649facda48f299b4d21ca273b6d0957b51b664388d2858816b9a127a46606515282dcbed09b7bf44910a51fd97b274281286f4ea5849970314f028892c7b70c42980e1b3c7f28683449bc137eaadaf74379eb3d79ba6789aaf7a1e8b3d72bae2e5e371f4a8252f7265a82c97e0f455122b45bc9f3a3b11e0a72fe6389f217d2cc43b94fc934f93141453c144c84501adb3c5fb67728687c870c919b134f3b9494f04d573a8b765f87c2e6f712741aa95d231d8a769fa9a7c4aa9d43a9646bfcb35db5d0c9a1b0af1b43d976f27c791c0a1f93ce256fe070d612aca49ede509453b6b5f1e386c28578edf4255b497f1b0abe6ef2a48d52253e1b8ae5a7d2d55e3f089935946ce3e8a4ee42fbc8a8a1749dedf6f4dd692897703ac9a96434e1ef4643692fc5d3fd27a1f7ee33147e4dbbca750e796f9ba1f45f8292132c4349ca52f2c894a66b3c3294e449a27e5cf7d9573d86e28ccff77c693a493194f4069d427a5da90e85a198af8312db6477dc040c25d39c935c66d278ecbf50cca632d4eae793a1f142d1c4b38ecb78174a25e59eefe75c2855a999cf65a7a4e75b28a997f85ef29cd2495a2875fcaf52326a5f67a16426c349912d3ee2c642d96554ef7ae3b6ea2b945389795636b6426935969e3631b44c5a8572f01c32079352a19c84c8a7faf6faa09c4239c618a355a3144abe397726d14e3a8c5128a7d3e549796fd20fa150ca4c25869e506e91711e5a5a4df69c50eacd1f563f74597b4d285d9f2e4dd741556e4c28f7c7134598c6727d0985d379e6fa4deed28b9550eef2bc1f6771124a6abf3f339ada60929050104a5072974c3a4249902faaccc7344b8c50d2d143e383677b0e15a1b0a20810a1946532dbee0fa3dc1a5b3f48f1dcef85511274e36f4e3d27c61e8c6274d538de2f27a40e8ca28aaa794cedb399ffa2a0ea992a4eed8be2e6b6dc0fdb309fee45e132aee5e72861c5e6454189f9440d254d1a39efa2985da47de9d3d9dfeaa254611fe46f43985e7351d48d26a74f2b3a4c5d5c9494d2af4f6ddea26cf2f4f368d319176d5112ea1d9fff32ccabad4539f409ab10329e7a132dcafe7e4a87886651127d593149125914a39eb81f64c9a2dd2416e5cfd5ab217aa3c4038bf2c9bbca68e71545d3d0a7d1d4aca8de1525e1644e25e3f38713d38a62a87d0d6e3d7a1f6745414ee74d7bfa2a4a52d4f3f4c9de24d9aa288f0c5f824cbafd94a4a29825d7e8383917f2a2a2ecfdc9ae2e3d453963eaff244b3545e93609a522a3b587504b518ea66faae3488a72aac6a07e4786dda8a3287d9b32df6ce663622a8a9256ff1b2557de6ba6a128089d3e568dc91f4e12280a5a1f3afe04317a4d9f28663cd9b44bf4de9678a2d83b4a3cfbfdd5753a51f20f3bfe6fa543f49c286efa586299b6109a6fe2b3d1cddaa6d644d9730ae1577225e69d89727aaacd9f6d333b268a7362960fb3e6254ab22f5ea277ddb99a96287749a5ca635889a2a6ca18d486f89b478972ef7a2c392725846812c58fd1941366fe799344414e29494cfb3673969128785413a693884962969028a75e68a7debcb22a1f51b61c1913d76df592234a2d1efb45c74f944e238a9bb9353bc49ff4184614f693a6986711c5ce49da5d2993f7ba224a8295ee2cff41a9998872942f15ab1411253109bb26fc7c88728c394e9a9976aa6c88c25bdf7ac8140b51cc2973ccdb14c2dd4442944ccc20e2f1348872feac5ea354c5354610c9e63cffaf4d20ca49b6d2bfbb79f4ef802806e5c9e433a56d72f80f0511bf0f4dddf420f543ba6b4ecd87f2fa5036c98450ffbc557a1e1f8a37d72a42e86e0fe58ea993e49a8493b4757a2866678a12e35cca5597876275c992d42455134d78286eed6b853e11254fee503ae1d3b3d6968c498e1d4a629edb0e2a6c4dfaeb707fa9eef4f8e950923fff556992aeaa9f4339ceb74b2a99fbbf1c4a4ace9d43c8c4a124c4866cf4f86f311cca15a2847ef78692ea29dd50bc92b1faa5b7a1f839e9934e926aa5936c28658cd66cea494ee2b786d2b9adfb67cdd4501c9d1f9ae4e0b39fb23494f4a8e930af0c0d85138498c8d9ce244cce503ae12d4268ff89ea98a1284ad0ce2e2a43f9cf3a95c7f394fbc950723b99c4cc0d293a632829ddb2af2363d2460ce554193f837ade98260cc51354cd5dedbed5602849299ab4449177925f2898075f7feb984ae55e286f9a6ad7b0bb509253ac6676b8508c91415b4c7ed1f12d944c3b68f9dc4937b95a288c92bfd7d4f4654916ea244f7a3c7162a16066fedd257685b2ed8799bdad508c7eef59568d518562bda5685262c9f9e88d418552d8894ff2c96fd62535865f1f43df791ac790c2b1bba57ae2791fcadb4796ccbb9549668c28146e7f3f8fdc33716d45c418502809aa9a1bd6a431e94df60031c6130a42c347c870a27410e7ae8e34da0f6338a16072f40f6d3244d8af6334a1b8ea25460d2a94204b6b3b8cc184627ca6cd261fd94fc7584223e366edd0e669f2a384dcec6e4e46e5c234dbd34fab6b93bca3df3192502cd9ca7664d049d0f9a0e00367a4b1038d0ee81cc6404239c9fea9923b7f8492ec268f764d9b318c50f6f598315bb224f104c728829b31c898e4c62042418cd09f32937cd3981f06a6577732af6fe661ecb3b3431788218c5228593e4af8241f3e16231885d1b97927da6456b5c40046312913fb4fdf6cb57bbf28b86be9bed8cd142bfaa2204ece1ff3a48df9a213a317a5ea146d3f31e6a0648d17799a90f93b9724bb2809ab29478aee4e79a318ba28bc881a9125753b44cf4531cb8ccc385d1a846c62e0a21c63ccace8e8d227aa18b728e7ce1a3657e9c5b0456973bed0fcd9df492b316a5196efa064537642c964a262d0a2945aa5a2b326691ec49845415353ca8791b5ee6b1e420c59147b4f4fd041a73263514c77f27bcf9534398d6a3ac034316051ac13a7348d5c17f7d22b4a928e313c9995c828b9a2783a26537247492bca269520de847d58511c93d2c7546a2ed3fe2aca1f2b963b26096b1b574539af7ae809b2a3f9c5a928852831f3ea2bf7a41715a56bfd8fa9169ea2b439ee9de6e839495213c314d6dd878c6d5857c88c67704d998493e2e00f94a26cf2ffa46ff949c2c3a428bd77c6d88e7514e5249fac760d1e3a410c51144cd8f5a7727fef1d3114e5dc415dd3a7f2cd61048a625f9998b37eb63e2914e313654fa3ddd47493b0fd8be189f269c7d57c27e62a3a6274a2f0267cd860b29a9a6b9813653fa1a9d3b8fc7b6f70b0f5264a6279697292732af9d5d344599464e6315f868387c1c1994874e4d8818e34182006260249f50c7a66285dc8365d27fd7ffc4d2c80942141c8504ed133a6a1b40f808ca19c43c98e1e93a869626700440cc5eed1edfb3d42689c71206128aadec71019f11f1a308080a124d77db0ebfd3c9d23902f14f4cc3f2f4449dd7ef242e1d204f139afe942a9636ede87d878e9692e9484da2a992506f3faec1612881692dd138f7bbd2b9b8dcf705392921de727a814240b6da33d670082859258af3b373ae68d1f02b942f9e418df26d6e3849e8058a198e4b8997766b426ad57a19cd6ff848f13fb72c36200a14241c8493131aecee8d354a7606ae93ea525b852285c988c1bc44d9dddc95007071285f2c99fe3714f780c966e1a205028776ae6787a5563c63ca1f0794449a59e64d43539a194d146bf9b74dba04b4d2828199f846d8f09456fcd6bdaea635e5b42293e64c932e19f9f4a4a28e9a4a64dbc125b9292500edf0cb2335575bca589312666fa47287d8ff44f5f1188118af14453ef29eb242544204528ca5668fb9fd19f33204428d9e6debe49f54df7304a26fd5c8b0c4aec9b85514c278fcc7d9e74cf9b04a360d5a3ed4c0a8cd249fef9f179923ab95f94357af96fceba92b4c41765d1b1d932e768f1a75e18d24d2b3ec92183170793417f654cb28b62664f277caa7e131f5d1433f67990497e729198249f18a4491f5c94f332e774ff27d9cae71625316e446eb4a4ae7b6c5114314a4eb1f89ceda416a5525b7d92d5afde4f8b72af9dcea437b328c8dc24fac6bd6fb52f8bc24921da4abad96dea63513e539954d6038b92be99d624293149dfbca2fc19d76ebd7145494cc949529ae4e691b6a224843c75a545c38a827ef5f8e6ab286d6c2fbd7b5d15a5729374c9723d15c513fe3a9dfe9fd039a828cdf9a78fc94665734e51ccce7d6adefd453ea6286996b5938da752f4a5289ebca7fe496dac639a14454b933b6f977632b91e45d9ced2e39eec64996a5194d43446e3a7181527a12899e6f40d5672507209280a26ee06a5315ffaeb9f2878b66ceb4bf9dcb4278a9ea304a53b63b293b9132553d116d3e09f4a8e39514e428cb4b6bcbfee781325b9c1c4a8d1f3e7c9d14431fc5e89a6f166a22407934b94c971fadfc544f1d3279d937eb89c732f5112563687a8712d51ead9f72c6eca3e2855a2a0840c5ab745747a13254ada5ff3e327e59cd0240abe49e9ad92244aa1f97a7c4c10a67d248a9b6bd2cda91512a5aa0fc2847bfa88f2c731bd4eb551944c1d51aed2d6ea4c52ff438d286e29951bbdc38892e9863a8b3ff7ec2ca26c5a4ebc29318a28099ee4eef0264dce49447946a991a33be293b97a88c256eff7f88d3279334431dfa82b9d7aa7c74214d35d6665d01b8f5512a2a47553bee56910a553512288927c4289794d8e3aa22410a5ac7b3d3973f58d0f88721acb0e4f6a2762ff434993e61c4366d10f2531cf3fcf98247ab6d88772926c63c9d43a2555e443494378debcfc74620af7500ca6e46ca684f450504a0999673d2e5f948772e6bccce6b95fdac143c9bbccf3ef42668fb903b27d9a311a3b94c53e3526c18338b1d7a13cebc14287f9c8a0431acac49025e86e0ec50f93d95a53aaf9490e25312ed3769049123a148792dc0e2b327dc8ce39702877e8c78d90d3a1f937144df6f0721f32a7d6b8a1a0a2ae31696a2d9db7a1f461f2eb24f127830da8d66a6d0d05ed64b11f4a534349bbbd29395c06b5494b4341e907e159c43df8070d050b252b4ddb4e09fe194ab15de2ae3d35fe3643e14ec4839e5d8682878c9b7744987b960c454d4da1a504ef5b750c85eff54dba166e9b1443d14f4c86a1a06c8492847752cae4c050923943e62c49ca185591f185821284be328f49bc5036cdb193d185d2c7ab78d498b90bf96f18195c284972c7e8ec2022630b25fff4252759e369734d8616ca49865b7daa491b75346464a1a0047d7234494ebe9e9a0c2c2494ec9dc488b014afa07e8e6c595beb9b143258e9dc1b4c4d86158a9e36759aad50158af5f183e82042849b1c2a94739cac9c75ed08644ca1644a50c2e9cc0ca5834a86140a3afadba3ea9d9ea024230a052926a849e2e2738c13144a99c1ccf49a99dc1922e309c5739153558209194e28cba8dc972083e93d6d1cc8684249838c98f69c3cfa6ac86042d9af34a4db9920648c93b18492b827b48971b7c4b44edab1038d33ae4086124a97d94b756f484612cad13289f6f3319824e814a273d8c83842ba5e72a76e2a73adeee5aeefa76272328c509c132bed6d32a80c3b838c222cdee9b5ba27e37a979b6df286fcf92c3149723c904184722cd3bdd32f0ea3d4a37e1fe3c99cec01ba51b723e9f84052460e1c1a70615c99fd4d495286f3abc74730d8d957ebb435d970153729738c3f4a50c2e3fe00463983be2fe1f3493b42f51fbf28c64fd6a2d7729531e7c317059dd7a6c4f5091d4ffde845c164f3574f62762979c2400acee0c18b921695f9109193e50477518e3d326cef248d1a7e5d14b3e4c40e4aed4e3aa98f5ce4339f235af77de0a2fc9b39cae9b79606257df8b845b1eb5d23b22e22d79bde4e5c8a0f5b1477844e72a1b31d1fb528cd9a7887f5feb8255ef7403cfc8316a5d2cbcb13a164165a8e6e6678559ee94e193dbf2b8b52db06d7bcd9feb2a1589473e8ab88091dbc44ce6b589446ab6aae6acfec662506f0e31545954f229ef33754e6c315e5ad1c7dab315bbf7a1fad28cca7cddee61de388fdc18a4ae45ab5424fb71d7cac223f54514eed7e7fa7df5494369924e389493c3953f8818a82979c04b99d1b36d09143870e73068f1b3c900d12742319541801157420cd151fa728b86c47afcf41679c9186294a42edfc2e6448dbdce060bb8106dac18e32eee0f0518a5255c9ddc9dc2608bd7f90a2a43575ffa8ce12e4d41fa328650c939adbbf4df03f4451fe92b78cc44728cad95cbeb39b32b7f6031425a5bb4bd01ead3196f0c7278ad984a713ec9150198a3e3c51daa4399efece9d28e96da74e652ef2943c278aafc9649b2869d33bd7a49310afb2264a375f32e6f7889ef59928fc7b8c8f11fb0726ca41942cb539a78a68f57189922466ff520bf51d77fcb04431a7f1f936ddb427c6dc4725caf55d82aa3b498925561f9428c5ec67ce1fa41f93b8eae3c60df7999a217c48a224c6c9f5e4159e8f486059eef5b266195af2e713cd7468201bd86047195c840f48a4fa447ab56f1e51141d7b83a9f8ac56c21f8ec8462423ccc6c7224ab25bac8493ddc418a1224ab2d3c7f3427b97bef79188d2cc79f4f01c5447e379f8404431e6567e77cca0192d1d3bd8a103073a56708882494a7cfc7bedc7fe6dd898c38721ca997c2e547709e9c8f1fb828f42143d4e4e8252e2ebbe5542145327a974e69609dd500b1f8328c92083eafc6964b2fccca491835282280715d9f9c14774f91f81289650fb1e7b3e65f88b02074439cb7bcd6ff43d031f7f28eef9c99b7495ecba267e30962c6a19ecfef3d18782d8347962494a8ac7071f8aa9943249a72d9de2cd1128e1630fa57e97d5b79acd97ae0e84831d2a401f7ce8a1249ade0d5be2a69a6641f8c843393e3bc9259ca7a8d195613ef050329d3c4db9dac9f369fee0e30ee51d759dfcc458081f76289e7ef713b404f3d8e2471dca25a819311de3e61e253a94849a94f1f53b3409f61cca9ac3576f8c9394fc971c14114bab73d3adbb0c4a36b96333a38f38e0071c0aaa4d79070fd2c0c71bf0c30d450ffbf91dcbd48d9216c1471bca191f93321db593fcfb830da5504a1237678a596ae8630dc53d25a23649825a9139143ed450f09394f42788d09ef6ff4843d935b39f32b571a3063fd050cadcdfa345d4f79916878f331443e57592a6e5ce4e6f8692cae7d6d3795286723655352d3a5a9f9c11e1830ce592d16cf5640ce5abd3196da5ec36490cc51069a2e75517f5416128b7271d4f3ef7943909180a635a3e94dce35f265f28891996413c49aa5fe385829877e7895d28f7596f36e13b97e65c287e1afb70a541b3df5b28d6c88ff6709e54af8572d691d9b09f313267a19894f0a60f2c947410fb5972093a969a3eae5012db842b7f3b1539d38715cadaeac9c393fad6317d54a170b2a9ede727ebf5d207150abad4cfe7d7b3da2d7d4ca164b2475e99dbaf6ee9430ae5dcf9bfbb26dc6d4b1f51287b3e39ecdf047957421f5028dfade692639227a47aa3f264d27102177ff22614fca487b0d94d32e34c28e7905d131b5a75d24b286b101ea4d94a28480b5de2a893e4ac3609a537134ec9248984b74f7d98343a4269ee5366759e5c198d50387a8f2828a9c3c42819838c498e3ba27025857727dbd49d34e8841a8d28e7b89fd15cbb7eb92f234c21dad396bc1697506311a5dbb041c8909b19548a351451eecdd0f922b38d6589351251f6d0b5cd498d106b20a2989a3de57d4eaa7108b351c3105ca31066a30621acc620ca310923d2fd4e83da591065d9924a560db24909268128b8968b0cb39edd7903a29c63efe74c42476ef487b29c70fba1f4d984eef43b69592509500835fa50cea0a183f0b039c886a883e34339e6533a62a34966f67b28e9ae67926a3d2625560d3d94cd3c6e77905e8d3c144778efc96db5dc20ab818792767756a59f35ee509261cdb4689126437fec504e27ffe6dea4a9434988870c3d275e830ec5fc7d6a32ebefcb8b35e650d29dd36ace58425f63460d39144bc70bcf3bcd554dc6a1dc9bb2833cf9aecbe4e050f04b0d9e74d8eb7cdd1bca2687d3f9e4706e329fdc503aa5e2a204e9b5a19c4f3ab32bb5c7a1061b8a49674972f00c4aeefa3594c4ea4ac65fac86e2a7bee71c4ead8c90a6a168fad2363da968286a79e6e47666ca3c67286e8a9f685956db2f9aa15852779e3939ba4bfe6a94a1e8415e3574fb35c8501a3542870ce2d47f4ca234a831867277f2164f1932e9f3f18c1a62285aa7122d733265525d612877b5c893a48a56d16e0d3094cb377d3c196c4f0a558d2f14c3a9941f7d6e59bba9e18592eaa0f4c4f0eee8a1e3035aa30b4535e9297e644ea6fb54830b051df4c88d1343851a5b2849632adbd3de28f15123d4d08266812de926a74b2c7c62ccfbf822f36848a8718592bcbb9b6512258dcce2e2a86185ab5185e27747cdf94c2dacc358830a3a853c5e37f4bb4d56c347864d72d6749ba5ac2185e209e28465b6129e7aac11856249aa3eda7c49f63d824249efc6b3b8ad8e2e264f28f75e95b0393e6f9de3848292fab2e474b23e86bf09c5f693a243bf6342d1c43e9dfe84934e69be8462c8c770a7d4cb4dac95502cd598e489e3778270935090614e6ee98d22a198ee35d4730ccbaaf50865cbcd7999e3462848b1ca8c1d7af35516a158e5354aef89f888b106110a6bf28cca4952cb4b378c72ea67a61399308abfe1e33d57158cf267ec20222ea4e650024631c824e6b0dd9b5f14ee4c78f649132332be28e7733feff092e4988efe4ce91f5e94a385f8afa88e490aeda2205bf2e5f249ba28bf956e894d7d2e0a7afc93ad6e705110a2c2eb469ca051bf452964a75ef524898f2fdba2981dcd2441f9f898a716c5d64d92ac21e26c54498bd2bce8ae0da349e809675138d1f4a7229f2c0a224eae93465ab1485814764f6aecb4d61d337e4549f254f2648618e28a92d4213cf4a986395385b4a25315cd9453b3bbf80e7547082b4c4356514cb3dcdecd1023ec244415c558f2ee8c8891d5212415a5dca0eddf4c0ccf6ab2a8280959924e9de3c163d939869053944bb987dc933acf3d892932b12f2d17424a6136485116f5bc16ea543a8aa27af0247cca754d9d2d4414e5d0adb19d69a497248784a2e4679275a715415128f965e1a6ff274afa293e947637c413e53631cdd3599e30f9a44748270aef27b3a9936328a54e219c287bf0b7536e7533af1bf208d944b9c7c3d7546a8e339b264ad2dd68b090692f8464a2b057a346650a3151d8e849c7a03636dbc9d920e4122549ace7c54a9628678e569e72bf368957a218dc44bce2f2debc4389d25dd6a6122b2fd96a12a58a79d394c10e9144496d656f67849062d2cc48944c73d467700f12c5cca3de3de85897cc8f28c84fe2d4ad04d111c8683039faed8a18d288d2a55ee972dfa4154218b1218b28ca86cdeb70a15644d1bce64fec51b5a24d9a89289b9b36318b344949821a11054d65a2fe77f5781c851ca27063d2677b99584ddf1005d9491263bcaccd9de790429464d0a67266fd1042147e940c2db23f832895507d8257ca853aa920caa1c4a44e5062ae6c3d0351ecd0fa2729199f3e8d802896aeee95946fa26285fc816de4fa61fb504683103e94dae4b0fee1bdd4da16b287528af26ce29a8e1e4a234d66caad38c9644e1e0a36ee79d448f95492f050f224269ad81c439eaa7728659de5a612b63a5b1b628792949b6d83c99689e3c93584d4a160d29cf49577aaf1e3cc103a94941cd578faabeac42c43e650d8a4a24ec8963243e45050f397f93732ba520d8983d9c810386035429aa4d4eacc9037146d830cf3582d0f296786b8a11c64a711fdd92afde2cc1047534508657227840d05116f5592673443d6503c39d693d020dd639542d4500e27e678a1944933240d85f7f5d7cc9c0c414349279d42bd833059107286522735fbacd03ca3b919cad9ed643439cff726bb0ce559f11ca6654b8ace642809a5cd2c444943c65036a9637692dca94bfa622889f22ee59a2a4d360f4331e6e7564f42d5e93ab3100286827dee244f5fb427cd7fa1789dd3c7122a1b84d678a1dc4156c8fc734ad021ec42f184fb9cde27174ab24919c254764908d94279e34369906d9eb14cf98490e43db5e98e3b2799215928c95e920c796257bab89921582857868f57a2c94e9af40cb942d93c6bce8a36618658a11843c3a7759a215528f8ae49b667d221542809a594b6cebeaada7ee61142a6503ccf3f2abb3dd609719221440a65d90c32677ad1cc49d45128898da546d7bcb4a7180ac51cba5517c254656ef60905b5551eeae97f9375ea84629244ffac6cd0a626994d2887f1d07042db661a13540d614249960a1d4cb4a41ab204b311a204b38137084942d962dd4fa7b1f7ac59f3400812428e50cace24eb949ce34e187f471936b8a123078e1e3976106204d7d246e64fef3baf0e8483471a67308e902294d7a4e9d123f385868729e3468f1c659cc1a33a104284f229f96ecbca3af38f86e97123073a084086c16e6a9b7d9b9efcb769b1dd1c932818250f264fccc1461e6b000146c98395da983b9e5d00f945e924695e4e0e1ea4efbe2895f8a69424de9ebd28e92e359749a90c0a20bc2888ce291df4677661360e48a7fddcde7a6cce454183de9d983be8a09964ab00828b8252f2b595529eb4457f05905b143f5eed654ec71645ef2d25378d12e3fcaf45c142c7f6e6cbdec974fb008416a5109a193687da244f5092a01e68ece8e3d103f1e081814501c82cca1ba2e35ab2094adc4c6119406451def23937a9c1ff7e332b80c4a2f4f5e1fa53355b3ba602082cca1d5efa233fc5e4d3500004905794a4fffead57ee9df538d8ce30e3a02b76d97ab3567577fb9231693c9eccdb9a896b2b4a1e636b9a4c726501082b0a3a326f0ef97d7269150535426852fafdb54f03a28ac2482f3117da54946414a579d2e3358b1215c513a949a509c23dc6e9144591d9a4c4f84d51b25102294531bf34e8553f35136b1052944ca7933b8b163d016414a5cf4d1bdff649b4b34144510ca5fc53e5abbec92f48288a26df2459d149f83c230828145126081566ab1dc8278ad9e12419cbe4c77916c413e50b79a639967990fd01e98496a37667329f7b279ae32555a8d1d124f76100c289d2c919f73c8b12e2497213aea94ce2a4e505a289528e9fd0ce9b72d97e104032514ed26389794f967525278060a2b449b69bafead1926c2d02c825caafa13505b14449109ea38e4942c7aa91412a51fc1b5d829d9e2fa11b1a4028a19328fdd9971432a6b5fe9f09209228f7ddea8bd4d0d1b3a40c241285d9a46d48944ccc9af13d06794479eb84921ae3db957c411c6136401ae18c0c257f3a99b971861a060c08238a3ffa37c9f6773a84691105af16f5b994a4a3788e224aa3bc4bb8ee74228a37efa34d12aaebf221a2781e27dbe9d7400ed15e8b5789567c696ba98e14298821b668005208274451fd4f923908b1415a9ba051823e01c8204ae959f3578569fd5e10853fd135f86810e5b1148882aac9536f4f1d5207447192bdfc98e80fc54d5a25aa88133f947f9464aaf59324c8fce943b9a349ea2ec52c4dea7c286f8556f150a2eda3bc87f2e9755dc6984d31d143e1646d4f33133e1a8379285fa8a613335484db878782ae2915a77430596cbb4371cde49c724d84a78aed50ce2ab249e609992a3cd5c1d91140ea5010ea318c4e2f49afa74a876212ed65cf4f060f640e2549a39ed0c1d472285db646ed1fbfb3ef701c4a155a258a3a3163e7d8c2a1ec1a273627ffa6bc92bea1a09e4cfc94f9fd91c9744341a8137574de8f206d28e778aa9a7cc2c3868d04614349f0f0994b08e51aca41f99bd226094f01440dc5a4a5ee6bd25db89e2c481acae7b5bda28411de49078286a27d9a28176935f624602681bc3a08e0ad51fcf21008940d6c1bf680d383471a681420003d780924480101e08146022ac023c719460101c8030002100009e0d0c1025c00001e3cde060104607a98c4460102607a9864071a360e0080013820013bceb88183637af0b8716301000840030e5010fb71e468d025868d71709fa571660642e3860e7224079dc1c3ad878e1c2718114571938c34993d2614e5183c4da88f260e3606457147c8ed2af133e9c9e0605b3390199f403ad8618619c88c038c78a224cda4ce0e1fc3c1e6da09ccd1a30c1c3ccc8d1b0918e1443187fa7c504a143fe9c2c1d665a461066ee20c338e267a201e99e8c119c70c648601463071898212aea32a33b544f94b9324af4b1669e5c071634719653d747c600395c01c3dd0c0c1a38c1b3712304209bc710301239328d6db49b5f00d6bdd273bcc904469fd84ee8f3efbb5eb20479246f6d0910379e8c8d1030d54468e48608e1e3ac891a471e34602462051aecedf24a4a813bfae2e63e411454f26d88afa1ceea2493970f0701e67ecb851238e28c8981426d96eb9efc776a41167d96e57b765ce88628bb8f895eed930b288f2c9f17272ffa699ca30370e8930c2c6a8edc14c27350e361d2389288931cbeaf7f008228aba272825ab453c4c1976839143942f46339eb03639d18c18a2183abed77f0ee741c773c348211e6d2f9f47ac84288e9c93841bef28a7321c6c653b460651780d3a4e08593f3dead86186193b0ea231228872f78919469894f518094441b6881256aab4c3cc8c1140944cdede8f2bd3ad494c051da8d48009441081835840021b3638808208a81da403df005862e40fa5d75442647f8b438729c30428d9a12371c40f3f18e9c3081f7aff986e996397f2d8d2601c18d4020ec2c81e0a232657f26192a8f78fe84175935d63ca70ba478941c3063a76b003072379d0abc1081e0a7fee59745231fac5be4369c47f8fb77eec50fe37e9c4658aeb9009be598dd0c1edb6da37af14f576bbad92af93321b994371b48961acecdb4b3047e450faf6be8e99b3f6a6b68b3012879256cd2bb7331ddaeac1c31c1d3bd8919c8560040e25efff7b3dc15d475638d86ef4008d1efe86a29ce4369f4978a0113794a4acd635755fd26a236d282729b3d527a17e8309d950aa974992e0a54d72f000e51646d660adae9e9da0c35e1851834169ce6c820c9e35c363073bca286387a7c193194d86678f2f49ba3082064bfb4a5977e7de868d3360b2768aab16997bd46766c0e41cc3e8a8a72e3b66a40ce718c4a90c259b74983378dc28325ce22721df942a0d2ea6913124eed774b4db6c9a0d46c47075c976eca58e5b7acc25ffded0b1a32e056568a0cf81c6e1f169f0283363240c25d3703dba46f8083fcf08184ada21d63bcdda7336c1c1da4307d2019ac0c8170adbe731d87b4c47bc50caf2f8d1357e8af0bad230d205576b55c462455e5e5e63833451539bdae6aa83112e944a109a45cbba5437bb71032f30b285622613733327fd068f1c376e9ced40e318336edc50632d980dcb4231889b206292a8694f4e8e112c94a53172858272cbced8a51c3218b1423159c9593bec7be760ca0f8c54a1286299afda2b73cb498562f6db4dbf2537328582897954de9cd81ca31f9142d15df4a4d52c7b3aae34a2501ceb53db490eb1f51e075b9fe580424949d245d9c8d1a296b163c79b05469e50b2cd2599aaad6938a160bf1dd36e3549db708e2614f65465e6183379d8130e361ba4f128b161c3066994615860c3c61a46985092c14efa24579e6e2468ec38088db21e3978e460812665a01c492b30b284b2898da89d514de7221c6c3cd8f13770704c19efa88c1e9f068f25010c6e848c28a13442e794b24ff2f97f70b0f5e08c1d68f460fb3478e848124a554295baf50d062348b8ca5dad43e4e2ceb6ecf73e892e8d1f43e88c1ca120d5fdad44ab5e3344c98d1ec80666c79881234900831b35468c50ceec2a294f8dfc541fc43152041f21425963d0f12445c9254e24328c729624e894cf27d95d2b228c9232a133948c76e25c2918c56ff32fa96411304a52d8f57d8af317256576a3f42631ed6cec8b62675f6a099aede43d7be1bce85da4882e188b919f482e58db38bdabab531797b53a59c4661ce1a26c5bda2b4b8c254c9cdca2741beaad1dba3227b14549e709bbf5934d68bb16c5e0a142890f3e2d4af7b5256f9a45665192c4f3c679ddc8a2fc9f6b357b1e759358943b281342f409aa9a6c5894ab4d3ce95f377642af2898542beff4415714a4f5061932bf3df6d88a6207ed6d1171a27b85ac28c996356adcf7b5c4d82a8abf1a553f345529495a44158513dfd87cbdeed17f9154149449fd2993a41d4f28828acc3336ddedec4d435c454d3e936f5553ee9bc829ca27d2f64b5a6dcd3b454c511243cf8849977aeea25294323c7e125f92dcd425a4289efcde229a2419c7ff5194ecc3a912449aa2289c4ccf183ec9dc9e178a92a91395f1ca0345c994d595d076c24de813659d0dd1dbdf16aa9527ae13c57cdf996962383371e684d90081c8264a9dbc836c921b370ff340e35108114da048264c04130575aa2d3be8cf254ab2471335d89aa80fb725ca39bd492683c922952849a6af666298641e9328204209b34104914994fb3dcb9957665125f58088240a278cb9659294474df2229128970a258fb4ca104a374288402269c226dfcba0a4ee118e4093d827a79caca912690423daaf3abd50b98f1751d04e57ebbb1eb69ed70810e280d161ccb881503a45944b5363ba27f17b53e260f5814822caae5f71b2f9838a7177947103a1614480831d8820a21ce3b74915993d44e12eb324fdddf100e95034508f0f201ba0814680876c800632a32c0622861029c49f738c5b9dc498ce149571461a3d140822841844dee13996795e9e25494f4d266464908ef333cc38d801114194f732c939e873d9201288c248fd9cad5774ccdf8b00e20fc97c8d1f3a496a3f942b93fe099be4932ec3227d28f5e433abaa7367d3443e94d3dbf5eceed3d89deca16082ed969c632ba28772b8af1efd26b56644f2606677acaaacbbab689e660e16231f37e549a9081eca66724f4cbeb7c81d4afa6134f48bc624f78ad8e110baefafb24dea603644e850ca7df37d134b9139d80444e450fa2c233fb24a72cb9238144ccef22c3f3a2f1081c31b6a4ff1b415b3b4ead2f604226e288e9055c25e286943316b90e5214c99989ef32288b0a1d09d6464da60d75983f14b52e23cce1251434912763477ec70a14f923414e363fca55cd506b9a2a1a8ff9b6433cd7b2e7486b2eee6aace9ff95436331474a4d9283fbb0ca5123b8f22642876101fdc2e4538d87a7018888006f4ce3066a0c81854d999fdb20ab3dc705d440ca54df5edff1232abe9110e2261289bf4da724df149980c86829ecf49693b25e6f4a8c81744bc50cc273f846cc99b84f8bb50de764d9a3c6b112e14e442f42b3b47640b9bee46db2b4992223b828816ca5d26c35cdc4f52b246240ba59419ff9c9a2ed491c30cfc8008164af1e193204b8ea140e40ac550755d95dd59e17826bbb1d39ec79c192255289db6cdb240840ae5bcf8baebdc9842d1a40df3ea61ace493d3d456202285627bd64ec29398bf0455d241240a05ffda98746e9127da9a2329638707747c80471744a050fe244788766f68a890b9c8134ec40907ed5311b18d211c6c0807460525d284c2697cbcd31cba27ed4c58af2a4c3cbcd43344968012e2d6aa3a09459450d2afa54ce5c47a934749a86b732dcecad54dce2b6f394d2bee8b20a15c9f993789072013224728aa9f0e971e967962c80825cd3e3d233cbf9f10294249dcdc29cbf3b87ba74588507cd33b3aaaac1ac32867bde718bdeb33412a8c52cf9c503ae63218c52a397f89e93260143779189da2d7f84579677b3fc6d5a4776a0d5f94e4dbb33f9ad45a329c418d5e94d37ace22aaa2a72cc48b921a69d29475f0f0cce1603436d5d845f94abedd73d0d864b32e4a4243a78ca14388c8b1462e8aa7757263d0f518fad7c045499079e71dd6c492ddad718bc2d949425ac986af996bd8a2209719c457eb667cab462d8abbe13fee9d125a9cd6984549f3fc56a7cfccb0230b6ac8826381068b621e398fed1cf48a729d76905182c815a5132d83b213cd248fa8150529e2cc359edc2debb0a2dc5184fcbced68bbfe2a0a72aa444f8cbd2a8a56163ad741c95bb5494541e6c409d6399b3841838a62be92459ef6f8298adf9ba6fd53b69dd9a6289a184fbbe39bd4746d290a4a8e32c9a429a9d75352944c924f99959cd913e5284a1b6b425c7fdc3da11345b9642e797e7a25de6ba12897924f942f751a5fb3366c20336cd87055d40045f15ad5a4103a7facd6f889f644f183ae3741e7db9863a946278ae139683b31a5833c8b13bd89d344494e7bea2c2d62b30665a258b29454ee254d34e660a218b2996925d6e494cd254a279494931b994f8a8d25ca594d38e15c359528f895dabcdb2f41c79812a519e9a3dddddb494c2751f83f59f489b14de9124914df327ed2b85b24cab1648c6cc786f8ca20513ef14566fa1a3d5a8bd0a834ace64282a250241689442271301450e83ca000331408001838240b0522c1601c89a2f2031480025724182e2c1a1e22160e0e181c14181286c3815020140885c16020281008048221b1863445f91eda66b3f484de0098263e7c8bf09a7afeccfe86a1b7716fa9ce8a9a86bfbf4ff54d8a3b1e0a9b441b0af32fa278a5fdf08dca78057dbb766ee425767565aeaf4417dbd3fac0217868de16bf20e7730a76c7512b7bc84e868d712509176113bc70a2d0ae4d4f162fd7d254e0ebbc9cf23dbe9c4bc58e63b1ed520529413f82a3602d656a2ecffacec3b23e2b3dc6c0f0e9487dfbeb67b97168336dedd99c2f7bbeddf429ce2efed2bed07dc486ff10cf9e364bb3837656b7b631b58f6c0aebd0aa9699ca2cb5fe9a79c6692c11c6ad82eb19f10db074594d5cbe354fe006c064eeb83a451a5c344f7e3f6934684daf72a71ea303e60242819f118c50c732b4f9277fce5bcc8e207a951eb07d72a0dc1c3d7132986b3e04f6dc8aec699ee861d0e23bdcf2be40a118ea180b61b55fc10deb063d611b8d38506958a89bf651440d206e1c8b08256201a922bf304c78a828c14dab4e6f5117167de8b351aee8ecd523b715d38438b7b26144d7299c73eb7445b73f238f030d837afd8036d4c1cc0945a5f9f41184b0ad71370e2556cceaeb6d68f4f9a1f27dbc9e4aeb2f88c00fdede338e3454ab01e9b6f2ac7b179ea3d2d30a08147c7e79c624eee4fd3dab184a77c635e99bd42aac4ccacd499f1047fd6c2b88630e62120398f8cbc3b9d54678f70b522279c19ea62549335a5c298cd533c799b6d192ce3b6195fb4c549a583789d43a3a722a1b4089eb72e87eb8043a51b18d6348602fe105ff0bbb889f5a4a31d199eb27ed2541be9530d1c2e241b38dd0c74c21831e10aef73cd8016ef429e6401ee0084a7c95e74d9ef662e38d98853f29c437384d7cf10069b7413f527f2876f165a5bac0e6c2a0d1dfc5828bd2396ac18cac794e7c52fe099d14609f127714368acdb9a157da2036ad397a3a930a3f9612f2611e8854f29788a376268168751349fe0c046b524e3abcac2df1a21ab2fb5a821e721382302b687a1d2c06e009cb306c49831e0dd8a13ba2631edf4d7c3db68ace502ae1562136d0b10396b2ccc3c27b4b89e14412fde4245c11c136b49fb40db0d5297b1a4b521fc710d29a57050b3dbcc2e0af1579ef0e6a3e40573b4260191af67d4d4353f5513bdb2beaee9ff5b91f5bfb7545f94af2e02f0bd47e966a62e063c141f80d427bf1277eb4b37b6bba495ff5f4cf01db34505faf33d63fa6b362d20aaa05269c87b54a33abf1b5a5c50f1db290bb8b2f6b49aa7b2a67b3366fd93a9d51d0475a977bff5bd397874fb79bff3f31a5781c165af27465ae44cd5f725f02f53559365b21e30413c64ab17b2374e81c527f9da31c4b3713fa1041e8f4ba3585092133a77ac7e9f6d29c8a46ffeef37c868428d7c1a5972c29d59670950a0bf2e9dc4cfe1b066f47620ecb8ac9de44dfd264f4c7f24bb160bc734008c45d080878c0312bc7486617e312cfdb371bf01216dcec16689947d5ee21bc2a04979623cb0c44ab4d04e3650c9ca9c900af2a2965e68ff216f75123b29655b59790edd341ba1ba26220a5ee3ab8c54f87424f4cb07b346ba520c4835cde49f3bd1b296addd25ec61a5ff350bf20ec277b2d00fed16eae39d7cded921ed22689cbfc75b88ade809d82b0f5957a0fcc907092bfcdc5df983d247c22b38b829f62ad087a03e6d6cd7753c28035c4783f2fb29c44e15e93745c29eff53e562c5328cb52d805202a9776763afb4abcbae38715d9496ebd9b9d9fa1b54bae8544fe1e25b9adb7800a4cc218ef5d642d9dd5f903c395975a0012aa4963f096afff98703df964dd562f363715c6be1049dd64a40470b932b7de6239577caf0e5dda32d64d9fb3269ed5304a794a44b5d0e83160f2cc086e939c008cde5d3453a622a29762510914adfddc0bed03ddf635c10d8e1b15a23ef0a6af1a2b0fbaffb84d3f54bdf44d8f9b7b67dc823e9215a4a17b9fe10e78d7eaf87afafa2405c540e1b816ba132ad04e5126dee44e7b6d1cfc2ef1043af4fc3a87b77122c03d518ed50e62072deb1af4a8c65c436222df12121d7f0dd661e7907dd9b94197b6d4756fc56e4793f83c47c2bbaf6a61817932b803a84aceac8ce8dd482de3498b74f00d95c50560980f975bd725f6203d4d280d2bbdcb7a3089f64d73e7c5b7266ee067247743ed5919d0b3120c8fff9a141b64a4a9e887defb30af78cc461c94aba44c4f8c25ed42ceb2634143a46b48de5a0355b49e372e0a6f17b49027792e845a98e9f931095cb4119171039ca1ee0a5744ac2ae74e9d9f4a1cdd4aa941955016e4a7c7fd78ed7b02d0639cbf4a5381ad3e1e0f6e391a9f366dda958958ed55b96991188756be2f39839741087f7c1007a49ea0f468447715399bfd12fdec82d9cfc448e86a48c9b7bccf832757b2c2ea5cf101bc10a4554c6b43d2e8015148fbe7c90bae2b46ab28e3bee1e6a170baba508101afd29f98a7ceb3b4ae02e9dc5e1db9491a6c700432dec427ff6051b350e676fccd965423e4b4b5eee1222a1e853fc4fb7ebecfe271a9ce85d501fd6b9f4433594a091f02a848869a19c0347c900ab2d4854c50b6218848c50cd255ac36798bb7e08987ba76576948e2b36f9e719992c3cd239dc3f3ac266dffbd661b9e11f7195076bda071e7643aaee41377e6e3e3289af78160c0cd6eead21db83a4641bd00f0c838ee92722ade10d948f798746155a133751aad3bf71660d04b34596739e604e1369ff29974348bfe398186dd0ec0b49bd436c01592d35fdf3dbdf896df9f90033527bc0899db68bcbb8060c12060c996b4b78b1d9d853bcd25b9d8e036a4b6b0df7b391f16635b49c298b0b5e0542914d75e3e5c44d13eebb2680af20d0ca47aab83624d151a30d68d56b4b3f922c4770ecb81c9c2c8fed0f0ac6f6276292fcfbb0ddac97bf351b0ee23a34370ee2bf41e8c84be324ebcf63d051f06c26f2d4659400aaec6f57582f569b4f99aac3dc69a5e456d827a6925843641bbb89c414f7d27769c60676e3726d51a0b6b30c5e46231abae90bb3ae07fdcec30ae460aa9300375dcef227682a9cd577de368d6f69fd65fa528ea86f347ea54e698b5b04f2cc254680d6d282560d434f1c0511bfae01a6c24363c809ff47f942b2ab20a962188accf87f09878c1b42df286642fa19678153c0b0fb2a9fdb9e46d4910662508f997a7e52d2130a59d5314af49410ba3e145454a627178a03b467193c607807c3e9be2f90bc7e81c0acd76a8ea29258a19e9ce971a6eb1dcc717c2b6a457eeeff6c93f9ce9e5fe7b19da705c16b3329edd0bdc5ce9c611ebaabb0dc2439c3b19b3362f5e3b403754b0e700a6d7281895f724b1771a9c845740853fac0f5f576927937825e6a4d3a375dedbd99efc2a7f36b86068bcc1e224065dc1ba713a15ea54aaca6bc3ae337514a4f5fa590df3b38caf469bca5557785aa921154c9b7880d06908b9426d77e33b2088405f176794c77afd49603c027be8c563d1dfa5db2dc9a5a4d023b1433fd2c5c16523d4e5864e45cc44622063657ea669a1a36582932a4e305d8cf564962c52485ed019f86add313a5b1fc0f6645dc14bf1d491ce941877a52039bf356a5249b62ab8f173a31d459baa35d60c1bc0154da33b9b0cb30b949f33f41a54488b3a66232949cf7d61545830af12e7208464ccd9a2e6b43972523214b1a5d0cc52673b07451f1d6d68af45b9e9e4930ca58a537512d930ff096164b6c2ca4cf3335c785395bef783222aa08c70a92484d1daa965ca0113aca0c45f1167cf04269fe3e2ebe839d732e88d3d2bdbf91a011b6b21bbbebd3c768cc0fd1084bb88a89fcfb43387608b771cceab9879cc49dea1b32720aa294bc80e4dd0d244fc0b877c016b27ee95c23d90c02ba70f4370c1ce5d2cde2a717606cdb86e9f570d69bf58926bfafa7446a9d207100bc8a19d61b28259e4d066728c4123558057cc91acde4275775c597b19f67be4cce00479ff20032ab77730ce3954941308414240a6c84f65ae6918fae8b159f6f10ff4103b94cd8d671f33b4850512c7565eb263319d30d6c1c02c952f60dbeb9baeec240f002fe6b636e993c96fe6b1188a1b8461d25682aacd8e32e2b476223f83926e3ac45a094e377c610968a66cc9b6c83b15649a0ed45ad428ecb1432efb4ef08002e8a97a8ed7745b82d4af3f473cb5168fb25d6f9c2c9ec70dd1f0eb599805e2763fb0f64352b7157b6a544f58a9cd6442af6624873ebcc165f30a210bb56be53621d543ddd091b1d096cf86230661d03c34e1cc8cc6ff8d84168207d301ee93ea7bae340913e82320749420438e1220dc53d24c6da52bf0e65d15035a97d0dd1e5ab6203f5d1aaed9fa50ced5153e60d8597a51bd76512fb3d4b3c29dc650c3901d1f3f7358c16c2c6d8ab2eadeabb419d512ec3e6aa9a94ac3868c7ac3a2614e2f2266d40ec7059a5048476cc2089d8880b0c4f8a920c259eb59a20843cecf6f45f99109f1992153a273a04e0a22bc4a9b39583d444c119411cb9e7a1884aa398700d589dea239fdf9b775000bee8e2702e9f0a1a99923b387cbb60bf16c8ba754aa6d34326bf081bae65aec155db417c3d83e30a0023436af4f51377aae46ceba71192f4dc9db89d626815ecf72592103045f2ccb2e487fd225a82e1b9443e8089d436822887e9a059b163324dd948d27fdfb28cb35fed1f8179e13e4c67f96b65999472e0ca902d0573a9b44624d7b0c094d6b66c942a058075a9d0ccda3d8a02e1199f4ca8d8c08d4453898e6ba988acf7294ca6c654bc26098aca10287983dcb7b6d35bac70fcae6bbe27e8fb32f562d0b4adad3a613217228e73b17459db7f8a781d43da8adbb408aa43179f2f8fc5e80a5853bae8a4cab3b68618428a2d309a26f169f7ba339e4280f3ea589582edad4a0c2893df47568ea5a1a0f3b53bb43da074753c79be0e8975917a3528372a1b72bab46a81086126d0f8e08ad7cf7f014500050260e37f6144d89373225f11c00f3e38970b1dda4369425e4a402b6e63284b3be6952819ffc249de3c383218de9f63447d0269c1682ed45b019a1a07395b363ec9a4a21bf4935c6bd6c199f53399f027c439e599cd4c6262a59c9d110542ed0426c980273994d9c0fbec9739ef4628cadb9e0191e9fc10b9f10175d2a40a0815bc20cc450e5bfc395a8f5fa2fc1b620d68945678c86cbb20a7c70d3b3a7fdc30d87e07cd9d71aa784176068a12128b0a751e7f0128c09eca83c564821906bb4a0bcaac36e29d7f590b74f9721e719acb997b9cb629cbfe2f1befa98d95958bb58636ee7bb92be5b915692c5f3de1125711347234867625c36235950ee95f630feec6eee04356cb8592e5e0933cc7aabc16b448d47236acdb33016aa403ba4366e5459c85dfa22722d98d45a2355dea45efb149084212f950740cf8faaf8c64c6add4d40feeaa5b8ddc0528ab37ba855b6422f5111ce218ec73b6d229d94479312b6875ad9520452f66194c2031753fad17f7ed4ff5dab061843d33331901cbe60e1cdb2f6924175be3c8d1fbf19f265a3e6814341ed5ce964cc676ca903cc70740fe2272fe4bf8e6715674036ae56d1334dd12cd1bd6b3eb5a6f5f57a553abf8dc14715a64890660642d0207034fa48e59b849fec3818b0ae900484581b951345ae28a338bf78a4b82ae33a7fb52965a0133d3432ced9147fd093839ed2cb134eb7a8667a6bddc680573775cb7f536ce8423d6ebb760a4f4d1e83d136520f2090e113b86f7b5c00040f43404ccf9e90fe7ae0ca830a9123903790f29903e3a527ab8dc52fe002b474ae207a0b5680fe1653f0f3205098211e8b862e1be2b93d0b4a780f15aa402acac992d97ebc1ce2924f59419ac5f23d714b3e4c90c05e2242a001fd781c6822998e5ca8daf02c56bfe3845555e1111fd7030d7a140b60998f468154cdd0049ae78ee1ad7d199b6dc6819aa58030e41bd72080ac4daae921595808f7410e1609cf06bafa2fd13a61f9267db54e35bab8c4cd10cadce8da75ae1558c1d7d470862b8700ecf8bb509badba8b027e3fe8555fa6da55f32d787d4b8dbc9f6f4af7e5cb2004e9ea3377cd847fc8d2147eeb1c6c01bbbaafbce946d00ad8689c8005a9ffdd98c9f722b9c92c9a149471efc2efe3b8ec07aecebe8a1e8fc0872da1fb9e672fca4cf44cc2361457cd364930bac98b35cc1f03f536a94b379af487df30b0450c3c47934deacaec37328ba62c2e1ba9da27111010bd77e82e2933356073727624e4b507462c12c1316690a4ef5a801fb6e135e1f3b6f03f8c11791ca405c71f90296c2429cce8793990b9ab30bbe1f01587a7b47ec2219196ebe4026e705589b10b8fe3689d04f6c17eb4123b1d5980eeba5c8d28d7484cfa3bbf90f435aa877995c824b05d33459a4b6300166bab88e53e9c32eaa6afdc7348de196cd6d06625d98d07e27c0bc5944b1b16bc7bb9ff3e65eaedde0541f947c10ce600d6c37455d09b2b17fc830193eeeabb3ae16483842de9b0495bae402c2d0611b10c92a8a06582a98635e7278ae22921fab13561bcb99bb2868f9f0d55a047815134da75592b78a045a39d63693790d394818a8a8ae645160b802f621726c473e8c1b57b733ed9a48420d877ebf1cd839965e2c70c8f02ad31ab3326b08614c8a619791f2e33fee51b32b4649383c3961658b264fb6b7290fd5976afa93d944bbaa77f674478a843a2dd414e1ba07c105bb2e99ea216990bc2300af638a6bbde1900b8271b629cd7ae33686fde7dcdb26c7dfd7b9b4801005ad6e6370e6a16fc37bb1d0da19dcbf4eba81377f7173b404181e42e40271d6e0e34df0cdb1265f2421235669b02a278fdd224d6a76a892b4e216390de8c3f738bc3d0dc84355d29d86f3dfbb049aa466e23908967d1c845e9972ed70978a299602bb5e99ea991105b63836fbdea156d883ef0432c28b97300d392abca8ae91de9154d3e779eb3fd78707122839a1b28df33df3b8a05dc61c5da3bd666879b206645db775efa1fb2e005e7bad26030c04c1d2a46ca81c41f15c1bba857581a819cd6bc23e6c4cbeffc022ccdd4b055581b92ada311b381e5e2bf7f401a28c734e5b737cdc69db59ba5794bb8119a000664f719d4abb8866d342bd4186d8eaf6f8b95a2d1480fd527461ce8efd1069404eef40bb4f89eedccdf8f845136ca3092889a67cbe4a49c175a20319632a413cc5aa9f333c2a2f18e2b0f1d49425a153bc32e7f2a202e972858e24515f8224205c5354b2acc20cae966b93e6791a24f68d1601afe969e10d4818a7ebd891151360a02d4b09ea995c6fa53bf9b8a87439d520bd640ec5fe6327bf540718d97b4a6812ffda5df99c0ee503bade46ac01a6184109c52e9b0dd5bdc463a09760d489ff15b6eb78eac3bf3e17e224af4870b3ace2228553910473ef381fe426bb44df863bc07fc33f7543fd7340610cc3cc5ef5ed398e4c580c405d295ae02826988235d7f8405e537362e14aad1a1d778d3035c905eafbf5ac72d4787bc7ffdf4e3f6b31a1ed2747fe07df8fee8b2628c2ed3474616eb34eca14c3a260201640f6f2fa8c7e53cbd1559554bf9da0b49803bcf76b5816a2685b3a8259f20af2830def0072c56c09b0ecace363532e380b8ee1820ffc5bb071d85917aef1a2ed0ebbf17febf7f95130235d09c690b44e6a07cda984ea3b4ca34070703f881f3415479c40ac6c89be52e3637104aaf9aa818e420e7912d37181e8adc520a2823e9ec4fe3458a48a842ec436b908e4b093afb85debec0af20e65b56d61991c4bacce23b01a4e0f6d6412e7890b548711abf29b85e9200cd1313214d3d9889591f31300c4df06daca5949b220cfc15562ea387fdb53d1099323b19137d92998761fa4e20256195f36cceb0539b75d66a509a264570571f60ffa66a11518ee2f1057d0a1bf27a906694a26e6c10ce4225ea34131c3bcde13d06c483823bc8933cb13d08437b1578b9333a0d9b1089144b150d6b5f8ca567d289edf4e156202e45b579cd9b398b200a1f35e4a498e2f10c158d853d7d9a2b70a45808b8485d881f23bd765c841e949eb168774e05f7666db5fb308ee4dd9fea2fdee11908cb550af9ab2260dd3e9e5052404e911dfbc779b67bfbfbc08ac60a61d21191eaa23efcabeb97e0fa4e74df5d8493e86d02bf709eb29475b532db2e2eea5c873b1dab1338d3bddb292f5f865491fb487e9d7390456466485d7a5ac85a6ca77186bb8fef25849d8fe4904f7c8bd813eb275a098d9a0ea629013b0fc121b47b36c3c0aacfbc1b982f2fa26a5b2485cca02c935e561118667d79e880908cbf230533c1becce6479090fc38894ddccb7468c374121f18e89833fbc20da847c38f9c01ff7a3e36c2475205baabd01ad4a8d97e3518629967ba054f5e5fc47c61e31ae5f4cb40545c692d2f54d0e5898fd59f0dd2493ecbd93e9c3d17903ed65b602b80aefc8d18dd4b2fc326534fb54c26aa53b6425c847545bb58ba6ccc82d102c9c092547c4ace0bbed51906b72ba636f2c254114681cc09ea6826b572a08d79e7efb21be7aef4d95c92ab2bbc99113cdd4a167e2996fa2d9cdf2ad2d15bf1ff7ffa3cb2b2131dbfc53612594813791144d82e37bef0abda99049aca086d874d0766554cf400491a16335e8afa085d720a3b8d94ee877667d6570374464d5fe5f025f6565e0beb888e38ca0af16e984b471534cbd9e6cfc20b3ecb63502a088162fe4f0b519175a140a4a3a32bd1deacab650e0099430d380f54f4e92e408a23224aa7816bb3e1b1e50f527b6abddb898bf441ceefa7bee9c14d260bce6eee5ab0b890f67a4472527a0b7202f9a058ee0e308288dca01d7121a479158c3a650acd60a09870561744900f3a9a97920572b85805de06f64573d9b31ae557b5cd32d89315175e8932b4ad1e16543ca3773fa6882514a940de24c3d01adfd8c43704a29642e7651dc605e79ad625910aa87282a155fb6e9af46a5376a1bf304ed53b4c25115039686c20460bbbcb65bb2359b802b61b84edc90cf76a342a2795103496cf035640742c2926a02f97bdb2be77fcbcb9b7950c47e6ae49289e5da3125bff54cf9604515b032457fd4e8f927b9d0ea2760bc8f7d2b6624615fc0a24cf83cb9ad85bae654e0b4799d3e60cdc7ae11d0a075be573e86201353438323f1c941b8d84e3c10881876c664e29628c631960583f3b84366d19c8820f3315a435fa105cce489962d52cb224babdba4dae7c3b9797de9d3569ad8071cc87a13434f4aae4cf36b736d0d5f8255355ef78c9c5f55aed25d72235d878d384125fa5af3b2c7d7e2438175a4768c3d066d742180be8bdb5f046c99eea9b9938ae0d01dc6a817b6b408e517819784905f41c606eac8007f61e8d1d9679893a358e55d10d77e0e580853571428aa3648204b03faa9c449879dc731a2e24aca0d19f9fab89d0a23e62cd5eb362434ce75eea5f0838a6cf8f37392f1901731a0f9d37d6e40116b40378e4a22a5afa17781d85b912256699c9a30b26c7acc98da480e38b7a4d1fbfad57adc907ae667dab1626e5e5bda5a95098b3526bc9c7cf6d0425613012ad17933cf176174474c9374a7de40de970b9883b0a73ca125d431deef291d8bc088e00512beb1fdb3620278da890eaa2d50bf3824690d95a1d90bc905e7038784e6d519f2a023c7b025e93f96e345d3e41887ae6b59680d377893d5c22d4aefed437129b03ca444380453ea82787f2809e14c94b9caba665cf2bc59015f15069026086b6f0370b783cef0d79b3092e27610d0cbfe3557afd690636de999b2934b2f5a10b1a9296d2c553bb844e202cc7ddf05b7b9a738e7c9372f58a1c011934ad13b7cd4c3a1350de7b1de1fa67c64a166652c8416eb939f4bbb246188ba13ef9f1bbebe42118a6734064746a48d215c068d8731bd8edc1c1d3f97b1d032be7f1391402c41321253d9d83da81bf89901e350239cc928eff04d1ec78517c87b68c20d34f63c646789c860c6cd332b907c38c948280abd5153535e10f51662a3c7f6c55142b436d2df54dc7bf42b424c924e952f2e615c91f70bb431724d89334992c1b2ac1d866e4091bf05702f01ec732027db2c5e7f15f1d040e4d2c8b3e85be21cadd6d42a08ab53680866c60377eb9e1ef4ad0941191e31d54189f1bc83b740dca4f55f4c77ba28ad0932f128a149cb7bbe6dbfc3bbefcf3b8a963cc993196e97296bc476e2e5321532436d83187649af339d2b1cd73a84636c21929ccd23658a740afe13ed2c31292f8c4667bc770ef66c7e345261d39a63cad3a05bbd1c9437c1f88a32334391106c268a791ba7bd394b702601990229f07e98f5c733dac2ca4e765f2221ca3c3220814e6f14dacc0a89c013097fb761fb9ab209c73c013bfc7cc0c329230549285f86421b547ad41432f13afe5d1cefc24deb70fcb63eb82e6d7674ca81415da996887a59786da9be03f19614a6bed8204a929f7b46e5dfe45c8772f25161bad145eda121a6b4e90bd87c85a3eae9b3f9a1b5ffdd538d399cd5aff699815fa35ddc068c8441a12d63aaab0991ffc7868913173103ea42a126032a74d66f63ab31c215782a95895dd7499e4998318d77457c770d3b5b5f0b434252e4fcef399f71ce4f8b7b35696521eca92014be54af0606d1b669641d25bf3911cf2f5af39da873fcf09c5c995e0e4b3da6136185453e41a8644b9743a8777398c9d828c151012aeb5e679c5735e8d5543c37c1d6f2e820df44f9a8fdd17a17b787d58bc3b1eb6605d2d0527ed28bcd63233f80f7aa96efd516cc4ae556414cef1f532abc3da6054f6d1289345532a90837beca7a3a89cd23aae8e182eea0e8e75a2c5e803e97d17577551e7704e7733bee88325c852a46fb3cba275537cf88b959a871d6fa2e1ff6a6e65f7e11990c5f59bb9b41be27d487399d07f862c3d8df994db431a7aba8b905f349902211b25cba7e7391b7388890acaf38cf7fc20cf76aa0f6b85d9db60ceb9612923b5a3d04a25b529d9e8d38c45f1d0ed32212da53235cbf6c9dda30d4bb8811cf3d2cde8302adee3262417c1a62307f1972717317455d044404111c41abce8dd4ded238cb04b175774c6ebb2c8cc0ea2e14cf1287a19bdca8b94a068a648f7ba0a576858c10bfbd1fbb58c2f8c6072d9d74c986a5464b8f746b35334ce41f6a7d095df610f4a39b7fb319de21771b53797a8e45685e5cb46b068353ee6df8ee937aa9026b87d225b9a9b23de92474e69c2992c31db074f04950718e712642d50e9591680c07bca6502a0bb3f6588cb25fa1095da5bf34e50465980c4e82c017e478cc98b2f57a5dd947b693ec4b43db9bce361a14958d2a1393b938eb06ed37dfba8573337bd2439a90bdbe86e9d0721eca1bed3dc454cf8458294da137dfbc0902709825aa11064255d594689046da9e73e822d0e2103b5a2fefb74010a2565a9a4990f6009d77c6e49fbb196753b7bed757a9380e34b4a77774db3a9067d938efa07dba3fd4975e53619cbb67630354f975817261c2b00826760094b9ee6a8637e9c6522c8bbe980be19ed91d32ea7d258bf212284740facc727657a83c36936cc418e00ff27f6c11cc97bc0d71b87f0a2f95786cfedf867e0ead226d4e3051bb7a40647f596b55d664d4dc19bc4db2b77b549c09b4b65a3fdce5596fb726b7db511c16df48b85c75e9e6c8ca5032227e1cbb4a887fbdd62d595058532e8edc4b5efcd21e388a2f6b6f792a30149bf6cbd562da195d037ed2433d29513e41cdeedf06d045a0b6f7300d6bde786ce9bf8eeec87effb6ce3658b00317528d9050a932dc3f0a9c61fd6fd09703e5c60561bf620af84af3777494ab1843c96890fc3cfa6a23f7e0fcabb46ec30f40757b0c5ddf3775ac0c9d483546d093e7dc19e9b9dada60ae7ad8bdc3b749162ab53b78af96d30e3eafba00db3f323d3b495b92b480ab041fb63559731bc208d25f0f5f2ea6155a054fdbeffc429ca7472e402854c811639320a7afd46ba8fdd7f63d57d0d143b593dc7285ff29440ac391e8a0590030153ee3f66b292bac72a00b755d06e0fd58600017856df7d1d4a6c3c4e86c19f1ffdaa3053638fabc2dca97661eb481f28a5039c30d0e07e957f67d103a40094c5f3b7c82a388c4be410bfac48c23909", + "patch": { + "balances": { + "balances": [ + [ + "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY", + 1152921504606846976 + ], + [ + "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty", + 1152921504606846976 + ], + [ + "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y", + 1152921504606846976 + ], + [ + "5DAAnrj7VHTznn2AWBemMuyBwZWs6FNFjdyVXUeYum3PTXFy", + 1152921504606846976 + ], + [ + "5HGjWAeFDfFCWPsjFQdVV2Msvz2XtMktvgocEZcCj68kUMaw", + 1152921504606846976 + ], + [ + "5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL", + 1152921504606846976 + ], + [ + "5GNJqTPyNqANBkUVMN1LPPrxXnFouWXoe2wNSmmEoLctxiZY", + 1152921504606846976 + ], + [ + "5HpG9w8EBLe5XCrbczpwq5TSXvedjrBGCwqxK1iQ7qUsSWFc", + 1152921504606846976 + ], + [ + "5Ck5SLSHYac6WFt5UZRSsdJjwmpSZq85fd5TRNAdZQVzEAPT", + 1152921504606846976 + ], + [ + "5HKPmK9GYtE1PSLsS1qiYU9xQ9Si1NcEhdeCq9sw5bqu4ns8", + 1152921504606846976 + ], + [ + "5FCfAonRZgTFrTd9HREEyeJjDpT397KMzizE6T3DvebLFE7n", + 1152921504606846976 + ], + [ + "5CRmqmsiNFExV6VbdmPJViVxrWmkaXXvBrSX8oqBT8R9vmWk", + 1152921504606846976 + ] + ] + }, + "collatorSelection": { + "candidacyBond": 16000000000, + "invulnerables": [ + "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY", + "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty" + ] + }, + "parachainInfo": { + "parachainId": 1000 + }, + "polkadotXcm": { + "safeXcmVersion": 5 + }, + "session": { + "keys": [ + [ + "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY", + "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY", + { + "aura": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY" + } + ], + [ + "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty", + "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty", + { + "aura": "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty" + } + ] + ] + }, + "sudo": { + "key": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY" + } + } + } + }, + "id": "custom", + "name": "Custom", + "para_id": 1000, + "properties": { + "tokenDecimals": 12, + "tokenSymbol": "UNIT" + }, + "protocolId": null, + "relay_chain": "rococo-local", + "telemetryEndpoints": null +} \ No newline at end of file diff --git a/templates/parachain/pallets/template/src/mock.rs b/templates/parachain/pallets/template/src/mock.rs index b924428d4145c51ec7de253d59380cdb8dce57f6..3eeb9604f015334cd71c485f648b0dc796d33a9b 100644 --- a/templates/parachain/pallets/template/src/mock.rs +++ b/templates/parachain/pallets/template/src/mock.rs @@ -18,7 +18,8 @@ mod test_runtime { RuntimeHoldReason, RuntimeSlashReason, RuntimeLockId, - RuntimeTask + RuntimeTask, + RuntimeViewFunction )] pub struct Test; diff --git a/templates/parachain/runtime/src/apis.rs b/templates/parachain/runtime/src/apis.rs index 05a508ca655fb1fe6be4db53a839b76c8a9c1cec..d7da43b86af166e991371acb78806c46072cdfc0 100644 --- a/templates/parachain/runtime/src/apis.rs +++ b/templates/parachain/runtime/src/apis.rs @@ -114,6 +114,12 @@ impl_runtime_apis! { } } + impl frame_support::view_functions::runtime_api::RuntimeViewFunction<Block> for Runtime { + fn execute_view_function(id: frame_support::view_functions::ViewFunctionId, input: Vec<u8>) -> Result<Vec<u8>, frame_support::view_functions::ViewFunctionDispatchError> { + Runtime::execute_view_function(id, input) + } + } + impl sp_block_builder::BlockBuilder<Block> for Runtime { fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult { Executive::apply_extrinsic(extrinsic) diff --git a/templates/parachain/runtime/src/lib.rs b/templates/parachain/runtime/src/lib.rs index 0be27ecce73945a6fbda409f7d19994493d9be0f..f312e9f80192fd767cdf93288c3331186aabf45a 100644 --- a/templates/parachain/runtime/src/lib.rs +++ b/templates/parachain/runtime/src/lib.rs @@ -262,7 +262,8 @@ mod runtime { RuntimeHoldReason, RuntimeSlashReason, RuntimeLockId, - RuntimeTask + RuntimeTask, + RuntimeViewFunction )] pub struct Runtime; diff --git a/templates/parachain/zombienet-omni-node.toml b/templates/parachain/zombienet-omni-node.toml index 29e99cfcd493113c3ee643c3cffb08e2fce498a9..2f263f157fcfa735101e12301f443277241df87d 100644 --- a/templates/parachain/zombienet-omni-node.toml +++ b/templates/parachain/zombienet-omni-node.toml @@ -14,7 +14,7 @@ ws_port = 9955 [[parachains]] id = 1000 -chain_spec_path = "<path/to/chain_spec.json>" +chain_spec_path = "./dev_chain_spec.json" [parachains.collator] name = "charlie" diff --git a/templates/solochain/pallets/template/src/mock.rs b/templates/solochain/pallets/template/src/mock.rs index 1b86cd9b7709a43bf7abe45893569b53a614f0e3..44085bc3bff18e90d301c5275944c6e8aa41fd20 100644 --- a/templates/solochain/pallets/template/src/mock.rs +++ b/templates/solochain/pallets/template/src/mock.rs @@ -18,7 +18,8 @@ mod runtime { RuntimeHoldReason, RuntimeSlashReason, RuntimeLockId, - RuntimeTask + RuntimeTask, + RuntimeViewFunction )] pub struct Test; diff --git a/templates/solochain/runtime/src/apis.rs b/templates/solochain/runtime/src/apis.rs index 06c645fa0c53959b209fa4bcfe867eb6c34a5a6d..9dc588c43a2d5eaaa823802972a735dab40d49b0 100644 --- a/templates/solochain/runtime/src/apis.rs +++ b/templates/solochain/runtime/src/apis.rs @@ -75,6 +75,12 @@ impl_runtime_apis! { } } + impl frame_support::view_functions::runtime_api::RuntimeViewFunction<Block> for Runtime { + fn execute_view_function(id: frame_support::view_functions::ViewFunctionId, input: Vec<u8>) -> Result<Vec<u8>, frame_support::view_functions::ViewFunctionDispatchError> { + Runtime::execute_view_function(id, input) + } + } + impl sp_block_builder::BlockBuilder<Block> for Runtime { fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult { Executive::apply_extrinsic(extrinsic) diff --git a/templates/solochain/runtime/src/lib.rs b/templates/solochain/runtime/src/lib.rs index 6a2149ec8b637c2b253a9327abd81260259cf150..f25b8413721ea2a2ede609fcfaf515f15d163468 100644 --- a/templates/solochain/runtime/src/lib.rs +++ b/templates/solochain/runtime/src/lib.rs @@ -196,7 +196,8 @@ mod runtime { RuntimeHoldReason, RuntimeSlashReason, RuntimeLockId, - RuntimeTask + RuntimeTask, + RuntimeViewFunction )] pub struct Runtime;